diff options
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/cpphash.h | 1 | ||||
-rw-r--r-- | gcc/cpplib.c | 17 | ||||
-rw-r--r-- | gcc/cppmain.c | 19 | ||||
-rw-r--r-- | gcc/cpptrad.c | 116 |
5 files changed, 105 insertions, 66 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7c08d424ea8..d5270c8fbf7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2002-06-13 Neil Booth <neil@daikokuya.demon.co.uk> + + * cpphash.h (_cpp_lex_identifier_trad): Remove. + * cpplib.c (end_directive): Don't skip, always remove overlay + apart from #define. + (prepare_directive_trad): Handle NULL pfile->directive. + (_cpp_handle_directive): Always call prepare_directive_trad + if traditional. + * cppmain.c (check_multiline_token): Rename account_for_newlines, + generalize inputs. + (scan_translation_unit_trad): Use it. + * cpptrad.c (skip_comment): Rename copy_comment, copy comment to + output, get escaped newline in comment close correct. + (check_output_buffer, skip_whitespace): Update. + (_cpp_lex_identifier_trad): Remove. + (scan_out_logical_line): Handle -C and comments in directives + properly. + Thu Jun 13 20:18:38 2002 J"orn Rennecke <joern.rennecke@superh.com> * config.gcc: Add support for sh[234]*-*-elf*, sh[2346lbe]*-*-linux*. diff --git a/gcc/cpphash.h b/gcc/cpphash.h index ae6a4f2301d..24b5ef7fccc 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -522,7 +522,6 @@ extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *)); extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *, size_t)); extern void _cpp_remove_overlay PARAMS ((cpp_reader *)); -extern cpp_hashnode *_cpp_lex_identifier_trad PARAMS ((cpp_reader *)); extern void _cpp_set_trad_context PARAMS ((cpp_reader *)); extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *)); extern bool _cpp_expansions_different_trad PARAMS ((const cpp_macro *, diff --git a/gcc/cpplib.c b/gcc/cpplib.c index acc71e7120a..aecfbaf0edd 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -256,14 +256,11 @@ end_directive (pfile, skip_line) { if (CPP_OPTION (pfile, traditional)) { - if (!pfile->directive || pfile->directive == &dtable[T_DEFINE]) - skip_line = false; - else + if (pfile->directive != &dtable[T_DEFINE]) _cpp_remove_overlay (pfile); } - /* We don't skip for an assembler #. */ - if (skip_line) + else if (skip_line) { skip_rest_of_line (pfile); if (!pfile->keep_tokens) @@ -289,7 +286,8 @@ prepare_directive_trad (pfile) CUR (pfile->context) = pfile->buffer->cur; else { - bool no_expand = ! (pfile->directive->flags & EXPAND); + bool no_expand = (pfile->directive + && ! (pfile->directive->flags & EXPAND)); bool was_skipping = pfile->state.skipping; pfile->state.skipping = false; @@ -382,6 +380,10 @@ _cpp_handle_directive (pfile, indented) "style of line directive is a GCC extension"); } + pfile->directive = dir; + if (CPP_OPTION (pfile, traditional)) + prepare_directive_trad (pfile); + if (dir) { /* If we have a directive that is not an opening conditional, @@ -441,9 +443,6 @@ _cpp_handle_directive (pfile, indented) pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments_in_macro_exp); - pfile->directive = dir; - if (CPP_OPTION (pfile, traditional)) - prepare_directive_trad (pfile); (*pfile->directive->handler) (pfile); } else if (skip == 0) diff --git a/gcc/cppmain.c b/gcc/cppmain.c index 0edc3d2b25b..7ebc1ad2c5a 100644 --- a/gcc/cppmain.c +++ b/gcc/cppmain.c @@ -43,7 +43,7 @@ static void setup_callbacks PARAMS ((cpp_reader *)); /* General output routines. */ static void scan_translation_unit PARAMS ((cpp_reader *)); static void scan_translation_unit_trad PARAMS ((cpp_reader *)); -static void check_multiline_token PARAMS ((const cpp_string *)); +static void account_for_newlines PARAMS ((const uchar *, size_t)); static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *)); static void print_line PARAMS ((const struct line_map *, unsigned int, @@ -208,19 +208,18 @@ scan_translation_unit (pfile) cpp_output_token (token, print.outf); if (token->type == CPP_COMMENT) - check_multiline_token (&token->val.str); + account_for_newlines (token->val.str.text, token->val.str.len); } } -/* Adjust print.line for newlines embedded in tokens. */ +/* Adjust print.line for newlines embedded in output. */ static void -check_multiline_token (str) - const cpp_string *str; +account_for_newlines (str, len) + const uchar *str; + size_t len; { - unsigned int i; - - for (i = 0; i < str->len; i++) - if (str->text[i] == '\n') + while (len--) + if (*str++ == '\n') print.line++; } @@ -239,6 +238,8 @@ scan_translation_unit_trad (pfile) maybe_print_line (print.map, pfile->out.first_line); fwrite (pfile->out.base, 1, len, print.outf); print.printed = 1; + if (!CPP_OPTION (pfile, discard_comments)) + account_for_newlines (pfile->out.base, len); } } diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index 03ee0e893a6..4765be2273a 100644 --- a/gcc/cpptrad.c +++ b/gcc/cpptrad.c @@ -22,17 +22,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cpphash.h" /* The replacement text of a function-like macro is stored as a - contiguous sequence of aligned blocks. Each block represents the - portion of text from the start of the previous block (or the start - of the macro replacement text in the case of the first block) to - the next parameter, or the end of the replacement list if there - are none left. - - Each block consists of an unsigned int, which is the length of text - contained in the third part, an unsigned short, which is the + contiguous sequence of aligned blocks, each representing the text + between subsequent parameters in that text. + + Each block comprises the length of text contained therein, the one-based index of the argument that immediately follows that text, and the text itself. The final block in the macro expansion is - recognizable as it has an argument index of zero. */ + easily recognizable as it has an argument index of zero. */ struct block { @@ -67,17 +63,16 @@ struct fun_macro unsigned int argc; }; -/* Lexing TODO: Handle -C, maybe -CC, and space in escaped newlines. - Stop cpplex.c from recognizing comments and directives during its - lexing pass. Get rid of line_base usage - seems pointless? Do we - get escaped newline at EOF correct? */ +/* Lexing TODO: Maybe handle -CC and space in escaped newlines. Stop + cpplex.c from recognizing comments and directives during its lexing + pass. Get rid of line_base usage - seems pointless? */ 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 *)); static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *)); -static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *)); +static const uchar *copy_comment PARAMS ((cpp_reader *, const uchar *)); 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 *)); @@ -99,6 +94,10 @@ check_output_buffer (pfile, n) cpp_reader *pfile; size_t n; { + /* We might need two bytes to terminate an unterminated comment, and + one more to terminate with a NUL. */ + n += 2 + 1; + if (n > (size_t) (pfile->out.limit - pfile->out.cur)) { size_t size = pfile->out.cur - pfile->out.base; @@ -134,45 +133,70 @@ skip_escaped_newlines (pfile, cur) cpp_reader *pfile; const uchar *cur; { - while (*cur == '\\' && is_vspace (cur[1])) - cur = handle_newline (pfile, cur + 1); + if (*cur == '\\' && is_vspace (cur[1])) + { + do + cur = handle_newline (pfile, cur + 1); + while (*cur == '\\' && is_vspace (cur[1])); + + if (cur == RLIMIT (pfile->context)) + cpp_error (pfile, DL_PEDWARN, + "backslash-newline at end of file"); + } return cur; } /* CUR points to the character after the asterisk introducing a - comment. Returns the position after the comment. */ + comment in the input buffer. The remaining comment is copied to + the buffer pointed to by pfile->out.cur, which must be of + sufficient size, and pfile->out.cur is updated. Unterminated + comments are diagnosed, and correctly terminated in the output. + + Returns a pointer to the first character after the comment in the + input buffer. */ static const uchar * -skip_comment (pfile, cur) +copy_comment (pfile, cur) cpp_reader *pfile; const uchar *cur; { unsigned int from_line = pfile->line; - unsigned int c = 0, prevc = 0; const uchar *limit = RLIMIT (pfile->context); + uchar *out = pfile->out.cur; while (cur < limit) { - prevc = c; - c = *cur++; + unsigned int c = *cur++; + *out++ = c; if (c == '/') { - if (prevc == '*') - break; + /* An immediate slash does not terminate the comment. */ + if (out[-2] == '*' && out > pfile->out.cur + 1) + 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); + { + cur = handle_newline (pfile, cur - 1); + /* Canonicalize newline sequences and skip escaped ones. */ + if (out[-2] == '\\') + out -= 2; + else + out[-1] = '\n'; + } } - if (c != '/' || prevc != '*') - cpp_error_with_line (pfile, DL_ERROR, from_line, 0, - "unterminated comment"); + cpp_error_with_line (pfile, DL_ERROR, from_line, 0, "unterminated comment"); + *out++ = '*'; + *out++ = '/'; + done: + pfile->out.cur = out; return cur; } @@ -206,7 +230,7 @@ skip_whitespace (pfile, cur) tmp = skip_escaped_newlines (pfile, cur + 1); if (*tmp == '*') { - cur = skip_comment (pfile, tmp + 1); + cur = copy_comment (pfile, tmp + 1); continue; } } @@ -246,23 +270,6 @@ lex_identifier (pfile, cur) return result; } -/* Reads an identifier, returning its hashnode. If the next token is - not an identifier, returns NULL. */ -cpp_hashnode * -_cpp_lex_identifier_trad (pfile) - cpp_reader *pfile; -{ - const uchar *cur = skip_whitespace (pfile, CUR (pfile->context)); - - if (!is_idstart (*cur)) - { - CUR (pfile->context) = cur; - return NULL; - } - - return lex_identifier (pfile, cur); -} - /* Overlays the true file buffer temporarily with text of length LEN starting at START. The true buffer is restored upon calling restore_buff(). */ @@ -381,7 +388,7 @@ scan_out_logical_line (pfile, macro) { cpp_context *context; const uchar *cur; - unsigned int c, paren_depth, quote = 0; + unsigned int c, paren_depth = 0, quote = 0; uchar *out; struct fun_macro fmacro; @@ -466,7 +473,22 @@ scan_out_logical_line (pfile, macro) { cur = skip_escaped_newlines (pfile, cur); if (*cur == '*') - out--, cur = skip_comment (pfile, cur + 1); + { + *out = '*'; + pfile->out.cur = out + 1; + cur = copy_comment (pfile, cur + 1); + + /* Comments in directives become spaces so that + tokens are properly separated when the ISO + preprocessor re-lexes the line. The exception + is #define. */ + if (pfile->state.in_directive && !macro) + out[-1] = ' '; + else if (CPP_OPTION (pfile, discard_comments)) + out -= 1; + else + out = pfile->out.cur; + } } break; |