OSDN Git Service

2004-09-09 Matt Austern <austern@apple.com>
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Sep 2004 19:16:56 +0000 (19:16 +0000)
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Sep 2004 19:16:56 +0000 (19:16 +0000)
    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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@87247 138bc75d-0d04-0410-961f-82ee72b054a4

libcpp/ChangeLog
libcpp/directives.c
libcpp/include/cpplib.h
libcpp/internal.h
libcpp/lex.c
libcpp/macro.c

index 131f188..7090249 100644 (file)
@@ -1,3 +1,43 @@
+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.
+
 2004-09-06  Serge Belyshev  <belyshev@lubercy.com>
 
        PR preprocessor/14699
@@ -38,9 +78,9 @@
        * macro.c: Likewise.
        * cpplib.h (cpp_deps_style): Export enum with name.
 
-2004-07-23  Matthias Klose  <doko@debian.org> 
+2004-07-23  Matthias Klose  <doko@debian.org>
 
-       * 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  <pavenis@latnet.lv>
 
index 76055a6..b2b6b32 100644 (file)
@@ -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)
index 5473641..4ee626e 100644 (file)
@@ -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,          "<?")   /* extension */ \
-  OP(CPP_MAX,          ">?")                   \
-\
-  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,       "<?=")  /* extension */ \
-  OP(CPP_MAX_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)  /* <stdio.h> 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,              "<?")   /* extension */                         \
+  OP(MAX,              ">?")                                           \
+                                                                       \
+  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,           "<?=")  /* extension */                         \
+  OP(MAX_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) /* <stdio.h> 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 *);
index 53b02f8..dc1e8fb 100644 (file)
@@ -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;     /* <> */
index 914703f..62a28f8 100644 (file)
@@ -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;
index 729ea06..7718334 100644 (file)
@@ -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;
     }