diff options
author | neil <neil@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-07-29 17:27:57 +0000 |
---|---|---|
committer | neil <neil@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-07-29 17:27:57 +0000 |
commit | fa233610fcbee7f3e67375962e6effe96c2b19e2 (patch) | |
tree | ae3bf4ef61f7e71d609b714e200c82e7e441cba2 | |
parent | 4d1f4307480c700e251e01b4931f8935db4a04cc (diff) | |
download | gcc-fa233610fcbee7f3e67375962e6effe96c2b19e2.tar.gz |
* cppexp.c (parse_defined): Always record the macro name.
(lex): Don't worry about identifiers, or special-case
CPP_NOT here.
(_cpp_parse_expr): Figure out at the end of the routine
whether we saw a valid !defined() expression.
* cppfiles.c (stack_include_file): Update for mi_valid.
(_cpp_pop_file_buffer): Similarly.
* cpplex.c (_cpp_lex_token): Similarly.
* cpphash.h (enum mi_state, enum mi_ind, mi_state,
mi_if_not_defined, mi_lexed): Remove.
(mi_valid): New.
* cpplib.c (do_if): Simplify.
(do_endif, push_conditional, _cpp_handle_directive): Update
for renaming of mi_state to mi_valid.
* cpp.texi: Add index entries for digraphs, and add comment
that C++ refers to them as alternative tokens.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44459 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cppexp.c | 42 | ||||
-rw-r--r-- | gcc/cppfiles.c | 8 | ||||
-rw-r--r-- | gcc/cpphash.h | 8 | ||||
-rw-r--r-- | gcc/cpplex.c | 2 | ||||
-rw-r--r-- | gcc/cpplib.c | 30 | ||||
-rw-r--r-- | gcc/cppmacro.c | 2 | ||||
-rw-r--r-- | gcc/doc/cpp.texi | 13 |
8 files changed, 68 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa26118a252..cb73400b1ee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2001-07-29 Neil Booth <neil@cat.daikokuya.demon.co.uk> + + * cppexp.c (parse_defined): Always record the macro name. + (lex): Don't worry about identifiers, or special-case + CPP_NOT here. + (_cpp_parse_expr): Figure out at the end of the routine + whether we saw a valid !defined() expression. + * cppfiles.c (stack_include_file): Update for mi_valid. + (_cpp_pop_file_buffer): Similarly. + * cpplex.c (_cpp_lex_token): Similarly. + * cpphash.h (enum mi_state, enum mi_ind, mi_state, + mi_if_not_defined, mi_lexed): Remove. + (mi_valid): New. + * cpplib.c (do_if): Simplify. + (do_endif, push_conditional, _cpp_handle_directive): Update + for renaming of mi_state to mi_valid. +doc: + * cpp.texi: Add index entries for digraphs, and add comment + that C++ refers to them as alternative tokens. + Sun Jul 29 18:59:13 CEST 2001 Jan Hubicka <jh@suse.cz> * basic-block.h (CLEANUP_PRE_LOOP): New. diff --git a/gcc/cppexp.c b/gcc/cppexp.c index 095a42d8280..52ffb27881c 100644 --- a/gcc/cppexp.c +++ b/gcc/cppexp.c @@ -267,16 +267,9 @@ parse_defined (pfile) op.unsignedp = 0; op.op = CPP_NUMBER; - /* No macros? At top of file? */ - if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0 - && pfile->mi_if_not_defined == MI_IND_NOT && pfile->mi_lexed == 1) - { - cpp_start_lookahead (pfile); - cpp_get_token (pfile, &token); - if (token.type == CPP_EOF) - pfile->mi_ind_cmacro = node; - cpp_stop_lookahead (pfile, 0); - } + /* A possible controlling macro of the form #if !defined (). + _cpp_parse_expr checks there was no other junk on the line. */ + pfile->mi_ind_cmacro = node; } pfile->state.prevent_expansion--; @@ -351,10 +344,6 @@ lex (pfile, skip_evaluation, token) } else { - /* Controlling #if expressions cannot contain identifiers (they - could become macros in the future). */ - pfile->mi_state = MI_FAILED; - op.op = CPP_NUMBER; op.unsignedp = 0; op.value = 0; @@ -377,11 +366,6 @@ lex (pfile, skip_evaluation, token) return op; } - case CPP_NOT: - /* We don't worry about its position here. */ - pfile->mi_if_not_defined = MI_IND_NOT; - /* Fall through. */ - default: if (((int) token->type > (int) CPP_EQ && (int) token->type < (int) CPP_PLUS_EQ) @@ -598,10 +582,12 @@ _cpp_parse_expr (pfile) register struct op *top = stack + 1; int skip_evaluation = 0; int result; + unsigned int lex_count, saw_leading_not; /* Set up detection of #if ! defined(). */ - pfile->mi_lexed = 0; - pfile->mi_if_not_defined = MI_IND_NONE; + pfile->mi_ind_cmacro = 0; + saw_leading_not = 0; + lex_count = 0; /* We've finished when we try to reduce this. */ top->op = CPP_EOF; @@ -618,7 +604,7 @@ _cpp_parse_expr (pfile) /* Read a token */ op = lex (pfile, skip_evaluation, &token); - pfile->mi_lexed++; + lex_count++; /* If the token is an operand, push its value and get next token. If it is an operator, get its priority and flags, and @@ -638,6 +624,11 @@ _cpp_parse_expr (pfile) continue; case CPP_EOF: prio = FORCE_REDUCE_PRIO; break; + + case CPP_NOT: + saw_leading_not = lex_count == 1; + prio = op_to_prio[op.op]; + break; case CPP_PLUS: case CPP_MINUS: prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break; /* else unary; fall through */ @@ -869,7 +860,14 @@ _cpp_parse_expr (pfile) } done: + /* The controlling macro expression is only valid if we called lex 3 + times: <!> <defined expression> and <EOF>. push_conditional () + checks that we are at top-of-file. */ + if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3)) + pfile->mi_ind_cmacro = 0; + result = (top[1].value != 0); + if (top != stack) CPP_ICE ("unbalanced stack in #if"); else if (!(top[1].flags & HAVE_VALUE)) diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 137882b340c..cb6ca5eda73 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -332,7 +332,7 @@ stack_include_file (pfile, inc) fp->sysp = sysp; /* Initialise controlling macro state. */ - pfile->mi_state = MI_OUTSIDE; + pfile->mi_valid = true; pfile->mi_cmacro = 0; pfile->include_depth++; @@ -748,12 +748,12 @@ _cpp_pop_file_buffer (pfile, buf) pfile->include_depth--; /* Record the inclusion-preventing macro, which could be NULL - meaning no controlling macro, if we haven't got it already. */ - if (pfile->mi_state == MI_OUTSIDE && inc->cmacro == NULL) + meaning no controlling macro. */ + if (pfile->mi_valid && inc->cmacro == NULL) inc->cmacro = pfile->mi_cmacro; /* Invalidate control macros in the #including file. */ - pfile->mi_state = MI_FAILED; + pfile->mi_valid = false; inc->refcnt--; if (inc->refcnt == 0 && DO_NOT_REREAD (inc)) diff --git a/gcc/cpphash.h b/gcc/cpphash.h index a8221d98a25..368fe46f287 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -93,10 +93,6 @@ struct search_path struct file_name_map *name_map; }; -/* Multiple-include optimisation. */ -enum mi_state {MI_FAILED = 0, MI_OUTSIDE}; -enum mi_ind {MI_IND_NONE = 0, MI_IND_NOT}; - /* #include types. */ enum include_type {IT_INCLUDE, IT_INCLUDE_NEXT, IT_IMPORT, IT_CMDLINE}; @@ -268,11 +264,9 @@ struct cpp_reader const struct directive *directive; /* Multiple inlcude optimisation. */ - enum mi_state mi_state; - enum mi_ind mi_if_not_defined; - unsigned int mi_lexed; const cpp_hashnode *mi_cmacro; const cpp_hashnode *mi_ind_cmacro; + bool mi_valid; /* Token lookahead. */ struct cpp_lookahead *la_read; /* Read from this lookahead. */ diff --git a/gcc/cpplex.c b/gcc/cpplex.c index 48217451523..5248a422f45 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -1266,7 +1266,7 @@ _cpp_lex_token (pfile, result) /* If not in a directive, this token invalidates controlling macros. */ if (!pfile->state.in_directive) - pfile->mi_state = MI_FAILED; + pfile->mi_valid = false; } /* An upper bound on the number of bytes needed to spell a token, diff --git a/gcc/cpplib.c b/gcc/cpplib.c index c196c1f9c96..8f9f54c8be6 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -358,7 +358,7 @@ _cpp_handle_directive (pfile, indented) /* If we have a directive that is not an opening conditional, invalidate any control macro. */ if (! (dir->flags & IF_COND)) - pfile->mi_state = MI_FAILED; + pfile->mi_valid = false; (*dir->handler) (pfile); } @@ -1278,27 +1278,22 @@ do_ifndef (pfile) push_conditional (pfile, skip, T_IFNDEF, node); } -/* #if cooperates with parse_defined to handle multiple-include - optimisations. If macro expansions or identifiers appear in the - expression, we cannot treat it as a controlling conditional, since - their values could change in the future. */ +/* _cpp_parse_expr puts a macro in a "#if !defined ()" expression in + pfile->mi_ind_cmacro so we can handle multiple-include + optimisations. If macro expansion occurs in the expression, we + cannot treat it as a controlling conditional, since the expansion + could change in the future. That is handled by cpp_get_token. */ static void do_if (pfile) cpp_reader *pfile; { int skip = 1; - const cpp_hashnode *cmacro = 0; if (! pfile->state.skipping) - { - /* Controlling macro of #if ! defined () */ - pfile->mi_ind_cmacro = 0; - skip = _cpp_parse_expr (pfile) == 0; - cmacro = pfile->mi_ind_cmacro; - } + skip = _cpp_parse_expr (pfile) == 0; - push_conditional (pfile, skip, T_IF, cmacro); + push_conditional (pfile, skip, T_IF, pfile->mi_ind_cmacro); } /* Flip skipping state if appropriate and continue without changing @@ -1395,7 +1390,7 @@ do_endif (pfile) /* If potential control macro, we go back outside again. */ if (ifs->next == 0 && ifs->mi_cmacro) { - pfile->mi_state = MI_OUTSIDE; + pfile->mi_valid = true; pfile->mi_cmacro = ifs->mi_cmacro; } @@ -1406,8 +1401,8 @@ do_endif (pfile) } /* Push an if_stack entry and set pfile->state.skipping accordingly. - If this is a #ifndef starting at the beginning of a file, - CMACRO is the macro name tested by the #ifndef. */ + If this is a #if or #ifndef, CMACRO is a potentially controlling + macro - we need to check here that we are at the top of the file. */ static void push_conditional (pfile, skip, type, cmacro) @@ -1425,7 +1420,8 @@ push_conditional (pfile, skip, type, cmacro) ifs->skip_elses = pfile->state.skipping || !skip; ifs->was_skipping = pfile->state.skipping; ifs->type = type; - if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0) + /* This condition is effectively a test for top-of-file. */ + if (pfile->mi_valid && pfile->mi_cmacro == 0) ifs->mi_cmacro = cmacro; else ifs->mi_cmacro = 0; diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index e630850106a..a4569a3e073 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -953,7 +953,7 @@ cpp_get_token (pfile, token) cpp_hashnode *node = token->val.node; /* Macros invalidate controlling macros. */ - pfile->mi_state = MI_FAILED; + pfile->mi_valid = false; if (node->flags & NODE_BUILTIN) { diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index 47ec9cde9d8..319f73510d8 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -536,15 +536,18 @@ be removed in GCC 3.1. You may use continued lines instead, or string constant concatenation. @xref{Differences from previous versions}. @cindex punctuators +@cindex digraphs +@cindex alternative tokens @dfn{Punctuators} are all the usual bits of punctuation which are meaningful to C and C++. All but three of the punctuation characters in ASCII are C punctuators. The exceptions are @samp{@@}, @samp{$}, and @samp{`}. In addition, all the two- and three-character operators are -punctuators. There are also six @dfn{digraphs}, which are merely -alternate ways to spell other punctuators. This is a second attempt to -work around missing punctuation in obsolete systems. It has no negative -side effects, unlike trigraphs, but does not cover as much ground. The -digraphs and their corresponding normal punctuators are: +punctuators. There are also six @dfn{digraphs}, which the C++ standard +calls @dfn{alternative tokens}, which are merely alternate ways to spell +other punctuators. This is a second attempt to work around missing +punctuation in obsolete systems. It has no negative side effects, +unlike trigraphs, but does not cover as much ground. The digraphs and +their corresponding normal punctuators are: @example Digraph: <% %> <: :> %: %:%: |