/* CPP Library. (Directive handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
{
struct pragma_entry *next;
const cpp_hashnode *pragma; /* Name and length. */
- int is_nspace;
+ bool is_nspace;
+ bool allow_expansion;
+ bool is_internal;
union {
pragma_cb handler;
struct pragma_entry *space;
static void directive_diagnostics (cpp_reader *, const directive *, int);
static void run_directive (cpp_reader *, int, const char *, size_t);
static char *glue_header_name (cpp_reader *);
-static const char *parse_include (cpp_reader *, int *);
+static const char *parse_include (cpp_reader *, int *, const cpp_token ***);
static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
static unsigned int read_flag (cpp_reader *, unsigned int);
static int strtoul_for_line (const uchar *, unsigned int, unsigned long *);
static struct pragma_entry *insert_pragma_entry (cpp_reader *,
struct pragma_entry **,
const cpp_hashnode *,
- pragma_cb);
+ pragma_cb,
+ bool, bool);
+static void register_pragma (cpp_reader *, const char *, const char *,
+ pragma_cb, bool, 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 *,
D(import, T_IMPORT, EXTENSION, INCL | EXPAND) /* 0 ObjC */ \
D(assert, T_ASSERT, EXTENSION, 0) /* 0 SVR4 */ \
D(unassert, T_UNASSERT, EXTENSION, 0) /* 0 SVR4 */ \
-D(sccs, T_SCCS, EXTENSION, 0) /* 0 SVR4? */
+D(sccs, T_SCCS, EXTENSION, IN_I) /* 0 SVR4? */
+
+/* #sccs is synonymous with #ident. */
+#define do_sccs do_ident
/* Use the table to generate a series of prototypes, an enum for the
directive names, and an array of directive handlers. */
pfile->directive->name);
}
+/* Ensure there are no stray tokens other than comments at the end of
+ a directive, and gather the comments. */
+static const cpp_token **
+check_eol_return_comments (cpp_reader *pfile)
+{
+ size_t c;
+ size_t capacity = 8;
+ const cpp_token **buf;
+
+ buf = XNEWVEC (const cpp_token *, capacity);
+ c = 0;
+ if (! SEEN_EOL ())
+ {
+ while (1)
+ {
+ const cpp_token *tok;
+
+ tok = _cpp_lex_token (pfile);
+ if (tok->type == CPP_EOF)
+ break;
+ if (tok->type != CPP_COMMENT)
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "extra tokens at end of #%s directive",
+ pfile->directive->name);
+ else
+ {
+ if (c + 1 >= capacity)
+ {
+ capacity *= 2;
+ buf = XRESIZEVEC (const cpp_token *, buf, capacity);
+ }
+ buf[c] = tok;
+ ++c;
+ }
+ }
+ }
+ buf[c] = NULL;
+ return buf;
+}
+
/* Called when entering a directive, _Pragma or command-line directive. */
static void
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;
/* Check if we have a known directive. INDENTED is nonzero if the
'#' of the directive was indented. This function is in this file
- to save unnecessarily exporting dtable etc. to cpplex.c. Returns
+ to save unnecessarily exporting dtable etc. to lex.c. Returns
nonzero if the line of tokens has been handled, zero if we should
continue processing the line. */
int
does not cause '#define foo bar' to get executed when
compiled with -save-temps, we recognize directives in
- -fpreprocessed mode only if the # is in column 1. cppmacro.c
+ -fpreprocessed mode only if the # is in column 1. macro.c
puts a space in front of any '#' at the start of a macro. */
if (CPP_OPTION (pfile, preprocessed)
&& (indented || !(dir->flags & IN_I)))
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);
return NULL;
}
-/* Process a #define directive. Most work is done in cppmacro.c. */
+/* Process a #define directive. Most work is done in macro.c. */
static void
do_define (cpp_reader *pfile)
{
/* To avoid lexed tokens overwriting our glued name, we can only
allocate from the string pool once we've lexed everything. */
- buffer = xmalloc (capacity);
+ buffer = XNEWVEC (char, capacity);
for (;;)
{
token = get_token_no_padding (pfile);
if (total_len + len > capacity)
{
capacity = (capacity + len) * 2;
- buffer = xrealloc (buffer, capacity);
+ buffer = XRESIZEVEC (char, buffer, capacity);
}
if (token->flags & PREV_WHITE)
buffer[total_len++] = ' ';
- total_len = (cpp_spell_token (pfile, token, (uchar *) &buffer[total_len])
+ total_len = (cpp_spell_token (pfile, token, (uchar *) &buffer[total_len],
+ true)
- (uchar *) buffer);
}
#pragma dependency. The string is malloced and the caller should
free it. Returns NULL on error. */
static const char *
-parse_include (cpp_reader *pfile, int *pangle_brackets)
+parse_include (cpp_reader *pfile, int *pangle_brackets,
+ const cpp_token ***buf)
{
char *fname;
const cpp_token *header;
header = get_token_no_padding (pfile);
if (header->type == CPP_STRING || header->type == CPP_HEADER_NAME)
{
- fname = xmalloc (header->val.str.len - 1);
+ fname = XNEWVEC (char, header->val.str.len - 1);
memcpy (fname, header->val.str.text + 1, header->val.str.len - 2);
fname[header->val.str.len - 2] = '\0';
*pangle_brackets = header->type == CPP_HEADER_NAME;
return NULL;
}
- check_eol (pfile);
+ if (buf == NULL || CPP_OPTION (pfile, discard_comments))
+ check_eol (pfile);
+ else
+ {
+ /* If we are not discarding comments, then gather them while
+ doing the eol check. */
+ *buf = check_eol_return_comments (pfile);
+ }
+
return fname;
}
{
const char *fname;
int angle_brackets;
+ const cpp_token **buf = NULL;
- fname = parse_include (pfile, &angle_brackets);
+ /* Re-enable saving of comments if requested, so that the include
+ callback can dump comments which follow #include. */
+ pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
+
+ fname = parse_include (pfile, &angle_brackets, &buf);
if (!fname)
+ {
+ if (buf)
+ XDELETEVEC (buf);
+ return;
+ }
+
+ if (!*fname)
+ {
+ cpp_error (pfile, CPP_DL_ERROR, "empty filename in #%s",
+ pfile->directive->name);
+ XDELETEVEC (fname);
+ if (buf)
+ XDELETEVEC (buf);
return;
+ }
/* Prevent #include recursion. */
if (pfile->line_table->depth >= CPP_STACK_MAX)
if (pfile->cb.include)
pfile->cb.include (pfile, pfile->directive_line,
- pfile->directive->name, fname, angle_brackets);
+ pfile->directive->name, fname, angle_brackets,
+ buf);
_cpp_stack_include (pfile, fname, angle_brackets, type);
}
- free ((void *) fname);
+ XDELETEVEC (fname);
+ if (buf)
+ XDELETEVEC (buf);
}
static void
{
const struct line_maps *line_table = pfile->line_table;
const struct line_map *map = &line_table->maps[line_table->used - 1];
+
+ /* skip_rest_of_line() may cause line table to be realloc()ed so note down
+ sysp right now. */
+
+ unsigned char map_sysp = map->sysp;
const cpp_token *token;
const char *new_file = map->to_file;
unsigned long new_lineno;
skip_rest_of_line (pfile);
_cpp_do_file_change (pfile, LC_RENAME, new_file, new_lineno,
- map->sysp);
+ map_sysp);
}
/* Interpret the # 44 "file" [flags] notation, which has slightly
const cpp_token *str = cpp_get_token (pfile);
if (str->type != CPP_STRING)
- cpp_error (pfile, CPP_DL_ERROR, "invalid #ident directive");
+ cpp_error (pfile, CPP_DL_ERROR, "invalid #%s directive",
+ pfile->directive->name);
else if (pfile->cb.ident)
pfile->cb.ident (pfile, pfile->directive_line, &str->val.str);
/* 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 allow_expansion, bool internal)
{
- struct pragma_entry *new;
+ struct pragma_entry *new_entry;
- new = (struct pragma_entry *)
+ new_entry = (struct pragma_entry *)
_cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
- new->pragma = pragma;
+ new_entry->pragma = pragma;
if (handler)
{
- new->is_nspace = 0;
- new->u.handler = handler;
+ new_entry->is_nspace = 0;
+ new_entry->u.handler = handler;
}
else
{
- new->is_nspace = 1;
- new->u.space = NULL;
+ new_entry->is_nspace = 1;
+ new_entry->u.space = NULL;
}
- new->next = *chain;
- *chain = new;
- return new;
+ new_entry->allow_expansion = allow_expansion;
+ new_entry->is_internal = internal;
+ new_entry->next = *chain;
+ *chain = new_entry;
+ return new_entry;
}
/* 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. If ALLOW_EXPANSION is set, allow macro
+ expansion while parsing pragma NAME. 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 allow_expansion, bool internal)
{
struct pragma_entry **chain = &pfile->pragmas;
struct pragma_entry *entry;
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,
+ allow_expansion, internal);
else if (!entry->is_nspace)
goto clash;
chain = &entry->u.space;
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, allow_expansion,
+ 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. If ALLOW_EXPANSION is set, allow macro
+ expansion while parsing pragma NAME. This function is exported
+ from libcpp. */
+void
+cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
+ pragma_cb handler, bool allow_expansion)
+{
+ register_pragma (pfile, space, name, handler, allow_expansion, false);
}
/* Register the pragmas the preprocessor itself handles. */
_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, false, 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, false, true);
+ register_pragma (pfile, "GCC", "system_header", do_pragma_system_header,
+ false, true);
+ register_pragma (pfile, "GCC", "dependency", do_pragma_dependency,
+ false, true);
}
/* Return the number of registered pragmas in PE. */
{
if (pe->is_nspace)
sd = save_registered_pragmas (pe->u.space, sd);
- *sd++ = xmemdup (HT_STR (&pe->pragma->ident),
- HT_LEN (&pe->pragma->ident),
- HT_LEN (&pe->pragma->ident) + 1);
+ *sd++ = (char *) xmemdup (HT_STR (&pe->pragma->ident),
+ HT_LEN (&pe->pragma->ident),
+ HT_LEN (&pe->pragma->ident) + 1);
}
return sd;
}
_cpp_save_pragma_names (cpp_reader *pfile)
{
int ct = count_registered_pragmas (pfile->pragmas);
- char **result = xnewvec (char *, ct);
+ char **result = XNEWVEC (char *, ct);
(void) save_registered_pragmas (pfile->pragmas, result);
return result;
}
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)
{
const cpp_token *token, *pragma_token = pfile->cur_token;
unsigned int count = 1;
+ /* Save the current position so that defer_pragmas mode can
+ copy the entire current line to a string. It will not work
+ to use _cpp_backup_tokens as that does not reverse buffer->cur. */
+ const uchar *line_start = CPP_BUFFER (pfile)->cur;
+
pfile->state.prevent_expansion++;
token = cpp_get_token (pfile);
if (p)
{
- /* Since the handler below doesn't get the line number, that it
- might need for diagnostics, make sure it has the right
- numbers in place. */
- if (pfile->cb.line_change)
- (*pfile->cb.line_change) (pfile, pragma_token, false);
- (*p->u.handler) (pfile);
+ if (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
+ numbers in place. */
+ if (pfile->cb.line_change)
+ (*pfile->cb.line_change) (pfile, pragma_token, false);
+ /* Never expand macros if handling a deferred pragma, since
+ the macro definitions now applicable may be different
+ from those at the point the pragma appeared. */
+ if (p->allow_expansion && !pfile->state.in_deferred_pragma)
+ pfile->state.prevent_expansion--;
+ (*p->u.handler) (pfile);
+ if (p->allow_expansion && !pfile->state.in_deferred_pragma)
+ pfile->state.prevent_expansion++;
+ }
+ else
+ {
+ /* Squirrel away the pragma text. Pragmas are
+ newline-terminated. */
+ const uchar *line_end;
+ uchar *s;
+ cpp_string body;
+ cpp_token *ptok;
+
+ 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)
{
const char *fname;
int angle_brackets, ordering;
- fname = parse_include (pfile, &angle_brackets);
+ fname = parse_include (pfile, &angle_brackets, NULL);
if (!fname)
return;
const unsigned char *src, *limit;
char *dest, *result;
- dest = result = alloca (in->len - 1);
+ dest = result = (char *) alloca (in->len - 1);
src = in->text + 1 + (in->text[0] == 'L');
limit = in->text + in->len - 1;
while (src < limit)
cpp_token *saved_cur_token = pfile->cur_token;
tokenrun *saved_cur_run = pfile->cur_run;
- pfile->context = xnew (cpp_context);
+ pfile->context = XNEW (cpp_context);
pfile->context->macro = 0;
pfile->context->prev = 0;
run_directive (pfile, T_PRAGMA, result, dest - result);
- free (pfile->context);
+ XDELETE (pfile->context);
pfile->context = saved_context;
pfile->cur_token = saved_cur_token;
pfile->cur_run = saved_cur_run;
_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);
"_Pragma takes a parenthesized string literal");
}
-/* Ignore #sccs on all systems. */
-static void
-do_sccs (cpp_reader *pfile ATTRIBUTE_UNUSED)
+/* 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);
+ void (*saved_line_change) (cpp_reader *, const cpp_token *, int)
+ = pfile->cb.line_change;
+
+ pfile->context = XNEW (cpp_context);
+ pfile->context->macro = 0;
+ pfile->context->prev = 0;
+ pfile->cb.line_change = NULL;
+ pfile->state.in_deferred_pragma = true;
+ CPP_OPTION (pfile, defer_pragmas) = false;
+
+ run_directive (pfile, T_PRAGMA, (const char *)s->text, s->len);
+
+ XDELETE (pfile->context);
+ pfile->context = saved_context;
+ pfile->cur_token = saved_cur_token;
+ pfile->cur_run = saved_cur_run;
+ pfile->cb.line_change = saved_line_change;
+ pfile->state.in_deferred_pragma = false;
+ CPP_OPTION (pfile, defer_pragmas) = saved_defer_pragmas;
}
/* Handle #ifdef. */
struct if_stack *ifs;
cpp_buffer *buffer = pfile->buffer;
- ifs = xobnew (&pfile->buffer_ob, struct if_stack);
+ ifs = XOBNEW (&pfile->buffer_ob, struct if_stack);
ifs->line = pfile->directive_line;
ifs->next = buffer->if_stack;
ifs->skip_elses = pfile->state.skipping || !skip;
else if (parse_answer (pfile, answerp, type) == 0)
{
unsigned int len = NODE_LEN (predicate->val.node);
- unsigned char *sym = alloca (len + 1);
+ unsigned char *sym = (unsigned char *) alloca (len + 1);
/* Prefix '#' to get it out of macro namespace. */
sym[0] = '#';
if (pfile->hash_table->alloc_subobject)
{
struct answer *temp_answer = new_answer;
- new_answer = pfile->hash_table->alloc_subobject (answer_size);
+ new_answer = (struct answer *) pfile->hash_table->alloc_subobject
+ (answer_size);
memcpy (new_answer, temp_answer, answer_size);
}
else
tack " 1" on the end. */
count = strlen (str);
- buf = alloca (count + 3);
+ buf = (char *) alloca (count + 3);
memcpy (buf, str, count);
p = strchr (str, '=');
_cpp_define_builtin (cpp_reader *pfile, const char *str)
{
size_t len = strlen (str);
- char *buf = alloca (len + 1);
+ char *buf = (char *) alloca (len + 1);
memcpy (buf, str, len);
buf[len] = '\n';
run_directive (pfile, T_DEFINE, buf, len);
cpp_undef (cpp_reader *pfile, const char *macro)
{
size_t len = strlen (macro);
- char *buf = alloca (len + 1);
+ char *buf = (char *) alloca (len + 1);
memcpy (buf, macro, len);
buf[len] = '\n';
run_directive (pfile, T_UNDEF, buf, len);
/* Copy the entire option so we can modify it. Change the first
"=" in the string to a '(', and tack a ')' on the end. */
- char *buf = alloca (count + 2);
+ char *buf = (char *) alloca (count + 2);
memcpy (buf, str, count);
if (p)
cpp_push_buffer (cpp_reader *pfile, const uchar *buffer, size_t len,
int from_stage3)
{
- cpp_buffer *new = xobnew (&pfile->buffer_ob, cpp_buffer);
+ cpp_buffer *new_buffer = XOBNEW (&pfile->buffer_ob, cpp_buffer);
/* Clears, amongst other things, if_stack and mi_cmacro. */
- memset (new, 0, sizeof (cpp_buffer));
+ memset (new_buffer, 0, sizeof (cpp_buffer));
- new->next_line = new->buf = buffer;
- new->rlimit = buffer + len;
- new->from_stage3 = from_stage3;
- new->prev = pfile->buffer;
- new->need_line = true;
+ new_buffer->next_line = new_buffer->buf = buffer;
+ new_buffer->rlimit = buffer + len;
+ new_buffer->from_stage3 = from_stage3;
+ new_buffer->prev = pfile->buffer;
+ new_buffer->need_line = true;
- pfile->buffer = new;
+ pfile->buffer = new_buffer;
- return new;
+ return new_buffer;
}
/* Pops a single buffer, with a file change call-back if appropriate.