From 278c466207b2d592d8ea21234d6cb228b95bc246 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Wed, 19 Jun 2002 05:40:08 +0000 Subject: [PATCH] cpphash.h (struct cpp_reader): Make date and time strings. * cpphash.h (struct cpp_reader): Make date and time strings. (_cpp_builtin_macro_text, _cpp_copy_replacement_text, _cpp_replacement_text_len): New. * cppinit.c (cpp_create_reader): Update. (init_builtins): Register appropriate builtins for -traditional-cpp. * cppmacro.c (new_number_token): Remove. (_cpp_builtin_macro_text): New. (builtin_macro): Use it. (cpp_macro_definition): Update to handle traditional macros. * cppmain.c (cb_line_change): Don't do column positioning for traditional output. * cpptrad.c (enum ls): Rename ls_fun_macro to ls_fun_open. New state ls_fun_close. (skip_whitespace): Fix. (maybe_start_funlike): Don't set state.parsing_args. (scan_out_logical_line): Remove duplicate error. Use lex_state rather than state.parsing_args. (push_replacement_text): Handle builtins. (_cpp_replacement_text_len, _cpp_copy_replacement_text): New. From-SVN: r54771 --- gcc/ChangeLog | 22 +++++++ gcc/cpphash.h | 11 ++-- gcc/cppinit.c | 11 ++-- gcc/cppmacro.c | 151 ++++++++++++++++++++++++++++--------------------- gcc/cppmain.c | 13 +++-- gcc/cpptrad.c | 132 ++++++++++++++++++++++++++++++++---------- 6 files changed, 234 insertions(+), 106 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 79fec5bfd3b..327cc7c26eb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2002-06-19 Neil Booth + + * cpphash.h (struct cpp_reader): Make date and time strings. + (_cpp_builtin_macro_text, _cpp_copy_replacement_text, + _cpp_replacement_text_len): New. + * cppinit.c (cpp_create_reader): Update. + (init_builtins): Register appropriate builtins for -traditional-cpp. + * cppmacro.c (new_number_token): Remove. + (_cpp_builtin_macro_text): New. + (builtin_macro): Use it. + (cpp_macro_definition): Update to handle traditional macros. + * cppmain.c (cb_line_change): Don't do column positioning for + traditional output. + * cpptrad.c (enum ls): Rename ls_fun_macro to ls_fun_open. New + state ls_fun_close. + (skip_whitespace): Fix. + (maybe_start_funlike): Don't set state.parsing_args. + (scan_out_logical_line): Remove duplicate error. Use lex_state + rather than state.parsing_args. + (push_replacement_text): Handle builtins. + (_cpp_replacement_text_len, _cpp_copy_replacement_text): New. + 2002-06-18 Hans-Peter Nilsson Kaveh R. Ghazi diff --git a/gcc/cpphash.h b/gcc/cpphash.h index 98dfb49ca7c..ee9a47effc4 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -370,9 +370,9 @@ struct cpp_reader for include files. (Altered as we get more of them.) */ unsigned int max_include_len; - /* Date and time tokens. Calculated together if either is requested. */ - cpp_token date; - cpp_token time; + /* Date and time text. Calculated together if either is requested. */ + const uchar *date; + const uchar *time; /* EOF token, and a token forcing paste avoidance. */ cpp_token avoid_paste; @@ -475,7 +475,8 @@ extern bool _cpp_save_parameter PARAMS ((cpp_reader *, cpp_macro *, extern bool _cpp_arguments_ok PARAMS ((cpp_reader *, cpp_macro *, const cpp_hashnode *, unsigned int)); - +extern const uchar *_cpp_builtin_macro_text PARAMS ((cpp_reader *, + cpp_hashnode *)); /* In cpphash.c */ extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *)); extern void _cpp_destroy_hashtable PARAMS ((cpp_reader *)); @@ -532,6 +533,8 @@ extern void _cpp_set_trad_context PARAMS ((cpp_reader *)); extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *)); extern bool _cpp_expansions_different_trad PARAMS ((const cpp_macro *, const cpp_macro *)); +extern uchar *_cpp_copy_replacement_text PARAMS ((const cpp_macro *, uchar *)); +extern size_t _cpp_replacement_text_len PARAMS ((const cpp_macro *)); /* Utility routines and macros. */ #define DSC(str) (const uchar *)str, sizeof str - 1 diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 411dbea1d13..1df4bacb12b 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -512,7 +512,6 @@ cpp_create_reader (lang) pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); /* Set up static tokens. */ - pfile->date.type = CPP_EOF; pfile->avoid_paste.type = CPP_PADDING; pfile->avoid_paste.val.source = NULL; pfile->eof.type = CPP_EOF; @@ -640,6 +639,8 @@ static const struct builtin builtin_array[] = B("__BASE_FILE__", BT_BASE_FILE), B("__LINE__", BT_SPECLINE), B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL), + /* Keep builtins not used for -traditional-cpp at the end, and + update init_builtins() if any more are added. */ B("_Pragma", BT_PRAGMA), B("__STDC__", BT_STDC), }; @@ -684,10 +685,12 @@ init_builtins (pfile) cpp_reader *pfile; { const struct builtin *b; + size_t n = ARRAY_SIZE (builtin_array); - for(b = builtin_array; - b < (builtin_array + ARRAY_SIZE (builtin_array)); - b++) + if (CPP_OPTION (pfile, traditional)) + n -= 2; + + for(b = builtin_array; b < builtin_array + n; b++) { cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len); hp->type = NT_MACRO; diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index 20149ec9b33..99cdc19e007 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -54,7 +54,6 @@ static const cpp_token *padding_token static void expand_arg PARAMS ((cpp_reader *, macro_arg *)); static const cpp_token *new_string_token PARAMS ((cpp_reader *, uchar *, 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 **, @@ -93,24 +92,6 @@ new_string_token (pfile, text, len) 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", @@ -121,19 +102,20 @@ static const char * const monthnames[] = 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) +const uchar * +_cpp_builtin_macro_text (pfile, node) cpp_reader *pfile; cpp_hashnode *node; { - const cpp_token *result; + 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)); - return 0; + break; case BT_FILE: case BT_BASE_FILE: @@ -149,10 +131,12 @@ builtin_macro (pfile, node) 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); + 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; @@ -160,16 +144,18 @@ builtin_macro (pfile, node) /* 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); + 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. */ - result = new_number_token (pfile, - 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. @@ -179,23 +165,20 @@ builtin_macro (pfile, node) value 0. */ case BT_STDC: { - int stdc; enum c_lang lang = CPP_OPTION (pfile, lang); if (CPP_IN_SYSTEM_HEADER (pfile) && CPP_OPTION (pfile, stdc_0_in_system_headers) && !(lang == CLK_STDC89 || lang == CLK_STDC94 || lang == CLK_STDC99)) /* || lang == CLK_CXX98 ? */ - stdc = 0; + number = 0; else - stdc = 1; - - result = new_number_token (pfile, stdc); + number = 1; } break; case BT_DATE: case BT_TIME: - if (pfile->date.type == CPP_EOF) + if (pfile->date == NULL) { /* Allocate __DATE__ and __TIME__ strings from permanent storage. We only do this once, and don't generate them @@ -204,30 +187,46 @@ builtin_macro (pfile, node) 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", + 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.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", + 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); } if (node->value.builtin == BT_DATE) - result = &pfile->date; + result = pfile->date; else - result = &pfile->time; + result = pfile->time; break; + } + + if (result == NULL) + { + /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */ + result = _cpp_unaligned_alloc (pfile, 21); + sprintf ((char *) result, "%u", number); + } + + return result; +} + +/* 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; +{ + const uchar *buf; - case BT_PRAGMA: + 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) @@ -237,7 +236,24 @@ builtin_macro (pfile, node) return 1; } - push_token_context (pfile, NULL, result, 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; } @@ -1598,18 +1614,23 @@ cpp_macro_definition (pfile, node) 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->exp.tokens[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) @@ -1652,8 +1673,10 @@ cpp_macro_definition (pfile, node) 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) { for (i = 0; i < macro->count; i++) { diff --git a/gcc/cppmain.c b/gcc/cppmain.c index 7ebc1ad2c5a..dba64041bf5 100644 --- a/gcc/cppmain.c +++ b/gcc/cppmain.c @@ -320,7 +320,6 @@ cb_line_change (pfile, token, parsing_args) return; maybe_print_line (print.map, token->line); - print.printed = 1; print.prev = 0; print.source = 0; @@ -329,12 +328,16 @@ cb_line_change (pfile, token, parsing_args) will provide a space if PREV_WHITE. Don't bother trying to reconstruct tabs; we can't get it right in general, and nothing ought to care. Some things do care; the fault lies with them. */ - if (token->col > 2) + if (!CPP_OPTION (pfile, traditional)) { - unsigned int spaces = token->col - 2; + print.printed = 1; + if (token->col > 2) + { + unsigned int spaces = token->col - 2; - while (spaces--) - putc (' ', print.outf); + while (spaces--) + putc (' ', print.outf); + } } } diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index b29750dd6c5..1adceaf3271 100644 --- a/gcc/cpptrad.c +++ b/gcc/cpptrad.c @@ -65,7 +65,8 @@ struct fun_macro /* Lexing state. It is mostly used to prevent macro expansion. */ enum ls {ls_none = 0, /* Normal state. */ - ls_fun_macro, /* When looking for '('. */ + ls_fun_open, /* When looking for '('. */ + ls_fun_close, /* When looking for ')'. */ ls_defined, /* After defined. */ ls_defined_close, /* Looking for ')' of defined(). */ ls_hash, /* After # in preprocessor conditional. */ @@ -262,7 +263,7 @@ skip_whitespace (pfile, cur, skip_comments) if (is_nvspace (c) && c) continue; - if (!c && cur != RLIMIT (pfile->context)) + if (!c && cur - 1 != RLIMIT (pfile->context)) continue; if (*cur == '/' && skip_comments) @@ -409,8 +410,6 @@ maybe_start_funlike (pfile, node, start, macro) macro->node = node; macro->offset = start - pfile->out.base; macro->argc = 0; - - pfile->state.parsing_args = 1; } /* Save the OFFSET of the start of the next argument to MACRO. */ @@ -485,19 +484,17 @@ scan_out_logical_line (pfile, macro) cur--; if (!pfile->buffer->from_stage3) cpp_error (pfile, DL_PEDWARN, "no newline at end of file"); - if (pfile->state.parsing_args == 2) - cpp_error (pfile, DL_ERROR, - "unterminated argument list invoking macro \"%s\"", - NODE_NAME (fmacro.node)); pfile->line++; goto done; case '\r': case '\n': cur = handle_newline (pfile, cur - 1); - if (pfile->state.parsing_args == 2 && !pfile->state.in_directive) + if ((lex_state == ls_fun_open || lex_state == ls_fun_close) + && !pfile->state.in_directive) { /* Newlines in arguments become a space. */ - out[-1] = ' '; + if (lex_state == ls_fun_close) + out[-1] = ' '; continue; } goto done; @@ -578,14 +575,17 @@ scan_out_logical_line (pfile, macro) if (node->type == NT_MACRO /* Should we expand for ls_answer? */ - && lex_state == ls_none + && (lex_state == ls_none || lex_state == ls_fun_open) && !pfile->state.prevent_expansion && !recursive_macro (pfile, node)) { - if (node->value.macro->fun_like) + /* Macros invalidate MI optimization. */ + pfile->mi_valid = false; + if (! (node->flags & NODE_BUILTIN) + && node->value.macro->fun_like) { maybe_start_funlike (pfile, node, out_start, &fmacro); - lex_state = ls_fun_macro; + lex_state = ls_fun_open; continue; } else @@ -594,6 +594,7 @@ scan_out_logical_line (pfile, macro) output, and push its replacement text. */ pfile->out.cur = out_start; push_replacement_text (pfile, node); + lex_state = ls_none; goto new_context; } } @@ -622,10 +623,9 @@ scan_out_logical_line (pfile, macro) if (quote == 0) { paren_depth++; - if (lex_state == ls_fun_macro) + if (lex_state == ls_fun_open) { - lex_state = ls_none; - pfile->state.parsing_args = 2; + lex_state = ls_fun_close; paren_depth = 1; out = pfile->out.base + fmacro.offset; fmacro.args[0] = fmacro.offset; @@ -638,7 +638,7 @@ scan_out_logical_line (pfile, macro) break; case ',': - if (quote == 0 && pfile->state.parsing_args == 2 && paren_depth == 1) + if (quote == 0 && lex_state == ls_fun_close && paren_depth == 1) save_argument (&fmacro, out - pfile->out.base); break; @@ -646,11 +646,11 @@ scan_out_logical_line (pfile, macro) if (quote == 0) { paren_depth--; - if (pfile->state.parsing_args == 2 && paren_depth == 0) + if (lex_state == ls_fun_close && paren_depth == 0) { cpp_macro *m = fmacro.node->value.macro; - pfile->state.parsing_args = 0; + lex_state = ls_none; save_argument (&fmacro, out - pfile->out.base); /* A single zero-length argument is no argument. */ @@ -701,12 +701,9 @@ scan_out_logical_line (pfile, macro) /* Some of these transitions of state are syntax errors. The ISO preprocessor will issue errors later. */ - if (lex_state == ls_fun_macro) - { - /* Missing '('. */ - lex_state = ls_none; - pfile->state.parsing_args = 0; - } + if (lex_state == ls_fun_open) + /* Missing '('. */ + lex_state = ls_none; else if (lex_state == ls_hash || lex_state == ls_predicate || lex_state == ls_defined) @@ -722,11 +719,10 @@ scan_out_logical_line (pfile, macro) if (fmacro.buff) _cpp_release_buff (pfile, fmacro.buff); - if (pfile->state.parsing_args == 2) + if (lex_state == ls_fun_close) cpp_error (pfile, DL_ERROR, "unterminated argument list invoking macro \"%s\"", NODE_NAME (fmacro.node)); - pfile->state.parsing_args = 0; } /* Push a context holding the replacement text of the macro NODE on @@ -737,9 +733,22 @@ push_replacement_text (pfile, node) cpp_reader *pfile; cpp_hashnode *node; { - cpp_macro *macro = node->value.macro; + size_t len; + const uchar *text; + + if (node->flags & NODE_BUILTIN) + { + text = _cpp_builtin_macro_text (pfile, node); + len = ustrlen (text); + } + else + { + cpp_macro *macro = node->value.macro; + text = macro->exp.text; + len = macro->count; + } - _cpp_push_text_context (pfile, node, macro->exp.text, macro->count); + _cpp_push_text_context (pfile, node, text, len); } /* Returns TRUE if traditional macro recursion is detected. */ @@ -784,6 +793,71 @@ recursive_macro (pfile, node) return recursing; } +/* Return the length of the replacement text of a function-like or + object-like non-builtin macro. */ +size_t +_cpp_replacement_text_len (macro) + const cpp_macro *macro; +{ + size_t len; + + if (macro->fun_like) + { + const uchar *exp; + + for (exp = macro->exp.text;;) + { + struct block *b = (struct block *) exp; + + len += b->text_len; + if (b->arg_index == 0) + break; + len += NODE_LEN (macro->params[b->arg_index - 1]); + exp += BLOCK_LEN (b->text_len); + } + } + else + len = macro->count; + + return len; +} + +/* Copy the replacement text of MACRO to DEST, which must be of + sufficient size. It is not NUL-terminated. The next character is + returned. */ +uchar * +_cpp_copy_replacement_text (macro, dest) + const cpp_macro *macro; + uchar *dest; +{ + if (macro->fun_like) + { + const uchar *exp; + + for (exp = macro->exp.text;;) + { + struct block *b = (struct block *) exp; + cpp_hashnode *param; + + memcpy (dest, b->text, b->text_len); + dest += b->text_len; + if (b->arg_index == 0) + break; + param = macro->params[b->arg_index - 1]; + memcpy (dest, NODE_NAME (param), NODE_LEN (param)); + dest += NODE_LEN (param); + exp += BLOCK_LEN (b->text_len); + } + } + else + { + memcpy (dest, macro->exp.text, macro->count); + dest += macro->count; + } + + return dest; +} + /* Push a context holding the replacement text of the macro NODE on the context stack. NODE is either object-like, or a function-like macro with no arguments. */ -- 2.30.2