This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
cpplib: remove cpp_register_pragma_space()
- To: gcc-patches at gcc dot gnu dot org
- Subject: cpplib: remove cpp_register_pragma_space()
- From: Neil Booth <neil at daikokuya dot demon dot co dot uk>
- Date: Sun, 14 Oct 2001 17:09:28 +0100
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 ----