From 26aea0737b2d0c4ee328d547555ae25ab5de9a0a Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Sat, 19 Apr 2003 00:22:51 +0000 Subject: [PATCH] cppfiles.c (ENABLE_VALGRIND_CHECKING, [...]): Remove. * cppfiles.c (ENABLE_VALGRIND_CHECKING, VALGRIND_DISCARD, MMAP_THRESHOLD, TEST_THRESHOLD, SHOULD_MMAP): Remove. (struct include_file): Remove fefcnt, mapped members. (open_file, stack_include_file, _cpp_pop_file_buffer): Disable caching. (read_include_file): Don't use mmap, terminate buffers in '\r'. (purge_cache): Don't use munmap. * cpphash.h (CPP_BUF_COLUMN): Update. (lexer_state): Remove lexing_comment. (struct _cpp_line_note): New. (struct cpp_buffer): New members cur_note, notes_used, notes_cap, next_line and need_line. Remove col_adjust and saved_flags. (_cpp_process_line_notes, _cpp_clean_line, _cpp_get_fresh_line, _cpp_skip_block_comment, scan_out_logical_line): New. (_cpp_init_mbchar): Remove. * cppinit.c (init_library): Remove call to _cpp_init_mbchar. (cpp_read_main_file): Set line to 1 earlier. (post_options): -traditional-cpp doesn't want trigraphs. * cpplex.c (MULTIBYTE_CHARS): Remove code predicated on this. (add_line_note, _cpp_clean_line, _cpp_process_line_notes, _cpp_get_fresh_line): New. (handle_newline, skip_escaped_newlines, trigraph_p, continue_after_nul, _cpp_init_mbchar): Remove. (get_effective_char): Update. (_cpp_skip_block_comment): Rename from skip_block_comment, simplify. (skip_line_comment): Simplify. (skip_whitespace, parse_identifier, parse_slow, parse_number, parse_string): Update. (cpp_lex_direct): Use clean lines and process line notes. Update. (cpp_interpret_charconst): No MULTIBYTE_CHARS. * cpplib.c (prepare_directive_trad): Call scan_out_logical_line directly. (_cpp_handle_directive): Don't set saved_flags. (run_directive, destringize_and_run, cpp_define, cpp_define_builtin, cpp_undef, handle_assertion, cpp_push_buffer): Update. (_cpp_pop_buffer): Free notes. * cppmacro.c (builtin_macro, paste_tokens): \n terminate buffer. * cpppch.c (cpp_read_state): \n terminate buffer. * cpptrad.c (skip_escaped_newlines, handle_newline): Remove. (copy_comment): Use _cpp_skip_block_comment. (skip_whitespace, lex_identifier, _cpp_read_logical_line_trad): Simplify. (_cpp_overlay_buffer, _cpp_remove_overlay, push_replacement_text, save_replacement_text): Update. (scan_out_logical_line): Update to use clean lines and process line notes. * fix-header.c (read_scan_file): Update. testsuite: * gcc.dg/cpp/_Pragma4.c: Remove stray space. * gcc.dg/cpp/trad/escaped-eof.c: Correct line number. From-SVN: r65808 --- gcc/ChangeLog | 49 ++ gcc/cppfiles.c | 98 +--- gcc/cpphash.h | 52 +- gcc/cppinit.c | 12 +- gcc/cpplex.c | 592 ++++++++------------ gcc/cpplib.c | 51 +- gcc/cppmacro.c | 24 +- gcc/cpppch.c | 3 +- gcc/cpptrad.c | 253 +++------ gcc/fix-header.c | 2 +- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/cpp/_Pragma4.c | 2 +- gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c | 2 +- 13 files changed, 451 insertions(+), 694 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b9bb923537..978e98ab794 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,52 @@ +2003-04-19 Neil Booth + + * cppfiles.c (ENABLE_VALGRIND_CHECKING, VALGRIND_DISCARD, + MMAP_THRESHOLD, TEST_THRESHOLD, SHOULD_MMAP): Remove. + (struct include_file): Remove fefcnt, mapped members. + (open_file, stack_include_file, _cpp_pop_file_buffer): Disable caching. + (read_include_file): Don't use mmap, terminate buffers in '\r'. + (purge_cache): Don't use munmap. + * cpphash.h (CPP_BUF_COLUMN): Update. + (lexer_state): Remove lexing_comment. + (struct _cpp_line_note): New. + (struct cpp_buffer): New members cur_note, notes_used, notes_cap, + next_line and need_line. Remove col_adjust and saved_flags. + (_cpp_process_line_notes, _cpp_clean_line, _cpp_get_fresh_line, + _cpp_skip_block_comment, scan_out_logical_line): New. + (_cpp_init_mbchar): Remove. + * cppinit.c (init_library): Remove call to _cpp_init_mbchar. + (cpp_read_main_file): Set line to 1 earlier. + (post_options): -traditional-cpp doesn't want trigraphs. + * cpplex.c (MULTIBYTE_CHARS): Remove code predicated on this. + (add_line_note, _cpp_clean_line, _cpp_process_line_notes, + _cpp_get_fresh_line): New. + (handle_newline, skip_escaped_newlines, trigraph_p, + continue_after_nul, _cpp_init_mbchar): Remove. + (get_effective_char): Update. + (_cpp_skip_block_comment): Rename from skip_block_comment, simplify. + (skip_line_comment): Simplify. + (skip_whitespace, parse_identifier, parse_slow, parse_number, + parse_string): Update. + (cpp_lex_direct): Use clean lines and process line notes. Update. + (cpp_interpret_charconst): No MULTIBYTE_CHARS. + * cpplib.c (prepare_directive_trad): Call scan_out_logical_line + directly. + (_cpp_handle_directive): Don't set saved_flags. + (run_directive, destringize_and_run, cpp_define, cpp_define_builtin, + cpp_undef, handle_assertion, cpp_push_buffer): Update. + (_cpp_pop_buffer): Free notes. + * cppmacro.c (builtin_macro, paste_tokens): \n terminate buffer. + * cpppch.c (cpp_read_state): \n terminate buffer. + * cpptrad.c (skip_escaped_newlines, handle_newline): Remove. + (copy_comment): Use _cpp_skip_block_comment. + (skip_whitespace, lex_identifier, _cpp_read_logical_line_trad): + Simplify. + (_cpp_overlay_buffer, _cpp_remove_overlay, push_replacement_text, + save_replacement_text): Update. + (scan_out_logical_line): Update to use clean lines and process + line notes. + * fix-header.c (read_scan_file): Update. + 2003-04-18 Douglas B Rupp * unwind-dw2-fde.c (__register_frame_info_bases): Check for diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 1ff34ff0084..4b8643d7445 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -30,47 +30,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "intl.h" #include "mkdeps.h" #include "splay-tree.h" -#ifdef ENABLE_VALGRIND_CHECKING -# ifdef HAVE_MEMCHECK_H -# include -# else -# include -# endif -#else -/* Avoid #ifdef:s when we can help it. */ -#define VALGRIND_DISCARD(x) -#endif - -#ifdef HAVE_MMAP_FILE -# include -# ifndef MMAP_THRESHOLD -# define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */ -# endif -# if MMAP_THRESHOLD -# define TEST_THRESHOLD(size, pagesize) \ - (size / pagesize >= MMAP_THRESHOLD && (size % pagesize) != 0) - /* Use mmap if the file is big enough to be worth it (controlled - by MMAP_THRESHOLD) and if we can safely count on there being - at least one readable NUL byte after the end of the file's - contents. This is true for all tested operating systems when - the file size is not an exact multiple of the page size. */ -# ifndef __CYGWIN__ -# define SHOULD_MMAP(size, pagesize) TEST_THRESHOLD (size, pagesize) -# else -# define WIN32_LEAN_AND_MEAN -# include - /* Cygwin can't correctly emulate mmap under Windows 9x style systems so - disallow use of mmap on those systems. Windows 9x does not zero fill - memory at EOF and beyond, as required. */ -# define SHOULD_MMAP(size, pagesize) ((GetVersion() & 0x80000000) \ - ? 0 : TEST_THRESHOLD (size, pagesize)) -# endif -# endif - -#else /* No MMAP_FILE */ -# undef MMAP_THRESHOLD -# define MMAP_THRESHOLD 0 -#endif #ifndef O_BINARY # define O_BINARY 0 @@ -102,8 +61,6 @@ struct include_file { int fd; /* fd open on file (short term storage only) */ int err_no; /* errno obtained if opening a file failed */ unsigned short include_count; /* number of times file has been read */ - unsigned short refcnt; /* number of stacked buffers using this file */ - unsigned char mapped; /* file buffer is mmapped */ unsigned char pch; /* 0: file not known to be a PCH. 1: file is a PCH (on return from find_include_file). @@ -278,7 +235,7 @@ open_file (pfile, filename) return file; /* Don't reopen one which is already loaded. */ - if (file->buffer != NULL) + if (0 && file->buffer != NULL) return file; /* We used to open files in nonblocking mode, but that caused more @@ -446,7 +403,7 @@ stack_include_file (pfile, inc) } /* Not in cache? */ - if (! inc->buffer) + if (1 || ! inc->buffer) { if (read_include_file (pfile, inc)) { @@ -471,7 +428,6 @@ stack_include_file (pfile, inc) fp = cpp_push_buffer (pfile, inc->buffer, inc->st.st_size, /* from_stage3 */ CPP_OPTION (pfile, preprocessed), 0); fp->inc = inc; - fp->inc->refcnt++; /* Initialize controlling macro state. */ pfile->mi_valid = true; @@ -507,9 +463,6 @@ read_include_file (pfile, inc) { ssize_t size, offset, count; uchar *buf; -#if MMAP_THRESHOLD - static int pagesize = -1; -#endif if (S_ISREG (inc->st.st_mode)) { @@ -528,25 +481,6 @@ read_include_file (pfile, inc) } size = inc->st.st_size; - inc->mapped = 0; -#if MMAP_THRESHOLD - if (pagesize == -1) - pagesize = getpagesize (); - - if (SHOULD_MMAP (size, pagesize)) - { - buf = (uchar *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0); - if (buf == (uchar *) -1) - goto perror_fail; - - /* We must tell Valgrind that the byte at buf[size] is actually - readable. Discard the handle to avoid handle leak. */ - VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (buf + size, 1)); - - inc->mapped = 1; - } - else -#endif { buf = (uchar *) xmalloc (size + 1); offset = 0; @@ -567,8 +501,8 @@ read_include_file (pfile, inc) } offset += count; } - /* The lexer requires that the buffer be NUL-terminated. */ - buf[size] = '\0'; + /* The lexer requires that the buffer be \n-terminated. */ + buf[size] = '\n'; } } else if (S_ISBLK (inc->st.st_mode)) @@ -600,8 +534,8 @@ read_include_file (pfile, inc) if (offset + 1 < size) buf = xrealloc (buf, offset + 1); - /* The lexer requires that the buffer be NUL-terminated. */ - buf[offset] = '\0'; + /* The lexer requires that the buffer be \n-terminated. */ + buf[offset] = '\n'; inc->st.st_size = offset; } @@ -614,26 +548,14 @@ read_include_file (pfile, inc) return 1; } -/* Drop INC's buffer from memory, if we are unlikely to need it again. */ +/* Drop INC's buffer from memory. */ static void purge_cache (inc) struct include_file *inc; { if (inc->buffer) { -#if MMAP_THRESHOLD - if (inc->mapped) - { - /* Undo the previous annotation for the - known-zero-byte-after-mmap. Discard the handle to avoid - handle leak. */ - VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (inc->buffer - + inc->st.st_size, 1)); - munmap ((PTR) inc->buffer, inc->st.st_size); - } - else -#endif - free ((PTR) inc->buffer); + free ((PTR) inc->buffer); inc->buffer = NULL; } } @@ -929,9 +851,7 @@ _cpp_pop_file_buffer (pfile, inc) /* Invalidate control macros in the #including file. */ pfile->mi_valid = false; - inc->refcnt--; - if (inc->refcnt == 0 && DO_NOT_REREAD (inc)) - purge_cache (inc); + purge_cache (inc); } /* Returns the first place in the include chain to start searching for diff --git a/gcc/cpphash.h b/gcc/cpphash.h index bc0d099599b..4b5cd499cf0 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -45,7 +45,7 @@ typedef unsigned char uchar; #define CPP_OPTION(PFILE, OPTION) ((PFILE)->opts.OPTION) #define CPP_BUFFER(PFILE) ((PFILE)->buffer) -#define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base + (BUF)->col_adjust) +#define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base) #define CPP_BUF_COL(BUF) CPP_BUF_COLUMN(BUF, (BUF)->cur) /* Maximum nesting of cpp_buffers. We use a static limit, partly for @@ -212,9 +212,6 @@ struct lexer_state all directives apart from #define. */ unsigned char save_comments; - /* Nonzero if we're mid-comment. */ - unsigned char lexing_comment; - /* Nonzero if lexing __VA_ARGS__ is valid. */ unsigned char va_args_ok; @@ -240,17 +237,37 @@ struct spec_nodes cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */ }; +typedef struct _cpp_line_note _cpp_line_note; +struct _cpp_line_note +{ + /* Location in the clean line the note refers to. */ + const uchar *pos; + + /* Type of note. */ + enum { NOTE_ESC_NL = 0, + NOTE_ESC_SPACE_NL, + NOTE_TRIGRAPH, + NOTE_NEWLINE } type; +}; + /* Represents the contents of a file cpplib has read in. */ struct cpp_buffer { - const unsigned char *cur; /* current position */ - const unsigned char *backup_to; /* if peeked character is not wanted */ - const unsigned char *rlimit; /* end of valid data */ - const unsigned char *line_base; /* start of current line */ + const uchar *cur; /* Current location. */ + const uchar *line_base; /* Start of current physical line. */ + const uchar *next_line; /* Start of to-be-cleaned logical line. */ + + const uchar *buf; /* Entire character buffer. */ + const uchar *rlimit; /* Writable byte at end of file. */ + + _cpp_line_note *notes; /* Array of notes. */ + unsigned int cur_note; /* Next note to process. */ + unsigned int notes_used; /* Number of notes. */ + unsigned int notes_cap; /* Size of allocated array. */ struct cpp_buffer *prev; - const unsigned char *buf; /* Entire character buffer. */ + const unsigned char *backup_to; /* Soon to die. */ /* Pointer into the include table; non-NULL if this is a file buffer. Used for include_next and to record control macros. */ @@ -260,15 +277,8 @@ struct cpp_buffer Used to prohibit unmatched #endif (etc) in an include file. */ struct if_stack *if_stack; - /* Token column position adjustment owing to tabs in whitespace. */ - unsigned int col_adjust; - - /* Contains PREV_WHITE and/or AVOID_LPASTE. */ - unsigned char saved_flags; - - /* Because of the way the lexer works, -Wtrigraphs can sometimes - warn twice for the same trigraph. This helps prevent that. */ - const unsigned char *last_Wtrigraphs; + /* True if we need to get the next clean line. */ + bool need_line; /* True if we have already warned about C++ comments in this file. The warning happens only for C89 extended mode with -pedantic on, @@ -503,13 +513,16 @@ extern bool _cpp_parse_expr PARAMS ((cpp_reader *)); extern struct op *_cpp_expand_op_stack PARAMS ((cpp_reader *)); /* In cpplex.c */ +extern void _cpp_process_line_notes PARAMS ((cpp_reader *, int)); +extern void _cpp_clean_line PARAMS ((cpp_reader *)); +extern bool _cpp_get_fresh_line PARAMS ((cpp_reader *)); +extern bool _cpp_skip_block_comment PARAMS ((cpp_reader *)); extern cpp_token *_cpp_temp_token PARAMS ((cpp_reader *)); extern const cpp_token *_cpp_lex_token PARAMS ((cpp_reader *)); extern cpp_token *_cpp_lex_direct PARAMS ((cpp_reader *)); extern int _cpp_equiv_tokens PARAMS ((const cpp_token *, const cpp_token *)); extern void _cpp_init_tokenrun PARAMS ((tokenrun *, unsigned int)); -extern void _cpp_init_mbchar PARAMS ((void)); /* In cppinit.c. */ extern void _cpp_maybe_push_include_file PARAMS ((cpp_reader *)); @@ -529,6 +542,7 @@ extern void _cpp_do_file_change PARAMS ((cpp_reader *, enum lc_reason, extern void _cpp_pop_buffer PARAMS ((cpp_reader *)); /* In cpptrad.c. */ +extern bool scan_out_logical_line PARAMS ((cpp_reader *, cpp_macro *)); extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *)); extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *, size_t)); diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 376d72e9e58..74679c0111b 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -125,8 +125,6 @@ init_library () we were compiled with a compiler that supports C99 designated initializers. */ init_trigraph_map (); - - _cpp_init_mbchar (); } } @@ -167,7 +165,6 @@ cpp_create_reader (lang, table) /* Initialize the line map. Start at logical line 1, so we can use a line number of zero for special states. */ init_line_maps (&pfile->line_maps); - pfile->line = 1; /* Initialize lexer state. */ pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); @@ -454,6 +451,7 @@ cpp_read_main_file (pfile, fname) } /* Open the main input file. */ + pfile->line = 1; if (!_cpp_read_file (pfile, fname)) return NULL; @@ -556,7 +554,11 @@ post_options (pfile) CPP_OPTION (pfile, traditional) = 0; } - /* Traditional CPP does not accurately track column information. */ if (CPP_OPTION (pfile, traditional)) - CPP_OPTION (pfile, show_column) = 0; + { + /* Traditional CPP does not accurately track column information. */ + CPP_OPTION (pfile, show_column) = 0; + CPP_OPTION (pfile, trigraphs) = 0; + CPP_OPTION (pfile, warn_trigraphs) = 0; + } } diff --git a/gcc/cpplex.c b/gcc/cpplex.c index 93e04b8b529..930e887948d 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -4,7 +4,6 @@ Based on CCCP program by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 Broken out to separate file, Zack Weinberg, Mar 2000 - Single-pass line tokenization by Neil Booth, April 2000 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -27,11 +26,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cpplib.h" #include "cpphash.h" -#ifdef MULTIBYTE_CHARS -#include "mbchar.h" -#include -#endif - /* Tokens with SPELL_STRING store their spelling in the token list, and it's length in the token->val.name.len. */ enum spell_type @@ -63,24 +57,19 @@ static const struct token_spelling token_spellings[N_TTYPES] = { TTYPE_TABLE }; #define TOKEN_NAME(token) (token_spellings[(token)->type].name) #define BACKUP() do {buffer->cur = buffer->backup_to;} while (0) -static void handle_newline PARAMS ((cpp_reader *)); -static cppchar_t skip_escaped_newlines PARAMS ((cpp_reader *)); +static void add_line_note PARAMS ((cpp_buffer *, const uchar *, unsigned int)); static cppchar_t get_effective_char PARAMS ((cpp_reader *)); -static int skip_block_comment PARAMS ((cpp_reader *)); static int skip_line_comment PARAMS ((cpp_reader *)); -static void adjust_column PARAMS ((cpp_reader *)); -static int skip_whitespace PARAMS ((cpp_reader *, cppchar_t)); +static void skip_whitespace PARAMS ((cpp_reader *, cppchar_t)); static cpp_hashnode *parse_identifier PARAMS ((cpp_reader *)); static uchar *parse_slow PARAMS ((cpp_reader *, const uchar *, int, unsigned int *)); static void parse_number PARAMS ((cpp_reader *, cpp_string *, int)); static int unescaped_terminator_p PARAMS ((cpp_reader *, const uchar *)); static void parse_string PARAMS ((cpp_reader *, cpp_token *, cppchar_t)); -static bool trigraph_p PARAMS ((cpp_reader *)); static void save_comment PARAMS ((cpp_reader *, cpp_token *, const uchar *, cppchar_t)); -static bool continue_after_nul PARAMS ((cpp_reader *)); static int name_p PARAMS ((cpp_reader *, const cpp_string *)); static int maybe_read_ucs PARAMS ((cpp_reader *, const unsigned char **, const unsigned char *, cppchar_t *)); @@ -89,15 +78,6 @@ static tokenrun *next_tokenrun PARAMS ((tokenrun *)); static unsigned int hex_digit_value PARAMS ((unsigned int)); static _cpp_buff *new_buff PARAMS ((size_t)); -/* Change to the native locale for multibyte conversions. */ -void -_cpp_init_mbchar () -{ -#ifdef MULTIBYTE_CHARS - setlocale (LC_CTYPE, ""); - GET_ENVIRONMENT (literal_codeset, "LANG"); -#endif -} /* Utility routine: @@ -114,132 +94,158 @@ cpp_ideq (token, string) return !ustrcmp (NODE_NAME (token->val.node), (const uchar *) string); } -/* Call when meeting a newline, assumed to be in buffer->cur[-1]. - Returns with buffer->cur pointing to the character immediately - following the newline (combination). */ +/* Record a note TYPE at byte POS into the current cleaned logical + line. */ static void -handle_newline (pfile) - cpp_reader *pfile; +add_line_note (buffer, pos, type) + cpp_buffer *buffer; + const uchar *pos; + unsigned int type; { - cpp_buffer *buffer = pfile->buffer; - - /* Handle CR-LF and LF-CR. Most other implementations (e.g. java) - only accept CR-LF; maybe we should fall back to that behavior? */ - if (buffer->cur[-1] + buffer->cur[0] == '\r' + '\n') - buffer->cur++; + if (buffer->notes_used == buffer->notes_cap) + { + buffer->notes_cap = buffer->notes_cap * 2 + 200; + buffer->notes = (_cpp_line_note *) + xrealloc (buffer->notes, buffer->notes_cap * sizeof (_cpp_line_note)); + } - buffer->line_base = buffer->cur; - buffer->col_adjust = 0; - pfile->line++; + buffer->notes[buffer->notes_used].pos = pos; + buffer->notes[buffer->notes_used].type = type; + buffer->notes_used++; } -/* Subroutine of skip_escaped_newlines; called when a 3-character - sequence beginning with "??" is encountered. buffer->cur points to - the second '?'. - - Warn if necessary, and returns true if the sequence forms a - trigraph and the trigraph should be honored. */ -static bool -trigraph_p (pfile) +/* Returns with a logical line that contains no escaped newlines or + trigraphs. This is a time-critical inner loop. */ +void +_cpp_clean_line (pfile) cpp_reader *pfile; { - cpp_buffer *buffer = pfile->buffer; - cppchar_t from_char = buffer->cur[1]; - bool accept; - - if (!_cpp_trigraph_map[from_char]) - return false; + cpp_buffer *buffer; + const uchar *s; + uchar c, *d, *p; - accept = CPP_OPTION (pfile, trigraphs); + buffer = pfile->buffer; + buffer->cur_note = buffer->notes_used = 0; + buffer->cur = buffer->line_base = buffer->next_line; + buffer->need_line = false; + s = buffer->next_line - 1; - /* Don't warn about trigraphs in comments. */ - if (CPP_OPTION (pfile, warn_trigraphs) && !pfile->state.lexing_comment) + if (!buffer->from_stage3) { - if (accept) - cpp_error_with_line (pfile, DL_WARNING, - pfile->line, CPP_BUF_COL (buffer) - 1, - "trigraph ??%c converted to %c", - (int) from_char, - (int) _cpp_trigraph_map[from_char]); - else if (buffer->cur != buffer->last_Wtrigraphs) + d = (uchar *) s; + + for (;;) { - buffer->last_Wtrigraphs = buffer->cur; - cpp_error_with_line (pfile, DL_WARNING, - pfile->line, CPP_BUF_COL (buffer) - 1, - "trigraph ??%c ignored", (int) from_char); + c = *++s; + *++d = c; + + if (c == '\n' || c == '\r') + { + /* Handle DOS line endings. */ + if (c == '\r' && s != buffer->rlimit && s[1] == '\n') + s++; + if (s == buffer->rlimit) + break; + + /* Escaped? */ + p = d; + while (p != buffer->next_line && is_nvspace (p[-1])) + p--; + if (p == buffer->next_line || p[-1] != '\\') + break; + + add_line_note (buffer, p - 1, + p != d ? NOTE_ESC_SPACE_NL: NOTE_ESC_NL); + d = p - 2; + buffer->next_line = p - 1; + } + else if (c == '?' && s[1] == '?' && _cpp_trigraph_map[s[2]]) + { + /* Add a note regardless, for the benefit of -Wtrigraphs. */ + add_line_note (buffer, d, NOTE_TRIGRAPH); + if (CPP_OPTION (pfile, trigraphs)) + { + *d = _cpp_trigraph_map[s[2]]; + s += 2; + } + } } } + else + { + do + s++; + while (*s != '\n' && *s != '\r'); + d = (uchar *) s; + + /* Handle DOS line endings. */ + if (*s == '\r' && s != buffer->rlimit && s[1] == '\n') + s++; + } - return accept; + *d = '\n'; + add_line_note (buffer, d + 1, NOTE_NEWLINE); + buffer->next_line = s + 1; } -/* Skips any escaped newlines introduced by '?' or a '\\', assumed to - lie in buffer->cur[-1]. Returns the next byte, which will be in - buffer->cur[-1]. This routine performs preprocessing stages 1 and - 2 of the ISO C standard. */ -static cppchar_t -skip_escaped_newlines (pfile) +/* Process the notes created by add_line_note as far as the current + location. */ +void +_cpp_process_line_notes (pfile, in_comment) cpp_reader *pfile; + int in_comment; { cpp_buffer *buffer = pfile->buffer; - cppchar_t next = buffer->cur[-1]; - /* Only do this if we apply stages 1 and 2. */ - if (!buffer->from_stage3) + for (;;) { - const unsigned char *saved_cur; - cppchar_t next1; + _cpp_line_note *note = &buffer->notes[buffer->cur_note]; + unsigned int col; - do - { - if (next == '?') - { - if (buffer->cur[0] != '?' || !trigraph_p (pfile)) - break; - - /* Translate the trigraph. */ - next = _cpp_trigraph_map[buffer->cur[1]]; - buffer->cur += 2; - if (next != '\\') - break; - } + if (note->pos > buffer->cur) + break; - if (buffer->cur == buffer->rlimit) - break; + buffer->cur_note++; + col = CPP_BUF_COLUMN (buffer, note->pos + 1); - /* We have a backslash, and room for at least one more - character. Skip horizontal whitespace. */ - saved_cur = buffer->cur; - do - next1 = *buffer->cur++; - while (is_nvspace (next1) && buffer->cur < buffer->rlimit); + switch (note->type) + { + case NOTE_NEWLINE: + /* This note is a kind of sentinel we should never reach. */ + abort (); - if (!is_vspace (next1)) + case NOTE_TRIGRAPH: + if (!in_comment && CPP_OPTION (pfile, warn_trigraphs)) { - buffer->cur = saved_cur; - break; + if (CPP_OPTION (pfile, trigraphs)) + cpp_error_with_line (pfile, DL_WARNING, pfile->line, col, + "trigraph converted to %c", + (int) note->pos[0]); + else + cpp_error_with_line (pfile, DL_WARNING, pfile->line, col, + "trigraph ??%c ignored", + (int) note->pos[2]); } + break; - if (saved_cur != buffer->cur - 1 - && !pfile->state.lexing_comment) - cpp_error (pfile, DL_WARNING, - "backslash and newline separated by space"); - - handle_newline (pfile); - buffer->backup_to = buffer->cur; - if (buffer->cur == buffer->rlimit) + case NOTE_ESC_SPACE_NL: + if (!in_comment) + cpp_error_with_line (pfile, DL_WARNING, pfile->line, col, + "backslash and newline separated by space"); + /* Fall through... */ + case NOTE_ESC_NL: + if (buffer->next_line > buffer->rlimit) { - cpp_error (pfile, DL_PEDWARN, - "backslash-newline at end of file"); - next = EOF; + cpp_error_with_line (pfile, DL_PEDWARN, pfile->line, col, + "backslash-newline at end of file"); + /* Prevent "no newline at end of file" warning. */ + buffer->next_line = buffer->rlimit; } - else - next = *buffer->cur++; + + buffer->line_base = note->pos; + pfile->line++; } - while (next == '\\' || next == '?'); } - - return next; } /* Obtain the next character, after trigraph conversion and skipping @@ -251,42 +257,34 @@ static cppchar_t get_effective_char (pfile) cpp_reader *pfile; { - cppchar_t next; cpp_buffer *buffer = pfile->buffer; buffer->backup_to = buffer->cur; - next = *buffer->cur++; - if (__builtin_expect (next == '?' || next == '\\', 0)) - next = skip_escaped_newlines (pfile); - - return next; + return *buffer->cur++; } /* Skip a C-style block comment. We find the end of the comment by seeing if an asterisk is before every '/' we encounter. Returns nonzero if comment terminated by EOF, zero otherwise. */ -static int -skip_block_comment (pfile) +bool +_cpp_skip_block_comment (pfile) cpp_reader *pfile; { cpp_buffer *buffer = pfile->buffer; - cppchar_t c = EOF, prevc = EOF; + cppchar_t c; - pfile->state.lexing_comment = 1; - while (buffer->cur != buffer->rlimit) - { - prevc = c, c = *buffer->cur++; + if (*buffer->cur == '/') + buffer->cur++; - /* FIXME: For speed, create a new character class of characters - of interest inside block comments. */ - if (c == '?' || c == '\\') - c = skip_escaped_newlines (pfile); + for (;;) + { + c = *buffer->cur++; /* People like decorating comments with '*', so check for '/' instead for efficiency. */ if (c == '/') { - if (prevc == '*') + if (buffer->cur[-2] == '*') break; /* Warn about potential nested comments, but not if the '/' @@ -298,14 +296,18 @@ skip_block_comment (pfile) pfile->line, CPP_BUF_COL (buffer), "\"/*\" within comment"); } - else if (is_vspace (c)) - handle_newline (pfile); - else if (c == '\t') - adjust_column (pfile); + else if (c == '\n') + { + buffer->cur--; + _cpp_process_line_notes (pfile, true); + if (buffer->next_line >= buffer->rlimit) + return true; + _cpp_clean_line (pfile); + pfile->line++; + } } - pfile->state.lexing_comment = 0; - return c != '/' || prevc != '*'; + return false; } /* Skip a C++ line comment, leaving buffer->cur pointing to the @@ -317,72 +319,16 @@ skip_line_comment (pfile) { cpp_buffer *buffer = pfile->buffer; unsigned int orig_line = pfile->line; - cppchar_t c; -#ifdef MULTIBYTE_CHARS - wchar_t wc; - int char_len; -#endif - - pfile->state.lexing_comment = 1; -#ifdef MULTIBYTE_CHARS - /* Reset multibyte conversion state. */ - (void) local_mbtowc (NULL, NULL, 0); -#endif - do - { - if (buffer->cur == buffer->rlimit) - goto at_eof; - -#ifdef MULTIBYTE_CHARS - char_len = local_mbtowc (&wc, (const char *) buffer->cur, - buffer->rlimit - buffer->cur); - if (char_len == -1) - { - cpp_error (pfile, DL_WARNING, - "ignoring invalid multibyte character"); - char_len = 1; - c = *buffer->cur++; - } - else - { - buffer->cur += char_len; - c = wc; - } -#else - c = *buffer->cur++; -#endif - if (c == '?' || c == '\\') - c = skip_escaped_newlines (pfile); - } - while (!is_vspace (c)); - /* Step back over the newline, except at EOF. */ - buffer->cur--; - at_eof: + while (*buffer->cur != '\n') + buffer->cur++; - pfile->state.lexing_comment = 0; + _cpp_process_line_notes (pfile, true); return orig_line != pfile->line; } -/* pfile->buffer->cur is one beyond the \t character. Update - col_adjust so we track the column correctly. */ +/* Skips whitespace, saving the next non-whitespace character. */ static void -adjust_column (pfile) - cpp_reader *pfile; -{ - cpp_buffer *buffer = pfile->buffer; - unsigned int col = CPP_BUF_COL (buffer) - 1; /* Zero-based column. */ - - /* Round it up to multiple of the tabstop, but subtract 1 since the - tab itself occupies a character position. */ - buffer->col_adjust += (CPP_OPTION (pfile, tabstop) - - col % CPP_OPTION (pfile, tabstop)) - 1; -} - -/* Skips whitespace, saving the next non-whitespace character. - Adjusts pfile->col_adjust to account for tabs. Without this, - tokens might be assigned an incorrect column. */ -static int skip_whitespace (pfile, c) cpp_reader *pfile; cppchar_t c; @@ -393,15 +339,11 @@ skip_whitespace (pfile, c) do { /* Horizontal space always OK. */ - if (c == ' ') + if (c == ' ' || c == '\t') ; - else if (c == '\t') - adjust_column (pfile); /* Just \f \v or \0 left. */ else if (c == '\0') { - if (buffer->cur - 1 == buffer->rlimit) - return 0; if (!warned) { cpp_error (pfile, DL_WARNING, "null character(s) ignored"); @@ -420,7 +362,6 @@ skip_whitespace (pfile, c) while (is_nvspace (c)); buffer->cur--; - return 1; } /* See if the characters of a number token are valid in a name (no @@ -461,7 +402,7 @@ parse_identifier (pfile) cur++; /* Check for slow-path cases. */ - if (*cur == '?' || *cur == '\\' || *cur == '$') + if (*cur == '$') { unsigned int len; @@ -532,8 +473,6 @@ parse_slow (pfile, cur, number_p, plen) { /* Potential escaped newline? */ buffer->backup_to = buffer->cur - 1; - if (c == '?' || c == '\\') - c = skip_escaped_newlines (pfile); if (!is_idchar (c)) { @@ -590,7 +529,7 @@ parse_number (pfile, number, leading_period) cur++; /* Check for slow-path cases. */ - if (*cur == '?' || *cur == '\\' || *cur == '$') + if (*cur == '$') number->text = parse_slow (pfile, cur, 1 + leading_period, &number->len); else { @@ -648,18 +587,10 @@ parse_string (pfile, token, terminator) unsigned char *dest, *limit; cppchar_t c; bool warned_nulls = false; -#ifdef MULTIBYTE_CHARS - wchar_t wc; - int char_len; -#endif dest = BUFF_FRONT (pfile->u_buff); limit = BUFF_LIMIT (pfile->u_buff); -#ifdef MULTIBYTE_CHARS - /* Reset multibyte conversion state. */ - (void) local_mbtowc (NULL, NULL, 0); -#endif for (;;) { /* We need room for another char, possibly the terminating NUL. */ @@ -671,41 +602,19 @@ parse_string (pfile, token, terminator) limit = BUFF_LIMIT (pfile->u_buff); } -#ifdef MULTIBYTE_CHARS - char_len = local_mbtowc (&wc, (const char *) buffer->cur, - buffer->rlimit - buffer->cur); - if (char_len == -1) - { - cpp_error (pfile, DL_WARNING, - "ignoring invalid multibyte character"); - char_len = 1; - c = *buffer->cur++; - } - else - { - buffer->cur += char_len; - c = wc; - } -#else c = *buffer->cur++; -#endif - - /* Handle trigraphs, escaped newlines etc. */ - if (c == '?' || c == '\\') - c = skip_escaped_newlines (pfile); if (c == terminator) { if (unescaped_terminator_p (pfile, dest)) break; } - else if (is_vspace (c)) + else if (c == '\n') { /* No string literal may extend over multiple lines. In assembly language, suppress the error except for <> includes. This is a kludge around not knowing where comments are. */ - unterminated: if (CPP_OPTION (pfile, lang) != CLK_ASM || terminator == '>') cpp_error (pfile, DL_ERROR, "missing terminating %c character", (int) terminator); @@ -714,8 +623,6 @@ parse_string (pfile, token, terminator) } else if (c == '\0') { - if (buffer->cur - 1 == buffer->rlimit) - goto unterminated; if (!warned_nulls) { warned_nulls = true; @@ -723,14 +630,6 @@ parse_string (pfile, token, terminator) "null character(s) preserved in literal"); } } -#ifdef MULTIBYTE_CHARS - if (char_len > 1) - { - for ( ; char_len > 0; --char_len) - *dest++ = (*buffer->cur - char_len); - } - else -#endif *dest++ = c; } @@ -890,55 +789,55 @@ _cpp_lex_token (pfile) return result; } -/* A NUL terminates the current buffer. For ISO preprocessing this is - EOF, but for traditional preprocessing it indicates we need a line - refill. Returns TRUE to continue preprocessing a new buffer, FALSE - to return a CPP_EOF to the caller. */ -static bool -continue_after_nul (pfile) +/* Returns true if a fresh line has been loaded. */ +bool +_cpp_get_fresh_line (pfile) cpp_reader *pfile; { - cpp_buffer *buffer = pfile->buffer; - bool more = false; + /* We can't get a new line until we leave the current directive. */ + if (pfile->state.in_directive) + return false; - buffer->saved_flags = BOL; - if (CPP_OPTION (pfile, traditional)) + for (;;) { - if (pfile->state.in_directive) - return false; + cpp_buffer *buffer = pfile->buffer; - _cpp_remove_overlay (pfile); - more = _cpp_read_logical_line_trad (pfile); - _cpp_overlay_buffer (pfile, pfile->out.base, - pfile->out.cur - pfile->out.base); - pfile->line = pfile->out.first_line; - } - else - { - /* Stop parsing arguments with a CPP_EOF. When we finally come - back here, do the work of popping the buffer. */ - if (!pfile->state.parsing_args) + if (!buffer->need_line) + return true; + + if (buffer->next_line < buffer->rlimit) { - if (buffer->cur != buffer->line_base) - { - /* Non-empty files should end in a newline. Don't warn - for command line and _Pragma buffers. */ - if (!buffer->from_stage3) - cpp_error (pfile, DL_PEDWARN, "no newline at end of file"); - handle_newline (pfile); - } + _cpp_clean_line (pfile); + return true; + } - /* Similarly, finish an in-progress directive with CPP_EOF - before popping the buffer. */ - if (!pfile->state.in_directive && buffer->prev) - { - more = !buffer->return_at_eof; - _cpp_pop_buffer (pfile); - } + /* First, get out of parsing arguments state. */ + if (pfile->state.parsing_args) + return false; + + /* End of buffer. Non-empty files should end in a newline. */ + if (buffer->buf != buffer->rlimit + && buffer->next_line > buffer->rlimit + && !buffer->from_stage3) + { + /* Only warn once. */ + buffer->next_line = buffer->rlimit; + cpp_error_with_line (pfile, DL_PEDWARN, pfile->line - 1, + CPP_BUF_COLUMN (buffer, buffer->cur), + "no newline at end of file"); + } + + if (buffer->return_at_eof) + { + buffer->return_at_eof = false; + return false; } - } - return more; + if (!buffer->prev) + return false; + + _cpp_pop_buffer (pfile); + } } #define IF_NEXT_IS(CHAR, THEN_TYPE, ELSE_TYPE) \ @@ -973,74 +872,49 @@ _cpp_lex_direct (pfile) cpp_token *result = pfile->cur_token++; fresh_line: + result->flags = 0; + if (pfile->buffer->need_line) + { + if (!_cpp_get_fresh_line (pfile)) + { + result->type = CPP_EOF; + return result; + } + if (!pfile->keep_tokens) + { + pfile->cur_run = &pfile->base_run; + result = pfile->base_run.base; + pfile->cur_token = result + 1; + } + result->flags = BOL; + if (pfile->state.parsing_args == 2) + result->flags |= PREV_WHITE; + } buffer = pfile->buffer; - result->flags = buffer->saved_flags; - buffer->saved_flags = 0; update_tokens_line: result->line = pfile->line; skipped_white: + if (buffer->cur >= buffer->notes[buffer->cur_note].pos + && !pfile->overlaid_buffer) + { + _cpp_process_line_notes (pfile, false); + result->line = pfile->line; + } c = *buffer->cur++; result->col = CPP_BUF_COLUMN (buffer, buffer->cur); - trigraph: switch (c) { case ' ': case '\t': case '\f': case '\v': case '\0': result->flags |= PREV_WHITE; - if (skip_whitespace (pfile, c)) - goto skipped_white; - - /* End of buffer. */ - buffer->cur--; - if (continue_after_nul (pfile)) - goto fresh_line; - result->type = CPP_EOF; - break; + skip_whitespace (pfile, c); + goto skipped_white; - case '\n': case '\r': - handle_newline (pfile); - buffer->saved_flags = BOL; - if (! pfile->state.in_directive) - { - if (pfile->state.parsing_args == 2) - buffer->saved_flags |= PREV_WHITE; - if (!pfile->keep_tokens) - { - pfile->cur_run = &pfile->base_run; - result = pfile->base_run.base; - pfile->cur_token = result + 1; - } - goto fresh_line; - } - result->type = CPP_EOF; - break; - - case '?': - case '\\': - /* These could start an escaped newline, or '?' a trigraph. Let - skip_escaped_newlines do all the work. */ - { - unsigned int line = pfile->line; - - c = skip_escaped_newlines (pfile); - if (line != pfile->line) - { - buffer->cur--; - /* We had at least one escaped newline of some sort. - Update the token's line and column. */ - goto update_tokens_line; - } - } - - /* We are either the original '?' or '\\', or a trigraph. */ - if (c == '?') - result->type = CPP_QUERY; - else if (c == '\\') - goto random_char; - else - goto trigraph; - break; + case '\n': + pfile->line++; + buffer->need_line = true; + goto fresh_line; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -1100,7 +974,7 @@ _cpp_lex_direct (pfile) if (c == '*') { - if (skip_block_comment (pfile)) + if (_cpp_skip_block_comment (pfile)) cpp_error (pfile, DL_ERROR, "unterminated comment"); } else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments) @@ -1331,6 +1205,7 @@ _cpp_lex_direct (pfile) case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break; case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break; + case '?': result->type = CPP_QUERY; break; case '~': result->type = CPP_COMPL; break; case ',': result->type = CPP_COMMA; break; case '(': result->type = CPP_OPEN_PAREN; break; @@ -1349,7 +1224,6 @@ _cpp_lex_direct (pfile) goto start_ident; /* Fall through... */ - random_char: default: result->type = CPP_OTHER; result->val.c = c; @@ -1927,10 +1801,6 @@ cpp_interpret_charconst (pfile, token, pchars_seen, unsignedp) cppchar_t c, mask, result = 0; bool unsigned_p; -#ifdef MULTIBYTE_CHARS - (void) local_mbtowc (NULL, NULL, 0); -#endif - /* Width in bits. */ if (token->type == CPP_CHAR) { @@ -1952,25 +1822,7 @@ cpp_interpret_charconst (pfile, token, pchars_seen, unsignedp) while (str < limit) { -#ifdef MULTIBYTE_CHARS - wchar_t wc; - int char_len; - - char_len = local_mbtowc (&wc, (const char *)str, limit - str); - if (char_len == -1) - { - cpp_error (pfile, DL_WARNING, - "ignoring invalid multibyte character"); - c = *str++; - } - else - { - str += char_len; - c = wc; - } -#else c = *str++; -#endif if (c == '\\') c = cpp_parse_escape (pfile, &str, limit, token->type == CPP_WCHAR); diff --git a/gcc/cpplib.c b/gcc/cpplib.c index 7d2d9652477..bb983b04a29 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -295,7 +295,7 @@ prepare_directive_trad (pfile) || pfile->directive == &dtable[T_ELIF]); if (no_expand) pfile->state.prevent_expansion++; - _cpp_read_logical_line_trad (pfile); + scan_out_logical_line (pfile, NULL); if (no_expand) pfile->state.prevent_expansion--; pfile->state.skipping = was_skipping; @@ -451,13 +451,12 @@ _cpp_handle_directive (pfile, indented) /* Restore state when within macro args. */ pfile->state.parsing_args = 2; pfile->state.prevent_expansion = 1; - pfile->buffer->saved_flags |= PREV_WHITE; } return skip; } /* Directive handler wrapper used by the command line option - processor. */ + processor. BUF is \n terminated. */ static void run_directive (pfile, dir_no, buf, count) cpp_reader *pfile; @@ -471,8 +470,11 @@ run_directive (pfile, dir_no, buf, count) if (dir_no == T_PRAGMA) pfile->buffer->inc = pfile->buffer->prev->inc; start_directive (pfile); - /* We don't want a leading # to be interpreted as a directive. */ - pfile->buffer->saved_flags = 0; + + /* This is a short-term fix to prevent a leading '#' being + interpreted as a directive. */ + _cpp_clean_line (pfile); + pfile->directive = &dtable[dir_no]; if (CPP_OPTION (pfile, traditional)) prepare_directive_trad (pfile); @@ -1378,7 +1380,7 @@ destringize_and_run (pfile, in) src++; *dest++ = *src++; } - *dest = '\0'; + *dest = '\n'; /* 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 @@ -1904,7 +1906,7 @@ cpp_define (pfile, str) buf[count++] = ' '; buf[count++] = '1'; } - buf[count] = '\0'; + buf[count] = '\n'; run_directive (pfile, T_DEFINE, buf, count); } @@ -1915,7 +1917,11 @@ _cpp_define_builtin (pfile, str) cpp_reader *pfile; const char *str; { - run_directive (pfile, T_DEFINE, str, strlen (str)); + size_t len = strlen (str); + char *buf = alloca (len + 1); + memcpy (buf, str, len); + buf[len] = '\n'; + run_directive (pfile, T_DEFINE, buf, len); } /* Process MACRO as if it appeared as the body of an #undef. */ @@ -1924,7 +1930,11 @@ cpp_undef (pfile, macro) cpp_reader *pfile; const char *macro; { - run_directive (pfile, T_UNDEF, macro, strlen (macro)); + size_t len = strlen (macro); + char *buf = alloca (len + 1); + memcpy (buf, macro, len); + buf[len] = '\n'; + run_directive (pfile, T_UNDEF, buf, len); } /* Process the string STR as if it appeared as the body of a #assert. */ @@ -1955,18 +1965,18 @@ handle_assertion (pfile, str, type) size_t count = strlen (str); const char *p = strchr (str, '='); + /* 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 + 2); + + memcpy (buf, str, count); if (p) { - /* 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 + 2); - - memcpy (buf, str, count); buf[p - str] = '('; buf[count++] = ')'; - buf[count] = '\0'; - str = buf; } + buf[count] = '\n'; + str = buf; run_directive (pfile, type, str, count); } @@ -2028,15 +2038,14 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof) /* Clears, amongst other things, if_stack and mi_cmacro. */ memset (new, 0, sizeof (cpp_buffer)); - new->line_base = new->buf = new->cur = buffer; + new->next_line = new->buf = buffer; new->rlimit = buffer + len; - new->from_stage3 = from_stage3 || CPP_OPTION (pfile, traditional); + new->from_stage3 = from_stage3; new->prev = pfile->buffer; new->return_at_eof = return_at_eof; - new->saved_flags = BOL; + new->need_line = true; pfile->buffer = new; - return new; } @@ -2062,6 +2071,8 @@ _cpp_pop_buffer (pfile) /* _cpp_do_file_change expects pfile->buffer to be the new one. */ pfile->buffer = buffer->prev; + free (buffer->notes); + /* Free the buffer object now; we may want to push a new buffer in _cpp_push_next_include_file. */ obstack_free (&pfile->buffer_ob, buffer); diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index 94fa8583a8a..0898dac8cd1 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -265,6 +265,8 @@ builtin_macro (pfile, node) cpp_hashnode *node; { const uchar *buf; + size_t len; + char *nbuf; if (node->value.builtin == BT_PRAGMA) { @@ -278,14 +280,13 @@ builtin_macro (pfile, node) } buf = _cpp_builtin_macro_text (pfile, node); + len = ustrlen (buf); + nbuf = alloca (len + 1); + memcpy (nbuf, buf, len); + nbuf[len]='\n'; - cpp_push_buffer (pfile, buf, ustrlen (buf), /* from_stage3 */ true, 1); - - /* Tweak the column number the lexer will report. */ - pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1; - - /* We don't want a leading # to be interpreted as a directive. */ - pfile->buffer->saved_flags = 0; + cpp_push_buffer (pfile, (uchar *) nbuf, len, /* from_stage3 */ true, 1); + _cpp_clean_line (pfile); /* Set pfile->cur_token as required by _cpp_lex_direct. */ pfile->cur_token = _cpp_temp_token (pfile); @@ -445,15 +446,10 @@ paste_tokens (pfile, plhs, rhs) if (lhs->type == CPP_DIV && rhs->type != CPP_EQ) *end++ = ' '; end = cpp_spell_token (pfile, rhs, end); - *end = '\0'; + *end = '\n'; cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true, 1); - - /* Tweak the column number the lexer will report. */ - pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1; - - /* We don't want a leading # to be interpreted as a directive. */ - pfile->buffer->saved_flags = 0; + _cpp_clean_line (pfile); /* Set pfile->cur_token as required by _cpp_lex_direct. */ pfile->cur_token = _cpp_temp_token (pfile); diff --git a/gcc/cpppch.c b/gcc/cpppch.c index 388a7532c11..602711a427e 100644 --- a/gcc/cpppch.c +++ b/gcc/cpppch.c @@ -708,7 +708,7 @@ cpp_read_state (r, name, f, data) if (fread (defn, 1, m.definition_length, f) != m.definition_length) goto error; - defn[m.definition_length] = '\0'; + defn[m.definition_length] = '\n'; h = cpp_lookup (r, defn, m.name_length); @@ -722,6 +722,7 @@ cpp_read_state (r, name, f, data) m.definition_length - m.name_length, true, 1) != NULL) { + _cpp_clean_line (r); if (!_cpp_create_definition (r, h)) abort (); _cpp_pop_buffer (r); diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index 92c4ee3d522..f2f94f6d045 100644 --- a/gcc/cpptrad.c +++ b/gcc/cpptrad.c @@ -81,14 +81,10 @@ enum ls {ls_none = 0, /* Normal state. */ /* Lexing TODO: Maybe handle space in escaped newlines. Stop cpplex.c from recognizing comments and directives during its lexing pass. */ -static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *)); -static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *, - const uchar *)); static const uchar *skip_whitespace PARAMS ((cpp_reader *, const uchar *, int)); static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *)); static const uchar *copy_comment PARAMS ((cpp_reader *, const uchar *, int)); -static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *)); static void check_output_buffer PARAMS ((cpp_reader *, size_t)); static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *)); static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *)); @@ -125,43 +121,6 @@ check_output_buffer (pfile, n) } } -/* To be called whenever a newline character is encountered in the - input file, at CUR. Handles DOS, Mac and Unix ends of line, and - increments pfile->line. - - Returns a pointer the character after the newline sequence. */ -static const uchar * -handle_newline (pfile, cur) - cpp_reader *pfile; - const uchar *cur; -{ - pfile->line++; - if (cur[0] + cur[1] == '\r' + '\n') - cur++; - return cur + 1; -} - -/* CUR points to any character in the current context, not necessarily - a backslash. Advances CUR until all escaped newlines are skipped, - and returns the new position without updating the context. - - Warns if a file buffer ends in an escaped newline. */ -static const uchar * -skip_escaped_newlines (pfile, cur) - cpp_reader *pfile; - const uchar *cur; -{ - const uchar *orig_cur = cur; - - while (*cur == '\\' && is_vspace (cur[1])) - cur = handle_newline (pfile, cur + 1); - - if (cur != orig_cur && cur == RLIMIT (pfile->context) && pfile->buffer->inc) - cpp_error (pfile, DL_PEDWARN, "backslash-newline at end of file"); - - return cur; -} - /* CUR points to the asterisk introducing a comment in the current context. IN_DEFINE is true if we are in the replacement text of a macro. @@ -180,43 +139,16 @@ copy_comment (pfile, cur, in_define) const uchar *cur; int in_define; { + bool unterminated, copy = false; unsigned int from_line = pfile->line; - const uchar *limit = RLIMIT (pfile->context); - uchar *out = pfile->out.cur; - - do - { - unsigned int c = *cur++; - *out++ = c; - - if (c == '/') - { - /* An immediate slash does not terminate the comment. */ - if (out[-2] == '*' && out - 2 > pfile->out.cur) - goto done; - - if (*cur == '*' && cur[1] != '/' - && CPP_OPTION (pfile, warn_comments)) - cpp_error_with_line (pfile, DL_WARNING, pfile->line, 0, - "\"/*\" within comment"); - } - else if (is_vspace (c)) - { - cur = handle_newline (pfile, cur - 1); - /* Canonicalize newline sequences and skip escaped ones. */ - if (out[-2] == '\\') - out -= 2; - else - out[-1] = '\n'; - } - } - while (cur < limit); + cpp_buffer *buffer = pfile->buffer; - cpp_error_with_line (pfile, DL_ERROR, from_line, 0, "unterminated comment"); - *out++ = '*'; - *out++ = '/'; + buffer->cur = cur; + unterminated = _cpp_skip_block_comment (pfile); + if (unterminated) + cpp_error_with_line (pfile, DL_ERROR, from_line, 0, + "unterminated comment"); - done: /* Comments in directives become spaces so that tokens are properly separated when the ISO preprocessor re-lexes the line. The exception is #define. */ @@ -227,7 +159,7 @@ copy_comment (pfile, cur, in_define) if (CPP_OPTION (pfile, discard_comments_in_macro_exp)) pfile->out.cur--; else - pfile->out.cur = out; + copy = true; } else pfile->out.cur[-1] = ' '; @@ -235,9 +167,21 @@ copy_comment (pfile, cur, in_define) else if (CPP_OPTION (pfile, discard_comments)) pfile->out.cur--; else - pfile->out.cur = out; + copy = true; - return cur; + if (copy) + { + size_t len = (size_t) (buffer->cur - cur); + memcpy (pfile->out.cur, cur, len); + pfile->out.cur += len; + if (unterminated) + { + *pfile->out.cur++ = '*'; + *pfile->out.cur++ = '/'; + } + } + + return buffer->cur; } /* CUR points to any character in the input buffer. Skips over all @@ -265,31 +209,18 @@ skip_whitespace (pfile, cur, skip_comments) unsigned int c = *cur++; *out++ = c; - if (is_nvspace (c) && c) + if (is_nvspace (c)) continue; - if (!c && cur - 1 != RLIMIT (pfile->context)) - continue; - - if (c == '/' && skip_comments) - { - const uchar *tmp = skip_escaped_newlines (pfile, cur); - if (*tmp == '*') - { - pfile->out.cur = out; - cur = copy_comment (pfile, tmp, false /* in_define */); - out = pfile->out.cur; - continue; - } - } - - out--; - if (c == '\\' && is_vspace (*cur)) + if (c == '/' && *cur == '*' && skip_comments) { - cur = skip_escaped_newlines (pfile, cur - 1); + pfile->out.cur = out; + cur = copy_comment (pfile, cur, false /* in_define */); + out = pfile->out.cur; continue; } + out--; break; } @@ -310,12 +241,7 @@ lex_identifier (pfile, cur) cpp_hashnode *result; do - { - do - *out++ = *cur++; - while (is_numchar (*cur)); - cur = skip_escaped_newlines (pfile, cur); - } + *out++ = *cur++; while (is_numchar (*cur)); CUR (pfile->context) = cur; @@ -340,11 +266,12 @@ _cpp_overlay_buffer (pfile, start, len) pfile->overlaid_buffer = buffer; buffer->saved_cur = buffer->cur; buffer->saved_rlimit = buffer->rlimit; + /* Prevent the ISO lexer from scanning a fresh line. */ + pfile->saved_line = pfile->line--; + buffer->need_line = false; buffer->cur = start; buffer->rlimit = start + len; - - pfile->saved_line = pfile->line; } /* Restores a buffer overlaid by _cpp_overlay_buffer(). */ @@ -356,7 +283,9 @@ _cpp_remove_overlay (pfile) buffer->cur = buffer->saved_cur; buffer->rlimit = buffer->saved_rlimit; + buffer->need_line = true; + pfile->overlaid_buffer = NULL; pfile->line = pfile->saved_line; } @@ -368,24 +297,10 @@ _cpp_read_logical_line_trad (pfile) { do { - if (pfile->buffer->cur == pfile->buffer->rlimit) - { - bool stop = true; - - /* Don't pop the last buffer. */ - if (pfile->buffer->prev) - { - stop = pfile->buffer->return_at_eof; - _cpp_pop_buffer (pfile); - } - - if (stop) - return false; - } - - scan_out_logical_line (pfile, NULL); + if (pfile->buffer->need_line && !_cpp_get_fresh_line (pfile)) + return false; } - while (pfile->state.skipping); + while (!scan_out_logical_line (pfile, NULL) || pfile->state.skipping); return true; } @@ -428,11 +343,12 @@ save_argument (macro, offset) If MACRO is non-NULL, then we are scanning the replacement list of MACRO, and we call save_replacement_text() every time we meet an argument. */ -static void +bool scan_out_logical_line (pfile, macro) cpp_reader *pfile; cpp_macro *macro; { + bool result = true; cpp_context *context; const uchar *cur; uchar *out; @@ -443,7 +359,6 @@ scan_out_logical_line (pfile, macro) fmacro.buff = NULL; - start_logical_line: quote = 0; header_ok = pfile->state.angled_headers; CUR (pfile->context) = pfile->buffer->cur; @@ -458,6 +373,12 @@ scan_out_logical_line (pfile, macro) for (;;) { + if (!context->prev + && cur >= pfile->buffer->notes[pfile->buffer->cur_note].pos) + { + pfile->buffer->cur = cur; + _cpp_process_line_notes (pfile, false); + } c = *cur++; *out++ = c; @@ -469,12 +390,10 @@ scan_out_logical_line (pfile, macro) case '\t': case '\f': case '\v': - continue; - case '\0': - if (cur - 1 != RLIMIT (context)) - continue; + continue; + case '\n': /* If this is a macro's expansion, pop it. */ if (context->prev) { @@ -483,22 +402,21 @@ scan_out_logical_line (pfile, macro) goto new_context; } - /* Premature end of file. Fake a new line. */ - cur--; - if (!pfile->buffer->from_stage3) - cpp_error (pfile, DL_PEDWARN, "no newline at end of file"); + /* Omit the newline from the output buffer. */ + pfile->out.cur = out - 1; + pfile->buffer->cur = cur; + pfile->buffer->need_line = true; pfile->line++; - goto done; - case '\r': case '\n': - cur = handle_newline (pfile, cur - 1); if ((lex_state == ls_fun_open || lex_state == ls_fun_close) - && !pfile->state.in_directive) + && !pfile->state.in_directive + && _cpp_get_fresh_line (pfile)) { /* Newlines in arguments become a space, but we don't clear any in-progress quote. */ if (lex_state == ls_fun_close) out[-1] = ' '; + cur = pfile->buffer->cur; continue; } goto done; @@ -521,35 +439,20 @@ scan_out_logical_line (pfile, macro) break; case '\\': - if (is_vspace (*cur)) - { - out--; - cur = skip_escaped_newlines (pfile, cur - 1); - continue; - } - else - { - /* Skip escaped quotes here, it's easier than above, but - take care to first skip escaped newlines. */ - cur = skip_escaped_newlines (pfile, cur); - if (*cur == '\\' || *cur == '"' || *cur == '\'') - *out++ = *cur++; - } + /* Skip escaped quotes here, it's easier than above. */ + if (*cur == '\\' || *cur == '"' || *cur == '\'') + *out++ = *cur++; break; case '/': /* Traditional CPP does not recognize comments within literals. */ - if (!quote) + if (!quote && *cur == '*') { - cur = skip_escaped_newlines (pfile, cur); - if (*cur == '*') - { - pfile->out.cur = out; - cur = copy_comment (pfile, cur, macro != 0); - out = pfile->out.cur; - continue; - } + pfile->out.cur = out; + cur = copy_comment (pfile, cur, macro != 0); + out = pfile->out.cur; + continue; } break; @@ -699,12 +602,14 @@ scan_out_logical_line (pfile, macro) cur = skip_whitespace (pfile, cur, true /* skip_comments */); out = pfile->out.cur; - if (is_vspace (*cur)) + if (*cur == '\n') { /* Null directive. Ignore it and don't invalidate the MI optimization. */ - out = pfile->out.base; - continue; + pfile->buffer->need_line = true; + pfile->line++; + result = false; + goto done; } else { @@ -724,9 +629,8 @@ scan_out_logical_line (pfile, macro) preprocessor lex the next token. */ pfile->buffer->cur = cur; _cpp_handle_directive (pfile, false /* indented */); - /* #include changes pfile->buffer so we need to - update the limits of the current context. */ - goto start_logical_line; + result = false; + goto done; } } } @@ -765,9 +669,6 @@ scan_out_logical_line (pfile, macro) } done: - out[-1] = '\0'; - pfile->buffer->cur = cur; - pfile->out.cur = out - 1; if (fmacro.buff) _cpp_release_buff (pfile, fmacro.buff); @@ -775,6 +676,7 @@ scan_out_logical_line (pfile, macro) cpp_error_with_line (pfile, DL_ERROR, fmacro.line, 0, "unterminated argument list invoking macro \"%s\"", NODE_NAME (fmacro.node)); + return result; } /* Push a context holding the replacement text of the macro NODE on @@ -787,11 +689,16 @@ push_replacement_text (pfile, node) { size_t len; const uchar *text; + uchar *buf; if (node->flags & NODE_BUILTIN) { text = _cpp_builtin_macro_text (pfile, node); len = ustrlen (text); + buf = _cpp_unaligned_alloc (pfile, len + 1); + memcpy (buf, text, len); + buf[len]='\n'; + text = buf; } else { @@ -944,7 +851,7 @@ replace_args_and_push (pfile, fmacro) exp += BLOCK_LEN (b->text_len); } - /* Allocate room for the expansion plus NUL. */ + /* Allocate room for the expansion plus \n. */ buff = _cpp_get_buff (pfile, len + 1); /* Copy the expansion and replace arguments. */ @@ -966,8 +873,8 @@ replace_args_and_push (pfile, fmacro) exp += BLOCK_LEN (b->text_len); } - /* NUL-terminate. */ - *p = '\0'; + /* \n-terminate. */ + *p = '\n'; _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len); /* So we free buffer allocation when macro is left. */ @@ -1034,10 +941,10 @@ save_replacement_text (pfile, macro, arg_index) if (macro->paramc == 0) { /* Object-like and function-like macros without parameters - simply store their NUL-terminated replacement text. */ + simply store their \n-terminated replacement text. */ exp = _cpp_unaligned_alloc (pfile, len + 1); memcpy (exp, pfile->out.base, len); - exp[len] = '\0'; + exp[len] = '\n'; macro->exp.text = exp; macro->count = len; } diff --git a/gcc/fix-header.c b/gcc/fix-header.c index 033019eb849..f76cbd146a0 100644 --- a/gcc/fix-header.c +++ b/gcc/fix-header.c @@ -692,7 +692,7 @@ read_scan_file (in_fname, argc, argv) if (special_file_handling == stdio_h && (fn = lookup_std_proto ("_filbuf", 7)) != NULL) { - static const unsigned char getchar_call[] = "getchar();"; + unsigned char getchar_call[] = "getchar();\n"; int seen_filbuf = 0; /* Scan the macro expansion of "getchar();". */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 99c3b2b12df..fc71e0cf9c3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-04-19 Neil Booth + + * gcc.dg/cpp/_Pragma4.c: Remove stray space. + * gcc.dg/cpp/trad/escaped-eof.c: Correct line number. + 2003-04-18 Eric Botcazou * gcc.c-torture/compile/20030418-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/cpp/_Pragma4.c b/gcc/testsuite/gcc.dg/cpp/_Pragma4.c index a7ac42d4e47..5c86b02c710 100644 --- a/gcc/testsuite/gcc.dg/cpp/_Pragma4.c +++ b/gcc/testsuite/gcc.dg/cpp/_Pragma4.c @@ -7,6 +7,6 @@ a b c /* { dg-final { if ![file exists _Pragma4.i] { return } } } - { dg-final { if { [grep _Pragma4.i "#pragma bar "] != "" } { return } } } + { dg-final { if { [grep _Pragma4.i "#pragma bar"] != "" } { return } } } { dg-final { fail "_Pragma4.c: #pragma appearing on its own line" } } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c b/gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c index 37ca95c6918..2c9c185b1d2 100644 --- a/gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c +++ b/gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c @@ -2,5 +2,5 @@ /* { dg-do preprocess } */ -/* { dg-warning "backslash-new" "escaped EOF warning" { target *-*-* } 7 } */ +/* { dg-warning "backslash-new" "escaped EOF warning" { target *-*-* } 6 } */ \ -- 2.30.2