From: Zack Weinberg Date: Fri, 21 Apr 2000 17:18:50 +0000 (+0000) Subject: cpphash.c (struct arg, [...]): Const-ify strings. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9e62c8114f04116b2107809c51bf33ef1a2993c9;p=gcc.git cpphash.c (struct arg, [...]): Const-ify strings. * cpphash.c (struct arg, struct arglist): Const-ify strings. (warn_trad_stringify, duplicate_arg_p): New helper functions. (collect_expansion): Rewrite to scan over a token list. Remove -traditional support. (collect_formal_parameters): Rename to collect_params; rewrite to scan over a token list. (_cpp_create_definition): Adjust to scan a token list. (_cpp_macroexpand): Remove -traditional support. (_cpp_compare_defs): Whitespace is now canonicalized. (comp_def_part): Delete function. * cpphash.h: Update prototypes. * cpplex.c (init_token_list): Don't set lineno if there is no buffer. (pedantic_whitespace): New function. (_cpp_scan_line): Mark tokens that had hspace before. Don't consume a newline. Use pedantic_whitespace. (_cpp_lex_token): Remove support for -traditional macros. (_cpp_get_define_token): Delete. (_cpp_get_directive_token): Do the real work here. Use pedantic_whitespace. (_cpp_init_input_buffer): Initialize pfile->directbuf. * cpplib.c (get_macro_name): Delete. (do_define): Read the entire line into pfile->directbuf, then feed the token list to _cpp_create_definition. * cpplib.h (HSPACE_BEFORE): new define. (struct cpp_reader): Add a toklist member, "directbuf". From-SVN: r33309 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 733d02d43e6..f9ef0700408 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,34 @@ 2000-04-21 Zack Weinberg + * cpphash.c (struct arg, struct arglist): Const-ify strings. + (warn_trad_stringify, duplicate_arg_p): New helper functions. + (collect_expansion): Rewrite to scan over a token list. + Remove -traditional support. + (collect_formal_parameters): Rename to collect_params; rewrite + to scan over a token list. + (_cpp_create_definition): Adjust to scan a token list. + (_cpp_macroexpand): Remove -traditional support. + (_cpp_compare_defs): Whitespace is now canonicalized. + (comp_def_part): Delete function. + + * cpphash.h: Update prototypes. + * cpplex.c (init_token_list): Don't set lineno if there is no + buffer. + (pedantic_whitespace): New function. + (_cpp_scan_line): Mark tokens that had hspace before. Don't + consume a newline. Use pedantic_whitespace. + (_cpp_lex_token): Remove support for -traditional macros. + (_cpp_get_define_token): Delete. + (_cpp_get_directive_token): Do the real work here. Use + pedantic_whitespace. + (_cpp_init_input_buffer): Initialize pfile->directbuf. + + * cpplib.c (get_macro_name): Delete. + (do_define): Read the entire line into pfile->directbuf, then + feed the token list to _cpp_create_definition. + * cpplib.h (HSPACE_BEFORE): new define. + (struct cpp_reader): Add a toklist member, "directbuf". + * predict.c (estimate_probability): New heuristic: if a jump branches around a block with no successors, predict it taken. Disentangle control flow. diff --git a/gcc/cpphash.c b/gcc/cpphash.c index 439cc805f45..c39ca9f5fa6 100644 --- a/gcc/cpphash.c +++ b/gcc/cpphash.c @@ -36,8 +36,6 @@ static int eq_HASHNODE PARAMS ((const void *, const void *)); static void del_HASHNODE PARAMS ((void *)); static int dump_hash_helper PARAMS ((void **, void *)); -static int comp_def_part PARAMS ((int, U_CHAR *, int, U_CHAR *, - int, int)); static void push_macro_expansion PARAMS ((cpp_reader *, U_CHAR *, int, HASHNODE *)); static int unsafe_chars PARAMS ((cpp_reader *, int, int)); @@ -61,21 +59,27 @@ static void special_symbol PARAMS ((HASHNODE *, cpp_reader *)); struct arg { - U_CHAR *name; - int len; + const U_CHAR *name; + unsigned int len; char rest_arg; }; struct arglist { U_CHAR *namebuf; - struct arg *argv; + const struct arg *argv; int argc; }; -static DEFINITION *collect_expansion PARAMS ((cpp_reader *, struct arglist *)); -static struct arglist *collect_formal_parameters PARAMS ((cpp_reader *)); +static DEFINITION *collect_expansion PARAMS ((cpp_reader *, cpp_toklist *, + struct arglist *, unsigned int)); +static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *, + struct arglist *)); + +static void warn_trad_stringify PARAMS ((cpp_reader *, U_CHAR *, size_t, + unsigned int, const struct arg *)); +static int duplicate_arg_p PARAMS ((U_CHAR *, U_CHAR *)); /* This structure represents one parsed argument in a macro call. `raw' points to the argument text as written (`raw_length' is its length). @@ -275,28 +279,64 @@ macro_cleanup (pbuf, pfile) return 0; } +/* Issue warnings for macro argument names seen inside strings. */ +static void +warn_trad_stringify (pfile, p, len, argc, argv) + cpp_reader *pfile; + U_CHAR *p; + size_t len; + unsigned int argc; + const struct arg *argv; + +{ + U_CHAR *limit; + unsigned int i; + + limit = p + len; + for (;;) + { + while (p < limit && !is_idstart (*p)) p++; + if (p >= limit) + break; + + for (i = 0; i < argc; i++) + if (!strncmp (p, argv[i].name, argv[i].len) + && ! is_idchar (p[argv[i].len])) + { + cpp_warning (pfile, + "macro argument \"%s\" would be stringified in traditional C", + argv[i].name); + break; + } + p++; + while (p < limit && is_idchar (*p)) p++; + if (p >= limit) + break; + } +} + /* Read a replacement list for a macro, and build the DEFINITION - structure. ARGLIST specifies the formal parameters to look for in - the text of the definition. If ARGLIST is null, this is an + structure. LIST contains the replacement list, beginning at + REPLACEMENT. ARGLIST specifies the formal parameters to look for + in the text of the definition. If ARGLIST is null, this is an object-like macro; if it points to an empty arglist, this is a - function-like macro with no arguments. - - A good half of this is devoted to supporting -traditional. - Kill me now. */ + function-like macro with no arguments. */ static DEFINITION * -collect_expansion (pfile, arglist) +collect_expansion (pfile, list, arglist, replacement) cpp_reader *pfile; + cpp_toklist *list; struct arglist *arglist; + unsigned int replacement; { DEFINITION *defn; struct reflist *pat = 0, *endpat = 0; enum cpp_ttype token; - long start, here, last; - int i; - int argc; + long start, last; + unsigned int i; + int j, argc; size_t len; - struct arg *argv; + const struct arg *argv; U_CHAR *tok, *exp; enum { START = 0, NORM, ARG, STRIZE, PASTE } last_token = START; @@ -311,15 +351,16 @@ collect_expansion (pfile, arglist) argc = 0; } + /* We copy the expansion text into the token_buffer, then out to + its proper home. */ last = start = CPP_WRITTEN (pfile); - last -= 2; /* two extra chars for the leading escape */ - for (;;) + CPP_PUTS (pfile, "\r ", 2); + + for (i = replacement; i < list->tokens_used; i++) { - /* Macro expansion is off, so we are guaranteed not to see POP - or EOF. */ - here = CPP_WRITTEN (pfile); - token = _cpp_get_define_token (pfile); - tok = pfile->token_buffer + here; + token = list->tokens[i].type; + tok = list->tokens[i].val.name.offset + list->namebuf; + len = list->tokens[i].val.name.len; switch (token) { case CPP_POP: @@ -329,90 +370,54 @@ collect_expansion (pfile, arglist) case CPP_VSPACE: goto done; - case CPP_HSPACE: - if (last_token == STRIZE || last_token == PASTE - || last_token == START) - CPP_SET_WRITTEN (pfile, here); - break; - case CPP_HASH: /* # is not special in object-like macros. It is special in - function-like macros with no args. (6.10.3.2 para 1.) */ - if (arglist == NULL) - goto norm; - /* # is not special immediately after PASTE. - (Implied by 6.10.3.3 para 4.) */ - if (last_token == PASTE) + function-like macros with no args. (6.10.3.2 para 1.) + However, it is not special after PASTE. (Implied by + 6.10.3.3 para 4.) */ + if (arglist == NULL || last_token == PASTE) goto norm; last_token = STRIZE; - CPP_SET_WRITTEN (pfile, here); /* delete from replacement text */ break; case CPP_PASTE: - /* If the last token was an argument, discard this token and - any hspace between it and the argument's position. Then - mark the arg raw_after. */ - if (last_token == ARG) - { - endpat->raw_after = 1; - last_token = PASTE; - CPP_SET_WRITTEN (pfile, last); - break; - } - else if (last_token == PASTE) + if (last_token == PASTE) /* ## ## - the second ## is ordinary. */ goto norm; else if (last_token == START) cpp_error (pfile, "`##' at start of macro definition"); - - /* Discard the token and any hspace before it. */ - while (is_hspace (pfile->token_buffer[here-1])) - here--; - CPP_SET_WRITTEN (pfile, here); - - if (last_token == STRIZE) + + else if (last_token == ARG) + /* If the last token was an argument, mark it raw_after. */ + endpat->raw_after = 1; + else if (last_token == STRIZE) /* Oops - that wasn't a stringify operator. */ CPP_PUTC (pfile, '#'); - last_token = PASTE; - break; - case CPP_COMMENT: - /* We must be in -traditional mode. Pretend this was a - token paste, but only if there was no leading or - trailing space and it's in the middle of the line. - _cpp_lex_token won't return a COMMENT if there was trailing - space. */ - CPP_SET_WRITTEN (pfile, here); - if (last_token == START) - break; - if (is_hspace (pfile->token_buffer[here-1])) - break; - if (last_token == ARG) - endpat->raw_after = 1; last_token = PASTE; break; case CPP_STRING: case CPP_CHAR: - if (last_token == STRIZE) - cpp_error (pfile, "`#' is not followed by a macro argument name"); - - if (CPP_TRADITIONAL (pfile) || CPP_WTRADITIONAL (pfile)) - goto maybe_trad_stringify; - else - goto norm; + if (argc && CPP_WTRADITIONAL (pfile)) + warn_trad_stringify (pfile, tok, len, argc, argv); + goto norm; case CPP_NAME: - for (i = 0; i < argc; i++) - if (!strncmp (tok, argv[i].name, argv[i].len) - && tok + argv[i].len == CPP_PWRITTEN (pfile)) + for (j = 0; j < argc; j++) + if (argv[j].len == len + && !strncmp (tok, argv[j].name, argv[j].len)) goto addref; /* fall through */ default: norm: if (last_token == STRIZE) - cpp_error (pfile, "`#' is not followed by a macro argument name"); + cpp_error (pfile, "# is not followed by a macro argument name"); + if (last_token != PASTE && last_token != START + && (list->tokens[i].flags & HSPACE_BEFORE)) + CPP_PUTC (pfile, ' '); + CPP_PUTS (pfile, tok, len); last_token = NORM; break; } @@ -421,85 +426,27 @@ collect_expansion (pfile, arglist) addref: { struct reflist *tpat; - + if (last_token != PASTE && (list->tokens[i].flags & HSPACE_BEFORE)) + CPP_PUTC (pfile, ' '); + /* Make a pat node for this arg and add it to the pat list */ tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); tpat->next = NULL; tpat->raw_before = (last_token == PASTE); tpat->raw_after = 0; tpat->stringify = (last_token == STRIZE); - tpat->rest_args = argv[i].rest_arg; - tpat->argno = i; - tpat->nchars = here - last; + tpat->rest_args = argv[j].rest_arg; + tpat->argno = j; + tpat->nchars = CPP_WRITTEN (pfile) - last; if (endpat == NULL) pat = tpat; else endpat->next = tpat; endpat = tpat; - last = here; + last = CPP_WRITTEN (pfile); } - CPP_SET_WRITTEN (pfile, here); /* discard arg name */ last_token = ARG; - continue; - - maybe_trad_stringify: - last_token = NORM; - { - U_CHAR *base, *p, *limit; - struct reflist *tpat; - - base = p = pfile->token_buffer + here; - limit = CPP_PWRITTEN (pfile); - - while (++p < limit) - { - if (is_idstart (*p)) - continue; - for (i = 0; i < argc; i++) - if (!strncmp (tok, argv[i].name, argv[i].len) - && ! is_idchar (tok[argv[i].len])) - goto mts_addref; - continue; - - mts_addref: - if (!CPP_TRADITIONAL (pfile)) - { - /* Must have got here because of -Wtraditional. */ - cpp_warning (pfile, - "macro argument `%.*s' would be stringified with -traditional", - (int) argv[i].len, argv[i].name); - continue; - } - if (CPP_WTRADITIONAL (pfile)) - cpp_warning (pfile, "macro argument `%.*s' is stringified", - (int) argv[i].len, argv[i].name); - - /* Remove the argument from the string. */ - memmove (p, p + argv[i].len, limit - (p + argv[i].len)); - limit -= argv[i].len; - - /* Make a pat node for this arg and add it to the pat list */ - tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); - tpat->next = NULL; - - /* Don't attempt to paste this with anything. */ - tpat->raw_before = 0; - tpat->raw_after = 0; - tpat->stringify = 1; - tpat->rest_args = argv[i].rest_arg; - tpat->argno = i; - tpat->nchars = (p - base) + here - last; - - if (endpat == NULL) - pat = tpat; - else - endpat->next = tpat; - endpat = tpat; - last = (p - base) + here; - } - CPP_ADJUST_WRITTEN (pfile, CPP_PWRITTEN (pfile) - limit); - } } done: @@ -508,241 +455,224 @@ collect_expansion (pfile, arglist) else if (last_token == PASTE) cpp_error (pfile, "`##' at end of macro definition"); - if (last_token == START) - { - /* Empty macro definition. */ - exp = (U_CHAR *) xstrdup ("\r \r "); - len = 1; - } - else - { - /* Trim trailing white space from definition. */ - here = CPP_WRITTEN (pfile); - while (here > last && is_hspace (pfile->token_buffer [here-1])) - here--; - CPP_SET_WRITTEN (pfile, here); - len = CPP_WRITTEN (pfile) - start + 1; - /* space for no-concat markers at either end */ - exp = (U_CHAR *) xmalloc (len + 4); - exp[0] = '\r'; - exp[1] = ' '; - exp[len + 1] = '\r'; - exp[len + 2] = ' '; - exp[len + 3] = '\0'; - memcpy (&exp[2], pfile->token_buffer + start, len - 1); - } - + CPP_PUTS (pfile, "\r ", 2); + len = CPP_WRITTEN (pfile) - start; CPP_SET_WRITTEN (pfile, start); + exp = (U_CHAR *) xmalloc (len + 1); + memcpy (exp, pfile->token_buffer + start, len); + exp[len] = '\0'; + defn = (DEFINITION *) xmalloc (sizeof (DEFINITION)); - defn->length = len + 3; + defn->length = len; defn->expansion = exp; defn->pattern = pat; - defn->rest_args = 0; + defn->rest_args = argv && argv[argc - 1].rest_arg; if (arglist) { defn->nargs = argc; defn->argnames = arglist->namebuf; if (argv) - { - defn->rest_args = argv[argc - 1].rest_arg; - free (argv); - } - free (arglist); + free ((PTR) argv); } else { defn->nargs = -1; defn->argnames = 0; - defn->rest_args = 0; } return defn; } -static struct arglist * -collect_formal_parameters (pfile) +/* Is argument NEW, which has just been added to the argument list, + a duplicate of a previous argument name? */ +static int +duplicate_arg_p (args, new) + U_CHAR *args, *new; +{ + size_t newlen = strlen (new) + 1; + size_t oldlen; + + while (args < new) + { + oldlen = strlen (args) + 1; + if (!memcmp (args, new, MIN (oldlen, newlen))) + return 1; + args += oldlen; + } + return 0; +} + +static unsigned int +collect_params (pfile, list, arglist) cpp_reader *pfile; + cpp_toklist *list; + struct arglist *arglist; { - struct arglist *result = 0; struct arg *argv = 0; - U_CHAR *namebuf = (U_CHAR *) xstrdup (""); + U_CHAR *namebuf, *p, *tok; + unsigned int len, argslen; + unsigned int argc, a, i, j; - U_CHAR *name, *tok; - size_t argslen = 1; - int len; - int argc = 0; - int i; - enum cpp_ttype token; - long old_written; - - old_written = CPP_WRITTEN (pfile); - token = _cpp_get_directive_token (pfile); - if (token != CPP_OPEN_PAREN) + /* The formal parameters list starts at token 1. */ + if (list->tokens[1].type != CPP_OPEN_PAREN) { cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters", - token, CPP_OPEN_PAREN); - goto invalid; + list->tokens[1].type, CPP_OPEN_PAREN); + return 0; } - argv = (struct arg *) xmalloc (sizeof (struct arg)); - argv[argc].len = 0; - argv[argc].rest_arg = 0; - for (;;) - { - CPP_SET_WRITTEN (pfile, old_written); - token = _cpp_get_directive_token (pfile); - switch (token) - { - case CPP_NAME: - tok = pfile->token_buffer + old_written; - len = CPP_PWRITTEN (pfile) - tok; - if (namebuf - && (name = (U_CHAR *) strstr (namebuf, tok)) - && name[len] == ',' - && (name == namebuf || name[-1] == ',')) - { - cpp_error (pfile, "duplicate macro argument name `%s'", tok); - continue; - } - if (CPP_PEDANTIC (pfile) && CPP_OPTION (pfile, c99) - && len == sizeof "__VA_ARGS__" - 1 - && !strncmp (tok, "__VA_ARGS__", len)) - cpp_pedwarn (pfile, - "C99 does not permit use of `__VA_ARGS__' as a macro argument name"); - namebuf = (U_CHAR *) xrealloc (namebuf, argslen + len + 1); - name = &namebuf[argslen - 1]; - argslen += len + 1; - - memcpy (name, tok, len); - name[len] = ','; - name[len+1] = '\0'; - argv[argc].len = len; - argv[argc].rest_arg = 0; - break; - - case CPP_COMMA: - argc++; - argv = (struct arg *) xrealloc (argv, (argc + 1)*sizeof(struct arg)); - argv[argc].len = 0; - break; - - case CPP_CLOSE_PAREN: - goto done; + /* Scan once and count the number of parameters; also check for + syntax errors here. */ + argc = 0; + argslen = 0; + for (i = 2; i < list->tokens_used; i++) + switch (list->tokens[i].type) + { + case CPP_NAME: + argslen += list->tokens[i].val.name.len + 1; + argc++; + break; + case CPP_COMMA: + break; + case CPP_CLOSE_PAREN: + goto scanned; + case CPP_VSPACE: + cpp_error_with_line (pfile, list->line, list->tokens[i].col, + "missing right paren in macro argument list"); + return 0; - case CPP_ELLIPSIS: - goto rest_arg; + default: + cpp_error_with_line (pfile, list->line, list->tokens[i].col, + "syntax error in #define"); + return 0; - case CPP_VSPACE: - cpp_error (pfile, "missing right paren in macro argument list"); - goto invalid; + case CPP_ELLIPSIS: + if (list->tokens[i-1].type != CPP_NAME) + { + argslen += sizeof "__VA_ARGS__"; + argc++; + } + i++; + if (list->tokens[i].type != CPP_CLOSE_PAREN) + { + cpp_error_with_line (pfile, list->line, list->tokens[i].col, + "another parameter follows \"...\""); + return 0; + } + goto scanned; + } - default: - cpp_error (pfile, "syntax error in #define"); - goto invalid; - } - } + cpp_ice (pfile, "collect_params: unreachable - i=%d, ntokens=%d, type=%d", + i, list->tokens_used, list->tokens[i-1].type); + return 0; - rest_arg: - /* There are two possible styles for a vararg macro: - the C99 way: #define foo(a, ...) a, __VA_ARGS__ - the gnu way: #define foo(a, b...) a, b - The C99 way can be considered a special case of the gnu way. - There are also some constraints to worry about, but we'll handle - those elsewhere. */ - if (argv[argc].len == 0) + scanned: + if (argc == 0) /* function-like macro, no arguments */ { - if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99)) - cpp_pedwarn (pfile, "C89 does not permit varargs macros"); - - len = sizeof "__VA_ARGS__" - 1; - namebuf = (U_CHAR *) xrealloc (namebuf, argslen + len + 1); - name = &namebuf[argslen - 1]; - argslen += len; - memcpy (name, "__VA_ARGS__", len); - argv[argc].len = len; + arglist->argc = 0; + arglist->argv = 0; + arglist->namebuf = 0; + return i + 1; } - else - if (CPP_PEDANTIC (pfile)) - cpp_pedwarn (pfile, "ISO C does not permit named varargs macros"); - - argv[argc].rest_arg = 1; - - token = _cpp_get_directive_token (pfile); - if (token != CPP_CLOSE_PAREN) + if (argslen == 0) { - cpp_error (pfile, "another parameter follows `...'"); - goto invalid; + cpp_ice (pfile, "collect_params: argc=%d argslen=0", argc); + return 0; } - done: - /* Go through argv and fix up the pointers. */ - len = 0; - for (i = 0; i <= argc; i++) - { - argv[i].name = namebuf + len; - len += argv[i].len + 1; - namebuf[len - 1] = '\0'; - } + /* Now allocate space and copy the suckers. */ + argv = (struct arg *) xmalloc (argc * sizeof (struct arg)); + namebuf = (U_CHAR *) xmalloc (argslen); + p = namebuf; + a = 0; + for (j = 2; j < i; j++) + switch (list->tokens[j].type) + { + case CPP_NAME: + tok = list->tokens[j].val.name.offset + list->namebuf; + len = list->tokens[j].val.name.len; + memcpy (p, tok, len); + p[len] = '\0'; + if (duplicate_arg_p (namebuf, p)) + { + cpp_error (pfile, "duplicate macro argument name \"%s\"", tok); + a++; + break; + } + if (CPP_PEDANTIC (pfile) && CPP_OPTION (pfile, c99) + && len == sizeof "__VA_ARGS__" - 1 + && !strcmp (p, "__VA_ARGS__")) + cpp_pedwarn (pfile, + "C99 does not permit use of __VA_ARGS__ as a macro argument name"); + argv[a].len = len; + argv[a].name = p; + argv[a].rest_arg = 0; + p += len; + a++; + break; - CPP_SET_WRITTEN (pfile, old_written); + case CPP_COMMA: + break; - result = (struct arglist *) xmalloc (sizeof (struct arglist)); - if (namebuf[0] != '\0') - { - result->namebuf = namebuf; - result->argc = argc + 1; - result->argv = argv; - } - else - { - free (namebuf); - result->namebuf = 0; - result->argc = 0; - result->argv = 0; - } + case CPP_ELLIPSIS: + if (list->tokens[j-1].type != CPP_NAME) + { + if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99)) + cpp_pedwarn (pfile, "C89 does not permit varargs macros"); - return result; + argv[a].len = sizeof "__VA_ARGS__" - 1; + argv[a].name = p; + argv[a].rest_arg = 1; + strcpy (p, "__VA_ARGS__"); + } + else + { + if (CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, + "ISO C does not permit named varargs macros"); + argv[a-1].rest_arg = 1; + } + break; - invalid: - if (argv) - free (argv); - if (namebuf) - free (namebuf); - return 0; + default: + cpp_ice (pfile, "collect_params: impossible token type %d", + list->tokens[j].type); + } + + arglist->argc = argc; + arglist->argv = argv; + arglist->namebuf = namebuf; + return i + 1; } -/* Create a DEFINITION node for a macro. The reader's point is just - after the macro name. If FUNLIKE is true, this is a function-like - macro. */ +/* Create a DEFINITION node for a macro. The replacement text + (including formal parameters if present) is in LIST. If FUNLIKE is + true, this is a function-like macro. */ DEFINITION * -_cpp_create_definition (pfile, funlike) +_cpp_create_definition (pfile, list, funlike) cpp_reader *pfile; + cpp_toklist *list; int funlike; { - struct arglist *args = 0; - unsigned int line, col; - const char *file; + struct arglist args; DEFINITION *defn; - - line = CPP_BUF_LINE (CPP_BUFFER (pfile)); - col = CPP_BUF_COL (CPP_BUFFER (pfile)); - file = CPP_BUFFER (pfile)->nominal_fname; + int replacement = 1; /* replacement begins at this token */ if (funlike) { - args = collect_formal_parameters (pfile); - if (args == 0) + replacement = collect_params (pfile, list, &args); + if (replacement == 0) return 0; } - defn = collect_expansion (pfile, args); + defn = collect_expansion (pfile, list, funlike ? &args : 0, replacement); if (defn == 0) return 0; - defn->line = line; - defn->file = file; - defn->col = col; + defn->file = CPP_BUFFER (pfile)->nominal_fname; + defn->line = list->line; + defn->col = list->tokens[0].col; return defn; } @@ -1098,11 +1028,8 @@ _cpp_macroexpand (pfile, hp) } else if (i < nargs) { - /* traditional C allows foo() if foo wants one argument. */ - if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile)) - ; /* the rest args token is allowed to absorb 0 tokens */ - else if (i == nargs - 1 && defn->rest_args) + if (i == nargs - 1 && defn->rest_args) rest_zero = 1; else if (i == 0) cpp_error (pfile, "macro `%s' used without args", hp->name); @@ -1158,8 +1085,7 @@ _cpp_macroexpand (pfile, hp) int need_space = -1; i = 0; arg->stringified = CPP_WRITTEN (pfile); - if (!CPP_TRADITIONAL (pfile)) - CPP_PUTC (pfile, '\"'); /* insert beginning quote */ + CPP_PUTC (pfile, '\"'); /* insert beginning quote */ for (; i < arglen; i++) { c = (ARG_BASE + arg->raw)[i]; @@ -1214,14 +1140,13 @@ _cpp_macroexpand (pfile, hp) CPP_ADJUST_WRITTEN (pfile, 4); } } - if (!CPP_TRADITIONAL (pfile)) - CPP_PUTC (pfile, '\"'); /* insert ending quote */ + CPP_PUTC (pfile, '\"'); /* insert ending quote */ arg->stringified_length = CPP_WRITTEN (pfile) - arg->stringified; } xbuf_len += args[ap->argno].stringified_length; } - else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile)) + else if (ap->raw_before || ap->raw_after) /* Add 4 for two \r-space markers to prevent token concatenation. */ xbuf_len += args[ap->argno].raw_length + 4; @@ -1288,7 +1213,7 @@ _cpp_macroexpand (pfile, hp) arg->stringified_length); totlen += arg->stringified_length; } - else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile)) + else if (ap->raw_before || ap->raw_after) { U_CHAR *p1 = ARG_BASE + arg->raw; U_CHAR *l1 = p1 + arg->raw_length; @@ -1340,7 +1265,6 @@ _cpp_macroexpand (pfile, hp) { U_CHAR *expanded = ARG_BASE + arg->expanded; if (!ap->raw_before && totlen > 0 && arg->expand_length - && !CPP_TRADITIONAL (pfile) && unsafe_chars (pfile, xbuf[totlen - 1], expanded[0])) { xbuf[totlen++] = '\r'; @@ -1351,7 +1275,6 @@ _cpp_macroexpand (pfile, hp) totlen += arg->expand_length; if (!ap->raw_after && totlen > 0 && offset < defn->length - && !CPP_TRADITIONAL (pfile) && unsafe_chars (pfile, xbuf[totlen - 1], exp[offset])) { xbuf[totlen++] = '\r'; @@ -1394,12 +1317,8 @@ _cpp_macroexpand (pfile, hp) /* Pop the space we've used in the token_buffer for argument expansion. */ CPP_SET_WRITTEN (pfile, old_written); - /* Recursive macro use sometimes works traditionally. - #define foo(x,y) bar (x (y,0), y) - foo (foo, baz) */ - - if (!CPP_TRADITIONAL (pfile)) - hp->type = T_DISABLED; + /* Per C89, a macro cannot be expanded recursively. */ + hp->type = T_DISABLED; } /* Return 1 iff a token ending in C1 followed directly by a token C2 @@ -1520,12 +1439,11 @@ _cpp_compare_defs (pfile, d1, d2) DEFINITION *d1, *d2; { struct reflist *a1, *a2; - U_CHAR *p1 = d1->expansion; - U_CHAR *p2 = d2->expansion; - int first = 1; if (d1->nargs != d2->nargs) return 1; + if (strcmp (d1->expansion, d2->expansion)) + return 1; if (CPP_PEDANTIC (pfile) && d1->argnames && d2->argnames) { @@ -1545,74 +1463,17 @@ _cpp_compare_defs (pfile, d1, d2) for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2; a1 = a1->next, a2 = a2->next) { - if (!((a1->nchars == a2->nchars && !strncmp (p1, p2, a1->nchars)) - || !comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0)) + if (a1->nchars != a2->nchars || a1->argno != a2->argno || a1->stringify != a2->stringify || a1->raw_before != a2->raw_before || a1->raw_after != a2->raw_after) return 1; - first = 0; - p1 += a1->nchars; - p2 += a2->nchars; } if (a1 != a2) return 1; - return comp_def_part (first, p1, d1->length - (p1 - d1->expansion), - p2, d2->length - (p2 - d2->expansion), 1); -} - -/* Return 1 if two parts of two macro definitions are effectively different. - One of the parts starts at BEG1 and has LEN1 chars; - the other has LEN2 chars at BEG2. - Any sequence of whitespace matches any other sequence of whitespace. - FIRST means these parts are the first of a macro definition; - so ignore leading whitespace entirely. - LAST means these parts are the last of a macro definition; - so ignore trailing whitespace entirely. */ - -static int -comp_def_part (first, beg1, len1, beg2, len2, last) - int first; - U_CHAR *beg1, *beg2; - int len1, len2; - int last; -{ - register U_CHAR *end1 = beg1 + len1; - register U_CHAR *end2 = beg2 + len2; - if (first) - { - while (beg1 != end1 && is_space(*beg1)) - beg1++; - while (beg2 != end2 && is_space(*beg2)) - beg2++; - } - if (last) - { - while (beg1 != end1 && is_space(end1[-1])) - end1--; - while (beg2 != end2 && is_space(end2[-1])) - end2--; - } - while (beg1 != end1 && beg2 != end2) - { - if (is_space(*beg1) && is_space(*beg2)) - { - while (beg1 != end1 && is_space(*beg1)) - beg1++; - while (beg2 != end2 && is_space(*beg2)) - beg2++; - } - else if (*beg1 == *beg2) - { - beg1++; - beg2++; - } - else - break; - } - return (beg1 != end1) || (beg2 != end2); + return 0; } /* Dump the definition of macro MACRO on stdout. The format is suitable diff --git a/gcc/cpphash.h b/gcc/cpphash.h index b0ac3c654b7..2b8a5d1fa1a 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -272,7 +272,8 @@ extern HASHNODE **_cpp_lookup_slot PARAMS ((cpp_reader *, enum insert_option, unsigned long *)); extern void _cpp_free_definition PARAMS ((DEFINITION *)); -extern DEFINITION *_cpp_create_definition PARAMS ((cpp_reader *, int)); +extern DEFINITION *_cpp_create_definition PARAMS ((cpp_reader *, + cpp_toklist *, int)); extern void _cpp_dump_definition PARAMS ((cpp_reader *, const U_CHAR *, long, DEFINITION *)); extern int _cpp_compare_defs PARAMS ((cpp_reader *, DEFINITION *, diff --git a/gcc/cpplex.c b/gcc/cpplex.c index deae87e9447..effb6ca0510 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -57,6 +57,8 @@ static void bump_column PARAMS ((cpp_printer *, unsigned int, static void expand_name_space PARAMS ((cpp_toklist *)); static void expand_token_space PARAMS ((cpp_toklist *)); static void init_token_list PARAMS ((cpp_reader *, cpp_toklist *, int)); +static void pedantic_whitespace PARAMS ((cpp_reader *, U_CHAR *, + unsigned int)); /* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */ @@ -474,7 +476,8 @@ init_token_list (pfile, list, recycle) list->namebuf = (unsigned char *) xmalloc (list->name_cap); } - list->line = pfile->buffer->lineno; + if (pfile->buffer) + list->line = pfile->buffer->lineno; list->dir_handler = 0; list->dir_flags = 0; } @@ -490,11 +493,13 @@ _cpp_scan_line (pfile, list) int i, col; long written, len; enum cpp_ttype type; + int space_before; init_token_list (pfile, list, 1); written = CPP_WRITTEN (pfile); i = 0; + space_before = 0; for (;;) { col = CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base; @@ -502,17 +507,26 @@ _cpp_scan_line (pfile, list) len = CPP_WRITTEN (pfile) - written; CPP_SET_WRITTEN (pfile, written); if (type == CPP_HSPACE) - continue; + { + if (CPP_PEDANTIC (pfile)) + pedantic_whitespace (pfile, pfile->token_buffer + written, len); + space_before = 1; + continue; + } if (list->tokens_used >= list->tokens_cap) expand_token_space (list); if (list->name_used + len >= list->name_cap) expand_name_space (list); + if (type == CPP_MACRO) + type = CPP_NAME; + list->tokens_used++; list->tokens[i].type = type; list->tokens[i].col = col; - + list->tokens[i].flags = space_before ? HSPACE_BEFORE : 0; + if (type == CPP_VSPACE) break; @@ -521,8 +535,12 @@ _cpp_scan_line (pfile, list) memcpy (list->namebuf + list->name_used, CPP_PWRITTEN (pfile), len); list->name_used += len; i++; + space_before = 0; } list->tokens[i].aux = CPP_BUFFER (pfile)->lineno + 1; + + /* XXX Temporary kluge: put back the newline. */ + FORWARD(-1); } @@ -1034,14 +1052,8 @@ _cpp_lex_token (pfile) For -traditional, a comment is equivalent to nothing. */ if (!CPP_OPTION (pfile, discard_comments)) return CPP_COMMENT; - else if (CPP_TRADITIONAL (pfile) - && ! is_space (PEEKC ())) - { - if (pfile->parsing_define_directive) - return CPP_COMMENT; - else - goto get_next; - } + else if (CPP_TRADITIONAL (pfile)) + goto get_next; else { CPP_PUTC (pfile, c); @@ -1060,7 +1072,7 @@ _cpp_lex_token (pfile) return CPP_OTHER; } - if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile)) + if (pfile->parsing_define_directive) { c2 = PEEKC (); if (c2 == '#') @@ -1510,6 +1522,26 @@ maybe_macroexpand (pfile, written) return 1; } +/* Complain about \v or \f in a preprocessing directive (constraint + violation, C99 6.10 para 5). Caller has checked CPP_PEDANTIC. */ +static void +pedantic_whitespace (pfile, p, len) + cpp_reader *pfile; + U_CHAR *p; + unsigned int len; +{ + while (len) + { + if (*p == '\v') + cpp_pedwarn (pfile, "vertical tab in preprocessing directive"); + else if (*p == '\f') + cpp_pedwarn (pfile, "form feed in preprocessing directive"); + p++; + len--; + } +} + + enum cpp_ttype cpp_get_token (pfile) cpp_reader *pfile; @@ -1591,14 +1623,10 @@ cpp_get_non_space_token (pfile) } /* Like cpp_get_token, except that it does not execute directives, - does not consume vertical space, and automatically pops off macro - buffers. - - XXX This function will exist only till collect_expansion doesn't - need to see whitespace anymore, then it'll be merged with - _cpp_get_directive_token (below). */ + does not consume vertical space, discards horizontal space, and + automatically pops off macro buffers. */ enum cpp_ttype -_cpp_get_define_token (pfile) +_cpp_get_directive_token (pfile) cpp_reader *pfile; { long old_written; @@ -1620,18 +1648,10 @@ _cpp_get_define_token (pfile) case CPP_HSPACE: if (CPP_PEDANTIC (pfile)) - { - U_CHAR *p, *limit; - p = pfile->token_buffer + old_written; - limit = CPP_PWRITTEN (pfile); - while (p < limit) - { - if (*p == '\v' || *p == '\f') - cpp_pedwarn (pfile, "%s in preprocessing directive", - *p == '\f' ? "formfeed" : "vertical tab"); - p++; - } - } + pedantic_whitespace (pfile, pfile->token_buffer + old_written, + CPP_WRITTEN (pfile) - old_written); + CPP_SET_WRITTEN (pfile, old_written); + goto get_next; return CPP_HSPACE; case CPP_DIRECTIVE: @@ -1660,23 +1680,6 @@ _cpp_get_define_token (pfile) } } -/* Just like _cpp_get_define_token except that it discards horizontal - whitespace. */ - -enum cpp_ttype -_cpp_get_directive_token (pfile) - cpp_reader *pfile; -{ - int old_written = CPP_WRITTEN (pfile); - for (;;) - { - enum cpp_ttype token = _cpp_get_define_token (pfile); - if (token != CPP_COMMENT && token != CPP_HSPACE) - return token; - CPP_SET_WRITTEN (pfile, old_written); - } -} - /* Determine the current line and column. Used only by read_and_prescan. */ static U_CHAR * find_position (start, limit, linep) @@ -2008,6 +2011,7 @@ _cpp_init_input_buffer (pfile) U_CHAR *tmp; init_chartab (); + init_token_list (pfile, &pfile->directbuf, 0); /* Determine the appropriate size for the input buffer. Normal C source files are smaller than eight K. */ diff --git a/gcc/cpplib.c b/gcc/cpplib.c index fb6b7709949..f8815842f58 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -66,7 +66,6 @@ static int read_line_number PARAMS ((cpp_reader *, int *)); static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *)); static int consider_directive_while_skipping PARAMS ((cpp_reader *, IF_STACK *)); -static int get_macro_name PARAMS ((cpp_reader *)); /* Values for the flags field of the table below. KANDR and COND directives come from traditional (K&R) C. The difference is, if we @@ -310,36 +309,6 @@ pass_thru_directive (buf, len, pfile, keyword) CPP_PUTS_Q (pfile, buf, len); } -/* Subroutine of do_define: determine the name of the macro to be - defined. */ - -static int -get_macro_name (pfile) - cpp_reader *pfile; -{ - long here, len; - - here = CPP_WRITTEN (pfile); - if (_cpp_get_directive_token (pfile) != CPP_NAME) - { - cpp_error (pfile, "`#define' must be followed by an identifier"); - goto invalid; - } - - len = CPP_WRITTEN (pfile) - here; - if (len == 7 && !strncmp (pfile->token_buffer + here, "defined", 7)) - { - cpp_error (pfile, "`defined' is not a legal macro name"); - goto invalid; - } - - return len; - - invalid: - _cpp_skip_rest_of_line (pfile); - return 0; -} - /* Process a #define command. */ static int @@ -348,47 +317,60 @@ do_define (pfile) { HASHNODE **slot; DEFINITION *def = 0; - long here; unsigned long hash; int len; int funlike = 0, empty = 0; U_CHAR *sym; - enum cpp_ttype token; + cpp_toklist *list = &pfile->directbuf; pfile->no_macro_expand++; pfile->parsing_define_directive++; CPP_OPTION (pfile, discard_comments)++; - here = CPP_WRITTEN (pfile); - len = get_macro_name (pfile); - if (len == 0) - goto out; + _cpp_scan_line (pfile, list); - /* Copy out the name so we can pop the token buffer. */ - len = CPP_WRITTEN (pfile) - here; - sym = (U_CHAR *) alloca (len + 1); - memcpy (sym, pfile->token_buffer + here, len); - sym[len] = '\0'; + /* First token on the line must be a NAME. There must be at least + one token (the VSPACE at the end). */ + if (list->tokens[0].type != CPP_NAME) + { + cpp_error_with_line (pfile, list->line, list->tokens[0].col, + "#define must be followed by an identifier"); + goto out; + } + + sym = list->namebuf + list->tokens[0].val.name.offset; + len = list->tokens[0].val.name.len; + + /* That NAME is not allowed to be "defined". (Not clear if the + standard requires this.) */ + if (len == 7 && !strncmp (sym, "defined", 7)) + { + cpp_error_with_line (pfile, list->line, list->tokens[0].col, + "\"defined\" is not a legal macro name"); + goto out; + } + + + if (list->tokens_used == 2 && list->tokens[1].type == CPP_VSPACE) + empty = 0; /* Empty definition of object-like macro. */ /* If the next character, with no intervening whitespace, is '(', - then this is a function-like macro. - XXX Layering violation. */ - CPP_SET_MARK (pfile); - token = _cpp_get_directive_token (pfile); - if (token == CPP_VSPACE) - empty = 0; /* Empty definition of object like macro. */ - else if (token == CPP_OPEN_PAREN && ADJACENT_TO_MARK (pfile)) - funlike = 1; - else if (ADJACENT_TO_MARK (pfile)) - /* If this is an object-like macro, C99 requires white space after - the name. */ - cpp_pedwarn (pfile, "missing white space after `#define %.*s'", len, sym); - CPP_GOTO_MARK (pfile); - CPP_SET_WRITTEN (pfile, here); + then this is a function-like macro. Otherwise it is an object- + like macro, and C99 requires whitespace after the name + (6.10.3 para 3). */ + else if (!(list->tokens[1].flags & HSPACE_BEFORE)) + { + if (list->tokens[1].type == CPP_OPEN_PAREN) + funlike = 1; + else + cpp_pedwarn (pfile, + "The C standard requires whitespace after #define %.*s", + len, sym); + } if (! empty) { - def = _cpp_create_definition (pfile, funlike); + def = _cpp_create_definition (pfile, list, funlike); if (def == 0) goto out; } diff --git a/gcc/cpplib.h b/gcc/cpplib.h index 6e3561ac01b..764d8e6c9e3 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -135,6 +135,9 @@ struct cpp_name unsigned int offset; /* from list->namebuf */ }; +/* Per token flags. */ +#define HSPACE_BEFORE (1 << 0) /* token preceded by hspace */ + /* A preprocessing token. This has been carefully packed and should occupy 16 bytes on both 32- and 64-bit hosts. */ @@ -146,7 +149,7 @@ struct cpp_token #else unsigned char type; #endif - unsigned char flags; /* flags - not presently used */ + unsigned char flags; /* flags - see above */ unsigned int aux; /* hash of a NAME, or something - see uses in the code */ union @@ -435,8 +438,12 @@ struct cpp_options struct cpp_reader { + /* Top of buffer stack. */ cpp_buffer *buffer; + /* Token list used by get_directive_token. */ + cpp_toklist directbuf; + /* A buffer used for both for cpp_get_token's output, and also internally. */ unsigned char *token_buffer; /* Allocated size of token_buffer. CPP_RESERVE allocates space. */