summaryrefslogtreecommitdiff
path: root/gcc/cpplib.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cpplib.c')
-rw-r--r--gcc/cpplib.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index 06b171758a0..5dde8870789 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -1577,6 +1577,81 @@ do_sccs (pfile, keyword)
}
#endif
+
+/* We've found an `#if' directive. If the only thing before it in
+ this file is white space, and if it is of the form
+ `#if ! defined SYMBOL', then SYMBOL is a possible controlling macro
+ for inclusion of this file. (See redundant_include_p in cppfiles.c
+ for an explanation of controlling macros.) If so, return a
+ malloc'd copy of SYMBOL. Otherwise, return NULL. */
+
+static U_CHAR *
+detect_if_not_defined (pfile)
+ cpp_reader *pfile;
+{
+ U_CHAR *control_macro = 0;
+
+ if (pfile->only_seen_white == 2)
+ {
+ char *ident;
+ enum cpp_token token;
+ int base_offset;
+ int token_offset;
+ int need_rparen = 0;
+
+ /* Save state required for restore. */
+ pfile->no_macro_expand++;
+ parse_set_mark (pfile);
+ base_offset = CPP_WRITTEN (pfile);
+
+ /* Look for `!', */
+ if (get_directive_token (pfile) != CPP_OTHER
+ || CPP_WRITTEN (pfile) != (size_t) base_offset + 1
+ || CPP_PWRITTEN (pfile)[-1] != '!')
+ goto restore;
+
+ /* ...then `defined', */
+ token_offset = CPP_WRITTEN (pfile);
+ token = get_directive_token (pfile);
+ if (token != CPP_NAME)
+ goto restore;
+ ident = pfile->token_buffer + token_offset;
+ CPP_NUL_TERMINATE (pfile);
+ if (strcmp (ident, "defined"))
+ goto restore;
+
+ /* ...then an optional '(' and the name, */
+ token_offset = CPP_WRITTEN (pfile);
+ token = get_directive_token (pfile);
+ if (token == CPP_LPAREN)
+ {
+ token_offset = CPP_WRITTEN (pfile);
+ token = get_directive_token (pfile);
+ if (token != CPP_NAME)
+ goto restore;
+ need_rparen = 1;
+ }
+ else if (token != CPP_NAME)
+ goto restore;
+
+ ident = pfile->token_buffer + token_offset;
+ CPP_NUL_TERMINATE (pfile);
+
+ /* ...then the ')', if necessary, */
+ if ((!need_rparen || get_directive_token (pfile) == CPP_RPAREN)
+ /* ...and make sure there's nothing else on the line. */
+ && get_directive_token (pfile) == CPP_VSPACE)
+ control_macro = xstrdup (ident);
+
+ restore:
+ CPP_SET_WRITTEN (pfile, base_offset);
+ pfile->no_macro_expand--;
+ parse_goto_mark (pfile);
+ }
+
+ return control_macro;
+}
+
/*
* handle #if command by
* 1) inserting special `defined' keyword into the hash table
@@ -1595,8 +1670,9 @@ do_if (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
{
+ U_CHAR *control_macro = detect_if_not_defined (pfile);
HOST_WIDEST_INT value = eval_if_expression (pfile);
- conditional_skip (pfile, value == 0, T_IF, NULL_PTR);
+ conditional_skip (pfile, value == 0, T_IF, control_macro);
return 0;
}