#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "cpplib.h"
#include "cpphash.h"
static struct pragma_entry *insert_pragma_entry
PARAMS ((cpp_reader *, struct pragma_entry **, const cpp_hashnode *,
pragma_cb));
+static int count_registered_pragmas PARAMS ((struct pragma_entry *));
+static char ** save_registered_pragmas
+ PARAMS ((struct pragma_entry *, char **));
+static char ** restore_registered_pragmas
+ PARAMS ((cpp_reader *, struct pragma_entry *, char **));
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 *));
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 */ \
-SCCS_ENTRY /* 0 SVR4? */
-
-/* #sccs is not always recognized. */
-#ifdef SCCS_DIRECTIVE
-# define SCCS_ENTRY D(sccs, T_SCCS, EXTENSION, 0)
-#else
-# define SCCS_ENTRY /* nothing */
-#endif
+D(sccs, T_SCCS, EXTENSION, 0) /* 0 SVR4? */
/* Use the table to generate a series of prototypes, an enum for the
directive names, and an array of directive handlers. */
cpp_reader *pfile;
{
/* Discard all stacked contexts. */
- while (pfile->context != &pfile->base_context)
+ while (pfile->context->prev)
_cpp_pop_context (pfile);
/* Sweep up all tokens remaining on the line. */
prepare_directive_trad (pfile)
cpp_reader *pfile;
{
- if (pfile->directive == &dtable[T_DEFINE])
- CUR (pfile->context) = pfile->buffer->cur;
- else
+ if (pfile->directive != &dtable[T_DEFINE])
{
bool no_expand = (pfile->directive
&& ! (pfile->directive->flags & EXPAND));
pfile->out.cur - pfile->out.base);
}
- /* Report diagnostics on the line of the directive. */
- pfile->line = pfile->directive_line;
-
/* Stop ISO C from expanding anything. */
pfile->state.prevent_expansion++;
}
-/* Output diagnostics for a directive DIR. INDENTED is non-zero if
+/* Output diagnostics for a directive DIR. INDENTED is nonzero if
the '#' was indented. */
static void
directive_diagnostics (pfile, dir, indented)
}
}
-/* Check if we have a known directive. INDENTED is non-zero if the
+/* 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
- non-zero if the line of tokens has been handled, zero if we should
+ nonzero if the line of tokens has been handled, zero if we should
continue processing the line. */
int
_cpp_handle_directive (pfile, indented)
if (dname->type == CPP_NAME)
{
- if (dname->val.node->directive_index)
- dir = &dtable[dname->val.node->directive_index - 1];
+ if (dname->val.node->is_directive)
+ dir = &dtable[dname->val.node->directive_index];
}
- /* We do not recognise the # followed by a number extension in
+ /* We do not recognize the # followed by a number extension in
assembler code. */
else if (dname->type == CPP_NUMBER && CPP_OPTION (pfile, lang) != CLK_ASM)
{
"style of line directive is a GCC extension");
}
- pfile->directive = dir;
- if (CPP_OPTION (pfile, traditional))
- prepare_directive_trad (pfile);
-
if (dir)
{
/* If we have a directive that is not an opening conditional,
skipping or not, we should lex angle-bracketed headers
correctly, and maybe output some diagnostics. */
pfile->state.angled_headers = dir->flags & INCL;
+ pfile->state.directive_wants_padding = dir->flags & INCL;
if (! CPP_OPTION (pfile, preprocessed))
directive_diagnostics (pfile, dir, indented);
if (pfile->state.skipping && !(dir->flags & COND))
cpp_token_as_text (pfile, dname));
}
+ pfile->directive = dir;
+ if (CPP_OPTION (pfile, traditional))
+ prepare_directive_trad (pfile);
+
if (dir)
- {
- /* If we are processing a `#define' directive and we have been
- requested to expand comments into macros, then re-enable
- saving of comments. */
- if (dir == &dtable[T_DEFINE])
- pfile->state.save_comments =
- ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
-
- (*pfile->directive->handler) (pfile);
- }
+ (*pfile->directive->handler) (pfile);
else if (skip == 0)
_cpp_backup_tokens (pfile, 1);
{
cpp_push_buffer (pfile, (const uchar *) buf, count,
/* from_stage3 */ true, 1);
+ /* Disgusting hack. */
+ if (dir_no == T_PRAGMA)
+ pfile->buffer->inc = pfile->buffer->prev->inc;
start_directive (pfile);
/* We don't want a leading # to be interpreted as a directive. */
pfile->buffer->saved_flags = 0;
prepare_directive_trad (pfile);
(void) (*pfile->directive->handler) (pfile);
end_directive (pfile, 1);
+ if (dir_no == T_PRAGMA)
+ pfile->buffer->inc = NULL;
_cpp_pop_buffer (pfile);
}
In C++, it may not be any of the "named operators" either,
per C++98 [lex.digraph], [lex.key].
Finally, the identifier may not have been poisoned. (In that case
- the lexer has issued the error message for us.)
-
- Note that if we're copying comments into macro expansions, we
- could encounter comment tokens here, so eat them all up first. */
-
- if (! CPP_OPTION (pfile, discard_comments_in_macro_exp))
- {
- while (token->type == CPP_COMMENT)
- token = _cpp_lex_token (pfile);
- }
+ the lexer has issued the error message for us.) */
if (token->type == CPP_NAME)
{
if (node)
{
+ /* If we have been requested to expand comments into macros,
+ then re-enable saving of comments. */
+ pfile->state.save_comments =
+ ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
+
if (_cpp_create_definition (pfile, node))
if (pfile->cb.define)
(*pfile->cb.define) (pfile, pfile->directive_line, node);
if (node->flags & NODE_WARN)
cpp_error (pfile, DL_WARNING, "undefining \"%s\"", NODE_NAME (node));
+ if (CPP_OPTION (pfile, warn_unused_macros))
+ _cpp_warn_if_unused_macro (pfile, node, NULL);
+
_cpp_free_definition (node);
}
check_eol (pfile);
buffer = (unsigned char *) xmalloc (capacity);
for (;;)
{
- token = cpp_get_token (pfile);
+ token = get_token_no_padding (pfile);
if (token->type == CPP_GREATER || token->type == CPP_EOF)
break;
dir = pfile->directive->name;
/* Allow macro expansion. */
- header = cpp_get_token (pfile);
+ header = get_token_no_padding (pfile);
if (header->type != CPP_STRING && header->type != CPP_HEADER_NAME)
{
if (header->type != CPP_LESS)
return NULL;
}
+ check_eol (pfile);
return header;
}
cpp_reader *pfile;
enum include_type type;
{
- const cpp_token *header;
+ const cpp_token *header = parse_include (pfile);
+ if (!header)
+ return;
- /* For #include_next, if this is the primary source file, warn and
- use the normal search logic. */
- if (type == IT_INCLUDE_NEXT && ! pfile->buffer->prev)
- {
- cpp_error (pfile, DL_WARNING, "#include_next in primary source file");
- type = IT_INCLUDE;
- }
- else if (type == IT_IMPORT && CPP_OPTION (pfile, warn_import))
+ /* Prevent #include recursion. */
+ if (pfile->line_maps.depth >= CPP_STACK_MAX)
{
- CPP_OPTION (pfile, warn_import) = 0;
- cpp_error (pfile, DL_WARNING,
- "#import is obsolete, use an #ifndef wrapper in the header file");
+ cpp_error (pfile, DL_ERROR, "#include nested too deeply");
+ return;
}
- header = parse_include (pfile);
- if (header)
- {
- /* Prevent #include recursion. */
- if (pfile->line_maps.depth >= CPP_STACK_MAX)
- cpp_error (pfile, DL_ERROR, "#include nested too deeply");
- else
- {
- check_eol (pfile);
- /* Get out of macro context, if we are. */
- skip_rest_of_line (pfile);
- if (pfile->cb.include)
- (*pfile->cb.include) (pfile, pfile->directive_line,
- pfile->directive->name, header);
+ /* Get out of macro context, if we are. */
+ skip_rest_of_line (pfile);
- _cpp_execute_include (pfile, header, type);
- }
- }
+ if (pfile->cb.include)
+ (*pfile->cb.include) (pfile, pfile->directive_line,
+ pfile->directive->name, header);
+
+ _cpp_execute_include (pfile, header, type);
}
static void
do_import (pfile)
cpp_reader *pfile;
{
+ if (CPP_OPTION (pfile, warn_import))
+ {
+ CPP_OPTION (pfile, warn_import) = 0;
+ cpp_error (pfile, DL_WARNING,
+ "#import is obsolete, use an #ifndef wrapper in the header file");
+ }
+
do_include_common (pfile, IT_IMPORT);
}
do_include_next (pfile)
cpp_reader *pfile;
{
- do_include_common (pfile, IT_INCLUDE_NEXT);
+ enum include_type type = IT_INCLUDE_NEXT;
+
+ /* If this is the primary source file, warn and use the normal
+ search logic. */
+ if (! pfile->buffer->prev)
+ {
+ cpp_error (pfile, DL_WARNING,
+ "#include_next in primary source file");
+ type = IT_INCLUDE;
+ }
+ do_include_common (pfile, type);
}
/* Subroutine of do_linemarker. Read possible flags after file name.
cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency);
}
+/* Return the number of registered pragmas in PE. */
+
+static int
+count_registered_pragmas (pe)
+ struct pragma_entry *pe;
+{
+ int ct = 0;
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ ct += count_registered_pragmas (pe->u.space);
+ ct++;
+ }
+ return ct;
+}
+
+/* Save into SD the names of the registered pragmas referenced by PE,
+ and return a pointer to the next free space in SD. */
+
+static char **
+save_registered_pragmas (pe, sd)
+ struct pragma_entry *pe;
+ char **sd;
+{
+ for (; pe != NULL; pe = pe->next)
+ {
+ 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);
+ }
+ return sd;
+}
+
+/* Return a newly-allocated array which saves the names of the
+ registered pragmas. */
+
+char **
+_cpp_save_pragma_names (pfile)
+ cpp_reader *pfile;
+{
+ int ct = count_registered_pragmas (pfile->pragmas);
+ char **result = xnewvec (char *, ct);
+ (void) save_registered_pragmas (pfile->pragmas, result);
+ return result;
+}
+
+/* Restore from SD the names of the registered pragmas referenced by PE,
+ and return a pointer to the next unused name in SD. */
+
+static char **
+restore_registered_pragmas (pfile, pe, sd)
+ cpp_reader *pfile;
+ struct pragma_entry *pe;
+ char **sd;
+{
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ sd = restore_registered_pragmas (pfile, pe->u.space, sd);
+ pe->pragma = cpp_lookup (pfile, U *sd, strlen (*sd));
+ free (*sd);
+ sd++;
+ }
+ return sd;
+}
+
+/* Restore the names of the registered pragmas from SAVED. */
+
+void
+_cpp_restore_pragma_names (pfile, saved)
+ cpp_reader *pfile;
+ char **saved;
+{
+ (void) restore_registered_pragmas (pfile, pfile->pragmas, saved);
+ free (saved);
+}
+
/* 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
do_pragma_once (pfile)
cpp_reader *pfile;
{
- cpp_error (pfile, DL_WARNING, "#pragma once is obsolete");
+ if (CPP_OPTION (pfile, warn_deprecated))
+ cpp_error (pfile, DL_WARNING, "#pragma once is obsolete");
if (pfile->buffer->prev == NULL)
cpp_error (pfile, DL_WARNING, "#pragma once in main file");
}
*dest = '\0';
- run_directive (pfile, T_PRAGMA, result, dest - result);
+ /* Ugh; an awful kludge. We are really not set up to be lexing
+ tokens when in the middle of a macro expansion. Use a new
+ context to force cpp_get_token to lex, and so skip_rest_of_line
+ doesn't go beyond the end of the text. Also, remember the
+ current lexing position so we can return to it later.
+
+ Something like line-at-a-time lexing should remove the need for
+ this. */
+ {
+ cpp_context *saved_context = pfile->context;
+ cpp_token *saved_cur_token = pfile->cur_token;
+ tokenrun *saved_cur_run = pfile->cur_run;
+
+ pfile->context = xnew (cpp_context);
+ pfile->context->macro = 0;
+ pfile->context->prev = 0;
+ run_directive (pfile, T_PRAGMA, result, dest - result);
+ free (pfile->context);
+ pfile->context = saved_context;
+ pfile->cur_token = saved_cur_token;
+ pfile->cur_run = saved_cur_run;
+ pfile->line--;
+ }
+
+ /* See above comment. For the moment, we'd like
+
+ token1 _Pragma ("foo") token2
+
+ to be output as
+
+ token1
+ # 7 "file.c"
+ #pragma foo
+ # 7 "file.c"
+ token2
+
+ Getting the line markers is a little tricky. */
+ if (pfile->cb.line_change)
+ (*pfile->cb.line_change) (pfile, pfile->cur_token, false);
}
/* Handle the _Pragma operator. */
{
const cpp_token *string = get__Pragma_string (pfile);
- if (!string)
+ if (string)
+ destringize_and_run (pfile, &string->val.str);
+ else
cpp_error (pfile, DL_ERROR,
"_Pragma takes a parenthesized string literal");
- else
- {
- /* Ideally, we'd like
- token1 _Pragma ("foo") token2
- to be output as
- token1
- # 7 "file.c"
- #pragma foo
- # 7 "file.c"
- token2
- Getting these correct line markers is a little tricky. */
-
- unsigned int orig_line = pfile->line;
- destringize_and_run (pfile, &string->val.str);
- pfile->line = orig_line;
- pfile->buffer->saved_flags = BOL;
- }
}
-/* Just ignore #sccs, on systems where we define it at all. */
-#ifdef SCCS_DIRECTIVE
+/* Just ignore #sccs on all systems. */
static void
do_sccs (pfile)
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
}
-#endif
/* Handle #ifdef. */
static void
const cpp_hashnode *node = lex_macro_node (pfile);
if (node)
- skip = node->type != NT_MACRO;
-
- if (node)
- check_eol (pfile);
+ {
+ skip = node->type != NT_MACRO;
+ _cpp_mark_macro_used (node);
+ check_eol (pfile);
+ }
}
push_conditional (pfile, skip, T_IFDEF, 0);
if (! pfile->state.skipping)
{
node = lex_macro_node (pfile);
- if (node)
- skip = node->type == NT_MACRO;
if (node)
- check_eol (pfile);
+ {
+ skip = node->type == NT_MACRO;
+ _cpp_mark_macro_used (node);
+ check_eol (pfile);
+ }
}
push_conditional (pfile, skip, T_IFNDEF, node);
}
/* Test an assertion within a preprocessor conditional. Returns
- non-zero on failure, zero on success. On success, the result of
- the test is written into VALUE. */
+ nonzero on failure, zero on success. On success, the result of
+ the test is written into VALUE, otherwise the value 0. */
int
_cpp_test_assertion (pfile, value)
cpp_reader *pfile;
cpp_hashnode *node;
node = parse_assertion (pfile, &answer, T_IF);
+
+ /* For recovery, an erroneous assertion expression is handled as a
+ failing assertion. */
+ *value = 0;
+
if (node)
*value = (node->type == NT_ASSERTION &&
(answer == 0 || *find_answer (node, answer) != 0));
pfile->buffer = new;
- if (CPP_OPTION (pfile, traditional))
- _cpp_set_trad_context (pfile);
-
return new;
}
_cpp_maybe_push_include_file (pfile);
}
}
-
- if (pfile->buffer && CPP_OPTION (pfile, traditional))
- _cpp_set_trad_context (pfile);
}
-/* Enter all recognised directives in the hash table. */
+/* Enter all recognized directives in the hash table. */
void
_cpp_init_directives (pfile)
cpp_reader *pfile;
for (i = 0; i < (unsigned int) N_DIRECTIVES; i++)
{
node = cpp_lookup (pfile, dtable[i].name, dtable[i].length);
- node->directive_index = i + 1;
+ node->is_directive = 1;
+ node->directive_index = i;
}
}