/* CPP Library.
- Copyright (C) 1986, 87, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1986, 87, 89, 92-99, 2000 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
#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))
(Note that it is false while we're expanding macro *arguments*.) */
#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
-/* Forward declarations. */
-
-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,
- enum node_type, U_CHAR *));
-static void skip_if_group PROTO ((cpp_reader *));
-
-static void parse_name PARAMS ((cpp_reader *, int));
-static void parse_string PARAMS ((cpp_reader *, int));
-static int parse_assertion PARAMS ((cpp_reader *));
+/* ACTIVE_MARK_P is true if there's a live mark in the buffer, in which
+ case CPP_BUMP_LINE must not be called. */
+#define ACTIVE_MARK_P() (CPP_BUFFER (pfile)->mark != -1)
/* External declarations. */
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 *));
+
+/* Forward declarations. */
+
+static void validate_else PARAMS ((cpp_reader *, const char *));
+static HOST_WIDEST_INT eval_if_expression PARAMS ((cpp_reader *));
+static void conditional_skip PARAMS ((cpp_reader *, int,
+ enum node_type, U_CHAR *));
+static void skip_if_group PARAMS ((cpp_reader *));
+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 *));
+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 void skip_rest_of_line PARAMS ((cpp_reader *));
+static void cpp_skip_hspace 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 int read_line_number PARAMS ((cpp_reader *, int *));
+static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *));
+static int consider_directive_while_skipping PARAMS ((cpp_reader *,
+ IF_STACK_FRAME *));
+static void skip_block_comment PARAMS ((cpp_reader *));
+static void skip_line_comment PARAMS ((cpp_reader *));
+static void parse_set_mark PARAMS ((cpp_reader *));
+static void parse_goto_mark PARAMS ((cpp_reader *));
/* Here is the actual list of #-directives.
This table is ordered by frequency of occurrence; the numbers
CPP_SET_WRITTEN (pfile, old_written);
}
-/* Process the string STR as if it appeared as the body of a #define
+/* Process the string STR as if it appeared as the body of a #define.
If STR is just an identifier, define it with value 1.
If STR has anything after the identifier, then it should
be identifier=definition. */
U_CHAR *buf, *p;
size_t count;
- /* Copy the entire option so we can modify it. */
- count = strlen (str) + 3;
- buf = (U_CHAR *) alloca (count);
- memcpy (buf, str, count - 2);
- /* Change the first "=" in the string to a space. If there is none,
- tack " 1" on the end. */
- p = (U_CHAR *) strchr (buf, '=');
+ p = strchr (str, '=');
+ /* Copy the entire option so we can modify it.
+ Change the first "=" in the string to a space. If there is none,
+ tack " 1" on the end. Then add a newline and a NUL. */
+
if (p)
{
- *p = ' ';
- count -= 2;
+ count = strlen (str) + 2;
+ buf = (U_CHAR *) alloca (count);
+ memcpy (buf, str, count - 2);
+ buf[p - str] = ' ';
+ buf[count - 2] = '\n';
+ buf[count - 1] = '\0';
}
else
- strcpy (&buf[count-3], " 1");
-
+ {
+ count = strlen (str) + 4;
+ buf = (U_CHAR *) alloca (count);
+ memcpy (buf, str, count - 4);
+ strcpy (&buf[count-4], " 1\n");
+ }
+
if (cpp_push_buffer (pfile, buf, count - 1) != NULL)
{
do_define (pfile, NULL);
}
}
+/* Determine whether the identifier ID, of length LEN, is a defined macro. */
+int
+cpp_defined (pfile, id, len)
+ cpp_reader *pfile;
+ const U_CHAR *id;
+ int len;
+{
+ HASHNODE *hp = cpp_lookup (pfile, id, len);
+ if (hp && hp->type == T_POISON)
+ {
+ cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
+ return 0;
+ }
+ return (hp != NULL);
+}
static enum cpp_token
null_underflow (pfile)
return 0;
}
-/* Skip a comment - C, C++, or Chill style. M is the first character
- of the comment marker. If this really is a comment, skip to its
- end and return ' '. If we hit end-of-file before end-of-comment,
- return EOF. If this is not a comment, return M (which will be
- '/' or '-'). */
-
-static int
-skip_comment (pfile, m)
+/* Skip a C-style block comment. We know it's a comment, and point is
+ at the second character of the starter. */
+static void
+skip_block_comment (pfile)
cpp_reader *pfile;
- int m;
{
- if (m == '/' && PEEKC() == '*')
+ int c, prev_c = -1;
+ long line, col;
+
+ FORWARD(1);
+ cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
+ for (;;)
{
- int c, prev_c = -1;
- long line, col;
-
- FORWARD(1);
- cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
- for (;;)
+ c = GETC ();
+ if (c == EOF)
{
- c = GETC ();
- if (c == EOF)
- {
- cpp_error_with_line (pfile, line, col, "unterminated comment");
- return EOF;
- }
- else if (c == '\n' || c == '\r')
- /* \r cannot be a macro escape marker here. */
+ cpp_error_with_line (pfile, line, col, "unterminated comment");
+ return;
+ }
+ else if (c == '\n' || c == '\r')
+ {
+ /* \r cannot be a macro escape marker here. */
+ if (!ACTIVE_MARK_P())
CPP_BUMP_LINE (pfile);
- else if (c == '/' && prev_c == '*')
- return ' ';
- else if (c == '*' && prev_c == '/'
- && CPP_OPTIONS (pfile)->warn_comments)
- cpp_warning (pfile, "`/*' within comment");
-
- prev_c = c;
}
+ else if (c == '/' && prev_c == '*')
+ return;
+ else if (c == '*' && prev_c == '/'
+ && CPP_OPTIONS (pfile)->warn_comments)
+ cpp_warning (pfile, "`/*' within comment");
+
+ prev_c = c;
}
- else if ((m == '/' && PEEKC() == '/'
- && CPP_OPTIONS (pfile)->cplusplus_comments)
- || (m == '-' && PEEKC() == '-'
- && CPP_OPTIONS (pfile)->chill))
+}
+
+/* Skip a C++/Chill line comment. We know it's a comment, and point
+ is at the second character of the initiator. */
+static void
+skip_line_comment (pfile)
+ cpp_reader *pfile;
+{
+ FORWARD(1);
+ for (;;)
{
- FORWARD(1);
- for (;;)
+ int c = GETC ();
+
+ /* We don't have to worry about EOF in here. */
+ if (c == '\n')
{
- int c = GETC ();
- if (c == EOF)
- return ' '; /* Allow // to be terminated by EOF. */
- if (c == '\n')
- {
- /* Don't consider final '\n' to be part of comment. */
- FORWARD(-1);
- return ' ';
- }
- else if (c == '\r')
- /* \r cannot be a macro escape marker here. */
- CPP_BUMP_LINE (pfile);
+ /* Don't consider final '\n' to be part of comment. */
+ FORWARD(-1);
+ return;
+ }
+ else if (c == '\r')
+ {
+ /* \r cannot be a macro escape marker here. */
+ if (!ACTIVE_MARK_P())
+ CPP_BUMP_LINE (pfile);
+ if (CPP_OPTIONS (pfile)->warn_comments)
+ cpp_warning (pfile, "backslash-newline within line comment");
}
}
- else
- return m;
}
-/* Identical to skip_comment except that it copies the comment into the
- token_buffer. This is used if put_out_comments. */
+/* Skip a comment - C, C++, or Chill style. M is the first character
+ of the comment marker. If this really is a comment, skip to its
+ end and return ' '. If this is not a comment, return M (which will
+ be '/' or '-'). */
+
static int
-copy_comment (pfile, m)
+skip_comment (pfile, m)
cpp_reader *pfile;
int m;
{
if (m == '/' && PEEKC() == '*')
{
- int c, prev_c = -1;
- long line, col;
-
- CPP_PUTC (pfile, '/');
- CPP_PUTC (pfile, '*');
- FORWARD(1);
- cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
- for (;;)
- {
- c = GETC ();
- if (c == EOF)
- {
- cpp_error_with_line (pfile, line, col, "unterminated comment");
- /* We must pretend this was a legitimate comment, so that the
- output in token_buffer is not passed back tagged CPP_POP. */
- return ' ';
- }
- else if (c == '\r')
- {
- /* \r cannot be a macro escape marker here. */
- CPP_BUMP_LINE (pfile);
- continue;
- }
-
- CPP_PUTC (pfile, c);
- if (c == '\n')
- {
- pfile->lineno++;
- CPP_BUMP_LINE (pfile);
- }
- else if (c == '/' && prev_c == '*')
- return ' ';
- else if (c == '*' && prev_c == '/'
- && CPP_OPTIONS (pfile)->warn_comments)
- cpp_warning (pfile, "`/*' within comment");
-
- prev_c = c;
- }
+ skip_block_comment (pfile);
+ return ' ';
}
- else if ((m == '/' && PEEKC() == '/'
- && CPP_OPTIONS (pfile)->cplusplus_comments)
- || (m == '-' && PEEKC() == '-'
- && CPP_OPTIONS (pfile)->chill))
+ else if (m == '/' && PEEKC() == '/')
{
- CPP_PUTC (pfile, m);
- CPP_PUTC (pfile, m);
- FORWARD(1);
- for (;;)
+ if (CPP_BUFFER (pfile)->system_header_p)
{
- int c = GETC ();
- if (c == EOF)
- return ' '; /* Allow line comments to be terminated by EOF. */
- else if (c == '\n')
+ /* We silently allow C++ comments in system headers, irrespective
+ of conformance mode, because lots of busted systems do that
+ and trying to clean it up in fixincludes is a nightmare. */
+ skip_line_comment (pfile);
+ return ' ';
+ }
+ else if (CPP_OPTIONS (pfile)->cplusplus_comments)
+ {
+ if (CPP_OPTIONS (pfile)->c89
+ && CPP_PEDANTIC (pfile)
+ && ! CPP_BUFFER (pfile)->warned_cplusplus_comments)
{
- /* Don't consider final '\n' to be part of comment. */
- FORWARD(-1);
- return ' ';
+ cpp_pedwarn (pfile,
+ "C++ style comments are not allowed in ISO C89");
+ cpp_pedwarn (pfile,
+ "(this will be reported only once per input file)");
+ CPP_BUFFER (pfile)->warned_cplusplus_comments = 1;
}
- else if (c == '\r')
- /* \r cannot be a macro escape marker here. */
- CPP_BUMP_LINE (pfile);
-
- CPP_PUTC (pfile, c);
+ skip_line_comment (pfile);
+ return ' ';
}
+ else
+ return m;
+ }
+ else if (m == '-' && PEEKC() == '-'
+ && CPP_OPTIONS (pfile)->chill)
+ {
+ skip_line_comment (pfile);
+ return ' ';
}
else
return m;
}
+/* Identical to skip_comment except that it copies the comment into the
+ token_buffer. This is used if !discard_comments. */
+static int
+copy_comment (pfile, m)
+ cpp_reader *pfile;
+ int m;
+{
+ U_CHAR *start = CPP_BUFFER (pfile)->cur; /* XXX Layering violation */
+ U_CHAR *limit;
+
+ if (skip_comment (pfile, m) == m)
+ return m;
+
+ CPP_PUTC (pfile, m);
+ for (limit = CPP_BUFFER (pfile)->cur; start <= limit; start++)
+ if (*start != '\r')
+ CPP_PUTC (pfile, *start);
+ return ' ';
+}
/* Skip whitespace \-newline and comments. Does not macro-expand. */
-void
+static void
cpp_skip_hspace (pfile)
cpp_reader *pfile;
{
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",
else if (c == '/' || c == '-')
{
c = skip_comment (pfile, c);
- if (c == EOF)
- return;
- else if (c != ' ')
+ if (c != ' ')
break;
}
else
parse_string (pfile, c);
continue;
case '/':
- if (PEEKC() == '*' && CPP_TRADITIONAL (pfile))
+ if (PEEKC() == '*')
{
- CPP_PUTS (pfile, "/**/", 4);
- skip_comment (pfile, c);
+ if (CPP_TRADITIONAL (pfile))
+ CPP_PUTS (pfile, "/**/", 4);
+ skip_block_comment (pfile);
continue;
}
/* else fall through */
the scan itself. >75% of calls to copy_r_o_l are from here or
skip_if_group, which means the common case is to copy stuff into the
token_buffer only to discard it. */
-void
+static void
skip_rest_of_line (pfile)
cpp_reader *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)
+ return 0;
+
+ 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());
ident_length = CPP_PWRITTEN (pfile) - ident;
if (ident_length == 0)
{
- /* A line of just `#' becomes blank. */
- if (PEEKC() == '\n')
- return 1;
- else
- return 0;
+ /* A line of just `#' becomes blank. A line with something
+ other than an identifier after the # is reparsed as a non-
+ directive line. */
+ CPP_SET_WRITTEN (pfile, old_written);
+ return (PEEKC() == '\n');
}
- /*
- * Decode the keyword and call the appropriate expansion
- * routine, after moving the input pointer up to the next line.
- */
+ /* Decode the keyword and call the appropriate expansion routine. */
for (kt = directive_table; ; kt++)
{
if (kt->length <= 0)
- return 0;
+ /* # identifier, but not a legit directive. Pass onward as a
+ CPP_DIRECTIVE token anyway - let the consumer worry about it. */
+ return 1;
if (kt->length == ident_length
&& !strncmp (kt->name, ident, ident_length))
break;
}
CPP_SET_WRITTEN (pfile, old_written);
- (*kt->func) (pfile, kt);
+
+ if (pfile->no_directives)
+ {
+ cpp_error (pfile, "`#%s' may not be used inside a macro argument",
+ kt->name);
+ skip_rest_of_line (pfile);
+ }
+ else
+ (*kt->func) (pfile, kt);
return 1;
}
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;
const U_CHAR *symname;
- int assertion;
{
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;
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);
macro = (U_CHAR *) alloca (end - buf + 1);
- bcopy (buf, macro, end - buf + 1);
+ memcpy (macro, buf, end - buf + 1);
end = macro + (end - buf);
CPP_SET_WRITTEN (pfile, here);
- mdef = create_definition (macro, end, pfile, keyword == NULL);
+ mdef = create_definition (macro, end, pfile);
if (mdef.defn == 0)
return 0;
- hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE);
-
- if ((hp = cpp_lookup (pfile, mdef.symnam, mdef.symlen, hashcode)) != NULL)
+ if ((hp = cpp_lookup (pfile, mdef.symnam, mdef.symlen)) != NULL)
{
int ok = 0;
- /* Redefining a precompiled key is ok. */
- if (hp->type == T_PCSTRING)
- ok = 1;
+ /* Redefining a poisoned identifier is even worse than `not ok'. */
+ 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_MACRO)
+ 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_OPTIONS (pfile)->done_initializing)
cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file,
- hp->value.defn->line,
+ hp->value.defn->line, -1,
"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;
+ free_definition (hp->value.defn);
+ hp->value.defn = mdef.defn;
+ }
}
else
- cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO,
- (char *) mdef.defn, hashcode);
+ cpp_install (pfile, mdef.symnam, mdef.symlen, new_type, (char *)mdef.defn);
- 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;
cpp_reader *pfile;
{
cpp_buffer *buf = CPP_BUFFER (pfile);
+ if (ACTIVE_MARK_P())
+ cpp_ice (pfile, "mark active in cpp_pop_buffer");
(*buf->cleanup) (buf, pfile);
CPP_BUFFER (pfile) = CPP_PREV_BUFFER (buf);
free (buf);
if (length < 0)
{
- cpp_fatal (pfile, "internal error: length < 0 in cpp_expand_to_buffer");
+ cpp_ice (pfile, "length < 0 in cpp_expand_to_buffer");
return;
}
/* Like cpp_get_token, except that it does not read past end-of-line.
Also, horizontal space is skipped, and macros are popped. */
-static enum cpp_token
+enum cpp_token
get_directive_token (pfile)
cpp_reader *pfile;
{
+ long old_written = CPP_WRITTEN (pfile);
+ enum cpp_token token;
+
for (;;)
{
- long old_written = CPP_WRITTEN (pfile);
- enum cpp_token token;
cpp_skip_hspace (pfile);
if (PEEKC () == '\n')
- return CPP_VSPACE;
+ return CPP_VSPACE;
+
token = cpp_get_token (pfile);
- switch (token)
- {
- case CPP_POP:
- if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
- return token;
- /* ... else fall though ... */
- case CPP_HSPACE: case CPP_COMMENT:
+ /* token could be hspace at the beginning of a macro. */
+ if (token == CPP_HSPACE || token == CPP_COMMENT)
+ {
CPP_SET_WRITTEN (pfile, old_written);
- break;
- default:
+ continue;
+ }
+
+ /* token cannot be vspace, it would have been caught above. */
+ if (token == CPP_VSPACE)
+ {
+ cpp_ice (pfile, "VSPACE in get_directive_token");
return token;
- }
+ }
+
+ /* token cannot be POP unless the buffer is a macro buffer. */
+ if (token != CPP_POP)
+ return token;
+
+ if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
+ {
+ cpp_ice (pfile, "POP of file buffer in get_directive_token");
+ return token;
+ }
+
+ /* We must pop the buffer by hand, or else cpp_get_token might
+ hand us white space or newline on the next invocation. */
+ cpp_pop_buffer (pfile);
}
}
\f
if (fp == CPP_NULL_BUFFER (pfile))
{
- cpp_fatal (pfile, "cpp internal error: fp == NULL_BUFFER in do_include");
+ cpp_ice (pfile, "fp == NULL_BUFFER in do_include");
return 0;
}
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;
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)
+ while ((hp = cpp_lookup (pfile, name, sym_length)) != NULL)
{
/* If we are generating additional info for debugging (with -g) we
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;
cpp_reader *pfile;
U_CHAR *macro;
{
- if (cpp_push_buffer (pfile, macro, strlen (macro)))
+ /* Copy the string so we can append a newline. */
+ size_t len = strlen (macro);
+ U_CHAR *buf = alloca (len + 2);
+ memcpy (buf, macro, len);
+ buf[len] = '\n';
+ buf[len + 1] = '\0';
+ if (cpp_push_buffer (pfile, buf, len + 1))
{
do_undef (pfile, NULL);
cpp_pop_buffer (pfile);
}
}
-\f
/*
* Report an error detected by the program we are processing.
* Use the text of the line in the error message.
"`#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;
}
cpp_reader *pfile;
const struct directive *keyword ATTRIBUTE_UNUSED;
{
- if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) {
- cpp_error (pfile, "`#elif' not within a conditional");
- return 0;
- } else {
- if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF) {
- cpp_error (pfile, "`#elif' after `#else'");
-#if 0
- fprintf (stderr, " (matches line %d", pfile->if_stack->lineno);
-#endif
- if (pfile->if_stack->fname != NULL && CPP_BUFFER (pfile)->fname != NULL
- && strcmp (pfile->if_stack->fname,
- CPP_BUFFER (pfile)->nominal_fname) != 0)
- fprintf (stderr, ", file %s", pfile->if_stack->fname);
- fprintf (stderr, ")\n");
+ if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
+ {
+ cpp_error (pfile, "`#elif' not within a conditional");
+ return 0;
+ }
+ else
+ {
+ if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
+ {
+ cpp_error (pfile, "`#elif' after `#else'");
+ cpp_error_with_line (pfile, pfile->if_stack->lineno, -1,
+ "the conditional began here");
+ }
+ pfile->if_stack->type = T_ELIF;
}
- pfile->if_stack->type = T_ELIF;
- }
if (pfile->if_stack->if_succeeded)
skip_if_group (pfile);
- else {
- HOST_WIDEST_INT value = eval_if_expression (pfile);
- if (value == 0)
- skip_if_group (pfile);
- else {
- ++pfile->if_stack->if_succeeded; /* continue processing input */
- output_line_command (pfile, same_file);
+ else
+ {
+ HOST_WIDEST_INT value = eval_if_expression (pfile);
+ if (value == 0)
+ skip_if_group (pfile);
+ else
+ {
+ ++pfile->if_stack->if_succeeded; /* continue processing input */
+ output_line_command (pfile, same_file);
+ }
}
- }
return 0;
}
HOST_WIDEST_INT value;
long old_written = CPP_WRITTEN (pfile);
- pfile->pcp_inside_if = 1;
+ /* Work around bug in cpp_get_token where it may mistake an
+ assertion for a directive. */
+ pfile->only_seen_white = 0;
+
value = cpp_parse_expr (pfile);
- pfile->pcp_inside_if = 0;
+ skip_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old_written); /* Pop */
return value;
}
else if (token == CPP_NAME)
{
- HASHNODE *hp = cpp_lookup (pfile, ident, ident_length, -1);
+ HASHNODE *hp = cpp_lookup (pfile, ident, ident_length);
skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
if (start_of_file && !skip)
{
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
{
}
skip_rest_of_line (pfile);
-#if 0
- if (pcp_outfile) {
- /* Output a precondition for this macro. */
- if (hp && hp->value.defn->predefined)
- fprintf (pcp_outfile, "#define %s\n", hp->name);
- else {
- U_CHAR *cp = buf;
- fprintf (pcp_outfile, "#undef ");
- while (is_idchar[*cp]) /* Ick! */
- fputc (*cp++, pcp_outfile);
- putc ('\n', pcp_outfile);
- }
-#endif
-
conditional_skip (pfile, skip, T_IF, control_macro);
return 0;
}
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;
return 0;
case T_ELSE:
- if (CPP_PEDANTIC (pfile) && pfile->if_stack != stack)
+ if (pfile->if_stack != stack)
validate_else (pfile, "#else");
/* fall through */
case T_ELIF:
- if (pfile->if_stack->type == T_ELSE)
- cpp_error (pfile, "`%s' after `#else'", kt->name);
-
if (pfile->if_stack == stack)
return 1;
else
}
case T_ENDIF:
- if (CPP_PEDANTIC (pfile) && pfile->if_stack != stack)
+ if (pfile->if_stack != stack)
validate_else (pfile, "#endif");
if (pfile->if_stack == stack)
cpp_reader *pfile;
const struct directive *keyword ATTRIBUTE_UNUSED;
{
- cpp_buffer *ip = CPP_BUFFER (pfile);
-
- if (CPP_PEDANTIC (pfile))
- validate_else (pfile, "#else");
+ validate_else (pfile, "#else");
skip_rest_of_line (pfile);
- if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) {
- cpp_error (pfile, "`#else' not within a conditional");
- return 0;
- } else {
- /* #ifndef can't have its special treatment for containing the whole file
- if it has a #else clause. */
- pfile->if_stack->control_macro = 0;
-
- if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF) {
- cpp_error (pfile, "`#else' after `#else'");
- fprintf (stderr, " (matches line %d", pfile->if_stack->lineno);
- if (strcmp (pfile->if_stack->fname, ip->nominal_fname) != 0)
- fprintf (stderr, ", file %s", pfile->if_stack->fname);
- fprintf (stderr, ")\n");
- }
- pfile->if_stack->type = T_ELSE;
- }
+ if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
+ {
+ cpp_error (pfile, "`#else' not within a conditional");
+ return 0;
+ }
+ else
+ {
+ /* #ifndef can't have its special treatment for containing the whole file
+ if it has a #else clause. */
+ pfile->if_stack->control_macro = 0;
+
+ if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
+ {
+ cpp_error (pfile, "`#else' after `#else'");
+ cpp_error_with_line (pfile, pfile->if_stack->lineno, -1,
+ "the conditional began here");
+ }
+ pfile->if_stack->type = T_ELSE;
+ }
if (pfile->if_stack->if_succeeded)
skip_if_group (pfile);
- else {
- ++pfile->if_stack->if_succeeded; /* continue processing input */
- output_line_command (pfile, same_file);
- }
+ else
+ {
+ ++pfile->if_stack->if_succeeded; /* continue processing input */
+ output_line_command (pfile, same_file);
+ }
return 0;
}
cpp_reader *pfile;
const struct directive *keyword ATTRIBUTE_UNUSED;
{
- if (CPP_PEDANTIC (pfile))
- validate_else (pfile, "#endif");
+ 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;
return 0;
}
-/* When an #else or #endif is found while skipping failed conditional,
- if -pedantic was specified, this is called to warn about text after
- the command name. P points to the first char after the command name. */
+/* Issue -pedantic warning for text which is not a comment following
+ an #else or #endif. Do not warn in system headers, as this is harmless
+ and very common on old systems. */
static void
validate_else (pfile, directive)
cpp_reader *pfile;
const char *directive;
{
- int c;
+ if (! CPP_PEDANTIC (pfile) || CPP_BUFFER (pfile)->system_header_p)
+ return;
+
cpp_skip_hspace (pfile);
- c = PEEKC ();
- if (c != EOF && c != '\n')
+ if (PEEKC () != '\n')
cpp_pedwarn (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_ice (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. */
-
+
enum cpp_token
cpp_get_token (pfile)
cpp_reader *pfile;
c = GETC();
if (c == EOF)
{
- handle_eof:
if (CPP_BUFFER (pfile)->manual_pop)
/* If we've been reading from redirected input, the
frontend will pop the buffer. */
}
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;
}
}
goto op2;
comment:
- if (opts->put_out_comments)
- c = copy_comment (pfile, c);
- else
+ if (opts->discard_comments)
c = skip_comment (pfile, c);
- if (c == EOF)
- goto handle_eof;
- else if (c != ' ')
+ else
+ c = copy_comment (pfile, c);
+ if (c != ' ')
goto randomchar;
/* Comments are equivalent to spaces.
For -traditional, a comment is equivalent to nothing. */
- if (opts->traditional || opts->put_out_comments)
+ if (opts->traditional || !opts->discard_comments)
return CPP_COMMENT;
else
{
CPP_PUTC (pfile, c);
return CPP_HSPACE;
}
-#if 0
- if (opts->for_lint) {
- U_CHAR *argbp;
- int cmdlen, arglen;
- char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
-
- if (lintcmd != NULL) {
- /* I believe it is always safe to emit this newline: */
- obp[-1] = '\n';
- bcopy ("#pragma lint ", (char *) obp, 13);
- obp += 13;
- bcopy (lintcmd, (char *) obp, cmdlen);
- obp += cmdlen;
-
- if (arglen != 0) {
- *(obp++) = ' ';
- bcopy (argbp, (char *) obp, arglen);
- obp += arglen;
- }
-
- /* OK, now bring us back to the state we were in before we entered
- this branch. We need #line because the newline for the pragma
- could mess things up. */
- output_line_command (pfile, same_file);
- *(obp++) = ' '; /* just in case, if comments are copied thru */
- *(obp++) = '/';
- }
- }
-#endif
case '#':
-#if 0
- /* If this is expanding a macro definition, don't recognize
- preprocessor directives. */
- if (ip->macro != 0)
- goto randomchar;
- /* If this is expand_into_temp_buffer, recognize them
- only after an actual newline at this level,
- not at the beginning of the input level. */
- if (ip->fname == 0 && beg_of_line == ip->buf)
- goto randomchar;
- if (ident_length)
- goto specialchar;
-#endif
-
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;
- return CPP_OTHER;
+ goto randomchar;
case '\"':
case '\'':
here. Just delete 'em. */
int d = GETC();
if (d != '-' && d != ' ')
- cpp_fatal (pfile,
- "internal error: unrecognized escape \\r%c",
- d);
+ cpp_ice (pfile, "unrecognized escape \\r%c", d);
CPP_ADJUST_WRITTEN (pfile, -1);
}
}
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);
}
return CPP_NAME;
ident = pfile->token_buffer + before_name_written;
ident_len = CPP_PWRITTEN (pfile) - ident;
- hp = cpp_lookup (pfile, ident, ident_len, -1);
+ hp = cpp_lookup (pfile, ident, ident_len);
if (!hp)
return CPP_NAME;
if (hp->type == T_DISABLED)
return CPP_NAME;
}
- /* If macro wants an arglist, verify that a '(' follows.
- first skip all whitespace, copying it to the output
- after the macro name. Then, if there is no '(',
- decide this is not a macro call and leave things that way. */
+ /* If macro wants an arglist, verify that a '(' follows. */
if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
{
- int is_macro_call, macbuf_whitespace = 0;
+ int macbuf_whitespace = 0;
+
+ while (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
+ {
+ U_CHAR *point = CPP_BUFFER (pfile)->cur;
+ for (;;)
+ {
+ cpp_skip_hspace (pfile);
+ c = PEEKC ();
+ if (c == '\n')
+ FORWARD(1);
+ else
+ break;
+ }
+ if (point != CPP_BUFFER (pfile)->cur)
+ macbuf_whitespace = 1;
+ if (c == '(')
+ goto is_macro_call;
+ else if (c != EOF)
+ goto not_macro_call;
+ cpp_pop_buffer (pfile);
+ }
parse_set_mark (pfile);
for (;;)
{
cpp_skip_hspace (pfile);
c = PEEKC ();
- is_macro_call = c == '(';
- if (c != EOF)
- {
- if (c != '\n')
- break;
- FORWARD (1);
- }
- else
- {
- if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
- {
- if (CPP_BUFFER (pfile)->mark !=
- (CPP_BUFFER (pfile)->cur
- - CPP_BUFFER (pfile)->buf))
- macbuf_whitespace = 1;
-
- /* The mark goes away automatically when
- the buffer is popped. */
- cpp_pop_buffer (pfile);
- parse_set_mark (pfile);
- }
- else
- break;
- }
+ if (c == '\n')
+ FORWARD(1);
+ else
+ break;
}
- if (!is_macro_call)
- {
- parse_goto_mark (pfile);
- if (macbuf_whitespace)
- CPP_PUTC (pfile, ' ');
- }
- else
- parse_clear_mark (pfile);
- if (!is_macro_call)
- return CPP_NAME;
+ parse_goto_mark (pfile);
+
+ if (c == '(')
+ goto is_macro_call;
+
+ not_macro_call:
+ if (macbuf_whitespace)
+ CPP_PUTC (pfile, ' ');
+ return CPP_NAME;
}
+ is_macro_call:
/* This is now known to be a macro call.
Expand the macro, reading arguments as needed,
and push the expansion on the input stack. */
{
CPP_PUTC (pfile, c);
c = PEEKC ();
- if (c == EOF || !is_hor_space[c])
+ if (c == EOF || !is_hspace(c))
break;
FORWARD(1);
}
}
else
{
- cpp_fatal (pfile,
- "internal error: unrecognized escape \\r%c", c);
+ cpp_ice (pfile, "unrecognized escape \\r%c", c);
goto get_next;
}
}
{
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;
CPP_ADJUST_WRITTEN (pfile, -1);
if (CPP_BUFFER (pfile)->has_escapes)
{
- cpp_fatal (pfile,
- "internal error: \\r escape inside string constant");
+ cpp_ice (pfile, "\\r escape inside string constant");
FORWARD(1);
}
else
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)
{
thislen = strlen (sym);
baselen = index (sym, '(') - sym;
- this = cpp_lookup (pfile, sym, thislen, -1);
+ this = cpp_lookup (pfile, sym, thislen);
if (this)
{
cpp_warning (pfile, "`%s' re-asserted", sym);
goto error;
}
- base = cpp_lookup (pfile, sym, baselen, -1);
+ base = cpp_lookup (pfile, sym, baselen);
if (! base)
- base = cpp_install (pfile, sym, baselen, T_ASSERT, 0, -1);
+ base = cpp_install (pfile, sym, baselen, T_ASSERT, 0);
else if (base->type != T_ASSERT)
{
/* Token clash - but with what?! */
- cpp_fatal (pfile,
- "cpp internal error: base->type != T_ASSERT in do_assert");
+ cpp_ice (pfile, "base->type != T_ASSERT in do_assert");
goto error;
}
this = cpp_install (pfile, sym, thislen, T_ASSERT,
- (char *)base->value.aschain, -1);
+ (char *)base->value.aschain);
base->value.aschain = this;
pfile->limit = (unsigned char *) sym; /* Pop */
thislen = strlen (sym);
if (ret == 1)
{
- base = cpp_lookup (pfile, sym, thislen, -1);
+ base = cpp_lookup (pfile, sym, thislen);
if (! base)
goto error; /* It isn't an error to #undef what isn't #defined,
so it isn't an error to #unassert what isn't
else
{
baselen = index (sym, '(') - sym;
- base = cpp_lookup (pfile, sym, baselen, -1);
+ base = cpp_lookup (pfile, sym, baselen);
if (! base) goto error;
- this = cpp_lookup (pfile, sym, thislen, -1);
+ this = cpp_lookup (pfile, sym, thislen);
if (! this) goto error;
next = base;
cpp_read_check_assertion (pfile)
cpp_reader *pfile;
{
- U_CHAR *name = CPP_PWRITTEN (pfile);
+ U_CHAR *name;
int result;
- HASHNODE *hp;
+ long written = CPP_WRITTEN (pfile);
FORWARD (1); /* Skip '#' */
cpp_skip_hspace (pfile);
result = 0;
else
{
- hp = cpp_lookup (pfile, name, CPP_PWRITTEN (pfile) - name, -1);
- result = (hp != 0);
+ name = pfile->token_buffer + written;
+ result = cpp_defined (pfile, name, CPP_PWRITTEN (pfile) - name);
}
- pfile->limit = name;
+ CPP_SET_WRITTEN (pfile, written);
return result;
}
-/* Remember the current position of PFILE. */
+/* Remember the current position of PFILE so it may be returned to
+ after looking ahead a bit.
-void
+ Note that when you set a mark, you _must_ return to that mark. You
+ may not forget about it and continue parsing. You may not pop a
+ buffer with an active mark. You may not call CPP_BUMP_LINE while a
+ mark is active. */
+
+static void
parse_set_mark (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
- if (ip->mark != -1)
- cpp_fatal (pfile,
- "cpp internal error: ip->mark != -1 in parse_set_mark");
+ if (ACTIVE_MARK_P())
+ cpp_ice (pfile, "mark active in parse_set_mark");
ip->mark = ip->cur - ip->buf;
}
-/* Clear the current mark - we no longer need it. */
-
-void
-parse_clear_mark (pfile)
- cpp_reader *pfile;
-{
- cpp_buffer *ip = CPP_BUFFER (pfile);
- if (ip->mark == -1)
- cpp_fatal (pfile,
- "cpp internal error: ip->mark == -1 in parse_clear_mark");
-
- ip->mark = -1;
-}
-
/* Backup the current position of PFILE to that saved in its mark,
and clear the mark. */
-void
+static void
parse_goto_mark (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
- if (ip->mark == -1)
- cpp_fatal (pfile,
- "cpp internal error: ip->mark == -1 in parse_goto_mark");
+ if (!ACTIVE_MARK_P())
+ cpp_ice (pfile, "mark not active in parse_goto_mark");
ip->cur = ip->buf + ip->mark;
ip->mark = -1;
}
-
-static void
-cpp_print_file_and_line (pfile)
- cpp_reader *pfile;
-{
- cpp_buffer *ip = cpp_file_buffer (pfile);
-
- if (ip != NULL)
- {
- long line, col;
- cpp_buf_line_and_col (ip, &line, &col);
- cpp_file_line_for_message (pfile, ip->nominal_fname,
- line, pfile->show_column ? col : -1);
- }
-}
-
-static void
-v_cpp_error (pfile, msgid, ap)
- cpp_reader *pfile;
- const char *msgid;
- va_list ap;
-{
- cpp_print_containing_files (pfile);
- cpp_print_file_and_line (pfile);
- v_cpp_message (pfile, 1, msgid, ap);
-}
-
-void
-cpp_error VPROTO ((cpp_reader * pfile, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START(ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_cpp_error (pfile, msgid, ap);
- va_end(ap);
-}
-
-/* Print error message but don't count it. */
-
-static void
-v_cpp_warning (pfile, msgid, ap)
- cpp_reader *pfile;
- const char *msgid;
- va_list ap;
-{
- if (CPP_OPTIONS (pfile)->inhibit_warnings)
- return;
-
- if (CPP_OPTIONS (pfile)->warnings_are_errors)
- pfile->errors++;
-
- cpp_print_containing_files (pfile);
- cpp_print_file_and_line (pfile);
- v_cpp_message (pfile, 0, msgid, ap);
-}
-
-void
-cpp_warning VPROTO ((cpp_reader * pfile, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_cpp_warning (pfile, msgid, ap);
- va_end(ap);
-}
-
-/* Print an error message and maybe count it. */
-
-void
-cpp_pedwarn VPROTO ((cpp_reader * pfile, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- msgid = va_arg (ap, const char *);
-#endif
-
- if (CPP_OPTIONS (pfile)->pedantic_errors)
- v_cpp_error (pfile, msgid, ap);
- else
- v_cpp_warning (pfile, msgid, ap);
- va_end(ap);
-}
-
-static void
-v_cpp_error_with_line (pfile, line, column, msgid, ap)
- cpp_reader * pfile;
- int line;
- int column;
- const char * msgid;
- va_list ap;
-{
- cpp_buffer *ip = cpp_file_buffer (pfile);
-
- cpp_print_containing_files (pfile);
-
- if (ip != NULL)
- cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
-
- v_cpp_message (pfile, 1, msgid, ap);
-}
-
-void
-cpp_error_with_line VPROTO ((cpp_reader * pfile, int line, int column,
- const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- int line;
- int column;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- line = va_arg (ap, int);
- column = va_arg (ap, int);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_cpp_error_with_line(pfile, line, column, msgid, ap);
- va_end(ap);
-}
-
-static void
-v_cpp_warning_with_line (pfile, line, column, msgid, ap)
- cpp_reader * pfile;
- int line;
- int column;
- const char *msgid;
- va_list ap;
-{
- cpp_buffer *ip;
-
- if (CPP_OPTIONS (pfile)->inhibit_warnings)
- return;
-
- if (CPP_OPTIONS (pfile)->warnings_are_errors)
- pfile->errors++;
-
- cpp_print_containing_files (pfile);
-
- ip = cpp_file_buffer (pfile);
-
- if (ip != NULL)
- cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
-
- v_cpp_message (pfile, 0, msgid, ap);
-}
-
-void
-cpp_warning_with_line VPROTO ((cpp_reader * pfile, int line, int column,
- const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- int line;
- int column;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- line = va_arg (ap, int);
- column = va_arg (ap, int);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_cpp_warning_with_line (pfile, line, column, msgid, ap);
- va_end(ap);
-}
-
-void
-cpp_pedwarn_with_line VPROTO ((cpp_reader * pfile, int line, int column,
- const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- int line;
- int column;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- line = va_arg (ap, int);
- column = va_arg (ap, int);
- msgid = va_arg (ap, const char *);
-#endif
-
- if (CPP_OPTIONS (pfile)->pedantic_errors)
- v_cpp_error_with_line (pfile, column, line, msgid, ap);
- else
- v_cpp_warning_with_line (pfile, line, column, msgid, ap);
- va_end(ap);
-}
-
-/* Report a warning (or an error if pedantic_errors)
- giving specified file name and line number, not current. */
-
-void
-cpp_pedwarn_with_file_and_line VPROTO ((cpp_reader *pfile, const char *file,
- int line, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- const char *file;
- int line;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- file = va_arg (ap, const char *);
- line = va_arg (ap, int);
- msgid = va_arg (ap, const char *);
-#endif
-
- if (!CPP_OPTIONS (pfile)->pedantic_errors
- && CPP_OPTIONS (pfile)->inhibit_warnings)
- return;
- if (file != NULL)
- cpp_file_line_for_message (pfile, file, line, -1);
- v_cpp_message (pfile, CPP_OPTIONS (pfile)->pedantic_errors, msgid, ap);
- va_end(ap);
-}
-
-/* my_strerror - return the descriptive text associated with an
- `errno' code. */
-
-static const char *
-my_strerror (errnum)
- int errnum;
-{
- const char *result;
-
-#ifndef VMS
-#ifndef HAVE_STRERROR
- result = (char *) ((errnum < sys_nerr) ? sys_errlist[errnum] : 0);
-#else
- result = strerror (errnum);
-#endif
-#else /* VMS */
- /* VAXCRTL's strerror() takes an optional second argument, which only
- matters when the first argument is EVMSERR. However, it's simplest
- just to pass it unconditionally. `vaxc$errno' is declared in
- <errno.h>, and maintained by the library in parallel with `errno'.
- We assume that caller's `errnum' either matches the last setting of
- `errno' by the library or else does not have the value `EVMSERR'. */
-
- result = strerror (errnum, vaxc$errno);
-#endif
-
- if (!result)
- result = "errno = ?";
-
- return result;
-}
-
-/* Error including a message from `errno'. */
-
-void
-cpp_error_from_errno (pfile, name)
- cpp_reader *pfile;
- const char *name;
-{
- cpp_message_from_errno (pfile, 1, name);
-}
-
-void
-cpp_message_from_errno (pfile, is_error, name)
- cpp_reader *pfile;
- int is_error;
- const char *name;
-{
- int e = errno;
- cpp_buffer *ip = cpp_file_buffer (pfile);
-
- cpp_print_containing_files (pfile);
-
- if (ip != NULL)
- cpp_file_line_for_message (pfile, ip->nominal_fname, ip->lineno, -1);
-
- cpp_message (pfile, is_error, "%s: %s", name, my_strerror (e));
-}
-
-void
-cpp_perror_with_name (pfile, name)
- cpp_reader *pfile;
- const char *name;
-{
- cpp_message (pfile, 1, "%s: %s: %s", progname, name, my_strerror (errno));
-}
-
-/* TODO:
- * No pre-compiled header file support.
- *
- * Possibly different enum token codes for each C/C++ token.
- *
- * Find and cleanup remaining uses of static variables,
- *
- * Support -dM flag (dump_all_macros).
- *
- * Support for_lint flag.
- */