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