#include "cpphash.h"
#include "intl.h"
-#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
-#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
+#define SKIP_WHITE_SPACE(p) do { while (is_hspace(*p)) p++; } while (0)
#define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) ? CPP_BUFFER (pfile)->cur[N] : EOF)
#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
/* Forward declarations. */
-static char *my_strerror PROTO ((int));
-static void validate_else PROTO ((cpp_reader *, char *));
+static const char *my_strerror PROTO ((int));
+static void validate_else PROTO ((cpp_reader *, const char *));
static HOST_WIDEST_INT eval_if_expression PROTO ((cpp_reader *));
static void conditional_skip PROTO ((cpp_reader *, int,
static void parse_name PARAMS ((cpp_reader *, int));
static void parse_string PARAMS ((cpp_reader *, int));
static int parse_assertion PARAMS ((cpp_reader *));
+static const char *if_directive_name PARAMS ((cpp_reader *,
+ struct if_stack *));
/* External declarations. */
struct directive {
int length; /* Length of name */
int (*func) /* Function to handle directive */
- PARAMS ((cpp_reader *, struct directive *));
- char *name; /* Name of directive */
+ PARAMS ((cpp_reader *, const struct directive *));
+ const char *name; /* Name of directive */
enum node_type type; /* Code which describes which directive. */
};
are going to be placed in a table and some old compilers have trouble with
pointers to functions returning void. */
-static int do_define PARAMS ((cpp_reader *, struct directive *));
-static int do_line PARAMS ((cpp_reader *, struct directive *));
-static int do_include PARAMS ((cpp_reader *, struct directive *));
-static int do_undef PARAMS ((cpp_reader *, struct directive *));
-static int do_error PARAMS ((cpp_reader *, struct directive *));
-static int do_pragma PARAMS ((cpp_reader *, struct directive *));
-static int do_ident PARAMS ((cpp_reader *, struct directive *));
-static int do_if PARAMS ((cpp_reader *, struct directive *));
-static int do_xifdef PARAMS ((cpp_reader *, struct directive *));
-static int do_else PARAMS ((cpp_reader *, struct directive *));
-static int do_elif PARAMS ((cpp_reader *, struct directive *));
-static int do_endif PARAMS ((cpp_reader *, struct directive *));
+static int do_define PARAMS ((cpp_reader *, const struct directive *));
+static int do_line PARAMS ((cpp_reader *, const struct directive *));
+static int do_include PARAMS ((cpp_reader *, const struct directive *));
+static int do_undef PARAMS ((cpp_reader *, const struct directive *));
+static int do_error PARAMS ((cpp_reader *, const struct directive *));
+static int do_pragma PARAMS ((cpp_reader *, const struct directive *));
+static int do_ident PARAMS ((cpp_reader *, const struct directive *));
+static int do_if PARAMS ((cpp_reader *, const struct directive *));
+static int do_xifdef PARAMS ((cpp_reader *, const struct directive *));
+static int do_else PARAMS ((cpp_reader *, const struct directive *));
+static int do_elif PARAMS ((cpp_reader *, const struct directive *));
+static int do_endif PARAMS ((cpp_reader *, const struct directive *));
#ifdef SCCS_DIRECTIVE
-static int do_sccs PARAMS ((cpp_reader *, struct directive *));
+static int do_sccs PARAMS ((cpp_reader *, const struct directive *));
#endif
-static int do_assert PARAMS ((cpp_reader *, struct directive *));
-static int do_unassert PARAMS ((cpp_reader *, struct directive *));
-static int do_warning PARAMS ((cpp_reader *, struct directive *));
-
-#define IS_INCLUDE_DIRECTIVE_TYPE(t) \
-((int) T_INCLUDE <= (int) (t) && (int) (t) <= (int) T_IMPORT)
-
-/* Here is the actual list of #-directives, most-often-used first.
- The initialize_builtins function assumes #define is the very first. */
-
-static struct directive directive_table[] = {
- { 6, do_define, "define", T_DEFINE },
- { 5, do_xifdef, "ifdef", T_IFDEF },
- { 6, do_xifdef, "ifndef", T_IFNDEF },
- { 7, do_include, "include", T_INCLUDE },
- { 12, do_include, "include_next", T_INCLUDE_NEXT },
- { 6, do_include, "import", T_IMPORT },
- { 5, do_endif, "endif", T_ENDIF },
- { 4, do_else, "else", T_ELSE },
- { 2, do_if, "if", T_IF },
- { 4, do_elif, "elif", T_ELIF },
- { 5, do_undef, "undef", T_UNDEF },
- { 5, do_error, "error", T_ERROR },
- { 7, do_warning, "warning", T_WARNING },
- { 6, do_pragma, "pragma", T_PRAGMA },
- { 4, do_line, "line", T_LINE },
- { 5, do_ident, "ident", T_IDENT },
+static int do_assert PARAMS ((cpp_reader *, const struct directive *));
+static int do_unassert PARAMS ((cpp_reader *, const struct directive *));
+static int do_warning PARAMS ((cpp_reader *, const struct directive *));
+static enum cpp_token null_underflow PARAMS ((cpp_reader *));
+static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
+static int skip_comment PARAMS ((cpp_reader *, int));
+static int copy_comment PARAMS ((cpp_reader *, int));
+static void copy_rest_of_line PARAMS ((cpp_reader *));
+static int handle_directive PARAMS ((cpp_reader *));
+static void pass_thru_directive PARAMS ((const U_CHAR *, size_t, cpp_reader *,
+ const struct directive *));
+static enum cpp_token get_directive_token PARAMS ((cpp_reader *));
+static int read_line_number PARAMS ((cpp_reader *, int *));
+static void cpp_print_file_and_line PARAMS ((cpp_reader *));
+static void v_cpp_error PARAMS ((cpp_reader *, const char *, va_list));
+static void v_cpp_warning PARAMS ((cpp_reader *, const char *, va_list));
+static void v_cpp_error_with_line PARAMS ((cpp_reader *, int, int,
+ const char *, va_list));
+static void v_cpp_warning_with_line PARAMS ((cpp_reader *, int, int, const char *, va_list));
+static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *));
+static int consider_directive_while_skipping PARAMS ((cpp_reader *, IF_STACK_FRAME *));
+
+/* Here is the actual list of #-directives.
+ This table is ordered by frequency of occurrence; the numbers
+ at the end are directive counts from all the source code I have
+ lying around (egcs and libc CVS as of 1999-05-18, plus grub-0.5.91,
+ linux-2.2.9, and pcmcia-cs-3.0.9). */
+
+static const struct directive directive_table[] = {
+ /* In C89 */
+ { 6, do_define, "define", T_DEFINE }, /* 270554 */
+ { 7, do_include, "include", T_INCLUDE }, /* 52262 */
+ { 5, do_endif, "endif", T_ENDIF }, /* 45855 */
+ { 5, do_xifdef, "ifdef", T_IFDEF }, /* 22000 */
+ { 2, do_if, "if", T_IF }, /* 18162 */
+ { 4, do_else, "else", T_ELSE }, /* 9863 */
+ { 6, do_xifdef, "ifndef", T_IFNDEF }, /* 9675 */
+ { 5, do_undef, "undef", T_UNDEF }, /* 4837 */
+ { 4, do_line, "line", T_LINE }, /* 2465 */
+ { 4, do_elif, "elif", T_ELIF }, /* 610 */
+ { 5, do_error, "error", T_ERROR }, /* 475 */
+ { 6, do_pragma, "pragma", T_PRAGMA }, /* 195 */
+
+ /* Extensions. All deprecated except #warning and #include_next. */
+ { 7, do_warning, "warning", T_WARNING }, /* 22 - GNU */
+ { 12, do_include, "include_next", T_INCLUDE_NEXT }, /* 19 - GNU */
+ { 5, do_ident, "ident", T_IDENT }, /* 11 - SVR4 */
+ { 6, do_include, "import", T_IMPORT }, /* 0 - ObjC */
+ { 6, do_assert, "assert", T_ASSERT }, /* 0 - SVR4 */
+ { 8, do_unassert, "unassert", T_UNASSERT }, /* 0 - SVR4 */
#ifdef SCCS_DIRECTIVE
- { 4, do_sccs, "sccs", T_SCCS },
+ { 4, do_sccs, "sccs", T_SCCS }, /* 0 - SVR2? */
#endif
- { 6, do_assert, "assert", T_ASSERT },
- { 8, do_unassert, "unassert", T_UNASSERT },
{ -1, 0, "", T_UNUSED }
};
c = GETC();
if (c == EOF)
return;
- else if (is_hor_space[c])
+ else if (is_hspace(c))
{
if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "%s in preprocessing directive",
cpp_reader *pfile;
{
int c;
- register struct directive *kt;
+ register const struct directive *kt;
int ident_length;
U_CHAR *ident;
long old_written = CPP_WRITTEN (pfile);
cpp_skip_hspace (pfile);
c = PEEKC ();
+ /* # followed by a number is equivalent to #line. Do not recognize
+ this form in assembly language source files. 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 (c >= '0' && c <= '9')
{
- /* Handle # followed by a line number. */
- if (CPP_PEDANTIC (pfile))
+ if (CPP_OPTIONS (pfile)->lang_asm)
+ {
+ skip_rest_of_line (pfile);
+ return 1;
+ }
+
+ if (CPP_PEDANTIC (pfile)
+ && ! CPP_PREPROCESSED (pfile)
+ && ! CPP_BUFFER (pfile)->manual_pop)
cpp_pedwarn (pfile, "`#' followed by integer");
do_line (pfile, NULL);
return 1;
}
+ /* If we are rescanning preprocessed input, don't obey any directives
+ other than # nnn. */
+ if (CPP_PREPROCESSED (pfile))
+ return 0;
+
/* Now find the directive name. */
CPP_PUTC (pfile, '#');
parse_name (pfile, GETC());
static void
pass_thru_directive (buf, len, pfile, keyword)
- U_CHAR *buf;
+ const U_CHAR *buf;
size_t len;
cpp_reader *pfile;
- struct directive *keyword;
+ const struct directive *keyword;
{
register unsigned keyword_length = keyword->length;
CPP_PUTS_Q (pfile, buf, len);
}
-/* Check a purported macro name SYMNAME, and yield its length.
- ASSERTION is nonzero if this is really for an assertion name. */
+/* Check a purported macro name SYMNAME, and yield its length. */
int
-check_macro_name (pfile, symname, assertion)
+check_macro_name (pfile, symname)
cpp_reader *pfile;
- U_CHAR *symname;
- int assertion;
+ const U_CHAR *symname;
{
- U_CHAR *p;
+ const U_CHAR *p;
int sym_length;
- for (p = symname; is_idchar[*p]; p++)
+ for (p = symname; is_idchar(*p); p++)
;
sym_length = p - symname;
if (sym_length == 0
|| (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
- cpp_error (pfile,
- assertion ? "invalid assertion name" : "invalid macro name");
- else if (!is_idstart[*symname]
+ cpp_error (pfile, "invalid macro name");
+ else if (!is_idstart(*symname)
|| (! strncmp (symname, "defined", 7) && sym_length == 7)) {
U_CHAR *msg; /* what pain... */
msg = (U_CHAR *) alloca (sym_length + 1);
bcopy (symname, msg, sym_length);
msg[sym_length] = 0;
- cpp_error (pfile,
- (assertion
- ? "invalid assertion name `%s'"
- : "invalid macro name `%s'"),
- msg);
+ cpp_error (pfile, "invalid macro name `%s'", msg);
}
return sym_length;
}
/* Process a #define command.
-KEYWORD is the keyword-table entry for #define,
-or NULL for a "predefined" macro. */
+ KEYWORD is the keyword-table entry for #define,
+ or NULL for a "predefined" macro,
+ or the keyword-table entry for #pragma in the case of a #pragma poison. */
static int
do_define (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword;
+ const struct directive *keyword;
{
int hashcode;
MACRODEF mdef;
HASHNODE *hp;
long here;
U_CHAR *macro, *buf, *end;
+ enum node_type new_type;
here = CPP_WRITTEN (pfile);
copy_rest_of_line (pfile);
+ if (keyword == NULL || keyword->type == T_DEFINE)
+ new_type = T_MACRO;
+ else
+ new_type = T_POISON;
+
/* Copy out the line so we can pop the token buffer. */
buf = pfile->token_buffer + here;
end = CPP_PWRITTEN (pfile);
/* Redefining a precompiled key is ok. */
if (hp->type == T_PCSTRING)
ok = 1;
+ /* Redefining a poisoned identifier is even worse than `not ok'. */
+ else if (hp->type == T_POISON)
+ ok = -1;
/* Redefining a macro is ok if the definitions are the same. */
else if (hp->type == T_MACRO)
ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST || hp->type == T_STDC)
ok = ! CPP_OPTIONS (pfile)->done_initializing;
- /* Print the warning if it's not ok. */
- if (!ok)
+ /* Print the warning or error if it's not ok. */
+ if (ok <= 0)
{
- cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
+ if (hp->type == T_POISON)
+ cpp_error (pfile, "redefining poisoned `%.*s'",
+ mdef.symlen, mdef.symnam);
+ else
+ cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
if (hp->type == T_MACRO)
cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file,
hp->value.defn->line,
"this is the location of the previous definition");
}
- /* Replace the old definition. */
- hp->type = T_MACRO;
- hp->value.defn = mdef.defn;
+ if (hp->type != T_POISON)
+ {
+ /* Replace the old definition. */
+ hp->type = new_type;
+ hp->value.defn = mdef.defn;
+ }
}
else
- cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO,
+ cpp_install (pfile, mdef.symnam, mdef.symlen, new_type,
(char *) mdef.defn, hashcode);
- if (keyword)
+ if (keyword != NULL && keyword->type == T_DEFINE)
{
if (CPP_OPTIONS (pfile)->debug_output
|| CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
return NULL;
}
- new = (cpp_buffer *) xcalloc (sizeof (cpp_buffer), 1);
+ new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer));
new->if_stack = pfile->if_stack;
new->cleanup = null_cleanup;
void
cpp_expand_to_buffer (pfile, buf, length)
cpp_reader *pfile;
- U_CHAR *buf;
+ const U_CHAR *buf;
int length;
{
register cpp_buffer *ip;
static int
do_include (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword;
+ const struct directive *keyword;
{
int importing = (keyword->type == T_IMPORT);
int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
static int
do_line (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
int new_lineno;
if (strcmp (fname, ip->nominal_fname))
{
- char *newname, *oldname;
+ const char *newname, *oldname;
if (!strcmp (fname, ip->fname))
newname = ip->fname;
else if (ip->last_nominal_fname
&& ip->last_nominal_fname != oldname
&& ip->last_nominal_fname != newname
&& ip->last_nominal_fname != ip->fname)
- free (ip->last_nominal_fname);
+ free ((void *) ip->last_nominal_fname);
if (newname == ip->fname)
ip->last_nominal_fname = NULL;
static int
do_undef (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword;
+ const struct directive *keyword;
{
int sym_length;
HASHNODE *hp;
cpp_skip_hspace (pfile);
c = GETC();
- if (! is_idstart[c])
+ if (! is_idstart(c))
{
cpp_error (pfile, "token after #undef is not an identifier");
skip_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, here);
- sym_length = check_macro_name (pfile, buf, 0);
+ sym_length = check_macro_name (pfile, buf);
while ((hp = cpp_lookup (pfile, name, sym_length, -1)) != NULL)
{
need to pass through all effective #undef commands. */
if (CPP_OPTIONS (pfile)->debug_output && keyword)
pass_thru_directive (name, sym_length, pfile, keyword);
- if (hp->type != T_MACRO)
- cpp_warning (pfile, "undefining `%s'", hp->name);
- delete_macro (hp);
+ if (hp->type == T_POISON)
+ cpp_error (pfile, "cannot undefine poisoned `%s'", hp->name);
+ else
+ {
+ if (hp->type != T_MACRO)
+ cpp_warning (pfile, "undefining `%s'", hp->name);
+ delete_macro (hp);
+ }
}
return 0;
static int
do_error (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
long here = CPP_WRITTEN (pfile);
U_CHAR *text;
static int
do_warning (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
U_CHAR *text;
long here = CPP_WRITTEN(pfile);
static int
do_ident (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
/* Allow #ident in system headers, since that's not user's fault. */
if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
static int
do_pragma (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
long here;
U_CHAR *buf;
"`#pragma implementation' for `%s' appears after file is included",
fcopy);
}
+ else if (!strncmp (buf, "poison", 6))
+ {
+ /* Poison these symbols so that all subsequent usage produces an
+ error message. */
+ U_CHAR *p = buf + 6;
+ size_t plen;
+ U_CHAR *syms;
+ int writeit;
+
+ SKIP_WHITE_SPACE (p);
+ plen = strlen(p) + 1;
+
+ syms = (U_CHAR *) alloca (plen);
+ memcpy (syms, p, plen);
+
+ /* As a rule, don't include #pragma poison commands in output,
+ unless the user asks for them. */
+ writeit = (CPP_OPTIONS (pfile)->debug_output
+ || CPP_OPTIONS (pfile)->dump_macros == dump_definitions
+ || CPP_OPTIONS (pfile)->dump_macros == dump_names);
+
+ if (writeit)
+ CPP_SET_WRITTEN (pfile, here);
+ else
+ CPP_SET_WRITTEN (pfile, here-8);
+
+ if (writeit)
+ {
+ CPP_RESERVE (pfile, plen + 7);
+ CPP_PUTS_Q (pfile, "poison", 7);
+ }
+
+ while (*syms != '\0')
+ {
+ U_CHAR *end = syms;
+
+ while (is_idchar(*end))
+ end++;
+
+ if (!is_hspace(*end) && *end != '\0')
+ {
+ cpp_error (pfile, "invalid #pragma poison directive");
+ return 1;
+ }
+
+ if (cpp_push_buffer (pfile, syms, end - syms) != NULL)
+ {
+ do_define (pfile, keyword);
+ cpp_pop_buffer (pfile);
+ }
+ if (writeit)
+ {
+ CPP_PUTC_Q (pfile, ' ');
+ CPP_PUTS_Q (pfile, syms, end - syms);
+ }
+ syms = end;
+ SKIP_WHITE_SPACE (syms);
+ }
+ }
return 0;
}
static int
do_sccs (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "ANSI C does not allow `#sccs'");
}
#endif
\f
+
+/* We've found an `#if' directive. If the only thing before it in
+ this file is white space, and if it is of the form
+ `#if ! defined SYMBOL', then SYMBOL is a possible controlling macro
+ for inclusion of this file. (See redundant_include_p in cppfiles.c
+ for an explanation of controlling macros.) If so, return a
+ malloc'd copy of SYMBOL. Otherwise, return NULL. */
+
+static U_CHAR *
+detect_if_not_defined (pfile)
+ cpp_reader *pfile;
+{
+ U_CHAR *control_macro = 0;
+
+ if (pfile->only_seen_white == 2)
+ {
+ char *ident;
+ enum cpp_token token;
+ int base_offset;
+ int token_offset;
+ int need_rparen = 0;
+
+ /* Save state required for restore. */
+ pfile->no_macro_expand++;
+ parse_set_mark (pfile);
+ base_offset = CPP_WRITTEN (pfile);
+
+ /* Look for `!', */
+ if (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 = get_directive_token (pfile);
+ if (token != CPP_NAME)
+ goto restore;
+ ident = pfile->token_buffer + token_offset;
+ CPP_NUL_TERMINATE (pfile);
+ if (strcmp (ident, "defined"))
+ goto restore;
+
+ /* ...then an optional '(' and the name, */
+ token_offset = CPP_WRITTEN (pfile);
+ token = get_directive_token (pfile);
+ if (token == CPP_LPAREN)
+ {
+ token_offset = CPP_WRITTEN (pfile);
+ token = get_directive_token (pfile);
+ if (token != CPP_NAME)
+ goto restore;
+ need_rparen = 1;
+ }
+ else if (token != CPP_NAME)
+ goto restore;
+
+ ident = pfile->token_buffer + token_offset;
+ CPP_NUL_TERMINATE (pfile);
+
+ /* ...then the ')', if necessary, */
+ if ((!need_rparen || get_directive_token (pfile) == CPP_RPAREN)
+ /* ...and make sure there's nothing else on the line. */
+ && get_directive_token (pfile) == CPP_VSPACE)
+ control_macro = xstrdup (ident);
+
+ restore:
+ CPP_SET_WRITTEN (pfile, base_offset);
+ pfile->no_macro_expand--;
+ parse_goto_mark (pfile);
+ }
+
+ return control_macro;
+}
+
/*
* handle #if command by
* 1) inserting special `defined' keyword into the hash table
static int
do_if (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
+ U_CHAR *control_macro = detect_if_not_defined (pfile);
HOST_WIDEST_INT value = eval_if_expression (pfile);
- conditional_skip (pfile, value == 0, T_IF, NULL_PTR);
+ conditional_skip (pfile, value == 0, T_IF, control_macro);
return 0;
}
static int
do_elif (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) {
cpp_error (pfile, "`#elif' not within a conditional");
static int
do_xifdef (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword;
+ const struct directive *keyword;
{
int skip;
cpp_buffer *ip = CPP_BUFFER (pfile);
control_macro = (U_CHAR *) xmalloc (ident_length + 1);
bcopy (ident, control_macro, ident_length + 1);
}
+ if (hp != NULL && hp->type == T_POISON)
+ {
+ cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
+ skip = !skip;
+ }
}
else
{
else {
U_CHAR *cp = buf;
fprintf (pcp_outfile, "#undef ");
- while (is_idchar[*cp]) /* Ick! */
+ while (is_idchar(*cp)) /* Ick! */
fputc (*cp++, pcp_outfile);
putc ('\n', pcp_outfile);
}
temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
temp->fname = CPP_BUFFER (pfile)->nominal_fname;
-#if 0
temp->lineno = CPP_BUFFER (pfile)->lineno;
-#endif
temp->next = pfile->if_stack;
temp->control_macro = control_macro;
pfile->if_stack = temp;
IF_STACK_FRAME *stack;
{
long ident_len, ident;
- struct directive *kt;
+ const struct directive *kt;
IF_STACK_FRAME *temp;
cpp_skip_hspace (pfile);
static int
do_else (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
static int
do_endif (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
if (CPP_PEDANTIC (pfile))
validate_else (pfile, "#endif");
skip_rest_of_line (pfile);
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
- cpp_error (pfile, "unbalanced `#endif'");
+ cpp_error (pfile, "`#endif' not within a conditional");
else
{
IF_STACK_FRAME *temp = pfile->if_stack;
static void
validate_else (pfile, directive)
cpp_reader *pfile;
- char *directive;
+ const char *directive;
{
int c;
cpp_skip_hspace (pfile);
"text following `%s' violates ANSI standard", directive);
}
+/* Convert T_IF, etc. to a string. Used in error messages. */
+static const char *
+if_directive_name (pfile, ifs)
+ cpp_reader *pfile;
+ struct if_stack *ifs;
+{
+ switch (ifs->type)
+ {
+ case T_IF: return "#if";
+ case T_IFDEF: return "#ifdef";
+ case T_IFNDEF: return "#ifndef";
+ case T_ELIF: return "#elif";
+ case T_ELSE: return "#else";
+ default:
+ cpp_fatal (pfile, "impossible if_stack->type value %d", ifs->type);
+ return "unknown";
+ }
+}
+
/* Get the next token, and add it to the text in pfile->token_buffer.
Return the kind of token we got. */
}
else
{
- cpp_buffer *next_buf
- = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
- CPP_BUFFER (pfile)->seen_eof = 1;
+ cpp_buffer *next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
+ struct if_stack *ifs, *nifs;
+
+ /* Unwind the conditional stack and generate error messages. */
+ for (ifs = pfile->if_stack;
+ ifs != CPP_BUFFER (pfile)->if_stack;
+ ifs = nifs)
+ {
+ cpp_error_with_line (pfile, ifs->lineno, -1,
+ "unterminated `%s' conditional",
+ if_directive_name (pfile, ifs));
+
+ nifs = ifs->next;
+ free (ifs);
+ }
+ pfile->if_stack = ifs;
+
if (CPP_BUFFER (pfile)->nominal_fname
&& next_buf != CPP_NULL_BUFFER (pfile))
{
output_line_command (pfile, leave_file);
CPP_BUFFER (pfile) = cur_buffer;
}
+
+ CPP_BUFFER (pfile)->seen_eof = 1;
return CPP_POP;
}
}
if (!pfile->only_seen_white)
goto randomchar;
+ /* -traditional directives are recognized only with the # in
+ column 1.
+ XXX Layering violation. */
+ if (CPP_TRADITIONAL (pfile)
+ && CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base != 1)
+ goto randomchar;
if (handle_directive (pfile))
return CPP_DIRECTIVE;
pfile->only_seen_white = 0;
c = PEEKC ();
if (c == EOF)
break;
- if (!is_idchar[c] && c != '.'
+ if (!is_idchar(c) && c != '.'
&& ((c2 != 'e' && c2 != 'E'
&& ((c2 != 'p' && c2 != 'P') || CPP_C89 (pfile)))
|| (c != '+' && c != '-')))
c = GETC();
if (c == EOF)
goto chill_number_eof;
- if (!is_idchar[c])
+ if (!is_idchar(c))
break;
CPP_PUTC (pfile, c);
}
{
CPP_PUTC (pfile, c);
c = PEEKC ();
- if (c == EOF || !is_hor_space[c])
+ if (c == EOF || !is_hspace(c))
break;
FORWARD(1);
}
{
for (;;)
{
- if (! is_idchar[c])
+ if (! is_idchar(c))
{
FORWARD (-1);
break;
cpp_pop_buffer (pfile);
continue;
}
- if (!CPP_TRADITIONAL (pfile))
- {
- cpp_error_with_line (pfile, start_line, start_column,
- "unterminated string or character constant");
- if (pfile->multiline_string_line != start_line
- && pfile->multiline_string_line != 0)
- cpp_error_with_line (pfile,
- pfile->multiline_string_line, -1,
- "possible real start of unterminated constant");
- pfile->multiline_string_line = 0;
- }
+
+ cpp_error_with_line (pfile, start_line, start_column,
+ "unterminated string or character constant");
+ if (pfile->multiline_string_line != start_line
+ && pfile->multiline_string_line != 0)
+ cpp_error_with_line (pfile,
+ pfile->multiline_string_line, -1,
+ "possible real start of unterminated constant");
+ pfile->multiline_string_line = 0;
break;
}
CPP_PUTC (pfile, cc);
case '\n':
CPP_BUMP_LINE (pfile);
pfile->lineno++;
- /* Traditionally, end of line ends a string constant with
- no error. */
- if (CPP_TRADITIONAL (pfile))
+
+ /* In Fortran and assembly language, silently terminate
+ strings of either variety at end of line. This is a
+ kludge around not knowing where comments are in these
+ languages. */
+ if (CPP_OPTIONS (pfile)->lang_fortran
+ || CPP_OPTIONS (pfile)->lang_asm)
return;
- /* Character constants may not extend over multiple lines. */
+ /* Character constants may not extend over multiple lines.
+ In Standard C, neither may strings. We accept multiline
+ strings as an extension. */
if (c == '\'')
{
cpp_error_with_line (pfile, start_line, start_column,
return;
}
if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
- {
- cpp_pedwarn_with_line (pfile, start_line, start_column,
- "string constant runs past end of line");
- }
+ cpp_pedwarn_with_line (pfile, start_line, start_column,
+ "string constant runs past end of line");
if (pfile->multiline_string_line == 0)
pfile->multiline_string_line = start_line;
break;
int c, dropwhite;
cpp_skip_hspace (pfile);
c = PEEKC();
- if (! is_idstart[c])
+ if (! is_idstart(c))
{
cpp_error (pfile, "assertion predicate is not an identifier");
return 0;
c = PEEKC();
if (c != '(')
{
- if (is_hor_space[c] || c == '\r')
+ if (is_hspace(c) || c == '\r')
cpp_skip_hspace (pfile);
c = PEEKC();
}
dropwhite = 1;
while ((c = GETC()) != ')')
{
- if (is_hor_space[c])
+ if (is_space(c))
{
if (! dropwhite)
{
static int
do_assert (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
char *sym;
int ret, c;
static int
do_unassert (pfile, keyword)
cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ const struct directive *keyword ATTRIBUTE_UNUSED;
{
int c, ret;
char *sym;
ip->mark = -1;
}
-void
+static void
cpp_print_file_and_line (pfile)
cpp_reader *pfile;
{
giving specified file name and line number, not current. */
void
-cpp_pedwarn_with_file_and_line VPROTO ((cpp_reader *pfile, char *file, int line,
- const char *msgid, ...))
+cpp_pedwarn_with_file_and_line VPROTO ((cpp_reader *pfile, const char *file,
+ int line, const char *msgid, ...))
{
#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
- char *file;
+ const char *file;
int line;
const char *msgid;
#endif
#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
- file = va_arg (ap, char *);
+ file = va_arg (ap, const char *);
line = va_arg (ap, int);
msgid = va_arg (ap, const char *);
#endif
/* my_strerror - return the descriptive text associated with an
`errno' code. */
-static char *
+static const char *
my_strerror (errnum)
int errnum;
{
- char *result;
+ const char *result;
#ifndef VMS
#ifndef HAVE_STRERROR