]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/input-scrub.c
19990502 sourceware import
[thirdparty/binutils-gdb.git] / gas / input-scrub.c
1 /* input_scrub.c - Break up input buffers into whole numbers of lines.
2 Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997
3 Free Software Foundation, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22 #include <errno.h> /* Need this to make errno declaration right */
23 #include "as.h"
24 #include "input-file.h"
25 #include "sb.h"
26 #include "listing.h"
27
28 /*
29 * O/S independent module to supply buffers of sanitised source code
30 * to rest of assembler. We get sanitised input data of arbitrary length.
31 * We break these buffers on line boundaries, recombine pieces that
32 * were broken across buffers, and return a buffer of full lines to
33 * the caller.
34 * The last partial line begins the next buffer we build and return to caller.
35 * The buffer returned to caller is preceeded by BEFORE_STRING and followed
36 * by AFTER_STRING, as sentinels. The last character before AFTER_STRING
37 * is a newline.
38 * Also looks after line numbers, for e.g. error messages.
39 */
40
41 /*
42 * We don't care how filthy our buffers are, but our callers assume
43 * that the following sanitation has already been done.
44 *
45 * No comments, reduce a comment to a space.
46 * Reduce a tab to a space unless it is 1st char of line.
47 * All multiple tabs and spaces collapsed into 1 char. Tab only
48 * legal if 1st char of line.
49 * # line file statements converted to .line x;.file y; statements.
50 * Escaped newlines at end of line: remove them but add as many newlines
51 * to end of statement as you removed in the middle, to synch line numbers.
52 */
53 \f
54 #define BEFORE_STRING ("\n")
55 #define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */
56 #define BEFORE_SIZE (1)
57 #define AFTER_SIZE (1)
58
59 static char *buffer_start; /*->1st char of full buffer area. */
60 static char *partial_where; /*->after last full line in buffer. */
61 static int partial_size; /* >=0. Number of chars in partial line in buffer. */
62 static char save_source[AFTER_SIZE];
63 /* Because we need AFTER_STRING just after last */
64 /* full line, it clobbers 1st part of partial */
65 /* line. So we preserve 1st part of partial */
66 /* line here. */
67 static unsigned int buffer_length; /* What is the largest size buffer that */
68 /* input_file_give_next_buffer() could */
69 /* return to us? */
70
71 /* The index into an sb structure we are reading from. -1 if none. */
72 static int sb_index = -1;
73
74 /* If we are reading from an sb structure, this is it. */
75 static sb from_sb;
76
77 /* The number of nested sb structures we have included. */
78 int macro_nest;
79
80 /* We can have more than one source file open at once, though the info for all
81 but the latest one are saved off in a struct input_save. These files remain
82 open, so we are limited by the number of open files allowed by the
83 underlying OS. We may also sequentially read more than one source file in an
84 assembly. */
85
86 /* We must track the physical file and line number for error messages. We also
87 track a "logical" file and line number corresponding to (C?) compiler
88 source line numbers. Whenever we open a file we must fill in
89 physical_input_file. So if it is NULL we have not opened any files yet. */
90
91 static char *physical_input_file;
92 static char *logical_input_file;
93
94 typedef unsigned int line_numberT; /* 1-origin line number in a source file. */
95 /* A line ends in '\n' or eof. */
96
97 static line_numberT physical_input_line;
98 static int logical_input_line;
99
100 /* Struct used to save the state of the input handler during include files */
101 struct input_save
102 {
103 char *buffer_start;
104 char *partial_where;
105 int partial_size;
106 char save_source[AFTER_SIZE];
107 unsigned int buffer_length;
108 char *physical_input_file;
109 char *logical_input_file;
110 line_numberT physical_input_line;
111 int logical_input_line;
112 int sb_index;
113 sb from_sb;
114 struct input_save *next_saved_file; /* Chain of input_saves */
115 char *input_file_save; /* Saved state of input routines */
116 char *saved_position; /* Caller's saved position in buf */
117 };
118
119 static struct input_save *input_scrub_push PARAMS ((char *saved_position));
120 static char *input_scrub_pop PARAMS ((struct input_save *arg));
121 static void as_1_char PARAMS ((unsigned int c, FILE * stream));
122
123 /* Saved information about the file that .include'd this one. When we hit EOF,
124 we automatically pop to that file. */
125
126 static struct input_save *next_saved_file;
127
128 /* Push the state of input reading and scrubbing so that we can #include.
129 The return value is a 'void *' (fudged for old compilers) to a save
130 area, which can be restored by passing it to input_scrub_pop(). */
131 static struct input_save *
132 input_scrub_push (saved_position)
133 char *saved_position;
134 {
135 register struct input_save *saved;
136
137 saved = (struct input_save *) xmalloc (sizeof *saved);
138
139 saved->saved_position = saved_position;
140 saved->buffer_start = buffer_start;
141 saved->partial_where = partial_where;
142 saved->partial_size = partial_size;
143 saved->buffer_length = buffer_length;
144 saved->physical_input_file = physical_input_file;
145 saved->logical_input_file = logical_input_file;
146 saved->physical_input_line = physical_input_line;
147 saved->logical_input_line = logical_input_line;
148 saved->sb_index = sb_index;
149 saved->from_sb = from_sb;
150 memcpy (saved->save_source, save_source, sizeof (save_source));
151 saved->next_saved_file = next_saved_file;
152 saved->input_file_save = input_file_push ();
153
154 input_file_begin (); /* Reinitialize! */
155 logical_input_line = -1;
156 logical_input_file = (char *) NULL;
157 buffer_length = input_file_buffer_size ();
158 sb_index = -1;
159
160 buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
161 memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
162
163 return saved;
164 } /* input_scrub_push() */
165
166 static char *
167 input_scrub_pop (saved)
168 struct input_save *saved;
169 {
170 char *saved_position;
171
172 input_scrub_end (); /* Finish off old buffer */
173
174 input_file_pop (saved->input_file_save);
175 saved_position = saved->saved_position;
176 buffer_start = saved->buffer_start;
177 buffer_length = saved->buffer_length;
178 physical_input_file = saved->physical_input_file;
179 logical_input_file = saved->logical_input_file;
180 physical_input_line = saved->physical_input_line;
181 logical_input_line = saved->logical_input_line;
182 sb_index = saved->sb_index;
183 from_sb = saved->from_sb;
184 partial_where = saved->partial_where;
185 partial_size = saved->partial_size;
186 next_saved_file = saved->next_saved_file;
187 memcpy (save_source, saved->save_source, sizeof (save_source));
188
189 free (saved);
190 return saved_position;
191 }
192 \f
193
194 void
195 input_scrub_begin ()
196 {
197 know (strlen (BEFORE_STRING) == BEFORE_SIZE);
198 know (strlen (AFTER_STRING) == AFTER_SIZE || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1));
199
200 input_file_begin ();
201
202 buffer_length = input_file_buffer_size ();
203
204 buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
205 memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
206
207 /* Line number things. */
208 logical_input_line = -1;
209 logical_input_file = (char *) NULL;
210 physical_input_file = NULL; /* No file read yet. */
211 next_saved_file = NULL; /* At EOF, don't pop to any other file */
212 do_scrub_begin (flag_m68k_mri);
213 }
214
215 void
216 input_scrub_end ()
217 {
218 if (buffer_start)
219 {
220 free (buffer_start);
221 buffer_start = 0;
222 input_file_end ();
223 }
224 }
225
226 /* Start reading input from a new file. */
227
228 char * /* Return start of caller's part of buffer. */
229 input_scrub_new_file (filename)
230 char *filename;
231 {
232 input_file_open (filename, !flag_no_comments);
233 physical_input_file = filename[0] ? filename : _("{standard input}");
234 physical_input_line = 0;
235
236 partial_size = 0;
237 return (buffer_start + BEFORE_SIZE);
238 }
239
240
241 /* Include a file from the current file. Save our state, cause it to
242 be restored on EOF, and begin handling a new file. Same result as
243 input_scrub_new_file. */
244
245 char *
246 input_scrub_include_file (filename, position)
247 char *filename;
248 char *position;
249 {
250 next_saved_file = input_scrub_push (position);
251 return input_scrub_new_file (filename);
252 }
253
254 /* Start getting input from an sb structure. This is used when
255 expanding a macro. */
256
257 void
258 input_scrub_include_sb (from, position)
259 sb *from;
260 char *position;
261 {
262 if (macro_nest > max_macro_nest)
263 as_fatal (_("macros nested too deeply"));
264 ++macro_nest;
265
266 next_saved_file = input_scrub_push (position);
267
268 sb_new (&from_sb);
269 if (from->len >= 1 && from->ptr[0] != '\n')
270 {
271 /* Add the sentinel required by read.c. */
272 sb_add_char (&from_sb, '\n');
273 }
274 sb_add_sb (&from_sb, from);
275 sb_index = 1;
276
277 /* These variables are reset by input_scrub_push. Restore them
278 since we are, after all, still at the same point in the file. */
279 logical_input_line = next_saved_file->logical_input_line;
280 logical_input_file = next_saved_file->logical_input_file;
281 }
282
283 void
284 input_scrub_close ()
285 {
286 input_file_close ();
287 }
288
289 char *
290 input_scrub_next_buffer (bufp)
291 char **bufp;
292 {
293 register char *limit; /*->just after last char of buffer. */
294
295 if (sb_index >= 0)
296 {
297 if (sb_index >= from_sb.len)
298 {
299 sb_kill (&from_sb);
300 cond_finish_check (macro_nest);
301 --macro_nest;
302 partial_where = NULL;
303 if (next_saved_file != NULL)
304 *bufp = input_scrub_pop (next_saved_file);
305 return partial_where;
306 }
307
308 partial_where = from_sb.ptr + from_sb.len;
309 partial_size = 0;
310 *bufp = from_sb.ptr + sb_index;
311 sb_index = from_sb.len;
312 return partial_where;
313 }
314
315 *bufp = buffer_start + BEFORE_SIZE;
316
317 if (partial_size)
318 {
319 memcpy (buffer_start + BEFORE_SIZE, partial_where,
320 (unsigned int) partial_size);
321 memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE);
322 }
323 limit = input_file_give_next_buffer (buffer_start
324 + BEFORE_SIZE
325 + partial_size);
326 if (limit)
327 {
328 register char *p; /* Find last newline. */
329
330 for (p = limit - 1; *p != '\n'; --p)
331 ;
332 ++p;
333
334 while (p <= buffer_start + BEFORE_SIZE)
335 {
336 int limoff;
337
338 limoff = limit - buffer_start;
339 buffer_length += input_file_buffer_size ();
340 buffer_start = xrealloc (buffer_start,
341 (BEFORE_SIZE
342 + 2 * buffer_length
343 + AFTER_SIZE));
344 *bufp = buffer_start + BEFORE_SIZE;
345 limit = input_file_give_next_buffer (buffer_start + limoff);
346
347 if (limit == NULL)
348 {
349 as_warn (_("partial line at end of file ignored"));
350 partial_where = NULL;
351 if (next_saved_file)
352 *bufp = input_scrub_pop (next_saved_file);
353 return NULL;
354 }
355
356 for (p = limit - 1; *p != '\n'; --p)
357 ;
358 ++p;
359 }
360
361 partial_where = p;
362 partial_size = limit - p;
363 memcpy (save_source, partial_where, (int) AFTER_SIZE);
364 memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE);
365 }
366 else
367 {
368 partial_where = 0;
369 if (partial_size > 0)
370 {
371 as_warn (_("Partial line at end of file ignored"));
372 }
373
374 /* Tell the listing we've finished the file. */
375 LISTING_EOF ();
376
377 /* If we should pop to another file at EOF, do it. */
378 if (next_saved_file)
379 {
380 *bufp = input_scrub_pop (next_saved_file); /* Pop state */
381 /* partial_where is now correct to return, since we popped it. */
382 }
383 }
384 return (partial_where);
385 } /* input_scrub_next_buffer() */
386 \f
387 /*
388 * The remaining part of this file deals with line numbers, error
389 * messages and so on.
390 */
391
392
393 int
394 seen_at_least_1_file () /* TRUE if we opened any file. */
395 {
396 return (physical_input_file != NULL);
397 }
398
399 void
400 bump_line_counters ()
401 {
402 if (sb_index < 0)
403 {
404 ++physical_input_line;
405 if (logical_input_line >= 0)
406 ++logical_input_line;
407 }
408 }
409 \f
410 /*
411 * new_logical_line()
412 *
413 * Tells us what the new logical line number and file are.
414 * If the line_number is -1, we don't change the current logical line
415 * number. If it is -2, we decrement the logical line number (this is
416 * to support the .appfile pseudo-op inserted into the stream by
417 * do_scrub_chars).
418 * If the fname is NULL, we don't change the current logical file name.
419 * Returns nonzero if the filename actually changes.
420 */
421 int
422 new_logical_line (fname, line_number)
423 char *fname; /* DON'T destroy it! We point to it! */
424 int line_number;
425 {
426 if (line_number >= 0)
427 logical_input_line = line_number;
428 else if (line_number == -2 && logical_input_line > 0)
429 --logical_input_line;
430
431 if (fname
432 && (logical_input_file == NULL
433 || strcmp (logical_input_file, fname)))
434 {
435 logical_input_file = fname;
436 return 1;
437 }
438 else
439 return 0;
440 } /* new_logical_line() */
441 \f
442 /*
443 * a s _ w h e r e ()
444 *
445 * Return the current file name and line number.
446 * namep should be char * const *, but there are compilers which screw
447 * up declarations like that, and it's easier to avoid it.
448 */
449 void
450 as_where (namep, linep)
451 char **namep;
452 unsigned int *linep;
453 {
454 if (logical_input_file != NULL
455 && (linep == NULL || logical_input_line >= 0))
456 {
457 *namep = logical_input_file;
458 if (linep != NULL)
459 *linep = logical_input_line;
460 }
461 else if (physical_input_file != NULL)
462 {
463 *namep = physical_input_file;
464 if (linep != NULL)
465 *linep = physical_input_line;
466 }
467 else
468 {
469 *namep = 0;
470 if (linep != NULL)
471 *linep = 0;
472 }
473 } /* as_where() */
474 \f
475
476
477
478 /*
479 * a s _ h o w m u c h ()
480 *
481 * Output to given stream how much of line we have scanned so far.
482 * Assumes we have scanned up to and including input_line_pointer.
483 * No free '\n' at end of line.
484 */
485 void
486 as_howmuch (stream)
487 FILE *stream; /* Opened for write please. */
488 {
489 register char *p; /* Scan input line. */
490 /* register char c; JF unused */
491
492 for (p = input_line_pointer - 1; *p != '\n'; --p)
493 {
494 }
495 ++p; /* p->1st char of line. */
496 for (; p <= input_line_pointer; p++)
497 {
498 /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
499 as_1_char ((unsigned char) *p, stream);
500 }
501 }
502
503 static void
504 as_1_char (c, stream)
505 unsigned int c;
506 FILE *stream;
507 {
508 if (c > 127)
509 {
510 (void) putc ('%', stream);
511 c -= 128;
512 }
513 if (c < 32)
514 {
515 (void) putc ('^', stream);
516 c += '@';
517 }
518 (void) putc (c, stream);
519 }
520
521 /* end of input_scrub.c */