X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=gcc%2Fcppmacro.c;fp=gcc%2Fcppmacro.c;h=0000000000000000000000000000000000000000;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=70e52fda6e86c924dc9b836b83ded52e2254570f;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c deleted file mode 100644 index 70e52fda..00000000 --- a/gcc/cppmacro.c +++ /dev/null @@ -1,1648 +0,0 @@ -/* Part of CPP library. (Macro and #define handling.) - Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998, - 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 - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! */ - -#include "config.h" -#include "system.h" -#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 syshdr : 1; /* If macro defined in system header. */ -}; - -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 *stringified; /* Stringified argument. */ - unsigned int count; /* # of tokens in argument. */ - unsigned int expanded_count; /* # of tokens in expanded argument. */ -}; - -/* Macro expansion. */ - -static int enter_macro_context PARAMS ((cpp_reader *, 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 const cpp_token *new_string_token PARAMS ((cpp_reader *, U_CHAR *, - unsigned 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 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 ((const cpp_hashnode *, - const cpp_macro *)); -static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *)); -static int parse_params PARAMS ((cpp_reader *, cpp_macro *)); -static void check_trad_stringification PARAMS ((cpp_reader *, - const cpp_macro *, - const cpp_string *)); - -/* 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; - unsigned char *text; - unsigned int len; -{ - cpp_token *token = _cpp_temp_token (pfile); - - text[len] = '\0'; - token->type = CPP_STRING; - token->val.str.len = len; - token->val.str.text = text; - token->flags = 0; - return token; -} - -/* Allocates and returns a CPP_NUMBER token evaluating to NUMBER. */ -static const cpp_token * -new_number_token (pfile, number) - cpp_reader *pfile; - unsigned int number; -{ - cpp_token *token = _cpp_temp_token (pfile); - /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */ - unsigned char *buf = _cpp_unaligned_alloc (pfile, 21); - - sprintf ((char *) buf, "%u", number); - token->type = CPP_NUMBER; - token->val.str.text = buf; - token->val.str.len = ustrlen (buf); - token->flags = 0; - return token; -} - -static const char * const monthnames[] = -{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -/* 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 built-in macro \"%s\"", NODE_NAME (node)); - return 0; - - case BT_FILE: - case BT_BASE_FILE: - { - unsigned int len; - const char *name; - U_CHAR *buf; - const struct line_map *map = pfile->map; - - if (node->value.builtin == BT_BASE_FILE) - while (! MAIN_FILE_P (map)) - map = INCLUDED_FROM (&pfile->line_maps, map); - - name = map->to_file; - len = strlen (name); - buf = _cpp_unaligned_alloc (pfile, len * 4 + 1); - len = cpp_quote_string (buf, (const unsigned char *) name, len) - buf; - - 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. */ - 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. */ - 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); - result = new_number_token (pfile, stdc); - } - break; - - case BT_DATE: - case BT_TIME: - if (pfile->date.type == CPP_EOF) - { - /* 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 = time (NULL); - struct tm *tb = localtime (&tt); - - pfile->date.val.str.text = - _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; - sprintf ((char *) pfile->date.val.str.text, "%s %2d %4d", - monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900); - - pfile->time.val.str.text = - _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; - sprintf ((char *) pfile->time.val.str.text, "%02d:%02d:%02d", - tb->tm_hour, tb->tm_min, tb->tm_sec); - } - - 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; -} - -/* 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. */ -U_CHAR * -cpp_quote_string (dest, src, len) - U_CHAR *dest; - const U_CHAR *src; - unsigned int len; -{ - while (len--) - { - U_CHAR c = *src++; - - if (c == '\\' || c == '"') - { - *dest++ = '\\'; - *dest++ = c; - } - else - { - if (ISPRINT (c)) - *dest++ = c; - else - { - sprintf ((char *) dest, "\\%03o", c); - dest += 4; - } - } - } - - return dest; -} - -/* 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; -{ - 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++) - { - 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) - len *= 4; - len += 2; - - if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < 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 (dest != BUFF_FRONT (pfile->u_buff)) - { - if (source == NULL) - source = token; - if (source->flags & PREV_WHITE) - *dest++ = ' '; - } - source = NULL; - - if (escape_it) - { - _cpp_buff *buff = _cpp_get_buff (pfile, len); - unsigned char *buf = BUFF_FRONT (buff); - len = cpp_spell_token (pfile, token, buf) - buf; - dest = cpp_quote_string (dest, buf, len); - _cpp_release_buff (pfile, buff); - } - else - dest = cpp_spell_token (pfile, token, dest); - - if (token->type == CPP_OTHER && token->val.c == '\\') - backslash_count++; - else - backslash_count = 0; - } - - /* Ignore the final \ of invalid string literals. */ - if (backslash_count & 1) - { - cpp_warning (pfile, "invalid string literal, ignoring final '\\'"); - dest--; - } - - /* Commit the memory, including NUL, and return the token. */ - if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < 1) - { - size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff); - _cpp_extend_buff (pfile, &pfile->u_buff, 1); - dest = BUFF_FRONT (pfile->u_buff) + len_so_far; - } - 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 - 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; - const cpp_token **plhs, *rhs; -{ - 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, 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; - const cpp_token *lhs; -{ - const cpp_token *rhs; - cpp_context *context = pfile->context; - - do - { - /* Take the token directly from the current context. We can do - this, because we are in the replacement list of either an - 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. */ - if (context->direct_p) - rhs = context->first.token++; - else - rhs = *context->first.ptoken++; - - if (rhs->type == CPP_PADDING) - abort (); - - if (!paste_tokens (pfile, &lhs, rhs)) - { - _cpp_backup_tokens (pfile, 1); - - /* 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)); - break; - } - } - while (rhs->flags & PASTE_LEFT); - - /* Put the resulting token in its own context. */ - 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. 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_buff *buff, *base_buff; - cpp_macro *macro; - macro_arg *args, *arg; - const cpp_token *token; - unsigned int argc; - bool error = false; - - 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; - - 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; - } - - token = cpp_get_token (pfile); - - 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; - - arg->first[ntokens++] = token; - } - - /* 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) - { - buff->cur = (unsigned char *) &arg->first[ntokens + 1]; - if (argc != macro->paramc) - arg++; - } - } - while (token->type != CPP_CLOSE_PAREN - && token->type != CPP_EOF - && token->type != CPP_HASH); - - if (token->type == CPP_EOF || token->type == CPP_HASH) - { - bool step_back = false; - - /* 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. */ - if (token->type == CPP_HASH) - { - cpp_error (pfile, - "directives may not be used inside a macro argument"); - step_back = true; - } - else - 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\"", - NODE_NAME (node)); - error = true; - } - 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 (argc + 1 == macro->paramc && macro->variadic) - { - if (CPP_PEDANTIC (pfile) && ! macro->syshdr) - cpp_pedwarn (pfile, "ISO C99 requires rest arguments to be used"); - } - else - { - cpp_error (pfile, - "macro \"%s\" requires %u arguments, but only %u given", - NODE_NAME (node), macro->paramc, argc); - error = true; - } - } - else if (argc > macro->paramc) - { - /* Empty argument to a macro taking no arguments is OK. */ - if (argc != 1 || arg->count) - { - cpp_error (pfile, - "macro \"%s\" passed %u arguments, but takes just %u", - NODE_NAME (node), argc, macro->paramc); - error = true; - } - } - - if (!error) - { - /* 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; - } - - _cpp_release_buff (pfile, base_buff); - return NULL; -} - -/* 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; - cpp_hashnode *node; -{ - const cpp_token *token, *padding = NULL; - - for (;;) - { - token = cpp_get_token (pfile); - if (token->type != CPP_PADDING) - break; - if (padding == NULL - || (!(padding->flags & PREV_WHITE) && token->val.source == NULL)) - padding = token; - } - - if (token->type == CPP_OPEN_PAREN) - { - pfile->state.parsing_args = 2; - return collect_args (pfile, node); - } - - /* 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) - { - /* 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 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; -{ - /* The presence of a macro invalidates a file's controlling macro. */ - pfile->mi_valid = false; - - pfile->state.angled_headers = false; - - /* Handle standard macros. */ - if (! (node->flags & NODE_BUILTIN)) - { - cpp_macro *macro = node->value.macro; - - 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. */ - node->flags |= NODE_DISABLED; - - if (macro->paramc == 0) - push_token_context (pfile, node, macro->expansion, macro->count); - - return 1; - } - - /* 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, node, args) - cpp_reader *pfile; - cpp_hashnode *node; - macro_arg *args; -{ - unsigned int i, total; - const cpp_token *src, *limit; - 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; - - for (src = macro->expansion; 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]; - - if (src->flags & STRINGIFY_ARG) - { - if (!arg->stringified) - arg->stringified = stringify_arg (pfile, arg); - } - else if ((src->flags & PASTE_LEFT) - || (src > macro->expansion && (src[-1].flags & PASTE_LEFT))) - total += arg->count - 1; - else - { - if (!arg->expanded) - expand_arg (pfile, arg); - total += arg->expanded_count - 1; - } - } - - /* 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++) - { - unsigned int count; - const cpp_token **from, **paste_flag; - - if (src->type != CPP_MACRO_ARG) - { - *dest++ = src; - continue; - } - - 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->expansion && (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; - - /* Padding on the left of an argument (unless RHS of ##). */ - if (!pfile->state.in_directive - && src != macro->expansion && !(src[-1].flags & PASTE_LEFT)) - *dest++ = padding_token (pfile, src); - - if (count) - { - memcpy (dest, from, count * sizeof (cpp_token *)); - 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; - } - - /* Avoid paste on RHS (even case count == 0). */ - if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT)) - *dest++ = &pfile->avoid_paste; - - /* 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) - { - result = xnew (cpp_context); - result->prev = pfile->context; - result->next = 0; - pfile->context->next = result; - } - - pfile->context = result; - return result; -} - -/* Push a list of pointers to tokens. */ -static void -push_ptoken_context (pfile, macro, buff, first, count) - cpp_reader *pfile; - cpp_hashnode *macro; - _cpp_buff *buff; - const cpp_token **first; - unsigned int count; -{ - cpp_context *context = next_context (pfile); - - context->direct_p = false; - context->macro = macro; - context->buff = buff; - context->first.ptoken = first; - context->last.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; - context->first.token = first; - 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; - macro_arg *arg; -{ - unsigned int capacity; - - if (arg->count == 0) - return; - - /* Loop, reading in the arguments. */ - capacity = 256; - arg->expanded = (const cpp_token **) - xmalloc (capacity * sizeof (cpp_token *)); - - push_ptoken_context (pfile, NULL, NULL, arg->first, arg->count + 1); - for (;;) - { - const cpp_token *token; - - if (arg->expanded_count + 1 >= capacity) - { - capacity *= 2; - arg->expanded = (const cpp_token **) - xrealloc (arg->expanded, capacity * sizeof (cpp_token *)); - } - - token = cpp_get_token (pfile); - - if (token->type == CPP_EOF) - break; - - arg->expanded[arg->expanded_count++] = token; - } - - _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; - - if (context->macro) - context->macro->flags &= ~NODE_DISABLED; - - if (context->buff) - _cpp_release_buff (pfile, context->buff); - - pfile->context = context->prev; -} - -/* Eternal routine to get a token. Also used nearly everywhere - internally, except for places where we know we can safely call - the lexer directly, such as lexing a directive name. - - Macro expansions and directives are transparently handled, - including entering included files. Thus tokens are post-macro - expansion, and after any intervening directives. External callers - see CPP_EOF only at EOF. Internal callers also see it when meeting - 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. */ -const cpp_token * -cpp_get_token (pfile) - cpp_reader *pfile; -{ - const cpp_token *result; - - for (;;) - { - cpp_hashnode *node; - cpp_context *context = pfile->context; - - /* Context->prev == 0 <=> base context. */ - if (!context->prev) - result = _cpp_lex_token (pfile); - else if (context->first.token != context->last.token) - { - if (context->direct_p) - result = context->first.token++; - else - result = *context->first.ptoken++; - - if (result->flags & PASTE_LEFT) - { - paste_all_tokens (pfile, result); - if (pfile->state.in_directive) - continue; - return padding_token (pfile, result); - } - } - else - { - _cpp_pop_context (pfile); - if (pfile->state.in_directive) - continue; - return &pfile->avoid_paste; - } - - if (result->type != CPP_NAME) - break; - - node = result->val.node; - - if (node->type != NT_MACRO || (result->flags & NO_EXPAND)) - break; - - if (!(node->flags & NODE_DISABLED)) - { - 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; - } - - break; - } - - return result; -} - -/* Returns true if we're expanding an object-like macro that was - defined in a system header. Just checks the macro at the top of - the stack. Used for diagnostic suppression. */ -int -cpp_sys_macro_p (pfile) - cpp_reader *pfile; -{ - cpp_hashnode *node = pfile->context->macro; - - return node && node->value.macro && node->value.macro->syshdr; -} - -/* Read each token in, until EOF. Directives are transparently - processed. */ -void -cpp_scan_nooutput (pfile) - cpp_reader *pfile; -{ - while (cpp_get_token (pfile)->type != CPP_EOF) - ; -} - -/* Step back one (or more) tokens. Can only step mack more than 1 if - they are from the lexer, and not from macro expansion. */ -void -_cpp_backup_tokens (pfile, count) - cpp_reader *pfile; - unsigned int count; -{ - if (pfile->context->prev == NULL) - { - pfile->lookaheads += count; - while (count--) - { - pfile->cur_token--; - 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; - } - } - } - else - { - if (count != 1) - abort (); - if (pfile->context->direct_p) - pfile->context->first.token--; - else - pfile->context->first.ptoken--; - } -} - -/* #define directive parsing and handling. */ - -/* Returns non-zero if a macro redefinition warning is required. */ -static int -warn_of_redefinition (node, macro2) - const cpp_hashnode *node; - const cpp_macro *macro2; -{ - const cpp_macro *macro1; - unsigned int i; - - /* Some redefinitions need to be warned about regardless. */ - if (node->flags & NODE_WARN) - return 1; - - /* 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 - || 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; - - /* Check parameter spellings. */ - for (i = 0; i < macro1->paramc; i++) - if (macro1->params[i] != macro2->params[i]) - return 1; - - return 0; -} - -/* Free the definition of hashnode H. */ -void -_cpp_free_definition (h) - cpp_hashnode *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 | NODE_DISABLED); -} - -/* Save parameter NODE to the parameter list of macro MACRO. Returns - 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; -{ - /* Constraint 6.10.3.6 - duplicate parameter names. */ - if (node->arg_index) - { - cpp_error (pfile, "duplicate macro parameter \"%s\"", NODE_NAME (node)); - return 1; - } - - if (BUFF_ROOM (pfile->a_buff) - < (macro->paramc + 1) * sizeof (cpp_hashnode *)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); - - ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node; - node->arg_index = macro->paramc; - return 0; -} - -/* Check the syntax of the parameters in a MACRO definition. */ -static int -parse_params (pfile, macro) - cpp_reader *pfile; - cpp_macro *macro; -{ - unsigned int prev_ident = 0; - - for (;;) - { - const cpp_token *token = _cpp_lex_token (pfile); - - switch (token->type) - { - default: - cpp_error (pfile, "\"%s\" may not appear in macro parameter list", - cpp_token_as_text (pfile, token)); - return 0; - - case CPP_NAME: - if (prev_ident) - { - cpp_error (pfile, "macro parameters must be comma-separated"); - return 0; - } - prev_ident = 1; - - if (save_parameter (pfile, macro, token->val.node)) - return 0; - continue; - - case CPP_CLOSE_PAREN: - if (prev_ident || macro->paramc == 0) - return 1; - - /* Fall through to pick up the error. */ - case CPP_COMMA: - if (!prev_ident) - { - cpp_error (pfile, "parameter name missing"); - return 0; - } - prev_ident = 0; - continue; - - case CPP_ELLIPSIS: - macro->variadic = 1; - if (!prev_ident) - { - 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"); - } - else if (CPP_OPTION (pfile, pedantic)) - cpp_pedwarn (pfile, "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) - return 1; - /* Fall through. */ - - case CPP_EOF: - cpp_error (pfile, "missing ')' in macro parameter list"); - return 0; - } - } -} - -/* Allocate room for a token from a macro's replacement list. */ -static cpp_token * -alloc_expansion_token (pfile, macro) - cpp_reader *pfile; - cpp_macro *macro; -{ - if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_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; - cpp_macro *macro; -{ - cpp_token *token; - - pfile->cur_token = alloc_expansion_token (pfile, macro); - token = _cpp_lex_direct (pfile); - - /* Is this a parameter? */ - if (token->type == CPP_NAME && token->val.node->arg_index) - { - token->type = CPP_MACRO_ARG; - token->val.arg_no = token->val.node->arg_index; - } - else if (CPP_WTRADITIONAL (pfile) && macro->paramc > 0 - && (token->type == CPP_STRING || token->type == CPP_CHAR)) - check_trad_stringification (pfile, macro, &token->val.str); - - return token; -} - -/* Parse a macro and save its expansion. Returns non-zero on success. */ -int -_cpp_create_definition (pfile, node) - cpp_reader *pfile; - cpp_hashnode *node; -{ - cpp_macro *macro; - cpp_token *token, *saved_cur_token; - const cpp_token *ctoken; - unsigned int i, ok = 1; - - macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); - macro->line = pfile->directive_line; - macro->params = 0; - macro->paramc = 0; - macro->variadic = 0; - macro->count = 0; - macro->fun_like = 0; - - /* Get the first token of the expansion (or the '(' of a - function-like macro). */ - ctoken = _cpp_lex_token (pfile); - - if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) - { - 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"); - - saved_cur_token = pfile->cur_token; - - if (macro->fun_like) - token = lex_expansion_token (pfile, macro); - else - { - token = alloc_expansion_token (pfile, macro); - *token = *ctoken; - } - - for (;;) - { - /* Check the stringifying # constraint 6.10.3.2.1 of - function-like macros when lexing the subsequent token. */ - if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like) - { - if (token->type == CPP_MACRO_ARG) - { - token->flags &= ~PREV_WHITE; - token->flags |= STRINGIFY_ARG; - token->flags |= token[-1].flags & PREV_WHITE; - token[-1] = token[0]; - macro->count--; - } - /* 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; - } - } - - if (token->type == CPP_EOF) - break; - - /* Paste operator constraint 6.10.3.3.1. */ - if (token->type == CPP_PASTE) - { - /* Token-paste ##, can appear in both object-like and - function-like macros, but not at the ends. */ - if (--macro->count > 0) - token = lex_expansion_token (pfile, macro); - - if (macro->count == 0 || token->type == CPP_EOF) - { - ok = 0; - cpp_error (pfile, - "'##' cannot appear at either end of a macro expansion"); - goto cleanup1; - } - - token[-1].flags |= PASTE_LEFT; - } - - 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. */ - 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; - - if (node->type != NT_VOID) - { - if (warn_of_redefinition (node, macro)) - { - cpp_pedwarn_with_line (pfile, 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_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 a function-like MACRO's - parameters. */ -static void -check_trad_stringification (pfile, macro, string) - cpp_reader *pfile; - const cpp_macro *macro; - const cpp_string *string; -{ - unsigned int i, len; - const U_CHAR *p, *q, *limit = string->text + string->len; - - /* Loop over the string. */ - for (p = string->text; p < limit; p = q) - { - /* Find the start of an identifier. */ - while (p < limit && !is_idstart (*p)) - p++; - - /* Find the end of the identifier. */ - q = p; - while (q < limit && is_idchar (*q)) - q++; - - len = q - p; - - /* Loop over the function macro arguments to see if the - identifier inside the string matches one of them. */ - for (i = 0; i < macro->paramc; i++) - { - const cpp_hashnode *node = macro->params[i]; - - 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)); - break; - } - } - } -} - -/* Returns the name, arguments and expansion of a macro, in a format - suitable to be read back in again, and therefore also for DWARF 2 - 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; - const cpp_hashnode *node; -{ - unsigned int i, len; - const cpp_macro *macro = node->value.macro; - unsigned char *buffer; - - if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN)) - { - cpp_ice (pfile, "invalid hash type %d in cpp_macro_definition", node->type); - return 0; - } - - /* Calculate length. */ - len = NODE_LEN (node) + 2; /* ' ' and NUL. */ - if (macro->fun_like) - { - 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]) + 1; /* "," */ - } - - for (i = 0; i < macro->count; i++) - { - cpp_token *token = ¯o->expansion[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 (len > pfile->macro_buffer_len) - { - pfile->macro_buffer = (U_CHAR *) xrealloc (pfile->macro_buffer, len); - pfile->macro_buffer_len = len; - } - - /* Fill in the buffer. Start with the macro name. */ - buffer = pfile->macro_buffer; - memcpy (buffer, NODE_NAME (node), NODE_LEN (node)); - buffer += NODE_LEN (node); - - /* Parameter names. */ - if (macro->fun_like) - { - *buffer++ = '('; - for (i = 0; i < macro->paramc; i++) - { - cpp_hashnode *param = macro->params[i]; - - if (param != pfile->spec_nodes.n__VA_ARGS__) - { - memcpy (buffer, NODE_NAME (param), NODE_LEN (param)); - buffer += NODE_LEN (param); - } - - if (i + 1 < macro->paramc) - /* 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++ = ' '; - - /* Expansion tokens. */ - if (macro->count) - { - for (i = 0; i < macro->count; i++) - { - cpp_token *token = ¯o->expansion[i]; - - if (token->flags & PREV_WHITE) - *buffer++ = ' '; - if (token->flags & STRINGIFY_ARG) - *buffer++ = '#'; - - if (token->type == CPP_MACRO_ARG) - { - len = NODE_LEN (macro->params[token->val.arg_no - 1]); - memcpy (buffer, - NODE_NAME (macro->params[token->val.arg_no - 1]), len); - buffer += len; - } - else - buffer = cpp_spell_token (pfile, token, buffer); - - if (token->flags & PASTE_LEFT) - { - *buffer++ = ' '; - *buffer++ = '#'; - *buffer++ = '#'; - /* Next has PREV_WHITE; see _cpp_create_definition. */ - } - } - } - - *buffer = '\0'; - return pfile->macro_buffer; -}