#include "c-pragma.h"
#include "toplev.h"
#include "intl.h"
-#include "ggc.h"
#include "tm_p.h"
#include "splay-tree.h"
#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ((ENV_VALUE) = getenv (ENV_NAME))
#endif
-#if USE_CPPLIB
-extern cpp_reader parse_in;
-#else
-/* Stream for reading from the input file. */
-FILE *finput;
-#endif
-
-/* Private idea of the line number. See discussion in c_lex(). */
-static int lex_lineno;
+/* The original file name, before changing "-" to "stdin". */
+static const char *orig_filename;
/* We may keep statistics about how long which files took to compile. */
static int header_time, body_time;
/* Cause the `yydebug' variable to be defined. */
#define YYDEBUG 1
-#if !USE_CPPLIB
-
-struct putback_buffer
-{
- unsigned char *buffer;
- int buffer_size;
- int index;
-};
-
-static struct putback_buffer putback = {NULL, 0, -1};
-
-static inline int getch PARAMS ((void));
-
-static inline int
-getch ()
-{
- if (putback.index != -1)
- {
- int ch = putback.buffer[putback.index];
- --putback.index;
- return ch;
- }
- return getc (finput);
-}
-
-static inline void put_back PARAMS ((int));
-
-static inline void
-put_back (ch)
- int ch;
-{
- if (ch != EOF)
- {
- if (putback.index == putback.buffer_size - 1)
- {
- putback.buffer_size += 16;
- putback.buffer = xrealloc (putback.buffer, putback.buffer_size);
- }
- putback.buffer[++putback.index] = ch;
- }
-}
-
-int linemode;
-
-#endif
-
/* File used for outputting assembler code. */
extern FILE *asm_out_file;
/* Number of bytes in a wide character. */
#define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
-#if !USE_CPPLIB
-static int maxtoken; /* Current nominal length of token buffer. */
-static char *token_buffer; /* Pointer to token buffer.
- Actual allocated length is maxtoken + 2. */
-#endif
-
int indent_level; /* Number of { minus number of }. */
int pending_lang_change; /* If we need to switch languages - C++ only */
int c_header_level; /* depth in C headers - C++ only */
static tree lex_charconst PARAMS ((const char *, unsigned int, int));
static void update_header_times PARAMS ((const char *));
static int dump_one_header PARAMS ((splay_tree_node, void *));
-static int mark_splay_tree_node PARAMS ((splay_tree_node, void *));
-static void mark_splay_tree PARAMS ((void *));
-
-#if !USE_CPPLIB
-static int skip_white_space PARAMS ((int));
-static char *extend_token_buffer PARAMS ((const char *));
-static void extend_token_buffer_to PARAMS ((int));
-static int read_line_number PARAMS ((int *));
-static void process_directive PARAMS ((void));
-#else
static void cb_ident PARAMS ((cpp_reader *, const cpp_string *));
-static void cb_enter_file PARAMS ((cpp_reader *));
-static void cb_leave_file PARAMS ((cpp_reader *));
-static void cb_rename_file PARAMS ((cpp_reader *));
+static void cb_file_change PARAMS ((cpp_reader *, const cpp_file_change *));
static void cb_def_pragma PARAMS ((cpp_reader *));
-#endif
-
+static void cb_define PARAMS ((cpp_reader *, cpp_hashnode *));
+static void cb_undef PARAMS ((cpp_reader *, cpp_hashnode *));
\f
const char *
init_c_lex (filename)
const char *filename;
{
+ struct cpp_callbacks *cb;
struct c_fileinfo *toplevel;
+ orig_filename = filename;
+
/* Set up filename timing. Must happen before cpp_start_read. */
file_info_tree = splay_tree_new ((splay_tree_compare_fn)strcmp,
0,
(splay_tree_delete_value_fn)free);
- /* Make sure to mark the filenames in the tree for GC. */
- ggc_add_root (&file_info_tree, 1, sizeof (file_info_tree),
- mark_splay_tree);
- toplevel = get_fileinfo (ggc_strdup ("<top level>"));
+ toplevel = get_fileinfo ("<top level>");
if (flag_detailed_statistics)
{
header_time = 0;
GET_ENVIRONMENT (literal_codeset, "LANG");
#endif
-#if !USE_CPPLIB
- /* Open input file. */
- if (filename == 0 || !strcmp (filename, "-"))
- {
- finput = stdin;
- filename = "stdin";
- }
- else
- finput = fopen (filename, "r");
- if (finput == 0)
- pfatal_with_name (filename);
-
-#ifdef IO_BUFFER_SIZE
- setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
-#endif
-#else /* !USE_CPPLIB */
+ cb = cpp_get_callbacks (parse_in);
- parse_in.cb.ident = cb_ident;
- parse_in.cb.enter_file = cb_enter_file;
- parse_in.cb.leave_file = cb_leave_file;
- parse_in.cb.rename_file = cb_rename_file;
- parse_in.cb.def_pragma = cb_def_pragma;
+ cb->ident = cb_ident;
+ cb->file_change = cb_file_change;
+ cb->def_pragma = cb_def_pragma;
- /* Make sure parse_in.digraphs matches flag_digraphs. */
- CPP_OPTION (&parse_in, digraphs) = flag_digraphs;
-
- if (! cpp_start_read (&parse_in, filename))
- exit (FATAL_EXIT_CODE); /* cpplib has emitted an error. */
+ /* Set the debug callbacks if we can use them. */
+ if (debug_info_level == DINFO_LEVEL_VERBOSE
+ && (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG))
+ {
+ cb->define = cb_define;
+ cb->undef = cb_undef;
+ }
if (filename == 0 || !strcmp (filename, "-"))
filename = "stdin";
-#endif
-#if !USE_CPPLIB
- maxtoken = 40;
- token_buffer = (char *) xmalloc (maxtoken + 2);
-#endif
- /* Start it at 0, because check_newline is called at the very beginning
- and will increment it to 1. */
- lineno = lex_lineno = 0;
+ /* Start it at 0. */
+ lineno = 0;
return filename;
}
+/* A thin wrapper around the real parser that initializes the
+ integrated preprocessor after debug output has been initialized. */
+
+int
+yyparse()
+{
+ if (! cpp_start_read (parse_in, orig_filename))
+ return 1; /* cpplib has emitted an error. */
+
+ return yyparse_1();
+}
+
struct c_fileinfo *
get_fileinfo (name)
const char *name;
splay_tree_foreach (file_info_tree, dump_one_header, 0);
}
-#if !USE_CPPLIB
-
-/* If C is not whitespace, return C.
- Otherwise skip whitespace and return first nonwhite char read. */
-
-static int
-skip_white_space (c)
- register int c;
-{
- for (;;)
- {
- switch (c)
- {
- /* There is no need to process comments or backslash-newline
- here. None can occur in the output of cpp. Do handle \r
- in case someone sent us a .i file. */
-
- case '\n':
- if (linemode)
- {
- put_back (c);
- return EOF;
- }
- c = check_newline ();
- break;
-
- case '\r':
- /* Per C99, horizontal whitespace is just these four characters. */
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- c = getch ();
- break;
-
- case '\\':
- error ("stray '\\' in program");
- c = getch ();
- break;
-
- default:
- return (c);
- }
- }
-}
-
-/* Skips all of the white space at the current location in the input file. */
-
-void
-position_after_white_space ()
-{
- register int c;
-
- c = getch ();
-
- put_back (skip_white_space (c));
-}
-
-/* Make the token buffer longer, preserving the data in it.
- P should point to just beyond the last valid character in the old buffer.
- The value we return is a pointer to the new buffer
- at a place corresponding to P. */
+/* Not yet handled: #pragma, #define, #undef.
+ No need to deal with linemarkers under normal conditions. */
static void
-extend_token_buffer_to (size)
- int size;
-{
- do
- maxtoken = maxtoken * 2 + 10;
- while (maxtoken < size);
- token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
-}
-
-static char *
-extend_token_buffer (p)
- const char *p;
-{
- int offset = p - token_buffer;
- extend_token_buffer_to (offset);
- return token_buffer + offset;
-}
-\f
-
-static int
-read_line_number (num)
- int *num;
-{
- tree value;
- enum cpp_ttype token = c_lex (&value);
-
- if (token == CPP_NUMBER && TREE_CODE (value) == INTEGER_CST)
- {
- *num = TREE_INT_CST_LOW (value);
- return 1;
- }
- else
- {
- if (token != CPP_EOF)
- error ("invalid #-line");
- return 0;
- }
-}
-
-/* At the beginning of a line, increment the line number
- and process any #-directive on this line.
- If the line is a #-directive, read the entire line and return a newline.
- Otherwise, return the line's first non-whitespace character. */
-
-int
-check_newline ()
+cb_ident (pfile, str)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ const cpp_string *str ATTRIBUTE_UNUSED;
{
- register int c;
-
- /* Loop till we get a nonblank, non-directive line. */
- for (;;)
+#ifdef ASM_OUTPUT_IDENT
+ if (! flag_no_ident)
{
- /* Read first nonwhite char on the line. */
- do
- c = getch ();
- while (c == ' ' || c == '\t');
-
- lex_lineno++;
- if (c == '#')
- {
- process_directive ();
- return '\n';
- }
-
- else if (c != '\n')
- break;
+ /* Convert escapes in the string. */
+ tree value = lex_string ((const char *)str->text, str->len, 0);
+ ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (value));
}
- return c;
+#endif
}
static void
-process_directive ()
+cb_file_change (pfile, fc)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ const cpp_file_change *fc;
{
- enum cpp_ttype token;
- tree value;
- int saw_line;
- enum { act_none, act_push, act_pop } action;
- int action_number, l;
- char *new_file;
-#ifndef NO_IMPLICIT_EXTERN_C
- int entering_c_header = 0;
-#endif
-
- /* Don't read beyond this line. */
- saw_line = 0;
- linemode = 1;
-
- token = c_lex (&value);
-
- if (token == CPP_NAME)
+ if (fc->reason == FC_ENTER)
{
- /* If a letter follows, then if the word here is `line', skip
- it and ignore it; otherwise, ignore the line, with an error
- if the word isn't `pragma'. */
-
- const char *name = IDENTIFIER_POINTER (value);
-
- if (!strcmp (name, "pragma"))
- {
- dispatch_pragma ();
- goto skipline;
- }
- else if (!strcmp (name, "define"))
- {
- debug_define (lex_lineno, GET_DIRECTIVE_LINE ());
- goto skipline;
- }
- else if (!strcmp (name, "undef"))
+ /* Don't stack the main buffer on the input stack;
+ we already did in compile_file. */
+ if (fc->from.filename)
{
- debug_undef (lex_lineno, GET_DIRECTIVE_LINE ());
- goto skipline;
- }
- else if (!strcmp (name, "line"))
- {
- saw_line = 1;
- token = c_lex (&value);
- goto linenum;
- }
- else if (!strcmp (name, "ident"))
- {
- /* #ident. We expect a string constant here.
- The pedantic warning and syntax error are now in cpp. */
-
- token = c_lex (&value);
- if (token != CPP_STRING || TREE_CODE (value) != STRING_CST)
- goto skipline;
-
-#ifdef ASM_OUTPUT_IDENT
- if (! flag_no_ident)
+ lineno = fc->from.lineno;
+ push_srcloc (fc->to.filename, 1);
+ input_file_stack->indent_level = indent_level;
+ debug_start_source_file (fc->to.filename);
+#ifndef NO_IMPLICIT_EXTERN_C
+ if (c_header_level)
+ ++c_header_level;
+ else if (fc->externc)
{
- ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (value));
+ c_header_level = 1;
+ ++pending_lang_change;
}
#endif
-
- /* Skip the rest of this line. */
- goto skipline;
- }
-
- error ("undefined or invalid # directive `%s'", name);
- goto skipline;
- }
-
- /* If the # is the only nonwhite char on the line,
- just ignore it. Check the new newline. */
- if (token == CPP_EOF)
- goto skipline;
-
-linenum:
- /* Here we have either `#line' or `# <nonletter>'.
- In either case, it should be a line number; a digit should follow. */
-
- if (token != CPP_NUMBER || TREE_CODE (value) != INTEGER_CST)
- {
- error ("invalid #-line");
- goto skipline;
- }
-
- /* subtract one, because it is the following line that
- gets the specified number */
-
- l = TREE_INT_CST_LOW (value) - 1;
-
- /* More follows: it must be a string constant (filename).
- It would be neat to use cpplib to quickly process the string, but
- (1) we don't have a handy tokenization of the string, and
- (2) I don't know how well that would work in the presense
- of filenames that contain wide characters. */
-
- if (saw_line)
- {
- /* Don't treat \ as special if we are processing #line 1 "...".
- If you want it to be treated specially, use # 1 "...". */
- ignore_escape_flag = 1;
- }
-
- /* Read the string constant. */
- token = c_lex (&value);
-
- ignore_escape_flag = 0;
-
- if (token == CPP_EOF)
- {
- /* No more: store the line number and check following line. */
- lex_lineno = l;
- goto skipline;
- }
-
- if (token != CPP_STRING || TREE_CODE (value) != STRING_CST)
- {
- error ("invalid #line");
- goto skipline;
- }
-
- new_file = TREE_STRING_POINTER (value);
-
- if (main_input_filename == 0)
- main_input_filename = new_file;
-
- action = act_none;
- action_number = 0;
-
- /* Each change of file name
- reinitializes whether we are now in a system header. */
- in_system_header = 0;
-
- if (!read_line_number (&action_number))
- {
- /* Update the name in the top element of input_file_stack. */
- if (input_file_stack)
- input_file_stack->name = input_filename;
- }
-
- /* `1' after file name means entering new file.
- `2' after file name means just left a file. */
-
- if (action_number == 1)
- {
- action = act_push;
- read_line_number (&action_number);
- }
- else if (action_number == 2)
- {
- action = act_pop;
- read_line_number (&action_number);
- }
- if (action_number == 3)
- {
- /* `3' after file name means this is a system header file. */
- in_system_header = 1;
- read_line_number (&action_number);
- }
-#ifndef NO_IMPLICIT_EXTERN_C
- if (action_number == 4)
- {
- /* `4' after file name means this is a C header file. */
- entering_c_header = 1;
- read_line_number (&action_number);
- }
-#endif
-
- /* Do the actions implied by the preceding numbers. */
- if (action == act_push)
- {
- lineno = lex_lineno;
- push_srcloc (input_filename, 1);
- input_file_stack->indent_level = indent_level;
- debug_start_source_file (input_filename);
-#ifndef NO_IMPLICIT_EXTERN_C
- if (c_header_level)
- ++c_header_level;
- else if (entering_c_header)
- {
- c_header_level = 1;
- ++pending_lang_change;
}
-#endif
+ else
+ main_input_filename = fc->to.filename;
}
- else if (action == act_pop)
+ else if (fc->reason == FC_LEAVE)
{
/* Popping out of a file. */
if (input_file_stack->next)
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level && --c_header_level == 0)
{
- if (entering_c_header)
+ if (fc->externc)
warning ("badly nested C headers from preprocessor");
--pending_lang_change;
}
if (indent_level != input_file_stack->indent_level)
{
warning_with_file_and_line
- (input_filename, lex_lineno,
+ (input_filename, lineno,
"This file contains more '%c's than '%c's.",
indent_level > input_file_stack->indent_level ? '{' : '}',
indent_level > input_file_stack->indent_level ? '}' : '{');
debug_end_source_file (input_file_stack->line);
}
else
- error ("#-lines for entering and leaving files don't match");
+ error ("leaving more files than we entered");
}
- update_header_times (new_file);
-
- input_filename = new_file;
- lex_lineno = l;
+ update_header_times (fc->to.filename);
+ in_system_header = fc->sysp != 0;
+ input_filename = fc->to.filename;
+ lineno = fc->to.lineno; /* Do we need this? */
/* Hook for C++. */
extract_interface_info ();
-
- /* skip the rest of this line. */
- skipline:
- linemode = 0;
-
- while (getch () != '\n');
-}
-#else /* USE_CPPLIB */
-
-/* Not yet handled: #pragma, #define, #undef.
- No need to deal with linemarkers under normal conditions. */
-
-static void
-cb_ident (pfile, str)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
- const cpp_string *str;
-{
-#ifdef ASM_OUTPUT_IDENT
- if (! flag_no_ident)
- {
- /* Convert escapes in the string. */
- tree value = lex_string ((const char *)str->text, str->len, 0);
- ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (value));
- }
-#endif
-}
-
-static void
-cb_enter_file (pfile)
- cpp_reader *pfile;
-{
- cpp_buffer *ip = CPP_BUFFER (pfile);
- /* Bleah, need a better interface to this. */
- const char *flags = cpp_syshdr_flags (pfile, ip);
-
- /* Mustn't stack the main buffer on the input stack. (Ick.) */
- if (ip->prev)
- {
- lex_lineno = lineno = ip->prev->lineno - 1;
- push_srcloc (ggc_alloc_string (ip->nominal_fname, -1), 1);
- input_file_stack->indent_level = indent_level;
- debug_start_source_file (ip->nominal_fname);
- }
- else
- lex_lineno = 1;
-
- update_header_times (ip->nominal_fname);
-
- /* Hook for C++. */
- extract_interface_info ();
-
- in_system_header = (flags[0] != 0);
-#ifndef NO_IMPLICIT_EXTERN_C
- if (c_header_level)
- ++c_header_level;
- else if (in_system_header && flags[1] != 0 && flags[2] != 0)
- {
- c_header_level = 1;
- ++pending_lang_change;
- }
-#endif
-}
-
-static void
-cb_leave_file (pfile)
- cpp_reader *pfile;
-{
- /* Bleah, need a better interface to this. */
- const char *flags = cpp_syshdr_flags (pfile, CPP_BUFFER (pfile));
-
- if (input_file_stack->next)
- {
-#ifndef NO_IMPLICIT_EXTERN_C
- if (c_header_level && --c_header_level == 0)
- {
- if (flags[2] != 0)
- warning ("badly nested C headers from preprocessor");
- --pending_lang_change;
- }
-#endif
-#if 0
- if (indent_level != input_file_stack->indent_level)
- {
- warning_with_file_and_line
- (input_filename, lex_lineno,
- "This file contains more '%c's than '%c's.",
- indent_level > input_file_stack->indent_level ? '{' : '}',
- indent_level > input_file_stack->indent_level ? '}' : '{');
- }
-#endif
- /* We get called for the main buffer, but we mustn't pop it. */
- pop_srcloc ();
- debug_end_source_file (input_file_stack->line);
- }
-
- in_system_header = (flags[0] != 0);
- lex_lineno = CPP_BUFFER (pfile)->lineno;
-
- update_header_times (input_file_stack->name);
- /* Hook for C++. */
- extract_interface_info ();
-}
-
-static void
-cb_rename_file (pfile)
- cpp_reader *pfile;
-{
- cpp_buffer *ip = CPP_BUFFER (pfile);
- /* Bleah, need a better interface to this. */
- const char *flags = cpp_syshdr_flags (pfile, ip);
- input_filename = ggc_alloc_string (ip->nominal_fname, -1);
- lex_lineno = ip->lineno;
- in_system_header = (flags[0] != 0);
-
- update_header_times (ip->nominal_fname);
- /* Hook for C++. */
- extract_interface_info ();
}
static void
if (s.type == CPP_NAME)
name = cpp_token_as_text (pfile, &s);
+ lineno = cpp_get_line (parse_in)->line;
if (name)
warning ("ignoring #pragma %s %s", space, name);
else
warning ("ignoring #pragma %s", space);
}
}
-#endif /* USE_CPPLIB */
+
+/* #define callback for DWARF and DWARF2 debug info. */
+static void
+cb_define (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ debug_define (lineno, (const char *) cpp_macro_definition (pfile, node));
+}
+
+/* #undef callback for DWARF and DWARF2 debug info. */
+static void
+cb_undef (pfile, node)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_hashnode *node;
+{
+ debug_undef (lineno, (const char *) node->name);
+}
/* Parse a '\uNNNN' or '\UNNNNNNNN' sequence.
c_lex (value)
tree *value;
{
-#if USE_CPPLIB
cpp_token tok;
enum cpp_ttype type;
retry:
timevar_push (TV_CPP);
- cpp_get_token (&parse_in, &tok);
+ cpp_get_token (parse_in, &tok);
timevar_pop (TV_CPP);
/* The C++ front end does horrible things with the current line
number. To ensure an accurate line number, we must reset it
every time we return a token. */
- lex_lineno = cpp_get_line (&parse_in)->line;
+ lineno = cpp_get_line (parse_in)->line;
*value = NULL_TREE;
- lineno = lex_lineno;
type = tok.type;
switch (type)
{
}
return type;
-
-#else
- int c;
- char *p;
- int wide_flag = 0;
- int objc_flag = 0;
- int charconst = 0;
-
- *value = NULL_TREE;
-
- retry:
- c = getch ();
-
- /* Effectively do c = skip_white_space (c)
- but do it faster in the usual cases. */
- while (1)
- switch (c)
- {
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- c = getch ();
- break;
-
- case '\r':
- case '\n':
- c = skip_white_space (c);
- default:
- goto found_nonwhite;
- }
- found_nonwhite:
-
- lineno = lex_lineno;
-
- switch (c)
- {
- case EOF:
- return CPP_EOF;
-
- case 'L':
- /* Capital L may start a wide-string or wide-character constant. */
- {
- register int c1 = getch();
- if (c1 == '\'')
- {
- wide_flag = 1;
- goto char_constant;
- }
- if (c1 == '"')
- {
- wide_flag = 1;
- goto string_constant;
- }
- put_back (c1);
- }
- goto letter;
-
- case '@':
- if (!doing_objc_thang)
- goto straychar;
- else
- {
- /* '@' may start a constant string object. */
- register int c1 = getch ();
- if (c1 == '"')
- {
- objc_flag = 1;
- goto string_constant;
- }
- put_back (c1);
- /* Fall through to treat '@' as the start of an identifier. */
- }
-
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- case '_':
- case '$':
- letter:
- p = token_buffer;
- while (ISALNUM (c) || c == '_' || c == '$' || c == '@')
- {
- /* Make sure this char really belongs in an identifier. */
- if (c == '$')
- {
- if (! dollars_in_ident)
- error ("'$' in identifier");
- else if (pedantic)
- pedwarn ("'$' in identifier");
- }
-
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
-
- *p++ = c;
- c = getch();
- }
-
- put_back (c);
-
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
- *p = 0;
-
- *value = get_identifier (token_buffer);
- return CPP_NAME;
-
- case '.':
- {
- /* It's hard to preserve tokenization on '.' because
- it could be a symbol by itself, or it could be the
- start of a floating point number and cpp won't tell us. */
- int c1 = getch ();
- if (c1 == '.')
- {
- int c2 = getch ();
- if (c2 == '.')
- return CPP_ELLIPSIS;
-
- put_back (c2);
- error ("parse error at '..'");
- }
- else if (c1 == '*' && c_language == clk_cplusplus)
- return CPP_DOT_STAR;
-
- put_back (c1);
- if (ISDIGIT (c1))
- goto number;
- }
- return CPP_DOT;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- number:
- p = token_buffer;
- /* Scan the next preprocessing number. All C numeric constants
- are preprocessing numbers, but not all preprocessing numbers
- are valid numeric constants. Preprocessing numbers fit the
- regular expression \.?[0-9]([0-9a-zA-Z_.]|[eEpP][+-])*
- See C99 section 6.4.8. */
- for (;;)
- {
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
-
- *p++ = c;
- c = getch();
-
- if (c == '+' || c == '-')
- {
- int d = p[-1];
- if (d == 'e' || d == 'E' || d == 'p' || d == 'P')
- continue;
- }
- if (ISALNUM (c) || c == '_' || c == '.')
- continue;
- break;
- }
- put_back (c);
-
- *value = lex_number (token_buffer, p - token_buffer);
- return CPP_NUMBER;
-
- case '\'':
- char_constant:
- charconst = 1;
-
- case '"':
- string_constant:
- {
- int delimiter = charconst ? '\'' : '"';
-#ifdef MULTIBYTE_CHARS
- int longest_char = local_mb_cur_max ();
- (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
-#endif
- c = getch ();
- p = token_buffer + 1;
-
- while (c != delimiter && c != EOF)
- {
- if (p + 2 > token_buffer + maxtoken)
- p = extend_token_buffer (p);
-
- /* ignore_escape_flag is set for reading the filename in #line. */
- if (!ignore_escape_flag && c == '\\')
- {
- *p++ = c;
- *p++ = getch (); /* escaped character */
- c = getch ();
- continue;
- }
- else
- {
-#ifdef MULTIBYTE_CHARS
- int i;
- int char_len = -1;
- for (i = 0; i < longest_char; ++i)
- {
- if (p + i >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
- p[i] = c;
-
- char_len = local_mblen (p, i + 1);
- if (char_len != -1)
- break;
- c = getch ();
- }
- if (char_len == -1)
- {
- /* Replace all except the first byte. */
- put_back (c);
- for (--i; i > 0; --i)
- put_back (p[i]);
- char_len = 1;
- }
- /* mbtowc sometimes needs an extra char before accepting */
- else if (char_len <= i)
- put_back (c);
-
- p += char_len;
-#else
- *p++ = c;
-#endif
- c = getch ();
- }
- }
- }
-
- if (charconst)
- {
- *value = lex_charconst (token_buffer + 1, p - (token_buffer + 1),
- wide_flag);
- return wide_flag ? CPP_WCHAR : CPP_CHAR;
- }
- else
- {
- *value = lex_string (token_buffer + 1, p - (token_buffer + 1),
- wide_flag);
- return wide_flag ? CPP_WSTRING : objc_flag ? CPP_OSTRING : CPP_STRING;
- }
-
- case '+':
- case '-':
- case '&':
- case '|':
- case ':':
- case '<':
- case '>':
- case '*':
- case '/':
- case '%':
- case '^':
- case '!':
- case '=':
- {
- int c1;
- enum cpp_ttype type = CPP_EOF;
-
- switch (c)
- {
- case '+': type = CPP_PLUS; break;
- case '-': type = CPP_MINUS; break;
- case '&': type = CPP_AND; break;
- case '|': type = CPP_OR; break;
- case ':': type = CPP_COLON; break;
- case '<': type = CPP_LESS; break;
- case '>': type = CPP_GREATER; break;
- case '*': type = CPP_MULT; break;
- case '/': type = CPP_DIV; break;
- case '%': type = CPP_MOD; break;
- case '^': type = CPP_XOR; break;
- case '!': type = CPP_NOT; break;
- case '=': type = CPP_EQ; break;
- }
-
- c1 = getch ();
-
- if (c1 == '=' && type < CPP_LAST_EQ)
- return type + (CPP_EQ_EQ - CPP_EQ);
- else if (c == c1)
- switch (c)
- {
- case '+': return CPP_PLUS_PLUS;
- case '-': return CPP_MINUS_MINUS;
- case '&': return CPP_AND_AND;
- case '|': return CPP_OR_OR;
- case ':':
- if (c_language == clk_cplusplus)
- return CPP_SCOPE;
- break;
-
- case '<': type = CPP_LSHIFT; goto do_triad;
- case '>': type = CPP_RSHIFT; goto do_triad;
- }
- else
- switch (c)
- {
- case '-':
- if (c1 == '>')
- {
- if (c_language == clk_cplusplus)
- {
- c1 = getch ();
- if (c1 == '*')
- return CPP_DEREF_STAR;
- put_back (c1);
- }
- return CPP_DEREF;
- }
- break;
-
- case '>':
- if (c1 == '?' && c_language == clk_cplusplus)
- { type = CPP_MAX; goto do_triad; }
- break;
-
- case '<':
- if (c1 == ':' && flag_digraphs)
- return CPP_OPEN_SQUARE;
- if (c1 == '%' && flag_digraphs)
- { indent_level++; return CPP_OPEN_BRACE; }
- if (c1 == '?' && c_language == clk_cplusplus)
- { type = CPP_MIN; goto do_triad; }
- break;
-
- case ':':
- if (c1 == '>' && flag_digraphs)
- return CPP_CLOSE_SQUARE;
- break;
- case '%':
- if (c1 == '>' && flag_digraphs)
- { indent_level--; return CPP_CLOSE_BRACE; }
- break;
- }
-
- put_back (c1);
- return type;
-
- do_triad:
- c1 = getch ();
- if (c1 == '=')
- type += (CPP_EQ_EQ - CPP_EQ);
- else
- put_back (c1);
- return type;
- }
-
- case '~': return CPP_COMPL;
- case '?': return CPP_QUERY;
- case ',': return CPP_COMMA;
- case '(': return CPP_OPEN_PAREN;
- case ')': return CPP_CLOSE_PAREN;
- case '[': return CPP_OPEN_SQUARE;
- case ']': return CPP_CLOSE_SQUARE;
- case '{': indent_level++; return CPP_OPEN_BRACE;
- case '}': indent_level--; return CPP_CLOSE_BRACE;
- case ';': return CPP_SEMICOLON;
-
- straychar:
- default:
- if (ISGRAPH (c))
- error ("stray '%c' in program", c);
- else
- error ("stray '\\%#o' in program", c);
- goto retry;
- }
- /* NOTREACHED */
-#endif
}
-
#define ERROR(msgid) do { error(msgid); goto syntax_error; } while(0)
static tree
case 'f': case 'F':
if (fflag)
ERROR ("more than one 'f' suffix on floating constant");
- else if (warn_traditional && !in_system_header)
+ else if (warn_traditional && !in_system_header
+ && ! cpp_sys_objmacro_p (parse_in))
warning ("traditional C rejects the 'f' suffix");
fflag = 1;
case 'l': case 'L':
if (lflag)
ERROR ("more than one 'l' suffix on floating constant");
- else if (warn_traditional && !in_system_header)
+ else if (warn_traditional && !in_system_header
+ && ! cpp_sys_objmacro_p (parse_in))
warning ("traditional C rejects the 'l' suffix");
lflag = 1;
case 'u': case 'U':
if (spec_unsigned)
error ("two 'u' suffixes on integer constant");
- else if (warn_traditional && !in_system_header)
+ else if (warn_traditional && !in_system_header
+ && ! cpp_sys_objmacro_p (parse_in))
warning ("traditional C rejects the 'u' suffix");
spec_unsigned = 1;
}
else
{
- p += char_len;
+ str += char_len;
c = wc;
}
#else
return value;
}
-
-/* Mark for GC a node in a splay tree whose keys are strings. */
-
-static int
-mark_splay_tree_node (n, data)
- splay_tree_node n;
- void *data ATTRIBUTE_UNUSED;
-{
- ggc_mark_string ((char *) n->key);
- return 0;
-}
-
-/* Mark for GC a splay tree whose keys are strings. */
-
-static void
-mark_splay_tree (p)
- void *p;
-{
- splay_tree st = *(splay_tree *) p;
-
- splay_tree_foreach (st, mark_splay_tree_node, NULL);
-}