From 21b11495d75df8fd0e5b23f0176f6aa676875055 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Thu, 9 Sep 2004 19:16:56 +0000 Subject: [PATCH] cpplib.h (TTYPE_TABLE): Remove CPP_ and SPELL_ prefixes throughout. 2004-09-09 Matt Austern Zack Weinberg * include/cpplib.h (TTYPE_TABLE): Remove CPP_ and SPELL_ prefixes throughout. Add entry for PRAGMA. Remove unnecessary "= 0" from EQ. (enum cpp_ttype): Adjust OP and TK definitions to restore prefixes, via token-paste. (CPP_LAST_EQ, CPP_FIRST_DIGRAPH, CPP_LAST_PUNCTUATOR, CPP_LAST_CPP_OP): Change from #defines to additional cpp_ttype enumerators. (struct cpp_options): Add defer_pragmas. (cpp_handle_deferred_pragma): Prototype new interface. * internal.h (struct cpp_reader): Add directive_result. * directives.c (struct pragma_entry): Add is_internal field; give boolean fields type bool. (start_directive): Initialize pfile->directive_result.type. (_cpp_do__Pragma): Likewise. (run_directive): Do not crash if pfile->buffer->prev is NULL. (insert_pragma_entry): Add 'internal' argument; set new->is_internal from it. (register_pragma): New static function, bulk of former cpp_register_pragma here; add 'internal' argument, pass along to insert_pragma_entry. (cpp_register_pragma): Now a wrapper around register_pragma which always passes false for 'internal' argument. (_cpp_init_internal_pragmas): Call register_pragma directly, passing true for 'internal'. (do_pragma): If CPP_OPTION (pfile, defer_pragmas) and this isn't an internal pragma, save text till the end of the line as a CPP_PRAGMA token instead of executing the pragma. (cpp_handle_deferred_pragma): New interface. * lex.c (token_spellings): Adjust OP and TK definitions to match changes to cpplib.h. (_cpp_lex_token): Check for a directive-result token and return it if present. (cpp_token_val_index): Handle CPP_PRAGMA. * macro.c (cpp_builtin_macro_text): Correct comment. (builtin_macro): Handle directive-result tokens from _cpp_do__Pragma. From-SVN: r87247 --- libcpp/ChangeLog | 44 +++++++++- libcpp/directives.c | 107 ++++++++++++++++++---- libcpp/include/cpplib.h | 190 +++++++++++++++++++++------------------- libcpp/internal.h | 3 + libcpp/lex.c | 17 +++- libcpp/macro.c | 17 ++-- 6 files changed, 258 insertions(+), 120 deletions(-) diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 131f1881108..7090249bd8a 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,43 @@ +2004-09-09 Matt Austern + Zack Weinberg + + * include/cpplib.h (TTYPE_TABLE): Remove CPP_ and SPELL_ + prefixes throughout. Add entry for PRAGMA. Remove + unnecessary "= 0" from EQ. + (enum cpp_ttype): Adjust OP and TK definitions to restore + prefixes, via token-paste. + (CPP_LAST_EQ, CPP_FIRST_DIGRAPH, CPP_LAST_PUNCTUATOR, CPP_LAST_CPP_OP): + Change from #defines to additional cpp_ttype enumerators. + (struct cpp_options): Add defer_pragmas. + (cpp_handle_deferred_pragma): Prototype new interface. + + * internal.h (struct cpp_reader): Add directive_result. + * directives.c (struct pragma_entry): Add is_internal field; + give boolean fields type bool. + (start_directive): Initialize pfile->directive_result.type. + (_cpp_do__Pragma): Likewise. + (run_directive): Do not crash if pfile->buffer->prev is NULL. + (insert_pragma_entry): Add 'internal' argument; set new->is_internal + from it. + (register_pragma): New static function, bulk of former + cpp_register_pragma here; add 'internal' argument, pass along + to insert_pragma_entry. + (cpp_register_pragma): Now a wrapper around register_pragma which + always passes false for 'internal' argument. + (_cpp_init_internal_pragmas): Call register_pragma directly, passing + true for 'internal'. + (do_pragma): If CPP_OPTION (pfile, defer_pragmas) and this isn't + an internal pragma, save text till the end of the line as a CPP_PRAGMA + token instead of executing the pragma. + (cpp_handle_deferred_pragma): New interface. + * lex.c (token_spellings): Adjust OP and TK definitions to + match changes to cpplib.h. + (_cpp_lex_token): Check for a directive-result token and + return it if present. + (cpp_token_val_index): Handle CPP_PRAGMA. + * macro.c (cpp_builtin_macro_text): Correct comment. + (builtin_macro): Handle directive-result tokens from _cpp_do__Pragma. + 2004-09-06 Serge Belyshev PR preprocessor/14699 @@ -38,9 +78,9 @@ * macro.c: Likewise. * cpplib.h (cpp_deps_style): Export enum with name. -2004-07-23 Matthias Klose +2004-07-23 Matthias Klose - * init.c (init_library): Use PACKAGE for the text domain. + * init.c (init_library): Use PACKAGE for the text domain. 2004-07-16 Andris Pavenis diff --git a/libcpp/directives.c b/libcpp/directives.c index 76055a6fc3a..b2b6b32e6c1 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -44,7 +44,8 @@ struct pragma_entry { struct pragma_entry *next; const cpp_hashnode *pragma; /* Name and length. */ - int is_nspace; + bool is_nspace; + bool is_internal; union { pragma_cb handler; struct pragma_entry *space; @@ -106,7 +107,10 @@ static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *, static struct pragma_entry *insert_pragma_entry (cpp_reader *, struct pragma_entry **, const cpp_hashnode *, - pragma_cb); + pragma_cb, + bool); +static void register_pragma (cpp_reader *, const char *, const char *, + pragma_cb, bool); static int count_registered_pragmas (struct pragma_entry *); static char ** save_registered_pragmas (struct pragma_entry *, char **); static char ** restore_registered_pragmas (cpp_reader *, struct pragma_entry *, @@ -219,6 +223,7 @@ start_directive (cpp_reader *pfile) /* Setup in-directive state. */ pfile->state.in_directive = 1; pfile->state.save_comments = 0; + pfile->directive_result.type = CPP_PADDING; /* Some handlers need the position of the # for diagnostics. */ pfile->directive_line = pfile->line_table->highest_line; @@ -442,7 +447,7 @@ run_directive (cpp_reader *pfile, int dir_no, const char *buf, size_t count) cpp_push_buffer (pfile, (const uchar *) buf, count, /* from_stage3 */ true); /* Disgusting hack. */ - if (dir_no == T_PRAGMA) + if (dir_no == T_PRAGMA && pfile->buffer->prev) pfile->buffer->file = pfile->buffer->prev->file; start_directive (pfile); @@ -954,10 +959,12 @@ lookup_pragma_entry (struct pragma_entry *chain, const cpp_hashnode *pragma) /* Create and insert a pragma entry for NAME at the beginning of a singly-linked CHAIN. If handler is NULL, it is a namespace, - otherwise it is a pragma and its handler. */ + otherwise it is a pragma and its handler. If INTERNAL is true + this pragma is being inserted by libcpp itself. */ static struct pragma_entry * insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain, - const cpp_hashnode *pragma, pragma_cb handler) + const cpp_hashnode *pragma, pragma_cb handler, + bool internal) { struct pragma_entry *new; @@ -975,6 +982,7 @@ insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain, new->u.space = NULL; } + new->is_internal = internal; new->next = *chain; *chain = new; return new; @@ -982,10 +990,12 @@ insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain, /* Register a pragma NAME in namespace SPACE. If SPACE is null, it goes in the global namespace. HANDLER is the handler it will call, - which must be non-NULL. */ -void -cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name, - pragma_cb handler) + which must be non-NULL. INTERNAL is true if this is a pragma + registered by cpplib itself, false if it is registered via + cpp_register_pragma */ +static void +register_pragma (cpp_reader *pfile, const char *space, const char *name, + pragma_cb handler, bool internal) { struct pragma_entry **chain = &pfile->pragmas; struct pragma_entry *entry; @@ -999,7 +1009,7 @@ cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name, node = cpp_lookup (pfile, U space, strlen (space)); entry = lookup_pragma_entry (*chain, node); if (!entry) - entry = insert_pragma_entry (pfile, chain, node, NULL); + entry = insert_pragma_entry (pfile, chain, node, NULL, internal); else if (!entry->is_nspace) goto clash; chain = &entry->u.space; @@ -1022,7 +1032,17 @@ cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name, cpp_error (pfile, CPP_DL_ICE, "#pragma %s is already registered", name); } else - insert_pragma_entry (pfile, chain, node, handler); + insert_pragma_entry (pfile, chain, node, handler, internal); +} + +/* Register a pragma NAME in namespace SPACE. If SPACE is null, it + goes in the global namespace. HANDLER is the handler it will call, + which must be non-NULL. This function is exported from libcpp. */ +void +cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name, + pragma_cb handler) +{ + register_pragma (pfile, space, name, handler, false); } /* Register the pragmas the preprocessor itself handles. */ @@ -1030,12 +1050,12 @@ void _cpp_init_internal_pragmas (cpp_reader *pfile) { /* Pragmas in the global namespace. */ - cpp_register_pragma (pfile, 0, "once", do_pragma_once); + register_pragma (pfile, 0, "once", do_pragma_once, true); /* New GCC-specific pragmas should be put in the GCC namespace. */ - cpp_register_pragma (pfile, "GCC", "poison", do_pragma_poison); - cpp_register_pragma (pfile, "GCC", "system_header", do_pragma_system_header); - cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency); + register_pragma (pfile, "GCC", "poison", do_pragma_poison, true); + register_pragma (pfile, "GCC", "system_header", do_pragma_system_header, true); + register_pragma (pfile, "GCC", "dependency", do_pragma_dependency, true); } /* Return the number of registered pragmas in PE. */ @@ -1113,7 +1133,11 @@ _cpp_restore_pragma_names (cpp_reader *pfile, char **saved) front end. C99 defines three pragmas and says that no macro expansion is to be performed on them; whether or not macro expansion happens for other pragmas is implementation defined. - This implementation never macro-expands the text after #pragma. */ + This implementation never macro-expands the text after #pragma. + + The library user has the option of deferring execution of + #pragmas not handled by cpplib, in which case they are converted + to CPP_PRAGMA tokens and inserted into the output stream. */ static void do_pragma (cpp_reader *pfile) { @@ -1138,7 +1162,7 @@ do_pragma (cpp_reader *pfile) } } - if (p) + if (p && (p->is_internal || !CPP_OPTION (pfile, defer_pragmas))) { /* Since the handler below doesn't get the line number, that it might need for diagnostics, make sure it has the right @@ -1147,6 +1171,31 @@ do_pragma (cpp_reader *pfile) (*pfile->cb.line_change) (pfile, pragma_token, false); (*p->u.handler) (pfile); } + else if (CPP_OPTION (pfile, defer_pragmas)) + { + /* Squirrel away the pragma text. Pragmas are newline-terminated. */ + const uchar *line_start, *line_end; + uchar *s; + cpp_string body; + cpp_token *ptok; + + _cpp_backup_tokens (pfile, count); + line_start = CPP_BUFFER (pfile)->cur; + line_end = ustrchr (line_start, '\n'); + + body.len = (line_end - line_start) + 1; + s = _cpp_unaligned_alloc (pfile, body.len + 1); + memcpy (s, line_start, body.len); + s[body.len] = '\0'; + body.text = s; + + /* Create a CPP_PRAGMA token. */ + ptok = &pfile->directive_result; + ptok->src_loc = pragma_token->src_loc; + ptok->type = CPP_PRAGMA; + ptok->flags = pragma_token->flags | NO_EXPAND; + ptok->val.str = body; + } else if (pfile->cb.def_pragma) { _cpp_backup_tokens (pfile, count); @@ -1350,6 +1399,7 @@ void _cpp_do__Pragma (cpp_reader *pfile) { const cpp_token *string = get__Pragma_string (pfile); + pfile->directive_result.type = CPP_PADDING; if (string) destringize_and_run (pfile, &string->val.str); @@ -1358,6 +1408,29 @@ _cpp_do__Pragma (cpp_reader *pfile) "_Pragma takes a parenthesized string literal"); } +/* Handle a pragma that the front end deferred until now. */ +void +cpp_handle_deferred_pragma (cpp_reader *pfile, const cpp_string *s) +{ + cpp_context *saved_context = pfile->context; + cpp_token *saved_cur_token = pfile->cur_token; + tokenrun *saved_cur_run = pfile->cur_run; + bool saved_defer_pragmas = CPP_OPTION (pfile, defer_pragmas); + + pfile->context = XNEW (cpp_context); + pfile->context->macro = 0; + pfile->context->prev = 0; + CPP_OPTION (pfile, defer_pragmas) = false; + + run_directive (pfile, T_PRAGMA, s->text, s->len); + + XDELETE (pfile->context); + pfile->context = saved_context; + pfile->cur_token = saved_cur_token; + pfile->cur_run = saved_cur_run; + CPP_OPTION (pfile, defer_pragmas) = saved_defer_pragmas; +} + /* Ignore #sccs on all systems. */ static void do_sccs (cpp_reader *pfile ATTRIBUTE_UNUSED) diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 547364112f6..4ee626ecd1c 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -52,101 +52,102 @@ struct _cpp_file; '='. The lexer needs operators ending in '=', like ">>=", to be in the same order as their counterparts without the '=', like ">>". */ -/* Positions in the table. */ -#define CPP_LAST_EQ CPP_MAX -#define CPP_FIRST_DIGRAPH CPP_HASH -#define CPP_LAST_PUNCTUATOR CPP_DOT_STAR -#define CPP_LAST_CPP_OP CPP_LESS_EQ - -#define TTYPE_TABLE \ - OP(CPP_EQ = 0, "=") \ - OP(CPP_NOT, "!") \ - OP(CPP_GREATER, ">") /* compare */ \ - OP(CPP_LESS, "<") \ - OP(CPP_PLUS, "+") /* math */ \ - OP(CPP_MINUS, "-") \ - OP(CPP_MULT, "*") \ - OP(CPP_DIV, "/") \ - OP(CPP_MOD, "%") \ - OP(CPP_AND, "&") /* bit ops */ \ - OP(CPP_OR, "|") \ - OP(CPP_XOR, "^") \ - OP(CPP_RSHIFT, ">>") \ - OP(CPP_LSHIFT, "<<") \ - OP(CPP_MIN, "?") \ -\ - OP(CPP_COMPL, "~") \ - OP(CPP_AND_AND, "&&") /* logical */ \ - OP(CPP_OR_OR, "||") \ - OP(CPP_QUERY, "?") \ - OP(CPP_COLON, ":") \ - OP(CPP_COMMA, ",") /* grouping */ \ - OP(CPP_OPEN_PAREN, "(") \ - OP(CPP_CLOSE_PAREN, ")") \ - TK(CPP_EOF, SPELL_NONE) \ - OP(CPP_EQ_EQ, "==") /* compare */ \ - OP(CPP_NOT_EQ, "!=") \ - OP(CPP_GREATER_EQ, ">=") \ - OP(CPP_LESS_EQ, "<=") \ -\ - /* These two are unary + / - in preprocessor expressions. */ \ - OP(CPP_PLUS_EQ, "+=") /* math */ \ - OP(CPP_MINUS_EQ, "-=") \ -\ - OP(CPP_MULT_EQ, "*=") \ - OP(CPP_DIV_EQ, "/=") \ - OP(CPP_MOD_EQ, "%=") \ - OP(CPP_AND_EQ, "&=") /* bit ops */ \ - OP(CPP_OR_EQ, "|=") \ - OP(CPP_XOR_EQ, "^=") \ - OP(CPP_RSHIFT_EQ, ">>=") \ - OP(CPP_LSHIFT_EQ, "<<=") \ - OP(CPP_MIN_EQ, "?=") \ - /* Digraphs together, beginning with CPP_FIRST_DIGRAPH. */ \ - OP(CPP_HASH, "#") /* digraphs */ \ - OP(CPP_PASTE, "##") \ - OP(CPP_OPEN_SQUARE, "[") \ - OP(CPP_CLOSE_SQUARE, "]") \ - OP(CPP_OPEN_BRACE, "{") \ - OP(CPP_CLOSE_BRACE, "}") \ - /* The remainder of the punctuation. Order is not significant. */ \ - OP(CPP_SEMICOLON, ";") /* structure */ \ - OP(CPP_ELLIPSIS, "...") \ - OP(CPP_PLUS_PLUS, "++") /* increment */ \ - OP(CPP_MINUS_MINUS, "--") \ - OP(CPP_DEREF, "->") /* accessors */ \ - OP(CPP_DOT, ".") \ - OP(CPP_SCOPE, "::") \ - OP(CPP_DEREF_STAR, "->*") \ - OP(CPP_DOT_STAR, ".*") \ - OP(CPP_ATSIGN, "@") /* used in Objective-C */ \ -\ - TK(CPP_NAME, SPELL_IDENT) /* word */ \ - TK(CPP_AT_NAME, SPELL_IDENT) /* @word - Objective-C */ \ - TK(CPP_NUMBER, SPELL_LITERAL) /* 34_be+ta */ \ -\ - TK(CPP_CHAR, SPELL_LITERAL) /* 'char' */ \ - TK(CPP_WCHAR, SPELL_LITERAL) /* L'char' */ \ - TK(CPP_OTHER, SPELL_LITERAL) /* stray punctuation */ \ -\ - TK(CPP_STRING, SPELL_LITERAL) /* "string" */ \ - TK(CPP_WSTRING, SPELL_LITERAL) /* L"string" */ \ - TK(CPP_OBJC_STRING, SPELL_LITERAL) /* @"string" - Objective-C */ \ - TK(CPP_HEADER_NAME, SPELL_LITERAL) /* in #include */ \ -\ - TK(CPP_COMMENT, SPELL_LITERAL) /* Only if output comments. */ \ - /* SPELL_LITERAL happens to DTRT. */ \ - TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \ - TK(CPP_PADDING, SPELL_NONE) /* Whitespace for cpp0. */ - -#define OP(e, s) e, -#define TK(e, s) e, +#define TTYPE_TABLE \ + OP(EQ, "=") \ + OP(NOT, "!") \ + OP(GREATER, ">") /* compare */ \ + OP(LESS, "<") \ + OP(PLUS, "+") /* math */ \ + OP(MINUS, "-") \ + OP(MULT, "*") \ + OP(DIV, "/") \ + OP(MOD, "%") \ + OP(AND, "&") /* bit ops */ \ + OP(OR, "|") \ + OP(XOR, "^") \ + OP(RSHIFT, ">>") \ + OP(LSHIFT, "<<") \ + OP(MIN, "?") \ + \ + OP(COMPL, "~") \ + OP(AND_AND, "&&") /* logical */ \ + OP(OR_OR, "||") \ + OP(QUERY, "?") \ + OP(COLON, ":") \ + OP(COMMA, ",") /* grouping */ \ + OP(OPEN_PAREN, "(") \ + OP(CLOSE_PAREN, ")") \ + TK(EOF, NONE) \ + OP(EQ_EQ, "==") /* compare */ \ + OP(NOT_EQ, "!=") \ + OP(GREATER_EQ, ">=") \ + OP(LESS_EQ, "<=") \ + \ + /* These two are unary + / - in preprocessor expressions. */ \ + OP(PLUS_EQ, "+=") /* math */ \ + OP(MINUS_EQ, "-=") \ + \ + OP(MULT_EQ, "*=") \ + OP(DIV_EQ, "/=") \ + OP(MOD_EQ, "%=") \ + OP(AND_EQ, "&=") /* bit ops */ \ + OP(OR_EQ, "|=") \ + OP(XOR_EQ, "^=") \ + OP(RSHIFT_EQ, ">>=") \ + OP(LSHIFT_EQ, "<<=") \ + OP(MIN_EQ, "?=") \ + /* Digraphs together, beginning with CPP_FIRST_DIGRAPH. */ \ + OP(HASH, "#") /* digraphs */ \ + OP(PASTE, "##") \ + OP(OPEN_SQUARE, "[") \ + OP(CLOSE_SQUARE, "]") \ + OP(OPEN_BRACE, "{") \ + OP(CLOSE_BRACE, "}") \ + /* The remainder of the punctuation. Order is not significant. */ \ + OP(SEMICOLON, ";") /* structure */ \ + OP(ELLIPSIS, "...") \ + OP(PLUS_PLUS, "++") /* increment */ \ + OP(MINUS_MINUS, "--") \ + OP(DEREF, "->") /* accessors */ \ + OP(DOT, ".") \ + OP(SCOPE, "::") \ + OP(DEREF_STAR, "->*") \ + OP(DOT_STAR, ".*") \ + OP(ATSIGN, "@") /* used in Objective-C */ \ + \ + TK(NAME, IDENT) /* word */ \ + TK(AT_NAME, IDENT) /* @word - Objective-C */ \ + TK(NUMBER, LITERAL) /* 34_be+ta */ \ + \ + TK(CHAR, LITERAL) /* 'char' */ \ + TK(WCHAR, LITERAL) /* L'char' */ \ + TK(OTHER, LITERAL) /* stray punctuation */ \ + \ + TK(STRING, LITERAL) /* "string" */ \ + TK(WSTRING, LITERAL) /* L"string" */ \ + TK(OBJC_STRING, LITERAL) /* @"string" - Objective-C */ \ + TK(HEADER_NAME, LITERAL) /* in #include */ \ + \ + TK(COMMENT, LITERAL) /* Only if output comments. */ \ + /* SPELL_LITERAL happens to DTRT. */ \ + TK(MACRO_ARG, NONE) /* Macro argument. */ \ + TK(PRAGMA, NONE) /* Only if deferring pragmas */ \ + TK(PADDING, NONE) /* Whitespace for -E. */ + +#define OP(e, s) CPP_ ## e, +#define TK(e, s) CPP_ ## e, enum cpp_ttype { TTYPE_TABLE - N_TTYPES + N_TTYPES, + + /* Positions in the table. */ + CPP_LAST_EQ = CPP_MAX, + CPP_FIRST_DIGRAPH = CPP_HASH, + CPP_LAST_PUNCTUATOR= CPP_DOT_STAR, + CPP_LAST_CPP_OP = CPP_LESS_EQ }; #undef OP #undef TK @@ -409,6 +410,10 @@ struct cpp_options /* Nonzero means __STDC__ should have the value 0 in system headers. */ unsigned char stdc_0_in_system_headers; + + /* True means return pragmas as tokens rather than processing + them directly. */ + bool defer_pragmas; }; /* Callback for header lookup for HEADER, which is the name of a @@ -634,6 +639,7 @@ extern unsigned char *cpp_spell_token (cpp_reader *, const cpp_token *, unsigned char *); extern void cpp_register_pragma (cpp_reader *, const char *, const char *, void (*) (cpp_reader *)); +extern void cpp_handle_deferred_pragma (cpp_reader *, const cpp_string *); extern int cpp_avoid_paste (cpp_reader *, const cpp_token *, const cpp_token *); extern const cpp_token *cpp_get_token (cpp_reader *); diff --git a/libcpp/internal.h b/libcpp/internal.h index 53b02f8c94c..dc1e8fb3d65 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -322,6 +322,9 @@ struct cpp_reader /* If in_directive, the directive if known. */ const struct directive *directive; + /* Token generated while handling a directive, if any. */ + cpp_token directive_result; + /* Search paths for include files. */ struct cpp_dir *quote_include; /* "" */ struct cpp_dir *bracket_include; /* <> */ diff --git a/libcpp/lex.c b/libcpp/lex.c index 914703fde2f..62a28f81b87 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -41,8 +41,8 @@ struct token_spelling static const unsigned char *const digraph_spellings[] = { U"%:", U"%:%:", U"<:", U":>", U"<%", U"%>" }; -#define OP(e, s) { SPELL_OPERATOR, U s }, -#define TK(e, s) { s, U #e }, +#define OP(e, s) { SPELL_OPERATOR, U s }, +#define TK(e, s) { SPELL_ ## s, U #e }, static const struct token_spelling token_spellings[N_TTYPES] = { TTYPE_TABLE }; #undef OP #undef TK @@ -736,7 +736,16 @@ _cpp_lex_token (cpp_reader *pfile) handles the directive as normal. */ && pfile->state.parsing_args != 1 && _cpp_handle_directive (pfile, result->flags & PREV_WHITE)) - continue; + { + if (pfile->directive_result.type == CPP_PADDING) + continue; + else + { + result = &pfile->directive_result; + break; + } + } + if (pfile->cb.line_change && !pfile->state.skipping) pfile->cb.line_change (pfile, result, pfile->state.parsing_args); } @@ -1573,6 +1582,8 @@ cpp_token_val_index (cpp_token *tok) return CPP_TOKEN_FLD_ARG_NO; else if (tok->type == CPP_PADDING) return CPP_TOKEN_FLD_SOURCE; + else if (tok->type == CPP_PRAGMA) + return CPP_TOKEN_FLD_STR; /* else fall through */ default: return CPP_TOKEN_FLD_NONE; diff --git a/libcpp/macro.c b/libcpp/macro.c index 729ea061b8b..77183343d9e 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -109,10 +109,8 @@ static const char * const monthnames[] = "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. */ +/* Helper function for builtin_macro. Returns the text generated by + a builtin macro. */ const uchar * _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) { @@ -245,8 +243,8 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) } /* 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 + context stack. Also handles _Pragma, for which a new token may not + be created. Returns 1 if it generates a new token context, 0 to return the token to the caller. */ static int builtin_macro (cpp_reader *pfile, cpp_hashnode *node) @@ -263,6 +261,13 @@ builtin_macro (cpp_reader *pfile, cpp_hashnode *node) return 0; _cpp_do__Pragma (pfile); + if (pfile->directive_result.type == CPP_PRAGMA) + { + cpp_token *tok = _cpp_temp_token (pfile); + *tok = pfile->directive_result; + push_token_context (pfile, NULL, tok, 1); + } + return 1; } -- 2.30.2