input-scrub.c revision 78828
133965Sjdp/* input_scrub.c - Break up input buffers into whole numbers of lines. 278828Sobrien Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 378828Sobrien 2000 433965Sjdp Free Software Foundation, Inc. 533965Sjdp 633965Sjdp This file is part of GAS, the GNU Assembler. 733965Sjdp 833965Sjdp GAS is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2, or (at your option) 1133965Sjdp any later version. 1233965Sjdp 1333965Sjdp GAS is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with GAS; see the file COPYING. If not, write to the Free 2033965Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2177298Sobrien 02111-1307, USA. */ 2233965Sjdp 2333965Sjdp#include <errno.h> /* Need this to make errno declaration right */ 2433965Sjdp#include "as.h" 2533965Sjdp#include "input-file.h" 2633965Sjdp#include "sb.h" 2760484Sobrien#include "listing.h" 2833965Sjdp 2933965Sjdp/* 3033965Sjdp * O/S independent module to supply buffers of sanitised source code 3133965Sjdp * to rest of assembler. We get sanitised input data of arbitrary length. 3233965Sjdp * We break these buffers on line boundaries, recombine pieces that 3333965Sjdp * were broken across buffers, and return a buffer of full lines to 3433965Sjdp * the caller. 3533965Sjdp * The last partial line begins the next buffer we build and return to caller. 3633965Sjdp * The buffer returned to caller is preceeded by BEFORE_STRING and followed 3733965Sjdp * by AFTER_STRING, as sentinels. The last character before AFTER_STRING 3833965Sjdp * is a newline. 3933965Sjdp * Also looks after line numbers, for e.g. error messages. 4033965Sjdp */ 4133965Sjdp 4233965Sjdp/* 4333965Sjdp * We don't care how filthy our buffers are, but our callers assume 4433965Sjdp * that the following sanitation has already been done. 4533965Sjdp * 4633965Sjdp * No comments, reduce a comment to a space. 4733965Sjdp * Reduce a tab to a space unless it is 1st char of line. 4833965Sjdp * All multiple tabs and spaces collapsed into 1 char. Tab only 4933965Sjdp * legal if 1st char of line. 5033965Sjdp * # line file statements converted to .line x;.file y; statements. 5133965Sjdp * Escaped newlines at end of line: remove them but add as many newlines 5233965Sjdp * to end of statement as you removed in the middle, to synch line numbers. 5333965Sjdp */ 5433965Sjdp 5533965Sjdp#define BEFORE_STRING ("\n") 5677298Sobrien#define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */ 5733965Sjdp#define BEFORE_SIZE (1) 5833965Sjdp#define AFTER_SIZE (1) 5933965Sjdp 6077298Sobrienstatic char *buffer_start; /*->1st char of full buffer area. */ 6177298Sobrienstatic char *partial_where; /*->after last full line in buffer. */ 6277298Sobrienstatic int partial_size; /* >=0. Number of chars in partial line in buffer. */ 6377298Sobrien 6477298Sobrien/* Because we need AFTER_STRING just after last full line, it clobbers 6577298Sobrien 1st part of partial line. So we preserve 1st part of partial line 6677298Sobrien here. */ 6733965Sjdpstatic char save_source[AFTER_SIZE]; 6833965Sjdp 6977298Sobrien/* What is the largest size buffer that input_file_give_next_buffer() 7077298Sobrien could return to us? */ 7177298Sobrienstatic unsigned int buffer_length; 7277298Sobrien 7333965Sjdp/* The index into an sb structure we are reading from. -1 if none. */ 7433965Sjdpstatic int sb_index = -1; 7533965Sjdp 7633965Sjdp/* If we are reading from an sb structure, this is it. */ 7733965Sjdpstatic sb from_sb; 7833965Sjdp 7960484Sobrien/* Should we do a conditional check on from_sb? */ 8060484Sobrienstatic int from_sb_is_expansion = 1; 8160484Sobrien 8233965Sjdp/* The number of nested sb structures we have included. */ 8333965Sjdpint macro_nest; 8433965Sjdp 8533965Sjdp/* We can have more than one source file open at once, though the info for all 8633965Sjdp but the latest one are saved off in a struct input_save. These files remain 8733965Sjdp open, so we are limited by the number of open files allowed by the 8833965Sjdp underlying OS. We may also sequentially read more than one source file in an 8977298Sobrien assembly. */ 9033965Sjdp 9133965Sjdp/* We must track the physical file and line number for error messages. We also 9233965Sjdp track a "logical" file and line number corresponding to (C?) compiler 9333965Sjdp source line numbers. Whenever we open a file we must fill in 9477298Sobrien physical_input_file. So if it is NULL we have not opened any files yet. */ 9533965Sjdp 9633965Sjdpstatic char *physical_input_file; 9733965Sjdpstatic char *logical_input_file; 9833965Sjdp 9977298Sobrientypedef unsigned int line_numberT; /* 1-origin line number in a source file. */ 10077298Sobrien/* A line ends in '\n' or eof. */ 10133965Sjdp 10233965Sjdpstatic line_numberT physical_input_line; 10333965Sjdpstatic int logical_input_line; 10433965Sjdp 10533965Sjdp/* Struct used to save the state of the input handler during include files */ 10677298Sobrienstruct input_save { 10777298Sobrien char * buffer_start; 10877298Sobrien char * partial_where; 10977298Sobrien int partial_size; 11077298Sobrien char save_source[AFTER_SIZE]; 11177298Sobrien unsigned int buffer_length; 11277298Sobrien char * physical_input_file; 11377298Sobrien char * logical_input_file; 11477298Sobrien line_numberT physical_input_line; 11577298Sobrien int logical_input_line; 11677298Sobrien int sb_index; 11777298Sobrien sb from_sb; 11877298Sobrien int from_sb_is_expansion; /* Should we do a conditional check? */ 11977298Sobrien struct input_save * next_saved_file; /* Chain of input_saves. */ 12077298Sobrien char * input_file_save; /* Saved state of input routines. */ 12177298Sobrien char * saved_position; /* Caller's saved position in buf. */ 12277298Sobrien}; 12333965Sjdp 12433965Sjdpstatic struct input_save *input_scrub_push PARAMS ((char *saved_position)); 12533965Sjdpstatic char *input_scrub_pop PARAMS ((struct input_save *arg)); 12633965Sjdpstatic void as_1_char PARAMS ((unsigned int c, FILE * stream)); 12733965Sjdp 12833965Sjdp/* Saved information about the file that .include'd this one. When we hit EOF, 12977298Sobrien we automatically pop to that file. */ 13033965Sjdp 13133965Sjdpstatic struct input_save *next_saved_file; 13233965Sjdp 13333965Sjdp/* Push the state of input reading and scrubbing so that we can #include. 13433965Sjdp The return value is a 'void *' (fudged for old compilers) to a save 13577298Sobrien area, which can be restored by passing it to input_scrub_pop(). */ 13677298Sobrien 13733965Sjdpstatic struct input_save * 13833965Sjdpinput_scrub_push (saved_position) 13933965Sjdp char *saved_position; 14033965Sjdp{ 14133965Sjdp register struct input_save *saved; 14233965Sjdp 14333965Sjdp saved = (struct input_save *) xmalloc (sizeof *saved); 14433965Sjdp 14533965Sjdp saved->saved_position = saved_position; 14633965Sjdp saved->buffer_start = buffer_start; 14733965Sjdp saved->partial_where = partial_where; 14833965Sjdp saved->partial_size = partial_size; 14933965Sjdp saved->buffer_length = buffer_length; 15033965Sjdp saved->physical_input_file = physical_input_file; 15133965Sjdp saved->logical_input_file = logical_input_file; 15233965Sjdp saved->physical_input_line = physical_input_line; 15333965Sjdp saved->logical_input_line = logical_input_line; 15433965Sjdp saved->sb_index = sb_index; 15533965Sjdp saved->from_sb = from_sb; 15660484Sobrien saved->from_sb_is_expansion = from_sb_is_expansion; 15733965Sjdp memcpy (saved->save_source, save_source, sizeof (save_source)); 15833965Sjdp saved->next_saved_file = next_saved_file; 15933965Sjdp saved->input_file_save = input_file_push (); 16033965Sjdp 16133965Sjdp input_file_begin (); /* Reinitialize! */ 16233965Sjdp logical_input_line = -1; 16333965Sjdp logical_input_file = (char *) NULL; 16433965Sjdp buffer_length = input_file_buffer_size (); 16533965Sjdp sb_index = -1; 16633965Sjdp 16733965Sjdp buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); 16833965Sjdp memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); 16933965Sjdp 17033965Sjdp return saved; 17177298Sobrien} 17233965Sjdp 17333965Sjdpstatic char * 17433965Sjdpinput_scrub_pop (saved) 17533965Sjdp struct input_save *saved; 17633965Sjdp{ 17733965Sjdp char *saved_position; 17833965Sjdp 17933965Sjdp input_scrub_end (); /* Finish off old buffer */ 18033965Sjdp 18133965Sjdp input_file_pop (saved->input_file_save); 18233965Sjdp saved_position = saved->saved_position; 18333965Sjdp buffer_start = saved->buffer_start; 18433965Sjdp buffer_length = saved->buffer_length; 18533965Sjdp physical_input_file = saved->physical_input_file; 18633965Sjdp logical_input_file = saved->logical_input_file; 18733965Sjdp physical_input_line = saved->physical_input_line; 18833965Sjdp logical_input_line = saved->logical_input_line; 18933965Sjdp sb_index = saved->sb_index; 19033965Sjdp from_sb = saved->from_sb; 19160484Sobrien from_sb_is_expansion = saved->from_sb_is_expansion; 19233965Sjdp partial_where = saved->partial_where; 19333965Sjdp partial_size = saved->partial_size; 19433965Sjdp next_saved_file = saved->next_saved_file; 19533965Sjdp memcpy (save_source, saved->save_source, sizeof (save_source)); 19633965Sjdp 19733965Sjdp free (saved); 19833965Sjdp return saved_position; 19933965Sjdp} 20033965Sjdp 20133965Sjdpvoid 20233965Sjdpinput_scrub_begin () 20333965Sjdp{ 20433965Sjdp know (strlen (BEFORE_STRING) == BEFORE_SIZE); 20577298Sobrien know (strlen (AFTER_STRING) == AFTER_SIZE 20677298Sobrien || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1)); 20733965Sjdp 20833965Sjdp input_file_begin (); 20933965Sjdp 21033965Sjdp buffer_length = input_file_buffer_size (); 21133965Sjdp 21233965Sjdp buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); 21333965Sjdp memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); 21433965Sjdp 21577298Sobrien /* Line number things. */ 21633965Sjdp logical_input_line = -1; 21733965Sjdp logical_input_file = (char *) NULL; 21877298Sobrien physical_input_file = NULL; /* No file read yet. */ 21933965Sjdp next_saved_file = NULL; /* At EOF, don't pop to any other file */ 22033965Sjdp do_scrub_begin (flag_m68k_mri); 22133965Sjdp} 22233965Sjdp 22333965Sjdpvoid 22433965Sjdpinput_scrub_end () 22533965Sjdp{ 22633965Sjdp if (buffer_start) 22733965Sjdp { 22833965Sjdp free (buffer_start); 22933965Sjdp buffer_start = 0; 23033965Sjdp input_file_end (); 23133965Sjdp } 23233965Sjdp} 23333965Sjdp 23477298Sobrien/* Start reading input from a new file. 23577298Sobrien Return start of caller's part of buffer. */ 23633965Sjdp 23777298Sobrienchar * 23833965Sjdpinput_scrub_new_file (filename) 23933965Sjdp char *filename; 24033965Sjdp{ 24133965Sjdp input_file_open (filename, !flag_no_comments); 24260484Sobrien physical_input_file = filename[0] ? filename : _("{standard input}"); 24333965Sjdp physical_input_line = 0; 24433965Sjdp 24533965Sjdp partial_size = 0; 24633965Sjdp return (buffer_start + BEFORE_SIZE); 24733965Sjdp} 24833965Sjdp 24933965Sjdp/* Include a file from the current file. Save our state, cause it to 25033965Sjdp be restored on EOF, and begin handling a new file. Same result as 25177298Sobrien input_scrub_new_file. */ 25233965Sjdp 25333965Sjdpchar * 25433965Sjdpinput_scrub_include_file (filename, position) 25533965Sjdp char *filename; 25633965Sjdp char *position; 25733965Sjdp{ 25833965Sjdp next_saved_file = input_scrub_push (position); 25933965Sjdp return input_scrub_new_file (filename); 26033965Sjdp} 26133965Sjdp 26233965Sjdp/* Start getting input from an sb structure. This is used when 26333965Sjdp expanding a macro. */ 26433965Sjdp 26533965Sjdpvoid 26660484Sobrieninput_scrub_include_sb (from, position, is_expansion) 26733965Sjdp sb *from; 26833965Sjdp char *position; 26960484Sobrien int is_expansion; 27033965Sjdp{ 27133965Sjdp if (macro_nest > max_macro_nest) 27277298Sobrien as_fatal (_("macros nested too deeply")); 27333965Sjdp ++macro_nest; 27433965Sjdp 27560484Sobrien#ifdef md_macro_start 27660484Sobrien if (is_expansion) 27760484Sobrien { 27860484Sobrien md_macro_start (); 27960484Sobrien } 28060484Sobrien#endif 28160484Sobrien 28233965Sjdp next_saved_file = input_scrub_push (position); 28333965Sjdp 28433965Sjdp sb_new (&from_sb); 28560484Sobrien from_sb_is_expansion = is_expansion; 28638889Sjdp if (from->len >= 1 && from->ptr[0] != '\n') 28738889Sjdp { 28838889Sjdp /* Add the sentinel required by read.c. */ 28938889Sjdp sb_add_char (&from_sb, '\n'); 29038889Sjdp } 29133965Sjdp sb_add_sb (&from_sb, from); 29233965Sjdp sb_index = 1; 29333965Sjdp 29433965Sjdp /* These variables are reset by input_scrub_push. Restore them 29533965Sjdp since we are, after all, still at the same point in the file. */ 29633965Sjdp logical_input_line = next_saved_file->logical_input_line; 29733965Sjdp logical_input_file = next_saved_file->logical_input_file; 29833965Sjdp} 29933965Sjdp 30033965Sjdpvoid 30133965Sjdpinput_scrub_close () 30233965Sjdp{ 30333965Sjdp input_file_close (); 30433965Sjdp} 30533965Sjdp 30633965Sjdpchar * 30733965Sjdpinput_scrub_next_buffer (bufp) 30833965Sjdp char **bufp; 30933965Sjdp{ 31077298Sobrien register char *limit; /*->just after last char of buffer. */ 31133965Sjdp 31233965Sjdp if (sb_index >= 0) 31333965Sjdp { 31433965Sjdp if (sb_index >= from_sb.len) 31533965Sjdp { 31633965Sjdp sb_kill (&from_sb); 31777298Sobrien if (from_sb_is_expansion 31877298Sobrien ) 31977298Sobrien { 32077298Sobrien cond_finish_check (macro_nest); 32160484Sobrien#ifdef md_macro_end 32277298Sobrien /* Allow the target to clean up per-macro expansion 32377298Sobrien data. */ 32477298Sobrien md_macro_end (); 32560484Sobrien#endif 32677298Sobrien } 32777298Sobrien --macro_nest; 32833965Sjdp partial_where = NULL; 32933965Sjdp if (next_saved_file != NULL) 33033965Sjdp *bufp = input_scrub_pop (next_saved_file); 33133965Sjdp return partial_where; 33233965Sjdp } 33333965Sjdp 33433965Sjdp partial_where = from_sb.ptr + from_sb.len; 33533965Sjdp partial_size = 0; 33633965Sjdp *bufp = from_sb.ptr + sb_index; 33733965Sjdp sb_index = from_sb.len; 33833965Sjdp return partial_where; 33933965Sjdp } 34033965Sjdp 34133965Sjdp *bufp = buffer_start + BEFORE_SIZE; 34233965Sjdp 34333965Sjdp if (partial_size) 34433965Sjdp { 34533965Sjdp memcpy (buffer_start + BEFORE_SIZE, partial_where, 34633965Sjdp (unsigned int) partial_size); 34733965Sjdp memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE); 34833965Sjdp } 34933965Sjdp limit = input_file_give_next_buffer (buffer_start 35033965Sjdp + BEFORE_SIZE 35133965Sjdp + partial_size); 35233965Sjdp if (limit) 35333965Sjdp { 35477298Sobrien register char *p; /* Find last newline. */ 35533965Sjdp 35633965Sjdp for (p = limit - 1; *p != '\n'; --p) 35733965Sjdp ; 35833965Sjdp ++p; 35933965Sjdp 36033965Sjdp while (p <= buffer_start + BEFORE_SIZE) 36133965Sjdp { 36233965Sjdp int limoff; 36333965Sjdp 36433965Sjdp limoff = limit - buffer_start; 36533965Sjdp buffer_length += input_file_buffer_size (); 36633965Sjdp buffer_start = xrealloc (buffer_start, 36733965Sjdp (BEFORE_SIZE 36833965Sjdp + 2 * buffer_length 36933965Sjdp + AFTER_SIZE)); 37033965Sjdp *bufp = buffer_start + BEFORE_SIZE; 37133965Sjdp limit = input_file_give_next_buffer (buffer_start + limoff); 37233965Sjdp 37333965Sjdp if (limit == NULL) 37433965Sjdp { 37560484Sobrien as_warn (_("partial line at end of file ignored")); 37633965Sjdp partial_where = NULL; 37733965Sjdp if (next_saved_file) 37833965Sjdp *bufp = input_scrub_pop (next_saved_file); 37933965Sjdp return NULL; 38033965Sjdp } 38133965Sjdp 38233965Sjdp for (p = limit - 1; *p != '\n'; --p) 38333965Sjdp ; 38433965Sjdp ++p; 38533965Sjdp } 38633965Sjdp 38733965Sjdp partial_where = p; 38833965Sjdp partial_size = limit - p; 38933965Sjdp memcpy (save_source, partial_where, (int) AFTER_SIZE); 39033965Sjdp memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE); 39133965Sjdp } 39233965Sjdp else 39333965Sjdp { 39433965Sjdp partial_where = 0; 39533965Sjdp if (partial_size > 0) 39633965Sjdp { 39760484Sobrien as_warn (_("Partial line at end of file ignored")); 39833965Sjdp } 39960484Sobrien 40060484Sobrien /* Tell the listing we've finished the file. */ 40160484Sobrien LISTING_EOF (); 40260484Sobrien 40377298Sobrien /* If we should pop to another file at EOF, do it. */ 40433965Sjdp if (next_saved_file) 40533965Sjdp { 40633965Sjdp *bufp = input_scrub_pop (next_saved_file); /* Pop state */ 40777298Sobrien /* partial_where is now correct to return, since we popped it. */ 40833965Sjdp } 40933965Sjdp } 41033965Sjdp return (partial_where); 41177298Sobrien} 41233965Sjdp 41377298Sobrien/* The remaining part of this file deals with line numbers, error 41477298Sobrien messages and so on. Return TRUE if we opened any file. */ 41533965Sjdp 41633965Sjdpint 41777298Sobrienseen_at_least_1_file () 41833965Sjdp{ 41933965Sjdp return (physical_input_file != NULL); 42033965Sjdp} 42133965Sjdp 42233965Sjdpvoid 42333965Sjdpbump_line_counters () 42433965Sjdp{ 42533965Sjdp if (sb_index < 0) 42633965Sjdp { 42733965Sjdp ++physical_input_line; 42833965Sjdp if (logical_input_line >= 0) 42933965Sjdp ++logical_input_line; 43033965Sjdp } 43133965Sjdp} 43233965Sjdp 43377298Sobrien/* Tells us what the new logical line number and file are. 43477298Sobrien If the line_number is -1, we don't change the current logical line 43577298Sobrien number. If it is -2, we decrement the logical line number (this is 43677298Sobrien to support the .appfile pseudo-op inserted into the stream by 43777298Sobrien do_scrub_chars). 43877298Sobrien If the fname is NULL, we don't change the current logical file name. 43977298Sobrien Returns nonzero if the filename actually changes. */ 44077298Sobrien 44138889Sjdpint 44233965Sjdpnew_logical_line (fname, line_number) 44377298Sobrien char *fname; /* DON'T destroy it! We point to it! */ 44433965Sjdp int line_number; 44533965Sjdp{ 44633965Sjdp if (line_number >= 0) 44733965Sjdp logical_input_line = line_number; 44833965Sjdp else if (line_number == -2 && logical_input_line > 0) 44933965Sjdp --logical_input_line; 45038889Sjdp 45138889Sjdp if (fname 45238889Sjdp && (logical_input_file == NULL 45338889Sjdp || strcmp (logical_input_file, fname))) 45438889Sjdp { 45538889Sjdp logical_input_file = fname; 45638889Sjdp return 1; 45738889Sjdp } 45838889Sjdp else 45938889Sjdp return 0; 46077298Sobrien} 46133965Sjdp 46277298Sobrien/* Return the current file name and line number. 46377298Sobrien namep should be char * const *, but there are compilers which screw 46477298Sobrien up declarations like that, and it's easier to avoid it. */ 46577298Sobrien 46677298Sobrienvoid 46733965Sjdpas_where (namep, linep) 46833965Sjdp char **namep; 46933965Sjdp unsigned int *linep; 47033965Sjdp{ 47133965Sjdp if (logical_input_file != NULL 47233965Sjdp && (linep == NULL || logical_input_line >= 0)) 47333965Sjdp { 47433965Sjdp *namep = logical_input_file; 47533965Sjdp if (linep != NULL) 47633965Sjdp *linep = logical_input_line; 47733965Sjdp } 47833965Sjdp else if (physical_input_file != NULL) 47933965Sjdp { 48033965Sjdp *namep = physical_input_file; 48133965Sjdp if (linep != NULL) 48233965Sjdp *linep = physical_input_line; 48333965Sjdp } 48433965Sjdp else 48533965Sjdp { 48633965Sjdp *namep = 0; 48733965Sjdp if (linep != NULL) 48833965Sjdp *linep = 0; 48933965Sjdp } 49077298Sobrien} 49133965Sjdp 49277298Sobrien/* Output to given stream how much of line we have scanned so far. 49377298Sobrien Assumes we have scanned up to and including input_line_pointer. 49477298Sobrien No free '\n' at end of line. */ 49533965Sjdp 49633965Sjdpvoid 49733965Sjdpas_howmuch (stream) 49877298Sobrien FILE *stream; /* Opened for write please. */ 49933965Sjdp{ 50077298Sobrien register char *p; /* Scan input line. */ 50133965Sjdp 50233965Sjdp for (p = input_line_pointer - 1; *p != '\n'; --p) 50333965Sjdp { 50433965Sjdp } 50577298Sobrien ++p; /* p->1st char of line. */ 50633965Sjdp for (; p <= input_line_pointer; p++) 50733965Sjdp { 50877298Sobrien /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */ 50933965Sjdp as_1_char ((unsigned char) *p, stream); 51033965Sjdp } 51133965Sjdp} 51233965Sjdp 51377298Sobrienstatic void 51433965Sjdpas_1_char (c, stream) 51533965Sjdp unsigned int c; 51633965Sjdp FILE *stream; 51733965Sjdp{ 51833965Sjdp if (c > 127) 51933965Sjdp { 52033965Sjdp (void) putc ('%', stream); 52133965Sjdp c -= 128; 52233965Sjdp } 52333965Sjdp if (c < 32) 52433965Sjdp { 52533965Sjdp (void) putc ('^', stream); 52633965Sjdp c += '@'; 52733965Sjdp } 52833965Sjdp (void) putc (c, stream); 52933965Sjdp} 530