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; }
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; }
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); }
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; }
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 *)); }