source: trunk/essentials/sys-devel/m4/src/macro.c

Last change on this file was 3090, checked in by bird, 18 years ago

m4 1.4.8

File size: 11.7 KB
Line 
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
27static void expand_macro (symbol *);
28static void expand_token (struct obstack *, token_type, token_data *);
29
30/* Current recursion level in expand_macro (). */
31int expansion_level = 0;
32
33/* The number of the current call of expand_macro (). */
34static 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. */
45static 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. */
51static struct obstack argv_stack;
52
53/*----------------------------------------------------------------------.
54| This function read all input, and expands each token, one at a time. |
55`----------------------------------------------------------------------*/
56
57void
58expand_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
82static void
83expand_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
139static bool
140expand_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
228static void
229collect_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
272void
273call_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
303static void
304expand_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}
Note: See TracBrowser for help on using the repository browser.