source: branches/libc-0.6/src/binutils/gas/input-scrub.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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