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