X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;ds=sidebyside;f=gcc%2Fcppmacro.c;h=b8fb792de885aed425d90d987b3a426f7202def9;hb=d10cfa8dc0e0c46fb4ebdcbb957029727bc8fe21;hp=e5260694c420b305dbe74d00fee3aa05943519f7;hpb=10b4496ae30845cc3fd784538f35424af952ee8b;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index e5260694c42..b8fb792de88 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,103 +25,94 @@ 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. */ - 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. */ -}; - typedef struct macro_arg macro_arg; struct macro_arg { - cpp_token *first; /* First token in unexpanded argument. */ - cpp_token *expanded; /* Macro-expanded argument. */ - cpp_token *stringified; /* Stringified argument. */ + const cpp_token **first; /* First token in unexpanded 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. */ }; /* Macro expansion. */ -static void lock_pools PARAMS ((cpp_reader *)); -static void unlock_pools PARAMS ((cpp_reader *)); static int enter_macro_context PARAMS ((cpp_reader *, cpp_hashnode *)); -static void builtin_macro PARAMS ((cpp_reader *, cpp_token *)); -static cpp_context *push_arg_context PARAMS ((cpp_reader *, macro_arg *)); -static enum cpp_ttype parse_arg PARAMS ((cpp_reader *, macro_arg *, int)); -static macro_arg *parse_args PARAMS ((cpp_reader *, const cpp_hashnode *)); +static int builtin_macro PARAMS ((cpp_reader *, cpp_hashnode *)); +static void push_token_context + PARAMS ((cpp_reader *, cpp_hashnode *, const cpp_token *, unsigned int)); +static void push_ptoken_context + 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 *)); +static const cpp_token *padding_token + PARAMS ((cpp_reader *, const cpp_token *)); static void expand_arg PARAMS ((cpp_reader *, macro_arg *)); -static unsigned char *quote_string PARAMS ((unsigned char *, - const unsigned char *, - unsigned int)); -static void make_string_token PARAMS ((cpp_pool *, cpp_token *, - const U_CHAR *, unsigned int)); -static void make_number_token PARAMS ((cpp_reader *, cpp_token *, int)); -static void stringify_arg PARAMS ((cpp_reader *, macro_arg *)); -static void paste_all_tokens PARAMS ((cpp_reader *, cpp_token *)); -static int paste_tokens PARAMS ((cpp_reader *, cpp_token *, cpp_token *)); -static int funlike_invocation_p PARAMS ((cpp_reader *, const cpp_hashnode *, - struct toklist *)); -static void replace_args PARAMS ((cpp_reader *, cpp_macro *, macro_arg *, - struct toklist *)); +static const cpp_token *new_string_token PARAMS ((cpp_reader *, uchar *, + 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 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 ((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 bool warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *, + const cpp_macro *)); +static bool parse_params PARAMS ((cpp_reader *, cpp_macro *)); static void check_trad_stringification PARAMS ((cpp_reader *, const cpp_macro *, const cpp_string *)); -/* Allocates a buffer to hold a token's TEXT, and converts TOKEN to a - CPP_STRING token containing TEXT in quoted form. */ -static void -make_string_token (pool, token, text, len) - cpp_pool *pool; - cpp_token *token; - const U_CHAR *text; - unsigned int len; +/* Emits a warning if NODE is a macro defined in the main file that + has not been used. */ +int +_cpp_warn_if_unused_macro (pfile, node, v) + cpp_reader *pfile; + cpp_hashnode *node; + void *v ATTRIBUTE_UNUSED; { - U_CHAR *buf = _cpp_pool_alloc (pool, len * 4 + 1); + if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + { + cpp_macro *macro = node->value.macro; + + if (!macro->used + /* Skip front-end built-ins and command line macros. */ + && macro->line >= pfile->first_unused_line + && MAIN_FILE_P (lookup_line (&pfile->line_maps, macro->line))) + cpp_error_with_line (pfile, DL_WARNING, macro->line, 0, + "macro \"%s\" is not used", NODE_NAME (node)); + } - token->type = CPP_STRING; - token->val.str.text = buf; - token->val.str.len = quote_string (buf, text, len) - buf; - buf[token->val.str.len] = '\0'; - token->flags = 0; + return 1; } -/* Allocates and converts a temporary token to a CPP_NUMBER token, - evaluating to NUMBER. */ -static void -make_number_token (pfile, token, number) +/* Allocates and returns a CPP_STRING token, containing TEXT of length + LEN, after null-terminating it. TEXT must be in permanent storage. */ +static const cpp_token * +new_string_token (pfile, text, len) cpp_reader *pfile; - cpp_token *token; - int number; + unsigned char *text; + unsigned int len; { - unsigned char *buf = _cpp_pool_alloc (&pfile->ident_pool, 20); + cpp_token *token = _cpp_temp_token (pfile); - sprintf ((char *) buf, "%d", number); - token->type = CPP_NUMBER; - token->val.str.text = buf; - token->val.str.len = ustrlen (buf); + text[len] = '\0'; + token->type = CPP_STRING; + token->val.str.len = len; + token->val.str.text = text; token->flags = 0; + return token; } static const char * const monthnames[] = @@ -130,21 +121,31 @@ static const char * const monthnames[] = "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -/* Handle builtin macros like __FILE__. */ -static void -builtin_macro (pfile, 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. */ +const uchar * +_cpp_builtin_macro_text (pfile, node) cpp_reader *pfile; - cpp_token *token; + cpp_hashnode *node; { - unsigned char flags = ((token->flags & (PREV_WHITE | BOL)) | AVOID_LPASTE); - cpp_hashnode *node = token->val.node; + const uchar *result = NULL; + unsigned int number = 1; switch (node->value.builtin) { + default: + cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"", + NODE_NAME (node)); + break; + case BT_FILE: case BT_BASE_FILE: { + unsigned int len; const char *name; + uchar *buf; const struct line_map *map = pfile->map; if (node->value.builtin == BT_BASE_FILE) @@ -152,91 +153,164 @@ builtin_macro (pfile, token) map = INCLUDED_FROM (&pfile->line_maps, map); name = map->to_file; - make_string_token (&pfile->ident_pool, token, - (const unsigned char *) name, strlen (name)); + len = strlen (name); + buf = _cpp_unaligned_alloc (pfile, len * 4 + 3); + result = buf; + *buf = '"'; + buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len); + *buf++ = '"'; + *buf = '\0'; } 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. */ - make_number_token (pfile, token, pfile->line_maps.depth - 1); + number = 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. */ - make_number_token (pfile, token, - SOURCE_LINE (pfile->map, pfile->cur_token[-1].line)); + if (CPP_OPTION (pfile, traditional)) + number = pfile->line; + else + number = pfile->cur_token[-1].line; + number = SOURCE_LINE (pfile->map, number); break; + /* __STDC__ has the value 1 under normal circumstances. + However, if (a) we are in a system header, (b) the option + stdc_0_in_system_headers is true (set by target config), and + (c) we are not in strictly conforming mode, then it has the + value 0. */ case BT_STDC: { - int stdc = (!CPP_IN_SYSTEM_HEADER (pfile) - || pfile->spec_nodes.n__STRICT_ANSI__->type != NT_VOID); - make_number_token (pfile, token, stdc); + if (CPP_IN_SYSTEM_HEADER (pfile) + && CPP_OPTION (pfile, stdc_0_in_system_headers) + && !CPP_OPTION (pfile,std)) + number = 0; + else + number = 1; } break; case BT_DATE: case BT_TIME: - if (pfile->date.type == CPP_EOF) + if (pfile->date == NULL) { - /* Allocate __DATE__ and __TIME__ from permanent storage, - and save them in pfile so we don't have to do this again. - We don't generate these strings at init time because - time() and localtime() are very slow on some systems. */ - time_t tt = time (NULL); - struct tm *tb = localtime (&tt); - - make_string_token (&pfile->ident_pool, &pfile->date, - DSC("Oct 11 1347")); - make_string_token (&pfile->ident_pool, &pfile->time, - DSC("12:34:56")); - - sprintf ((char *) pfile->date.val.str.text, "%s %2d %4d", - monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900); - sprintf ((char *) pfile->time.val.str.text, "%02d:%02d:%02d", - tb->tm_hour, tb->tm_min, tb->tm_sec); + /* Allocate __DATE__ and __TIME__ strings from permanent + storage. We only do this once, and don't generate them + at init time, because time() and localtime() are very + slow on some systems. */ + time_t tt; + struct tm *tb = NULL; + + /* (time_t) -1 is a legitimate value for "number of seconds + since the Epoch", so we have to do a little dance to + distinguish that from a genuine error. */ + errno = 0; + tt = time(NULL); + if (tt != (time_t)-1 || errno == 0) + tb = localtime (&tt); + + if (tb) + { + pfile->date = _cpp_unaligned_alloc (pfile, + sizeof ("\"Oct 11 1347\"")); + sprintf ((char *) pfile->date, "\"%s %2d %4d\"", + monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900); + + pfile->time = _cpp_unaligned_alloc (pfile, + sizeof ("\"12:34:56\"")); + sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"", + tb->tm_hour, tb->tm_min, tb->tm_sec); + } + else + { + cpp_errno (pfile, DL_WARNING, + "could not determine date and time"); + + pfile->date = U"\"??? ?? ????\""; + pfile->time = U"\"??:??:??\""; + } } - *token = node->value.builtin == BT_DATE ? pfile->date: pfile->time; - break; - default: - cpp_ice (pfile, "invalid builtin macro \"%s\"", NODE_NAME (node)); + if (node->value.builtin == BT_DATE) + result = pfile->date; + else + result = pfile->time; break; } - token->flags = flags; -} + if (result == NULL) + { + /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */ + result = _cpp_unaligned_alloc (pfile, 21); + sprintf ((char *) result, "%u", number); + } -static void -lock_pools (pfile) - cpp_reader *pfile; -{ - _cpp_lock_pool (&pfile->argument_pool); + return result; } -static void -unlock_pools (pfile) +/* Convert builtin macros like __FILE__ to a token and push it 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; { - _cpp_unlock_pool (&pfile->argument_pool); + const uchar *buf; + + if (node->value.builtin == 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; + } + + buf = _cpp_builtin_macro_text (pfile, node); + + cpp_push_buffer (pfile, buf, ustrlen (buf), /* from_stage3 */ true, 1); + + /* Tweak the column number the lexer will report. */ + pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1; + + /* We don't want a leading # to be interpreted as a directive. */ + pfile->buffer->saved_flags = 0; + + /* Set pfile->cur_token as required by _cpp_lex_direct. */ + pfile->cur_token = _cpp_temp_token (pfile); + push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1); + if (pfile->buffer->cur != pfile->buffer->rlimit) + cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"", + NODE_NAME (node)); + _cpp_pop_buffer (pfile); + + return 1; } -/* Adds backslashes before all backslashes and double quotes appearing - in strings. Non-printable characters are converted to octal. */ -static U_CHAR * -quote_string (dest, src, len) - U_CHAR *dest; - const U_CHAR *src; +/* 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. Returns + a pointer to the end of the string. */ +uchar * +cpp_quote_string (dest, src, len) + uchar *dest; + const uchar *src; unsigned int len; { while (len--) { - U_CHAR c = *src++; + uchar c = *src++; if (c == '\\' || c == '"') { @@ -258,54 +332,67 @@ 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. */ -static void +/* 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 = cpp_token_len (token); + const cpp_token *token = arg->first[i]; + + if (token->type == CPP_PADDING) + { + if (source == NULL) + source = token->val.source; + continue; + } 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; } - /* No leading white space. */ - if (token->flags & PREV_WHITE && total_len > 0) - *dest++ = ' '; + /* Leading white space? */ + if (dest != BUFF_FRONT (pfile->u_buff)) + { + if (source == NULL) + source = token; + if (source->flags & PREV_WHITE) + *dest++ = ' '; + } + source = NULL; 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); + dest = cpp_quote_string (dest, buf, len); + _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++; @@ -316,110 +403,76 @@ stringify_arg (pfile, arg) /* Ignore the final \ of invalid string literals. */ if (backslash_count & 1) { - cpp_warning (pfile, "invalid string literal, ignoring final '\\'"); - total_len--; + cpp_error (pfile, DL_WARNING, + "invalid string literal, ignoring final '\\'"); + dest--; } - /* Null terminate, and commit the memory. */ - start[total_len] = '\0'; - POOL_COMMIT (pool, total_len + 1); - - arg->stringified = xnew (cpp_token); - arg->stringified->flags = 0; - arg->stringified->type = CPP_STRING; - arg->stringified->val.str.text = start; - arg->stringified->val.str.len = total_len; + /* Commit the memory, including NUL, and return the token. */ + 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, the LHS becomes the pasted - token, and 0 is returned. For failure, we update the flags of the - RHS appropriately and return non-zero. */ -static int -paste_tokens (pfile, lhs, rhs) +/* Try to paste two tokens. On success, return nonzero. In any + case, PLHS is updated to point to the pasted token, which is + guaranteed to not have the PASTE_LEFT flag set. */ +static bool +paste_tokens (pfile, plhs, rhs) cpp_reader *pfile; - cpp_token *lhs, *rhs; + const cpp_token **plhs, *rhs; { - unsigned char flags; - int digraph = 0; - enum cpp_ttype type; - - type = cpp_can_paste (pfile, lhs, rhs, &digraph); - - if (type == CPP_EOF) - { - /* Mandatory warning for all apart from assembler. */ - if (CPP_OPTION (pfile, lang) != CLK_ASM) - cpp_warning (pfile, - "pasting \"%s\" and \"%s\" does not give a valid preprocessing token", - cpp_token_as_text (pfile, lhs), - cpp_token_as_text (pfile, rhs)); - - /* The standard states that behaviour is undefined. By the - principle of least surpise, we step back before the RHS, and - mark it to prevent macro expansion. Tests in the testsuite - rely on clearing PREV_WHITE here, though you could argue we - should actually set it. Assembler can have '.' in labels and - so requires that we don't insert spaces there. Maybe we should - change this to put out a space unless it's assembler. */ - rhs->flags &= ~PREV_WHITE; - rhs->flags |= NO_EXPAND; - return 1; - } - - flags = lhs->flags & ~DIGRAPH; - if (digraph) - flags |= DIGRAPH; - - /* Identifiers and numbers need spellings to be pasted. */ - if (type == CPP_NAME || type == CPP_NUMBER) - { - unsigned int total_len = cpp_token_len (lhs) + cpp_token_len (rhs); - unsigned char *result, *end; - - result = _cpp_pool_alloc (&pfile->ident_pool, total_len + 1); - - /* Paste the spellings and null terminate. */ - end = cpp_spell_token (pfile, rhs, cpp_spell_token (pfile, lhs, result)); - *end = '\0'; - total_len = end - result; - - if (type == CPP_NAME) - { - lhs->val.node = cpp_lookup (pfile, result, total_len); - if (lhs->val.node->flags & NODE_OPERATOR) - { - flags |= NAMED_OP; - lhs->type = lhs->val.node->value.operator; - } - } - else - { - lhs->val.str.text = result; - lhs->val.str.len = total_len; - } - } - else if (type == CPP_WCHAR || type == CPP_WSTRING) - lhs->val.str = rhs->val.str; - - /* Set type and flags after pasting spellings. */ - lhs->type = type; - lhs->flags = flags; - - return 0; + unsigned char *buf, *end; + const cpp_token *lhs; + unsigned int len; + bool valid; + + lhs = *plhs; + len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1; + buf = (unsigned char *) alloca (len); + end = cpp_spell_token (pfile, lhs, buf); + + /* Avoid comment headers, since they are still processed in stage 3. + It is simpler to insert a space here, rather than modifying the + lexer to ignore comments in some circumstances. Simply returning + false doesn't work, since we want to clear the PASTE_LEFT flag. */ + if (lhs->type == CPP_DIV + && (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); + + /* Tweak the column number the lexer will report. */ + pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1; + + /* We don't want a leading # to be interpreted as a directive. */ + pfile->buffer->saved_flags = 0; + + /* 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; + _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; - cpp_token *lhs; + const cpp_token *lhs; { - cpp_token *rhs; - unsigned char orig_flags = lhs->flags; + const cpp_token *rhs; + cpp_context *context = pfile->context; do { @@ -428,300 +481,349 @@ paste_all_tokens (pfile, lhs) object-like macro, or a function-like macro with arguments inserted. In either case, the constraints to #define guarantee we have at least one more token. */ - rhs = pfile->context->list.first++; - if (paste_tokens (pfile, lhs, rhs)) + if (context->direct_p) + rhs = FIRST (context).token++; + else + rhs = *FIRST (context).ptoken++; + + if (rhs->type == CPP_PADDING) + abort (); + + if (!paste_tokens (pfile, &lhs, rhs)) { - /* We failed. Step back so we read the RHS in next. */ - pfile->context->list.first--; + _cpp_backup_tokens (pfile, 1); + + /* Mandatory error for all apart from assembler. */ + if (CPP_OPTION (pfile, lang) != CLK_ASM) + cpp_error (pfile, DL_ERROR, + "pasting \"%s\" and \"%s\" does not give a valid preprocessing token", + cpp_token_as_text (pfile, lhs), + cpp_token_as_text (pfile, rhs)); break; } } while (rhs->flags & PASTE_LEFT); - /* The pasted token has the PREV_WHITE flag of the LHS, is no longer - PASTE_LEFT, and is subject to macro expansion. */ - lhs->flags &= ~(PREV_WHITE | BOL | PASTE_LEFT | NO_EXPAND); - lhs->flags |= orig_flags & (PREV_WHITE | BOL | AVOID_LPASTE); + /* Put the resulting token in its own context. */ + push_token_context (pfile, NULL, lhs, 1); } -/* Reads the unexpanded tokens of a macro argument into ARG. VAR_ARGS - is non-zero if this is a variadic macro. Returns the type of the - token that caused reading to finish. */ -static enum cpp_ttype -parse_arg (pfile, arg, variadic) +/* Returns TRUE if the number of arguments ARGC supplied in an + invocation of the MACRO referenced by NODE is valid. An empty + invocation to a macro with no parameters should pass ARGC as zero. + + Note that MACRO cannot necessarily be deduced from NODE, in case + NODE was redefined whilst collecting arguments. */ +bool +_cpp_arguments_ok (pfile, macro, node, argc) cpp_reader *pfile; - struct macro_arg *arg; - int variadic; + cpp_macro *macro; + const cpp_hashnode *node; + unsigned int argc; { - enum cpp_ttype result; - unsigned int paren = 0; - unsigned int line; + if (argc == macro->paramc) + return true; - arg->first = (cpp_token *) POOL_FRONT (&pfile->argument_pool); - for (;; arg->count++) + if (argc < macro->paramc) { - cpp_token *token = &arg->first[arg->count]; - if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->argument_pool)) - { - _cpp_next_chunk (&pfile->argument_pool, sizeof (cpp_token), - (unsigned char **) &arg->first); - token = &arg->first[arg->count]; - } - - /* Newlines in arguments are white space (6.10.3.10). */ - line = pfile->line; - cpp_get_token (pfile, token); - - if (line != pfile->line) - token->flags |= PREV_WHITE; + /* As an extension, a rest argument is allowed to not appear in + the invocation at all. + e.g. #define debug(format, args...) something + debug("string"); - result = token->type; + This is exactly the same as if there had been an empty rest + argument - debug("string", ). */ - if (result == CPP_OPEN_PAREN) - paren++; - else if (result == CPP_CLOSE_PAREN && paren-- == 0) - break; - /* Commas are not terminators within parantheses or variadic. */ - else if (result == CPP_COMMA && paren == 0 && !variadic) - break; - else if (result == CPP_EOF) - { - /* We still need the EOF (added below) to end pre-expansion - and directives. */ - if (pfile->context->prev || pfile->state.in_directive) - _cpp_backup_tokens (pfile, 1); - /* Error reported by caller. */ - break; - } - else if (result == CPP_HASH && token->flags & BOL) + if (argc + 1 == macro->paramc && macro->variadic) { - /* 6.10.3 paragraph 11: If there are sequences of - preprocessing tokens within the list of arguments that - would otherwise act as preprocessing directives, the - behavior is undefined. - - This implementation will report a hard error, terminate - the macro invocation, and proceed to process the - directive. */ - cpp_error (pfile, - "directives may not be used inside a macro argument"); - _cpp_backup_tokens (pfile, 1); - result = CPP_EOF; - break; + if (CPP_PEDANTIC (pfile) && ! macro->syshdr) + cpp_error (pfile, DL_PEDWARN, + "ISO C99 requires rest arguments to be used"); + return true; } - } - /* Commit the memory used to store the arguments. We make the last - argument a CPP_EOF, so that it terminates macro pre-expansion, - but it is not included in arg->count. */ - arg->first[arg->count].type = CPP_EOF; - POOL_COMMIT (&pfile->argument_pool, (arg->count + 1) * sizeof (cpp_token)); + cpp_error (pfile, DL_ERROR, + "macro \"%s\" requires %u arguments, but only %u given", + NODE_NAME (node), macro->paramc, argc); + } + else + cpp_error (pfile, DL_ERROR, + "macro \"%s\" passed %u arguments, but takes just %u", + NODE_NAME (node), argc, macro->paramc); - return result; + return false; } -/* Parse the arguments making up a macro invocation. */ -static macro_arg * -parse_args (pfile, node) +/* 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; const cpp_hashnode *node; { - cpp_macro *macro = node->value.macro; - macro_arg *args, *cur; - enum cpp_ttype type; - int argc, error = 0; - - /* Allocate room for at least one argument, and zero it out. */ - argc = macro->paramc ? macro->paramc: 1; - args = xcnewvec (macro_arg, argc); + _cpp_buff *buff, *base_buff; + cpp_macro *macro; + macro_arg *args, *arg; + const cpp_token *token; + unsigned int argc; - for (cur = args, argc = 0; ;) + macro = node->value.macro; + if (macro->paramc) + argc = macro->paramc; + else + argc = 1; + buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *) + + sizeof (macro_arg))); + base_buff = buff; + args = (macro_arg *) buff->base; + memset (args, 0, argc * sizeof (macro_arg)); + buff->cur = (unsigned char *) &args[argc]; + arg = args, argc = 0; + + /* Collect the tokens making up each argument. We don't yet know + how many arguments have been supplied, whether too many or too + few. Hence the slightly bizarre usage of "argc" and "arg". */ + do { + unsigned int paren_depth = 0; + unsigned int ntokens = 0; + argc++; + arg->first = (const cpp_token **) buff->cur; - type = parse_arg (pfile, cur, argc == macro->paramc && macro->variadic); - if (type == CPP_CLOSE_PAREN || type == CPP_EOF) - break; + for (;;) + { + /* Require space for 2 new tokens (including a CPP_EOF). */ + if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit) + { + buff = _cpp_append_extend_buff (pfile, buff, + 1000 * sizeof (cpp_token *)); + arg->first = (const cpp_token **) buff->cur; + } - /* Re-use the last argument for excess arguments. */ - if (argc < macro->paramc) - cur++; - } + token = cpp_get_token (pfile); - if (type == CPP_EOF) - { - cpp_error (pfile, "unterminated argument list invoking macro \"%s\"", - NODE_NAME (node)); - error = 1; - } - else if (argc < macro->paramc) - { - /* As an extension, a rest argument is allowed to not appear in - the invocation at all. - e.g. #define debug(format, args...) something - debug("string"); - - This is exactly the same as if there had been an empty rest - argument - debug("string", ). */ + if (token->type == CPP_PADDING) + { + /* Drop leading padding. */ + if (ntokens == 0) + continue; + } + else if (token->type == CPP_OPEN_PAREN) + paren_depth++; + else if (token->type == CPP_CLOSE_PAREN) + { + if (paren_depth-- == 0) + break; + } + else if (token->type == CPP_COMMA) + { + /* A comma does not terminate an argument within + parentheses or as part of a variable argument. */ + if (paren_depth == 0 + && ! (macro->variadic && argc == macro->paramc)) + break; + } + else if (token->type == CPP_EOF + || (token->type == CPP_HASH && token->flags & BOL)) + break; - if (argc + 1 == macro->paramc && macro->variadic) - { - if (CPP_PEDANTIC (pfile) && ! macro->syshdr) - cpp_pedwarn (pfile, "ISO C99 requires rest arguments to be used"); + arg->first[ntokens++] = token; } - else + + /* Drop trailing padding. */ + while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING) + ntokens--; + + arg->count = ntokens; + arg->first[ntokens] = &pfile->eof; + + /* Terminate the argument. Excess arguments loop back and + overwrite the final legitimate argument, before failing. */ + if (argc <= macro->paramc) { - cpp_error (pfile, - "macro \"%s\" requires %u arguments, but only %u given", - NODE_NAME (node), macro->paramc, argc); - error = 1; + buff->cur = (unsigned char *) &arg->first[ntokens + 1]; + if (argc != macro->paramc) + arg++; } } - else if (argc > macro->paramc) + while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF); + + if (token->type == CPP_EOF) { - /* Empty argument to a macro taking no arguments is OK. */ - if (argc != 1 || cur->count) - { - cpp_error (pfile, - "macro \"%s\" passed %u arguments, but takes just %u", - NODE_NAME (node), argc, macro->paramc); - error = 1; - } + /* 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 (pfile->context->prev || pfile->state.in_directive) + _cpp_backup_tokens (pfile, 1); + cpp_error (pfile, DL_ERROR, + "unterminated argument list invoking macro \"%s\"", + NODE_NAME (node)); } - - if (error) + else { - free (args); - args = 0; + /* A single empty argument is counted as no argument. */ + if (argc == 1 && macro->paramc == 0 && args[0].count == 0) + argc = 0; + if (_cpp_arguments_ok (pfile, macro, node, argc)) + { + /* GCC has special semantics for , ## b where b is a varargs + parameter: we remove the comma if b was omitted entirely. + If b was merely an empty argument, the comma is retained. + If the macro takes just one (varargs) parameter, then we + retain the comma only if we are standards conforming. + + If FIRST is NULL replace_args () swallows the comma. */ + if (macro->variadic && (argc < macro->paramc + || (argc == 1 && args[0].count == 0 + && !CPP_OPTION (pfile, std)))) + args[macro->paramc - 1].first = NULL; + return base_buff; + } } - return args; + /* An error occurred. */ + _cpp_release_buff (pfile, base_buff); + return NULL; } -static int -funlike_invocation_p (pfile, node, list) +/* 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; - struct toklist *list; + cpp_hashnode *node; { - cpp_token maybe_paren; - macro_arg *args = 0; + const cpp_token *token, *padding = NULL; - pfile->state.parsing_args = 1; - pfile->state.prevent_expansion++; - - pfile->keep_tokens++; - cpp_get_token (pfile, &maybe_paren); - pfile->state.parsing_args = 2; - - if (maybe_paren.type == CPP_OPEN_PAREN) - args = parse_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.prevent_expansion--; - pfile->state.parsing_args = 0; - pfile->keep_tokens--; + if (token->type == CPP_OPEN_PAREN) + { + pfile->state.parsing_args = 2; + return collect_args (pfile, node); + } - if (args) + /* CPP_EOF can be the end of macro arguments, or the end of the + file. We mustn't back up over the latter. Ugh. */ + if (token->type != CPP_EOF || token == &pfile->eof) { - if (node->value.macro->paramc > 0) - replace_args (pfile, node->value.macro, args, list); - free (args); + /* 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 args != 0; + 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; { - cpp_context *context; - cpp_macro *macro = node->value.macro; - struct toklist list; + /* The presence of a macro invalidates a file's controlling macro. */ + pfile->mi_valid = false; - /* Save the position of the outermost macro invocation. */ - if (!pfile->context->prev) - lock_pools (pfile); + pfile->state.angled_headers = false; - if (macro->fun_like && !funlike_invocation_p (pfile, node, &list)) + /* Handle standard macros. */ + if (! (node->flags & NODE_BUILTIN)) { - if (!pfile->context->prev) - unlock_pools (pfile); - return 0; - } + cpp_macro *macro = node->value.macro; - if (macro->paramc == 0) - { - list.first = macro->expansion; - list.limit = macro->expansion + macro->count; - } + if (macro->fun_like) + { + _cpp_buff *buff; - context = next_context (pfile); - context->list = list; - context->macro = macro; - - /* Disable the macro within its expansion. */ - macro->disabled = 1; + 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--; - return 1; -} + if (buff == NULL) + { + if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr) + cpp_error (pfile, DL_WARNING, + "function-like macro \"%s\" must be used with arguments in traditional C", + NODE_NAME (node)); -/* Move to the next context. Create one if there is none. */ -static cpp_context * -next_context (pfile) - cpp_reader *pfile; -{ - cpp_context *prev = pfile->context; - cpp_context *result = prev->next; + return 0; + } - if (result == 0) - { - result = xnew (cpp_context); - prev->next = result; - result->prev = prev; - result->next = 0; + if (macro->paramc > 0) + replace_args (pfile, node, macro, (macro_arg *) buff->base); + _cpp_release_buff (pfile, buff); + } + + /* Disable the macro within its expansion. */ + node->flags |= NODE_DISABLED; + + macro->used = 1; + + if (macro->paramc == 0) + push_token_context (pfile, node, macro->exp.tokens, macro->count); + + return 1; } - pfile->context = result; - return result; + /* Handle built-in macros and the _Pragma operator. */ + return builtin_macro (pfile, node); } +/* 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, list) +replace_args (pfile, node, macro, args) cpp_reader *pfile; + cpp_hashnode *node; cpp_macro *macro; macro_arg *args; - struct toklist *list; { - unsigned char flags = 0; unsigned int i, total; const cpp_token *src, *limit; - cpp_token *dest; + const cpp_token **dest, **first; macro_arg *arg; - - src = macro->expansion; - limit = src + macro->count; + _cpp_buff *buff; /* First, fully macro-expand arguments, calculating the number of - tokens in the final expansion as we go. This ensures that the - possible recursive use of argument_pool is fine. */ - total = limit - src; - for (; src < limit; src++) + tokens in the final expansion as we go. The ordering of the if + statements below is subtle; we must handle stringification before + pasting. */ + total = macro->count; + limit = macro->exp.tokens + macro->count; + + for (src = macro->exp.tokens; src < limit; src++) if (src->type == CPP_MACRO_ARG) { + /* Leading and trailing padding tokens. */ + total += 2; + /* We have an argument. If it is not being stringified or pasted it is macro-replaced before insertion. */ arg = &args[src->val.arg_no - 1]; @@ -729,166 +831,262 @@ replace_args (pfile, macro, args, list) if (src->flags & STRINGIFY_ARG) { if (!arg->stringified) - stringify_arg (pfile, arg); + arg->stringified = stringify_arg (pfile, arg); } else if ((src->flags & PASTE_LEFT) - || (src > macro->expansion && (src[-1].flags & PASTE_LEFT))) + || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) total += arg->count - 1; else { if (!arg->expanded) - { - arg->expanded_count = 0; - if (arg->count) - expand_arg (pfile, arg); - } + expand_arg (pfile, arg); total += arg->expanded_count - 1; } } - dest = (cpp_token *) _cpp_pool_alloc (&pfile->argument_pool, - total * sizeof (cpp_token)); - list->first = dest; + /* Now allocate space for the expansion, copy the tokens and replace + the arguments. */ + buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *)); + first = (const cpp_token **) buff->base; + dest = first; - for (src = macro->expansion; src < limit; src++) - if (src->type == CPP_MACRO_ARG) - { - unsigned int count; - const cpp_token *from; + for (src = macro->exp.tokens; src < limit; src++) + { + unsigned int count; + const cpp_token **from, **paste_flag; - arg = &args[src->val.arg_no - 1]; - if (src->flags & STRINGIFY_ARG) - { - from = arg->stringified, count = 1; - /* Ugh. Maintain position of original argument. */ - arg->stringified->line = src->line; - arg->stringified->col = src->col; - } - else if (src->flags & PASTE_LEFT) - count = arg->count, from = arg->first; - else if (src > macro->expansion && (src[-1].flags & PASTE_LEFT)) - { - count = arg->count, from = arg->first; - if (dest != list->first) - { - /* GCC has special semantics for , ## b where b is a - varargs parameter: the comma disappears if b was - given no actual arguments (not merely if b is an - empty argument); otherwise pasting is turned off. */ - if (dest[-1].type == CPP_COMMA - && macro->variadic - && src->val.arg_no == macro->paramc) - { - if (count == 0) - dest--; - else - dest[-1].flags &= ~PASTE_LEFT; - } - /* Count == 0 is the RHS a placemarker case. */ - else if (count == 0) - dest[-1].flags &= ~PASTE_LEFT; - } - } - else - count = arg->expanded_count, from = arg->expanded; + if (src->type != CPP_MACRO_ARG) + { + *dest++ = src; + continue; + } - /* Count == 0 is the LHS a placemarker case. */ - if (count) - { - memcpy (dest, from, count * sizeof (cpp_token)); + paste_flag = 0; + arg = &args[src->val.arg_no - 1]; + if (src->flags & STRINGIFY_ARG) + count = 1, from = &arg->stringified; + else if (src->flags & PASTE_LEFT) + count = arg->count, from = arg->first; + else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT)) + { + count = arg->count, from = arg->first; + if (dest != first) + { + if (dest[-1]->type == CPP_COMMA + && macro->variadic + && src->val.arg_no == macro->paramc) + { + /* Swallow a pasted comma if from == NULL, otherwise + drop the paste flag. */ + if (from == NULL) + dest--; + else + paste_flag = dest - 1; + } + /* Remove the paste flag if the RHS is a placemarker. */ + else if (count == 0) + paste_flag = dest - 1; + } + } + else + count = arg->expanded_count, from = arg->expanded; - /* The first token gets PREV_WHITE of the CPP_MACRO_ARG. */ - dest->flags &= ~(PREV_WHITE | BOL); - dest->flags |= src->flags & (PREV_WHITE | BOL); - dest->flags |= AVOID_LPASTE; + /* Padding on the left of an argument (unless RHS of ##). */ + if (!pfile->state.in_directive + && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT)) + *dest++ = padding_token (pfile, src); - /* The last token gets the PASTE_LEFT of the CPP_MACRO_ARG. */ - dest[count - 1].flags |= src->flags & PASTE_LEFT; + if (count) + { + memcpy (dest, from, count * sizeof (cpp_token *)); + dest += count; - dest += count; - } + /* With a non-empty argument on the LHS of ##, the last + token should be flagged PASTE_LEFT. */ + if (src->flags & PASTE_LEFT) + paste_flag = dest - 1; + } - /* The token after the argument must avoid an accidental paste. */ - flags = AVOID_LPASTE; - } - else - { - *dest = *src; - dest->flags |= flags; - dest++; - flags = 0; - } + /* Avoid paste on RHS (even case count == 0). */ + if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT)) + *dest++ = &pfile->avoid_paste; - list->limit = dest; + /* Add a new paste flag, or remove an unwanted one. */ + if (paste_flag) + { + cpp_token *token = _cpp_temp_token (pfile); + token->type = (*paste_flag)->type; + token->val.str = (*paste_flag)->val.str; + if (src->flags & PASTE_LEFT) + token->flags = (*paste_flag)->flags | PASTE_LEFT; + else + token->flags = (*paste_flag)->flags & ~PASTE_LEFT; + *paste_flag = token; + } + } /* Free the expanded arguments. */ for (i = 0; i < macro->paramc; i++) + if (args[i].expanded) + free (args[i].expanded); + + push_ptoken_context (pfile, node, buff, first, dest - first); +} + +/* Return a special padding token, with padding inherited from SOURCE. */ +static const cpp_token * +padding_token (pfile, source) + cpp_reader *pfile; + const cpp_token *source; +{ + cpp_token *result = _cpp_temp_token (pfile); + + result->type = CPP_PADDING; + result->val.source = source; + result->flags = 0; + return result; +} + +/* 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; +{ + cpp_context *result = pfile->context->next; + + if (result == 0) { - if (args[i].expanded) - free (args[i].expanded); - if (args[i].stringified) - free (args[i].stringified); + result = xnew (cpp_context); + result->prev = pfile->context; + result->next = 0; + pfile->context->next = result; } + + pfile->context = result; + return result; } -/* Subroutine of expand_arg to put the unexpanded tokens on the - context stack. */ -static cpp_context * -push_arg_context (pfile, arg) +/* Push a list of pointers to tokens. */ +static void +push_ptoken_context (pfile, macro, buff, first, count) cpp_reader *pfile; - macro_arg *arg; + cpp_hashnode *macro; + _cpp_buff *buff; + const cpp_token **first; + unsigned int count; { cpp_context *context = next_context (pfile); - context->macro = 0; - context->list.first = arg->first; - context->list.limit = arg->first + arg->count + 1; - return context; + context->direct_p = false; + context->macro = macro; + context->buff = buff; + FIRST (context).ptoken = first; + LAST (context).ptoken = first + count; } +/* Push a list of tokens. */ +static void +push_token_context (pfile, macro, first, count) + cpp_reader *pfile; + cpp_hashnode *macro; + const cpp_token *first; + unsigned int count; +{ + cpp_context *context = next_context (pfile); + + context->direct_p = true; + context->macro = macro; + context->buff = NULL; + FIRST (context).token = first; + LAST (context).token = first + count; +} + +/* Push a traditional macro's replacement text. */ +void +_cpp_push_text_context (pfile, macro, start, len) + cpp_reader *pfile; + cpp_hashnode *macro; + const uchar *start; + size_t len; +{ + cpp_context *context = next_context (pfile); + + context->direct_p = true; + context->macro = macro; + context->buff = NULL; + CUR (context) = start; + RLIMIT (context) = start + len; + macro->flags |= NODE_DISABLED; +} + +/* 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; macro_arg *arg; { - cpp_token *token; - unsigned int capacity = 256; + unsigned int capacity; + bool saved_warn_trad; + + if (arg->count == 0) + return; + + /* Don't warn about funlike macros when pre-expanding. */ + saved_warn_trad = CPP_WTRADITIONAL (pfile); + CPP_WTRADITIONAL (pfile) = 0; /* Loop, reading in the arguments. */ - arg->expanded = (cpp_token *) xmalloc (capacity * sizeof (cpp_token)); + capacity = 256; + arg->expanded = (const cpp_token **) + xmalloc (capacity * sizeof (cpp_token *)); - push_arg_context (pfile, arg); - do + push_ptoken_context (pfile, NULL, NULL, arg->first, arg->count + 1); + for (;;) { - if (arg->expanded_count >= capacity) + const cpp_token *token; + + if (arg->expanded_count + 1 >= capacity) { capacity *= 2; - arg->expanded = (cpp_token *) - xrealloc (arg->expanded, capacity * sizeof (cpp_token)); + arg->expanded = (const cpp_token **) + xrealloc (arg->expanded, capacity * sizeof (cpp_token *)); } - token = &arg->expanded[arg->expanded_count++]; - cpp_get_token (pfile, token); + + token = cpp_get_token (pfile); + + if (token->type == CPP_EOF) + break; + + arg->expanded[arg->expanded_count++] = token; } - while (token->type != CPP_EOF); - arg->expanded_count--; + _cpp_pop_context (pfile); - /* Pop the context we pushed. */ - pfile->context = pfile->context->prev; + CPP_WTRADITIONAL (pfile) = saved_warn_trad; } +/* 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; - pfile->context = context->prev; - if (!pfile->context->prev && !pfile->state.parsing_args) - unlock_pools (pfile); + if (context->macro) + context->macro->flags &= ~NODE_DISABLED; + + if (context->buff) + _cpp_release_buff (pfile, context->buff); - /* Re-enable a macro when leaving its expansion. */ - context->macro->disabled = 0; + pfile->context = context->prev; } /* Eternal routine to get a token. Also used nearly everywhere @@ -902,84 +1100,79 @@ _cpp_pop_context (pfile) a directive inside a macro call, when at the end of a directive and state.in_directive is still 1, and at the end of argument pre-expansion. */ -void -cpp_get_token (pfile, token) +const cpp_token * +cpp_get_token (pfile) cpp_reader *pfile; - cpp_token *token; { + const cpp_token *result; + for (;;) { + cpp_hashnode *node; cpp_context *context = pfile->context; /* Context->prev == 0 <=> base context. */ if (!context->prev) - *token = *_cpp_lex_token (pfile); - else if (context->list.first != context->list.limit) + result = _cpp_lex_token (pfile); + else if (FIRST (context).token != LAST (context).token) { - *token = *context->list.first++; - token->flags |= pfile->buffer->saved_flags; - pfile->buffer->saved_flags = 0; - /* PASTE_LEFT tokens can only appear in macro expansions. */ - if (token->flags & PASTE_LEFT) + if (context->direct_p) + result = FIRST (context).token++; + else + result = *FIRST (context).ptoken++; + + if (result->flags & PASTE_LEFT) { - /* Maintains position of original token. */ - paste_all_tokens (pfile, token); - pfile->buffer->saved_flags = AVOID_LPASTE; + paste_all_tokens (pfile, result); + if (pfile->state.in_directive) + continue; + return padding_token (pfile, result); } } else { - if (!context->macro) - cpp_ice (pfile, "context->macro == 0"); - - /* Avoid accidental paste at the end of a macro. */ - pfile->buffer->saved_flags |= AVOID_LPASTE; _cpp_pop_context (pfile); - continue; + if (pfile->state.in_directive) + continue; + return &pfile->avoid_paste; } - if (token->type != CPP_NAME) - break; + if (pfile->state.in_directive && result->type == CPP_COMMENT) + continue; - /* Handle macros and the _Pragma operator. */ - if (token->val.node->type == NT_MACRO - && !pfile->state.prevent_expansion - && !(token->flags & NO_EXPAND)) - { - cpp_hashnode *node = token->val.node; + if (result->type != CPP_NAME) + break; - /* Macros invalidate controlling macros. */ - pfile->mi_valid = false; + node = result->val.node; - if (node->flags & NODE_BUILTIN) - { - /* Maintains position of original token. */ - builtin_macro (pfile, token); - pfile->buffer->saved_flags = AVOID_LPASTE; - break; - } + if (node->type != NT_MACRO || (result->flags & NO_EXPAND)) + break; - if (node->value.macro->disabled) - token->flags |= NO_EXPAND; - else if (enter_macro_context (pfile, node)) + if (!(node->flags & NODE_DISABLED)) + { + if (!pfile->state.prevent_expansion + && enter_macro_context (pfile, node)) { - /* Pass AVOID_LPASTE and our PREV_WHITE to next token. */ - pfile->buffer->saved_flags = ((token->flags & (PREV_WHITE | BOL)) - | AVOID_LPASTE); - continue; + 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 (token->val.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; } /* Returns true if we're expanding an object-like macro that was @@ -989,22 +1182,27 @@ 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 - processed. */ +/* Read each token in, until end of the current file. Directives are + transparently processed. */ void cpp_scan_nooutput (pfile) cpp_reader *pfile; { - cpp_token token; + /* Request a CPP_EOF token at the end of this file, rather than + transparently continuing with the including file. */ + pfile->buffer->return_at_eof = true; - do - cpp_get_token (pfile, &token); - while (token.type != CPP_EOF); + if (CPP_OPTION (pfile, traditional)) + while (_cpp_read_logical_line_trad (pfile)) + ; + else + while (cpp_get_token (pfile)->type != CPP_EOF) + ; } /* Step back one (or more) tokens. Can only step mack more than 1 if @@ -1020,7 +1218,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; @@ -1031,14 +1231,17 @@ _cpp_backup_tokens (pfile, count) { if (count != 1) abort (); - pfile->context->list.first--; + if (pfile->context->direct_p) + FIRST (pfile->context).token--; + else + FIRST (pfile->context).ptoken--; } } /* #define directive parsing and handling. */ -/* Returns non-zero if a macro redefinition warning is required. */ -static int +/* Returns nonzero if a macro redefinition warning is required. */ +static bool warn_of_redefinition (pfile, node, macro2) cpp_reader *pfile; const cpp_hashnode *node; @@ -1049,37 +1252,37 @@ warn_of_redefinition (pfile, node, macro2) /* Some redefinitions need to be warned about regardless. */ if (node->flags & NODE_WARN) - return 1; - - if (! CPP_PEDANTIC (pfile)) - return 0; + 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). */ macro1 = node->value.macro; - /* The quick failures. */ - if (macro1->count != macro2->count - || macro1->paramc != macro2->paramc + /* Don't check count here as it can be different in valid + traditional redefinitions with just whitespace differences. */ + if (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->expansion[i], ¯o2->expansion[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 _cpp_expansions_different_trad (macro1, macro2); + + if (macro1->count == macro2->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. */ - void _cpp_free_definition (h) cpp_hashnode *h; @@ -1087,50 +1290,43 @@ _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. */ -static int -save_parameter (pfile, macro, node) + zero on success, nonzero if the parameter is a duplicate. */ +bool +_cpp_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) { - cpp_error (pfile, "duplicate macro parameter \"%s\"", NODE_NAME (node)); - return 1; + cpp_error (pfile, DL_ERROR, "duplicate macro parameter \"%s\"", + NODE_NAME (node)); + return true; } - 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; - return 0; + ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node; + node->arg_index = macro->paramc; + return false; } -/* Check the syntax of the paramters in a MACRO definition. */ -static int +/* Check the syntax of the parameters in a MACRO definition. Returns + false if an error occurs. */ +static bool parse_params (pfile, macro) cpp_reader *pfile; cpp_macro *macro; { unsigned int prev_ident = 0; - macro->params = (cpp_hashnode **) POOL_FRONT (&pfile->macro_pool); for (;;) { const cpp_token *token = _cpp_lex_token (pfile); @@ -1138,32 +1334,40 @@ parse_params (pfile, macro) switch (token->type) { default: - cpp_error (pfile, "\"%s\" may not appear in macro parameter list", + /* Allow/ignore comments in parameter lists if we are + preserving comments in macro expansions. */ + if (token->type == CPP_COMMENT + && ! CPP_OPTION (pfile, discard_comments_in_macro_exp)) + continue; + + cpp_error (pfile, DL_ERROR, + "\"%s\" may not appear in macro parameter list", cpp_token_as_text (pfile, token)); - return 0; + return false; case CPP_NAME: if (prev_ident) { - cpp_error (pfile, "macro parameters must be comma-separated"); - return 0; + cpp_error (pfile, DL_ERROR, + "macro parameters must be comma-separated"); + return false; } prev_ident = 1; - if (save_parameter (pfile, macro, token->val.node)) - return 0; + if (_cpp_save_parameter (pfile, macro, token->val.node)) + return false; continue; case CPP_CLOSE_PAREN: if (prev_ident || macro->paramc == 0) - break; + return true; /* Fall through to pick up the error. */ case CPP_COMMA: if (!prev_ident) { - cpp_error (pfile, "parameter name missing"); - return 0; + cpp_error (pfile, DL_ERROR, "parameter name missing"); + return false; } prev_ident = 0; continue; @@ -1172,30 +1376,27 @@ parse_params (pfile, macro) macro->variadic = 1; if (!prev_ident) { - save_parameter (pfile, macro, pfile->spec_nodes.n__VA_ARGS__); + _cpp_save_parameter (pfile, macro, + pfile->spec_nodes.n__VA_ARGS__); pfile->state.va_args_ok = 1; if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, pedantic)) - cpp_pedwarn (pfile, - "anonymous variadic macros were introduced in C99"); + cpp_error (pfile, DL_PEDWARN, + "anonymous variadic macros were introduced in C99"); } else if (CPP_OPTION (pfile, pedantic)) - cpp_pedwarn (pfile, "ISO C does not permit named variadic macros"); + cpp_error (pfile, DL_PEDWARN, + "ISO C does not permit named variadic macros"); /* We're at the end, and just expect a closing parenthesis. */ token = _cpp_lex_token (pfile); if (token->type == CPP_CLOSE_PAREN) - break; + return true; /* Fall through. */ case CPP_EOF: - cpp_error (pfile, "missing ')' in macro parameter list"); - return 0; + cpp_error (pfile, DL_ERROR, "missing ')' in macro parameter list"); + return false; } - - /* Success. Commit the parameter array. */ - POOL_COMMIT (&pfile->macro_pool, - macro->paramc * sizeof (cpp_hashnode *)); - return 1; } } @@ -1205,20 +1406,14 @@ alloc_expansion_token (pfile, macro) cpp_reader *pfile; cpp_macro *macro; { - cpp_token *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)); - /* 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]; - } - - 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; @@ -1229,7 +1424,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; @@ -1242,25 +1437,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_pool_alloc (&pfile->macro_pool, - 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). */ @@ -1268,16 +1451,18 @@ _cpp_create_definition (pfile, node) if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) { - if (!(ok = parse_params (pfile, macro))) - goto cleanup2; + bool ok = parse_params (pfile, macro); + macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); + if (!ok) + return false; + + /* Success. Commit the parameter array. */ + BUFF_FRONT (pfile->a_buff) = (uchar *) ¯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); + cpp_error (pfile, DL_PEDWARN, + "ISO C requires whitespace after the macro name"); if (macro->fun_like) token = lex_expansion_token (pfile, macro); @@ -1304,9 +1489,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, "'#' is not followed by a macro parameter"); - goto cleanup1; + cpp_error (pfile, DL_ERROR, + "'#' is not followed by a macro parameter"); + return false; } } @@ -1323,82 +1508,112 @@ _cpp_create_definition (pfile, node) if (macro->count == 0 || token->type == CPP_EOF) { - ok = 0; - cpp_error (pfile, + cpp_error (pfile, DL_ERROR, "'##' cannot appear at either end of a macro expansion"); - goto cleanup1; + return false; } token[-1].flags |= PASTE_LEFT; - /* Give it a PREV_WHITE for -dM etc. */ - token->flags |= PREV_WHITE; } token = lex_expansion_token (pfile, macro); } + macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff); + /* Don't count the CPP_EOF. */ macro->count--; - /* Clear the whitespace flag from the leading token, but put a space - in front of a leading # which might be used to fake a directive. */ - if (macro->expansion[0].type == CPP_HASH) - macro->expansion[0].flags |= PREV_WHITE; - else - macro->expansion[0].flags &= ~PREV_WHITE; + /* Clear whitespace on first token for warn_of_redefinition(). */ + if (macro->count) + macro->exp.tokens[0].flags &= ~PREV_WHITE; - /* 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); + /* Commit the memory. */ + BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count]; + return true; +} + +/* Parse a macro and save its expansion. Returns nonzero 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->used = 0; + macro->count = 0; + macro->fun_like = 0; /* To suppress some diagnostics. */ macro->syshdr = pfile->map->sysp != 0; - /* Commit the memory. */ - POOL_COMMIT (&pfile->macro_pool, macro->count * sizeof (cpp_token)); + if (CPP_OPTION (pfile, traditional)) + ok = _cpp_create_trad_definition (pfile, macro); + else + { + cpp_token *saved_cur_token = pfile->cur_token; - if (node->type != NT_VOID) + 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_MACRO) { + if (CPP_OPTION (pfile, warn_unused_macros)) + _cpp_warn_if_unused_macro (pfile, node, NULL); + if (warn_of_redefinition (pfile, node, macro)) { - cpp_pedwarn_with_line (pfile, pfile->directive_line, 0, - "\"%s\" redefined", NODE_NAME (node)); + 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_pedwarn_with_line (pfile, 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); } + if (node->type != NT_VOID) + _cpp_free_definition (node); + /* Enter definition in hash table. */ node->type = NT_MACRO; node->value.macro = macro; 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; } -/* 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; @@ -1406,8 +1621,8 @@ check_trad_stringification (pfile, macro, string) const cpp_string *string; { unsigned int i, len; - const U_CHAR *p, *q, *limit = string->text + string->len; - + const uchar *p, *q, *limit = string->text + string->len; + /* Loop over the string. */ for (p = string->text; p < limit; p = q) { @@ -1431,9 +1646,9 @@ check_trad_stringification (pfile, macro, string) if (NODE_LEN (node) == len && !memcmp (p, NODE_NAME (node), len)) { - cpp_warning (pfile, - "macro argument \"%s\" would be stringified with -traditional.", - NODE_NAME (node)); + cpp_error (pfile, DL_WARNING, + "macro argument \"%s\" would be stringified in traditional C", + NODE_NAME (node)); break; } } @@ -1445,7 +1660,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; @@ -1457,37 +1671,43 @@ cpp_macro_definition (pfile, node) if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN)) { - cpp_ice (pfile, "invalid hash type %d in cpp_macro_definition", node->type); + cpp_error (pfile, DL_ICE, + "invalid hash type %d in cpp_macro_definition", node->type); return 0; } /* Calculate length. */ - len = NODE_LEN (node) + 1; /* ' ' */ + len = NODE_LEN (node) + 2; /* ' ' and NUL. */ if (macro->fun_like) { - len += 3; /* "()" plus possible final "." of named - varargs (we have + 2 below). */ + len += 4; /* "()" plus possible final ".." of named + varargs (we have + 1 below). */ for (i = 0; i < macro->paramc; i++) - len += NODE_LEN (macro->params[i]) + 2; /* ", " */ + len += NODE_LEN (macro->params[i]) + 1; /* "," */ } - for (i = 0; i < macro->count; i++) + if (CPP_OPTION (pfile, traditional)) + len += _cpp_replacement_text_len (macro); + else { - cpp_token *token = ¯o->expansion[i]; + for (i = 0; i < macro->count; i++) + { + cpp_token *token = ¯o->exp.tokens[i]; - if (token->type == CPP_MACRO_ARG) - len += NODE_LEN (macro->params[token->val.arg_no - 1]); - else - len += cpp_token_len (token); /* Includes room for ' '. */ - if (token->flags & STRINGIFY_ARG) - len++; /* "#" */ - if (token->flags & PASTE_LEFT) - len += 3; /* " ##" */ + if (token->type == CPP_MACRO_ARG) + len += NODE_LEN (macro->params[token->val.arg_no - 1]); + else + len += cpp_token_len (token); /* Includes room for ' '. */ + if (token->flags & STRINGIFY_ARG) + len++; /* "#" */ + if (token->flags & PASTE_LEFT) + len += 3; /* " ##" */ + } } if (len > pfile->macro_buffer_len) { - pfile->macro_buffer = (U_CHAR *) xrealloc (pfile->macro_buffer, len); + pfile->macro_buffer = (uchar *) xrealloc (pfile->macro_buffer, len); pfile->macro_buffer_len = len; } @@ -1511,20 +1731,28 @@ cpp_macro_definition (pfile, node) } if (i + 1 < macro->paramc) - *buffer++ = ',', *buffer++ = ' '; + /* Don't emit a space after the comma here; we're trying + to emit a Dwarf-friendly definition, and the Dwarf spec + forbids spaces in the argument list. */ + *buffer++ = ','; else if (macro->variadic) *buffer++ = '.', *buffer++ = '.', *buffer++ = '.'; } *buffer++ = ')'; } + /* The Dwarf spec requires a space after the macro name, even if the + definition is the empty string. */ + *buffer++ = ' '; + + if (CPP_OPTION (pfile, traditional)) + buffer = _cpp_copy_replacement_text (macro, buffer); + else if (macro->count) /* Expansion tokens. */ - if (macro->count) { - *buffer++ = ' '; for (i = 0; i < macro->count; i++) { - cpp_token *token = ¯o->expansion[i]; + cpp_token *token = ¯o->exp.tokens[i]; if (token->flags & PREV_WHITE) *buffer++ = ' ';