static void print_token (const char *s, token_type t, token_data *td) { fprintf (stderr, "%s: ", s); switch (t) { /* TOKSW */ case TOKEN_SIMPLE: fprintf (stderr, "char:"); break; case TOKEN_WORD: fprintf (stderr, "word:"); break; case TOKEN_STRING: fprintf (stderr, "string:"); break; case TOKEN_MACDEF: fprintf (stderr, "macro: 0x%x\n", TOKEN_DATA_FUNC (td)); break; case TOKEN_EOF: fprintf (stderr, "eof\n"); break; } fprintf (stderr, "\t\"%s\"\n", TOKEN_DATA_TEXT (td)); }
/* * When a MACRO token is seen, next_token () uses get_macro_func () to * retrieve the value of the function pointer. */ static void init_macro_token (token_data *td) { if (isp->type != INPUT_MACRO) internal_error ("Bad call to get_macro_func ()"); TOKEN_DATA_TYPE (td) = TOKEN_FUNC; TOKEN_DATA_FUNC (td) = isp->u.u_m.func; TOKEN_DATA_FUNC_TRACED (td) = isp->u.u_m.traced; }
static void init_macro_token (token_data *td) { if (isp->type != INPUT_MACRO) { M4ERROR ((warning_status, 0, "INTERNAL ERROR: bad call to init_macro_token ()")); abort (); } TOKEN_DATA_TYPE (td) = TOKEN_FUNC; TOKEN_DATA_FUNC (td) = isp->u.func; }
static void init_macro_token (token_data *td) { if (isp->funcs->read_func != macro_read) { MP4HERROR ((warning_status, 0, "INTERNAL ERROR: Bad call to init_macro_token ()")); exit (1); } TOKEN_DATA_TYPE (td) = TOKEN_FUNC; TOKEN_DATA_FUNC (td) = isp->u.u_m.func; TOKEN_DATA_FUNC_TRACED (td) = isp->u.u_m.traced; }
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 (); } }
static int print_token (const char *s, token_type t, token_data *td) { fprintf (stderr, "%s: ", s); switch (t) { /* TOKSW */ case TOKEN_SIMPLE: fprintf (stderr, "char\t\"%s\"\n", TOKEN_DATA_TEXT (td)); break; case TOKEN_WORD: fprintf (stderr, "word\t\"%s\"\n", TOKEN_DATA_TEXT (td)); break; case TOKEN_ENTITY: fprintf (stderr, "entity\t\"%s\"\n", TOKEN_DATA_TEXT (td)); break; case TOKEN_STRING: fprintf (stderr, "string\t\"%s\"\n", TOKEN_DATA_TEXT (td)); break; case TOKEN_QUOTED: fprintf (stderr, "quoted\t\"%s\"\n", TOKEN_DATA_TEXT (td)); break; case TOKEN_BGROUP: fprintf (stderr, "bgroup\n"); break; case TOKEN_EGROUP: fprintf (stderr, "egroup\n"); break; case TOKEN_QUOTE: fprintf (stderr, "quote\n"); break; case TOKEN_SPACE: fprintf (stderr, "space\t\"%s\"\n", TOKEN_DATA_TEXT (td)); break; case TOKEN_MACDEF: fprintf (stderr, "macro 0x%x\n", (int)TOKEN_DATA_FUNC (td)); break; case TOKEN_EOF: fprintf (stderr, "eof\n"); break; case TOKEN_NONE: fprintf (stderr, "none\n"); break; default: MP4HERROR ((warning_status, 0, "INTERNAL ERROR: unknown token in print_token")); break; } return 0; }
token_type next_token (token_data *td, int *line) { int ch; int quote_level; token_type type; #ifdef ENABLE_CHANGEWORD int startpos; char *orig_text = NULL; #endif const char *file; int dummy; obstack_free (&token_stack, token_bottom); if (!line) line = &dummy; /* Can't consume character until after CHAR_MACRO is handled. */ ch = peek_input (); if (ch == CHAR_EOF) { #ifdef DEBUG_INPUT xfprintf (stderr, "next_token -> EOF\n"); #endif next_char (); return TOKEN_EOF; } if (ch == CHAR_MACRO) { init_macro_token (td); next_char (); #ifdef DEBUG_INPUT xfprintf (stderr, "next_token -> MACDEF (%s)\n", find_builtin_by_addr (TOKEN_DATA_FUNC (td))->name); #endif return TOKEN_MACDEF; } next_char (); /* Consume character we already peeked at. */ file = current_file; *line = current_line; if (MATCH (ch, bcomm.string, true)) { obstack_grow (&token_stack, bcomm.string, bcomm.length); while ((ch = next_char ()) != CHAR_EOF && !MATCH (ch, ecomm.string, true)) obstack_1grow (&token_stack, ch); if (ch != CHAR_EOF) obstack_grow (&token_stack, ecomm.string, ecomm.length); else /* current_file changed to "" if we see CHAR_EOF, use the previous value we stored earlier. */ M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, *line, "ERROR: end of file in comment")); type = TOKEN_STRING; } else if (default_word_regexp && (isalpha (ch) || ch == '_')) { obstack_1grow (&token_stack, ch); while ((ch = peek_input ()) != CHAR_EOF && (isalnum (ch) || ch == '_')) { obstack_1grow (&token_stack, ch); next_char (); } type = TOKEN_WORD; } #ifdef ENABLE_CHANGEWORD else if (!default_word_regexp && word_regexp.fastmap[ch]) { obstack_1grow (&token_stack, ch); while (1) { ch = peek_input (); if (ch == CHAR_EOF) break; obstack_1grow (&token_stack, ch); startpos = re_search (&word_regexp, (char *) obstack_base (&token_stack), obstack_object_size (&token_stack), 0, 0, ®s); if (startpos || regs.end [0] != (regoff_t) obstack_object_size (&token_stack)) { *(((char *) obstack_base (&token_stack) + obstack_object_size (&token_stack)) - 1) = '\0'; break; } next_char (); } obstack_1grow (&token_stack, '\0'); orig_text = (char *) obstack_finish (&token_stack); if (regs.start[1] != -1) obstack_grow (&token_stack,orig_text + regs.start[1], regs.end[1] - regs.start[1]); else obstack_grow (&token_stack, orig_text,regs.end[0]); type = TOKEN_WORD; } #endif /* ENABLE_CHANGEWORD */ else if (!MATCH (ch, lquote.string, true)) { switch (ch) { case '(': type = TOKEN_OPEN; break; case ',': type = TOKEN_COMMA; break; case ')': type = TOKEN_CLOSE; break; default: type = TOKEN_SIMPLE; break; } obstack_1grow (&token_stack, ch); } else { bool fast = lquote.length == 1 && rquote.length == 1; quote_level = 1; while (1) { /* Try scanning a buffer first. */ const char *buffer = (isp && isp->type == INPUT_STRING ? isp->u.u_s.string : NULL); if (buffer && *buffer) { size_t len = isp->u.u_s.end - buffer; const char *p = buffer; do { p = (char *) memchr2 (p, *lquote.string, *rquote.string, buffer + len - p); } while (p && fast && (*p++ == *rquote.string ? --quote_level : ++quote_level)); if (p) { if (fast) { assert (!quote_level); obstack_grow (&token_stack, buffer, p - buffer - 1); isp->u.u_s.string += p - buffer; break; } obstack_grow (&token_stack, buffer, p - buffer); ch = to_uchar (*p); isp->u.u_s.string += p - buffer + 1; } else { obstack_grow (&token_stack, buffer, len); isp->u.u_s.string += len; continue; } } /* Fall back to a byte. */ else ch = next_char (); if (ch == CHAR_EOF) /* current_file changed to "" if we see CHAR_EOF, use the previous value we stored earlier. */ M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, *line, "ERROR: end of file in string")); if (MATCH (ch, rquote.string, true)) { if (--quote_level == 0) break; obstack_grow (&token_stack, rquote.string, rquote.length); } else if (MATCH (ch, lquote.string, true)) { quote_level++; obstack_grow (&token_stack, lquote.string, lquote.length); } else obstack_1grow (&token_stack, ch); } type = TOKEN_STRING; } obstack_1grow (&token_stack, '\0'); TOKEN_DATA_TYPE (td) = TOKEN_TEXT; TOKEN_DATA_TEXT (td) = (char *) obstack_finish (&token_stack); #ifdef ENABLE_CHANGEWORD if (orig_text == NULL) orig_text = TOKEN_DATA_TEXT (td); TOKEN_DATA_ORIG_TEXT (td) = orig_text; #endif #ifdef DEBUG_INPUT xfprintf (stderr, "next_token -> %s (%s)\n", token_type_string (type), TOKEN_DATA_TEXT (td)); #endif return type; }
static bool expand_argument (struct obstack *obs, token_data *argp) { token_type t; token_data td; char *text; int paren_level; const char *file = current_file; int line = current_line; TOKEN_DATA_TYPE (argp) = TOKEN_VOID; /* Skip leading white space. */ do { t = next_token (&td, NULL); } while (t == TOKEN_SIMPLE && isspace (to_uchar (*TOKEN_DATA_TEXT (&td)))); paren_level = 0; while (1) { switch (t) { /* TOKSW */ case TOKEN_COMMA: case TOKEN_CLOSE: if (paren_level == 0) { /* The argument MUST be finished, whether we want it or not. */ obstack_1grow (obs, '\0'); text = (char *) obstack_finish (obs); if (TOKEN_DATA_TYPE (argp) == TOKEN_VOID) { TOKEN_DATA_TYPE (argp) = TOKEN_TEXT; TOKEN_DATA_TEXT (argp) = text; } return t == TOKEN_COMMA; } /* fallthru */ case TOKEN_OPEN: case TOKEN_SIMPLE: text = TOKEN_DATA_TEXT (&td); if (*text == '(') paren_level++; else if (*text == ')') paren_level--; expand_token (obs, t, &td, line); break; case TOKEN_EOF: /* current_file changed to "" if we see TOKEN_EOF, use the previous value we stored earlier. */ M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line, "ERROR: end of file in argument list")); break; case TOKEN_WORD: case TOKEN_STRING: expand_token (obs, t, &td, line); break; case TOKEN_MACDEF: if (obstack_object_size (obs) == 0) { TOKEN_DATA_TYPE (argp) = TOKEN_FUNC; TOKEN_DATA_FUNC (argp) = TOKEN_DATA_FUNC (&td); } break; default: M4ERROR ((warning_status, 0, "INTERNAL ERROR: bad token type in expand_argument ()")); abort (); } t = next_token (&td, NULL); } }