diff options
author | Zack Weinberg <zack@gcc.gnu.org> | 2004-09-09 19:16:56 +0000 |
---|---|---|
committer | Zack Weinberg <zack@gcc.gnu.org> | 2004-09-09 19:16:56 +0000 |
commit | 21b11495d75df8fd0e5b23f0176f6aa676875055 (patch) | |
tree | e54413e76af5e0dcfeb68d4c3f3c4ea1d44ceec0 /libcpp/directives.c | |
parent | b49ce401c20c43ae693407fdd9218fdb2e576d4f (diff) | |
download | gcc-21b11495d75df8fd0e5b23f0176f6aa676875055.zip gcc-21b11495d75df8fd0e5b23f0176f6aa676875055.tar.gz gcc-21b11495d75df8fd0e5b23f0176f6aa676875055.tar.bz2 |
cpplib.h (TTYPE_TABLE): Remove CPP_ and SPELL_ prefixes throughout.
2004-09-09 Matt Austern <austern@apple.com>
Zack Weinberg <zack@codesourcery.com>
* 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
Diffstat (limited to 'libcpp/directives.c')
-rw-r--r-- | libcpp/directives.c | 107 |
1 files changed, 90 insertions, 17 deletions
diff --git a/libcpp/directives.c b/libcpp/directives.c index 76055a6..b2b6b32 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) |