| 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 | }
|
|---|