diff options
Diffstat (limited to 'gcc/cpplex.c')
-rw-r--r-- | gcc/cpplex.c | 257 |
1 files changed, 189 insertions, 68 deletions
diff --git a/gcc/cpplex.c b/gcc/cpplex.c index ccf1302..0813359 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -47,6 +47,10 @@ static U_CHAR *find_position PARAMS ((U_CHAR *, U_CHAR *, unsigned long *)); static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *)); static void null_warning PARAMS ((cpp_reader *, unsigned int)); +static void safe_fwrite PARAMS ((cpp_reader *, const U_CHAR *, + size_t, FILE *)); +static void output_line_command PARAMS ((cpp_reader *, cpp_printer *)); + /* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */ void @@ -116,70 +120,131 @@ cpp_pop_buffer (pfile) return CPP_BUFFER (pfile); } -/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer. - Pop the buffer when done. */ +/* Deal with the annoying semantics of fwrite. */ +static void +safe_fwrite (pfile, buf, len, fp) + cpp_reader *pfile; + const U_CHAR *buf; + size_t len; + FILE *fp; +{ + size_t count; -void -cpp_scan_buffer (pfile) + while (len) + { + count = fwrite (buf, 1, len, fp); + if (count == 0) + goto error; + len -= count; + buf += count; + } + return; + + error: + cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); +} + +/* Notify the compiler proper that the current line number has jumped, + or the current file name has changed. */ + +static void +output_line_command (pfile, print) cpp_reader *pfile; + cpp_printer *print; { - cpp_buffer *buffer = CPP_BUFFER (pfile); - enum cpp_ttype token; - if (CPP_OPTION (pfile, no_output)) + unsigned int line; + cpp_buffer *ip; + enum { same = 0, enter, leave, rname } change; + static const char * const codes[] = { "", " 1", " 2", "" }; + + if (CPP_OPTION (pfile, no_line_commands)) + return; + + ip = cpp_file_buffer (pfile); + if (ip == NULL) + return; + line = CPP_BUF_LINE (ip); + + // fprintf (print->outf, "[%u %u", print->lineno, line); + + /* Determine whether the current filename has changed, and if so, + how. 'nominal_fname' values are unique, so they can be compared + by comparing pointers. */ + if (ip->nominal_fname == print->last_fname) + change = same; + else { - long old_written = CPP_WRITTEN (pfile); - /* In no-output mode, we can ignore everything but directives. */ - for (;;) + if (pfile->buffer_stack_depth == print->last_bsd) + change = rname; + else { - if (! pfile->only_seen_white) - _cpp_skip_rest_of_line (pfile); - token = cpp_get_token (pfile); - if (token == CPP_EOF) /* Should not happen ... */ - break; - if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) - { - if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL) - cpp_pop_buffer (pfile); - break; - } + if (pfile->buffer_stack_depth > print->last_bsd) + change = enter; + else + change = leave; + print->last_bsd = pfile->buffer_stack_depth; } - CPP_SET_WRITTEN (pfile, old_written); + print->last_fname = ip->nominal_fname; } - else + /* If the current file has not changed, we can output a few newlines + instead if we want to increase the line number by a small amount. + We cannot do this if print->lineno is zero, because that means we + haven't output any line commands yet. (The very first line + command output is a `same_file' command.) */ + if (change == same && print->lineno != 0 + && line >= print->lineno && line < print->lineno + 8) { - for (;;) + while (line > print->lineno) { - token = cpp_get_token (pfile); - if (token == CPP_EOF) /* Should not happen ... */ - break; - if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) - { - if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL) - cpp_pop_buffer (pfile); - break; - } + putc ('\n', print->outf); + print->lineno++; } + // putc(']', print->outf); + return; } + +#ifndef NO_IMPLICIT_EXTERN_C + if (CPP_OPTION (pfile, cplusplus)) + fprintf (print->outf, "# %u \"%s\"%s%s%s\n", line, ip->nominal_fname, + codes[change], + ip->system_header_p ? " 3" : "", + (ip->system_header_p == 2) ? " 4" : ""); + else +#endif + fprintf (print->outf, "# %u \"%s\"%s%s\n", line, ip->nominal_fname, + codes[change], + ip->system_header_p ? " 3" : ""); + print->lineno = line; +} + +/* Write the contents of the token_buffer to the output stream, and + clear the token_buffer. Also handles generating line commands and + keeping track of file transitions. */ + +void +cpp_output_tokens (pfile, print) + cpp_reader *pfile; + cpp_printer *print; +{ + if (CPP_PWRITTEN (pfile)[-1] == '\n' && print->lineno) + print->lineno++; + safe_fwrite (pfile, pfile->token_buffer, + CPP_WRITTEN (pfile) - print->written, print->outf); + output_line_command (pfile, print); + CPP_SET_WRITTEN (pfile, print->written); } -/* - * Rescan a string (which may have escape marks) into pfile's buffer. - * Place the result in pfile->token_buffer. - * - * The input is copied before it is scanned, so it is safe to pass - * it something from the token_buffer that will get overwritten - * (because it follows CPP_WRITTEN). This is used by do_include. - */ +/* Scan a string (which may have escape marks), perform macro expansion, + and write the result to the token_buffer. */ void -cpp_expand_to_buffer (pfile, buf, length) +_cpp_expand_to_buffer (pfile, buf, length) cpp_reader *pfile; const U_CHAR *buf; int length; { - register cpp_buffer *ip; - U_CHAR *buf1; - int save_no_output; + cpp_buffer *ip; + enum cpp_ttype token; if (length < 0) { @@ -188,27 +253,85 @@ cpp_expand_to_buffer (pfile, buf, length) } /* Set up the input on the input stack. */ - - buf1 = (U_CHAR *) alloca (length + 1); - memcpy (buf1, buf, length); - buf1[length] = 0; - - ip = cpp_push_buffer (pfile, buf1, length); + ip = cpp_push_buffer (pfile, buf, length); if (ip == NULL) return; ip->has_escapes = 1; /* Scan the input, create the output. */ - save_no_output = CPP_OPTION (pfile, no_output); - CPP_OPTION (pfile, no_output) = 0; - CPP_OPTION (pfile, no_line_commands)++; - cpp_scan_buffer (pfile); - CPP_OPTION (pfile, no_line_commands)--; - CPP_OPTION (pfile, no_output) = save_no_output; - + for (;;) + { + token = cpp_get_token (pfile); + if (token == CPP_EOF) + break; + if (token == CPP_POP && CPP_BUFFER (pfile) == ip) + { + cpp_pop_buffer (pfile); + break; + } + } CPP_NUL_TERMINATE (pfile); } +/* Scan until CPP_BUFFER (PFILE) is exhausted, discarding output. + Then pop the buffer. */ + +void +cpp_scan_buffer_nooutput (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = CPP_BUFFER (pfile); + enum cpp_ttype token; + unsigned int old_written = CPP_WRITTEN (pfile); + /* In no-output mode, we can ignore everything but directives. */ + for (;;) + { + if (! pfile->only_seen_white) + _cpp_skip_rest_of_line (pfile); + token = cpp_get_token (pfile); + if (token == CPP_EOF) + break; + if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) + { + cpp_pop_buffer (pfile); + break; + } + } + CPP_SET_WRITTEN (pfile, old_written); +} + +/* Scan until CPP_BUFFER (pfile) is exhausted, writing output to PRINT. + Then pop the buffer. */ + +void +cpp_scan_buffer (pfile, print) + cpp_reader *pfile; + cpp_printer *print; +{ + cpp_buffer *buffer = CPP_BUFFER (pfile); + enum cpp_ttype token; + + for (;;) + { + token = cpp_get_token (pfile); + if ((token == CPP_POP && !CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) + || token == CPP_EOF || token == CPP_VSPACE + /* XXX Temporary kluge - force flush after #include only */ + || (token == CPP_DIRECTIVE + && CPP_BUFFER (pfile)->nominal_fname != print->last_fname)) + { + cpp_output_tokens (pfile, print); + if (token == CPP_EOF) + return; + if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) + { + cpp_pop_buffer (pfile); + return; + } + } + } +} + /* Return the topmost cpp_buffer that corresponds to a file (not a macro). */ cpp_buffer * @@ -706,6 +829,9 @@ _cpp_lex_token (pfile) register int c, c2; enum cpp_ttype token; + if (CPP_BUFFER (pfile) == NULL) + return CPP_EOF; + get_next: c = GETC(); switch (c) @@ -749,6 +875,7 @@ _cpp_lex_token (pfile) hash: if (pfile->parsing_if_directive) { + CPP_ADJUST_WRITTEN (pfile, -1); if (_cpp_parse_assertion (pfile)) return CPP_ASSERTION; return CPP_OTHER; @@ -1227,12 +1354,6 @@ cpp_get_token (pfile) if (pfile->only_seen_white == 0) pfile->only_seen_white = 1; CPP_BUMP_LINE (pfile); - if (! CPP_OPTION (pfile, no_line_commands)) - { - pfile->lineno++; - if (CPP_BUFFER (pfile)->lineno != pfile->lineno) - _cpp_output_line_command (pfile, same_file); - } return token; case CPP_HSPACE: @@ -1256,15 +1377,15 @@ cpp_get_token (pfile) return CPP_NAME; case CPP_EOF: + if (CPP_BUFFER (pfile) == NULL) + return CPP_EOF; if (CPP_BUFFER (pfile)->manual_pop) /* If we've been reading from redirected input, the frontend will pop the buffer. */ return CPP_EOF; - else if (CPP_BUFFER (pfile)->seen_eof) - { - if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) == NULL) - return CPP_EOF; + if (CPP_BUFFER (pfile)->seen_eof) + { cpp_pop_buffer (pfile); goto get_next; } |