Beispiel #1
0
void
trace_pre (const char *name, int id, int argc, token_data **argv)
{
  int i;
  const builtin *bp;

  trace_header (id);
  trace_format ("%s", name);

  if (argc > 1 && (debug_level & DEBUG_TRACE_ARGS))
    {
      trace_format ("(");

      for (i = 1; i < argc; i++)
        {
          if (i != 1)
            trace_format (", ");

          switch (TOKEN_DATA_TYPE (argv[i]))
            {
            case TOKEN_TEXT:
              trace_format ("%l%S%r", TOKEN_DATA_TEXT (argv[i]));
              break;

            case TOKEN_FUNC:
              bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[i]));
              if (bp == NULL)
                {
                  M4ERROR ((warning_status, 0, "\
INTERNAL ERROR: builtin not found in builtin table! (trace_pre ())"));
                  abort ();
                }
              trace_format ("<%s>", bp->name);
              break;

            case TOKEN_VOID:
            default:
              M4ERROR ((warning_status, 0,
                        "INTERNAL ERROR: bad token data type (trace_pre ())"));
              abort ();
            }

        }
Beispiel #2
0
static void
expand_macro (symbol *sym)
{
  struct obstack arguments;     /* Alternate obstack if argc_stack is busy.  */
  unsigned argv_base;           /* Size of argv_stack on entry.  */
  bool use_argc_stack = true;   /* Whether argc_stack is safe.  */
  token_data **argv;
  int argc;
  struct obstack *expansion;
  const char *expanded;
  bool traced;
  int my_call_id;

  /* Report errors at the location where the open parenthesis (if any)
     was found, but after expansion, restore global state back to the
     location of the close parenthesis.  This is safe since we
     guarantee that macro expansion does not alter the state of
     current_file/current_line (dnl, include, and sinclude are special
     cased in the input engine to ensure this fact).  */
  const char *loc_open_file = current_file;
  int loc_open_line = current_line;
  const char *loc_close_file;
  int loc_close_line;

  SYMBOL_PENDING_EXPANSIONS (sym)++;
  expansion_level++;
  if (nesting_limit > 0 && expansion_level > nesting_limit)
    M4ERROR ((EXIT_FAILURE, 0,
              "recursion limit of %d exceeded, use -L<N> to change it",
              nesting_limit));

  macro_call_id++;
  my_call_id = macro_call_id;

  traced = (debug_level & DEBUG_TRACE_ALL) || SYMBOL_TRACED (sym);

  argv_base = obstack_object_size (&argv_stack);
  if (obstack_object_size (&argc_stack) > 0)
    {
      /* We cannot use argc_stack if this is a nested invocation, and an
         outer invocation has an unfinished argument being
         collected.  */
      obstack_init (&arguments);
      use_argc_stack = false;
    }

  if (traced && (debug_level & DEBUG_TRACE_CALL))
    trace_prepre (SYMBOL_NAME (sym), my_call_id);

  collect_arguments (sym, &argv_stack,
                     use_argc_stack ? &argc_stack : &arguments);

  argc = ((obstack_object_size (&argv_stack) - argv_base)
          / sizeof (token_data *));
  argv = (token_data **) ((char *) obstack_base (&argv_stack) + argv_base);

  loc_close_file = current_file;
  loc_close_line = current_line;
  current_file = loc_open_file;
  current_line = loc_open_line;

  if (traced)
    trace_pre (SYMBOL_NAME (sym), my_call_id, argc, argv);

  expansion = push_string_init ();
  call_macro (sym, argc, argv, expansion);
  expanded = push_string_finish ();

  if (traced)
    trace_post (SYMBOL_NAME (sym), my_call_id, argc, expanded);

  current_file = loc_close_file;
  current_line = loc_close_line;

  --expansion_level;
  --SYMBOL_PENDING_EXPANSIONS (sym);

  if (SYMBOL_DELETED (sym))
    free_symbol (sym);

  if (use_argc_stack)
    obstack_free (&argc_stack, argv[0]);
  else
    obstack_free (&arguments, NULL);
  obstack_blank (&argv_stack, -argc * sizeof (token_data *));
}