diff options
author | Ian Lance Taylor <ian@airs.com> | 1995-08-21 18:35:11 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1995-08-21 18:35:11 +0000 |
commit | 7e047ac2c1fcb16f721c715a48c8d4b8b4776485 (patch) | |
tree | e564914df3cf5fa253fbf65ea8b9b36deaddd40a /gas/input-scrub.c | |
parent | 7172e2266f4a25fc34dda564ac13c89c9d855cde (diff) | |
download | gdb-7e047ac2c1fcb16f721c715a48c8d4b8b4776485.zip gdb-7e047ac2c1fcb16f721c715a48c8d4b8b4776485.tar.gz gdb-7e047ac2c1fcb16f721c715a48c8d4b8b4776485.tar.bz2 |
Add support for macros.
* as.c: Include sb.h and macro.h.
(max_macro_next): New global variable.
(main): Call macro_init.
(macro_expr): New static function.
* as.h (max_macro_nest): Declare.
* read.c (line_label): Rename from mri_line_label. Change all
uses.
(potable): Add exitm, irp, irpc, macro, mexit, rept.
(read_a_source_file): Always clear line_label at the start of a
line, not just when flag_mri or LABELS_WITHOUT_COLONS. Fixup
MRI/LABELS_WITHOUT_COLONS handling. In MRI mode, permit label:
equ val. Set line_label when calling colon. In MRI mode, a
leading '.' does not imply a pseudo-op. Check for macro expansion
before calling md_assemble.
(s_irp): New function.
(get_line_sb): New static function.
(s_macro): New function.
(s_mexit): New function.
(s_rept): New function.
* read.h (line_label): Rename from mri_line_label.
(s_irp, s_rept): Declare.
(s_macro, s_mexit): Declare.
* input-scrub.c: Include sb.h.
(sb_index, from_sb): New static variables.
(macro_nest): New static variable.
(struct input_save): Add sb_index and from_sb fields. Change
next_saved_file field to be struct input_save *.
(next_saved_file): Changed to be struct input_save *.
(input_scrub_push): Change to return type struct input_save *.
Save sb_index and from_sb.
(input_scrub_pop): Change parameter type to struct input_save *.
Restore sb_index and from_sb.
(input_scrub_include_sb): New function.
(input_scrub_next_buffer): Handle reading from from_sb.
(bump_line_counters): Only increment lines if not using from_sb.
* config/tc-m68k.c (opt_table): Add nest.
(opt_nest): New static function.
* gasp.c: Include sb.h and macro.h. Move all sb related functions
and definitions to sb.h and sb.c. Move all macro related
functions and definitions to macro.h and macro.c.
* sb.h, sb.c: New files, extracted from gasp.c.
* macro.h, macro.c: Likewise.
* Makefile.in (OBJS): Add sb.o and macro.o
(GASPOBJS): Define.
(gasp.new): Depend upon $(GASPOBJS). Use $(GASPOBJS) to link.
(TARG_CPU_DEP_m68k): Depend upon subsegs.h.
(gasp.o): Depend upon sb.h and macro.h.
(sb.o): New target.
(macro.o): New target.
(as.o): Depend upon sb.h and macro.h.
(input-scrub.o): Depend upon sb.h.
(read.o): Depend upon sb.h and macro.h.
Diffstat (limited to 'gas/input-scrub.c')
-rw-r--r-- | gas/input-scrub.c | 613 |
1 files changed, 322 insertions, 291 deletions
diff --git a/gas/input-scrub.c b/gas/input-scrub.c index bdfd91c..b495ae0 100644 --- a/gas/input-scrub.c +++ b/gas/input-scrub.c @@ -1,29 +1,30 @@ /* input_scrub.c - Break up input buffers into whole numbers of lines. Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. - + This file is part of GAS, the GNU Assembler. - + GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <errno.h> /* Need this to make errno declaration right */ +#include <errno.h> /* Need this to make errno declaration right */ #include "as.h" #include "input-file.h" +#include "sb.h" /* * O/S independent module to supply buffers of sanitised source code - * to rest of assembler. We get sanitized input data of arbitrary length. + * to rest of assembler. We get sanitised input data of arbitrary length. * We break these buffers on line boundaries, recombine pieces that * were broken across buffers, and return a buffer of full lines to * the caller. @@ -52,22 +53,26 @@ #define BEFORE_SIZE (1) #define AFTER_SIZE (1) -static char * buffer_start; /*->1st char of full buffer area. */ -static char * partial_where; /*->after last full line in buffer. */ +static char *buffer_start; /*->1st char of full buffer area. */ +static char *partial_where; /*->after last full line in buffer. */ static int partial_size; /* >=0. Number of chars in partial line in buffer. */ -static char save_source [AFTER_SIZE]; +static char save_source[AFTER_SIZE]; /* Because we need AFTER_STRING just after last */ /* full line, it clobbers 1st part of partial */ /* line. So we preserve 1st part of partial */ /* line here. */ -static int buffer_length; /* What is the largest size buffer that */ +static unsigned int buffer_length; /* What is the largest size buffer that */ /* input_file_give_next_buffer() could */ /* return to us? */ -/* Saved information about the file that .include'd this one. When we hit EOF, - we automatically pop to that file. */ +/* The index into an sb structure we are reading from. -1 if none. */ +static int sb_index = -1; + +/* If we are reading from an sb structure, this is it. */ +static sb from_sb; -static char *next_saved_file; +/* The number of nested sb structures we have included. */ +static int macro_nest; /* We can have more than one source file open at once, though the info for all but the latest one are saved off in a struct input_save. These files remain @@ -80,140 +85,152 @@ static char *next_saved_file; source line numbers. Whenever we open a file we must fill in physical_input_file. So if it is NULL we have not opened any files yet. */ -char *physical_input_file; -char *logical_input_file; +static char *physical_input_file; +static char *logical_input_file; -typedef unsigned int line_numberT; /* 1-origin line number in a source file. */ +typedef unsigned int line_numberT; /* 1-origin line number in a source file. */ /* A line ends in '\n' or eof. */ -line_numberT physical_input_line; -line_numberT logical_input_line; +static line_numberT physical_input_line; +static int logical_input_line; /* Struct used to save the state of the input handler during include files */ -struct input_save { - char *buffer_start; - char *partial_where; - int partial_size; - char save_source [AFTER_SIZE]; - int buffer_length; - char *physical_input_file; - char *logical_input_file; - line_numberT physical_input_line; - line_numberT logical_input_line; - char *next_saved_file; /* Chain of input_saves */ - char *input_file_save; /* Saved state of input routines */ - char *saved_position; /* Caller's saved position in buf */ -}; - -#if __STDC__ == 1 -static void as_1_char(unsigned int c, FILE *stream); -#else /* __STDC__ */ -static void as_1_char(); -#endif /* not __STDC__ */ +struct input_save + { + char *buffer_start; + char *partial_where; + int partial_size; + char save_source[AFTER_SIZE]; + unsigned int buffer_length; + char *physical_input_file; + char *logical_input_file; + line_numberT physical_input_line; + int logical_input_line; + int sb_index; + sb from_sb; + struct input_save *next_saved_file; /* Chain of input_saves */ + char *input_file_save; /* Saved state of input routines */ + char *saved_position; /* Caller's saved position in buf */ + }; + +static struct input_save *input_scrub_push PARAMS ((char *saved_position)); +static char *input_scrub_pop PARAMS ((struct input_save *arg)); +static void as_1_char PARAMS ((unsigned int c, FILE * stream)); + +/* Saved information about the file that .include'd this one. When we hit EOF, + we automatically pop to that file. */ + +static struct input_save *next_saved_file; /* Push the state of input reading and scrubbing so that we can #include. The return value is a 'void *' (fudged for old compilers) to a save area, which can be restored by passing it to input_scrub_pop(). */ -char *input_scrub_push(saved_position) -char *saved_position; +static struct input_save * +input_scrub_push (saved_position) + char *saved_position; { - register struct input_save *saved; - - saved = (struct input_save *) xmalloc(sizeof *saved); - - saved->saved_position = saved_position; - saved->buffer_start = buffer_start; - saved->partial_where = partial_where; - saved->partial_size = partial_size; - saved->buffer_length = buffer_length; - saved->physical_input_file = physical_input_file; - saved->logical_input_file = logical_input_file; - saved->physical_input_line = physical_input_line; - saved->logical_input_line = logical_input_line; - memcpy(saved->save_source, save_source, sizeof(save_source)); - saved->next_saved_file = next_saved_file; - saved->input_file_save = input_file_push(); - - input_file_begin(); /* Reinitialize! */ - logical_input_line = 0; - logical_input_file = (char *)NULL; - - return((char *) saved); -} /* input_scrub_push() */ - -char * - input_scrub_pop (arg) -char *arg; + register struct input_save *saved; + + saved = (struct input_save *) xmalloc (sizeof *saved); + + saved->saved_position = saved_position; + saved->buffer_start = buffer_start; + saved->partial_where = partial_where; + saved->partial_size = partial_size; + saved->buffer_length = buffer_length; + saved->physical_input_file = physical_input_file; + saved->logical_input_file = logical_input_file; + saved->physical_input_line = physical_input_line; + saved->logical_input_line = logical_input_line; + saved->sb_index = sb_index; + saved->from_sb = from_sb; + memcpy (saved->save_source, save_source, sizeof (save_source)); + saved->next_saved_file = next_saved_file; + saved->input_file_save = input_file_push (); + + input_file_begin (); /* Reinitialize! */ + logical_input_line = -1; + logical_input_file = (char *) NULL; + buffer_length = input_file_buffer_size (); + + buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); + memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); + + return saved; +} /* input_scrub_push() */ + +static char * +input_scrub_pop (saved) + struct input_save *saved; { - register struct input_save *saved; - char *saved_position; - - input_scrub_end (); /* Finish off old buffer */ - - saved = (struct input_save *)arg; - - input_file_pop (saved->input_file_save); - saved_position = saved->saved_position; - buffer_start = saved->buffer_start; - buffer_length = saved->buffer_length; - physical_input_file = saved->physical_input_file; - logical_input_file = saved->logical_input_file; - physical_input_line = saved->physical_input_line; - logical_input_line = saved->logical_input_line; - partial_where = saved->partial_where; - partial_size = saved->partial_size; - next_saved_file = saved->next_saved_file; - memcpy(save_source, saved->save_source, sizeof (save_source)); - - free(arg); - return saved_position; + char *saved_position; + + input_scrub_end (); /* Finish off old buffer */ + + input_file_pop (saved->input_file_save); + saved_position = saved->saved_position; + buffer_start = saved->buffer_start; + buffer_length = saved->buffer_length; + physical_input_file = saved->physical_input_file; + logical_input_file = saved->logical_input_file; + physical_input_line = saved->physical_input_line; + logical_input_line = saved->logical_input_line; + sb_index = saved->sb_index; + from_sb = saved->from_sb; + partial_where = saved->partial_where; + partial_size = saved->partial_size; + next_saved_file = saved->next_saved_file; + memcpy (save_source, saved->save_source, sizeof (save_source)); + + free (saved); + return saved_position; } - + void - input_scrub_begin () +input_scrub_begin () { - know(strlen(BEFORE_STRING) == BEFORE_SIZE); - know(strlen(AFTER_STRING) == AFTER_SIZE || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1)); - - input_file_begin (); - - buffer_length = input_file_buffer_size (); - - buffer_start = xmalloc((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); - memcpy(buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); - - /* Line number things. */ - logical_input_line = 0; - logical_input_file = (char *)NULL; - physical_input_file = NULL; /* No file read yet. */ - next_saved_file = NULL; /* At EOF, don't pop to any other file */ - do_scrub_begin(); + know (strlen (BEFORE_STRING) == BEFORE_SIZE); + know (strlen (AFTER_STRING) == AFTER_SIZE || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1)); + + input_file_begin (); + + buffer_length = input_file_buffer_size (); + + buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); + memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); + + /* Line number things. */ + logical_input_line = -1; + logical_input_file = (char *) NULL; + physical_input_file = NULL; /* No file read yet. */ + next_saved_file = NULL; /* At EOF, don't pop to any other file */ + do_scrub_begin (); } void - input_scrub_end () +input_scrub_end () { - if (buffer_start) - { - free (buffer_start); - buffer_start = 0; - input_file_end (); - } + if (buffer_start) + { + free (buffer_start); + buffer_start = 0; + input_file_end (); + } } /* Start reading input from a new file. */ char * /* Return start of caller's part of buffer. */ - input_scrub_new_file (filename) -char * filename; +input_scrub_new_file (filename) + char *filename; { - input_file_open (filename, !flagseen['f']); - physical_input_file = filename[0] ? filename : "{standard input}"; - physical_input_line = 0; - - partial_size = 0; - return (buffer_start + BEFORE_SIZE); + input_file_open (filename, !flag_no_comments); + physical_input_file = filename[0] ? filename : "{standard input}"; + physical_input_line = 0; + + partial_size = 0; + return (buffer_start + BEFORE_SIZE); } @@ -222,94 +239,113 @@ char * filename; input_scrub_new_file. */ char * - input_scrub_include_file (filename, position) -char *filename; -char *position; +input_scrub_include_file (filename, position) + char *filename; + char *position; { - next_saved_file = input_scrub_push(position); - return input_scrub_new_file (filename); + next_saved_file = input_scrub_push (position); + return input_scrub_new_file (filename); } +/* Start getting input from an sb structure. This is used when + expanding a macro. */ + void - input_scrub_close () +input_scrub_include_sb (from, position) + sb *from; + char *position; { - input_file_close (); + if (macro_nest > max_macro_nest) + as_fatal ("macros nested too deeply"); + ++macro_nest; + + next_saved_file = input_scrub_push (position); + + sb_new (&from_sb); + /* Add the sentinel required by read.c. */ + sb_add_char (&from_sb, '\n'); + sb_add_sb (&from_sb, from); + sb_index = 1; + + /* These variables are reset by input_scrub_push. Restore them + since we are, after all, still at the same point in the file. */ + logical_input_line = next_saved_file->logical_input_line; + logical_input_file = next_saved_file->logical_input_file; } + +void +input_scrub_close () +{ + input_file_close (); +} + char * - input_scrub_next_buffer (bufp) -char **bufp; +input_scrub_next_buffer (bufp) + char **bufp; { - register char * limit; /*->just after last char of buffer. */ - - *bufp = buffer_start + BEFORE_SIZE; - -#ifdef DONTDEF - if(preprocess) { - if(save_buffer) { - *bufp = save_buffer; - save_buffer = 0; - } - limit = input_file_give_next_buffer(buffer_start+BEFORE_SIZE); - if (!limit) { - partial_where = 0; - if(partial_size) - as_warn("Partial line at end of file ignored"); - return partial_where; - } - - if(partial_size) - memcpy(partial_where, save_source, (int) AFTER_SIZE); - do_scrub(partial_where,partial_size,buffer_start+BEFORE_SIZE,limit-(buffer_start+BEFORE_SIZE),&out_string,&out_length); - limit=out_string + out_length; - for(p=limit;*--p!='\n';) - ; - p++; - if(p<=buffer_start+BEFORE_SIZE) - as_fatal("Source line too long. Please change file '%s' and re-make the assembler.", __FILE__); - - partial_where = p; - partial_size = limit-p; - memcpy(save_source, partial_where, (int) AFTER_SIZE); - memcpy(partial_where, AFTER_STRING, (int) AFTER_SIZE); - - save_buffer = *bufp; - *bufp = out_string; - - return partial_where; + register char *limit; /*->just after last char of buffer. */ + + if (sb_index >= 0) + { + if (sb_index >= from_sb.len) + { + sb_kill (&from_sb); + --macro_nest; + partial_where = NULL; + if (next_saved_file != NULL) + *bufp = input_scrub_pop (next_saved_file); + return partial_where; } - - /* We're not preprocessing. Do the right thing */ -#endif - if (partial_size) { - memcpy(buffer_start + BEFORE_SIZE, partial_where, (int) partial_size); - memcpy(buffer_start + BEFORE_SIZE, save_source, (int) AFTER_SIZE); + + partial_where = from_sb.ptr + from_sb.len; + partial_size = 0; + *bufp = from_sb.ptr + sb_index; + sb_index = from_sb.len; + return partial_where; + } + + *bufp = buffer_start + BEFORE_SIZE; + + if (partial_size) + { + memcpy (buffer_start + BEFORE_SIZE, partial_where, + (unsigned int) partial_size); + memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE); + } + limit = input_file_give_next_buffer (buffer_start + + BEFORE_SIZE + + partial_size); + if (limit) + { + register char *p; /* Find last newline. */ + + for (p = limit; *--p != '\n';);; + ++p; + if (p <= buffer_start + BEFORE_SIZE) + { + as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__); + } + partial_where = p; + partial_size = limit - p; + memcpy (save_source, partial_where, (int) AFTER_SIZE); + memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE); + } + else + { + partial_where = 0; + if (partial_size > 0) + { + as_warn ("Partial line at end of file ignored"); } - limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size); - if (limit) { - register char * p; /* Find last newline. */ - - for (p = limit; *--p != '\n';) ;; - ++p; - if (p <= buffer_start + BEFORE_SIZE) { - as_fatal("Source line too long. Please change file %s then rebuild assembler.", __FILE__); - } - partial_where = p; - partial_size = limit - p; - memcpy(save_source, partial_where, (int) AFTER_SIZE); - memcpy(partial_where, AFTER_STRING, (int) AFTER_SIZE); - } else { - partial_where = 0; - if (partial_size > 0) { - as_warn("Partial line at end of file ignored"); - } - /* If we should pop to another file at EOF, do it. */ - if (next_saved_file) { - *bufp = input_scrub_pop (next_saved_file); /* Pop state */ - /* partial_where is now correct to return, since we popped it. */ - } + /* If we should pop to another file at EOF, do it. */ + if (next_saved_file) + { + *bufp = input_scrub_pop (next_saved_file); /* Pop state */ + /* partial_where is now correct to return, since we popped it. */ } - return(partial_where); -} /* input_scrub_next_buffer() */ + } + return (partial_where); +} /* input_scrub_next_buffer() */ /* * The remaining part of this file deals with line numbers, error @@ -318,83 +354,84 @@ char **bufp; int - seen_at_least_1_file () /* TRUE if we opened any file. */ +seen_at_least_1_file () /* TRUE if we opened any file. */ { - return (physical_input_file != NULL); + return (physical_input_file != NULL); } void - bump_line_counters () +bump_line_counters () { - ++ physical_input_line; - /* ++ logical_input_line; FIXME-now remove this. */ + if (sb_index < 0) + { + ++physical_input_line; + if (logical_input_line >= 0) + ++logical_input_line; + } } /* * new_logical_line() * * Tells us what the new logical line number and file are. - * If the line_number is <0, we don't change the current logical line number. + * If the line_number is -1, we don't change the current logical line + * number. If it is -2, we decrement the logical line number (this is + * to support the .appfile pseudo-op inserted into the stream by + * do_scrub_next_char). * If the fname is NULL, we don't change the current logical file name. */ -void new_logical_line(fname, line_number) -char *fname; /* DON'T destroy it! We point to it! */ -int line_number; +void +new_logical_line (fname, line_number) + char *fname; /* DON'T destroy it! We point to it! */ + int line_number; { - if (fname) { - logical_input_file = fname; - } /* if we have a file name */ - - if (line_number >= 0) { - logical_input_line = line_number; - } /* if we have a line number */ -} /* new_logical_line() */ + if (fname) + { + logical_input_file = fname; + } /* if we have a file name */ + + if (line_number >= 0) + logical_input_line = line_number; + else if (line_number == -2 && logical_input_line > 0) + --logical_input_line; +} /* new_logical_line() */ /* * a s _ w h e r e () * - * Write a line to stderr locating where we are in reading - * input source files. - * As a sop to the debugger of AS, pretty-print the offending line. + * Return the current file name and line number. + * namep should be char * const *, but there are compilers which screw + * up declarations like that, and it's easier to avoid it. */ -void as_where() { - char *p; - line_numberT line; - - if (logical_input_file && (logical_input_line > 0)) { - p = logical_input_file; - line = logical_input_line; - } else { - p = physical_input_file; - line = physical_input_line; - } /* line number should match file name */ - - fprintf(stderr, "%s:%u: ", p, line); - -#ifdef DONTDEF - if (physical_input_file) { - if (input_file_is_open()) { /* we can still read lines from source */ - fprintf (stderr," @ physical line %ld., file \"%s\"", - (long) physical_input_line, physical_input_file); - fprintf (stderr," @ logical line %ld., file \"%s\"\n", - (long) logical_input_line, logical_input_file); - (void)putc(' ', stderr); - as_howmuch (stderr); - (void)putc('\n', stderr); - } else { - fprintf(stderr, " After reading source.\n"); - } /* input file is still open */ - } else { - fprintf(stderr, " Before reading source.\n"); - } /* we tried to read SOME source */ -#endif /* DONTDEF */ - - return; -} /* as_where() */ +void +as_where (namep, linep) + char **namep; + unsigned int *linep; +{ + if (logical_input_file != NULL + && (linep == NULL || logical_input_line >= 0)) + { + *namep = logical_input_file; + if (linep != NULL) + *linep = logical_input_line; + } + else if (physical_input_file != NULL) + { + *namep = physical_input_file; + if (linep != NULL) + *linep = physical_input_line; + } + else + { + *namep = (char *) "*unknown*"; + if (linep != NULL) + *linep = 0; + } +} /* as_where() */ + - /* * a s _ h o w m u c h () * @@ -403,46 +440,40 @@ void as_where() { * No free '\n' at end of line. */ void - as_howmuch (stream) -FILE * stream; /* Opened for write please. */ +as_howmuch (stream) + FILE *stream; /* Opened for write please. */ { - register char * p; /* Scan input line. */ - /* register char c; JF unused */ - - for (p = input_line_pointer - 1; * p != '\n'; --p) - { - } - ++ p; /* p->1st char of line. */ - for (; p <= input_line_pointer; p++) - { - /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */ - /* c = *p & 0xFF; JF unused */ - as_1_char(*p, stream); - } + register char *p; /* Scan input line. */ + /* register char c; JF unused */ + + for (p = input_line_pointer - 1; *p != '\n'; --p) + { + } + ++p; /* p->1st char of line. */ + for (; p <= input_line_pointer; p++) + { + /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */ + /* c = *p & 0xFF; JF unused */ + as_1_char ((unsigned char) *p, stream); + } } -static void as_1_char (c,stream) -unsigned int c; -FILE *stream; +static void +as_1_char (c, stream) + unsigned int c; + FILE *stream; { - if (c > 127) - { - (void)putc('%', stream); - c -= 128; - } - if (c < 32) - { - (void)putc('^', stream); - c += '@'; - } - (void)putc(c, stream); + if (c > 127) + { + (void) putc ('%', stream); + c -= 128; + } + if (c < 32) + { + (void) putc ('^', stream); + c += '@'; + } + (void) putc (c, stream); } -/* - * Local Variables: - * comment-column: 0 - * fill-column: 131 - * End: - */ - /* end of input_scrub.c */ |