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]

cpplib: remove cpp_register_pragma_space()


I'm working on cleaning up pragma handling, and aim to remove the
dependency on c_lex() for the non-C front ends.

This patch removes the need to register pragma spaces (they are
created on the fly if a pragma with an unknown namespace is
registered), and does some sanity checks we didn't do before: the same
pragma cannot be registered more than once, and a pragma in the global
namespace cannot be registered if it clashes with a namespace name.

I'll commit this if it bootstraps without regressions.

Neil.

	* c-pragma.h (cpp_register_pragma_space): Remove.
	* cpplib.h (cpp_register_pragma_space): Remove.
	* cpplib.c (lookup_pragma_entry, insert_pragma_entry): New.
	(cpp_register_pragma_space): Remove.
	(cpp_register_pragma): Simplify using lookup_pragma_entry,
	add sanity checks.
	(do_pragma): Similarly.
	(_cpp_init_internal_pragmas): Don't register namespaces.

	* config/v850/v850.h (REGISTER_TARGET_PRAGMAS):
	Don't register namespaces.
	* cp/lex.c (init_cp_pragma): Similarly.
	* doc/tm.texi: Update.

============================================================
Index: gcc/c-pragma.h
*** c-pragma.h	2001/08/28 23:03:51	1.24
--- gcc/c-pragma.h	2001/10/14 15:56:25
*************** typedef struct cpp_reader cpp_reader;
*** 51,57 ****
  extern void cpp_register_pragma PARAMS ((cpp_reader *,
  					 const char *, const char *,
  					 void (*) PARAMS ((cpp_reader *))));
- extern void cpp_register_pragma_space PARAMS ((cpp_reader *, const char *));
  #endif
  
  #endif /* GCC_C_PRAGMA_H */
--- 51,56 ----
============================================================
Index: gcc/cpplib.c
*** cpplib.c	2001/10/10 11:33:06	1.281
--- gcc/cpplib.c	2001/10/14 15:56:37
*************** struct if_stack
*** 47,52 ****
--- 47,66 ----
    int type;			/* Most recent conditional, for diagnostics.  */
  };
  
+ /* Contains a registered pragma or pragma namespace.  */
+ typedef void (*pragma_cb) PARAMS ((cpp_reader *));
+ struct pragma_entry
+ {
+   struct pragma_entry *next;
+   const char *name;
+   size_t len;
+   int is_nspace;
+   union {
+     pragma_cb handler;
+     struct pragma_entry *space;
+   } u;
+ };
+ 
  /* Values for the origin field of struct directive.  KANDR directives
     come from traditional (K&R) C.  STDC89 directives come from the
     1989 C standard.  EXTENSION directives are extensions.  */
*************** static int  strtoul_for_line	PARAMS ((co
*** 96,101 ****
--- 110,119 ----
  static void do_diagnostic	PARAMS ((cpp_reader *, enum error_type, int));
  static cpp_hashnode *lex_macro_node	PARAMS ((cpp_reader *));
  static void do_include_common	PARAMS ((cpp_reader *, enum include_type));
+ static struct pragma_entry *lookup_pragma_entry
+   PARAMS ((struct pragma_entry *, const char *pragma));
+ static struct pragma_entry *insert_pragma_entry
+   PARAMS ((cpp_reader *, struct pragma_entry **, const char *, pragma_cb));
  static void do_pragma_once	PARAMS ((cpp_reader *));
  static void do_pragma_poison	PARAMS ((cpp_reader *));
  static void do_pragma_system_header	PARAMS ((cpp_reader *));
*************** do_ident (pfile)
*** 842,990 ****
    check_eol (pfile);
  }
  
! /* Pragmata handling.  We handle some of these, and pass the rest on
!    to the 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.  */
! 
! /* Sub-handlers for the pragmas needing treatment here.
!    They return 1 if the token buffer is to be popped, 0 if not.  */
! typedef void (*pragma_cb) PARAMS ((cpp_reader *));
! struct pragma_entry
  {
!   struct pragma_entry *next;
!   const char *name;
!   size_t len;
!   int isnspace;
!   union {
!     pragma_cb handler;
!     struct pragma_entry *space;
!   } u;
! };
  
! void
! cpp_register_pragma (pfile, space, name, handler)
       cpp_reader *pfile;
!      const char *space;
       const char *name;
       pragma_cb handler;
  {
!   struct pragma_entry **x, *new;
!   size_t len;
! 
!   x = &pfile->pragmas;
!   if (space)
!     {
!       struct pragma_entry *p = pfile->pragmas;
!       len = strlen (space);
!       while (p)
! 	{
! 	  if (p->isnspace && p->len == len && !memcmp (p->name, space, len))
! 	    {
! 	      x = &p->u.space;
! 	      goto found;
! 	    }
! 	  p = p->next;
! 	}
!       cpp_ice (pfile, "unknown #pragma namespace %s", space);
!       return;
!     }
  
-  found:
    new = (struct pragma_entry *)
      _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
    new->name = name;
    new->len = strlen (name);
!   new->isnspace = 0;
!   new->u.handler = handler;
  
!   new->next = *x;
!   *x = new;
  }
  
  void
! cpp_register_pragma_space (pfile, space)
       cpp_reader *pfile;
       const char *space;
  {
!   struct pragma_entry *new;
!   const struct pragma_entry *p = pfile->pragmas;
!   size_t len = strlen (space);
  
!   while (p)
      {
!       if (p->isnspace && p->len == len && !memcmp (p->name, space, len))
! 	/* Multiple different callers are allowed to register the same
! 	   namespace.  */
! 	return;
!       p = p->next;
      }
! 
!   new = (struct pragma_entry *)
!     _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
!   new->name = space;
!   new->len = len;
!   new->isnspace = 1;
!   new->u.space = 0;
! 
!   new->next = pfile->pragmas;
!   pfile->pragmas = new;
  }
!   
  void
  _cpp_init_internal_pragmas (pfile)
       cpp_reader *pfile;
  {
!   /* top level */
    cpp_register_pragma (pfile, 0, "poison", do_pragma_poison);
    cpp_register_pragma (pfile, 0, "once", do_pragma_once);
  
!   /* GCC namespace */
!   cpp_register_pragma_space (pfile, "GCC");
! 
    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);
  }
  
  static void
  do_pragma (pfile)
       cpp_reader *pfile;
  {
!   pragma_cb handler = NULL;
!   const struct pragma_entry *p;
    const cpp_token *token;
!   unsigned int count = 0;
  
-   p = pfile->pragmas;
    pfile->state.prevent_expansion++;
  
-  new_space:
-   count++;
    token = cpp_get_token (pfile);
    if (token->type == CPP_NAME)
      {
!       const cpp_hashnode *node = token->val.node;
!       size_t len = NODE_LEN (node);
! 
!       while (p)
  	{
! 	  if (strlen (p->name) == len
! 	      && !memcmp (p->name, NODE_NAME (node), len))
! 	    {
! 	      if (p->isnspace)
! 		{
! 		  p = p->u.space;
! 		  goto new_space;
! 		}
! 	      else
! 		{
! 		  handler = p->u.handler;
! 		  break;
! 		}
! 	    }
! 	  p = p->next;
  	}
      }
  
--- 860,1005 ----
    check_eol (pfile);
  }
  
! /* Lookup a PRAGMA name in a singly-linked CHAIN.  Returns the
!    matching entry, or NULL if none is found.  The returned entry could
!    be the start of a namespace chain, or a pragma.  */
! static struct pragma_entry *
! lookup_pragma_entry (chain, pragma)
!      struct pragma_entry *chain;
!      const char *pragma;
  {
!   size_t len = strlen (pragma);
  
!   while (chain)
!     {
!       if (chain->len == len && !memcmp (chain->name, pragma, len))
! 	break;
!       chain = chain->next;
!     }
! 
!   return chain;
! }
! 
! /* 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.  */
! static struct pragma_entry *
! insert_pragma_entry (pfile, chain, name, handler)
       cpp_reader *pfile;
!      struct pragma_entry **chain;
       const char *name;
       pragma_cb handler;
  {
!   struct pragma_entry *new;
  
    new = (struct pragma_entry *)
      _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
    new->name = name;
    new->len = strlen (name);
!   if (handler)
!     {
!       new->is_nspace = 0;
!       new->u.handler = handler;
!     }
!   else
!     {
!       new->is_nspace = 1;
!       new->u.space = NULL;
!     }
  
!   new->next = *chain;
!   *chain = new;
!   return new;
  }
  
+ /* 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 (pfile, space, name, handler)
       cpp_reader *pfile;
       const char *space;
+      const char *name;
+      pragma_cb handler;
  {
!   struct pragma_entry **chain = &pfile->pragmas;
!   struct pragma_entry *entry;
  
!   if (!handler)
!     abort ();
! 
!   if (space)
      {
!       entry = lookup_pragma_entry (*chain, space);
!       if (!entry)
! 	entry = insert_pragma_entry (pfile, chain, space, NULL);
!       else if (!entry->is_nspace)
! 	goto clash;
!       chain = &entry->u.space;
!     }
! 
!   /* Check for duplicates.  */
!   entry = lookup_pragma_entry (*chain, name);
!   if (entry)
!     {
!       if (entry->is_nspace)
! 	clash:
! 	cpp_ice (pfile,
! 		 "registering \"%s\" as both a pragma and a pragma namespace",
! 		 entry->name);
!       else if (space)
! 	cpp_ice (pfile, "#pragma %s %s is already registered", space, name);
!       else
! 	cpp_ice (pfile, "#pragma %s is already registered", name);
      }
!   else
!     insert_pragma_entry (pfile, chain, name, handler);
  }
! 
! /* Register the pragmas the preprocessor itself handles.  */
  void
  _cpp_init_internal_pragmas (pfile)
       cpp_reader *pfile;
  {
!   /* Pragmas in the global namespace.  */
    cpp_register_pragma (pfile, 0, "poison", do_pragma_poison);
    cpp_register_pragma (pfile, 0, "once", do_pragma_once);
  
!   /* 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);
  }
  
+ /* Pragmata handling.  We handle some, and pass the rest on to the
+    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.  */
  static void
  do_pragma (pfile)
       cpp_reader *pfile;
  {
!   const struct pragma_entry *p = NULL;
    const cpp_token *token;
!   unsigned int count = 1;
  
    pfile->state.prevent_expansion++;
  
    token = cpp_get_token (pfile);
    if (token->type == CPP_NAME)
      {
!       p = lookup_pragma_entry (pfile->pragmas,
! 			       (char *) NODE_NAME (token->val.node));
!       if (p && p->is_nspace)
  	{
! 	  count = 2;
! 	  token = cpp_get_token (pfile);
! 	  if (token->type == CPP_NAME)
! 	    p = lookup_pragma_entry (p->u.space,
! 				     (char *) NODE_NAME (token->val.node));
! 	  else
! 	    p = NULL;
  	}
      }
  
*************** do_pragma (pfile)
*** 996,1008 ****
    if (pfile->cb.line_change)
      (*pfile->cb.line_change)(pfile, token, 1);
  
!   if (handler)
!     (*handler) (pfile);
    else if (pfile->cb.def_pragma)
      {
        _cpp_backup_tokens (pfile, count);
        (*pfile->cb.def_pragma) (pfile, pfile->directive_line);
      }
    pfile->state.prevent_expansion--;
  }
  
--- 1011,1024 ----
    if (pfile->cb.line_change)
      (*pfile->cb.line_change)(pfile, token, 1);
  
!   if (p)
!     (*p->u.handler) (pfile);
    else if (pfile->cb.def_pragma)
      {
        _cpp_backup_tokens (pfile, count);
        (*pfile->cb.def_pragma) (pfile, pfile->directive_line);
      }
+ 
    pfile->state.prevent_expansion--;
  }
  
============================================================
Index: gcc/cpplib.h
*** cpplib.h	2001/10/11 12:43:39	1.196
--- gcc/cpplib.h	2001/10/14 15:56:37
*************** extern unsigned char *cpp_spell_token PA
*** 494,500 ****
  extern void cpp_register_pragma PARAMS ((cpp_reader *,
  					 const char *, const char *,
  					 void (*) PARAMS ((cpp_reader *))));
- extern void cpp_register_pragma_space PARAMS ((cpp_reader *, const char *));
  
  extern int cpp_start_read PARAMS ((cpp_reader *, const char *));
  extern void cpp_finish PARAMS ((cpp_reader *));
--- 494,499 ----
============================================================
Index: gcc/config/v850/v850.h
*** v850.h	2001/09/11 16:50:03	1.46
--- gcc/config/v850/v850.h	2001/10/14 15:56:40
*************** do { char dstr[30];					\
*** 1503,1509 ****
  
  /* Tell compiler we want to support GHS pragmas */
  #define REGISTER_TARGET_PRAGMAS(PFILE) do {				  \
-   cpp_register_pragma_space (PFILE, "ghs");				  \
    cpp_register_pragma (PFILE, "ghs", "interrupt", ghs_pragma_interrupt);  \
    cpp_register_pragma (PFILE, "ghs", "section",   ghs_pragma_section);    \
    cpp_register_pragma (PFILE, "ghs", "starttda",  ghs_pragma_starttda);   \
--- 1503,1508 ----
============================================================
Index: gcc/cp/lex.c
*** lex.c	2001/10/13 13:24:34	1.251
--- gcc/cp/lex.c	2001/10/14 15:56:44
*************** init_cp_pragma ()
*** 677,683 ****
    cpp_register_pragma (parse_in, 0, "implementation",
  		       handle_pragma_implementation);
  
-   cpp_register_pragma_space (parse_in, "GCC");
    cpp_register_pragma (parse_in, "GCC", "interface", handle_pragma_interface);
    cpp_register_pragma (parse_in, "GCC", "implementation",
  		       handle_pragma_implementation);
--- 677,682 ----
============================================================
Index: gcc/doc/tm.texi
*** tm.texi	2001/10/09 23:11:55	1.62
--- gcc/doc/tm.texi	2001/10/14 15:57:15
*************** This macro is no longer supported.  You 
*** 8485,8494 ****
  @findex pragma
  @item REGISTER_TARGET_PRAGMAS (@var{pfile})
  Define this macro if you want to implement any target-specific pragmas.
! If defined, it is a C expression which makes a series of calls to the
! @code{cpp_register_pragma} and/or @code{cpp_register_pragma_space}
! functions.  The @var{pfile} argument is the first argument to supply to
! these functions.  The macro may also do setup required for the pragmas.
  
  The primary reason to define this macro is to provide compatibility with
  other compilers for the same target.  In general, we discourage
--- 8485,8494 ----
  @findex pragma
  @item REGISTER_TARGET_PRAGMAS (@var{pfile})
  Define this macro if you want to implement any target-specific pragmas.
! If defined, it is a C expression which makes a series of calls to
! @code{cpp_register_pragma} for each pragma, with @var{pfile} passed as
! the first argument to to these functions.  The macro may also do any
! setup required for the pragmas.
  
  The primary reason to define this macro is to provide compatibility with
  other compilers for the same target.  In general, we discourage
*************** pragma of the form
*** 8511,8525 ****
  #pragma [@var{space}] @var{name} @dots{}
  @end smallexample
  
! @var{space} must have been the subject of a previous call to
! @code{cpp_register_pragma_space}, or else be a null pointer.  The
! callback routine receives @var{pfile} as its first argument, but must
! not use it for anything (this may change in the future).  It may read
! any text after the @var{name} by making calls to @code{c_lex}.  Text
! which is not read by the callback will be silently ignored.
  
- Note that both @var{space} and @var{name} are case sensitive.
- 
  For an example use of this routine, see @file{c4x.h} and the callback
  routines defined in @file{c4x.c}.
  
--- 8511,8523 ----
  #pragma [@var{space}] @var{name} @dots{}
  @end smallexample
  
! @var{space} is the case-sensitive namespace of the pragma, or
! @code{NULL} to put the pragma in the global namespace.  The callback
! routine receives @var{pfile} as its first argument, which can be passed
! on to cpplib's functions if necessary.  It may read any text after the
! @var{name} by making calls to @code{c_lex}.  Text which is not read by
! the callback will be silently ignored.
  
  For an example use of this routine, see @file{c4x.h} and the callback
  routines defined in @file{c4x.c}.
  
*************** the target-specific, language-specific o
*** 8534,8548 ****
  code that uses @code{c_lex}.  Note it will also be necessary to add a
  rule to the makefile fragment pointed to by @code{tmake_file} that shows
  how to build this object file.
- @end deftypefun
- 
- @deftypefun void cpp_register_pragma_space (cpp_reader *@var{pfile}, const char *@var{space})
- This routine establishes a namespace for pragmas, which will be
- registered by subsequent calls to @code{cpp_register_pragma}.  For
- example, pragmas defined by the C standard are in the @samp{STDC}
- namespace, and pragmas specific to GCC are in the @samp{GCC} namespace.
- 
- For an example use of this routine in a target header, see @file{v850.h}.
  @end deftypefun
  
  @findex HANDLE_SYSV_PRAGMA
--- 8532,8537 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]