input-scrub.c revision 60484
133965Sjdp/* input_scrub.c - Break up input buffers into whole numbers of lines. 233965Sjdp Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997 333965Sjdp Free Software Foundation, Inc. 433965Sjdp 533965Sjdp This file is part of GAS, the GNU Assembler. 633965Sjdp 733965Sjdp GAS is free software; you can redistribute it and/or modify 833965Sjdp it under the terms of the GNU General Public License as published by 933965Sjdp the Free Software Foundation; either version 2, or (at your option) 1033965Sjdp any later version. 1133965Sjdp 1233965Sjdp GAS is distributed in the hope that it will be useful, 1333965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1433965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965Sjdp GNU General Public License for more details. 1633965Sjdp 1733965Sjdp You should have received a copy of the GNU General Public License 1833965Sjdp along with GAS; see the file COPYING. If not, write to the Free 1933965Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2033965Sjdp 02111-1307, USA. */ 2133965Sjdp 2233965Sjdp#include <errno.h> /* Need this to make errno declaration right */ 2333965Sjdp#include "as.h" 2433965Sjdp#include "input-file.h" 2533965Sjdp#include "sb.h" 2660484Sobrien#include "listing.h" 2733965Sjdp 2833965Sjdp/* 2933965Sjdp * O/S independent module to supply buffers of sanitised source code 3033965Sjdp * to rest of assembler. We get sanitised input data of arbitrary length. 3133965Sjdp * We break these buffers on line boundaries, recombine pieces that 3233965Sjdp * were broken across buffers, and return a buffer of full lines to 3333965Sjdp * the caller. 3433965Sjdp * The last partial line begins the next buffer we build and return to caller. 3533965Sjdp * The buffer returned to caller is preceeded by BEFORE_STRING and followed 3633965Sjdp * by AFTER_STRING, as sentinels. The last character before AFTER_STRING 3733965Sjdp * is a newline. 3833965Sjdp * Also looks after line numbers, for e.g. error messages. 3933965Sjdp */ 4033965Sjdp 4133965Sjdp/* 4233965Sjdp * We don't care how filthy our buffers are, but our callers assume 4333965Sjdp * that the following sanitation has already been done. 4433965Sjdp * 4533965Sjdp * No comments, reduce a comment to a space. 4633965Sjdp * Reduce a tab to a space unless it is 1st char of line. 4733965Sjdp * All multiple tabs and spaces collapsed into 1 char. Tab only 4833965Sjdp * legal if 1st char of line. 4933965Sjdp * # line file statements converted to .line x;.file y; statements. 5033965Sjdp * Escaped newlines at end of line: remove them but add as many newlines 5133965Sjdp * to end of statement as you removed in the middle, to synch line numbers. 5233965Sjdp */ 5333965Sjdp 5433965Sjdp#define BEFORE_STRING ("\n") 5533965Sjdp#define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */ 5633965Sjdp#define BEFORE_SIZE (1) 5733965Sjdp#define AFTER_SIZE (1) 5833965Sjdp 5933965Sjdpstatic char *buffer_start; /*->1st char of full buffer area. */ 6033965Sjdpstatic char *partial_where; /*->after last full line in buffer. */ 6133965Sjdpstatic int partial_size; /* >=0. Number of chars in partial line in buffer. */ 6233965Sjdpstatic char save_source[AFTER_SIZE]; 6333965Sjdp/* Because we need AFTER_STRING just after last */ 6433965Sjdp/* full line, it clobbers 1st part of partial */ 6533965Sjdp/* line. So we preserve 1st part of partial */ 6633965Sjdp/* line here. */ 6733965Sjdpstatic unsigned int buffer_length; /* What is the largest size buffer that */ 6833965Sjdp/* input_file_give_next_buffer() could */ 6933965Sjdp/* return to us? */ 7033965Sjdp 7133965Sjdp/* The index into an sb structure we are reading from. -1 if none. */ 7233965Sjdpstatic int sb_index = -1; 7333965Sjdp 7433965Sjdp/* If we are reading from an sb structure, this is it. */ 7533965Sjdpstatic sb from_sb; 7633965Sjdp 7760484Sobrien/* Should we do a conditional check on from_sb? */ 7860484Sobrienstatic int from_sb_is_expansion = 1; 7960484Sobrien 8033965Sjdp/* The number of nested sb structures we have included. */ 8133965Sjdpint macro_nest; 8233965Sjdp 8333965Sjdp/* We can have more than one source file open at once, though the info for all 8433965Sjdp but the latest one are saved off in a struct input_save. These files remain 8533965Sjdp open, so we are limited by the number of open files allowed by the 8633965Sjdp underlying OS. We may also sequentially read more than one source file in an 8733965Sjdp assembly. */ 8833965Sjdp 8933965Sjdp/* We must track the physical file and line number for error messages. We also 9033965Sjdp track a "logical" file and line number corresponding to (C?) compiler 9133965Sjdp source line numbers. Whenever we open a file we must fill in 9233965Sjdp physical_input_file. So if it is NULL we have not opened any files yet. */ 9333965Sjdp 9433965Sjdpstatic char *physical_input_file; 9533965Sjdpstatic char *logical_input_file; 9633965Sjdp 9733965Sjdptypedef unsigned int line_numberT; /* 1-origin line number in a source file. */ 9833965Sjdp/* A line ends in '\n' or eof. */ 9933965Sjdp 10033965Sjdpstatic line_numberT physical_input_line; 10133965Sjdpstatic int logical_input_line; 10233965Sjdp 10333965Sjdp/* Struct used to save the state of the input handler during include files */ 10433965Sjdpstruct input_save 10533965Sjdp { 10633965Sjdp char *buffer_start; 10733965Sjdp char *partial_where; 10833965Sjdp int partial_size; 10933965Sjdp char save_source[AFTER_SIZE]; 11033965Sjdp unsigned int buffer_length; 11133965Sjdp char *physical_input_file; 11233965Sjdp char *logical_input_file; 11333965Sjdp line_numberT physical_input_line; 11433965Sjdp int logical_input_line; 11533965Sjdp int sb_index; 11633965Sjdp sb from_sb; 11760484Sobrien int from_sb_is_expansion; /* Should we do a conditional check? */ 11833965Sjdp struct input_save *next_saved_file; /* Chain of input_saves */ 11933965Sjdp char *input_file_save; /* Saved state of input routines */ 12033965Sjdp char *saved_position; /* Caller's saved position in buf */ 12133965Sjdp }; 12233965Sjdp 12333965Sjdpstatic struct input_save *input_scrub_push PARAMS ((char *saved_position)); 12433965Sjdpstatic char *input_scrub_pop PARAMS ((struct input_save *arg)); 12533965Sjdpstatic void as_1_char PARAMS ((unsigned int c, FILE * stream)); 12633965Sjdp 12733965Sjdp/* Saved information about the file that .include'd this one. When we hit EOF, 12833965Sjdp we automatically pop to that file. */ 12933965Sjdp 13033965Sjdpstatic struct input_save *next_saved_file; 13133965Sjdp 13233965Sjdp/* Push the state of input reading and scrubbing so that we can #include. 13333965Sjdp The return value is a 'void *' (fudged for old compilers) to a save 13433965Sjdp area, which can be restored by passing it to input_scrub_pop(). */ 13533965Sjdpstatic struct input_save * 13633965Sjdpinput_scrub_push (saved_position) 13733965Sjdp char *saved_position; 13833965Sjdp{ 13933965Sjdp register struct input_save *saved; 14033965Sjdp 14133965Sjdp saved = (struct input_save *) xmalloc (sizeof *saved); 14233965Sjdp 14333965Sjdp saved->saved_position = saved_position; 14433965Sjdp saved->buffer_start = buffer_start; 14533965Sjdp saved->partial_where = partial_where; 14633965Sjdp saved->partial_size = partial_size; 14733965Sjdp saved->buffer_length = buffer_length; 14833965Sjdp saved->physical_input_file = physical_input_file; 14933965Sjdp saved->logical_input_file = logical_input_file; 15033965Sjdp saved->physical_input_line = physical_input_line; 15133965Sjdp saved->logical_input_line = logical_input_line; 15233965Sjdp saved->sb_index = sb_index; 15333965Sjdp saved->from_sb = from_sb; 15460484Sobrien saved->from_sb_is_expansion = from_sb_is_expansion; 15533965Sjdp memcpy (saved->save_source, save_source, sizeof (save_source)); 15633965Sjdp saved->next_saved_file = next_saved_file; 15733965Sjdp saved->input_file_save = input_file_push (); 15833965Sjdp 15933965Sjdp input_file_begin (); /* Reinitialize! */ 16033965Sjdp logical_input_line = -1; 16133965Sjdp logical_input_file = (char *) NULL; 16233965Sjdp buffer_length = input_file_buffer_size (); 16333965Sjdp sb_index = -1; 16433965Sjdp 16533965Sjdp buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); 16633965Sjdp memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); 16733965Sjdp 16833965Sjdp return saved; 16933965Sjdp} /* input_scrub_push() */ 17033965Sjdp 17133965Sjdpstatic char * 17233965Sjdpinput_scrub_pop (saved) 17333965Sjdp struct input_save *saved; 17433965Sjdp{ 17533965Sjdp char *saved_position; 17633965Sjdp 17733965Sjdp input_scrub_end (); /* Finish off old buffer */ 17833965Sjdp 17933965Sjdp input_file_pop (saved->input_file_save); 18033965Sjdp saved_position = saved->saved_position; 18133965Sjdp buffer_start = saved->buffer_start; 18233965Sjdp buffer_length = saved->buffer_length; 18333965Sjdp physical_input_file = saved->physical_input_file; 18433965Sjdp logical_input_file = saved->logical_input_file; 18533965Sjdp physical_input_line = saved->physical_input_line; 18633965Sjdp logical_input_line = saved->logical_input_line; 18733965Sjdp sb_index = saved->sb_index; 18833965Sjdp from_sb = saved->from_sb; 18960484Sobrien from_sb_is_expansion = saved->from_sb_is_expansion; 19033965Sjdp partial_where = saved->partial_where; 19133965Sjdp partial_size = saved->partial_size; 19233965Sjdp next_saved_file = saved->next_saved_file; 19333965Sjdp memcpy (save_source, saved->save_source, sizeof (save_source)); 19433965Sjdp 19533965Sjdp free (saved); 19633965Sjdp return saved_position; 19733965Sjdp} 19833965Sjdp 19933965Sjdp 20033965Sjdpvoid 20133965Sjdpinput_scrub_begin () 20233965Sjdp{ 20333965Sjdp know (strlen (BEFORE_STRING) == BEFORE_SIZE); 20433965Sjdp know (strlen (AFTER_STRING) == AFTER_SIZE || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1)); 20533965Sjdp 20633965Sjdp input_file_begin (); 20733965Sjdp 20833965Sjdp buffer_length = input_file_buffer_size (); 20933965Sjdp 21033965Sjdp buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); 21133965Sjdp memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); 21233965Sjdp 21333965Sjdp /* Line number things. */ 21433965Sjdp logical_input_line = -1; 21533965Sjdp logical_input_file = (char *) NULL; 21633965Sjdp physical_input_file = NULL; /* No file read yet. */ 21733965Sjdp next_saved_file = NULL; /* At EOF, don't pop to any other file */ 21833965Sjdp do_scrub_begin (flag_m68k_mri); 21933965Sjdp} 22033965Sjdp 22133965Sjdpvoid 22233965Sjdpinput_scrub_end () 22333965Sjdp{ 22433965Sjdp if (buffer_start) 22533965Sjdp { 22633965Sjdp free (buffer_start); 22733965Sjdp buffer_start = 0; 22833965Sjdp input_file_end (); 22933965Sjdp } 23033965Sjdp} 23133965Sjdp 23233965Sjdp/* Start reading input from a new file. */ 23333965Sjdp 23433965Sjdpchar * /* Return start of caller's part of buffer. */ 23533965Sjdpinput_scrub_new_file (filename) 23633965Sjdp char *filename; 23733965Sjdp{ 23833965Sjdp input_file_open (filename, !flag_no_comments); 23960484Sobrien physical_input_file = filename[0] ? filename : _("{standard input}"); 24033965Sjdp physical_input_line = 0; 24133965Sjdp 24233965Sjdp partial_size = 0; 24333965Sjdp return (buffer_start + BEFORE_SIZE); 24433965Sjdp} 24533965Sjdp 24633965Sjdp 24733965Sjdp/* Include a file from the current file. Save our state, cause it to 24833965Sjdp be restored on EOF, and begin handling a new file. Same result as 24933965Sjdp input_scrub_new_file. */ 25033965Sjdp 25133965Sjdpchar * 25233965Sjdpinput_scrub_include_file (filename, position) 25333965Sjdp char *filename; 25433965Sjdp char *position; 25533965Sjdp{ 25633965Sjdp next_saved_file = input_scrub_push (position); 25733965Sjdp return input_scrub_new_file (filename); 25833965Sjdp} 25933965Sjdp 26033965Sjdp/* Start getting input from an sb structure. This is used when 26133965Sjdp expanding a macro. */ 26233965Sjdp 26333965Sjdpvoid 26460484Sobrieninput_scrub_include_sb (from, position, is_expansion) 26533965Sjdp sb *from; 26633965Sjdp char *position; 26760484Sobrien int is_expansion; 26833965Sjdp{ 26933965Sjdp if (macro_nest > max_macro_nest) 27060484Sobrien as_fatal (_("buffers nested too deeply")); 27133965Sjdp ++macro_nest; 27233965Sjdp 27360484Sobrien#ifdef md_macro_start 27460484Sobrien if (is_expansion) 27560484Sobrien { 27660484Sobrien md_macro_start (); 27760484Sobrien } 27860484Sobrien#endif 27960484Sobrien 28033965Sjdp next_saved_file = input_scrub_push (position); 28133965Sjdp 28233965Sjdp sb_new (&from_sb); 28360484Sobrien from_sb_is_expansion = is_expansion; 28438889Sjdp if (from->len >= 1 && from->ptr[0] != '\n') 28538889Sjdp { 28638889Sjdp /* Add the sentinel required by read.c. */ 28738889Sjdp sb_add_char (&from_sb, '\n'); 28838889Sjdp } 28933965Sjdp sb_add_sb (&from_sb, from); 29033965Sjdp sb_index = 1; 29133965Sjdp 29233965Sjdp /* These variables are reset by input_scrub_push. Restore them 29333965Sjdp since we are, after all, still at the same point in the file. */ 29433965Sjdp logical_input_line = next_saved_file->logical_input_line; 29533965Sjdp logical_input_file = next_saved_file->logical_input_file; 29633965Sjdp} 29733965Sjdp 29833965Sjdpvoid 29933965Sjdpinput_scrub_close () 30033965Sjdp{ 30133965Sjdp input_file_close (); 30233965Sjdp} 30333965Sjdp 30433965Sjdpchar * 30533965Sjdpinput_scrub_next_buffer (bufp) 30633965Sjdp char **bufp; 30733965Sjdp{ 30833965Sjdp register char *limit; /*->just after last char of buffer. */ 30933965Sjdp 31033965Sjdp if (sb_index >= 0) 31133965Sjdp { 31233965Sjdp if (sb_index >= from_sb.len) 31333965Sjdp { 31433965Sjdp sb_kill (&from_sb); 31560484Sobrien if (from_sb_is_expansion) 31660484Sobrien { 31760484Sobrien cond_finish_check (macro_nest); 31860484Sobrien#ifdef md_macro_end 31960484Sobrien /* allow the target to clean up per-macro expansion data */ 32060484Sobrien md_macro_end (); 32160484Sobrien#endif 32260484Sobrien } 32360484Sobrien --macro_nest; 32433965Sjdp partial_where = NULL; 32533965Sjdp if (next_saved_file != NULL) 32633965Sjdp *bufp = input_scrub_pop (next_saved_file); 32733965Sjdp return partial_where; 32833965Sjdp } 32933965Sjdp 33033965Sjdp partial_where = from_sb.ptr + from_sb.len; 33133965Sjdp partial_size = 0; 33233965Sjdp *bufp = from_sb.ptr + sb_index; 33333965Sjdp sb_index = from_sb.len; 33433965Sjdp return partial_where; 33533965Sjdp } 33633965Sjdp 33733965Sjdp *bufp = buffer_start + BEFORE_SIZE; 33833965Sjdp 33933965Sjdp if (partial_size) 34033965Sjdp { 34133965Sjdp memcpy (buffer_start + BEFORE_SIZE, partial_where, 34233965Sjdp (unsigned int) partial_size); 34333965Sjdp memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE); 34433965Sjdp } 34533965Sjdp limit = input_file_give_next_buffer (buffer_start 34633965Sjdp + BEFORE_SIZE 34733965Sjdp + partial_size); 34833965Sjdp if (limit) 34933965Sjdp { 35033965Sjdp register char *p; /* Find last newline. */ 35133965Sjdp 35233965Sjdp for (p = limit - 1; *p != '\n'; --p) 35333965Sjdp ; 35433965Sjdp ++p; 35533965Sjdp 35633965Sjdp while (p <= buffer_start + BEFORE_SIZE) 35733965Sjdp { 35833965Sjdp int limoff; 35933965Sjdp 36033965Sjdp limoff = limit - buffer_start; 36133965Sjdp buffer_length += input_file_buffer_size (); 36233965Sjdp buffer_start = xrealloc (buffer_start, 36333965Sjdp (BEFORE_SIZE 36433965Sjdp + 2 * buffer_length 36533965Sjdp + AFTER_SIZE)); 36633965Sjdp *bufp = buffer_start + BEFORE_SIZE; 36733965Sjdp limit = input_file_give_next_buffer (buffer_start + limoff); 36833965Sjdp 36933965Sjdp if (limit == NULL) 37033965Sjdp { 37160484Sobrien as_warn (_("partial line at end of file ignored")); 37233965Sjdp partial_where = NULL; 37333965Sjdp if (next_saved_file) 37433965Sjdp *bufp = input_scrub_pop (next_saved_file); 37533965Sjdp return NULL; 37633965Sjdp } 37733965Sjdp 37833965Sjdp for (p = limit - 1; *p != '\n'; --p) 37933965Sjdp ; 38033965Sjdp ++p; 38133965Sjdp } 38233965Sjdp 38333965Sjdp partial_where = p; 38433965Sjdp partial_size = limit - p; 38533965Sjdp memcpy (save_source, partial_where, (int) AFTER_SIZE); 38633965Sjdp memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE); 38733965Sjdp } 38833965Sjdp else 38933965Sjdp { 39033965Sjdp partial_where = 0; 39133965Sjdp if (partial_size > 0) 39233965Sjdp { 39360484Sobrien as_warn (_("Partial line at end of file ignored")); 39433965Sjdp } 39560484Sobrien 39660484Sobrien /* Tell the listing we've finished the file. */ 39760484Sobrien LISTING_EOF (); 39860484Sobrien 39933965Sjdp /* If we should pop to another file at EOF, do it. */ 40033965Sjdp if (next_saved_file) 40133965Sjdp { 40233965Sjdp *bufp = input_scrub_pop (next_saved_file); /* Pop state */ 40333965Sjdp /* partial_where is now correct to return, since we popped it. */ 40433965Sjdp } 40533965Sjdp } 40633965Sjdp return (partial_where); 40733965Sjdp} /* input_scrub_next_buffer() */ 40833965Sjdp 40933965Sjdp/* 41033965Sjdp * The remaining part of this file deals with line numbers, error 41133965Sjdp * messages and so on. 41233965Sjdp */ 41333965Sjdp 41433965Sjdp 41533965Sjdpint 41633965Sjdpseen_at_least_1_file () /* TRUE if we opened any file. */ 41733965Sjdp{ 41833965Sjdp return (physical_input_file != NULL); 41933965Sjdp} 42033965Sjdp 42133965Sjdpvoid 42233965Sjdpbump_line_counters () 42333965Sjdp{ 42433965Sjdp if (sb_index < 0) 42533965Sjdp { 42633965Sjdp ++physical_input_line; 42733965Sjdp if (logical_input_line >= 0) 42833965Sjdp ++logical_input_line; 42933965Sjdp } 43033965Sjdp} 43133965Sjdp 43233965Sjdp/* 43333965Sjdp * new_logical_line() 43433965Sjdp * 43533965Sjdp * Tells us what the new logical line number and file are. 43633965Sjdp * If the line_number is -1, we don't change the current logical line 43733965Sjdp * number. If it is -2, we decrement the logical line number (this is 43833965Sjdp * to support the .appfile pseudo-op inserted into the stream by 43933965Sjdp * do_scrub_chars). 44033965Sjdp * If the fname is NULL, we don't change the current logical file name. 44138889Sjdp * Returns nonzero if the filename actually changes. 44233965Sjdp */ 44338889Sjdpint 44433965Sjdpnew_logical_line (fname, line_number) 44533965Sjdp char *fname; /* DON'T destroy it! We point to it! */ 44633965Sjdp int line_number; 44733965Sjdp{ 44833965Sjdp if (line_number >= 0) 44933965Sjdp logical_input_line = line_number; 45033965Sjdp else if (line_number == -2 && logical_input_line > 0) 45133965Sjdp --logical_input_line; 45238889Sjdp 45338889Sjdp if (fname 45438889Sjdp && (logical_input_file == NULL 45538889Sjdp || strcmp (logical_input_file, fname))) 45638889Sjdp { 45738889Sjdp logical_input_file = fname; 45838889Sjdp return 1; 45938889Sjdp } 46038889Sjdp else 46138889Sjdp return 0; 46233965Sjdp} /* new_logical_line() */ 46333965Sjdp 46433965Sjdp/* 46533965Sjdp * a s _ w h e r e () 46633965Sjdp * 46733965Sjdp * Return the current file name and line number. 46833965Sjdp * namep should be char * const *, but there are compilers which screw 46933965Sjdp * up declarations like that, and it's easier to avoid it. 47033965Sjdp */ 47133965Sjdpvoid 47233965Sjdpas_where (namep, linep) 47333965Sjdp char **namep; 47433965Sjdp unsigned int *linep; 47533965Sjdp{ 47633965Sjdp if (logical_input_file != NULL 47733965Sjdp && (linep == NULL || logical_input_line >= 0)) 47833965Sjdp { 47933965Sjdp *namep = logical_input_file; 48033965Sjdp if (linep != NULL) 48133965Sjdp *linep = logical_input_line; 48233965Sjdp } 48333965Sjdp else if (physical_input_file != NULL) 48433965Sjdp { 48533965Sjdp *namep = physical_input_file; 48633965Sjdp if (linep != NULL) 48733965Sjdp *linep = physical_input_line; 48833965Sjdp } 48933965Sjdp else 49033965Sjdp { 49133965Sjdp *namep = 0; 49233965Sjdp if (linep != NULL) 49333965Sjdp *linep = 0; 49433965Sjdp } 49533965Sjdp} /* as_where() */ 49633965Sjdp 49733965Sjdp 49833965Sjdp 49933965Sjdp 50033965Sjdp/* 50133965Sjdp * a s _ h o w m u c h () 50233965Sjdp * 50333965Sjdp * Output to given stream how much of line we have scanned so far. 50433965Sjdp * Assumes we have scanned up to and including input_line_pointer. 50533965Sjdp * No free '\n' at end of line. 50633965Sjdp */ 50733965Sjdpvoid 50833965Sjdpas_howmuch (stream) 50933965Sjdp FILE *stream; /* Opened for write please. */ 51033965Sjdp{ 51133965Sjdp register char *p; /* Scan input line. */ 51233965Sjdp /* register char c; JF unused */ 51333965Sjdp 51433965Sjdp for (p = input_line_pointer - 1; *p != '\n'; --p) 51533965Sjdp { 51633965Sjdp } 51733965Sjdp ++p; /* p->1st char of line. */ 51833965Sjdp for (; p <= input_line_pointer; p++) 51933965Sjdp { 52033965Sjdp /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */ 52133965Sjdp as_1_char ((unsigned char) *p, stream); 52233965Sjdp } 52333965Sjdp} 52433965Sjdp 52533965Sjdpstatic void 52633965Sjdpas_1_char (c, stream) 52733965Sjdp unsigned int c; 52833965Sjdp FILE *stream; 52933965Sjdp{ 53033965Sjdp if (c > 127) 53133965Sjdp { 53233965Sjdp (void) putc ('%', stream); 53333965Sjdp c -= 128; 53433965Sjdp } 53533965Sjdp if (c < 32) 53633965Sjdp { 53733965Sjdp (void) putc ('^', stream); 53833965Sjdp c += '@'; 53933965Sjdp } 54033965Sjdp (void) putc (c, stream); 54133965Sjdp} 54233965Sjdp 54333965Sjdp/* end of input_scrub.c */ 544