X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcppmacro.c;h=538c689b1e5eee11f3996f6e50d93853973c962e;hb=0e62d8da8abc63fed2972043163030fd5b27df22;hp=47c44716807c2fbbb050e252ac028070a459169e;hpb=1785b647c73cfe054bd95725c39ac711dc324852;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index 47c44716807..538c689b1e5 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -1,6 +1,6 @@ /* Part of CPP library. (Macro and #define handling.) Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Written by Per Bothner, 1994. Based on CCCP program by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 @@ -25,20 +25,18 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "config.h" #include "system.h" -#include "intl.h" /* for _("") below. */ #include "cpplib.h" #include "cpphash.h" struct cpp_macro { cpp_hashnode **params; /* Parameters, if any. */ - cpp_token *expansion; /* First token of replacement list. */ + cpp_token *expansion; /* First token of replacement list. */ unsigned int line; /* Starting line number. */ unsigned int count; /* Number of tokens in expansion. */ unsigned short paramc; /* Number of parameters. */ unsigned int fun_like : 1; /* If a function-like macro. */ unsigned int variadic : 1; /* If a variadic macro. */ - unsigned int disabled : 1; /* If macro is disabled. */ unsigned int syshdr : 1; /* If macro defined in system header. */ }; @@ -46,7 +44,7 @@ typedef struct macro_arg macro_arg; struct macro_arg { const cpp_token **first; /* First token in unexpanded argument. */ - const cpp_token **expanded; /* Macro-expanded argument. */ + const cpp_token **expanded; /* Macro-expanded argument. */ const cpp_token *stringified; /* Stringified argument. */ unsigned int count; /* # of tokens in argument. */ unsigned int expanded_count; /* # of tokens in expanded argument. */ @@ -55,11 +53,11 @@ struct macro_arg /* Macro expansion. */ static int enter_macro_context PARAMS ((cpp_reader *, cpp_hashnode *)); -static const cpp_token *builtin_macro PARAMS ((cpp_reader *, cpp_hashnode *)); +static int builtin_macro PARAMS ((cpp_reader *, cpp_hashnode *)); static void push_token_context - PARAMS ((cpp_reader *, cpp_macro *, const cpp_token *, unsigned int)); + PARAMS ((cpp_reader *, cpp_hashnode *, const cpp_token *, unsigned int)); static void push_ptoken_context - PARAMS ((cpp_reader *, cpp_macro *, _cpp_buff *, + PARAMS ((cpp_reader *, cpp_hashnode *, _cpp_buff *, const cpp_token **, unsigned int)); static _cpp_buff *collect_args PARAMS ((cpp_reader *, const cpp_hashnode *)); static cpp_context *next_context PARAMS ((cpp_reader *)); @@ -71,19 +69,19 @@ static unsigned char *quote_string PARAMS ((unsigned char *, unsigned int)); static const cpp_token *new_string_token PARAMS ((cpp_reader *, U_CHAR *, unsigned int)); -static const cpp_token *new_number_token PARAMS ((cpp_reader *, int)); +static const cpp_token *new_number_token PARAMS ((cpp_reader *, unsigned int)); static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *)); static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *)); static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **, const cpp_token *)); -static int funlike_invocation_p PARAMS ((cpp_reader *, const cpp_hashnode *)); -static void replace_args PARAMS ((cpp_reader *, cpp_macro *, macro_arg *)); +static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_arg *)); +static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *)); /* #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 ((cpp_reader *, const cpp_hashnode *, +static int warn_of_redefinition PARAMS ((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 *)); @@ -113,12 +111,13 @@ new_string_token (pfile, text, len) static const cpp_token * new_number_token (pfile, number) cpp_reader *pfile; - int number; + unsigned int number; { cpp_token *token = _cpp_temp_token (pfile); - unsigned char *buf = _cpp_pool_alloc (&pfile->ident_pool, 20); + /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */ + unsigned char *buf = _cpp_unaligned_alloc (pfile, 21); - sprintf ((char *) buf, "%d", number); + sprintf ((char *) buf, "%u", number); token->type = CPP_NUMBER; token->val.str.text = buf; token->val.str.len = ustrlen (buf); @@ -132,17 +131,22 @@ static const char * const monthnames[] = "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -/* Handle builtin macros like __FILE__. */ -static const cpp_token * +/* Handle builtin macros like __FILE__, and push the resulting token + on the context stack. Also handles _Pragma, for which no new token + is created. Returns 1 if it generates a new token context, 0 to + return the token to the caller. */ +static int builtin_macro (pfile, node) cpp_reader *pfile; cpp_hashnode *node; { + const cpp_token *result; + switch (node->value.builtin) { default: - cpp_ice (pfile, "invalid builtin macro \"%s\"", NODE_NAME (node)); - return new_number_token (pfile, 1); + cpp_ice (pfile, "invalid built-in macro \"%s\"", NODE_NAME (node)); + return 0; case BT_FILE: case BT_BASE_FILE: @@ -158,31 +162,36 @@ builtin_macro (pfile, node) name = map->to_file; len = strlen (name); - buf = _cpp_pool_alloc (&pfile->ident_pool, len * 4 + 1); + buf = _cpp_unaligned_alloc (pfile, len * 4 + 1); len = quote_string (buf, (const unsigned char *) name, len) - buf; - return new_string_token (pfile, buf, len); + result = new_string_token (pfile, buf, len); } - + break; + case BT_INCLUDE_LEVEL: /* The line map depth counts the primary source as level 1, but historically __INCLUDE_DEPTH__ has called the primary source level 0. */ - return new_number_token (pfile, pfile->line_maps.depth - 1); + result = new_number_token (pfile, pfile->line_maps.depth - 1); + break; case BT_SPECLINE: /* If __LINE__ is embedded in a macro, it must expand to the line of the macro's invocation, not its definition. Otherwise things like assert() will not work properly. */ - return new_number_token (pfile, SOURCE_LINE (pfile->map, - pfile->cur_token[-1].line)); + result = new_number_token (pfile, + SOURCE_LINE (pfile->map, + pfile->cur_token[-1].line)); + break; case BT_STDC: { int stdc = (!CPP_IN_SYSTEM_HEADER (pfile) || pfile->spec_nodes.n__STRICT_ANSI__->type != NT_VOID); - return new_number_token (pfile, stdc); + result = new_number_token (pfile, stdc); } + break; case BT_DATE: case BT_TIME: @@ -196,7 +205,7 @@ builtin_macro (pfile, node) struct tm *tb = localtime (&tt); pfile->date.val.str.text = - _cpp_pool_alloc (&pfile->ident_pool, sizeof ("Oct 11 1347")); + _cpp_unaligned_alloc (pfile, sizeof ("Oct 11 1347")); pfile->date.val.str.len = sizeof ("Oct 11 1347") - 1; pfile->date.type = CPP_STRING; pfile->date.flags = 0; @@ -204,7 +213,7 @@ builtin_macro (pfile, node) monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900); pfile->time.val.str.text = - _cpp_pool_alloc (&pfile->ident_pool, sizeof ("12:34:56")); + _cpp_unaligned_alloc (pfile, sizeof ("12:34:56")); pfile->time.val.str.len = sizeof ("12:34:56") - 1; pfile->time.type = CPP_STRING; pfile->time.flags = 0; @@ -212,12 +221,29 @@ builtin_macro (pfile, node) tb->tm_hour, tb->tm_min, tb->tm_sec); } - return node->value.builtin == BT_DATE ? &pfile->date: &pfile->time; + if (node->value.builtin == BT_DATE) + result = &pfile->date; + else + result = &pfile->time; + break; + + case BT_PRAGMA: + /* Don't interpret _Pragma within directives. The standard is + not clear on this, but to me this makes most sense. */ + if (pfile->state.in_directive) + return 0; + + _cpp_do__Pragma (pfile); + return 1; } + + push_token_context (pfile, NULL, result, 1); + return 1; } -/* Adds backslashes before all backslashes and double quotes appearing - in strings. Non-printable characters are converted to octal. */ +/* Copies SRC, of length LEN, to DEST, adding backslashes before all + backslashes and double quotes. Non-printable characters are + converted to octal. DEST must be of sufficient size. */ static U_CHAR * quote_string (dest, src, len) U_CHAR *dest; @@ -248,24 +274,22 @@ quote_string (dest, src, len) return dest; } -/* Convert a token sequence to a single string token according to the - rules of the ISO C #-operator. */ +/* Convert a token sequence ARG to a single string token according to + the rules of the ISO C #-operator. */ static const cpp_token * stringify_arg (pfile, arg) cpp_reader *pfile; macro_arg *arg; { - cpp_pool *pool = &pfile->ident_pool; - unsigned char *start = POOL_FRONT (pool); - unsigned int i, escape_it, total_len = 0, backslash_count = 0; + unsigned char *dest = BUFF_FRONT (pfile->u_buff); + unsigned int i, escape_it, backslash_count = 0; const cpp_token *source = NULL; + size_t len; /* Loop, reading in the argument's tokens. */ for (i = 0; i < arg->count; i++) { - unsigned char *dest; const cpp_token *token = arg->first[i]; - unsigned int len; if (token->type == CPP_PADDING) { @@ -277,21 +301,22 @@ stringify_arg (pfile, arg) escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING || token->type == CPP_CHAR || token->type == CPP_WCHAR); + /* Room for each char being written in octal, initial space and + final NUL. */ len = cpp_token_len (token); if (escape_it) - /* Worst case is each char is octal. */ len *= 4; - len += 2; /* Room for initial space and final NUL. */ + len += 2; - dest = &start[total_len]; - if (dest + len > POOL_LIMIT (pool)) + if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < len) { - _cpp_next_chunk (pool, len, (unsigned char **) &start); - dest = &start[total_len]; + size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff); + _cpp_extend_buff (pfile, &pfile->u_buff, len); + dest = BUFF_FRONT (pfile->u_buff) + len_so_far; } /* Leading white space? */ - if (total_len) + if (dest != BUFF_FRONT (pfile->u_buff)) { if (source == NULL) source = token; @@ -302,15 +327,14 @@ stringify_arg (pfile, arg) if (escape_it) { - unsigned char *buf = (unsigned char *) xmalloc (len); - + _cpp_buff *buff = _cpp_get_buff (pfile, len); + unsigned char *buf = BUFF_FRONT (buff); len = cpp_spell_token (pfile, token, buf) - buf; dest = quote_string (dest, buf, len); - free (buf); + _cpp_release_buff (pfile, buff); } else dest = cpp_spell_token (pfile, token, dest); - total_len = dest - start; if (token->type == CPP_OTHER && token->val.c == '\\') backslash_count++; @@ -322,12 +346,13 @@ stringify_arg (pfile, arg) if (backslash_count & 1) { cpp_warning (pfile, "invalid string literal, ignoring final '\\'"); - total_len--; + dest--; } /* Commit the memory, including NUL, and return the token. */ - POOL_COMMIT (pool, total_len + 1); - return new_string_token (pfile, start, total_len); + len = dest - BUFF_FRONT (pfile->u_buff); + BUFF_FRONT (pfile->u_buff) = dest + 1; + return new_string_token (pfile, dest - len, len); } /* Try to paste two tokens. On success, return non-zero. In any @@ -356,6 +381,7 @@ paste_tokens (pfile, plhs, rhs) && (rhs->type == CPP_MULT || rhs->type == CPP_DIV)) *end++ = ' '; end = cpp_spell_token (pfile, rhs, end); + *end = '\0'; cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true, 1); @@ -368,18 +394,19 @@ paste_tokens (pfile, plhs, rhs) /* Set pfile->cur_token as required by _cpp_lex_direct. */ pfile->cur_token = _cpp_temp_token (pfile); *plhs = _cpp_lex_direct (pfile); - valid = (pfile->buffer->cur == pfile->buffer->rlimit - && pfile->buffer->read_ahead == EOF); + valid = pfile->buffer->cur == pfile->buffer->rlimit; _cpp_pop_buffer (pfile); return valid; } -/* Handles an arbitrarily long sequence of ## operators. This - implementation is left-associative, non-recursive, and finishes a - paste before handling succeeding ones. If the paste fails, we back - up a token to just after the ## operator, with the effect that it - appears in the output stream normally. */ +/* Handles an arbitrarily long sequence of ## operators, with initial + operand LHS. This implementation is left-associative, + non-recursive, and finishes a paste before handling succeeding + ones. If a paste fails, we back up to the RHS of the failing ## + operator before pushing the context containing the result of prior + successful pastes, with the effect that the RHS appears in the + output stream after the pasted LHS normally. */ static void paste_all_tokens (pfile, lhs) cpp_reader *pfile; @@ -422,9 +449,11 @@ paste_all_tokens (pfile, lhs) push_token_context (pfile, NULL, lhs, 1); } -/* Reads and returns the arguments to a function-like macro invocation. - Assumes the opening parenthesis has been processed. If there is an - error, emits an appropriate diagnostic and returns NULL. */ +/* Reads and returns the arguments to a function-like macro + invocation. Assumes the opening parenthesis has been processed. + If there is an error, emits an appropriate diagnostic and returns + NULL. Each argument is terminated by a CPP_EOF token, for the + future benefit of expand_arg(). */ static _cpp_buff * collect_args (pfile, node) cpp_reader *pfile; @@ -447,7 +476,7 @@ collect_args (pfile, node) base_buff = buff; args = (macro_arg *) buff->base; memset (args, 0, argc * sizeof (macro_arg)); - buff->cur = (char *) &args[argc]; + buff->cur = (unsigned char *) &args[argc]; arg = args, argc = 0; /* Collect the tokens making up each argument. We don't yet know @@ -464,10 +493,10 @@ collect_args (pfile, node) for (;;) { /* Require space for 2 new tokens (including a CPP_EOF). */ - if ((char *) &arg->first[ntokens + 2] > buff->limit) + if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit) { - buff = _cpp_extend_buff (pfile, buff, - 1000 * sizeof (cpp_token *)); + buff = _cpp_append_extend_buff (pfile, buff, + 1000 * sizeof (cpp_token *)); arg->first = (const cpp_token **) buff->cur; } @@ -512,7 +541,7 @@ collect_args (pfile, node) overwrite the final legitimate argument, before failing. */ if (argc <= macro->paramc) { - buff->cur = (char *) &arg->first[ntokens + 1]; + buff->cur = (unsigned char *) &arg->first[ntokens + 1]; if (argc != macro->paramc) arg++; } @@ -538,10 +567,12 @@ collect_args (pfile, node) step_back = true; } else - /* We still need the CPP_EOF to end directives, and to end - pre-expansion of a macro argument. */ step_back = (pfile->context->prev || pfile->state.in_directive); + /* We still need the CPP_EOF to end directives, and to end + pre-expansion of a macro argument. Step back is not + unconditional, since we don't want to return a CPP_EOF to our + callers at the end of an -include-d file. */ if (step_back) _cpp_backup_tokens (pfile, 1); cpp_error (pfile, "unterminated argument list invoking macro \"%s\"", @@ -590,83 +621,108 @@ collect_args (pfile, node) return NULL; } -static int +/* Search for an opening parenthesis to the macro of NODE, in such a + way that, if none is found, we don't lose the information in any + intervening padding tokens. If we find the parenthesis, collect + the arguments and return the buffer containing them. */ +static _cpp_buff * funlike_invocation_p (pfile, node) cpp_reader *pfile; - const cpp_hashnode *node; + cpp_hashnode *node; { - const cpp_token *maybe_paren; - _cpp_buff *buff = NULL; - - pfile->state.prevent_expansion++; - pfile->keep_tokens++; - - pfile->state.parsing_args = 1; - do - maybe_paren = cpp_get_token (pfile); - while (maybe_paren->type == CPP_PADDING); - pfile->state.parsing_args = 2; + const cpp_token *token, *padding = NULL; - if (maybe_paren->type == CPP_OPEN_PAREN) - buff = collect_args (pfile, node); - else + for (;;) { - _cpp_backup_tokens (pfile, 1); - if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr) - cpp_warning (pfile, - "function-like macro \"%s\" must be used with arguments in traditional C", - NODE_NAME (node)); + token = cpp_get_token (pfile); + if (token->type != CPP_PADDING) + break; + if (padding == NULL + || (!(padding->flags & PREV_WHITE) && token->val.source == NULL)) + padding = token; } - pfile->state.parsing_args = 0; - pfile->keep_tokens--; - pfile->state.prevent_expansion--; - - if (buff) + if (token->type == CPP_OPEN_PAREN) { - if (node->value.macro->paramc > 0) - replace_args (pfile, node->value.macro, (macro_arg *) buff->base); - _cpp_release_buff (pfile, buff); + pfile->state.parsing_args = 2; + return collect_args (pfile, node); } - return buff != 0; + /* Back up. We may have skipped padding, in which case backing up + more than one token when expanding macros is in general too + difficult. We re-insert it in its own context. */ + _cpp_backup_tokens (pfile, 1); + if (padding) + push_token_context (pfile, NULL, padding, 1); + + return NULL; } -/* Push the context of a macro onto the context stack. TOKEN is the - macro name. If we can successfully start expanding the macro, - TOKEN is replaced with the first token of the expansion, and we - return non-zero. */ +/* Push the context of a macro with hash entry NODE onto the context + stack. If we can successfully expand the macro, we push a context + containing its yet-to-be-rescanned replacement list and return one. + Otherwise, we don't push a context and return zero. */ static int enter_macro_context (pfile, node) cpp_reader *pfile; cpp_hashnode *node; { - if (node->flags & NODE_BUILTIN) - push_token_context (pfile, NULL, builtin_macro (pfile, node), 1); - else + /* The presence of a macro invalidates a file's controlling macro. */ + pfile->mi_valid = false; + + /* Handle standard macros. */ + if (! (node->flags & NODE_BUILTIN)) { cpp_macro *macro = node->value.macro; - if (macro->fun_like && !funlike_invocation_p (pfile, node)) - return 0; + if (macro->fun_like) + { + _cpp_buff *buff; + + pfile->state.prevent_expansion++; + pfile->keep_tokens++; + pfile->state.parsing_args = 1; + buff = funlike_invocation_p (pfile, node); + pfile->state.parsing_args = 0; + pfile->keep_tokens--; + pfile->state.prevent_expansion--; + + if (buff == NULL) + { + if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr) + cpp_warning (pfile, + "function-like macro \"%s\" must be used with arguments in traditional C", + NODE_NAME (node)); + + return 0; + } + + if (node->value.macro->paramc > 0) + replace_args (pfile, node, (macro_arg *) buff->base); + _cpp_release_buff (pfile, buff); + } /* Disable the macro within its expansion. */ - macro->disabled = 1; + node->flags |= NODE_DISABLED; if (macro->paramc == 0) - push_token_context (pfile, macro, macro->expansion, macro->count); + push_token_context (pfile, node, macro->expansion, macro->count); + + return 1; } - - return 1; + + /* Handle built-in macros and the _Pragma operator. */ + return builtin_macro (pfile, node); } -/* Take the expansion of a function-like MACRO, replacing parameters - with the actual arguments. Each argument is macro-expanded before - replacement, unless operated upon by the # or ## operators. */ +/* Replace the parameters in a function-like macro of NODE with the + actual ARGS, and place the result in a newly pushed token context. + Expand each argument before replacing, unless it is operated upon + by the # or ## operators. */ static void -replace_args (pfile, macro, args) +replace_args (pfile, node, args) cpp_reader *pfile; - cpp_macro *macro; + cpp_hashnode *node; macro_arg *args; { unsigned int i, total; @@ -674,11 +730,13 @@ replace_args (pfile, macro, args) const cpp_token **dest, **first; macro_arg *arg; _cpp_buff *buff; + cpp_macro *macro; /* First, fully macro-expand arguments, calculating the number of tokens in the final expansion as we go. The ordering of the if statements below is subtle; we must handle stringification before pasting. */ + macro = node->value.macro; total = macro->count; limit = macro->expansion + macro->count; @@ -796,7 +854,7 @@ replace_args (pfile, macro, args) if (args[i].expanded) free (args[i].expanded); - push_ptoken_context (pfile, macro, buff, first, dest - first); + push_ptoken_context (pfile, node, buff, first, dest - first); } /* Return a special padding token, with padding inherited from SOURCE. */ @@ -813,7 +871,8 @@ padding_token (pfile, source) return result; } -/* Move to the next context. Create one if there is none. */ +/* Get a new uninitialized context. Create a new one if we cannot + re-use an old one. */ static cpp_context * next_context (pfile) cpp_reader *pfile; @@ -836,7 +895,7 @@ next_context (pfile) static void push_ptoken_context (pfile, macro, buff, first, count) cpp_reader *pfile; - cpp_macro *macro; + cpp_hashnode *macro; _cpp_buff *buff; const cpp_token **first; unsigned int count; @@ -854,7 +913,7 @@ push_ptoken_context (pfile, macro, buff, first, count) static void push_token_context (pfile, macro, first, count) cpp_reader *pfile; - cpp_macro *macro; + cpp_hashnode *macro; const cpp_token *first; unsigned int count; { @@ -867,6 +926,12 @@ push_token_context (pfile, macro, first, count) context->last.token = first + count; } +/* 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 + as if it were a normal part of the token stream. collect_args() + has terminated the argument's tokens with a CPP_EOF so that we know + when we have fully expanded the argument. */ static void expand_arg (pfile, arg) cpp_reader *pfile; @@ -905,15 +970,17 @@ expand_arg (pfile, arg) _cpp_pop_context (pfile); } +/* Pop the current context off the stack, re-enabling the macro if the + context represented a macro's replacement list. The context + structure is not freed so that we can re-use it later. */ void _cpp_pop_context (pfile) cpp_reader *pfile; { cpp_context *context = pfile->context; - /* Re-enable a macro when leaving its expansion. */ if (context->macro) - context->macro->disabled = 0; + context->macro->flags &= ~NODE_DISABLED; if (context->buff) _cpp_release_buff (pfile, context->buff); @@ -974,39 +1041,31 @@ cpp_get_token (pfile) node = result->val.node; - /* Handle macros and the _Pragma operator. */ - if (node->type == NT_MACRO && !(result->flags & NO_EXPAND)) + if (node->type != NT_MACRO || (result->flags & NO_EXPAND)) + break; + + if (!(node->flags & NODE_DISABLED)) { - /* Macros invalidate controlling macros. */ - pfile->mi_valid = false; - - if (!(node->flags & NODE_BUILTIN) && node->value.macro->disabled) - { - /* Flag this token as always unexpandable. */ - cpp_token *t = _cpp_temp_token (pfile); - t->type = result->type; - t->flags = result->flags | NO_EXPAND; - t->val.str = result->val.str; - result = t; - } - else if (!pfile->state.prevent_expansion - && enter_macro_context (pfile, node)) + if (!pfile->state.prevent_expansion + && enter_macro_context (pfile, node)) { if (pfile->state.in_directive) continue; return padding_token (pfile, result); } } + else + { + /* Flag this token as always unexpandable. FIXME: move this + to collect_args()?. */ + cpp_token *t = _cpp_temp_token (pfile); + t->type = result->type; + t->flags = result->flags | NO_EXPAND; + t->val.str = result->val.str; + result = t; + } - /* Don't interpret _Pragma within directives. The standard is - not clear on this, but to me this makes most sense. */ - if (node != pfile->spec_nodes.n__Pragma - || pfile->state.in_directive) - break; - - /* Handle it, and loop back for another token. MI is cleared - since this token came from either the lexer or a macro. */ - _cpp_do__Pragma (pfile); + break; } return result; @@ -1019,9 +1078,9 @@ int cpp_sys_macro_p (pfile) cpp_reader *pfile; { - cpp_macro *macro = pfile->context->macro; + cpp_hashnode *node = pfile->context->macro; - return macro && macro->syshdr; + return node && node->value.macro && node->value.macro->syshdr; } /* Read each token in, until EOF. Directives are transparently @@ -1047,7 +1106,9 @@ _cpp_backup_tokens (pfile, count) while (count--) { pfile->cur_token--; - if (pfile->cur_token == pfile->cur_run->base) + if (pfile->cur_token == pfile->cur_run->base + /* Possible with -fpreprocessed and no leading #line. */ + && pfile->cur_run->prev != NULL) { pfile->cur_run = pfile->cur_run->prev; pfile->cur_token = pfile->cur_run->limit; @@ -1069,8 +1130,7 @@ _cpp_backup_tokens (pfile, count) /* Returns non-zero if a macro redefinition warning is required. */ static int -warn_of_redefinition (pfile, node, macro2) - cpp_reader *pfile; +warn_of_redefinition (node, macro2) const cpp_hashnode *node; const cpp_macro *macro2; { @@ -1081,9 +1141,6 @@ warn_of_redefinition (pfile, node, macro2) if (node->flags & NODE_WARN) return 1; - if (! CPP_PEDANTIC (pfile)) - return 0; - /* Redefinition of a macro is allowed if and only if the old and new definitions are the same. (6.10.3 paragraph 2). */ macro1 = node->value.macro; @@ -1109,7 +1166,6 @@ warn_of_redefinition (pfile, node, macro2) } /* Free the definition of hashnode H. */ - void _cpp_free_definition (h) cpp_hashnode *h; @@ -1117,19 +1173,17 @@ _cpp_free_definition (h) /* Macros and assertions no longer have anything to free. */ h->type = NT_VOID; /* Clear builtin flag in case of redefinition. */ - h->flags &= ~NODE_BUILTIN; + h->flags &= ~(NODE_BUILTIN | NODE_DISABLED); } /* Save parameter NODE to the parameter list of macro MACRO. Returns - zero on success, non-zero if the paramter is a duplicate. */ + zero on success, non-zero if the parameter is a duplicate. */ static int save_parameter (pfile, macro, node) cpp_reader *pfile; cpp_macro *macro; cpp_hashnode *node; { - cpp_hashnode **dest; - /* Constraint 6.10.3.6 - duplicate parameter names. */ if (node->arg_index) { @@ -1137,22 +1191,16 @@ save_parameter (pfile, macro, node) return 1; } - dest = ¯o->params[macro->paramc]; - - /* Check we have room for the parameters. */ - if ((unsigned char *) (dest + 1) >= POOL_LIMIT (&pfile->macro_pool)) - { - _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_hashnode *), - (unsigned char **) ¯o->params); - dest = ¯o->params[macro->paramc]; - } + if (BUFF_ROOM (pfile->a_buff) + < (macro->paramc + 1) * sizeof (cpp_hashnode *)) + _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); - *dest = node; - node->arg_index = ++macro->paramc; + ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node; + node->arg_index = macro->paramc; return 0; } -/* Check the syntax of the paramters in a MACRO definition. */ +/* Check the syntax of the parameters in a MACRO definition. */ static int parse_params (pfile, macro) cpp_reader *pfile; @@ -1160,7 +1208,6 @@ parse_params (pfile, macro) { unsigned int prev_ident = 0; - macro->params = (cpp_hashnode **) POOL_FRONT (&pfile->macro_pool); for (;;) { const cpp_token *token = _cpp_lex_token (pfile); @@ -1186,7 +1233,7 @@ parse_params (pfile, macro) case CPP_CLOSE_PAREN: if (prev_ident || macro->paramc == 0) - break; + return 1; /* Fall through to pick up the error. */ case CPP_COMMA: @@ -1214,18 +1261,13 @@ parse_params (pfile, macro) /* We're at the end, and just expect a closing parenthesis. */ token = _cpp_lex_token (pfile); if (token->type == CPP_CLOSE_PAREN) - break; + return 1; /* Fall through. */ case CPP_EOF: cpp_error (pfile, "missing ')' in macro parameter list"); return 0; } - - /* Success. Commit the parameter array. */ - POOL_COMMIT (&pfile->macro_pool, - macro->paramc * sizeof (cpp_hashnode *)); - return 1; } } @@ -1235,20 +1277,14 @@ alloc_expansion_token (pfile, macro) cpp_reader *pfile; cpp_macro *macro; { - cpp_token *token = ¯o->expansion[macro->count]; - - /* Check we have room for the token. */ - if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->macro_pool)) - { - _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_token), - (unsigned char **) ¯o->expansion); - token = ¯o->expansion[macro->count]; - } + if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token)) + _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_token)); - macro->count++; - return token; + return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++]; } +/* Lex a token from the expansion of MACRO, but mark parameters as we + find them and warn of traditional stringification. */ static cpp_token * lex_expansion_token (pfile, macro) cpp_reader *pfile; @@ -1259,7 +1295,7 @@ lex_expansion_token (pfile, macro) pfile->cur_token = alloc_expansion_token (pfile, macro); token = _cpp_lex_direct (pfile); - /* Is this an argument? */ + /* Is this a parameter? */ if (token->type == CPP_NAME && token->val.node->arg_index) { token->type = CPP_MACRO_ARG; @@ -1283,8 +1319,7 @@ _cpp_create_definition (pfile, node) const cpp_token *ctoken; unsigned int i, ok = 1; - macro = (cpp_macro *) _cpp_pool_alloc (&pfile->macro_pool, - sizeof (cpp_macro)); + macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); macro->line = pfile->directive_line; macro->params = 0; macro->paramc = 0; @@ -1298,16 +1333,19 @@ _cpp_create_definition (pfile, node) if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) { - if (!(ok = parse_params (pfile, macro))) + ok = parse_params (pfile, macro); + macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); + if (!ok) goto cleanup2; + + /* Success. Commit the parameter array. */ + BUFF_FRONT (pfile->a_buff) = (U_CHAR *) ¯o->params[macro->paramc]; macro->fun_like = 1; } else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE)) cpp_pedwarn (pfile, "ISO C requires whitespace after the macro name"); - pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); saved_cur_token = pfile->cur_token; - macro->expansion = (cpp_token *) POOL_FRONT (&pfile->macro_pool); if (macro->fun_like) token = lex_expansion_token (pfile, macro); @@ -1365,23 +1403,30 @@ _cpp_create_definition (pfile, node) token = lex_expansion_token (pfile, macro); } + macro->expansion = (cpp_token *) BUFF_FRONT (pfile->a_buff); + /* Don't count the CPP_EOF. */ macro->count--; + /* Clear whitespace on first token for warn_of_redefinition(). */ + if (macro->count) + macro->expansion[0].flags &= ~PREV_WHITE; + + /* Commit the memory. */ + BUFF_FRONT (pfile->a_buff) = (U_CHAR *) ¯o->expansion[macro->count]; + /* Implement the macro-defined-to-itself optimisation. */ - macro->disabled = (macro->count == 1 && !macro->fun_like - && macro->expansion[0].type == CPP_NAME - && macro->expansion[0].val.node == node); + if (macro->count == 1 && !macro->fun_like + && macro->expansion[0].type == CPP_NAME + && macro->expansion[0].val.node == node) + node->flags |= NODE_DISABLED; /* To suppress some diagnostics. */ macro->syshdr = pfile->map->sysp != 0; - /* Commit the memory. */ - POOL_COMMIT (&pfile->macro_pool, macro->count * sizeof (cpp_token)); - if (node->type != NT_VOID) { - if (warn_of_redefinition (pfile, node, macro)) + if (warn_of_redefinition (node, macro)) { cpp_pedwarn_with_line (pfile, pfile->directive_line, 0, "\"%s\" redefined", NODE_NAME (node)); @@ -1417,9 +1462,8 @@ _cpp_create_definition (pfile, node) return ok; } -/* Warn if a token in `string' matches one of the function macro - arguments in `info'. This function assumes that the macro is a - function macro and not an object macro. */ +/* Warn if a token in STRING matches one of a function-like MACRO's + parameters. */ static void check_trad_stringification (pfile, macro, string) cpp_reader *pfile; @@ -1453,7 +1497,7 @@ check_trad_stringification (pfile, macro, string) && !memcmp (p, NODE_NAME (node), len)) { cpp_warning (pfile, - "macro argument \"%s\" would be stringified with -traditional.", + "macro argument \"%s\" would be stringified with -traditional", NODE_NAME (node)); break; } @@ -1466,7 +1510,6 @@ check_trad_stringification (pfile, macro, string) debugging info. e.g. "PASTE(X, Y) X ## Y", or "MACNAME EXPANSION". Caller is expected to generate the "#define" bit if needed. The returned text is temporary, and automatically freed later. */ - const unsigned char * cpp_macro_definition (pfile, node) cpp_reader *pfile;