aboutsummaryrefslogtreecommitdiff
path: root/gcc/cpplib.c
diff options
context:
space:
mode:
authorZack Weinberg <zack@gcc.gnu.org>2000-07-04 01:58:21 +0000
committerZack Weinberg <zack@gcc.gnu.org>2000-07-04 01:58:21 +0000
commit041c31944c94d5ee089bd569c4361fbc3d2acaea (patch)
tree1c91fa44eb386dd706e44d139ed980ea94f05cae /gcc/cpplib.c
parent4f647814cefff8ee95ac918a8484d5da8c415825 (diff)
downloadgcc-041c31944c94d5ee089bd569c4361fbc3d2acaea.zip
gcc-041c31944c94d5ee089bd569c4361fbc3d2acaea.tar.gz
gcc-041c31944c94d5ee089bd569c4361fbc3d2acaea.tar.bz2
top level:
2000-07-03 Zack Weinberg <zack@wolery.cumb.org> * fix-header.c (struct partial_proto): Remove unnecessary fields. (recognized_extern, recognized_function, read_scan_file): Update for new scheme. (check_protection): It's still a multiple include guard even if it doesn't always trigger. * scan-decls.c (skip_to_closing_brace, scan_decls): Update for new scheme. * scan.h: Declare struct cpp_token. Update prototypes. 2000-07-03 Neil Booth <neilb@earthling.net> Zack Weinberg <zack@wolery.cumb.org> Complete overhaul of the lexer and macro expander. * cpphash.c (object_defn, funct_defn, push_macro_expansion, arg, arglist, argdata, reflist, collect_objlike_expansion, collect_funlike_expansion, collect_params, warn_trad_stringify, trad_stringify, duplicate_arg_p, add_pat, unsafe_chars, macarg, compare_defs, special_symbol, scan_arguments, stringify, funlike_macroexpand, _cpp_quote_string, monthnames): Delete. (cpp_lookup, _cpp_free_definition, dump_funlike_macro, _cpp_create_definition, _cpp_dump_definition, dump_hash_helper): Adjust. (find_param, count_params, parse_define, var_args_str, check_macro_redefinition, save_expansion): New. * cpplex.c (skip_block_comment, skip_line_comment, parse_name, parse_string, output_line_command, trigraph_replace, lex_line, cpp_push_buffer, cpp_pop_buffer, cpp_output_tokens, cpp_scan_buffer_nooutput, cpp_scan_buffer, cpp_free_toklist, cpp_idcmp, _cpp_get_directive_token, _cpp_init_input_buffer, _cpp_skip_rest_of_line): Modify. (maybe_macroexpand, skip_comment, copy_comment, skip_string, find_position, null_warning, bump_column, expand_name_space, pedantic_whitespace, _cpp_output_list, _cpp_slice_toklist, _cpp_squeeze_toklist, _cpp_scan_until, _cpp_skip_hspace, _cpp_parse_name, _cpp_lex_token, cpp_get_non_space_token, _cpp_prescan): Delete. (dump_param_spelling, process_directive, lex_next, is_macro_disabled, stringify_arg, expand_context_stack, output_token, make_string_token, alloc_number_token, special_symbol, duplicate_token, maybe_paste_with_next, can_paste, prevent_macro_expansion, restore_macro_expansion, get_temp_token, release_temp_tokens, quote_string, token_names, token_spellings, _cpp_expand_name_space, _cpp_glue_header_name, _cpp_reserve_name_space, digraph_spellings, trigraph_ok, skip_whitespace, save_comment, placemarker_token, eof_token, cpp_context, macro_args, get_raw_token, parse_arg, parse_args, save_token, push_arg_context, push_macro_context, pop_context, do_pop_context, free_macro_args, _cpp_get_line, _cpp_run_directive): New. * cpplib.c (validate_else, parse_include, push_conditional, pass_thru_directive, read_line_number, parse_ifdef, detect_if_not_defined, _cpp_check_directive, do_define, do_undef, do_include, do_import, do_include_next, do_error, do_warning, do_ident, do_pragma, pragma_dispatch, gcc_pragmas, top_pragmas, do_pragma_gcc, do_pragma_implementation, do_pragma_poison, do_pragma_system_header, do_pragma_dependency, do_sccs, do_ifdef, do_ifndef, do_else, dl_elif, do_endif, _cpp_unwind_if_stack, do_assert, do_unassert, cpp_define, cpp_undef, cpp_assert, cpp_unassert, cpp_defined): Update for new scheme. (strtoul_for_line, get_define_node, dump_macro_name, _cpp_check_linemarker, _cpp_parse_assertion): New. (_cpp_handle_directive, do_pragma_default): Delete. * cpphash.h (struct predicate): Now struct answer. (enum spell_type, struct token_spelling, struct directive, directive_handler): New. Update prototypes. Remove unused macros. * cpplib.h: Update prototypes. Remove unused macros, structure definitions, and fields. * cpperror.c (print_containing_files, v_message): Adjust. * cppexp.c (parse_assertion, lex, parse_escape, _cpp_parse_expr): Adjust. * cppfiles.c (open_include_file, _cpp_execute_include, _cpp_compare_file_date, cpp_read_file, read_include_file): Adjust. * cppinit.c (dump_special_to_buffer): Delete. (append_include_chain, merge_include_chains, cpp_reader_init, cpp_cleanup, initialize_builtins, builtin_array, cpp_start_read, cpp_finish, handle_option, print_help): Adjust. * cppmain.c (main): Adjust. testsuite: 2000-07-03 Zack Weinberg <zack@wolery.cumb.org> * testsuite/gcc.dg/cpp/19951025-1.c: Adjust regexps. * testsuite/gcc.dg/cpp/19990703-1.c: Likewise. * testsuite/gcc.dg/cpp/20000625-1.c: Likewise. * testsuite/gcc.dg/cpp/20000625-2.c: Likewise. * testsuite/gcc.dg/cpp/macro1.c, testsuite/gcc.dg/cpp/paste1.c, testsuite/gcc.dg/cpp/paste2.c, testsuite/gcc.dg/cpp/paste3.c, testsuite/gcc.dg/cpp/paste4.c, testsuite/gcc.dg/cpp/strify1.c, testsuite/gcc.dg/cpp/strify2.c: New tests. From-SVN: r34859
Diffstat (limited to 'gcc/cpplib.c')
-rw-r--r--gcc/cpplib.c1561
1 files changed, 677 insertions, 884 deletions
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index 26396df..9e8c4c7 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -27,23 +27,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "intl.h"
#include "symcat.h"
-/* `struct directive' defines one #-directive, including how to handle it. */
-
-struct directive
-{
- directive_handler func; /* Function to handle directive. */
- const U_CHAR *name; /* Name of directive. */
- unsigned short length; /* Length of name. */
- unsigned short flags; /* Flags describing this directive. */
-};
-
/* Stack of conditionals currently in progress
(including both successful and failing conditionals). */
struct if_stack
{
struct if_stack *next;
- int lineno; /* line number where condition started */
+ unsigned int lineno; /* line number where condition started */
+ unsigned int colno; /* and column */
int was_skipping; /* value of pfile->skipping before this if */
const cpp_hashnode *cmacro; /* macro name for #ifndef around entire file */
int type; /* type of last directive seen in this group */
@@ -51,30 +42,26 @@ struct if_stack
/* Forward declarations. */
-static void validate_else PARAMS ((cpp_reader *, const U_CHAR *));
-static unsigned int parse_include PARAMS ((cpp_reader *, const U_CHAR *, int));
-static void push_conditional PARAMS ((cpp_reader *, int, int,
- const cpp_hashnode *));
-static void pass_thru_directive PARAMS ((const U_CHAR *, size_t,
- cpp_reader *, int));
-static int read_line_number PARAMS ((cpp_reader *, int *));
-static const cpp_hashnode *parse_ifdef PARAMS ((cpp_reader *, const U_CHAR *));
-static const cpp_hashnode *detect_if_not_defined PARAMS ((cpp_reader *));
-
-/* Values for the flags field of the table below. KANDR and COND
- directives come from traditional (K&R) C. The difference is, if we
- care about it while skipping a failed conditional block, its origin
- is COND. STDC89 directives come from the 1989 C standard.
- EXTENSION directives are extensions, with origins noted below. */
+static void validate_else PARAMS ((cpp_reader *, const U_CHAR *));
+static int parse_include PARAMS ((cpp_reader *, const U_CHAR *, int,
+ const U_CHAR **, unsigned int *,
+ int *));
+static void push_conditional PARAMS ((cpp_reader *, int, int,
+ const cpp_hashnode *));
+static void pass_thru_directive PARAMS ((cpp_reader *));
+static int read_line_number PARAMS ((cpp_reader *, int *));
+static int strtoul_for_line PARAMS ((const U_CHAR *, unsigned int,
+ unsigned long *));
-#define KANDR 0
-#define COND 1
-#define STDC89 2
-#define EXTENSION 3
+static const cpp_hashnode *parse_ifdef PARAMS ((cpp_reader *, const U_CHAR *));
+static const cpp_hashnode *detect_if_not_defined
+ PARAMS ((cpp_reader *));
+static cpp_hashnode *get_define_node PARAMS ((cpp_reader *));
+static void dump_macro_name PARAMS ((cpp_reader *, cpp_hashnode *));
-#define ORIGIN_MASK 3
-#define ORIGIN(f) ((f) & ORIGIN_MASK)
-#define TRAD_DIRECT_P(f) (ORIGIN (f) == KANDR || ORIGIN (f) == COND)
+/* Utility. */
+#define str_match(sym, len, str) \
+((len) == (sizeof (str) - 1) && !ustrncmp ((sym), U(str), sizeof (str) - 1))
/* This is the table of directive handlers. It is ordered by
frequency of occurrence; the numbers at the end are directive
@@ -88,31 +75,31 @@ static const cpp_hashnode *detect_if_not_defined PARAMS ((cpp_reader *));
/* #sccs is not always recognized. */
#ifdef SCCS_DIRECTIVE
-# define SCCS_ENTRY D(sccs, T_SCCS, EXTENSION) /* 0 - SVR2? */
+# define SCCS_ENTRY D(sccs, T_SCCS, EXTENSION, 0)
#else
# define SCCS_ENTRY /* nothing */
#endif
-#define DIRECTIVE_TABLE \
-D(define, T_DEFINE = 0, KANDR) /* 270554 */ \
-D(include, T_INCLUDE, KANDR | SYNTAX_INCLUDE) /* 52262 */ \
-D(endif, T_ENDIF, COND) /* 45855 */ \
-D(ifdef, T_IFDEF, COND) /* 22000 */ \
-D(if, T_IF, COND) /* 18162 */ \
-D(else, T_ELSE, COND) /* 9863 */ \
-D(ifndef, T_IFNDEF, COND) /* 9675 */ \
-D(undef, T_UNDEF, KANDR) /* 4837 */ \
-D(line, T_LINE, KANDR) /* 2465 */ \
-D(elif, T_ELIF, COND) /* 610 */ \
-D(error, T_ERROR, STDC89) /* 475 */ \
-D(pragma, T_PRAGMA, STDC89) /* 195 */ \
-D(warning, T_WARNING, EXTENSION) /* 22 GNU */ \
-D(include_next, T_INCLUDE_NEXT, EXTENSION | SYNTAX_INCLUDE) /* 19 GNU */ \
-D(ident, T_IDENT, EXTENSION) /* 11 SVR4 */ \
-D(import, T_IMPORT, EXTENSION | SYNTAX_INCLUDE) /* 0 ObjC */ \
-D(assert, T_ASSERT, EXTENSION) /* 0 SVR4 */ \
-D(unassert, T_UNASSERT, EXTENSION) /* 0 SVR4 */ \
-SCCS_ENTRY
+#define DIRECTIVE_TABLE \
+D(define, T_DEFINE = 0, KANDR, COMMENTS) /* 270554 */ \
+D(include, T_INCLUDE, KANDR, EXPAND | INCL) /* 52262 */ \
+D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \
+D(ifdef, T_IFDEF, KANDR, COND) /* 22000 */ \
+D(if, T_IF, KANDR, COND | EXPAND) /* 18162 */ \
+D(else, T_ELSE, KANDR, COND) /* 9863 */ \
+D(ifndef, T_IFNDEF, KANDR, COND) /* 9675 */ \
+D(undef, T_UNDEF, KANDR, 0) /* 4837 */ \
+D(line, T_LINE, KANDR, EXPAND) /* 2465 */ \
+D(elif, T_ELIF, KANDR, COND | EXPAND) /* 610 */ \
+D(error, T_ERROR, STDC89, 0) /* 475 */ \
+D(pragma, T_PRAGMA, STDC89, 0) /* 195 */ \
+D(warning, T_WARNING, EXTENSION, 0) /* 22 GNU */ \
+D(include_next, T_INCLUDE_NEXT, EXTENSION, EXPAND | INCL) /* 19 GNU */ \
+D(ident, T_IDENT, EXTENSION, 0) /* 11 SVR4 */ \
+D(import, T_IMPORT, EXTENSION, EXPAND | INCL) /* 0 ObjC */ \
+D(assert, T_ASSERT, EXTENSION, 0) /* 0 SVR4 */ \
+D(unassert, T_UNASSERT, EXTENSION, 0) /* 0 SVR4 */ \
+SCCS_ENTRY /* 0 SVR2? */
/* Use the table to generate a series of prototypes, an enum for the
directive names, and an array of directive handlers. */
@@ -122,11 +109,11 @@ SCCS_ENTRY
pointers to functions returning void. */
/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */
-#define D(name, t, f) static int CONCAT2(do_,name) PARAMS ((cpp_reader *));
+#define D(name, t, o, f) static int CONCAT2(do_,name) PARAMS ((cpp_reader *));
DIRECTIVE_TABLE
#undef D
-#define D(n, tag, f) tag,
+#define D(n, tag, o, f) tag,
enum
{
DIRECTIVE_TABLE
@@ -135,9 +122,9 @@ enum
#undef D
/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */
-#define D(name, t, flags) \
+#define D(name, t, origin, flags) \
{ CONCAT2(do_,name), (const U_CHAR *) STRINGX(name), \
- sizeof STRINGX(name) - 1, flags },
+ sizeof STRINGX(name) - 1, origin, flags },
static const struct directive dtable[] =
{
DIRECTIVE_TABLE
@@ -147,292 +134,237 @@ DIRECTIVE_TABLE
/* Check if a token's name matches that of a known directive. Put in
this file to save exporting dtable and other unneeded information. */
-void
-_cpp_check_directive (list, token)
- cpp_toklist *list;
- cpp_token *token;
+const struct directive *
+_cpp_check_directive (pfile, token, bol)
+ cpp_reader *pfile;
+ const cpp_token *token;
+ int bol;
{
const U_CHAR *name = token->val.name.text;
size_t len = token->val.name.len;
unsigned int i;
- list->dirno = -1;
- list->flags &= ~SYNTAX_INCLUDE;
+ /* If we are rescanning preprocessed input, don't obey any directives
+ other than # nnn. */
+ if (CPP_OPTION (pfile, preprocessed))
+ return 0;
for (i = 0; i < N_DIRECTIVES; i++)
- if (dtable[i].length == len && !ustrncmp (dtable[i].name, name, len))
+ if (dtable[i].length == len && !memcmp (dtable[i].name, name, len))
{
- list->dirno = i;
- if (dtable[i].flags & SYNTAX_INCLUDE)
- list->flags |= SYNTAX_INCLUDE;
- break;
+ /* If we are skipping a failed conditional group, all non-conditional
+ directives are ignored. */
+ if (pfile->skipping && !(dtable[i].flags & COND))
+ return 0;
+
+ /* In -traditional mode, a directive is ignored unless its #
+ is in column 1. */
+ if (!bol && dtable[i].origin == KANDR && CPP_WTRADITIONAL (pfile))
+ cpp_warning (pfile, "traditional C ignores #%s with the # indented",
+ dtable[i].name);
+
+ if (!bol && CPP_TRADITIONAL (pfile))
+ return 0;
+
+ /* Issue -pedantic warnings for extended directives. */
+ if (CPP_PEDANTIC (pfile) && dtable[i].origin == EXTENSION)
+ cpp_pedwarn (pfile, "ISO C does not allow #%s", dtable[i].name);
+
+ /* -Wtraditional gives warnings about directives with inappropriate
+ indentation of #. */
+ if (bol && dtable[i].origin != KANDR && CPP_WTRADITIONAL (pfile))
+ cpp_warning (pfile,
+ "suggest hiding #%s from traditional C with an indented #",
+ dtable[i].name);
+
+ return &dtable[i];
}
-}
-/* Handle a possible # directive.
- '#' has already been read. */
+ return 0;
+}
-int
-_cpp_handle_directive (pfile)
+const struct directive *
+_cpp_check_linemarker (pfile, token, bol)
cpp_reader *pfile;
+ const cpp_token *token ATTRIBUTE_UNUSED;
+ int bol;
{
- int i;
- int hash_at_bol;
- unsigned int len;
- U_CHAR *ident;
- long old_written = CPP_WRITTEN (pfile);
- enum cpp_ttype tok;
-
- if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
- {
- cpp_ice (pfile, "handle_directive called on macro buffer");
- return 0;
- }
-
- /* -traditional directives are recognized only with the # in column 1. */
- hash_at_bol = CPP_IN_COLUMN_1 (pfile);
-
- /* Scan the next token, then pretend we didn't. */
- CPP_SET_MARK (pfile);
- pfile->no_macro_expand++;
- tok = _cpp_get_directive_token (pfile);
- pfile->no_macro_expand--;
-
- ident = pfile->token_buffer + old_written;
- len = CPP_PWRITTEN (pfile) - ident;
- CPP_SET_WRITTEN (pfile, old_written);
- CPP_GOTO_MARK (pfile);
-
/* # followed by a number is equivalent to #line. Do not recognize
this form in assembly language source files or skipped
conditional groups. Complain about this form if we're being
pedantic, but not if this is regurgitated input (preprocessed or
fed back in by the C++ frontend). */
- if (tok == CPP_NUMBER)
- {
- if (pfile->skipping || CPP_OPTION (pfile, lang_asm))
- return 0;
-
- if (CPP_PEDANTIC (pfile)
- && CPP_BUFFER (pfile)->inc
- && ! CPP_OPTION (pfile, preprocessed))
- cpp_pedwarn (pfile, "# followed by integer");
- i = T_LINE;
- goto process_directive;
- }
+ if (pfile->skipping || CPP_OPTION (pfile, lang_asm))
+ return 0;
- /* If we are rescanning preprocessed input, don't obey any directives
- other than # nnn. */
- else if (CPP_OPTION (pfile, preprocessed))
+ if (CPP_PEDANTIC (pfile) && CPP_BUFFER (pfile)->inc
+ && ! CPP_OPTION (pfile, preprocessed))
+ cpp_pedwarn (pfile, "# followed by integer");
+
+ /* In -traditional mode, a directive is ignored unless its #
+ is in column 1. */
+ if (!bol && CPP_WTRADITIONAL (pfile))
+ cpp_warning (pfile, "traditional C ignores #%s with the # indented",
+ dtable[T_LINE].name);
+
+ if (!bol && CPP_TRADITIONAL (pfile))
return 0;
+
+ return &dtable[T_LINE];
+}
- /* A line of just # becomes blank. */
- else if (tok == CPP_VSPACE)
- return 1;
+static void
+dump_macro_name (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ CPP_PUTS (pfile, "#define ", sizeof "#define " - 1);
+ CPP_PUTS (pfile, node->name, node->length);
+}
- /* A NAME token might in fact be a directive! */
- else if (tok == CPP_NAME)
- {
- for (i = 0; i < N_DIRECTIVES; i++)
- {
- if (dtable[i].length == len
- && !ustrncmp (dtable[i].name, ident, len))
- goto real_directive;
- }
- /* Don't complain about invalid directives in assembly source,
- we don't know where the comments are, and # may introduce
- assembler pseudo-ops. Don't complain about invalid directives
- in skipped conditional groups (6.10 p4). */
- if (!pfile->skipping && !CPP_OPTION (pfile, lang_asm))
- cpp_error (pfile, "invalid preprocessing directive #%.*s",
- (int) len, ident);
- return 0;
- }
- /* And anything else means the # wasn't a directive marker. */
- else
- return 0;
+/* Pass the current directive through to the output file. */
+static void
+pass_thru_directive (pfile)
+ cpp_reader *pfile;
+{
+ /* XXX This output may be genuinely needed even when there is no
+ printer. */
+ if (! pfile->printer)
+ return;
+ /* Flush first (temporary). */
+ cpp_output_tokens (pfile, pfile->printer, pfile->token_list.line);
+ _cpp_dump_list (pfile, &pfile->token_list, pfile->first_directive_token, 1);
+}
- real_directive:
+static cpp_hashnode *
+get_define_node (pfile)
+ cpp_reader *pfile;
+{
+ cpp_hashnode *node;
+ const cpp_token *token;
+ const U_CHAR *sym;
+ unsigned int len;
- /* If we are skipping a failed conditional group, all non-conditional
- directives are ignored. */
- if (pfile->skipping && ORIGIN (dtable[i].flags) != COND)
- return 0;
+ /* Skip any -C comments. */
+ while ((token = cpp_get_token (pfile))->type == CPP_COMMENT)
+ ;
- /* In -traditional mode, a directive is ignored unless its # is in
- column 1. */
- if (CPP_TRADITIONAL (pfile) && !hash_at_bol)
+ if (token->type != CPP_NAME)
{
- if (CPP_WTRADITIONAL (pfile))
- cpp_warning (pfile, "ignoring #%s because of its indented #",
- dtable[i].name);
+ cpp_error_with_line (pfile, pfile->token_list.line, token->col,
+ "macro names must be identifiers");
return 0;
}
- /* no_directives is set when we are parsing macro arguments. Directives
- in macro arguments are undefined behavior (C99 6.10.3.11); this
- implementation chooses to make them hard errors. */
- if (pfile->no_directives)
+ /* That identifier is not allowed to be "defined". See predefined
+ macro names (6.10.8.4). */
+ len = token->val.name.len;
+ sym = token->val.name.text;
+ if (str_match (sym, len, "defined"))
{
- cpp_error (pfile, "#%s may not be used inside a macro argument",
- dtable[i].name);
- _cpp_skip_rest_of_line (pfile);
- return 1;
+ cpp_error_with_line (pfile, pfile->token_list.line, token->col,
+ "\"defined\" is not a legal macro name");
+ return 0;
}
- /* Issue -pedantic warnings for extended directives. */
- if (CPP_PEDANTIC (pfile) && ORIGIN (dtable[i].flags) == EXTENSION)
- cpp_pedwarn (pfile, "ISO C does not allow #%s", dtable[i].name);
-
- /* -Wtraditional gives warnings about directives with inappropriate
- indentation of #. */
- if (CPP_WTRADITIONAL (pfile))
+ node = cpp_lookup (pfile, sym, len);
+ /* Check for poisoned identifiers now. */
+ if (node->type == T_POISON)
{
- if (!hash_at_bol && TRAD_DIRECT_P (dtable[i].flags))
- cpp_warning (pfile, "traditional C ignores #%s with the # indented",
- dtable[i].name);
- else if (hash_at_bol && ! TRAD_DIRECT_P (dtable[i].flags))
- cpp_warning (pfile,
- "suggest hiding #%s from traditional C with an indented #",
- dtable[i].name);
+ cpp_error (pfile, "attempt to use poisoned \"%.*s\"", (int) len, sym);
+ return 0;
}
- /* Unfortunately, it's necessary to scan the directive name again,
- now we know we're going to consume it. FIXME. */
-
- pfile->no_macro_expand++;
- _cpp_get_directive_token (pfile);
- pfile->no_macro_expand--;
- CPP_SET_WRITTEN (pfile, old_written);
-
- process_directive:
- (void) (*dtable[i].func) (pfile);
- return 1;
-}
-
-/* Pass a directive through to the output file.
- BUF points to the contents of the directive, as a contiguous string.
- LEN is the length of the string pointed to by BUF.
- KEYWORD is the keyword-table entry for the directive. */
-
-static void
-pass_thru_directive (buf, len, pfile, keyword)
- const U_CHAR *buf;
- size_t len;
- cpp_reader *pfile;
- int keyword;
-{
- const struct directive *kt = &dtable[keyword];
- register unsigned klen = kt->length;
-
- CPP_RESERVE (pfile, 1 + klen + len);
- CPP_PUTC_Q (pfile, '#');
- CPP_PUTS_Q (pfile, kt->name, klen);
- if (len != 0 && buf[0] != ' ')
- CPP_PUTC_Q (pfile, ' ');
- CPP_PUTS_Q (pfile, buf, len);
+ return node;
}
/* Process a #define command. */
-
static int
do_define (pfile)
cpp_reader *pfile;
{
cpp_hashnode *node;
- int len;
- const U_CHAR *sym;
- cpp_toklist *list = &pfile->directbuf;
- pfile->no_macro_expand++;
- CPP_OPTION (pfile, discard_comments)++;
+ if ((node = get_define_node (pfile)))
+ if (_cpp_create_definition (pfile, node))
+ {
+ if (CPP_OPTION (pfile, debug_output)
+ || CPP_OPTION (pfile, dump_macros) == dump_definitions)
+ _cpp_dump_definition (pfile, node);
+ else if (CPP_OPTION (pfile, dump_macros) == dump_names)
+ dump_macro_name (pfile, node);
+ }
+ return 0;
+}
+
+/* Remove the definition of a symbol from the symbol table. */
+static int
+do_undef (pfile)
+ cpp_reader *pfile;
+{
+ cpp_hashnode *node = get_define_node (pfile);
- _cpp_scan_until (pfile, list, CPP_VSPACE);
+ if (cpp_get_token (pfile)->type != CPP_EOF)
+ cpp_pedwarn (pfile, "junk on line after #undef");
- /* First token on the line must be a NAME. There may not be any
- tokens in the list (if we had #define all by itself on a line). */
- if (list->tokens_used == 0
- || TOK_TYPE (list, 0) != CPP_NAME)
+ /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier
+ is not currently defined as a macro name. */
+ if (node && node->type != T_VOID)
{
- cpp_error_with_line (pfile, list->line, TOK_COL (list, 0),
- "#define must be followed by an identifier");
- goto out;
- }
+ /* If we are generating additional info for debugging (with -g) we
+ need to pass through all effective #undef commands. */
+ if (CPP_OPTION (pfile, debug_output)
+ || CPP_OPTION (pfile, dump_macros) == dump_definitions
+ || CPP_OPTION (pfile, dump_macros) == dump_names)
+ pass_thru_directive (pfile);
- sym = TOK_NAME (list, 0);
- len = TOK_LEN (list, 0);
+ if (node->type != T_MACRO)
+ cpp_warning (pfile, "undefining \"%s\"", node->name);
- /* That NAME is not allowed to be "defined". (Not clear if the
- standard requires this.) */
- if (len == 7 && !ustrncmp (sym, U"defined", 7))
- {
- cpp_error_with_line (pfile, list->line, TOK_COL (list, 0),
- "\"defined\" is not a legal macro name");
- goto out;
+ _cpp_free_definition (node);
+ node->type = T_VOID;
}
- node = cpp_lookup (pfile, sym, len);
- /* Check for poisoned identifiers now. All other checks
- are done in cpphash.c. */
- if (node->type == T_POISON)
- {
- cpp_error (pfile, "redefining poisoned `%.*s'", len, sym);
- goto out;
- }
-
- if (_cpp_create_definition (pfile, list, node) == 0)
- goto out;
-
- if (CPP_OPTION (pfile, debug_output)
- || CPP_OPTION (pfile, dump_macros) == dump_definitions)
- _cpp_dump_definition (pfile, node);
- else if (CPP_OPTION (pfile, dump_macros) == dump_names)
- pass_thru_directive (sym, len, pfile, T_DEFINE);
-
- out:
- pfile->no_macro_expand--;
- CPP_OPTION (pfile, discard_comments)--;
return 0;
}
+
/* Handle #include and #import. */
-static unsigned int
-parse_include (pfile, name, trail)
+static int
+parse_include (pfile, dir, trail, strp, lenp, abp)
cpp_reader *pfile;
- const U_CHAR *name;
+ const U_CHAR *dir;
int trail;
+ const U_CHAR **strp;
+ unsigned int *lenp;
+ int *abp;
{
- long old_written = CPP_WRITTEN (pfile);
- enum cpp_ttype token;
- int len;
-
- pfile->parsing_include_directive++;
- token = _cpp_get_directive_token (pfile);
- pfile->parsing_include_directive--;
+ const cpp_token *name = cpp_get_token (pfile);
- len = CPP_WRITTEN (pfile) - old_written;
-
- if (token != CPP_STRING)
+ if (name->type != CPP_STRING && name->type != CPP_HEADER_NAME)
{
- cpp_error (pfile, "#%s expects \"FILENAME\" or <FILENAME>", name);
- CPP_SET_WRITTEN (pfile, old_written);
- _cpp_skip_rest_of_line (pfile);
- return 0;
+ if (name->type == CPP_LESS)
+ name = _cpp_glue_header_name (pfile);
+ else
+ {
+ cpp_error (pfile, "#%s expects \"FILENAME\" or <FILENAME>", dir);
+ return 1;
+ }
}
-
- if (!trail && _cpp_get_directive_token (pfile) != CPP_VSPACE)
+ if (name->val.name.len == 0)
{
- cpp_error (pfile, "junk at end of #%s", name);
- _cpp_skip_rest_of_line (pfile);
+ cpp_error (pfile, "empty file name in #%s", dir);
+ return 1;
}
- CPP_SET_WRITTEN (pfile, old_written);
-
- if (len == 0)
- cpp_error (pfile, "empty file name in #%s", name);
+ if (!trail && cpp_get_token (pfile)->type != CPP_EOF)
+ cpp_error (pfile, "junk at end of #%s", dir);
- return len;
+ *lenp = name->val.name.len;
+ *strp = name->val.name.text;
+ *abp = (name->type == CPP_HEADER_NAME);
+ return 0;
}
static int
@@ -440,19 +372,15 @@ do_include (pfile)
cpp_reader *pfile;
{
unsigned int len;
- U_CHAR *token;
+ const U_CHAR *str;
+ int ab;
- len = parse_include (pfile, dtable[T_INCLUDE].name, 0);
- if (len == 0)
+ if (parse_include (pfile, dtable[T_INCLUDE].name, 0, &str, &len, &ab))
return 0;
- token = (U_CHAR *) alloca (len + 1);
- memcpy (token, CPP_PWRITTEN (pfile), len);
- token[len] = '\0';
-
- if (CPP_OPTION (pfile, dump_includes))
- pass_thru_directive (token, len, pfile, T_INCLUDE);
- _cpp_execute_include (pfile, token, len, 0, 0);
+ _cpp_execute_include (pfile, str, len, 0, 0, ab);
+ if (CPP_OPTION (pfile, dump_includes))
+ pass_thru_directive (pfile);
return 0;
}
@@ -461,7 +389,8 @@ do_import (pfile)
cpp_reader *pfile;
{
unsigned int len;
- U_CHAR *token;
+ const U_CHAR *str;
+ int ab;
if (CPP_OPTION (pfile, warn_import)
&& !CPP_IN_SYSTEM_HEADER (pfile) && !pfile->import_warning)
@@ -471,17 +400,12 @@ do_import (pfile)
"#import is obsolete, use an #ifndef wrapper in the header file");
}
- len = parse_include (pfile, dtable[T_IMPORT].name, 0);
- if (len == 0)
+ if (parse_include (pfile, dtable[T_IMPORT].name, 0, &str, &len, &ab))
return 0;
- token = (U_CHAR *) alloca (len + 1);
- memcpy (token, CPP_PWRITTEN (pfile), len);
- token[len] = '\0';
-
- if (CPP_OPTION (pfile, dump_includes))
- pass_thru_directive (token, len, pfile, T_IMPORT);
- _cpp_execute_include (pfile, token, len, 1, 0);
+ _cpp_execute_include (pfile, str, len, 1, 0, ab);
+ if (CPP_OPTION (pfile, dump_includes))
+ pass_thru_directive (pfile);
return 0;
}
@@ -490,32 +414,35 @@ do_include_next (pfile)
cpp_reader *pfile;
{
unsigned int len;
- U_CHAR *token;
+ const U_CHAR *str;
struct file_name_list *search_start = 0;
+ int ab;
- len = parse_include (pfile, dtable[T_INCLUDE_NEXT].name, 0);
- if (len == 0)
+ if (parse_include (pfile, dtable[T_INCLUDE_NEXT].name, 0, &str, &len, &ab))
return 0;
- token = (U_CHAR *) alloca (len + 1);
- memcpy (token, CPP_PWRITTEN (pfile), len);
- token[len] = '\0';
-
- if (CPP_OPTION (pfile, dump_includes))
- pass_thru_directive (token, len, pfile, T_INCLUDE_NEXT);
- /* For #include_next, skip in the search path past the dir in which the
- containing file was found. Treat files specified using an absolute path
- as if there are no more directories to search. Treat the primary source
- file like any other included source, but generate a warning. */
+ /* For #include_next, skip in the search path past the dir in which
+ the current file was found. If this is the last directory in the
+ search path, don't include anything. If the current file was
+ specified with an absolute path, use the normal search logic. If
+ this is the primary source file, use the normal search logic and
+ generate a warning. */
if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)))
{
if (CPP_BUFFER (pfile)->inc->foundhere)
- search_start = CPP_BUFFER (pfile)->inc->foundhere->next;
+ {
+ search_start = CPP_BUFFER (pfile)->inc->foundhere->next;
+ if (!search_start)
+ return 0;
+ }
}
else
cpp_warning (pfile, "#include_next in primary source file");
- _cpp_execute_include (pfile, token, len, 0, search_start);
+ _cpp_execute_include (pfile, str, len, 0, search_start, ab);
+ if (CPP_OPTION (pfile, dump_includes))
+ pass_thru_directive (pfile);
+
return 0;
}
@@ -529,27 +456,47 @@ read_line_number (pfile, num)
cpp_reader *pfile;
int *num;
{
- long save_written = CPP_WRITTEN (pfile);
- U_CHAR *p;
- enum cpp_ttype token = _cpp_get_directive_token (pfile);
- p = pfile->token_buffer + save_written;
+ const cpp_token *tok = cpp_get_token (pfile);
+ enum cpp_ttype type = tok->type;
+ const U_CHAR *p = tok->val.name.text;
+ unsigned int len = tok->val.name.len;
- if (token == CPP_NUMBER && p + 1 == CPP_PWRITTEN (pfile)
- && p[0] >= '1' && p[0] <= '4')
+ if (type == CPP_NUMBER && len == 1 && p[0] >= '1' && p[0] <= '4')
{
*num = p[0] - '0';
- CPP_SET_WRITTEN (pfile, save_written);
return 1;
}
else
{
- if (token != CPP_VSPACE && token != CPP_EOF)
+ if (type != CPP_VSPACE && type != CPP_EOF)
cpp_error (pfile, "invalid format #line");
- CPP_SET_WRITTEN (pfile, save_written);
return 0;
}
}
+/* Another subroutine of do_line. Convert a number in STR, of length
+ LEN, to binary; store it in NUMP, and return 0 if the number was
+ legal, 1 if not. Temporary, hopefully. */
+static int
+strtoul_for_line (str, len, nump)
+ const U_CHAR *str;
+ unsigned int len;
+ unsigned long *nump;
+{
+ unsigned long reg = 0;
+ U_CHAR c;
+ while (len--)
+ {
+ c = *str++;
+ if (!ISDIGIT (c))
+ return 1;
+ reg *= 10;
+ reg += c - '0';
+ }
+ *nump = reg;
+ return 0;
+}
+
/* Interpret #line command.
Note that the filename string (if any) is treated as if it were an
include filename. That means no escape handling. */
@@ -559,156 +506,92 @@ do_line (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
- unsigned int new_lineno;
- long old_written = CPP_WRITTEN (pfile);
- enum cpp_ttype token;
- char *x;
-
- token = _cpp_get_directive_token (pfile);
+ unsigned long new_lineno, old_lineno;
+ /* C99 raised the minimum limit on #line numbers. */
+ unsigned int cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767;
+ int action_number = 0;
+ enum cpp_ttype type;
+ const U_CHAR *str;
+ char *fname;
+ unsigned int len;
+ const cpp_token *tok;
- if (token != CPP_NUMBER)
- {
- cpp_error (pfile, "token after #line is not an integer");
- goto bad_line_directive;
- }
+ tok = cpp_get_token (pfile);
+ type = tok->type;
+ str = tok->val.name.text;
+ len = tok->val.name.len;
- CPP_PUTC (pfile, '\0'); /* not terminated for us */
- new_lineno = strtoul ((const char *) (pfile->token_buffer + old_written),
- &x, 10);
- if (x[0] != '\0')
+ if (type != CPP_NUMBER || strtoul_for_line (str, len, &new_lineno))
{
- cpp_error (pfile, "token after #line is not an integer");
- goto bad_line_directive;
+ cpp_error (pfile, "token after #line is not a positive integer");
+ goto done;
}
- CPP_SET_WRITTEN (pfile, old_written);
-
- if (CPP_PEDANTIC (pfile) && (new_lineno <= 0 || new_lineno > 32767))
- cpp_pedwarn (pfile, "line number out of range in #line");
- token = _cpp_get_directive_token (pfile);
+ if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap))
+ cpp_pedwarn (pfile, "line number out of range");
- if (token == CPP_STRING)
- {
- U_CHAR *fname = pfile->token_buffer + old_written + 1;
- U_CHAR *end_name = CPP_PWRITTEN (pfile) - 1;
- int action_number = 0;
-
- if (read_line_number (pfile, &action_number))
- {
- if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "garbage at end of #line");
+ old_lineno = ip->lineno;
+ ip->lineno = new_lineno;
+ tok = cpp_get_token (pfile);
+ type = tok->type;
+ str = tok->val.name.text;
+ len = tok->val.name.len;
- /* This is somewhat questionable: change the buffer stack
- depth so that output_line_command thinks we've stacked
- another buffer. */
- if (action_number == 1)
- {
- pfile->buffer_stack_depth++;
- cpp_make_system_header (pfile, ip, 0);
- read_line_number (pfile, &action_number);
- }
- else if (action_number == 2)
- {
- pfile->buffer_stack_depth--;
- cpp_make_system_header (pfile, ip, 0);
- read_line_number (pfile, &action_number);
- }
- if (action_number == 3)
- {
- cpp_make_system_header (pfile, ip, 1);
- read_line_number (pfile, &action_number);
- }
- if (action_number == 4)
- {
- cpp_make_system_header (pfile, ip, 2);
- read_line_number (pfile, &action_number);
- }
- }
-
- *end_name = '\0';
-
- if (strcmp ((const char *)fname, ip->nominal_fname))
- {
- if (!strcmp ((const char *)fname, ip->inc->name))
- ip->nominal_fname = ip->inc->name;
- else
- ip->nominal_fname = _cpp_fake_include (pfile, (const char *)fname);
- }
- }
- else if (token != CPP_VSPACE && token != CPP_EOF)
+ if (type == CPP_VSPACE || type == CPP_EOF)
+ goto done;
+ else if (type != CPP_STRING)
{
cpp_error (pfile, "second token after #line is not a string");
- goto bad_line_directive;
+ ip->lineno = old_lineno; /* malformed #line should have no effect */
+ goto done;
}
- /* The Newline at the end of this line remains to be processed.
- To put the next line at the specified line number,
- we must store a line number now that is one less. */
- ip->lineno = new_lineno - 1;
- CPP_SET_WRITTEN (pfile, old_written);
- return 0;
-
- bad_line_directive:
- _cpp_skip_rest_of_line (pfile);
- CPP_SET_WRITTEN (pfile, old_written);
- return 0;
-}
+ fname = alloca (len + 1);
+ memcpy (fname, str, len);
+ fname[len] = '\0';
+
+ if (strcmp (fname, ip->nominal_fname))
+ {
+ if (!strcmp (fname, ip->inc->name))
+ ip->nominal_fname = ip->inc->name;
+ else
+ ip->nominal_fname = _cpp_fake_include (pfile, fname);
+ }
-/* Remove the definition of a symbol from the symbol table.
- According to the C standard, it is not an error to undef
- something that has no definitions. */
-static int
-do_undef (pfile)
- cpp_reader *pfile;
-{
- int len;
- cpp_hashnode *hp;
- U_CHAR *name;
- long here = CPP_WRITTEN (pfile);
- enum cpp_ttype token;
+ if (read_line_number (pfile, &action_number) == 0)
+ return 0;
- pfile->no_macro_expand++;
- token = _cpp_get_directive_token (pfile);
- pfile->no_macro_expand--;
+ if (CPP_PEDANTIC (pfile))
+ cpp_pedwarn (pfile, "garbage at end of #line");
- if (token != CPP_NAME)
+ /* This is somewhat questionable: change the buffer stack
+ depth so that output_line_command thinks we've stacked
+ another buffer. */
+ if (action_number == 1)
{
- cpp_error (pfile, "token after #undef is not an identifier");
- _cpp_skip_rest_of_line (pfile);
- return 0;
+ pfile->buffer_stack_depth++;
+ cpp_make_system_header (pfile, ip, 0);
+ read_line_number (pfile, &action_number);
}
- len = CPP_WRITTEN (pfile) - here;
-
- token = _cpp_get_directive_token (pfile);
- if (token != CPP_VSPACE)
- {
- cpp_pedwarn (pfile, "junk on line after #undef");
- _cpp_skip_rest_of_line (pfile);
- }
-
- name = pfile->token_buffer + here;
- CPP_SET_WRITTEN (pfile, here);
-
- hp = cpp_lookup (pfile, name, len);
- if (hp->type == T_VOID)
- ; /* Not defined in the first place - do nothing. */
- else if (hp->type == T_POISON)
- cpp_error (pfile, "cannot undefine poisoned \"%s\"", hp->name);
- else
+ else if (action_number == 2)
{
- /* If we are generating additional info for debugging (with -g) we
- need to pass through all effective #undef commands. */
- if (CPP_OPTION (pfile, debug_output))
- pass_thru_directive (hp->name, len, pfile, T_UNDEF);
-
- if (hp->type != T_MACRO && hp->type != T_FMACRO
- && hp->type != T_EMPTY && hp->type != T_IDENTITY)
- cpp_warning (pfile, "undefining `%s'", hp->name);
-
- _cpp_free_definition (hp);
- hp->type = T_VOID;
+ pfile->buffer_stack_depth--;
+ cpp_make_system_header (pfile, ip, 0);
+ read_line_number (pfile, &action_number);
}
+ if (action_number == 3)
+ {
+ cpp_make_system_header (pfile, ip, 1);
+ read_line_number (pfile, &action_number);
+ }
+ if (action_number == 4)
+ {
+ cpp_make_system_header (pfile, ip, 2);
+ read_line_number (pfile, &action_number);
+ }
+ return 0;
+ done:
return 0;
}
@@ -722,14 +605,14 @@ static int
do_error (pfile)
cpp_reader *pfile;
{
- const U_CHAR *text, *limit;
+ U_CHAR *text, *limit;
- _cpp_skip_hspace (pfile);
- text = CPP_BUFFER (pfile)->cur;
- _cpp_skip_rest_of_line (pfile);
- limit = CPP_BUFFER (pfile)->cur;
+ text = pfile->limit;
+ _cpp_dump_list (pfile, &pfile->token_list, pfile->first_directive_token, 0);
+ limit = pfile->limit;
+ pfile->limit = text;
+ cpp_error (pfile, "%.*s", (int)(limit - text), text);
- cpp_error (pfile, "#error %.*s", (int)(limit - text), text);
return 0;
}
@@ -742,14 +625,13 @@ static int
do_warning (pfile)
cpp_reader *pfile;
{
- const U_CHAR *text, *limit;
+ U_CHAR *text, *limit;
- _cpp_skip_hspace (pfile);
- text = CPP_BUFFER (pfile)->cur;
- _cpp_skip_rest_of_line (pfile);
- limit = CPP_BUFFER (pfile)->cur;
-
- cpp_warning (pfile, "#warning %.*s", (int)(limit - text), text);
+ text = pfile->limit;
+ _cpp_dump_list (pfile, &pfile->token_list, pfile->first_directive_token, 0);
+ limit = pfile->limit;
+ pfile->limit = text;
+ cpp_warning (pfile, "%.*s", (int)(limit - text), text);
return 0;
}
@@ -759,21 +641,17 @@ static int
do_ident (pfile)
cpp_reader *pfile;
{
- long old_written = CPP_WRITTEN (pfile);
-
- CPP_PUTS (pfile, "#ident ", 7);
-
/* Next token should be a string constant. */
- if (_cpp_get_directive_token (pfile) == CPP_STRING)
+ if (cpp_get_token (pfile)->type == CPP_STRING)
/* And then a newline. */
- if (_cpp_get_directive_token (pfile) == CPP_VSPACE)
- /* Good - ship it. */
- return 0;
+ if (cpp_get_token (pfile)->type == CPP_VSPACE)
+ {
+ /* Good - ship it. */
+ pass_thru_directive (pfile);
+ return 0;
+ }
cpp_error (pfile, "invalid #ident");
- _cpp_skip_rest_of_line (pfile);
- CPP_SET_WRITTEN (pfile, old_written); /* discard directive */
-
return 0;
}
@@ -792,17 +670,17 @@ do_ident (pfile)
They return 1 if the token buffer is to be popped, 0 if not. */
struct pragma_entry
{
- char const *name;
+ const char *name;
int (*handler) PARAMS ((cpp_reader *));
};
static int pragma_dispatch
- PARAMS ((cpp_reader *, const struct pragma_entry *, U_CHAR *, size_t));
+ PARAMS ((cpp_reader *, const struct pragma_entry *,
+ const U_CHAR *, size_t));
static int do_pragma_once PARAMS ((cpp_reader *));
static int do_pragma_implementation PARAMS ((cpp_reader *));
static int do_pragma_poison PARAMS ((cpp_reader *));
static int do_pragma_system_header PARAMS ((cpp_reader *));
-static int do_pragma_default PARAMS ((cpp_reader *));
static int do_pragma_gcc PARAMS ((cpp_reader *));
static int do_pragma_dependency PARAMS ((cpp_reader *));
@@ -811,9 +689,8 @@ static const struct pragma_entry top_pragmas[] =
{"once", do_pragma_once},
{"implementation", do_pragma_implementation},
{"poison", do_pragma_poison},
- {"system_header", do_pragma_system_header},
{"GCC", do_pragma_gcc},
- {NULL, do_pragma_default}
+ {NULL, NULL}
};
static const struct pragma_entry gcc_pragmas[] =
@@ -822,74 +699,41 @@ static const struct pragma_entry gcc_pragmas[] =
{"poison", do_pragma_poison},
{"system_header", do_pragma_system_header},
{"dependency", do_pragma_dependency},
- {NULL, do_pragma_default}
+ {NULL, NULL}
};
static int pragma_dispatch (pfile, table, p, len)
cpp_reader *pfile;
const struct pragma_entry *table;
- U_CHAR *p;
+ const U_CHAR *p;
size_t len;
{
for (; table->name; table++)
if (strlen (table->name) == len && !memcmp (p, table->name, len))
return (*table->handler) (pfile);
- return (*table->handler) (pfile);
+ return 0;
}
static int
do_pragma (pfile)
cpp_reader *pfile;
{
- long here, key;
- U_CHAR *buf;
+ const cpp_token *tok;
int pop;
- enum cpp_ttype token;
- size_t len;
-
- here = CPP_WRITTEN (pfile);
- CPP_PUTS (pfile, "#pragma ", 8);
- key = CPP_WRITTEN (pfile);
- pfile->no_macro_expand++;
- token = _cpp_get_directive_token (pfile);
- if (token != CPP_NAME)
+ tok = cpp_get_token (pfile);
+ if (tok->type == CPP_EOF)
+ return 0;
+ else if (tok->type != CPP_NAME)
{
- if (token == CPP_VSPACE)
- goto empty;
- else
- goto skip;
+ cpp_error (pfile, "malformed #pragma directive");
+ return 0;
}
- buf = pfile->token_buffer + key;
- len = CPP_WRITTEN (pfile) - key;
- CPP_PUTC (pfile, ' ');
-
- pop = pragma_dispatch (pfile, top_pragmas, buf, len);
-
- if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
- goto skip;
-
- if (pop)
- CPP_SET_WRITTEN (pfile, here);
- pfile->no_macro_expand--;
- return 0;
-
- skip:
- cpp_error (pfile, "malformed #pragma directive");
- _cpp_skip_rest_of_line (pfile);
- empty:
- CPP_SET_WRITTEN (pfile, here);
- pfile->no_macro_expand--;
- return 0;
-}
-
-static int
-do_pragma_default (pfile)
- cpp_reader *pfile;
-{
- while (_cpp_get_directive_token (pfile) != CPP_VSPACE)
- CPP_PUTC (pfile, ' ');
+ pop = pragma_dispatch (pfile, top_pragmas,
+ tok->val.name.text, tok->val.name.len);
+ if (!pop)
+ pass_thru_directive (pfile);
return 0;
}
@@ -897,21 +741,16 @@ static int
do_pragma_gcc (pfile)
cpp_reader *pfile;
{
- long key;
- enum cpp_ttype token;
- U_CHAR *buf;
- size_t len;
-
- key = CPP_WRITTEN (pfile);
- token = _cpp_get_directive_token (pfile);
- if (token != CPP_NAME)
- return token == CPP_VSPACE;
-
- buf = pfile->token_buffer + key;
- len = CPP_WRITTEN (pfile) - key;
- CPP_PUTC (pfile, ' ');
+ const cpp_token *tok;
+
+ tok = cpp_get_token (pfile);
+ if (tok->type == CPP_EOF)
+ return 1;
+ else if (tok->type != CPP_NAME)
+ return 0;
- return pragma_dispatch (pfile, gcc_pragmas, buf, len);
+ return pragma_dispatch (pfile, gcc_pragmas,
+ tok->val.name.text, tok->val.name.len);
}
static int
@@ -939,27 +778,22 @@ do_pragma_implementation (pfile)
{
/* Be quiet about `#pragma implementation' for a file only if it hasn't
been included yet. */
- enum cpp_ttype token;
- long written = CPP_WRITTEN (pfile);
- U_CHAR *name;
+ const cpp_token *tok = cpp_get_token (pfile);
char *copy;
- size_t len;
- token = _cpp_get_directive_token (pfile);
- if (token == CPP_VSPACE)
+ if (tok->type == CPP_EOF)
return 0;
- else if (token != CPP_STRING)
+ else if (tok->type != CPP_STRING
+ || cpp_get_token (pfile)->type != CPP_EOF)
{
cpp_error (pfile, "malformed #pragma implementation");
return 1;
}
- /* Trim the leading and trailing quote marks from the string. */
- name = pfile->token_buffer + written + 1;
- len = CPP_PWRITTEN (pfile) - name;
- copy = alloca (len);
- memcpy (copy, name, len - 1);
- copy[len - 1] = '\0';
+ /* Make a NUL-terminated copy of the string. */
+ copy = alloca (tok->val.name.len + 1);
+ memcpy (copy, tok->val.name.text, tok->val.name.len);
+ copy[tok->val.name.len] = '\0';
if (cpp_included (pfile, copy))
cpp_warning (pfile,
@@ -974,11 +808,8 @@ do_pragma_poison (pfile)
{
/* Poison these symbols so that all subsequent usage produces an
error message. */
- U_CHAR *p;
+ const cpp_token *tok;
cpp_hashnode *hp;
- long written;
- size_t len;
- enum cpp_ttype token;
int writeit;
/* As a rule, don't include #pragma poison commands in output,
@@ -989,31 +820,25 @@ do_pragma_poison (pfile)
for (;;)
{
- written = CPP_WRITTEN (pfile);
- token = _cpp_get_directive_token (pfile);
- if (token == CPP_VSPACE)
+ tok = cpp_get_token (pfile);
+ if (tok->type == CPP_EOF)
break;
- if (token != CPP_NAME)
+ if (tok->type != CPP_NAME)
{
cpp_error (pfile, "invalid #pragma poison directive");
- _cpp_skip_rest_of_line (pfile);
return 1;
}
- p = pfile->token_buffer + written;
- len = CPP_PWRITTEN (pfile) - p;
- hp = cpp_lookup (pfile, p, len);
+ hp = cpp_lookup (pfile, tok->val.name.text, tok->val.name.len);
if (hp->type == T_POISON)
; /* It is allowed to poison the same identifier twice. */
else
{
if (hp->type != T_VOID)
- cpp_warning (pfile, "poisoning existing macro `%s'", hp->name);
+ cpp_warning (pfile, "poisoning existing macro \"%s\"", hp->name);
_cpp_free_definition (hp);
hp->type = T_POISON;
}
- if (writeit)
- CPP_PUTC (pfile, ' ');
}
return !writeit;
}
@@ -1028,7 +853,7 @@ static int
do_pragma_system_header (pfile)
cpp_reader *pfile;
{
- cpp_buffer *ip = cpp_file_buffer (pfile);
+ cpp_buffer *ip = CPP_BUFFER (pfile);
if (CPP_PREV_BUFFER (ip) == NULL)
cpp_warning (pfile, "#pragma system_header outside include file");
else
@@ -1044,33 +869,37 @@ static int
do_pragma_dependency (pfile)
cpp_reader *pfile;
{
- U_CHAR *original_name, *name;
- unsigned len;
- int ordering;
-
- len = parse_include (pfile, (const U_CHAR *)"pragma dependency", 1);
- original_name = (U_CHAR *) alloca (len + 1);
- name = (U_CHAR *) alloca (len + 1);
- memcpy (original_name, CPP_PWRITTEN (pfile), len);
- memcpy (name, CPP_PWRITTEN (pfile), len);
- original_name[len] = name[len] = 0;
-
- ordering = _cpp_compare_file_date (pfile, name, len, 0);
+ const U_CHAR *name;
+ unsigned int len;
+ int ordering, ab;
+ char left, right;
+
+ if (parse_include (pfile, U"pragma dependency", 1, &name, &len, &ab))
+ return 1;
+
+ left = ab ? '<' : '"';
+ right = ab ? '>' : '"';
+
+ ordering = _cpp_compare_file_date (pfile, name, len, ab);
if (ordering < 0)
- cpp_warning (pfile, "cannot find source %s", original_name);
+ cpp_warning (pfile, "cannot find source %c%s%c", left, name, right);
else if (ordering > 0)
{
- const U_CHAR *text, *limit;
- _cpp_skip_hspace (pfile);
- text = CPP_BUFFER (pfile)->cur;
- _cpp_skip_rest_of_line (pfile);
- limit = CPP_BUFFER (pfile)->cur;
+ const cpp_token *msg = cpp_get_token (pfile);
- cpp_warning (pfile, "current file is older than %s", original_name);
- if (limit != text)
- cpp_warning (pfile, "%.*s", (int)(limit - text), text);
+ cpp_warning (pfile, "current file is older than %c%s%c",
+ left, name, right);
+ if (msg->type != CPP_EOF)
+ {
+ U_CHAR *text, *limit;
+
+ text = pfile->limit;
+ _cpp_dump_list (pfile, &pfile->token_list, msg, 0);
+ limit = pfile->limit;
+ pfile->limit = text;
+ cpp_warning (pfile, "%.*s", (int)(limit - text), text);
+ }
}
- _cpp_skip_rest_of_line (pfile);
return 1;
}
@@ -1078,9 +907,8 @@ do_pragma_dependency (pfile)
#ifdef SCCS_DIRECTIVE
static int
do_sccs (pfile)
- cpp_reader *pfile;
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
{
- _cpp_skip_rest_of_line (pfile);
return 0;
}
#endif
@@ -1096,117 +924,76 @@ static const cpp_hashnode *
detect_if_not_defined (pfile)
cpp_reader *pfile;
{
- const cpp_hashnode *cmacro = 0;
- enum cpp_ttype token;
- unsigned int base_offset;
- unsigned int token_offset;
- unsigned int need_rparen = 0;
- unsigned int token_len;
-
- if (pfile->skipping || pfile->only_seen_white != 2)
- return NULL;
-
- /* Save state required for restore. */
- pfile->no_macro_expand++;
- CPP_SET_MARK (pfile);
- base_offset = CPP_WRITTEN (pfile);
-
- /* Look for `!', */
- if (_cpp_get_directive_token (pfile) != CPP_OTHER
- || CPP_WRITTEN (pfile) != (size_t) base_offset + 1
- || CPP_PWRITTEN (pfile)[-1] != '!')
- goto restore;
-
- /* ...then `defined', */
- token_offset = CPP_WRITTEN (pfile);
- token = _cpp_get_directive_token (pfile);
- if (token != CPP_NAME)
- goto restore;
- if (ustrncmp (pfile->token_buffer + token_offset, U"defined", 7))
- goto restore;
-
- /* ...then an optional '(' and the name, */
- token_offset = CPP_WRITTEN (pfile);
- token = _cpp_get_directive_token (pfile);
- if (token == CPP_OPEN_PAREN)
- {
- token_offset = CPP_WRITTEN (pfile);
- need_rparen = 1;
- token = _cpp_get_directive_token (pfile);
- }
- if (token != CPP_NAME)
- goto restore;
+ const cpp_token *token;
+ cpp_hashnode *cmacro = 0;
+
+ /* We are guaranteed that tokens are consecutive and end in CPP_EOF. */
+ token = pfile->first_directive_token + 2;
+
+ if (token->type != CPP_NOT)
+ return 0;
- token_len = CPP_WRITTEN (pfile) - token_offset;
+ token++;
+ if (token->type != CPP_NAME
+ || !str_match (token->val.name.text, token->val.name.len, "defined"))
+ return 0;
+
+ token++;
+ if (token->type == CPP_OPEN_PAREN)
+ token++;
- /* ...then the ')', if necessary, */
- if (need_rparen && _cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
- goto restore;
+ if (token->type != CPP_NAME)
+ return 0;
- /* ...and make sure there's nothing else on the line. */
- if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
- goto restore;
+ cmacro = cpp_lookup (pfile, token->val.name.text, token->val.name.len);
- /* We have a legitimate controlling macro for this header. */
- cmacro = cpp_lookup (pfile, pfile->token_buffer + token_offset, token_len);
+ if (token[-1].type == CPP_OPEN_PAREN)
+ {
+ token++;
+ if (token->type != CPP_CLOSE_PAREN)
+ return 0;
+ }
- restore:
- CPP_SET_WRITTEN (pfile, base_offset);
- pfile->no_macro_expand--;
- CPP_GOTO_MARK (pfile);
+ token++;
+ if (token->type != CPP_EOF)
+ return 0;
return cmacro;
}
-/* Parse an #ifdef or #ifndef directive. Returns 1 for defined, 0 for
- not defined; the macro tested is left in the token buffer (but
- popped). */
+/* Parse an #ifdef or #ifndef directive. Returns the hash node of the
+ macro being tested, and issues various error messages. */
static const cpp_hashnode *
parse_ifdef (pfile, name)
cpp_reader *pfile;
const U_CHAR *name;
{
- U_CHAR *ident;
+ const U_CHAR *ident;
unsigned int len;
- enum cpp_ttype token;
- long old_written = CPP_WRITTEN (pfile);
+ enum cpp_ttype type;
const cpp_hashnode *node = 0;
- pfile->no_macro_expand++;
- token = _cpp_get_directive_token (pfile);
- pfile->no_macro_expand--;
-
- ident = pfile->token_buffer + old_written;
- len = CPP_WRITTEN (pfile) - old_written;
+ const cpp_token *token = cpp_get_token (pfile);
+ type = token->type;
+ ident = token->val.name.text;
+ len = token->val.name.len;
- if (token == CPP_VSPACE)
+ if (!CPP_TRADITIONAL (pfile))
{
- if (! CPP_TRADITIONAL (pfile))
+ if (type == CPP_EOF)
cpp_pedwarn (pfile, "#%s with no argument", name);
- goto done;
- }
- else if (token == CPP_NAME)
- {
- node = cpp_lookup (pfile, ident, len);
- }
- else
- {
- if (! CPP_TRADITIONAL (pfile))
- cpp_error (pfile, "#%s with invalid argument", name);
+ else if (type != CPP_NAME)
+ cpp_pedwarn (pfile, "#%s with invalid argument", name);
+ else if (cpp_get_token (pfile)->type != CPP_EOF)
+ cpp_pedwarn (pfile, "garbage at end of #%s", name);
}
- if (!CPP_TRADITIONAL (pfile))
- {
- if (_cpp_get_directive_token (pfile) == CPP_VSPACE)
- goto done;
-
- cpp_pedwarn (pfile, "garbage at end of #%s", name);
- }
- _cpp_skip_rest_of_line (pfile);
-
- done:
- CPP_SET_WRITTEN (pfile, old_written); /* Pop */
+ if (type == CPP_NAME)
+ node = cpp_lookup (pfile, ident, len);
+ if (node && node->type == T_POISON)
+ cpp_error (pfile, "attempt to use poisoned identifier \"%s\"", node->name);
+
return node;
}
@@ -1217,14 +1004,15 @@ do_ifdef (pfile)
cpp_reader *pfile;
{
int def = 0;
- const cpp_hashnode *node = parse_ifdef (pfile, dtable[T_IFDEF].name);
- if (node)
+ const cpp_hashnode *node = 0;
+
+ if (! pfile->skipping)
{
- if (node->type == T_POISON)
- cpp_error (pfile, "attempt to use poisoned `%s'", node->name);
- else
- def = (node->type != T_VOID);
+ node = parse_ifdef (pfile, dtable[T_IFDEF].name);
+ if (node)
+ def = (node->type != T_VOID && node->type != T_POISON);
}
+
push_conditional (pfile, !def, T_IFDEF, 0);
return 0;
}
@@ -1236,21 +1024,19 @@ static int
do_ifndef (pfile)
cpp_reader *pfile;
{
- int start_of_file;
+ int start_of_file = 0;
int def = 0;
- const cpp_hashnode *cmacro;
+ const cpp_hashnode *cmacro = 0;
- start_of_file = pfile->only_seen_white == 2;
- cmacro = parse_ifdef (pfile, dtable[T_IFNDEF].name);
- if (cmacro)
+ if (! pfile->skipping)
{
- if (cmacro->type == T_POISON)
- cpp_error (pfile, "attempt to use poisoned `%s'", cmacro->name);
- else
- def = (cmacro->type != T_VOID);
+ start_of_file = (pfile->token_list.flags & BEG_OF_FILE);
+ cmacro = parse_ifdef (pfile, dtable[T_IFNDEF].name);
+ if (cmacro)
+ def = cmacro->type != T_VOID;
}
- push_conditional (pfile, def, T_IFNDEF,
- start_of_file ? cmacro : 0);
+
+ push_conditional (pfile, def, T_IFNDEF, start_of_file ? cmacro : 0);
return 0;
}
@@ -1282,7 +1068,6 @@ do_else (pfile)
cpp_reader *pfile;
{
struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
-
validate_else (pfile, dtable[T_ELSE].name);
if (ifs == NULL)
@@ -1293,13 +1078,13 @@ do_else (pfile)
if (ifs->type == T_ELSE)
{
cpp_error (pfile, "#else after #else");
- cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
+ cpp_error_with_line (pfile, ifs->lineno, ifs->colno,
+ "the conditional began here");
}
/* #ifndef can't have its special treatment for containing the whole file
if it has a #else clause. */
ifs->cmacro = 0;
-
ifs->type = T_ELSE;
if (! ifs->was_skipping)
{
@@ -1330,24 +1115,24 @@ do_elif (pfile)
if (ifs->type == T_ELSE)
{
cpp_error (pfile, "#elif after #else");
- cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
+ cpp_error_with_line (pfile, ifs->lineno, ifs->colno,
+ "the conditional began here");
}
ifs->type = T_ELIF;
if (ifs->was_skipping)
- _cpp_skip_rest_of_line (pfile);
- else if (pfile->skipping != 1)
+ return 0; /* Don't evaluate a nested #if */
+
+ if (pfile->skipping != 1)
{
- _cpp_skip_rest_of_line (pfile);
pfile->skipping = 2; /* one block succeeded, so don't do any others */
+ return 0;
}
- else
- pfile->skipping = ! _cpp_parse_expr (pfile);
+ pfile->skipping = ! _cpp_parse_expr (pfile);
return 0;
}
-
/* #endif pops the if stack and resets pfile->skipping. */
static int
@@ -1370,6 +1155,7 @@ do_endif (pfile)
return 0;
}
+
/* Push an if_stack entry and set pfile->skipping accordingly.
If this is a #ifndef starting at the beginning of a file,
CMACRO is the macro name tested by the #ifndef. */
@@ -1384,7 +1170,7 @@ push_conditional (pfile, skip, type, cmacro)
struct if_stack *ifs;
ifs = (struct if_stack *) xmalloc (sizeof (struct if_stack));
- ifs->lineno = CPP_BUFFER (pfile)->lineno;
+ ifs->lineno = _cpp_get_line (pfile, &ifs->colno);
ifs->next = CPP_BUFFER (pfile)->if_stack;
ifs->cmacro = cmacro;
ifs->was_skipping = pfile->skipping;
@@ -1404,19 +1190,11 @@ validate_else (pfile, directive)
cpp_reader *pfile;
const U_CHAR *directive;
{
- if (CPP_PEDANTIC (pfile))
- {
- long old_written = CPP_WRITTEN (pfile);
- pfile->no_macro_expand++;
- if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
- cpp_pedwarn (pfile, "ISO C forbids text after #%s", directive);
- CPP_SET_WRITTEN (pfile, old_written);
- pfile->no_macro_expand--;
- }
- _cpp_skip_rest_of_line (pfile);
+ if (CPP_PEDANTIC (pfile) && cpp_get_token (pfile)->type != CPP_EOF)
+ cpp_pedwarn (pfile, "ISO C forbids text after #%s", directive);
}
-/* Called when we reach the end of a macro buffer. Walk back up the
+/* Called when we reach the end of a file. Walk back up the
conditional stack till we reach its level at entry to this file,
issuing error messages. Then force skipping off. */
void
@@ -1428,7 +1206,7 @@ _cpp_unwind_if_stack (pfile, pbuf)
for (ifs = pbuf->if_stack; ifs; ifs = nifs)
{
- cpp_error_with_line (pfile, ifs->lineno, 1, "unterminated #%s",
+ cpp_error_with_line (pfile, ifs->lineno, ifs->colno, "unterminated #%s",
dtable[ifs->type].name);
nifs = ifs->next;
free (ifs);
@@ -1436,173 +1214,210 @@ _cpp_unwind_if_stack (pfile, pbuf)
pfile->skipping = 0;
}
-#define WARNING(msgid) do { cpp_warning(pfile, msgid); goto error; } while (0)
-#define ERROR(msgid) do { cpp_error(pfile, msgid); goto error; } while (0)
-#define ICE(msgid) do { cpp_ice(pfile, msgid); goto error; } while (0)
-static int
-do_assert (pfile)
+/* Parses an assertion, returning a pointer to the hash node of the
+ predicate, or 0 on error. If an answer was supplied, it is
+ allocated and placed in ANSWERP, otherwise it is set to 0. We use
+ _cpp_get_raw_token, since we cannot assume tokens are consecutive
+ in a #if statement (we may be in a macro), and we don't want to
+ macro expand. */
+cpp_hashnode *
+_cpp_parse_assertion (pfile, answerp)
cpp_reader *pfile;
+ struct answer **answerp;
{
- long old_written;
+ struct answer *answer = 0;
+ cpp_toklist *list;
U_CHAR *sym;
- size_t len;
- cpp_hashnode *hp;
- struct predicate *pred = 0;
- enum cpp_ttype type;
+ const cpp_token *token, *predicate;
+ const struct directive *d = pfile->token_list.directive;
+ unsigned int len = 0;
- old_written = CPP_WRITTEN (pfile);
- pfile->no_macro_expand++;
+ predicate = _cpp_get_raw_token (pfile);
+ if (predicate->type == CPP_EOF)
+ {
+ cpp_error (pfile, "assertion without predicate");
+ return 0;
+ }
+ else if (predicate->type != CPP_NAME)
+ {
+ cpp_error (pfile, "predicate must be an identifier");
+ return 0;
+ }
- CPP_PUTC (pfile, '#'); /* force token out of macro namespace */
- type = _cpp_get_directive_token (pfile);
- if (type == CPP_VSPACE)
- ERROR ("#assert without predicate");
- else if (type != CPP_NAME)
- ERROR ("assertion predicate is not an identifier");
+ token = _cpp_get_raw_token (pfile);
+ if (token->type != CPP_OPEN_PAREN)
+ {
+ /* #unassert and #if are OK without predicate. */
+ if (d == &dtable[T_UNASSERT])
+ {
+ if (token->type == CPP_EOF)
+ goto lookup_node;
+ }
+ else if (d != &dtable[T_ASSERT])
+ {
+ _cpp_push_token (pfile, token);
+ goto lookup_node;
+ }
+ cpp_error (pfile, "missing '(' after predicate");
+ return 0;
+ }
- sym = pfile->token_buffer + old_written;
- len = CPP_WRITTEN (pfile) - old_written;
- hp = cpp_lookup (pfile, sym, len);
+ /* Allocate a struct answer, and copy the answer to it. */
+ answer = (struct answer *) xmalloc (sizeof (struct answer));
+ list = &answer->list;
+ _cpp_init_toklist (list, NO_DUMMY_TOKEN);
- if (_cpp_get_directive_token (pfile) != CPP_OPEN_PAREN)
- ERROR ("missing token-sequence in #assert");
+ for (;;)
+ {
+ cpp_token *dest;
- pred = (struct predicate *) xmalloc (sizeof (struct predicate));
- _cpp_init_toklist (&pred->answer, NO_DUMMY_TOKEN);
+ token = _cpp_get_raw_token (pfile);
- if (_cpp_scan_until (pfile, &pred->answer, CPP_CLOSE_PAREN)
- != CPP_CLOSE_PAREN)
- ERROR ("missing close paren in #assert");
+ if (token->type == CPP_EOF)
+ {
+ cpp_error (pfile, "missing ')' to complete answer");
+ goto error;
+ }
+ if (token->type == CPP_CLOSE_PAREN)
+ break;
- if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
- ICE ("impossible token, expecting ) in do_assert");
+ /* Copy the token. */
+ _cpp_expand_token_space (list, 1);
+ dest = &list->tokens[list->tokens_used++];
+ *dest = *token;
- if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
- ERROR ("junk at end of #assert");
+ if (token_spellings[token->type].type > SPELL_NONE)
+ {
+ _cpp_expand_name_space (list, token->val.name.len);
+ dest->val.name.text = list->namebuf + list->name_used;
+ memcpy (list->namebuf + list->name_used,
+ token->val.name.text, token->val.name.len);
+ list->name_used += token->val.name.len;
+ }
+ }
- if (hp->type == T_ASSERTION)
+ if (list->tokens_used == 0)
{
- /* Check for reassertion. */
- const struct predicate *old;
-
- for (old = hp->value.pred; old; old = old->next)
- if (_cpp_equiv_toklists (&pred->answer, &old->answer))
- /* We used to warn about this, but SVR4 cc doesn't, so let's
- match that (also consistent with #define). goto error will
- clean up. */
- goto error;
- pred->next = hp->value.pred;
+ cpp_error (pfile, "predicate's answer is empty");
+ goto error;
}
- else
+
+ /* Drop whitespace at start. */
+ list->tokens[0].flags &= ~PREV_WHITE;
+
+ if ((d == &dtable[T_ASSERT] || d == &dtable[T_UNASSERT])
+ && token[1].type != CPP_EOF)
{
- hp->type = T_ASSERTION;
- pred->next = 0;
+ cpp_error (pfile, "junk at end of assertion");
+ goto error;
}
-
- _cpp_squeeze_toklist (&pred->answer);
- hp->value.pred = pred;
- pfile->no_macro_expand--;
- CPP_SET_WRITTEN (pfile, old_written);
- return 0;
+
+ lookup_node:
+ *answerp = answer;
+ len = predicate->val.name.len + 1;
+ sym = alloca (len);
+
+ /* Prefix '#' to get it out of macro namespace. */
+ sym[0] = '#';
+ memcpy (sym + 1, predicate->val.name.text, len);
+ return cpp_lookup (pfile, sym, len);
error:
- _cpp_skip_rest_of_line (pfile);
- pfile->no_macro_expand--;
- CPP_SET_WRITTEN (pfile, old_written);
- if (pred)
- {
- _cpp_free_toklist (&pred->answer);
- free (pred);
- }
+ FREE_ANSWER (answer);
return 0;
}
-static int
-do_unassert (pfile)
- cpp_reader *pfile;
+/* Returns a pointer to the pointer to the answer in the answer chain,
+ or a pointer to NULL if the answer is not in the chain. */
+struct answer **
+find_answer (node, candidate)
+ cpp_hashnode *node;
+ const cpp_toklist *candidate;
{
- long old_written;
- U_CHAR *sym;
- size_t len;
- cpp_hashnode *hp;
- cpp_toklist ans;
- enum cpp_ttype type;
- int specific = 0;
+ struct answer **result;
- old_written = CPP_WRITTEN (pfile);
- pfile->no_macro_expand++;
+ for (result = &node->value.answers; *result; result = &(*result)->next)
+ if (_cpp_equiv_toklists (&(*result)->list, candidate))
+ break;
- CPP_PUTC (pfile, '#'); /* force token out of macro namespace */
- if (_cpp_get_directive_token (pfile) != CPP_NAME)
- ERROR ("#unassert must be followed by an identifier");
-
- sym = pfile->token_buffer + old_written;
- len = CPP_WRITTEN (pfile) - old_written;
- hp = cpp_lookup (pfile, sym, len);
+ return result;
+}
- type = _cpp_get_directive_token (pfile);
- if (type == CPP_OPEN_PAREN)
+#define WARNING(msgid) do { cpp_warning(pfile, msgid); goto error; } while (0)
+#define ERROR(msgid) do { cpp_error(pfile, msgid); goto error; } while (0)
+#define ICE(msgid) do { cpp_ice(pfile, msgid); goto error; } while (0)
+static int
+do_assert (pfile)
+ cpp_reader *pfile;
+{
+ struct answer *new_answer;
+ cpp_hashnode *node;
+
+ node = _cpp_parse_assertion (pfile, &new_answer);
+ if (node)
{
- specific = 1;
- _cpp_init_toklist (&ans, NO_DUMMY_TOKEN);
-
- if (_cpp_scan_until (pfile, &ans, CPP_CLOSE_PAREN)
- != CPP_CLOSE_PAREN)
- ERROR ("missing close paren in #unassert");
-
- if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
- ICE ("impossible token, expecting ) in do_unassert");
+ new_answer->next = 0;
+ new_answer->list.line = pfile->token_list.line;
+ new_answer->list.file = pfile->token_list.file;
- type = _cpp_get_directive_token (pfile);
+ if (node->type == T_ASSERTION)
+ {
+ if (*find_answer (node, &new_answer->list))
+ goto err;
+ new_answer->next = node->value.answers;
+ }
+ node->type = T_ASSERTION;
+ node->value.answers = new_answer;
}
+ return 0;
- if (type != CPP_VSPACE)
- ERROR ("junk at end of #unassert");
-
- if (hp->type != T_ASSERTION)
- /* Not an error to #unassert something that isn't asserted.
- goto error to clean up. */
- goto error;
+ err:
+ cpp_warning (pfile, "\"%.*s\" re-asserted",
+ node->length - 1, node->name + 1);
+ FREE_ANSWER (new_answer);
+ return 0;
+}
- if (specific)
- {
- /* Find this specific answer and remove it. */
- struct predicate *o, *p;
-
- for (p = NULL, o = hp->value.pred; o; p = o, o = o->next)
- if (_cpp_equiv_toklists (&ans, &o->answer))
- {
- if (p)
- p->next = o->next;
- else
- hp->value.pred = o->next;
-
- _cpp_free_toklist (&o->answer);
- free (o);
- break;
- }
- }
- else
+static int
+do_unassert (pfile)
+ cpp_reader *pfile;
+{
+ cpp_hashnode *node;
+ struct answer *answer, *temp, *next;
+
+ node = _cpp_parse_assertion (pfile, &answer);
+ if (node)
{
- struct predicate *o, *p;
- for (o = hp->value.pred; o; o = p)
+ /* It isn't an error to #unassert something that isn't asserted. */
+ if (node->type == T_ASSERTION)
{
- p = o->next;
- _cpp_free_toklist ((cpp_toklist *) &o->answer);
- free (o);
+ if (answer)
+ {
+ struct answer **p = find_answer (node, &answer->list);
+
+ temp = *p;
+ if (temp)
+ {
+ *p = temp->next;
+ FREE_ANSWER (temp);
+ }
+ if (node->value.answers == 0)
+ node->type = T_VOID;
+ }
+ else
+ {
+ for (temp = node->value.answers; temp; temp = next)
+ {
+ next = temp->next;
+ FREE_ANSWER (temp);
+ }
+ node->type = T_VOID;
+ }
}
- hp->value.pred = NULL;
- }
- if (hp->value.pred == NULL)
- hp->type = T_VOID; /* Last answer for this predicate deleted. */
-
- error:
- _cpp_skip_rest_of_line (pfile);
- pfile->no_macro_expand--;
- CPP_SET_WRITTEN (pfile, old_written);
- if (specific)
- _cpp_free_toklist (&ans);
+ if (answer)
+ FREE_ANSWER (answer);
+ }
return 0;
}
@@ -1643,11 +1458,7 @@ cpp_define (pfile, str)
strcpy (&buf[count-4], " 1\n");
}
- if (cpp_push_buffer (pfile, (U_CHAR *)buf, count - 1) != NULL)
- {
- do_define (pfile);
- cpp_pop_buffer (pfile);
- }
+ _cpp_run_directive (pfile, &dtable[T_DEFINE], buf, count - 1);
}
/* Process MACRO as if it appeared as the body of an #undef. */
@@ -1656,17 +1467,7 @@ cpp_undef (pfile, macro)
cpp_reader *pfile;
const char *macro;
{
- /* Copy the string so we can append a newline. */
- size_t len = strlen (macro);
- char *buf = (char *) alloca (len + 2);
- memcpy (buf, macro, len);
- buf[len] = '\n';
- buf[len + 1] = '\0';
- if (cpp_push_buffer (pfile, (U_CHAR *)buf, len + 1) != NULL)
- {
- do_undef (pfile);
- cpp_pop_buffer (pfile);
- }
+ _cpp_run_directive (pfile, &dtable[T_UNDEF], macro, strlen (macro));
}
/* Process the string STR as if it appeared as the body of a #assert. */
@@ -1675,11 +1476,7 @@ cpp_assert (pfile, str)
cpp_reader *pfile;
const char *str;
{
- if (cpp_push_buffer (pfile, (const U_CHAR *)str, strlen (str)) != NULL)
- {
- do_assert (pfile);
- cpp_pop_buffer (pfile);
- }
+ _cpp_run_directive (pfile, &dtable[T_ASSERT], str, strlen (str));
}
/* Process STR as if it appeared as the body of an #unassert. */
@@ -1688,11 +1485,7 @@ cpp_unassert (pfile, str)
cpp_reader *pfile;
const char *str;
{
- if (cpp_push_buffer (pfile, (const U_CHAR *)str, strlen (str)) != NULL)
- {
- do_unassert (pfile);
- cpp_pop_buffer (pfile);
- }
+ _cpp_run_directive (pfile, &dtable[T_UNASSERT], str, strlen (str));
}
/* Determine whether the identifier ID, of length LEN, is a defined macro. */
@@ -1705,7 +1498,7 @@ cpp_defined (pfile, id, len)
cpp_hashnode *hp = cpp_lookup (pfile, id, len);
if (hp->type == T_POISON)
{
- cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
+ cpp_error (pfile, "attempt to use poisoned \"%s\"", hp->name);
return 0;
}
return (hp->type != T_VOID);