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