X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=support%2Fcpp2%2Fcpplib.c;h=286c22f634fe62395f8c15c22a627bbf79909ba3;hb=9cedee0a6119679ce3070ce50399bc4089aa4beb;hp=2b3512b8cc87b6abf84afc7d96fe53aff6452c93;hpb=10ad364006038b2154eba9402fc70aabd90ce708;p=fw%2Fsdcc diff --git a/support/cpp2/cpplib.c b/support/cpp2/cpplib.c index 2b3512b8..286c22f6 100644 --- a/support/cpp2/cpplib.c +++ b/support/cpp2/cpplib.c @@ -1,6 +1,6 @@ /* CPP Library. (Directive handling.) Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 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 @@ -24,7 +24,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cpplib.h" #include "cpphash.h" -#include "intl.h" #include "obstack.h" /* Chained list of answers to an assertion. */ @@ -37,14 +36,27 @@ struct answer /* Stack of conditionals currently in progress (including both successful and failing conditionals). */ - struct if_stack { struct if_stack *next; - cpp_lexer_pos pos; /* line and column where condition started */ + unsigned int line; /* Line where condition started. */ const cpp_hashnode *mi_cmacro;/* macro name for #ifndef around entire file */ - unsigned char was_skipping; /* Value of pfile->skipping before this if. */ - int type; /* type of last directive seen in this group */ + bool skip_elses; /* Can future #else / #elif be skipped? */ + bool was_skipping; /* If were skipping on entry. */ + int type; /* Most recent conditional, for diagnostics. */ +}; + +/* Contains a registered pragma or pragma namespace. */ +typedef void (*pragma_cb) PARAMS ((cpp_reader *)); +struct pragma_entry +{ + struct pragma_entry *next; + const cpp_hashnode *pragma; /* Name and length. */ + int is_nspace; + union { + pragma_cb handler; + struct pragma_entry *space; + } u; }; /* Values for the origin field of struct directive. KANDR directives @@ -82,28 +94,38 @@ static void skip_rest_of_line PARAMS ((cpp_reader *)); static void check_eol PARAMS ((cpp_reader *)); static void start_directive PARAMS ((cpp_reader *)); static void end_directive PARAMS ((cpp_reader *, int)); +static void directive_diagnostics + PARAMS ((cpp_reader *, const directive *, int)); static void run_directive PARAMS ((cpp_reader *, int, - enum cpp_buffer_type, const char *, size_t)); -static int glue_header_name PARAMS ((cpp_reader *, cpp_token *)); -static int parse_include PARAMS ((cpp_reader *, cpp_token *)); +static const cpp_token *glue_header_name PARAMS ((cpp_reader *)); +static const cpp_token *parse_include PARAMS ((cpp_reader *)); static void push_conditional PARAMS ((cpp_reader *, int, int, const cpp_hashnode *)); static unsigned int read_flag PARAMS ((cpp_reader *, unsigned int)); +static U_CHAR *dequote_string PARAMS ((cpp_reader *, const U_CHAR *, + unsigned int)); static int strtoul_for_line PARAMS ((const U_CHAR *, unsigned int, unsigned long *)); static void do_diagnostic PARAMS ((cpp_reader *, enum error_type, int)); -static cpp_hashnode *lex_macro_node PARAMS ((cpp_reader *)); +static cpp_hashnode *lex_macro_node PARAMS ((cpp_reader *)); static void do_include_common PARAMS ((cpp_reader *, enum include_type)); +static struct pragma_entry *lookup_pragma_entry + PARAMS ((struct pragma_entry *, const cpp_hashnode *pragma)); +static struct pragma_entry *insert_pragma_entry + PARAMS ((cpp_reader *, struct pragma_entry **, const cpp_hashnode *, + pragma_cb)); static void do_pragma_once PARAMS ((cpp_reader *)); static void do_pragma_poison PARAMS ((cpp_reader *)); static void do_pragma_sdcc_hash PARAMS ((cpp_reader *)); -static void do_pragma_preproc_asm PARAMS ((cpp_reader *)); -static void do_pragma_system_header PARAMS ((cpp_reader *)); -static void do_pragma_dependency PARAMS ((cpp_reader *)); -static int get__Pragma_string PARAMS ((cpp_reader *, cpp_token *)); -static unsigned char *destringize PARAMS ((const cpp_string *, - unsigned int *)); +static void do_pragma_preproc_asm PARAMS ((cpp_reader *)); +static void do_pragma_system_header PARAMS ((cpp_reader *)); +static void do_pragma_dependency PARAMS ((cpp_reader *)); +static void do_linemarker PARAMS ((cpp_reader *)); +static const cpp_token *get_token_no_padding PARAMS ((cpp_reader *)); +static const cpp_token *get__Pragma_string PARAMS ((cpp_reader *)); +static unsigned char *destringize PARAMS ((const cpp_string *, unsigned int *)); +static void destringize_and_run PARAMS ((cpp_reader *, const cpp_string *)); static int parse_answer PARAMS ((cpp_reader *, struct answer **, int)); static cpp_hashnode *parse_assertion PARAMS ((cpp_reader *, struct answer **, int)); @@ -111,6 +133,8 @@ static struct answer ** find_answer PARAMS ((cpp_hashnode *, const struct answer *)); static void handle_assertion PARAMS ((cpp_reader *, const char *, int)); +extern cpp_output_string PARAMS ((const char *s)); + /* This is the table of directive handlers. It 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 @@ -129,7 +153,7 @@ D(if, T_IF, KANDR, COND | IF_COND) /* 18162 */ \ D(else, T_ELSE, KANDR, COND) /* 9863 */ \ D(ifndef, T_IFNDEF, KANDR, COND | IF_COND) /* 9675 */ \ D(undef, T_UNDEF, KANDR, IN_I) /* 4837 */ \ -D(line, T_LINE, KANDR, IN_I) /* 2465 */ \ +D(line, T_LINE, KANDR, 0) /* 2465 */ \ D(elif, T_ELIF, STDC89, COND) /* 610 */ \ D(error, T_ERROR, STDC89, 0) /* 475 */ \ D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \ @@ -151,11 +175,7 @@ SCCS_ENTRY /* 0 SVR4? */ /* Use the table to generate a series of prototypes, an enum for the directive names, and an array of directive handlers. */ -/* The directive-processing functions are declared to return int - instead of void, because some old compilers have trouble with - pointers to functions returning void. */ - -/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ +/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ #define D(name, t, o, f) static void CONCAT2(do_,name) PARAMS ((cpp_reader *)); DIRECTIVE_TABLE #undef D @@ -168,7 +188,7 @@ enum }; #undef D -/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ +/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ #define D(name, t, origin, flags) \ { CONCAT2(do_,name), (const U_CHAR *) STRINGX(name), \ sizeof STRINGX(name) - 1, origin, flags }, @@ -179,26 +199,29 @@ DIRECTIVE_TABLE #undef D #undef DIRECTIVE_TABLE +/* Wrapper struct directive for linemarkers. + The origin is more or less true - the original K+R cpp + did use this notation in its preprocessed output. */ +static const directive linemarker_dir = +{ + do_linemarker, U"#", 1, KANDR, IN_I +}; + +#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF) + /* Skip any remaining tokens in a directive. */ static void skip_rest_of_line (pfile) cpp_reader *pfile; { - cpp_token token; - - /* Discard all input lookaheads. */ - while (pfile->la_read) - _cpp_release_lookahead (pfile); - /* Discard all stacked contexts. */ - while (pfile->context != &pfile->base_context) + while (pfile->context->prev) _cpp_pop_context (pfile); /* Sweep up all tokens remaining on the line. */ - pfile->state.prevent_expansion++; - while (!pfile->state.next_bol) - _cpp_lex_token (pfile, &token); - pfile->state.prevent_expansion--; + if (! SEEN_EOL ()) + while (_cpp_lex_token (pfile)->type != CPP_EOF) + ; } /* Ensure there are no stray tokens at the end of a directive. */ @@ -206,15 +229,9 @@ static void check_eol (pfile) cpp_reader *pfile; { - if (!pfile->state.next_bol) - { - cpp_token token; - - _cpp_lex_token (pfile, &token); - if (token.type != CPP_EOF) - cpp_pedwarn (pfile, "extra tokens at end of #%s directive", - pfile->directive->name); - } + if (! SEEN_EOL () && _cpp_lex_token (pfile)->type != CPP_EOF) + cpp_pedwarn (pfile, "extra tokens at end of #%s directive", + pfile->directive->name); } /* Called when entering a directive, _Pragma or command-line directive. */ @@ -222,22 +239,12 @@ static void start_directive (pfile) cpp_reader *pfile; { - cpp_buffer *buffer = pfile->buffer; - /* Setup in-directive state. */ pfile->state.in_directive = 1; pfile->state.save_comments = 0; /* Some handlers need the position of the # for diagnostics. */ - pfile->directive_pos = pfile->lexer_pos; - - /* Don't save directive tokens for external clients. */ - pfile->la_saved = pfile->la_write; - pfile->la_write = 0; - - /* Turn off skipping. */ - buffer->was_skipping = pfile->skipping; - pfile->skipping = 0; + pfile->directive_line = pfile->line; } /* Called when leaving a directive, _Pragma or command-line directive. */ @@ -246,155 +253,149 @@ end_directive (pfile, skip_line) cpp_reader *pfile; int skip_line; { - cpp_buffer *buffer = pfile->buffer; - - /* Restore pfile->skipping before skip_rest_of_line, so that e.g. - __VA_ARGS__ in the rest of the directive doesn't warn. */ - pfile->skipping = buffer->was_skipping; - /* We don't skip for an assembler #. */ if (skip_line) - skip_rest_of_line (pfile); + { + skip_rest_of_line (pfile); + if (!pfile->keep_tokens) + { + pfile->cur_run = &pfile->base_run; + pfile->cur_token = pfile->base_run.base; + } + } /* Restore state. */ - pfile->la_write = pfile->la_saved; pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); pfile->state.in_directive = 0; pfile->state.angled_headers = 0; - pfile->state.line_extension = 0; pfile->directive = 0; } -/* Check if a token's name matches that of a known directive. Put in - this file to save exporting dtable and other unneeded information. */ +/* Output diagnostics for a directive DIR. INDENTED is non-zero if + the '#' was indented. */ +static void +directive_diagnostics (pfile, dir, indented) + cpp_reader *pfile; + const directive *dir; + int indented; +{ + /* Issue -pedantic warnings for extensions. */ + if (CPP_PEDANTIC (pfile) + && ! pfile->state.skipping + && dir->origin == EXTENSION) + cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name); + + /* Traditionally, a directive is ignored unless its # is in + column 1. Therefore in code intended to work with K+R + compilers, directives added by C89 must have their # + indented, and directives present in traditional C must not. + This is true even of directives in skipped conditional + blocks. #elif cannot be used at all. */ + if (CPP_WTRADITIONAL (pfile)) + { + if (dir == &dtable[T_ELIF]) + cpp_warning (pfile, "suggest not using #elif in traditional C"); + else if (indented && dir->origin == KANDR) + cpp_warning (pfile, + "traditional C ignores #%s with the # indented", + dir->name); + else if (!indented && dir->origin != KANDR) + cpp_warning (pfile, + "suggest hiding #%s from traditional C with an indented #", + dir->name); + } +} + +/* Check if we have a known directive. INDENTED is non-zero if the + '#' of the directive was indented. This function is in this file + to save unnecessarily exporting dtable etc. to cpplex.c. Returns + non-zero if the line of tokens has been handled, zero if we should + continue processing the line. */ int _cpp_handle_directive (pfile, indented) cpp_reader *pfile; int indented; { - cpp_buffer *buffer = pfile->buffer; const directive *dir = 0; - cpp_token dname; + const cpp_token *dname; int skip = 1; start_directive (pfile); + dname = _cpp_lex_token (pfile); - /* Lex the directive name directly. */ - _cpp_lex_token (pfile, &dname); - - if (dname.type == CPP_NAME) + if (dname->type == CPP_NAME) { - unsigned int index = dname.val.node->directive_index; - if (index) - dir = &dtable[index - 1]; + if (dname->val.node->directive_index) + dir = &dtable[dname->val.node->directive_index - 1]; } - else if (dname.type == CPP_NUMBER) + /* We do not recognise the # followed by a number extension in + assembler code. */ + else if (dname->type == CPP_NUMBER && CPP_OPTION (pfile, lang) != CLK_ASM) { - /* # followed by a number is equivalent to #line. Do not - recognize this form in assembly language source files or - skipped conditional groups. Complain about this form if - we're being pedantic, but not if this is regurgitated input - (preprocessed or fed back in by the C++ frontend). */ - if (! buffer->was_skipping && CPP_OPTION (pfile, lang) != CLK_ASM) - { - dir = &dtable[T_LINE]; - pfile->state.line_extension = 1; - _cpp_push_token (pfile, &dname, &pfile->directive_pos); - if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, preprocessed)) - cpp_pedwarn (pfile, "# followed by integer"); - } + dir = &linemarker_dir; + if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, preprocessed) + && ! pfile->state.skipping) + cpp_pedwarn (pfile, "style of line directive is a GCC extension"); } - pfile->directive = dir; if (dir) { - /* Make sure we lex headers correctly, whether skipping or not. */ - pfile->state.angled_headers = dir->flags & INCL; - - /* If we are rescanning preprocessed input, only directives tagged - with IN_I are honored, and the warnings below are suppressed. */ - if (CPP_OPTION (pfile, preprocessed)) + /* If we have a directive that is not an opening conditional, + invalidate any control macro. */ + if (! (dir->flags & IF_COND)) + pfile->mi_valid = false; + + /* Kluge alert. In order to be sure that code like this + + #define HASH # + HASH define foo bar + + does not cause '#define foo bar' to get executed when + compiled with -save-temps, we recognize directives in + -fpreprocessed mode only if the # is in column 1. cppmacro.c + puts a space in front of any '#' at the start of a macro. */ + if (CPP_OPTION (pfile, preprocessed) + && (indented || !(dir->flags & IN_I))) { - /* Kluge alert. In order to be sure that code like this - #define HASH # - HASH define foo bar - does not cause '#define foo bar' to get executed when - compiled with -save-temps, we recognize directives in - -fpreprocessed mode only if the # is in column 1 and the - directive name starts in column 2. This output can only - be generated by the directive callbacks in cppmain.c (see - also the special case in scan_buffer). */ - if (dir->flags & IN_I && !indented && !(dname.flags & PREV_WHITE)) - (*dir->handler) (pfile); - /* That check misses '# 123' linemarkers. Let them through too. */ - else if (dname.type == CPP_NUMBER) - (*dir->handler) (pfile); - else - { - /* We don't want to process this directive. Put back the - tokens so caller will see them (and issue an error, - probably). */ - _cpp_push_token (pfile, &dname, &pfile->directive_pos); - skip = 0; - } + skip = 0; + dir = 0; } else { - /* Traditionally, a directive is ignored unless its # is in - column 1. Therefore in code intended to work with K+R - compilers, directives added by C89 must have their # - indented, and directives present in traditional C must - not. This is true even of directives in skipped - conditional blocks. */ - if (CPP_WTRADITIONAL (pfile)) - { - if (dir == &dtable[T_ELIF]) - cpp_warning (pfile, - "suggest not using #elif in traditional C"); - else if (indented && dir->origin == KANDR) - cpp_warning (pfile, - "traditional C ignores #%s with the # indented", - dir->name); - else if (!indented && dir->origin != KANDR) - cpp_warning (pfile, - "suggest hiding #%s from traditional C with an indented #", - dir->name); - } - - /* If we are skipping a failed conditional group, all - non-conditional directives are ignored. */ - if (! buffer->was_skipping || (dir->flags & COND)) - { - /* Issue -pedantic warnings for extensions. */ - if (CPP_PEDANTIC (pfile) && dir->origin == EXTENSION) - cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name); - - /* If we have a directive that is not an opening - conditional, invalidate any control macro. */ - if (! (dir->flags & IF_COND)) - pfile->mi_state = MI_FAILED; - - (*dir->handler) (pfile); - } + /* In failed conditional groups, all non-conditional + directives are ignored. Before doing that, whether + skipping or not, we should lex angle-bracketed headers + correctly, and maybe output some diagnostics. */ + pfile->state.angled_headers = dir->flags & INCL; + if (! CPP_OPTION (pfile, preprocessed)) + directive_diagnostics (pfile, dir, indented); + if (pfile->state.skipping && !(dir->flags & COND)) + dir = 0; } } - else if (dname.type != CPP_EOF && ! buffer->was_skipping) + else if (dname->type == CPP_EOF) + ; /* CPP_EOF is the "null directive". */ + else { /* An unknown directive. Don't complain about it in assembly source: we don't know where the comments are, and # may introduce assembler pseudo-ops. Don't complain about invalid directives in skipped conditional groups (6.10 p4). */ if (CPP_OPTION (pfile, lang) == CLK_ASM) - { - /* Output the # and lookahead token for the assembler. */ - _cpp_push_token (pfile, &dname, &pfile->directive_pos); - skip = 0; - } - else + skip = 0; + else if (!pfile->state.skipping) cpp_error (pfile, "invalid preprocessing directive #%s", - cpp_token_as_text (pfile, &dname)); + cpp_token_as_text (pfile, dname)); } + if (dir) + { + pfile->directive = dir; + (*pfile->directive->handler) (pfile); + } + else if (skip == 0) + _cpp_backup_tokens (pfile, 1); + end_directive (pfile, skip); return skip; } @@ -402,35 +403,26 @@ _cpp_handle_directive (pfile, indented) /* Directive handler wrapper used by the command line option processor. */ static void -run_directive (pfile, dir_no, type, buf, count) +run_directive (pfile, dir_no, buf, count) cpp_reader *pfile; int dir_no; - enum cpp_buffer_type type; const char *buf; size_t count; { - unsigned int output_line = pfile->lexer_pos.output_line; - cpp_buffer *buffer; - - buffer = cpp_push_buffer (pfile, (const U_CHAR *) buf, count, type, 0); - + cpp_push_buffer (pfile, (const U_CHAR *) buf, count, + /* from_stage3 */ true, 1); + /* Disgusting hack. */ if (dir_no == T_PRAGMA) - { - /* A kludge to avoid line markers for _Pragma. */ - pfile->lexer_pos.output_line = output_line; - /* Avoid interpretation of directives in a _Pragma string. */ - pfile->state.next_bol = 0; - } - + pfile->buffer->inc = pfile->buffer->prev->inc; start_directive (pfile); - pfile->state.prevent_expansion++; + /* We don't want a leading # to be interpreted as a directive. */ + pfile->buffer->saved_flags = 0; pfile->directive = &dtable[dir_no]; (void) (*pfile->directive->handler) (pfile); - pfile->state.prevent_expansion--; - check_eol (pfile); end_directive (pfile, 1); - - cpp_pop_buffer (pfile); + if (dir_no == T_PRAGMA) + pfile->buffer->inc = NULL; + _cpp_pop_buffer (pfile); } /* Checks for validity the macro name in #define, #undef, #ifdef and @@ -439,42 +431,43 @@ static cpp_hashnode * lex_macro_node (pfile) cpp_reader *pfile; { - cpp_token token; - - /* Lex the macro name directly. */ - _cpp_lex_token (pfile, &token); + cpp_hashnode *node; + const cpp_token *token = _cpp_lex_token (pfile); /* The token immediately after #define must be an identifier. That - identifier is not allowed to be "defined". See predefined macro - names (6.10.8.4). In C++, it is not allowed to be any of the - macro names (which are keywords in C++) either. */ + identifier may not be "defined", per C99 6.10.8p4. + In C++, it may not be any of the "named operators" either, + per C++98 [lex.digraph], [lex.key]. + Finally, the identifier may not have been poisoned. (In that case + the lexer has issued the error message for us.) */ - if (token.type != CPP_NAME) + if (token->type != CPP_NAME) { - if (token.type == CPP_EOF) + if (token->type == CPP_EOF) cpp_error (pfile, "no macro name given in #%s directive", pfile->directive->name); - else if (token.flags & NAMED_OP) + else if (token->flags & NAMED_OP) cpp_error (pfile, - "\"%s\" cannot be used as a macro name as it is an operator in C++", - NODE_NAME (token.val.node)); + "\"%s\" cannot be used as a macro name as it is an operator in C++", + NODE_NAME (token->val.node)); else cpp_error (pfile, "macro names must be identifiers"); + + return 0; } - else + + node = token->val.node; + if (node->flags & NODE_POISONED) + return 0; + + if (node == pfile->spec_nodes.n_defined) { - cpp_hashnode *node = token.val.node; - - /* In Objective C, some keywords begin with '@', but general - identifiers do not, and you're not allowed to #define them. */ - if (node == pfile->spec_nodes.n_defined || NODE_NAME (node)[0] == '@') - cpp_error (pfile, "\"%s\" cannot be used as a macro name", - NODE_NAME (node)); - else if (!(node->flags & NODE_POISONED)) - return node; + cpp_error (pfile, "\"%s\" cannot be used as a macro name", + NODE_NAME (node)); + return 0; } - return 0; + return node; } /* Process a #define directive. Most work is done in cppmacro.c. */ @@ -488,23 +481,23 @@ do_define (pfile) { if (_cpp_create_definition (pfile, node)) if (pfile->cb.define) - (*pfile->cb.define) (pfile, node); + (*pfile->cb.define) (pfile, pfile->directive_line, node); } } -/* Handle #undef. Marks the identifier NT_VOID in the hash table. */ +/* Handle #undef. Mark the identifier NT_VOID in the hash table. */ static void do_undef (pfile) cpp_reader *pfile; { - cpp_hashnode *node = lex_macro_node (pfile); + cpp_hashnode *node = lex_macro_node (pfile); /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier is not currently defined as a macro name. */ if (node && node->type == NT_MACRO) { if (pfile->cb.undef) - (*pfile->cb.undef) (pfile, node); + (*pfile->cb.undef) (pfile, pfile->directive_line, node); if (node->flags & NODE_WARN) cpp_warning (pfile, "undefining \"%s\"", NODE_NAME (node)); @@ -516,102 +509,94 @@ do_undef (pfile) /* Helper routine used by parse_include. Reinterpret the current line as an h-char-sequence (< ... >); we are looking at the first token - after the <. Returns zero on success. */ -static int -glue_header_name (pfile, header) + after the <. Returns the header as a token, or NULL on failure. */ +static const cpp_token * +glue_header_name (pfile) cpp_reader *pfile; - cpp_token *header; { - cpp_token token; - unsigned char *buffer, *token_mem; + cpp_token *header = NULL; + const cpp_token *token; + unsigned char *buffer; size_t len, total_len = 0, capacity = 1024; /* To avoid lexed tokens overwriting our glued name, we can only allocate from the string pool once we've lexed everything. */ - buffer = (unsigned char *) xmalloc (capacity); for (;;) { - cpp_get_token (pfile, &token); + token = cpp_get_token (pfile); - if (token.type == CPP_GREATER || token.type == CPP_EOF) + if (token->type == CPP_GREATER || token->type == CPP_EOF) break; - len = cpp_token_len (&token); + len = cpp_token_len (token); if (total_len + len > capacity) { capacity = (capacity + len) * 2; buffer = (unsigned char *) xrealloc (buffer, capacity); } - if (token.flags & PREV_WHITE) + if (token->flags & PREV_WHITE) buffer[total_len++] = ' '; - total_len = cpp_spell_token (pfile, &token, &buffer[total_len]) - buffer; + total_len = cpp_spell_token (pfile, token, &buffer[total_len]) - buffer; } - if (token.type == CPP_EOF) + if (token->type == CPP_EOF) cpp_error (pfile, "missing terminating > character"); else { - token_mem = _cpp_pool_alloc (&pfile->ident_pool, total_len + 1); + unsigned char *token_mem = _cpp_unaligned_alloc (pfile, total_len + 1); memcpy (token_mem, buffer, total_len); token_mem[total_len] = '\0'; + header = _cpp_temp_token (pfile); header->type = CPP_HEADER_NAME; - header->flags &= ~PREV_WHITE; + header->flags = 0; header->val.str.len = total_len; header->val.str.text = token_mem; } free ((PTR) buffer); - return token.type == CPP_EOF; + return header; } -/* Parse the header name of #include, #include_next, #import and - #pragma dependency. Returns zero on success. */ -static int -parse_include (pfile, header) +/* Returns the header string of #include, #include_next, #import and + #pragma dependency. Returns NULL on error. */ +static const cpp_token * +parse_include (pfile) cpp_reader *pfile; - cpp_token *header; { - int is_pragma = pfile->directive == &dtable[T_PRAGMA]; const unsigned char *dir; + const cpp_token *header; - if (is_pragma) + if (pfile->directive == &dtable[T_PRAGMA]) dir = U"pragma dependency"; else dir = pfile->directive->name; /* Allow macro expansion. */ - cpp_get_token (pfile, header); + header = cpp_get_token (pfile); if (header->type != CPP_STRING && header->type != CPP_HEADER_NAME) { if (header->type != CPP_LESS) { cpp_error (pfile, "#%s expects \"FILENAME\" or ", dir); - return 1; + return NULL; } - if (glue_header_name (pfile, header)) - return 1; + + header = glue_header_name (pfile); + if (header == NULL) + return header; } if (header->val.str.len == 0) { cpp_error (pfile, "empty file name in #%s", dir); - return 1; - } - - if (!is_pragma) - { - check_eol (pfile); - /* Get out of macro context, if we are. */ - skip_rest_of_line (pfile); - if (pfile->cb.include) - (*pfile->cb.include) (pfile, dir, header); + return NULL; } - return 0; + return header; } /* Handle #include, #include_next and #import. */ @@ -620,26 +605,38 @@ do_include_common (pfile, type) cpp_reader *pfile; enum include_type type; { - cpp_token header; + const cpp_token *header; - if (!parse_include (pfile, &header)) + /* For #include_next, if this is the primary source file, warn and + use the normal search logic. */ + if (type == IT_INCLUDE_NEXT && ! pfile->buffer->prev) + { + cpp_warning (pfile, "#include_next in primary source file"); + type = IT_INCLUDE; + } + else if (type == IT_IMPORT && CPP_OPTION (pfile, warn_import)) + { + CPP_OPTION (pfile, warn_import) = 0; + cpp_warning (pfile, + "#import is obsolete, use an #ifndef wrapper in the header file"); + } + + header = parse_include (pfile); + if (header) { /* Prevent #include recursion. */ - if (pfile->buffer_stack_depth >= CPP_STACK_MAX) + if (pfile->line_maps.depth >= CPP_STACK_MAX) cpp_fatal (pfile, "#include nested too deeply"); - else if (pfile->context->prev) - cpp_ice (pfile, "attempt to push file buffer with contexts stacked"); else { - /* For #include_next, if this is the primary source file, - warn and use the normal search logic. */ - if (type == IT_INCLUDE_NEXT && ! pfile->buffer->prev) - { - cpp_warning (pfile, "#include_next in primary source file"); - type = IT_INCLUDE; - } - - _cpp_execute_include (pfile, &header, type); + check_eol (pfile); + /* Get out of macro context, if we are. */ + skip_rest_of_line (pfile); + if (pfile->cb.include) + (*pfile->cb.include) (pfile, pfile->directive_line, + pfile->directive->name, header); + + _cpp_execute_include (pfile, header, type); } } } @@ -655,13 +652,6 @@ static void do_import (pfile) cpp_reader *pfile; { - if (!pfile->import_warning && CPP_OPTION (pfile, warn_import)) - { - pfile->import_warning = 1; - cpp_warning (pfile, - "#import is obsolete, use an #ifndef wrapper in the header file"); - } - do_include_common (pfile, IT_IMPORT); } @@ -672,21 +662,20 @@ do_include_next (pfile) do_include_common (pfile, IT_INCLUDE_NEXT); } -/* Subroutine of do_line. Read possible flags after file name. LAST - is the last flag seen; 0 if this is the first flag. Return the flag - if it is valid, 0 at the end of the directive. Otherwise complain. */ - +/* Subroutine of do_linemarker. Read possible flags after file name. + LAST is the last flag seen; 0 if this is the first flag. Return the + flag if it is valid, 0 at the end of the directive. Otherwise + complain. */ static unsigned int read_flag (pfile, last) cpp_reader *pfile; unsigned int last; { - cpp_token token; + const cpp_token *token = _cpp_lex_token (pfile); - _cpp_lex_token (pfile, &token); - if (token.type == CPP_NUMBER && token.val.str.len == 1) + if (token->type == CPP_NUMBER && token->val.str.len == 1) { - unsigned int flag = token.val.str.text[0] - '0'; + unsigned int flag = token->val.str.text[0] - '0'; if (flag > last && flag <= 4 && (flag != 4 || last == 3) @@ -694,15 +683,49 @@ read_flag (pfile, last) return flag; } - if (token.type != CPP_EOF) + if (token->type != CPP_EOF) cpp_error (pfile, "invalid flag \"%s\" in line directive", - cpp_token_as_text (pfile, &token)); + cpp_token_as_text (pfile, token)); return 0; } -/* Another subroutine of do_line. Convert a number in STR, of length - LEN, to binary; store it in NUMP, and return 0 if the number was - well-formed, 1 if not. Temporary, hopefully. */ +/* Subroutine of do_line and do_linemarker. Returns a version of STR + which has a NUL terminator and all escape sequences converted to + their equivalents. Temporary, hopefully. */ +static U_CHAR * +dequote_string (pfile, str, len) + cpp_reader *pfile; + const U_CHAR *str; + unsigned int len; +{ + U_CHAR *result = _cpp_unaligned_alloc (pfile, len + 1); + U_CHAR *dst = result; + const U_CHAR *limit = str + len; + unsigned int c; + unsigned HOST_WIDE_INT mask; + + /* We need the mask to match the host's 'unsigned char', not the + target's. */ + if (CHAR_BIT < HOST_BITS_PER_WIDE_INT) + mask = ((unsigned HOST_WIDE_INT) 1 << CHAR_BIT) - 1; + else + mask = ~(unsigned HOST_WIDE_INT)0; + + while (str < limit) + { + c = *str++; + if (c != '\\') + *dst++ = c; + else + *dst++ = cpp_parse_escape (pfile, (const U_CHAR **)&str, limit, mask, 0); + } + *dst++ = '\0'; + return result; +} + +/* Subroutine of do_line and do_linemarker. Convert a number in STR, + of length LEN, to binary; store it in NUMP, and return 0 if the + number was well-formed, 1 if not. Temporary, hopefully. */ static int strtoul_for_line (str, len, nump) const U_CHAR *str; @@ -724,167 +747,150 @@ strtoul_for_line (str, len, nump) } /* Interpret #line command. - Note that the filename string (if any) is treated as if it were an - include filename. That means no escape handling. */ - + Note that the filename string (if any) is a true string constant + (escapes are interpreted), unlike in #line. */ static void do_line (pfile) cpp_reader *pfile; { - cpp_buffer *buffer = pfile->buffer; - const char *filename = buffer->nominal_fname; - unsigned int lineno = buffer->lineno; - enum cpp_fc_reason reason = FC_RENAME; + const cpp_token *token; + const char *new_file = pfile->map->to_file; unsigned long new_lineno; - unsigned int cap; - cpp_token token; /* C99 raised the minimum limit on #line numbers. */ - cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767; + unsigned int cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767; /* #line commands expand macros. */ - cpp_get_token (pfile, &token); - if (token.type != CPP_NUMBER - || strtoul_for_line (token.val.str.text, token.val.str.len, &new_lineno)) + token = cpp_get_token (pfile); + if (token->type != CPP_NUMBER + || strtoul_for_line (token->val.str.text, token->val.str.len, + &new_lineno)) { cpp_error (pfile, "\"%s\" after #line is not a positive integer", - cpp_token_as_text (pfile, &token)); + cpp_token_as_text (pfile, token)); return; - } + } if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap)) cpp_pedwarn (pfile, "line number out of range"); - cpp_get_token (pfile, &token); - if (token.type == CPP_STRING) + token = cpp_get_token (pfile); + if (token->type == CPP_STRING) { - const char *fname = (const char *) token.val.str.text; - - /* Only accept flags for the # 55 form. */ - if (! pfile->state.line_extension) - check_eol (pfile); - else - { - int flag = 0, sysp = 0; - - flag = read_flag (pfile, flag); - if (flag == 1) - { - reason = FC_ENTER; - flag = read_flag (pfile, flag); - } - else if (flag == 2) - { - reason = FC_LEAVE; - flag = read_flag (pfile, flag); - } - if (flag == 3) - { - sysp = 1; - flag = read_flag (pfile, flag); - if (flag == 4) - sysp = 2, read_flag (pfile, flag); - } - - if (reason == FC_ENTER) - { - /* Fake a buffer stack for diagnostics. */ - cpp_push_buffer (pfile, 0, 0, BUF_FAKE, fname); - /* Fake an include for cpp_included. */ - _cpp_fake_include (pfile, fname); - buffer = pfile->buffer; - } - else if (reason == FC_LEAVE) - { - if (buffer->type != BUF_FAKE) - cpp_warning (pfile, "file \"%s\" left but not entered", - buffer->nominal_fname); - else - { - cpp_pop_buffer (pfile); - buffer = pfile->buffer; -#ifdef ENABLE_CHECKING - if (strcmp (buffer->nominal_fname, fname)) - cpp_warning (pfile, "expected to return to file \"%s\"", - buffer->nominal_fname); - if (buffer->lineno + 1 != new_lineno) - cpp_warning (pfile, "expected to return to line number %u", - buffer->lineno + 1); - if (buffer->sysp != sysp) - cpp_warning (pfile, "header flags for \"%s\" have changed", - buffer->nominal_fname); -#endif - } - } - buffer->sysp = sysp; - } - buffer->nominal_fname = fname; + new_file = (const char *) dequote_string (pfile, token->val.str.text, + token->val.str.len); + check_eol (pfile); } - else if (token.type != CPP_EOF) + else if (token->type != CPP_EOF) { cpp_error (pfile, "\"%s\" is not a valid filename", - cpp_token_as_text (pfile, &token)); + cpp_token_as_text (pfile, token)); return; } - /* Our line number is incremented after the directive is processed. */ - buffer->lineno = new_lineno - 1; - _cpp_do_file_change (pfile, reason, filename, lineno); + skip_rest_of_line (pfile); + _cpp_do_file_change (pfile, LC_RENAME, new_file, new_lineno, + pfile->map->sysp); } -/* Arrange the file_change callback. */ -void -_cpp_do_file_change (pfile, reason, from_file, from_lineno) +/* Interpret the # 44 "file" [flags] notation, which has slightly + different syntax and semantics from #line: Flags are allowed, + and we never complain about the line number being too big. */ +static void +do_linemarker (pfile) cpp_reader *pfile; - enum cpp_fc_reason reason; - const char *from_file; - unsigned int from_lineno; { - if (pfile->cb.file_change) - { - cpp_file_change fc; - cpp_buffer *buffer = pfile->buffer; + const cpp_token *token; + const char *new_file = pfile->map->to_file; + unsigned long new_lineno; + unsigned int new_sysp = pfile->map->sysp; + enum lc_reason reason = LC_RENAME; + int flag; - fc.reason = reason; - fc.to.filename = buffer->nominal_fname; - fc.to.lineno = buffer->lineno + 1; - fc.sysp = buffer->sysp; - fc.externc = CPP_OPTION (pfile, cplusplus) && buffer->sysp == 2; + /* Back up so we can get the number again. Putting this in + _cpp_handle_directive risks two calls to _cpp_backup_tokens in + some circumstances, which can segfault. */ + _cpp_backup_tokens (pfile, 1); - /* Caller doesn't need to handle FC_ENTER. */ - if (reason == FC_ENTER) + /* #line commands expand macros. */ + token = cpp_get_token (pfile); + if (token->type != CPP_NUMBER + || strtoul_for_line (token->val.str.text, token->val.str.len, + &new_lineno)) + { + cpp_error (pfile, "\"%s\" after # is not a positive integer", + cpp_token_as_text (pfile, token)); + return; + } + + token = cpp_get_token (pfile); + if (token->type == CPP_STRING) + { + new_file = (const char *) dequote_string (pfile, token->val.str.text, + token->val.str.len); + new_sysp = 0; + flag = read_flag (pfile, 0); + if (flag == 1) { - if (buffer->prev) - { - from_file = buffer->prev->nominal_fname; - from_lineno = buffer->prev->lineno; - } - else - from_file = 0; + reason = LC_ENTER; + /* Fake an include for cpp_included (). */ + _cpp_fake_include (pfile, new_file); + flag = read_flag (pfile, flag); + } + else if (flag == 2) + { + reason = LC_LEAVE; + flag = read_flag (pfile, flag); + } + if (flag == 3) + { + new_sysp = 1; + flag = read_flag (pfile, flag); + if (flag == 4) + new_sysp = 2; } - /* Special case for file "foo.i" with "# 1 foo.c" on first line. */ - else if (reason == FC_RENAME && ! buffer->prev - && pfile->directive_pos.line == 1) - from_file = 0; - - fc.from.filename = from_file; - fc.from.lineno = from_lineno; - pfile->cb.file_change (pfile, &fc); + + check_eol (pfile); + } + else if (token->type != CPP_EOF) + { + cpp_error (pfile, "\"%s\" is not a valid filename", + cpp_token_as_text (pfile, token)); + return; } + + skip_rest_of_line (pfile); + _cpp_do_file_change (pfile, reason, new_file, new_lineno, new_sysp); } -/* - * Report a warning or error detected by the program we are - * processing. Use the directive's tokens in the error message. - */ +/* Arrange the file_change callback. pfile->line has changed to + FILE_LINE of TO_FILE, for reason REASON. SYSP is 1 for a system + header, 2 for a system header that needs to be extern "C" protected, + and zero otherwise. */ +void +_cpp_do_file_change (pfile, reason, to_file, file_line, sysp) + cpp_reader *pfile; + enum lc_reason reason; + const char *to_file; + unsigned int file_line; + unsigned int sysp; +{ + pfile->map = add_line_map (&pfile->line_maps, reason, sysp, + pfile->line, to_file, file_line); + + if (pfile->cb.file_change) + (*pfile->cb.file_change) (pfile, pfile->map); +} +/* Report a warning or error detected by the program we are + processing. Use the directive's tokens in the error message. */ static void do_diagnostic (pfile, code, print_dir) cpp_reader *pfile; enum error_type code; int print_dir; { - if (_cpp_begin_message (pfile, code, NULL, 0)) + if (_cpp_begin_message (pfile, code, 0, 0)) { if (print_dir) fprintf (stderr, "#%s ", pfile->directive->name); @@ -910,183 +916,188 @@ do_warning (pfile) } /* Report program identification. */ - static void do_ident (pfile) cpp_reader *pfile; { - cpp_token str; + const cpp_token *str = cpp_get_token (pfile); - cpp_get_token (pfile, &str); - if (str.type != CPP_STRING) - cpp_error (pfile, "invalid #ident"); + if (str->type != CPP_STRING) + cpp_error (pfile, "invalid #ident directive"); else if (pfile->cb.ident) - (*pfile->cb.ident) (pfile, &str.val.str); + (*pfile->cb.ident) (pfile, pfile->directive_line, &str->val.str); check_eol (pfile); } -/* Pragmata handling. We handle some of these, and pass the rest on - to the front end. C99 defines three pragmas and says that no macro - expansion is to be performed on them; whether or not macro - expansion happens for other pragmas is implementation defined. - This implementation never macro-expands the text after #pragma. */ - -/* Sub-handlers for the pragmas needing treatment here. - They return 1 if the token buffer is to be popped, 0 if not. */ -struct pragma_entry +/* Lookup a PRAGMA name in a singly-linked CHAIN. Returns the + matching entry, or NULL if none is found. The returned entry could + be the start of a namespace chain, or a pragma. */ +static struct pragma_entry * +lookup_pragma_entry (chain, pragma) + struct pragma_entry *chain; + const cpp_hashnode *pragma; { - struct pragma_entry *next; - const char *name; - size_t len; - int isnspace; - union { - void (*handler) PARAMS ((cpp_reader *)); - struct pragma_entry *space; - } u; -}; + while (chain && chain->pragma != pragma) + chain = chain->next; -void -cpp_register_pragma (pfile, space, name, handler) + return chain; +} + +/* Create and insert a pragma entry for NAME at the beginning of a + singly-linked CHAIN. If handler is NULL, it is a namespace, + otherwise it is a pragma and its handler. */ +static struct pragma_entry * +insert_pragma_entry (pfile, chain, pragma, handler) cpp_reader *pfile; - const char *space; - const char *name; - void (*handler) PARAMS ((cpp_reader *)); + struct pragma_entry **chain; + const cpp_hashnode *pragma; + pragma_cb handler; { - struct pragma_entry **x, *new; - size_t len; + struct pragma_entry *new; - x = &pfile->pragmas; - if (space) + new = (struct pragma_entry *) + _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry)); + new->pragma = pragma; + if (handler) { - struct pragma_entry *p = pfile->pragmas; - len = strlen (space); - while (p) - { - if (p->isnspace && p->len == len && !memcmp (p->name, space, len)) - { - x = &p->u.space; - goto found; - } - p = p->next; - } - cpp_ice (pfile, "unknown #pragma namespace %s", space); - return; + new->is_nspace = 0; + new->u.handler = handler; + } + else + { + new->is_nspace = 1; + new->u.space = NULL; } - found: - new = xnew (struct pragma_entry); - new->name = name; - new->len = strlen (name); - new->isnspace = 0; - new->u.handler = handler; - - new->next = *x; - *x = new; + new->next = *chain; + *chain = new; + return new; } +/* Register a pragma NAME in namespace SPACE. If SPACE is null, it + goes in the global namespace. HANDLER is the handler it will call, + which must be non-NULL. */ void -cpp_register_pragma_space (pfile, space) +cpp_register_pragma (pfile, space, name, handler) cpp_reader *pfile; const char *space; + const char *name; + pragma_cb handler; { - struct pragma_entry *new; - const struct pragma_entry *p = pfile->pragmas; - size_t len = strlen (space); + struct pragma_entry **chain = &pfile->pragmas; + struct pragma_entry *entry; + const cpp_hashnode *node; + + if (!handler) + abort (); - while (p) + if (space) { - if (p->isnspace && p->len == len && !memcmp (p->name, space, len)) - /* Multiple different callers are allowed to register the same - namespace. */ - return; - p = p->next; + node = cpp_lookup (pfile, U space, strlen (space)); + entry = lookup_pragma_entry (*chain, node); + if (!entry) + entry = insert_pragma_entry (pfile, chain, node, NULL); + else if (!entry->is_nspace) + goto clash; + chain = &entry->u.space; } - new = xnew (struct pragma_entry); - new->name = space; - new->len = len; - new->isnspace = 1; - new->u.space = 0; - - new->next = pfile->pragmas; - pfile->pragmas = new; + /* Check for duplicates. */ + node = cpp_lookup (pfile, U name, strlen (name)); + entry = lookup_pragma_entry (*chain, node); + if (entry) + { + if (entry->is_nspace) + clash: + cpp_ice (pfile, + "registering \"%s\" as both a pragma and a pragma namespace", + NODE_NAME (node)); + else if (space) + cpp_ice (pfile, "#pragma %s %s is already registered", space, name); + else + cpp_ice (pfile, "#pragma %s is already registered", name); + } + else + insert_pragma_entry (pfile, chain, node, handler); } - + +/* Register the pragmas the preprocessor itself handles. */ void _cpp_init_internal_pragmas (pfile) cpp_reader *pfile; { - /* top level */ + /* Pragmas in the global namespace. */ cpp_register_pragma (pfile, 0, "poison", do_pragma_poison); cpp_register_pragma (pfile, 0, "once", do_pragma_once); - /* GCC namespace */ - cpp_register_pragma_space (pfile, "GCC"); - + /* New GCC-specific pragmas should be put in the GCC namespace. */ cpp_register_pragma (pfile, "GCC", "poison", do_pragma_poison); cpp_register_pragma (pfile, "GCC", "system_header", do_pragma_system_header); cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency); - + /* Kevin abuse for SDCC. */ cpp_register_pragma(pfile, 0, "sdcc_hash", do_pragma_sdcc_hash); - /* SDCC _asm specific */ + /* SDCC _asm specific */ cpp_register_pragma(pfile, 0, "preproc_asm", do_pragma_preproc_asm); } +/* Pragmata handling. We handle some, and pass the rest on to the + front end. C99 defines three pragmas and says that no macro + expansion is to be performed on them; whether or not macro + expansion happens for other pragmas is implementation defined. + This implementation never macro-expands the text after #pragma. */ static void do_pragma (pfile) cpp_reader *pfile; { - const struct pragma_entry *p; - cpp_token tok; - int drop = 0; + const struct pragma_entry *p = NULL; + const cpp_token *token; + unsigned int count = 1; - p = pfile->pragmas; pfile->state.prevent_expansion++; - cpp_start_lookahead (pfile); - new_space: - cpp_get_token (pfile, &tok); - if (tok.type == CPP_NAME) + token = cpp_get_token (pfile); + if (token->type == CPP_NAME) { - const cpp_hashnode *node = tok.val.node; - size_t len = NODE_LEN (node); - - while (p) + p = lookup_pragma_entry (pfile->pragmas, token->val.node); + if (p && p->is_nspace) { - if (strlen (p->name) == len - && !memcmp (p->name, NODE_NAME (node), len)) - { - if (p->isnspace) - { - p = p->u.space; - goto new_space; - } - else - { - (*p->u.handler) (pfile); - drop = 1; - break; - } - } - p = p->next; + count = 2; + token = cpp_get_token (pfile); + if (token->type == CPP_NAME) + p = lookup_pragma_entry (p->u.space, token->val.node); + else + p = NULL; } } - cpp_stop_lookahead (pfile, drop); - pfile->state.prevent_expansion--; + /* FIXME. This is an awful kludge to get the front ends to update + their notion of line number for diagnostic purposes. The line + number should be passed to the handler and they should do it + themselves. Stand-alone CPP must ignore us, otherwise it will + prefix the directive with spaces, hence the 1. Ugh. */ + if (pfile->cb.line_change) + (*pfile->cb.line_change)(pfile, token, 1); - if (!drop && pfile->cb.def_pragma) - (*pfile->cb.def_pragma) (pfile); + if (p) + (*p->u.handler) (pfile); + else if (pfile->cb.def_pragma) + { + _cpp_backup_tokens (pfile, count); + (*pfile->cb.def_pragma) (pfile, pfile->directive_line); + } + + pfile->state.prevent_expansion--; } +/* Handle #pragma once. */ static void do_pragma_once (pfile) cpp_reader *pfile; { cpp_warning (pfile, "#pragma once is obsolete"); - + if (pfile->buffer->prev == NULL) cpp_warning (pfile, "#pragma once in main file"); else @@ -1095,28 +1106,28 @@ do_pragma_once (pfile) check_eol (pfile); } +/* Handle #pragma poison, to poison one or more identifiers so that + the lexer produces a hard error for each subsequent usage. */ static void do_pragma_poison (pfile) cpp_reader *pfile; { - /* Poison these symbols so that all subsequent usage produces an - error message. */ - cpp_token tok; + const cpp_token *tok; cpp_hashnode *hp; pfile->state.poisoned_ok = 1; for (;;) { - _cpp_lex_token (pfile, &tok); - if (tok.type == CPP_EOF) + tok = _cpp_lex_token (pfile); + if (tok->type == CPP_EOF) break; - if (tok.type != CPP_NAME) + if (tok->type != CPP_NAME) { cpp_error (pfile, "invalid #pragma GCC poison directive"); break; } - hp = tok.val.node; + hp = tok->val.node; if (hp->flags & NODE_POISONED) continue; @@ -1126,28 +1137,21 @@ do_pragma_poison (pfile) hp->flags |= NODE_POISONED | NODE_DIAGNOSTIC; } pfile->state.poisoned_ok = 0; - -#if 0 /* Doesn't quite work yet. */ - if (tok.type == CPP_EOF && pfile->cb.poison) - (*pfile->cb.poison) (pfile); -#endif } static void do_pragma_sdcc_hash (pfile) cpp_reader *pfile; { - cpp_token tok; - /*cpp_hashnode *hp;*/ + const cpp_token *tok = _cpp_lex_token (pfile); - _cpp_lex_token (pfile, &tok); - if (tok.type == CPP_PLUS) + if (tok->type == CPP_PLUS) { CPP_OPTION(pfile, allow_naked_hash)++; } - else if (tok.type == CPP_MINUS) + else if (tok->type == CPP_MINUS) { - CPP_OPTION(pfile, allow_naked_hash)--; + CPP_OPTION(pfile, allow_naked_hash)--; } else { @@ -1161,16 +1165,15 @@ static void do_pragma_preproc_asm (pfile) cpp_reader *pfile; { - cpp_token tok; + const cpp_token *tok = _cpp_lex_token (pfile); - _cpp_lex_token (pfile, &tok); - if (tok.type == CPP_PLUS) + if (tok->type == CPP_PLUS) { CPP_OPTION(pfile, preproc_asm) = 1; } - else if (tok.type == CPP_MINUS) + else if (tok->type == CPP_MINUS) { - CPP_OPTION(pfile, preproc_asm)= 0; + CPP_OPTION(pfile, preproc_asm)= 0; } else { @@ -1193,9 +1196,11 @@ do_pragma_system_header (pfile) if (buffer->prev == 0) cpp_warning (pfile, "#pragma system_header ignored outside include file"); else - cpp_make_system_header (pfile, 1, 0); - - check_eol (pfile); + { + check_eol (pfile); + skip_rest_of_line (pfile); + cpp_make_system_header (pfile, 1, 0); + } } /* Check the modified date of the current include file against a specified @@ -1205,46 +1210,61 @@ static void do_pragma_dependency (pfile) cpp_reader *pfile; { - cpp_token header, msg; + const cpp_token *header; int ordering; - - if (parse_include (pfile, &header)) + + header = parse_include (pfile); + if (!header) return; - ordering = _cpp_compare_file_date (pfile, &header); + ordering = _cpp_compare_file_date (pfile, header); if (ordering < 0) cpp_warning (pfile, "cannot find source %s", - cpp_token_as_text (pfile, &header)); + cpp_token_as_text (pfile, header)); else if (ordering > 0) { cpp_warning (pfile, "current file is older than %s", - cpp_token_as_text (pfile, &header)); - cpp_start_lookahead (pfile); - cpp_get_token (pfile, &msg); - cpp_stop_lookahead (pfile, msg.type == CPP_EOF); - if (msg.type != CPP_EOF) - do_diagnostic (pfile, WARNING, 0); + cpp_token_as_text (pfile, header)); + if (cpp_get_token (pfile)->type != CPP_EOF) + { + _cpp_backup_tokens (pfile, 1); + do_diagnostic (pfile, WARNING, 0); + } } } -/* Check syntax is "(string-literal)". Returns 0 on success. */ -static int -get__Pragma_string (pfile, string) +/* Get a token but skip padding. */ +static const cpp_token * +get_token_no_padding (pfile) + cpp_reader *pfile; +{ + for (;;) + { + const cpp_token *result = cpp_get_token (pfile); + if (result->type != CPP_PADDING) + return result; + } +} + +/* Check syntax is "(string-literal)". Returns the string on success, + or NULL on failure. */ +static const cpp_token * +get__Pragma_string (pfile) cpp_reader *pfile; - cpp_token *string; { - cpp_token paren; + const cpp_token *string; - cpp_get_token (pfile, &paren); - if (paren.type != CPP_OPEN_PAREN) - return 1; + if (get_token_no_padding (pfile)->type != CPP_OPEN_PAREN) + return NULL; - cpp_get_token (pfile, string); + string = get_token_no_padding (pfile); if (string->type != CPP_STRING && string->type != CPP_WSTRING) - return 1; + return NULL; + + if (get_token_no_padding (pfile)->type != CPP_CLOSE_PAREN) + return NULL; - cpp_get_token (pfile, &paren); - return paren.type != CPP_CLOSE_PAREN; + return string; } /* Returns a malloced buffer containing a destringized cpp_string by @@ -1270,23 +1290,86 @@ destringize (in, len) return result; } +/* Destringize IN into a temporary buffer, by removing the first \ of + \" and \\ sequences, and process the result as a #pragma directive. */ +static void +destringize_and_run (pfile, in) + cpp_reader *pfile; + const cpp_string *in; +{ + const unsigned char *src, *limit; + char *dest, *result; + + dest = result = alloca (in->len + 1); + for (src = in->text, limit = src + in->len; src < limit;) + { + /* We know there is a character following the backslash. */ + if (*src == '\\' && (src[1] == '\\' || src[1] == '"')) + src++; + *dest++ = *src++; + } + *dest = '\0'; + + /* Ugh; an awful kludge. We are really not set up to be lexing + tokens when in the middle of a macro expansion. Use a new + context to force cpp_get_token to lex, and so skip_rest_of_line + doesn't go beyond the end of the text. Also, remember the + current lexing position so we can return to it later. + + Something like line-at-a-time lexing should remove the need for + this. */ + { + cpp_context *saved_context = pfile->context; + cpp_token *saved_cur_token = pfile->cur_token; + tokenrun *saved_cur_run = pfile->cur_run; + + pfile->context = xnew (cpp_context); + pfile->context->macro = 0; + pfile->context->prev = 0; + run_directive (pfile, T_PRAGMA, result, dest - result); + free (pfile->context); + pfile->context = saved_context; + pfile->cur_token = saved_cur_token; + pfile->cur_run = saved_cur_run; + } + + /* See above comment. For the moment, we'd like + + token1 _Pragma ("foo") token2 + + to be output as + + token1 + # 7 "file.c" + #pragma foo + # 7 "file.c" + token2 + + Getting the line markers is a little tricky. */ + if (pfile->cb.line_change) + (*pfile->cb.line_change) (pfile, pfile->cur_token, false); +} + +/* Handle the _Pragma operator. */ void _cpp_do__Pragma (pfile) cpp_reader *pfile; { - cpp_token string; - unsigned char *buffer; - unsigned int len; + const cpp_token *string = get__Pragma_string (pfile); - if (get__Pragma_string (pfile, &string)) + if (string) { - cpp_error (pfile, "_Pragma takes a parenthesized string literal"); - return; + unsigned int len; + + unsigned char *buffer = destringize (&string->val.str, &len); + buffer[len] = 0; + cpp_output_string ("\n#pragma "); + cpp_output_string (buffer); + cpp_output_string ("\n"); + free ((PTR) buffer); } - - buffer = destringize (&string.val.str, &len); - run_directive (pfile, T_PRAGMA, BUF_PRAGMA, (char *) buffer, len); - free ((PTR) buffer); + else + cpp_error (pfile, "_Pragma takes a parenthesized string literal"); } /* Just ignore #sccs, on systems where we define it at all. */ @@ -1298,13 +1381,14 @@ do_sccs (pfile) } #endif +/* Handle #ifdef. */ static void do_ifdef (pfile) cpp_reader *pfile; { int skip = 1; - if (! pfile->buffer->was_skipping) + if (! pfile->state.skipping) { const cpp_hashnode *node = lex_macro_node (pfile); @@ -1318,6 +1402,7 @@ do_ifdef (pfile) push_conditional (pfile, skip, T_IFDEF, 0); } +/* Handle #ifndef. */ static void do_ifndef (pfile) cpp_reader *pfile; @@ -1325,7 +1410,7 @@ do_ifndef (pfile) int skip = 1; const cpp_hashnode *node = 0; - if (! pfile->buffer->was_skipping) + if (! pfile->state.skipping) { node = lex_macro_node (pfile); if (node) @@ -1338,33 +1423,26 @@ do_ifndef (pfile) push_conditional (pfile, skip, T_IFNDEF, node); } -/* #if cooperates with parse_defined to handle multiple-include - optimisations. If macro expansions or identifiers appear in the - expression, we cannot treat it as a controlling conditional, since - their values could change in the future. */ - +/* _cpp_parse_expr puts a macro in a "#if !defined ()" expression in + pfile->mi_ind_cmacro so we can handle multiple-include + optimisations. If macro expansion occurs in the expression, we + cannot treat it as a controlling conditional, since the expansion + could change in the future. That is handled by cpp_get_token. */ static void do_if (pfile) cpp_reader *pfile; { int skip = 1; - const cpp_hashnode *cmacro = 0; - if (! pfile->buffer->was_skipping) - { - /* Controlling macro of #if ! defined () */ - pfile->mi_ind_cmacro = 0; - skip = _cpp_parse_expr (pfile) == 0; - cmacro = pfile->mi_ind_cmacro; - } + if (! pfile->state.skipping) + skip = _cpp_parse_expr (pfile) == 0; - push_conditional (pfile, skip, T_IF, cmacro); + push_conditional (pfile, skip, T_IF, pfile->mi_ind_cmacro); } /* Flip skipping state if appropriate and continue without changing if_stack; this is so that the error message for missing #endif's etc. will point to the original #if. */ - static void do_else (pfile) cpp_reader *pfile; @@ -1379,26 +1457,26 @@ do_else (pfile) if (ifs->type == T_ELSE) { cpp_error (pfile, "#else after #else"); - cpp_error_with_line (pfile, ifs->pos.line, ifs->pos.col, + cpp_error_with_line (pfile, ifs->line, 0, "the conditional began here"); } ifs->type = T_ELSE; - /* Buffer->was_skipping is 1 if all conditionals in this chain - have been false, 2 if a conditional has been true. */ - if (! ifs->was_skipping && buffer->was_skipping != 2) - buffer->was_skipping = ! buffer->was_skipping; + /* Skip any future (erroneous) #elses or #elifs. */ + pfile->state.skipping = ifs->skip_elses; + ifs->skip_elses = true; /* Invalidate any controlling macro. */ ifs->mi_cmacro = 0; - } - check_eol (pfile); + /* Only check EOL if was not originally skipping. */ + if (!ifs->was_skipping) + check_eol (pfile); + } } -/* handle a #elif directive by not changing if_stack either. see the +/* Handle a #elif directive by not changing if_stack either. See the comment above do_else. */ - static void do_elif (pfile) cpp_reader *pfile; @@ -1413,29 +1491,28 @@ do_elif (pfile) if (ifs->type == T_ELSE) { cpp_error (pfile, "#elif after #else"); - cpp_error_with_line (pfile, ifs->pos.line, ifs->pos.col, + cpp_error_with_line (pfile, ifs->line, 0, "the conditional began here"); } ifs->type = T_ELIF; - /* Don't evaluate #elif if our higher level is skipping. */ - if (! ifs->was_skipping) + /* Only evaluate this if we aren't skipping elses. During + evaluation, set skipping to false to get lexer warnings. */ + if (ifs->skip_elses) + pfile->state.skipping = 1; + else { - /* Buffer->was_skipping is 1 if all conditionals in this - chain have been false, 2 if a conditional has been true. */ - if (buffer->was_skipping == 1) - buffer->was_skipping = ! _cpp_parse_expr (pfile); - else - buffer->was_skipping = 2; - - /* Invalidate any controlling macro. */ - ifs->mi_cmacro = 0; + pfile->state.skipping = 0; + pfile->state.skipping = ! _cpp_parse_expr (pfile); + ifs->skip_elses = ! pfile->state.skipping; } + + /* Invalidate any controlling macro. */ + ifs->mi_cmacro = 0; } } -/* #endif pops the if stack and resets pfile->skipping. */ - +/* #endif pops the if stack and resets pfile->state.skipping. */ static void do_endif (pfile) cpp_reader *pfile; @@ -1447,25 +1524,27 @@ do_endif (pfile) cpp_error (pfile, "#endif without #if"); else { + /* Only check EOL if was not originally skipping. */ + if (!ifs->was_skipping) + check_eol (pfile); + /* If potential control macro, we go back outside again. */ if (ifs->next == 0 && ifs->mi_cmacro) { - pfile->mi_state = MI_OUTSIDE; + pfile->mi_valid = true; pfile->mi_cmacro = ifs->mi_cmacro; } buffer->if_stack = ifs->next; - buffer->was_skipping = ifs->was_skipping; + pfile->state.skipping = ifs->was_skipping; obstack_free (&pfile->buffer_ob, ifs); } - - check_eol (pfile); } -/* Push an if_stack entry and set pfile->skipping accordingly. - If this is a #ifndef starting at the beginning of a file, - CMACRO is the macro name tested by the #ifndef. */ - +/* Push an if_stack entry for a preprocessor conditional, and set + pfile->state.skipping to SKIP. If TYPE indicates the conditional + is #if or #ifndef, CMACRO is a potentially controlling macro, and + we need to check here that we are at the top of the file. */ static void push_conditional (pfile, skip, type, cmacro) cpp_reader *pfile; @@ -1477,74 +1556,64 @@ push_conditional (pfile, skip, type, cmacro) cpp_buffer *buffer = pfile->buffer; ifs = xobnew (&pfile->buffer_ob, struct if_stack); - ifs->pos = pfile->directive_pos; + ifs->line = pfile->directive_line; ifs->next = buffer->if_stack; - ifs->was_skipping = buffer->was_skipping; + ifs->skip_elses = pfile->state.skipping || !skip; + ifs->was_skipping = pfile->state.skipping; ifs->type = type; - if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0) + /* This condition is effectively a test for top-of-file. */ + if (pfile->mi_valid && pfile->mi_cmacro == 0) ifs->mi_cmacro = cmacro; else ifs->mi_cmacro = 0; - buffer->was_skipping = skip; + pfile->state.skipping = skip; buffer->if_stack = ifs; } -/* Read the tokens of the answer into the macro pool. Only commit the - memory if we intend it as permanent storage, i.e. the #assert case. - Returns 0 on success. */ - +/* Read the tokens of the answer into the macro pool, in a directive + of type TYPE. Only commit the memory if we intend it as permanent + storage, i.e. the #assert case. Returns 0 on success, and sets + ANSWERP to point to the answer. */ static int parse_answer (pfile, answerp, type) cpp_reader *pfile; struct answer **answerp; int type; { - cpp_token paren, *token; + const cpp_token *paren; struct answer *answer; - - if (POOL_FRONT (&pfile->macro_pool) + sizeof (struct answer) > - POOL_LIMIT (&pfile->macro_pool)) - _cpp_next_chunk (&pfile->macro_pool, sizeof (struct answer), 0); - answer = (struct answer *) POOL_FRONT (&pfile->macro_pool); - answer->count = 0; + unsigned int acount; /* In a conditional, it is legal to not have an open paren. We should save the following token in this case. */ - if (type == T_IF) - cpp_start_lookahead (pfile); - cpp_get_token (pfile, &paren); - if (type == T_IF) - cpp_stop_lookahead (pfile, paren.type == CPP_OPEN_PAREN); + paren = cpp_get_token (pfile); /* If not a paren, see if we're OK. */ - if (paren.type != CPP_OPEN_PAREN) + if (paren->type != CPP_OPEN_PAREN) { /* In a conditional no answer is a test for any answer. It could be followed by any token. */ if (type == T_IF) - return 0; + { + _cpp_backup_tokens (pfile, 1); + return 0; + } /* #unassert with no answer is valid - it removes all answers. */ - if (type == T_UNASSERT && paren.type == CPP_EOF) + if (type == T_UNASSERT && paren->type == CPP_EOF) return 0; cpp_error (pfile, "missing '(' after predicate"); return 1; } - for (;;) + for (acount = 0;; acount++) { - token = &answer->first[answer->count]; - /* Check we have room for the token. */ - if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->macro_pool)) - { - _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_token), - (unsigned char **) &answer); - token = &answer->first[answer->count]; - } + size_t room_needed; + const cpp_token *token = cpp_get_token (pfile); + cpp_token *dest; - cpp_get_token (pfile, token); if (token->type == CPP_CLOSE_PAREN) break; @@ -1553,27 +1622,38 @@ parse_answer (pfile, answerp, type) cpp_error (pfile, "missing ')' to complete answer"); return 1; } - answer->count++; + + /* struct answer includes the space for one token. */ + room_needed = (sizeof (struct answer) + acount * sizeof (cpp_token)); + + if (BUFF_ROOM (pfile->a_buff) < room_needed) + _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (struct answer)); + + dest = &((struct answer *) BUFF_FRONT (pfile->a_buff))->first[acount]; + *dest = *token; + + /* Drop whitespace at start, for answer equivalence purposes. */ + if (acount == 0) + dest->flags &= ~PREV_WHITE; } - if (answer->count == 0) + if (acount == 0) { cpp_error (pfile, "predicate's answer is empty"); return 1; } - /* Drop whitespace at start. */ - answer->first->flags &= ~PREV_WHITE; + answer = (struct answer *) BUFF_FRONT (pfile->a_buff); + answer->count = acount; + answer->next = NULL; *answerp = answer; - if (type == T_ASSERT || type == T_UNASSERT) - check_eol (pfile); return 0; } -/* Parses an assertion, returning a pointer to the hash node of the - predicate, or 0 on error. If an answer was supplied, it is placed - in ANSWERP, otherwise it is set to 0. */ +/* Parses an assertion directive of type TYPE, returning a pointer to + the hash node of the predicate, or 0 on error. If an answer was + supplied, it is placed in ANSWERP, otherwise it is set to 0. */ static cpp_hashnode * parse_assertion (pfile, answerp, type) cpp_reader *pfile; @@ -1581,25 +1661,25 @@ parse_assertion (pfile, answerp, type) int type; { cpp_hashnode *result = 0; - cpp_token predicate; + const cpp_token *predicate; /* We don't expand predicates or answers. */ pfile->state.prevent_expansion++; *answerp = 0; - cpp_get_token (pfile, &predicate); - if (predicate.type == CPP_EOF) + predicate = cpp_get_token (pfile); + if (predicate->type == CPP_EOF) cpp_error (pfile, "assertion without predicate"); - else if (predicate.type != CPP_NAME) + else if (predicate->type != CPP_NAME) cpp_error (pfile, "predicate must be an identifier"); else if (parse_answer (pfile, answerp, type) == 0) { - unsigned int len = NODE_LEN (predicate.val.node); + unsigned int len = NODE_LEN (predicate->val.node); unsigned char *sym = alloca (len + 1); /* Prefix '#' to get it out of macro namespace. */ sym[0] = '#'; - memcpy (sym + 1, NODE_NAME (predicate.val.node), len); + memcpy (sym + 1, NODE_NAME (predicate->val.node), len); result = cpp_lookup (pfile, sym, len + 1); } @@ -1607,7 +1687,7 @@ parse_assertion (pfile, answerp, type) return result; } -/* Returns a pointer to the pointer to the answer in the answer chain, +/* Returns a pointer to the pointer to CANDIDATE in the answer chain, or a pointer to NULL if the answer is not in the chain. */ static struct answer ** find_answer (node, candidate) @@ -1655,13 +1735,14 @@ _cpp_test_assertion (pfile, value) return node == 0; } +/* Handle #assert. */ static void do_assert (pfile) cpp_reader *pfile; { struct answer *new_answer; cpp_hashnode *node; - + node = parse_assertion (pfile, &new_answer, T_ASSERT); if (node) { @@ -1677,21 +1758,24 @@ do_assert (pfile) } new_answer->next = node->value.answers; } + node->type = NT_ASSERTION; node->value.answers = new_answer; - POOL_COMMIT (&pfile->macro_pool, (sizeof (struct answer) - + (new_answer->count - 1) - * sizeof (cpp_token))); + BUFF_FRONT (pfile->a_buff) += (sizeof (struct answer) + + (new_answer->count - 1) + * sizeof (cpp_token)); + check_eol (pfile); } } +/* Handle #unassert. */ static void do_unassert (pfile) cpp_reader *pfile; { cpp_hashnode *node; struct answer *answer; - + node = parse_assertion (pfile, &answer, T_UNASSERT); /* It isn't an error to #unassert something that isn't asserted. */ if (node && node->type == NT_ASSERTION) @@ -1708,6 +1792,8 @@ do_unassert (pfile) /* Did we free the last answer? */ if (node->value.answers == 0) node->type = NT_VOID; + + check_eol (pfile); } else _cpp_free_definition (node); @@ -1721,8 +1807,7 @@ do_unassert (pfile) /* 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. */ - + be identifier=definition. */ void cpp_define (pfile, str) cpp_reader *pfile; @@ -1731,13 +1816,12 @@ cpp_define (pfile, str) char *buf, *p; size_t count; - /* Copy the entire option so we can modify it. + /* 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. */ - /* Length including the null. */ count = strlen (str); - buf = (char *) alloca (count + 2); + buf = (char *) alloca (count + 3); memcpy (buf, str, count); p = strchr (str, '='); @@ -1748,8 +1832,9 @@ cpp_define (pfile, str) buf[count++] = ' '; buf[count++] = '1'; } + buf[count] = '\0'; - run_directive (pfile, T_DEFINE, BUF_CL_OPTION, buf, count); + run_directive (pfile, T_DEFINE, buf, count); } /* Slight variant of the above for use by initialize_builtins. */ @@ -1758,7 +1843,7 @@ _cpp_define_builtin (pfile, str) cpp_reader *pfile; const char *str; { - run_directive (pfile, T_DEFINE, BUF_BUILTIN, str, strlen (str)); + run_directive (pfile, T_DEFINE, str, strlen (str)); } /* Process MACRO as if it appeared as the body of an #undef. */ @@ -1767,10 +1852,10 @@ cpp_undef (pfile, macro) cpp_reader *pfile; const char *macro; { - run_directive (pfile, T_UNDEF, BUF_CL_OPTION, macro, strlen (macro)); + run_directive (pfile, T_UNDEF, macro, strlen (macro)); } -/* Process the string STR as if it appeared as the body of a #assert. */ +/* Process the string STR as if it appeared as the body of a #assert. */ void cpp_assert (pfile, str) cpp_reader *pfile; @@ -1779,14 +1864,14 @@ cpp_assert (pfile, str) handle_assertion (pfile, str, T_ASSERT); } -/* Process STR as if it appeared as the body of an #unassert. */ +/* Process STR as if it appeared as the body of an #unassert. */ void cpp_unassert (pfile, str) cpp_reader *pfile; const char *str; { handle_assertion (pfile, str, T_UNASSERT); -} +} /* Common code for cpp_assert (-A) and cpp_unassert (-A-). */ static void @@ -1802,15 +1887,16 @@ handle_assertion (pfile, str, type) { /* Copy the entire option so we can modify it. Change the first "=" in the string to a '(', and tack a ')' on the end. */ - char *buf = (char *) alloca (count + 1); + char *buf = (char *) alloca (count + 2); memcpy (buf, str, count); buf[p - str] = '('; buf[count++] = ')'; + buf[count] = '\0'; str = buf; } - run_directive (pfile, type, BUF_CL_OPTION, str, count); + run_directive (pfile, type, str, count); } /* The number of errors for a given reader. */ @@ -1837,6 +1923,14 @@ cpp_get_callbacks (pfile) return &pfile->cb; } +/* The line map set. */ +const struct line_maps * +cpp_get_line_maps (pfile) + cpp_reader *pfile; +{ + return &pfile->line_maps; +} + /* Copy the given callbacks structure to our own. */ void cpp_set_callbacks (pfile, cb) @@ -1850,60 +1944,25 @@ cpp_set_callbacks (pfile, cb) doesn't fail. It does not generate a file change call back; that is the responsibility of the caller. */ cpp_buffer * -cpp_push_buffer (pfile, buffer, len, type, filename) +cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof) cpp_reader *pfile; const U_CHAR *buffer; size_t len; - enum cpp_buffer_type type; - const char *filename; + int from_stage3; + int return_at_eof; { cpp_buffer *new = xobnew (&pfile->buffer_ob, cpp_buffer); - if (type == BUF_FAKE) - { - /* A copy of the current buffer, just with a new name and type. */ - memcpy (new, pfile->buffer, sizeof (cpp_buffer)); - new->type = BUF_FAKE; - } - else - { - if (type == BUF_BUILTIN) - filename = _(""); - else if (type == BUF_CL_OPTION) - filename = _(""); - else if (type == BUF_PRAGMA) - filename = "<_Pragma>"; - - /* Clears, amongst other things, if_stack and mi_cmacro. */ - memset (new, 0, sizeof (cpp_buffer)); - - new->line_base = new->buf = new->cur = buffer; - new->rlimit = buffer + len; - new->sysp = 0; + /* Clears, amongst other things, if_stack and mi_cmacro. */ + memset (new, 0, sizeof (cpp_buffer)); - /* No read ahead or extra char initially. */ - new->read_ahead = EOF; - new->extra_char = EOF; - - /* Preprocessed files, builtins, _Pragma and command line - options don't do trigraph and escaped newline processing. */ - new->from_stage3 = type != BUF_FILE || CPP_OPTION (pfile, preprocessed); - - pfile->lexer_pos.output_line = 1; - } - - if (*filename == '\0') - new->nominal_fname = _(""); - else - new->nominal_fname = filename; - new->type = type; + new->line_base = new->buf = new->cur = buffer; + new->rlimit = buffer + len; + new->from_stage3 = from_stage3; new->prev = pfile->buffer; - new->pfile = pfile; - new->include_stack_listed = 0; - new->lineno = 1; + new->return_at_eof = return_at_eof; + new->saved_flags = BOL; - pfile->state.next_bol = 1; - pfile->buffer_stack_depth++; pfile->buffer = new; return new; @@ -1912,56 +1971,34 @@ cpp_push_buffer (pfile, buffer, len, type, filename) /* If called from do_line, pops a single buffer. Otherwise pops all buffers until a real file is reached. Generates appropriate call-backs. */ -cpp_buffer * -cpp_pop_buffer (pfile) +void +_cpp_pop_buffer (pfile) cpp_reader *pfile; { - cpp_buffer *buffer; + cpp_buffer *buffer = pfile->buffer; struct if_stack *ifs; + bool pushed = false; - for (;;) - { - buffer = pfile->buffer; - /* Walk back up the conditional stack till we reach its level at - entry to this file, issuing error messages. */ - for (ifs = buffer->if_stack; ifs; ifs = ifs->next) - cpp_error_with_line (pfile, ifs->pos.line, ifs->pos.col, - "unterminated #%s", dtable[ifs->type].name); - - if (buffer->type == BUF_FAKE) - buffer->prev->cur = buffer->cur; - else if (buffer->type == BUF_FILE) - _cpp_pop_file_buffer (pfile, buffer); - - pfile->buffer = buffer->prev; - pfile->buffer_stack_depth--; - - /* Callbacks only generated for faked or real files. */ - if (buffer->type != BUF_FILE && buffer->type != BUF_FAKE) - break; - - /* No callback for EOF of last file. */ - if (!pfile->buffer) - break; + /* Walk back up the conditional stack till we reach its level at + entry to this file, issuing error messages. */ + for (ifs = buffer->if_stack; ifs; ifs = ifs->next) + cpp_error_with_line (pfile, ifs->line, 0, + "unterminated #%s", dtable[ifs->type].name); - /* do_line does its own call backs. */ - pfile->buffer->include_stack_listed = 0; - if (pfile->directive == &dtable[T_LINE]) - break; + /* In case of a missing #endif. */ + pfile->state.skipping = 0; - _cpp_do_file_change (pfile, FC_LEAVE, buffer->nominal_fname, - buffer->lineno); - if (pfile->buffer->type == BUF_FILE) - break; + /* Update the reader's buffer before _cpp_do_file_change. */ + pfile->buffer = buffer->prev; - cpp_warning (pfile, "file \"%s\" entered but not left", - buffer->nominal_fname); - } + if (buffer->inc) + pushed = _cpp_pop_file_buffer (pfile, buffer->inc); - obstack_free (&pfile->buffer_ob, buffer); - return pfile->buffer; + if (!pushed) + obstack_free (&pfile->buffer_ob, buffer); } +/* Enter all recognised directives in the hash table. */ void _cpp_init_directives (pfile) cpp_reader *pfile; @@ -1969,7 +2006,6 @@ _cpp_init_directives (pfile) unsigned int i; cpp_hashnode *node; - /* Register the directives. */ for (i = 0; i < (unsigned int) N_DIRECTIVES; i++) { node = cpp_lookup (pfile, dtable[i].name, dtable[i].length);