Beispiel #1
0
static int
match_input (const char *s)
{
  int n;			/* number of characters matched */
  int ch;			/* input character */
  const char *t;

  ch = peek_input ();
  if (ch != *s)
    return 0;			/* fail */
  (void) next_char ();

  if (s[1] == '\0')
    return 1;			/* short match */

  for (n = 1, t = s++; (ch = peek_input ()) == *s++; n++)
    {
      (void) next_char ();
      if (*s == '\0')		/* long match */
	return 1;
    }

  /* Failed, push back input.  */
  obstack_grow (push_string_init (), t, n);
  push_string_finish ();
  return 0;
}
Beispiel #2
0
static boolean
match_comment (const unsigned char *s)
{
  int n;                        /* number of characters matched */
  int ch;                       /* input character */
  const unsigned char *t;
  struct obstack *st;

  ch = peek_input ();
  if (ch != *s)
    return FALSE;               /* fail */

  (void) next_char ();
  if (s[1] == '\0')
    return TRUE;                /* short match */

  for (n = 1, t = s++; (ch = peek_input ()) == *s++; n++)
    {
      (void) next_char ();
      if (*s == '\0')           /* long match */
        return TRUE;
    }

  /* Push back input.  */
  st = push_string_init ();
  obstack_grow (st, t, n);
  push_string_finish (READ_NORMAL);
  return FALSE;
}
Beispiel #3
0
void
read_file_verbatim (struct obstack *obs)
{
  int ch;
  int (*f)(void);
  struct obstack *st;

  if (next != NULL)
    st = obs;
  else
    st = push_string_init ();

  f = isp->funcs->read_func;
  if (f != NULL)
    {
      while ((ch = (*f)()) != CHAR_RETRY)
        obstack_1grow (st, ch);
    }
  else
    {
      MP4HERROR ((warning_status, 0,
        "INTERNAL ERROR: Input stack botch in read_file_verbatim ()"));
      exit (1);
    }
  push_string_finish (READ_BODY);
}
Beispiel #4
0
static bool
match_input (const char *s, bool consume)
{
  int n;                        /* number of characters matched */
  int ch;                       /* input character */
  const char *t;
  bool result = false;

  ch = peek_input ();
  if (ch != to_uchar (*s))
    return false;                       /* fail */

  if (s[1] == '\0')
    {
      if (consume)
        next_char ();
      return true;                      /* short match */
    }

  next_char ();
  for (n = 1, t = s++; peek_input () == to_uchar (*s++); )
    {
      next_char ();
      n++;
      if (*s == '\0')           /* long match */
        {
          if (consume)
            return true;
          result = true;
          break;
        }
    }

  /* Failed or shouldn't consume, push back input.  */
  {
    struct obstack *h = push_string_init ();

    /* `obstack_grow' may be macro evaluating its arg 1 several times. */
    obstack_grow (h, t, n);
  }
  push_string_finish ();
  return result;
}
Beispiel #5
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 *));
}