This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ parser speedups (1/n): cpplib infrastructure


Matt Austern and I have been collaborating on a patch to speed up the
C++ parser by improving the data structures it uses for lookahead and
backtracking.  That patch is not yet ready, but pieces of it are, so I
am peeling them off.

This patch sets up some infrastructure in cpplib which allows a
library user to specify that most #pragmas (those not processed by
cpplib itself) are to be "deferred" -- encapsulated in a pseudo-string
token and written to the output stream.  Later, the library user can
call cpp_handle_deferred_pragma with one of these tokens to execute
the #pragma.  Also, we make it slightly more convenient for a library
user to do things with TTYPE_TABLE.

Matt wrote almost all of this code; I just adjusted some of the naming
conventions.

Bootstrapped i686-linux, no regressions.

zw

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.

===================================================================
Index: directives.c
--- directives.c	24 Jul 2004 18:04:42 -0000	1.4
+++ directives.c	9 Sep 2004 18:00:47 -0000
@@ -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_pragm
 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 di
   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
 
 /* 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, 
       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, 
 
 /* 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, 
       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, 
 	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 *p
    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: internal.h
--- internal.h	24 Jul 2004 18:04:42 -0000	1.6
+++ internal.h	9 Sep 2004 18:00:47 -0000
@@ -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: lex.c
--- lex.c	24 Jul 2004 18:04:42 -0000	1.4
+++ lex.c	9 Sep 2004 18:00:47 -0000
@@ -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: macro.c
--- macro.c	24 Jul 2004 18:04:42 -0000	1.4
+++ macro.c	9 Sep 2004 18:00:47 -0000
@@ -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 *pfi
 }
 
 /* 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_ha
 	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;
     }
 
===================================================================
Index: include/cpplib.h
--- include/cpplib.h	24 Jul 2004 18:04:42 -0000	1.4
+++ include/cpplib.h	9 Sep 2004 18:00:47 -0000
@@ -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 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) e,
-#define TK(e, s) 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 (c
 				       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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]