From cbc69f844ef9dcec70f15d45467026c5fd937db2 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Wed, 5 Jun 2002 20:27:12 +0000 Subject: [PATCH] cpphash.h (_cpp_create_definition): Update prototype. * cpphash.h (_cpp_create_definition): Update prototype. (_cpp_push_text_context, _cpp_create_trad_definition): New. ( cpp_lex_identifier_trad): New. (_cpp_set_trad_context): New. * cppinit.c (cpp_finish_options): Don't conditionalize builtins. * cpplib.c (SEEN_EOL): Update. (lex_macro_node): Update for -traditional. (cpp_push_buffer, _cpp_pop_buffer): Similarly. * cppmacro.c (_cpp_create_definition): Split into create_iso_definition() and _cpp_create_trad_definition(). (warn_of_redefinition): Update prototype; handle traditional macros. (_cpp_push_text_context): New. * cpptrad.c (skip_whitespace, push_replacement_text): New. (lex_identifier): Call ht_lookup with correct start. (_cpp_lex_identifier_tradm _cpp_create_trad_definition, _cpp_set_trad_context): New. (scan_out_logical_line): Update to handle changing contexts. From-SVN: r54293 --- gcc/ChangeLog | 21 +++++++ gcc/cpphash.h | 7 ++- gcc/cppinit.c | 8 +-- gcc/cpplib.c | 66 +++++++++++--------- gcc/cppmacro.c | 152 +++++++++++++++++++++++++++------------------ gcc/cpptrad.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 317 insertions(+), 101 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9fac44231aa..a51e8cfcced 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2002-06-05 Neil Booth + + * cpphash.h (_cpp_create_definition): Update prototype. + (_cpp_push_text_context, _cpp_create_trad_definition): New. + ( cpp_lex_identifier_trad): New. + (_cpp_set_trad_context): New. + * cppinit.c (cpp_finish_options): Don't conditionalize builtins. + * cpplib.c (SEEN_EOL): Update. + (lex_macro_node): Update for -traditional. + (cpp_push_buffer, _cpp_pop_buffer): Similarly. + * cppmacro.c (_cpp_create_definition): Split into + create_iso_definition() and _cpp_create_trad_definition(). + (warn_of_redefinition): Update prototype; handle traditional + macros. + (_cpp_push_text_context): New. + * cpptrad.c (skip_whitespace, push_replacement_text): New. + (lex_identifier): Call ht_lookup with correct start. + (_cpp_lex_identifier_tradm _cpp_create_trad_definition, + _cpp_set_trad_context): New. + (scan_out_logical_line): Update to handle changing contexts. + Wed Jun 5 20:42:31 2002 J"orn Rennecke * config.gcc (sh-*-elf*, sh64*-*-elf*): Unify. diff --git a/gcc/cpphash.h b/gcc/cpphash.h index 6d3f1b9fb09..e508b80ddcf 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -424,8 +424,11 @@ extern int _cpp_begin_message PARAMS ((cpp_reader *, int, /* In cppmacro.c */ extern void _cpp_free_definition PARAMS ((cpp_hashnode *)); -extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *)); +extern bool _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *)); extern void _cpp_pop_context PARAMS ((cpp_reader *)); +extern void _cpp_push_text_context PARAMS ((cpp_reader *, cpp_hashnode *, + const uchar *, const uchar*)); +extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *)); /* In cpphash.c */ extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *)); @@ -478,6 +481,8 @@ extern void _cpp_pop_buffer PARAMS ((cpp_reader *)); extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *)); extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *, size_t)); +extern cpp_hashnode *_cpp_lex_identifier_trad PARAMS ((cpp_reader *)); +extern void _cpp_set_trad_context PARAMS ((cpp_reader *)); /* Utility routines and macros. */ #define DSC(str) (const uchar *)str, sizeof str - 1 diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 580ef35a87d..9d6a105852a 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -995,12 +995,10 @@ cpp_finish_options (pfile) struct pending_option *p; _cpp_do_file_change (pfile, LC_RENAME, _(""), 1, 0); - if (!CPP_OPTION (pfile, traditional) /* REMOVEME */) - init_builtins (pfile); + init_builtins (pfile); _cpp_do_file_change (pfile, LC_RENAME, _(""), 1, 0); - if (!CPP_OPTION (pfile, traditional) /* REMOVEME */) - for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next) - (*p->handler) (pfile, p->arg); + for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next) + (*p->handler) (pfile, p->arg); /* Scan -imacros files after -D, -U, but before -include. pfile->next_include_file is NULL, so _cpp_pop_buffer does not diff --git a/gcc/cpplib.c b/gcc/cpplib.c index e819ffca4d0..acc6f111f47 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -202,7 +202,8 @@ static const directive linemarker_dir = do_linemarker, U"#", 1, KANDR, IN_I }; -#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF) +#define SEEN_EOL() (CPP_OPTION (pfile, traditional) \ + || pfile->cur_token[-1].type == CPP_EOF) /* Skip any remaining tokens in a directive. */ static void @@ -447,7 +448,6 @@ lex_macro_node (pfile) cpp_reader *pfile; { cpp_hashnode *node; - const cpp_token *token = _cpp_lex_token (pfile); /* The token immediately after #define must be an identifier. That identifier may not be "defined", per C99 6.10.8p4. @@ -459,39 +459,43 @@ lex_macro_node (pfile) Note that if we're copying comments into macro expansions, we could encounter comment tokens here, so eat them all up first. */ - if (! CPP_OPTION (pfile, discard_comments_in_macro_exp)) + if (CPP_OPTION (pfile, traditional)) + node = _cpp_lex_identifier_trad (pfile); + else { - while (token->type == CPP_COMMENT) - token = _cpp_lex_token (pfile); - } + const cpp_token *token = _cpp_lex_token (pfile); + + if (! CPP_OPTION (pfile, discard_comments_in_macro_exp)) + { + while (token->type == CPP_COMMENT) + token = _cpp_lex_token (pfile); + } - if (token->type != CPP_NAME) - { if (token->type == CPP_EOF) - cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive", - pfile->directive->name); - else if (token->flags & NAMED_OP) - cpp_error (pfile, DL_ERROR, - "\"%s\" cannot be used as a macro name as it is an operator in C++", - NODE_NAME (token->val.node)); + { + cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive", + pfile->directive->name); + return NULL; + } + + if (token->type == CPP_NAME || (token->flags & NAMED_OP)) + node = token->val.node; else - cpp_error (pfile, DL_ERROR, "macro names must be identifiers"); - - return 0; + node = NULL; } - node = token->val.node; - if (node->flags & NODE_POISONED) - return 0; + if (!node) + cpp_error (pfile, DL_ERROR, "macro names must be identifiers"); + else if (node->flags & NODE_OPERATOR) + cpp_error (pfile, DL_ERROR, + "\"%s\" cannot be used as a macro name as it is an operator in C++", + NODE_NAME (node)); + else if (node == pfile->spec_nodes.n_defined) + cpp_error (pfile, DL_ERROR, "\"defined\" cannot be used as a macro name"); + else if (! (node->flags & NODE_POISONED)) + return node; - if (node == pfile->spec_nodes.n_defined) - { - cpp_error (pfile, DL_ERROR, "\"%s\" cannot be used as a macro name", - NODE_NAME (node)); - return 0; - } - - return node; + return NULL; } /* Process a #define directive. Most work is done in cppmacro.c. */ @@ -1890,6 +1894,9 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof) pfile->buffer = new; + if (CPP_OPTION (pfile, traditional)) + _cpp_set_trad_context (pfile); + return new; } @@ -1934,6 +1941,9 @@ _cpp_pop_buffer (pfile) _cpp_maybe_push_include_file (pfile); } } + + if (pfile->buffer && CPP_OPTION (pfile, traditional)) + _cpp_set_trad_context (pfile); } /* Enter all recognised directives in the hash table. */ diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index ae5dfa92ec9..0b1f0ffc9fe 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -62,13 +62,14 @@ static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **, static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, cpp_macro *, macro_arg *)); static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *)); +static bool create_iso_definition PARAMS ((cpp_reader *, cpp_macro *)); /* #define directive parsing and handling. */ static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *)); static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *)); -static int warn_of_redefinition PARAMS ((const cpp_hashnode *, - const cpp_macro *)); +static bool warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *, + const cpp_macro *)); static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *)); static int parse_params PARAMS ((cpp_reader *, cpp_macro *)); static void check_trad_stringification PARAMS ((cpp_reader *, @@ -917,6 +918,22 @@ push_token_context (pfile, macro, first, count) LAST (context).token = first + count; } +/* Push a traditional macro's replacement text. */ +void +_cpp_push_text_context (pfile, macro, start, end) + cpp_reader *pfile; + cpp_hashnode *macro; + const uchar *start, *end; +{ + cpp_context *context = next_context (pfile); + + context->direct_p = true; + context->macro = macro; + context->buff = NULL; + CUR (context) = start; + RLIMIT (context) = end; +} + /* Expand an argument ARG before replacing parameters in a function-like macro. This works by pushing a context with the argument's tokens, and then expanding that into a temporary buffer @@ -1127,8 +1144,9 @@ _cpp_backup_tokens (pfile, count) /* #define directive parsing and handling. */ /* Returns non-zero if a macro redefinition warning is required. */ -static int -warn_of_redefinition (node, macro2) +static bool +warn_of_redefinition (pfile, node, macro2) + cpp_reader *pfile; const cpp_hashnode *node; const cpp_macro *macro2; { @@ -1137,7 +1155,7 @@ warn_of_redefinition (node, macro2) /* Some redefinitions need to be warned about regardless. */ if (node->flags & NODE_WARN) - return 1; + return true; /* Redefinition of a macro is allowed if and only if the old and new definitions are the same. (6.10.3 paragraph 2). */ @@ -1148,19 +1166,22 @@ warn_of_redefinition (node, macro2) || macro1->paramc != macro2->paramc || macro1->fun_like != macro2->fun_like || macro1->variadic != macro2->variadic) - return 1; - - /* Check each token. */ - for (i = 0; i < macro1->count; i++) - if (! _cpp_equiv_tokens (¯o1->exp.tokens[i], ¯o2->exp.tokens[i])) - return 1; + return true; /* Check parameter spellings. */ for (i = 0; i < macro1->paramc; i++) if (macro1->params[i] != macro2->params[i]) - return 1; + return true; - return 0; + /* Check the replacement text or tokens. */ + if (CPP_OPTION (pfile, traditional)) + return memcmp (macro1->exp.text, macro2->exp.text, macro1->count); + + for (i = 0; i < macro1->count; i++) + if (!_cpp_equiv_tokens (¯o1->exp.tokens[i], ¯o2->exp.tokens[i])) + return true; + + return false; } /* Free the definition of hashnode H. */ @@ -1316,24 +1337,13 @@ lex_expansion_token (pfile, macro) return token; } -/* Parse a macro and save its expansion. Returns non-zero on success. */ -int -_cpp_create_definition (pfile, node) +static bool +create_iso_definition (pfile, macro) cpp_reader *pfile; - cpp_hashnode *node; + cpp_macro *macro; { - cpp_macro *macro; - cpp_token *token, *saved_cur_token; + cpp_token *token; const cpp_token *ctoken; - unsigned int i, ok = 1; - - macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); - macro->line = pfile->directive_line; - macro->params = 0; - macro->paramc = 0; - macro->variadic = 0; - macro->count = 0; - macro->fun_like = 0; /* Get the first token of the expansion (or the '(' of a function-like macro). */ @@ -1341,10 +1351,10 @@ _cpp_create_definition (pfile, node) if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) { - ok = parse_params (pfile, macro); + bool ok = parse_params (pfile, macro); macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); if (!ok) - goto cleanup2; + return false; /* Success. Commit the parameter array. */ BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc]; @@ -1354,8 +1364,6 @@ _cpp_create_definition (pfile, node) cpp_error (pfile, DL_PEDWARN, "ISO C requires whitespace after the macro name"); - saved_cur_token = pfile->cur_token; - if (macro->fun_like) token = lex_expansion_token (pfile, macro); else @@ -1381,10 +1389,9 @@ _cpp_create_definition (pfile, node) /* Let assembler get away with murder. */ else if (CPP_OPTION (pfile, lang) != CLK_ASM) { - ok = 0; cpp_error (pfile, DL_ERROR, "'#' is not followed by a macro parameter"); - goto cleanup1; + return false; } } @@ -1401,10 +1408,9 @@ _cpp_create_definition (pfile, node) if (macro->count == 0 || token->type == CPP_EOF) { - ok = 0; cpp_error (pfile, DL_ERROR, "'##' cannot appear at either end of a macro expansion"); - goto cleanup1; + return false; } token[-1].flags |= PASTE_LEFT; @@ -1425,25 +1431,68 @@ _cpp_create_definition (pfile, node) /* Commit the memory. */ BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count]; - /* Implement the macro-defined-to-itself optimisation. */ - if (macro->count == 1 && !macro->fun_like - && macro->exp.tokens[0].type == CPP_NAME - && macro->exp.tokens[0].val.node == node) - node->flags |= NODE_DISABLED; + return true; +} +/* Parse a macro and save its expansion. Returns non-zero on success. */ +bool +_cpp_create_definition (pfile, node) + cpp_reader *pfile; + cpp_hashnode *node; +{ + cpp_macro *macro; + unsigned int i; + bool ok; + + macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); + macro->line = pfile->directive_line; + macro->params = 0; + macro->paramc = 0; + macro->variadic = 0; + macro->count = 0; + macro->fun_like = 0; /* To suppress some diagnostics. */ macro->syshdr = pfile->map->sysp != 0; + if (CPP_OPTION (pfile, traditional)) + ok = _cpp_create_trad_definition (pfile, macro); + else + { + cpp_token *saved_cur_token = pfile->cur_token; + + ok = create_iso_definition (pfile, macro); + + /* Restore lexer position because of games lex_expansion_token() + plays lexing the macro. We set the type for SEEN_EOL() in + cpplib.c. + + Longer term we should lex the whole line before coming here, + and just copy the expansion. */ + saved_cur_token[-1].type = pfile->cur_token[-1].type; + pfile->cur_token = saved_cur_token; + + /* Stop the lexer accepting __VA_ARGS__. */ + pfile->state.va_args_ok = 0; + } + + /* Clear the fast argument lookup indices. */ + for (i = macro->paramc; i-- > 0; ) + macro->params[i]->arg_index = 0; + + if (!ok) + return ok; + if (node->type != NT_VOID) { - if (warn_of_redefinition (node, macro)) + if (warn_of_redefinition (pfile, node, macro)) { cpp_error_with_line (pfile, DL_PEDWARN, pfile->directive_line, 0, "\"%s\" redefined", NODE_NAME (node)); if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) - cpp_error_with_line (pfile, DL_PEDWARN, node->value.macro->line, 0, - "this is the location of the previous definition"); + cpp_error_with_line (pfile, DL_PEDWARN, + node->value.macro->line, 0, + "this is the location of the previous definition"); } _cpp_free_definition (node); } @@ -1454,21 +1503,6 @@ _cpp_create_definition (pfile, node) if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_"))) node->flags |= NODE_WARN; - cleanup1: - - /* Set type for SEEN_EOL() in cpplib.c, restore the lexer position. */ - saved_cur_token[-1].type = pfile->cur_token[-1].type; - pfile->cur_token = saved_cur_token; - - cleanup2: - - /* Stop the lexer accepting __VA_ARGS__. */ - pfile->state.va_args_ok = 0; - - /* Clear the fast argument lookup indices. */ - for (i = macro->paramc; i-- > 0; ) - macro->params[i]->arg_index = 0; - return ok; } diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index 4f4d97c9ca7..63972487333 100644 --- a/gcc/cpptrad.c +++ b/gcc/cpptrad.c @@ -23,16 +23,19 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Lexing TODO: Handle -C, maybe -CC, and space in escaped newlines. Stop cpplex.c from recognizing comments and directives during its - lexing pass. Get rid of line_base usage - seems pointless? */ + lexing pass. Get rid of line_base usage - seems pointless? Do we + get escaped newline at EOF correct? */ static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *)); static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *, const uchar *)); +static const uchar *skip_whitespace PARAMS ((cpp_reader *, const uchar *)); static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *)); static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *)); static void scan_out_logical_line PARAMS ((cpp_reader *pfile)); static void check_output_buffer PARAMS ((cpp_reader *, size_t)); static void restore_buff PARAMS ((cpp_reader *)); +static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *)); /* Ensures we have N bytes' space in the output buffer, and reallocates it if not. */ @@ -118,6 +121,47 @@ skip_comment (pfile, cur) return cur; } +/* Skip any horizontal whitespace and comments beginning at CUR, + returning the following character. */ +static const uchar * +skip_whitespace (pfile, cur) + cpp_reader *pfile; + const uchar *cur; +{ + const uchar *tmp; + + for (;;) + { + while (is_nvspace (*cur) && *cur != 0) + cur++; + + if (*cur == '\0' && cur != RLIMIT (pfile->context)) + continue; + + if (*cur == '\\') + { + tmp = cur; + cur = skip_escaped_newlines (pfile, cur); + if (tmp != cur) + continue; + } + + if (*cur == '/') + { + tmp = skip_escaped_newlines (pfile, cur + 1); + if (*tmp == '*') + { + cur = skip_comment (pfile, tmp + 1); + continue; + } + } + + break; + } + + return cur; +} + /* Lexes and outputs an identifier starting at CUR, which is assumed to point to a valid first character of an identifier. Returns the hashnode, and updates trad_out_cur. */ @@ -128,6 +172,7 @@ lex_identifier (pfile, cur) { size_t len; uchar *out = pfile->trad_out_cur; + cpp_hashnode *result; do { @@ -140,9 +185,27 @@ lex_identifier (pfile, cur) CUR (pfile->context) = cur; len = out - pfile->trad_out_cur; + result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur, + len, HT_ALLOC); pfile->trad_out_cur = out; - return (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur, - len, HT_ALLOC); + return result; +} + +/* Reads an identifier, returning its hashnode. If the next token is + not an identifier, returns NULL. */ +cpp_hashnode * +_cpp_lex_identifier_trad (pfile) + cpp_reader *pfile; +{ + const uchar *cur = skip_whitespace (pfile, CUR (pfile->context)); + + if (!ISIDST (*cur)) + { + CUR (pfile->context) = cur; + return NULL; + } + + return lex_identifier (pfile, cur); } /* Overlays the true file buffer temporarily with text of length LEN @@ -226,11 +289,14 @@ static void scan_out_logical_line (pfile) cpp_reader *pfile; { - cpp_context *context = pfile->context; - const uchar *cur = CUR (context); + cpp_context *context; + const uchar *cur; unsigned int c, quote = 0; uchar *out; + new_context: + context = pfile->context; + cur = CUR (context); check_output_buffer (pfile, RLIMIT (context) - cur); out = pfile->trad_out_cur; @@ -246,6 +312,16 @@ scan_out_logical_line (pfile) case '\0': if (cur - 1 != RLIMIT (context)) break; + + /* If this is a macro's expansion, pop it. */ + if (context->prev) + { + pfile->trad_out_cur = out - 1; + _cpp_pop_context (pfile); + goto new_context; + } + + /* Premature end of file. Fake a new line. */ cur--; if (!pfile->buffer->from_stage3) cpp_error (pfile, DL_PEDWARN, "no newline at end of file"); @@ -254,11 +330,10 @@ scan_out_logical_line (pfile) case '\r': case '\n': cur = handle_newline (pfile, cur - 1); + out[-1] = '\0'; finish_output: - out[-1] = '\n'; - out[0] = '\0'; CUR (context) = cur; - pfile->trad_out_cur = out; + pfile->trad_out_cur = out - 1; return; case '"': @@ -309,6 +384,13 @@ scan_out_logical_line (pfile) pfile->trad_out_cur = --out; node = lex_identifier (pfile, cur - 1); + if (node->type == NT_MACRO) + { + /* Remove the macro name from the output. */ + pfile->trad_out_cur = out; + push_replacement_text (pfile, node); + goto new_context; + } out = pfile->trad_out_cur; cur = CUR (context); } @@ -319,3 +401,69 @@ scan_out_logical_line (pfile) } } } + +/* Push a context holding the replacement text of the macro NODE on + the context stack. Doesn't yet handle special built-ins or + function-like macros. */ +static void +push_replacement_text (pfile, node) + cpp_reader *pfile; + cpp_hashnode *node; +{ + cpp_macro *macro = node->value.macro; + + _cpp_push_text_context (pfile, node, + macro->exp.text, + macro->exp.text + macro->count); +} + +/* Analyze and save the replacement text of a macro. */ +bool +_cpp_create_trad_definition (pfile, macro) + cpp_reader *pfile; + cpp_macro *macro; +{ + const uchar *cur, *limit; + uchar *exp; + size_t len; + + /* Skip leading whitespace now. */ + CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context)); + + pfile->trad_out_cur = pfile->trad_out_base; + scan_out_logical_line (pfile); + + /* Skip trailing white space. */ + cur = pfile->trad_out_base; + limit = pfile->trad_out_cur; + while (limit > cur && is_space (limit[-1])) + limit--; + + len = (size_t) (limit - cur); + exp = _cpp_unaligned_alloc (pfile, len + 1); + memcpy (exp, cur, len); + exp[len] = '\0'; + + macro->exp.text = exp; + /* Include NUL. */ + macro->count = len; + + return true; +} + +/* Prepare to be able to scan the current buffer. */ +void +_cpp_set_trad_context (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + cpp_context *context = pfile->context; + + if (pfile->context->prev) + abort (); + + pfile->trad_out_cur = pfile->trad_out_base; + CUR (context) = buffer->cur; + RLIMIT (context) = buffer->rlimit; + check_output_buffer (pfile, RLIMIT (context) - CUR (context)); +}