1 | /* GNU m4 -- A simple macro processor
|
---|
2 |
|
---|
3 | Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006 Free Software
|
---|
4 | Foundation, Inc.
|
---|
5 |
|
---|
6 | This program is free software; you can redistribute it and/or modify
|
---|
7 | it under the terms of the GNU General Public License as published by
|
---|
8 | the Free Software Foundation; either version 2 of the License, or
|
---|
9 | (at your option) any later version.
|
---|
10 |
|
---|
11 | This program is distributed in the hope that it will be useful,
|
---|
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | GNU General Public License for more details.
|
---|
15 |
|
---|
16 | You should have received a copy of the GNU General Public License
|
---|
17 | along with this program; if not, write to the Free Software
|
---|
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
---|
19 | 02110-1301 USA
|
---|
20 | */
|
---|
21 |
|
---|
22 | /* This file contains the functions, that performs the basic argument
|
---|
23 | parsing and macro expansion. */
|
---|
24 |
|
---|
25 | #include "m4.h"
|
---|
26 |
|
---|
27 | static void expand_macro (symbol *);
|
---|
28 | static void expand_token (struct obstack *, token_type, token_data *);
|
---|
29 |
|
---|
30 | /* Current recursion level in expand_macro (). */
|
---|
31 | int expansion_level = 0;
|
---|
32 |
|
---|
33 | /* The number of the current call of expand_macro (). */
|
---|
34 | static int macro_call_id = 0;
|
---|
35 |
|
---|
36 | /* The shared stack of collected arguments for macro calls; as each
|
---|
37 | argument is collected, it is finished and its location stored in
|
---|
38 | argv_stack. Normally, this stack can be used simultaneously by
|
---|
39 | multiple macro calls; the exception is when an outer macro has
|
---|
40 | generated some text, then calls a nested macro, in which case the
|
---|
41 | nested macro must use a local stack to leave the unfinished text
|
---|
42 | alone. Too bad obstack.h does not provide an easy way to reopen a
|
---|
43 | finished object for further growth, but in practice this does not
|
---|
44 | hurt us too much. */
|
---|
45 | static struct obstack argc_stack;
|
---|
46 |
|
---|
47 | /* The shared stack of pointers to collected arguments for macro
|
---|
48 | calls. This object is never finished; we exploit the fact that
|
---|
49 | obstack_blank is documented to take a negative size to reduce the
|
---|
50 | size again. */
|
---|
51 | static struct obstack argv_stack;
|
---|
52 |
|
---|
53 | /*----------------------------------------------------------------------.
|
---|
54 | | This function read all input, and expands each token, one at a time. |
|
---|
55 | `----------------------------------------------------------------------*/
|
---|
56 |
|
---|
57 | void
|
---|
58 | expand_input (void)
|
---|
59 | {
|
---|
60 | token_type t;
|
---|
61 | token_data td;
|
---|
62 |
|
---|
63 | obstack_init (&argc_stack);
|
---|
64 | obstack_init (&argv_stack);
|
---|
65 |
|
---|
66 | while ((t = next_token (&td)) != TOKEN_EOF)
|
---|
67 | expand_token ((struct obstack *) NULL, t, &td);
|
---|
68 |
|
---|
69 | obstack_free (&argc_stack, NULL);
|
---|
70 | obstack_free (&argv_stack, NULL);
|
---|
71 | }
|
---|
72 | |
---|
73 |
|
---|
74 |
|
---|
75 | /*------------------------------------------------------------------------.
|
---|
76 | | Expand one token, according to its type. Potential macro names |
|
---|
77 | | (TOKEN_WORD) are looked up in the symbol table, to see if they have a |
|
---|
78 | | macro definition. If they have, they are expanded as macros, otherwise |
|
---|
79 | | the text are just copied to the output. |
|
---|
80 | `------------------------------------------------------------------------*/
|
---|
81 |
|
---|
82 | static void
|
---|
83 | expand_token (struct obstack *obs, token_type t, token_data *td)
|
---|
84 | {
|
---|
85 | symbol *sym;
|
---|
86 |
|
---|
87 | switch (t)
|
---|
88 | { /* TOKSW */
|
---|
89 | case TOKEN_EOF:
|
---|
90 | case TOKEN_MACDEF:
|
---|
91 | break;
|
---|
92 |
|
---|
93 | case TOKEN_OPEN:
|
---|
94 | case TOKEN_COMMA:
|
---|
95 | case TOKEN_CLOSE:
|
---|
96 | case TOKEN_SIMPLE:
|
---|
97 | case TOKEN_STRING:
|
---|
98 | shipout_text (obs, TOKEN_DATA_TEXT (td), strlen (TOKEN_DATA_TEXT (td)));
|
---|
99 | break;
|
---|
100 |
|
---|
101 | case TOKEN_WORD:
|
---|
102 | sym = lookup_symbol (TOKEN_DATA_TEXT (td), SYMBOL_LOOKUP);
|
---|
103 | if (sym == NULL || SYMBOL_TYPE (sym) == TOKEN_VOID
|
---|
104 | || (SYMBOL_TYPE (sym) == TOKEN_FUNC
|
---|
105 | && SYMBOL_BLIND_NO_ARGS (sym)
|
---|
106 | && peek_token () != TOKEN_OPEN))
|
---|
107 | {
|
---|
108 | #ifdef ENABLE_CHANGEWORD
|
---|
109 | shipout_text (obs, TOKEN_DATA_ORIG_TEXT (td),
|
---|
110 | strlen (TOKEN_DATA_ORIG_TEXT (td)));
|
---|
111 | #else
|
---|
112 | shipout_text (obs, TOKEN_DATA_TEXT (td),
|
---|
113 | strlen (TOKEN_DATA_TEXT (td)));
|
---|
114 | #endif
|
---|
115 | }
|
---|
116 | else
|
---|
117 | expand_macro (sym);
|
---|
118 | break;
|
---|
119 |
|
---|
120 | default:
|
---|
121 | M4ERROR ((warning_status, 0,
|
---|
122 | "INTERNAL ERROR: bad token type in expand_token ()"));
|
---|
123 | abort ();
|
---|
124 | }
|
---|
125 | }
|
---|
126 | |
---|
127 |
|
---|
128 |
|
---|
129 | /*-------------------------------------------------------------------------.
|
---|
130 | | This function parses one argument to a macro call. It expects the first |
|
---|
131 | | left parenthesis, or the separating comma to have been read by the |
|
---|
132 | | caller. It skips leading whitespace, and reads and expands tokens, |
|
---|
133 | | until it finds a comma or an right parenthesis at the same level of |
|
---|
134 | | parentheses. It returns a flag indicating whether the argument read are |
|
---|
135 | | the last for the active macro call. The argument are build on the |
|
---|
136 | | obstack OBS, indirectly through expand_token (). |
|
---|
137 | `-------------------------------------------------------------------------*/
|
---|
138 |
|
---|
139 | static bool
|
---|
140 | expand_argument (struct obstack *obs, token_data *argp)
|
---|
141 | {
|
---|
142 | token_type t;
|
---|
143 | token_data td;
|
---|
144 | char *text;
|
---|
145 | int paren_level;
|
---|
146 | const char *file = current_file;
|
---|
147 | int line = current_line;
|
---|
148 |
|
---|
149 | TOKEN_DATA_TYPE (argp) = TOKEN_VOID;
|
---|
150 |
|
---|
151 | /* Skip leading white space. */
|
---|
152 | do
|
---|
153 | {
|
---|
154 | t = next_token (&td);
|
---|
155 | }
|
---|
156 | while (t == TOKEN_SIMPLE && isspace (to_uchar (*TOKEN_DATA_TEXT (&td))));
|
---|
157 |
|
---|
158 | paren_level = 0;
|
---|
159 |
|
---|
160 | while (1)
|
---|
161 | {
|
---|
162 |
|
---|
163 | switch (t)
|
---|
164 | { /* TOKSW */
|
---|
165 | case TOKEN_COMMA:
|
---|
166 | case TOKEN_CLOSE:
|
---|
167 | if (paren_level == 0)
|
---|
168 | {
|
---|
169 | /* The argument MUST be finished, whether we want it or not. */
|
---|
170 | obstack_1grow (obs, '\0');
|
---|
171 | text = (char *) obstack_finish (obs);
|
---|
172 |
|
---|
173 | if (TOKEN_DATA_TYPE (argp) == TOKEN_VOID)
|
---|
174 | {
|
---|
175 | TOKEN_DATA_TYPE (argp) = TOKEN_TEXT;
|
---|
176 | TOKEN_DATA_TEXT (argp) = text;
|
---|
177 | }
|
---|
178 | return t == TOKEN_COMMA;
|
---|
179 | }
|
---|
180 | /* fallthru */
|
---|
181 | case TOKEN_OPEN:
|
---|
182 | case TOKEN_SIMPLE:
|
---|
183 | text = TOKEN_DATA_TEXT (&td);
|
---|
184 |
|
---|
185 | if (*text == '(')
|
---|
186 | paren_level++;
|
---|
187 | else if (*text == ')')
|
---|
188 | paren_level--;
|
---|
189 | expand_token (obs, t, &td);
|
---|
190 | break;
|
---|
191 |
|
---|
192 | case TOKEN_EOF:
|
---|
193 | /* current_file changed to "" if we see TOKEN_EOF, use the
|
---|
194 | previous value we stored earlier. */
|
---|
195 | M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line,
|
---|
196 | "ERROR: end of file in argument list"));
|
---|
197 | break;
|
---|
198 |
|
---|
199 | case TOKEN_WORD:
|
---|
200 | case TOKEN_STRING:
|
---|
201 | expand_token (obs, t, &td);
|
---|
202 | break;
|
---|
203 |
|
---|
204 | case TOKEN_MACDEF:
|
---|
205 | if (obstack_object_size (obs) == 0)
|
---|
206 | {
|
---|
207 | TOKEN_DATA_TYPE (argp) = TOKEN_FUNC;
|
---|
208 | TOKEN_DATA_FUNC (argp) = TOKEN_DATA_FUNC (&td);
|
---|
209 | }
|
---|
210 | break;
|
---|
211 |
|
---|
212 | default:
|
---|
213 | M4ERROR ((warning_status, 0,
|
---|
214 | "INTERNAL ERROR: bad token type in expand_argument ()"));
|
---|
215 | abort ();
|
---|
216 | }
|
---|
217 |
|
---|
218 | t = next_token (&td);
|
---|
219 | }
|
---|
220 | }
|
---|
221 |
|
---|
222 | /*-------------------------------------------------------------------------.
|
---|
223 | | Collect all the arguments to a call of the macro SYM. The arguments are |
|
---|
224 | | stored on the obstack ARGUMENTS and a table of pointers to the arguments |
|
---|
225 | | on the obstack ARGPTR. |
|
---|
226 | `-------------------------------------------------------------------------*/
|
---|
227 |
|
---|
228 | static void
|
---|
229 | collect_arguments (symbol *sym, struct obstack *argptr,
|
---|
230 | struct obstack *arguments)
|
---|
231 | {
|
---|
232 | token_data td;
|
---|
233 | token_data *tdp;
|
---|
234 | bool more_args;
|
---|
235 | bool groks_macro_args = SYMBOL_MACRO_ARGS (sym);
|
---|
236 |
|
---|
237 | TOKEN_DATA_TYPE (&td) = TOKEN_TEXT;
|
---|
238 | TOKEN_DATA_TEXT (&td) = SYMBOL_NAME (sym);
|
---|
239 | tdp = (token_data *) obstack_copy (arguments, &td, sizeof td);
|
---|
240 | obstack_ptr_grow (argptr, tdp);
|
---|
241 |
|
---|
242 | if (peek_token () == TOKEN_OPEN)
|
---|
243 | {
|
---|
244 | next_token (&td); /* gobble parenthesis */
|
---|
245 | do
|
---|
246 | {
|
---|
247 | more_args = expand_argument (arguments, &td);
|
---|
248 |
|
---|
249 | if (!groks_macro_args && TOKEN_DATA_TYPE (&td) == TOKEN_FUNC)
|
---|
250 | {
|
---|
251 | TOKEN_DATA_TYPE (&td) = TOKEN_TEXT;
|
---|
252 | TOKEN_DATA_TEXT (&td) = (char *) "";
|
---|
253 | }
|
---|
254 | tdp = (token_data *) obstack_copy (arguments, &td, sizeof td);
|
---|
255 | obstack_ptr_grow (argptr, tdp);
|
---|
256 | }
|
---|
257 | while (more_args);
|
---|
258 | }
|
---|
259 | }
|
---|
260 | |
---|
261 |
|
---|
262 |
|
---|
263 | /*------------------------------------------------------------------------.
|
---|
264 | | The actual call of a macro is handled by call_macro (). call_macro () |
|
---|
265 | | is passed a symbol SYM, whose type is used to call either a builtin |
|
---|
266 | | function, or the user macro expansion function expand_user_macro () |
|
---|
267 | | (lives in builtin.c). There are ARGC arguments to the call, stored in |
|
---|
268 | | the ARGV table. The expansion is left on the obstack EXPANSION. Macro |
|
---|
269 | | tracing is also handled here. |
|
---|
270 | `------------------------------------------------------------------------*/
|
---|
271 |
|
---|
272 | void
|
---|
273 | call_macro (symbol *sym, int argc, token_data **argv,
|
---|
274 | struct obstack *expansion)
|
---|
275 | {
|
---|
276 | switch (SYMBOL_TYPE (sym))
|
---|
277 | {
|
---|
278 | case TOKEN_FUNC:
|
---|
279 | (*SYMBOL_FUNC (sym)) (expansion, argc, argv);
|
---|
280 | break;
|
---|
281 |
|
---|
282 | case TOKEN_TEXT:
|
---|
283 | expand_user_macro (expansion, sym, argc, argv);
|
---|
284 | break;
|
---|
285 |
|
---|
286 | default:
|
---|
287 | M4ERROR ((warning_status, 0,
|
---|
288 | "INTERNAL ERROR: bad symbol type in call_macro ()"));
|
---|
289 | abort ();
|
---|
290 | }
|
---|
291 | }
|
---|
292 |
|
---|
293 | /*-------------------------------------------------------------------------.
|
---|
294 | | The macro expansion is handled by expand_macro (). It parses the |
|
---|
295 | | arguments, using collect_arguments (), and builds a table of pointers to |
|
---|
296 | | the arguments. The arguments themselves are stored on a local obstack. |
|
---|
297 | | Expand_macro () uses call_macro () to do the call of the macro. |
|
---|
298 | | |
|
---|
299 | | Expand_macro () is potentially recursive, since it calls expand_argument |
|
---|
300 | | (), which might call expand_token (), which might call expand_macro (). |
|
---|
301 | `-------------------------------------------------------------------------*/
|
---|
302 |
|
---|
303 | static void
|
---|
304 | expand_macro (symbol *sym)
|
---|
305 | {
|
---|
306 | struct obstack arguments; /* Alternate obstack if argc_stack is busy. */
|
---|
307 | unsigned argv_base; /* Size of argv_stack on entry. */
|
---|
308 | bool use_argc_stack = true; /* Whether argc_stack is safe. */
|
---|
309 | token_data **argv;
|
---|
310 | int argc;
|
---|
311 | struct obstack *expansion;
|
---|
312 | const char *expanded;
|
---|
313 | bool traced;
|
---|
314 | int my_call_id;
|
---|
315 |
|
---|
316 | /* Report errors at the location where the open parenthesis (if any)
|
---|
317 | was found, but after expansion, restore global state back to the
|
---|
318 | location of the close parenthesis. This is safe since we
|
---|
319 | guarantee that macro expansion does not alter the state of
|
---|
320 | current_file/current_line (dnl, include, and sinclude are special
|
---|
321 | cased in the input engine to ensure this fact). */
|
---|
322 | const char *loc_open_file = current_file;
|
---|
323 | int loc_open_line = current_line;
|
---|
324 | const char *loc_close_file;
|
---|
325 | int loc_close_line;
|
---|
326 |
|
---|
327 | SYMBOL_PENDING_EXPANSIONS (sym)++;
|
---|
328 | expansion_level++;
|
---|
329 | if (nesting_limit > 0 && expansion_level > nesting_limit)
|
---|
330 | M4ERROR ((EXIT_FAILURE, 0,
|
---|
331 | "ERROR: recursion limit of %d exceeded, use -L<N> to change it",
|
---|
332 | nesting_limit));
|
---|
333 |
|
---|
334 | macro_call_id++;
|
---|
335 | my_call_id = macro_call_id;
|
---|
336 |
|
---|
337 | traced = (debug_level & DEBUG_TRACE_ALL) || SYMBOL_TRACED (sym);
|
---|
338 |
|
---|
339 | argv_base = obstack_object_size (&argv_stack);
|
---|
340 | if (obstack_object_size (&argc_stack) > 0)
|
---|
341 | {
|
---|
342 | /* We cannot use argc_stack if this is a nested invocation, and an
|
---|
343 | outer invocation has an unfinished argument being
|
---|
344 | collected. */
|
---|
345 | obstack_init (&arguments);
|
---|
346 | use_argc_stack = false;
|
---|
347 | }
|
---|
348 |
|
---|
349 | if (traced && (debug_level & DEBUG_TRACE_CALL))
|
---|
350 | trace_prepre (SYMBOL_NAME (sym), my_call_id);
|
---|
351 |
|
---|
352 | collect_arguments (sym, &argv_stack,
|
---|
353 | use_argc_stack ? &argc_stack : &arguments);
|
---|
354 |
|
---|
355 | argc = ((obstack_object_size (&argv_stack) - argv_base)
|
---|
356 | / sizeof (token_data *));
|
---|
357 | argv = (token_data **) ((char *) obstack_base (&argv_stack) + argv_base);
|
---|
358 |
|
---|
359 | loc_close_file = current_file;
|
---|
360 | loc_close_line = current_line;
|
---|
361 | current_file = loc_open_file;
|
---|
362 | current_line = loc_open_line;
|
---|
363 |
|
---|
364 | if (traced)
|
---|
365 | trace_pre (SYMBOL_NAME (sym), my_call_id, argc, argv);
|
---|
366 |
|
---|
367 | expansion = push_string_init ();
|
---|
368 | call_macro (sym, argc, argv, expansion);
|
---|
369 | expanded = push_string_finish ();
|
---|
370 |
|
---|
371 | if (traced)
|
---|
372 | trace_post (SYMBOL_NAME (sym), my_call_id, argc, argv, expanded);
|
---|
373 |
|
---|
374 | current_file = loc_close_file;
|
---|
375 | current_line = loc_close_line;
|
---|
376 |
|
---|
377 | --expansion_level;
|
---|
378 | --SYMBOL_PENDING_EXPANSIONS (sym);
|
---|
379 |
|
---|
380 | if (SYMBOL_DELETED (sym))
|
---|
381 | free_symbol (sym);
|
---|
382 |
|
---|
383 | if (use_argc_stack)
|
---|
384 | obstack_free (&argc_stack, argv[0]);
|
---|
385 | else
|
---|
386 | obstack_free (&arguments, NULL);
|
---|
387 | obstack_blank (&argv_stack, -argc * sizeof (token_data *));
|
---|
388 | }
|
---|