1*47405Sdonn /* input_scrub.c - layer between app and the rest of the world
2*47405Sdonn    Copyright (C) 1987 Free Software Foundation, Inc.
3*47405Sdonn 
4*47405Sdonn This file is part of GAS, the GNU Assembler.
5*47405Sdonn 
6*47405Sdonn GAS is free software; you can redistribute it and/or modify
7*47405Sdonn it under the terms of the GNU General Public License as published by
8*47405Sdonn the Free Software Foundation; either version 1, or (at your option)
9*47405Sdonn any later version.
10*47405Sdonn 
11*47405Sdonn GAS is distributed in the hope that it will be useful,
12*47405Sdonn but WITHOUT ANY WARRANTY; without even the implied warranty of
13*47405Sdonn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*47405Sdonn GNU General Public License for more details.
15*47405Sdonn 
16*47405Sdonn You should have received a copy of the GNU General Public License
17*47405Sdonn along with GAS; see the file COPYING.  If not, write to
18*47405Sdonn the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19*47405Sdonn 
20*47405Sdonn #include "as.h"
21*47405Sdonn #include "read.h"
22*47405Sdonn #include "input-file.h"
23*47405Sdonn 
24*47405Sdonn /*
25*47405Sdonn  * O/S independent module to supply buffers of sanitised source code
26*47405Sdonn  * to rest of assembler. We get raw input data of some length.
27*47405Sdonn  * Also looks after line numbers, for e.g. error messages.
28*47405Sdonn  * This module used to do the sanitising, but now a pre-processor program
29*47405Sdonn  * (app) does that job so this module is degenerate.
30*47405Sdonn  * Now input is pre-sanitised, so we only worry about finding the
31*47405Sdonn  * last partial line. A buffer of full lines is returned to caller.
32*47405Sdonn  * The last partial line begins the next buffer we build and return to caller.
33*47405Sdonn  * The buffer returned to caller is preceeded by BEFORE_STRING and followed
34*47405Sdonn  * by AFTER_STRING. The last character before AFTER_STRING is a newline.
35*47405Sdonn  */
36*47405Sdonn 
37*47405Sdonn /*
38*47405Sdonn  * We expect the following sanitation has already been done.
39*47405Sdonn  *
40*47405Sdonn  * No comments, reduce a comment to a space.
41*47405Sdonn  * Reduce a tab to a space unless it is 1st char of line.
42*47405Sdonn  * All multiple tabs and spaces collapsed into 1 char. Tab only
43*47405Sdonn  *   legal if 1st char of line.
44*47405Sdonn  * # line file statements converted to .line x;.file y; statements.
45*47405Sdonn  * Escaped newlines at end of line: remove them but add as many newlines
46*47405Sdonn  *   to end of statement as you removed in the middle, to synch line numbers.
47*47405Sdonn  */
48*47405Sdonn 
49*47405Sdonn #define BEFORE_STRING ("\n")
50*47405Sdonn #define AFTER_STRING ("\0")	/* bcopy of 0 chars might choke. */
51*47405Sdonn #define BEFORE_SIZE (1)
52*47405Sdonn #define AFTER_SIZE  (1)
53*47405Sdonn 
54*47405Sdonn static char *	buffer_start;	/* -> 1st char of full buffer area. */
55*47405Sdonn static char *	partial_where;	/* -> after last full line in buffer. */
56*47405Sdonn static int	partial_size;	/* >=0. Number of chars in partial line in buffer. */
57*47405Sdonn static char	save_source [AFTER_SIZE];
58*47405Sdonn 				/* Because we need AFTER_STRING just after last */
59*47405Sdonn 				/* full line, it clobbers 1st part of partial */
60*47405Sdonn 				/* line. So we preserve 1st part of partial */
61*47405Sdonn 				/* line here. */
62*47405Sdonn static int	buffer_length;	/* What is the largest size buffer that */
63*47405Sdonn 				/* input_file_give_next_buffer() could */
64*47405Sdonn 				/* return to us? */
65*47405Sdonn 
66*47405Sdonn static void as_1_char ();
67*47405Sdonn 
68*47405Sdonn /*
69*47405Sdonn We never have more than one source file open at once.
70*47405Sdonn We may, however, read more than 1 source file in an assembly.
71*47405Sdonn NULL means we have no file open right now.
72*47405Sdonn */
73*47405Sdonn 
74*47405Sdonn 
75*47405Sdonn /*
76*47405Sdonn We must track the physical file and line number for error messages.
77*47405Sdonn We also track a "logical" file and line number corresponding to (C?)
78*47405Sdonn compiler source line numbers.
79*47405Sdonn Whenever we open a file we must fill in physical_input_file. So if it is NULL
80*47405Sdonn we have not opened any files yet.
81*47405Sdonn */
82*47405Sdonn 
83*47405Sdonn static
84*47405Sdonn char *		physical_input_file,
85*47405Sdonn      *		logical_input_file;
86*47405Sdonn 
87*47405Sdonn 
88*47405Sdonn 
89*47405Sdonn typedef unsigned int line_numberT;	/* 1-origin line number in a source file. */
90*47405Sdonn 				/* A line ends in '\n' or eof. */
91*47405Sdonn 
92*47405Sdonn static
93*47405Sdonn line_numberT	physical_input_line,
94*47405Sdonn 		logical_input_line;
95*47405Sdonn 
96*47405Sdonn void
97*47405Sdonn input_scrub_begin ()
98*47405Sdonn {
99*47405Sdonn   know( strlen(BEFORE_STRING) == BEFORE_SIZE );
100*47405Sdonn   know( strlen( AFTER_STRING) ==  AFTER_SIZE );
101*47405Sdonn 
102*47405Sdonn   input_file_begin ();
103*47405Sdonn 
104*47405Sdonn   buffer_length = input_file_buffer_size ();
105*47405Sdonn 
106*47405Sdonn   buffer_start = xmalloc ((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
107*47405Sdonn   bcopy (BEFORE_STRING, buffer_start, (int)BEFORE_SIZE);
108*47405Sdonn 
109*47405Sdonn   /* Line number things. */
110*47405Sdonn   logical_input_line = 0;
111*47405Sdonn   logical_input_file = (char *)NULL;
112*47405Sdonn   physical_input_file = NULL;	/* No file read yet. */
113*47405Sdonn   do_scrub_begin();
114*47405Sdonn }
115*47405Sdonn 
116*47405Sdonn void
117*47405Sdonn input_scrub_end ()
118*47405Sdonn {
119*47405Sdonn   input_file_end ();
120*47405Sdonn }
121*47405Sdonn 
122*47405Sdonn char *				/* Return start of caller's part of buffer. */
123*47405Sdonn input_scrub_new_file (filename)
124*47405Sdonn      char *	filename;
125*47405Sdonn {
126*47405Sdonn   input_file_open (filename, !flagseen['f']);
127*47405Sdonn   physical_input_file = filename[0] ? filename : "{standard input}";
128*47405Sdonn   physical_input_line = 0;
129*47405Sdonn 
130*47405Sdonn   partial_size = 0;
131*47405Sdonn   return (buffer_start + BEFORE_SIZE);
132*47405Sdonn }
133*47405Sdonn 
134*47405Sdonn char *
135*47405Sdonn input_scrub_next_buffer (bufp)
136*47405Sdonn char **bufp;
137*47405Sdonn {
138*47405Sdonn   register char *	limit;	/* -> just after last char of buffer. */
139*47405Sdonn 
140*47405Sdonn #ifdef DONTDEF
141*47405Sdonn   if(preprocess) {
142*47405Sdonn     if(save_buffer) {
143*47405Sdonn       *bufp = save_buffer;
144*47405Sdonn       save_buffer = 0;
145*47405Sdonn     }
146*47405Sdonn     limit = input_file_give_next_buffer(buffer_start+BEFORE_SIZE);
147*47405Sdonn     if (!limit) {
148*47405Sdonn       partial_where = 0;
149*47405Sdonn       if(partial_size)
150*47405Sdonn         as_warn("Partial line at end of file ignored");
151*47405Sdonn       return partial_where;
152*47405Sdonn     }
153*47405Sdonn 
154*47405Sdonn     if(partial_size)
155*47405Sdonn       bcopy(save_source, partial_where,(int)AFTER_SIZE);
156*47405Sdonn     do_scrub(partial_where,partial_size,buffer_start+BEFORE_SIZE,limit-(buffer_start+BEFORE_SIZE),&out_string,&out_length);
157*47405Sdonn     limit=out_string + out_length;
158*47405Sdonn     for(p=limit;*--p!='\n';)
159*47405Sdonn       ;
160*47405Sdonn     p++;
161*47405Sdonn     if(p<=buffer_start+BEFORE_SIZE)
162*47405Sdonn       as_fatal("Source line too long.  Please change file '%s' and re-make the assembler.",__FILE__);
163*47405Sdonn 
164*47405Sdonn     partial_where = p;
165*47405Sdonn     partial_size = limit-p;
166*47405Sdonn     bcopy(partial_where, save_source,(int)AFTER_SIZE);
167*47405Sdonn     bcopy(AFTER_STRING, partial_where, (int)AFTER_SIZE);
168*47405Sdonn 
169*47405Sdonn     save_buffer = *bufp;
170*47405Sdonn     *bufp = out_string;
171*47405Sdonn 
172*47405Sdonn     return partial_where;
173*47405Sdonn   }
174*47405Sdonn 
175*47405Sdonn   /* We're not preprocessing.  Do the right thing */
176*47405Sdonn #endif
177*47405Sdonn   if (partial_size)
178*47405Sdonn     {
179*47405Sdonn       bcopy (partial_where, buffer_start + BEFORE_SIZE, (int)partial_size);
180*47405Sdonn       bcopy (save_source, buffer_start + BEFORE_SIZE, (int)AFTER_SIZE);
181*47405Sdonn     }
182*47405Sdonn   limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size);
183*47405Sdonn   if (limit)
184*47405Sdonn     {
185*47405Sdonn       register char *	p;	/* Find last newline. */
186*47405Sdonn 
187*47405Sdonn       for (p = limit;   * -- p != '\n';   )
188*47405Sdonn 	{
189*47405Sdonn 	}
190*47405Sdonn       ++ p;
191*47405Sdonn       if (p <= buffer_start + BEFORE_SIZE)
192*47405Sdonn 	{
193*47405Sdonn 	  as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__);
194*47405Sdonn 	}
195*47405Sdonn       partial_where = p;
196*47405Sdonn       partial_size = limit - p;
197*47405Sdonn       bcopy (partial_where, save_source,  (int)AFTER_SIZE);
198*47405Sdonn       bcopy (AFTER_STRING, partial_where, (int)AFTER_SIZE);
199*47405Sdonn     }
200*47405Sdonn   else
201*47405Sdonn     {
202*47405Sdonn       partial_where = 0;
203*47405Sdonn       if (partial_size > 0)
204*47405Sdonn 	{
205*47405Sdonn 	  as_warn( "Partial line at end of file ignored" );
206*47405Sdonn 	}
207*47405Sdonn     }
208*47405Sdonn   return (partial_where);
209*47405Sdonn }
210*47405Sdonn 
211*47405Sdonn /*
212*47405Sdonn  * The remaining part of this file deals with line numbers, error
213*47405Sdonn  * messages and so on.
214*47405Sdonn  */
215*47405Sdonn 
216*47405Sdonn 
217*47405Sdonn int
218*47405Sdonn seen_at_least_1_file ()		/* TRUE if we opened any file. */
219*47405Sdonn {
220*47405Sdonn   return (physical_input_file != NULL);
221*47405Sdonn }
222*47405Sdonn 
223*47405Sdonn void
224*47405Sdonn bump_line_counters ()
225*47405Sdonn {
226*47405Sdonn   ++ physical_input_line;
227*47405Sdonn   ++ logical_input_line;
228*47405Sdonn }
229*47405Sdonn 
230*47405Sdonn /*
231*47405Sdonn  *			new_logical_line()
232*47405Sdonn  *
233*47405Sdonn  * Tells us what the new logical line number and file are.
234*47405Sdonn  * If the line_number is <0, we don't change the current logical line number.
235*47405Sdonn  * If the fname is NULL, we don't change the current logical file name.
236*47405Sdonn  */
237*47405Sdonn void
238*47405Sdonn new_logical_line (fname, line_number)
239*47405Sdonn      char *	fname;		/* DON'T destroy it! We point to it! */
240*47405Sdonn      int	line_number;
241*47405Sdonn {
242*47405Sdonn   if ( fname )
243*47405Sdonn     {
244*47405Sdonn       logical_input_file = fname;
245*47405Sdonn     }
246*47405Sdonn   if ( line_number >= 0 )
247*47405Sdonn     {
248*47405Sdonn       logical_input_line = line_number;
249*47405Sdonn     }
250*47405Sdonn }
251*47405Sdonn 
252*47405Sdonn /*
253*47405Sdonn  *			a s _ w h e r e ( )
254*47405Sdonn  *
255*47405Sdonn  * Write a line to stderr locating where we are in reading
256*47405Sdonn  * input source files.
257*47405Sdonn  * As a sop to the debugger of AS, pretty-print the offending line.
258*47405Sdonn  */
259*47405Sdonn void
260*47405Sdonn as_where()
261*47405Sdonn {
262*47405Sdonn   char *p;
263*47405Sdonn   line_numberT line;
264*47405Sdonn 
265*47405Sdonn   if (physical_input_file)
266*47405Sdonn     {				/* we tried to read SOME source */
267*47405Sdonn       if (input_file_is_open())
268*47405Sdonn 	{			/* we can still read lines from source */
269*47405Sdonn #ifdef DONTDEF
270*47405Sdonn 	  fprintf (stderr," @ physical line %ld., file \"%s\"",
271*47405Sdonn 		   (long) physical_input_line, physical_input_file);
272*47405Sdonn 	  fprintf (stderr," @ logical line %ld., file \"%s\"\n",
273*47405Sdonn 		   (long) logical_input_line, logical_input_file);
274*47405Sdonn 	  (void)putc(' ', stderr);
275*47405Sdonn 	  as_howmuch (stderr);
276*47405Sdonn 	  (void)putc('\n', stderr);
277*47405Sdonn #else
278*47405Sdonn 		p = logical_input_file ? logical_input_file : physical_input_file;
279*47405Sdonn 		line = logical_input_line ? logical_input_line : physical_input_line;
280*47405Sdonn 		fprintf(stderr,"%s:%u:", p, line);
281*47405Sdonn #endif
282*47405Sdonn 	}
283*47405Sdonn       else
284*47405Sdonn 	{
285*47405Sdonn #ifdef DONTDEF
286*47405Sdonn 	  fprintf (stderr," After reading source.\n");
287*47405Sdonn #else
288*47405Sdonn 	p = logical_input_file ? logical_input_file : physical_input_file;
289*47405Sdonn 	line = logical_input_line ? logical_input_line : physical_input_line;
290*47405Sdonn 	fprintf (stderr,"%s:unknown:", p);
291*47405Sdonn #endif
292*47405Sdonn 	}
293*47405Sdonn     }
294*47405Sdonn   else
295*47405Sdonn     {
296*47405Sdonn #ifdef DONTDEF
297*47405Sdonn       fprintf (stderr," Before reading source.\n");
298*47405Sdonn #else
299*47405Sdonn #endif
300*47405Sdonn     }
301*47405Sdonn }
302*47405Sdonn 
303*47405Sdonn 
304*47405Sdonn 
305*47405Sdonn 
306*47405Sdonn /*
307*47405Sdonn  *			a s _ h o w m u c h ( )
308*47405Sdonn  *
309*47405Sdonn  * Output to given stream how much of line we have scanned so far.
310*47405Sdonn  * Assumes we have scanned up to and including input_line_pointer.
311*47405Sdonn  * No free '\n' at end of line.
312*47405Sdonn  */
313*47405Sdonn void
314*47405Sdonn as_howmuch (stream)
315*47405Sdonn      FILE * stream;		/* Opened for write please. */
316*47405Sdonn {
317*47405Sdonn   register	char *	p;	/* Scan input line. */
318*47405Sdonn   /* register	char	c; JF unused */
319*47405Sdonn 
320*47405Sdonn   for (p = input_line_pointer - 1;   * p != '\n';   --p)
321*47405Sdonn     {
322*47405Sdonn     }
323*47405Sdonn   ++ p;				/* p -> 1st char of line. */
324*47405Sdonn   for (;  p <= input_line_pointer;  p++)
325*47405Sdonn     {
326*47405Sdonn       /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
327*47405Sdonn       /* c = *p & 0xFF; JF unused */
328*47405Sdonn       as_1_char (*p, stream);
329*47405Sdonn     }
330*47405Sdonn }
331*47405Sdonn 
332*47405Sdonn static void
333*47405Sdonn as_1_char (c,stream)
334*47405Sdonn      unsigned char c;
335*47405Sdonn      FILE *	stream;
336*47405Sdonn {
337*47405Sdonn   if ( c > 127 )
338*47405Sdonn     {
339*47405Sdonn       (void)putc( '%', stream);
340*47405Sdonn       c -= 128;
341*47405Sdonn     }
342*47405Sdonn   if ( c < 32 )
343*47405Sdonn     {
344*47405Sdonn       (void)putc( '^', stream);
345*47405Sdonn       c += '@';
346*47405Sdonn     }
347*47405Sdonn   (void)putc( c, stream);
348*47405Sdonn }
349*47405Sdonn 
350*47405Sdonn /* end: input_scrub.c */
351