diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 041abc3fff6..11e30c7968b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,57 @@ +2000-04-14 Zack Weinberg + + * cpplex.c (cpp_output_tokens, cpp_scan_buffer_nooutput): New public + interfaces. + (safe_fwrite, output_line_command): New static functions. + (cpp_expand_to_buffer): Now private to cpplib. + (cpp_scan_buffer): Take a printer. + + * cpphash.h: Update prototypes. + * cpplib.h: Update prototypes. + (cpp_printer): New. + (cpp_buffer): Remove last_nominal_fname. + (cpp_reader): Remove lineno. + + * cppmain.c: Use a cpp_printer. + * fix-header.c: No need to inhibit line commands. Call + cpp_start_read with no printer. + + * cpperror.c (cpp_notice_from_errno): Provide default name. + * cppfiles.c (make_IHASH, _cpp_fake_ihash): New functions. + (find_include_file, cpp_read_file): Use make_IHASH. + (file_cleanup): Set control_macro and clear + input_stack_listing_current here. + (_cpp_execute_include): Don't output entering-file marker. + * cpphash.c (special_symbol): Look for the line number in the + buffer, not the reader. + (_cpp_macroexpand): No need to disable line commands. + (_cpp_dump_definition): No need to generate line commands. + (dump_hash_helper): Remove excess newline from output. + * cppinit.c (dump_special_to_buffer): No need to generate line + commands. + (cpp_printer_init): New. + (cpp_start_read): Take a printer, and start it up if it's not + NULL. No need to generate line commands. + (cpp_finish): Expect no buffers stacked at all. Take a + printer argument, and flush the output buffer if it's not + NULL. + * cpplex.c (_cpp_lex_token): Return EOF if there's no buffer. + Don't put two hashes at the beginning of an assertion. + (cpp_get_token): Don't increment pfile->lineno or emit line + commands here. Return EOF if there's no buffer when we get + EOF. + * cpplib.c (do_define, skip_if_group): + No need to disable line commands. + (_cpp_output_line_command): Delete function. + (do_line): Don't emit line commands here, but set things up so + they will be emitted if necessary. Use _cpp_fake_ihash to + make unique nominal_fnames if necessary. + (do_elif, do_else, _cpp_handle_eof): Call cpp_error_with_line + with 0 for column, not -1. + (_cpp_handle_eof): Don't set the control macro here. Don't + clear input_stack_listing_current here. Don't emit line + commands. + 2000-04-14 Geoff Keating * config/rs6000/sysv4.h (LINK_START_SOLARIS_SPEC): Define to empty diff --git a/gcc/cpperror.c b/gcc/cpperror.c index 0ba2561bdcb..0e8afc4ffa9 100644 --- a/gcc/cpperror.c +++ b/gcc/cpperror.c @@ -440,5 +440,7 @@ cpp_notice_from_errno (pfile, name) cpp_reader *pfile; const char *name; { + if (name[0] == '\0') + name = "stdout"; cpp_notice (pfile, "%s: %s", name, xstrerror (errno)); } diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 2be195aa90c..59ee7c76f03 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -34,6 +34,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *, struct file_name_list *)); +static IHASH *make_IHASH PARAMS ((const char *, const char *, + struct file_name_list *, + unsigned int, IHASH **)); static struct file_name_map *read_name_map PARAMS ((cpp_reader *, const char *)); static char *read_filename_string PARAMS ((int, FILE *)); @@ -154,6 +157,46 @@ cpp_included (pfile, fname) return (ptr != NULL); } +/* Create an IHASH entry and insert it in SLOT. */ +static IHASH * +make_IHASH (name, fname, path, hash, slot) + const char *name, *fname; + struct file_name_list *path; + unsigned int hash; + IHASH **slot; +{ + IHASH *ih; + if (path == ABSOLUTE_PATH) + { + ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name)); + ih->nshort = ih->name; + } + else + { + char *s; + + if ((s = strstr (name, fname)) != NULL) + { + ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name)); + ih->nshort = ih->name + (s - name); + } + else + { + ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name) + + strlen (fname) + 1); + ih->nshort = ih->name + strlen (name) + 1; + strcpy ((char *)ih->nshort, fname); + } + } + strcpy ((char *)ih->name, name); + ih->foundhere = path; + ih->control_macro = NULL; + ih->hash = hash; + ih->next_this_file = *slot; + *slot = ih; + return ih; +} + static int file_cleanup (pbuf, pfile) cpp_buffer *pbuf; @@ -163,6 +206,12 @@ file_cleanup (pbuf, pfile) free ((PTR) pbuf->buf); if (pfile->system_include_depth) pfile->system_include_depth--; + if (pfile->potential_control_macro) + { + pbuf->ihash->control_macro = pfile->potential_control_macro; + pfile->potential_control_macro = 0; + } + pfile->input_stack_listing_current = 0; return 0; } @@ -265,41 +314,34 @@ find_include_file (pfile, fname, search_start, ihash, before) if (f == -1) return -1; - if (path == ABSOLUTE_PATH) - { - ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name)); - ih->nshort = ih->name; - } - else - { - char *s; - - if ((s = strstr (name, fname)) != NULL) - { - ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name)); - ih->nshort = ih->name + (s - name); - } - else - { - ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name) - + strlen (fname) + 1); - ih->nshort = ih->name + strlen (name) + 1; - strcpy ((char *)ih->nshort, fname); - } - } - strcpy ((char *)ih->name, name); - ih->foundhere = path; - ih->control_macro = NULL; - ih->hash = dummy.hash; - - ih->next_this_file = *slot; - *slot = ih; - + ih = make_IHASH (name, fname, path, dummy.hash, slot); *before = 0; *ihash = ih; return f; } +/* Create a dummy IHASH entry for FNAME, and return its name pointer. + This is used by #line. */ +const char * +_cpp_fake_ihash (pfile, fname) + cpp_reader *pfile; + const char *fname; +{ + IHASH *ih, **slot; + IHASH dummy; + + dummy.nshort = fname; + dummy.hash = _cpp_calc_hash (fname, strlen (fname)); + slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files, + (const void *)&dummy, + dummy.hash, 1); + if (*slot) + return (*slot)->name; + ih = make_IHASH (fname, 0, ABSOLUTE_PATH, dummy.hash, slot); + return ih->name; +} + + /* The file_name_map structure holds a mapping of file names for a particular directory. This mapping is read from the file named FILE_NAME_MAP_FILE in that directory. Such a file can be used to @@ -594,14 +636,12 @@ _cpp_execute_include (pfile, fname, len, no_reinclude, search_start) fprintf (stderr, " %s\n", ihash->name); } - /* Actually process the file */ - + /* Actually process the file. */ if (no_reinclude) ihash->control_macro = (const U_CHAR *) ""; if (read_include_file (pfile, fd, ihash)) { - _cpp_output_line_command (pfile, enter_file); if (angle_brackets) pfile->system_include_depth++; /* Decremented in file_cleanup. */ } @@ -637,17 +677,7 @@ cpp_read_file (pfile, fname) return 1; /* Already included. */ } else - { - ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (fname)); - ih->control_macro = 0; - ih->foundhere = ABSOLUTE_PATH; /* well sort of ... */ - ih->hash = dummy.hash; - strcpy ((char *)ih->name, fname); - ih->nshort = ih->name; - - ih->next_this_file = *slot; - *slot = ih; - } + ih = make_IHASH (fname, 0, ABSOLUTE_PATH, dummy.hash, slot); if (*fname == '\0') f = 0; diff --git a/gcc/cpphash.c b/gcc/cpphash.c index e9d20b372f7..bead2140c06 100644 --- a/gcc/cpphash.c +++ b/gcc/cpphash.c @@ -911,7 +911,7 @@ special_symbol (hp, pfile) case T_SPECLINE: ip = cpp_file_buffer (pfile); CPP_RESERVE (pfile, 10); - sprintf (CPP_PWRITTEN (pfile), "%u", CPP_BUF_LINE (pfile)); + sprintf (CPP_PWRITTEN (pfile), "%u", CPP_BUF_LINE (ip)); CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile))); return; @@ -1025,7 +1025,6 @@ _cpp_macroexpand (pfile, hp) /* Skip over the opening parenthesis. */ CPP_OPTION (pfile, discard_comments)++; - CPP_OPTION (pfile, no_line_commands)++; pfile->no_macro_expand++; pfile->no_directives++; @@ -1058,7 +1057,6 @@ _cpp_macroexpand (pfile, hp) } while (token == CPP_COMMA); CPP_OPTION (pfile, discard_comments)--; - CPP_OPTION (pfile, no_line_commands)--; pfile->no_macro_expand--; pfile->no_directives--; if (token != CPP_RPAREN) @@ -1221,9 +1219,9 @@ _cpp_macroexpand (pfile, hp) if (args[ap->argno].expand_length < 0) { args[ap->argno].expanded = CPP_WRITTEN (pfile); - cpp_expand_to_buffer (pfile, - ARG_BASE + args[ap->argno].raw, - args[ap->argno].raw_length); + _cpp_expand_to_buffer (pfile, + ARG_BASE + args[ap->argno].raw, + args[ap->argno].raw_length); args[ap->argno].expand_length = CPP_WRITTEN (pfile) - args[ap->argno].expanded; @@ -1611,9 +1609,6 @@ _cpp_dump_definition (pfile, sym, len, defn) long len; DEFINITION *defn; { - if (pfile->lineno == 0) - _cpp_output_line_command (pfile, same_file); - CPP_RESERVE (pfile, len + sizeof "#define "); CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1); CPP_PUTS_Q (pfile, sym, len); @@ -1691,7 +1686,7 @@ _cpp_dump_definition (pfile, sym, len, defn) if (*x == '\r') x += 2, i -= 2; if (i > 0) CPP_PUTS (pfile, x, i); } - if (pfile->lineno == 0) + if (CPP_BUFFER (pfile) == 0 || ! pfile->done_initializing) CPP_PUTC (pfile, '\n'); CPP_NUL_TERMINATE (pfile); } @@ -1706,10 +1701,7 @@ dump_hash_helper (h, p) cpp_reader *pfile = (cpp_reader *)p; if (hp->type == T_MACRO) - { - _cpp_dump_definition (pfile, hp->name, hp->length, hp->value.defn); - CPP_PUTC (pfile, '\n'); - } + _cpp_dump_definition (pfile, hp->name, hp->length, hp->value.defn); return 1; } diff --git a/gcc/cpphash.h b/gcc/cpphash.h index a23aa87fc22..99e45fb0c71 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -263,9 +263,6 @@ extern unsigned char _cpp_IStable[256]; #define ADJACENT_TO_MARK(PFILE) \ (CPP_BUFFER(PFILE)->cur - CPP_BUFFER(PFILE)->mark == 1) -/* Last arg to output_line_command. */ -enum file_change_code {same_file, rename_file, enter_file, leave_file}; - /* In cpphash.c */ extern HASHNODE *_cpp_make_hashnode PARAMS ((const U_CHAR *, size_t, enum node_type, @@ -293,6 +290,7 @@ extern void _cpp_execute_include PARAMS ((cpp_reader *, char *, unsigned int, int, struct file_name_list *)); extern void _cpp_init_include_hash PARAMS ((cpp_reader *)); +extern const char *_cpp_fake_ihash PARAMS ((cpp_reader *, const char *)); /* In cppexp.c */ extern int _cpp_parse_expr PARAMS ((cpp_reader *)); @@ -301,6 +299,8 @@ extern int _cpp_parse_expr PARAMS ((cpp_reader *)); extern void _cpp_parse_name PARAMS ((cpp_reader *, int)); extern void _cpp_skip_rest_of_line PARAMS ((cpp_reader *)); extern void _cpp_skip_hspace PARAMS ((cpp_reader *)); +extern void _cpp_expand_to_buffer PARAMS ((cpp_reader *, + const unsigned char *, int)); extern int _cpp_parse_assertion PARAMS ((cpp_reader *)); extern enum cpp_ttype _cpp_lex_token PARAMS ((cpp_reader *)); extern long _cpp_read_and_prescan PARAMS ((cpp_reader *, cpp_buffer *, @@ -315,8 +315,5 @@ extern enum cpp_ttype _cpp_get_define_token /* In cpplib.c */ extern int _cpp_handle_directive PARAMS ((cpp_reader *)); extern void _cpp_handle_eof PARAMS ((cpp_reader *)); -extern void _cpp_output_line_command PARAMS ((cpp_reader *, - enum file_change_code)); - #endif diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 32293f6d27f..5174da8d5bf 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -521,12 +521,11 @@ dump_special_to_buffer (pfile, macro_name) { static const char define_directive[] = "#define "; int macro_name_length = strlen (macro_name); - _cpp_output_line_command (pfile, same_file); CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length); CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1); CPP_PUTS_Q (pfile, macro_name, macro_name_length); CPP_PUTC_Q (pfile, ' '); - cpp_expand_to_buffer (pfile, macro_name, macro_name_length); + _cpp_expand_to_buffer (pfile, macro_name, macro_name_length); CPP_PUTC (pfile, '\n'); } @@ -554,6 +553,31 @@ cpp_reader_init (pfile) _cpp_init_include_hash (pfile); } +/* Initialize a cpp_printer structure. As a side effect, open the + output file. */ +cpp_printer * +cpp_printer_init (pfile, print) + cpp_reader *pfile; + cpp_printer *print; +{ + memset (print, '\0', sizeof (cpp_printer)); + if (CPP_OPTION (pfile, out_fname) == NULL) + CPP_OPTION (pfile, out_fname) = ""; + + if (CPP_OPTION (pfile, out_fname)[0] == '\0') + print->outf = stdout; + else + { + print->outf = fopen (CPP_OPTION (pfile, out_fname), "w"); + if (! print->outf) + { + cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); + return NULL; + } + } + return print; +} + /* Free resources used by PFILE. This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology). */ void @@ -829,8 +853,9 @@ initialize_standard_includes (pfile) */ int -cpp_start_read (pfile, fname) +cpp_start_read (pfile, print, fname) cpp_reader *pfile; + cpp_printer *print; const char *fname; { struct pending_option *p, *q; @@ -915,6 +940,14 @@ cpp_start_read (pfile, fname) CPP_BUFFER (pfile)->lineno = 0; + if (print) + { + print->lineno = 0; + print->last_fname = CPP_BUFFER (pfile)->nominal_fname; + print->last_bsd = pfile->buffer_stack_depth; + print->written = CPP_WRITTEN (pfile); + } + /* Install __LINE__, etc. */ initialize_builtins (pfile); @@ -927,42 +960,32 @@ cpp_start_read (pfile, fname) free (p); p = q; } - pfile->done_initializing = 1; - CPP_BUFFER (pfile)->lineno = 1; - - if (CPP_OPTION (pfile, preprocessed)) - /* If we've already processed this code, we want to trust the #line - directives in the input. But we still need to update our line - counter accordingly. */ - pfile->lineno = CPP_BUFFER (pfile)->lineno; - else - _cpp_output_line_command (pfile, same_file); pfile->only_seen_white = 2; + CPP_BUFFER (pfile)->lineno = 1; + if (print && ! CPP_OPTION (pfile, no_output)) + cpp_output_tokens (pfile, print); /* The -imacros files can be scanned now, but the -include files have to be pushed onto the include stack and processed later, in the main loop calling cpp_get_token. */ - CPP_OPTION (pfile, no_output)++; p = CPP_OPTION (pfile, pending)->imacros_head; while (p) { if (cpp_read_file (pfile, p->arg)) - cpp_scan_buffer (pfile); - + cpp_scan_buffer_nooutput (pfile); q = p->next; free (p); p = q; } - CPP_OPTION (pfile, no_output)--; p = CPP_OPTION (pfile, pending)->include_head; while (p) { - if (cpp_read_file (pfile, p->arg)) - _cpp_output_line_command (pfile, enter_file); - + if (cpp_read_file (pfile, p->arg) + && print && ! CPP_OPTION (pfile, no_output)) + cpp_output_tokens (pfile, print); q = p->next; free (p); p = q; @@ -979,13 +1002,16 @@ cpp_start_read (pfile, fname) clear macro definitions, such that you could call cpp_start_read with a new filename to restart processing. */ void -cpp_finish (pfile) +cpp_finish (pfile, print) cpp_reader *pfile; + cpp_printer *print; { - if (CPP_PREV_BUFFER (CPP_BUFFER (pfile))) - cpp_ice (pfile, "buffers still stacked in cpp_finish"); - while (CPP_BUFFER (pfile)) - cpp_pop_buffer (pfile); + if (CPP_BUFFER (pfile)) + { + cpp_ice (pfile, "buffers still stacked in cpp_finish"); + while (CPP_BUFFER (pfile)) + cpp_pop_buffer (pfile); + } /* Don't write the deps file if preprocessing has failed. */ if (CPP_OPTION (pfile, print_deps) && pfile->errors == 0) @@ -1015,6 +1041,14 @@ cpp_finish (pfile) if (CPP_OPTION (pfile, dump_macros) == dump_only) _cpp_dump_macro_hash (pfile); + + /* Flush any pending output. */ + if (print) + { + cpp_output_tokens (pfile, print); + if (ferror (print->outf) || fclose (print->outf)) + cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); + } } static void diff --git a/gcc/cpplex.c b/gcc/cpplex.c index ccf1302c309..08133595a71 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. */ - -void -cpp_scan_buffer (pfile) +/* 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; { - cpp_buffer *buffer = CPP_BUFFER (pfile); - enum cpp_ttype token; - if (CPP_OPTION (pfile, no_output)) + size_t count; + + while (len) { - long 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) /* 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; - } - } - CPP_SET_WRITTEN (pfile, old_written); - } - else - { - for (;;) - { - 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; - } - } + 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)); } -/* - * 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. - */ +/* 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; +{ + 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 + { + if (pfile->buffer_stack_depth == print->last_bsd) + change = rname; + else + { + if (pfile->buffer_stack_depth > print->last_bsd) + change = enter; + else + change = leave; + print->last_bsd = pfile->buffer_stack_depth; + } + print->last_fname = ip->nominal_fname; + } + /* 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) + { + while (line > print->lineno) + { + 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_expand_to_buffer (pfile, buf, length) +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); +} + +/* 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_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; } diff --git a/gcc/cpplib.c b/gcc/cpplib.c index 2ad02883919..3549bed8f74 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -352,7 +352,6 @@ do_define (pfile) pfile->no_macro_expand++; pfile->parsing_define_directive++; CPP_OPTION (pfile, discard_comments)++; - CPP_OPTION (pfile, no_line_commands)++; here = CPP_WRITTEN (pfile); len = get_macro_name (pfile); @@ -453,85 +452,9 @@ do_define (pfile) pfile->no_macro_expand--; pfile->parsing_define_directive--; CPP_OPTION (pfile, discard_comments)--; - CPP_OPTION (pfile, no_line_commands)--; return 0; } -/* - * write out a #line command, for instance, after an #include file. - * FILE_CHANGE says whether we are entering a file, leaving, or neither. - */ - -void -_cpp_output_line_command (pfile, file_change) - cpp_reader *pfile; - enum file_change_code file_change; -{ - unsigned int line; - cpp_buffer *ip; - - if (CPP_OPTION (pfile, no_line_commands) - || CPP_OPTION (pfile, no_output)) - return; - - ip = cpp_file_buffer (pfile); - line = ip->lineno; - - /* If the current file has not changed, we omit the #line if it would - appear to be a no-op, and we output a few newlines instead - if we want to increase the line number by a small amount. - We cannot do this if pfile->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 (file_change == same_file && pfile->lineno != 0) - { - if (line == pfile->lineno) - return; - - /* If the inherited line number is a little too small, - output some newlines instead of a #line command. */ - if (line > pfile->lineno && line < pfile->lineno + 8) - { - CPP_RESERVE (pfile, 20); - while (line > pfile->lineno) - { - CPP_PUTC_Q (pfile, '\n'); - pfile->lineno++; - } - return; - } - } - - CPP_RESERVE (pfile, 4 * strlen (ip->nominal_fname) + 50); - CPP_PUTS_Q (pfile, "# ", 2); - - sprintf ((char *) CPP_PWRITTEN (pfile), "%u ", line); - CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile))); - - _cpp_quote_string (pfile, ip->nominal_fname); - if (file_change != same_file && file_change != rename_file) - { - CPP_PUTC_Q (pfile, ' '); - CPP_PUTC_Q (pfile, file_change == enter_file ? '1' : '2'); - } - /* Tell cc1 if following text comes from a system header file. */ - if (ip->system_header_p) - { - CPP_PUTC_Q (pfile, ' '); - CPP_PUTC_Q (pfile, '3'); - } -#ifndef NO_IMPLICIT_EXTERN_C - /* Tell cc1plus if following text should be treated as C. */ - if (ip->system_header_p == 2 && CPP_OPTION (pfile, cplusplus)) - { - CPP_PUTC_Q (pfile, ' '); - CPP_PUTC_Q (pfile, '4'); - } -#endif - CPP_PUTC_Q (pfile, '\n'); - pfile->lineno = line; -} - /* Handle #include and #import. */ static unsigned int @@ -713,9 +636,8 @@ do_line (pfile) cpp_reader *pfile; { cpp_buffer *ip = CPP_BUFFER (pfile); - int new_lineno; + unsigned int new_lineno; long old_written = CPP_WRITTEN (pfile); - enum file_change_code file_change = same_file; enum cpp_ttype token; char *x; @@ -727,7 +649,7 @@ do_line (pfile) goto bad_line_directive; } - new_lineno = strtol (pfile->token_buffer + old_written, &x, 10); + new_lineno = strtoul (pfile->token_buffer + old_written, &x, 10); if (x[0] != '\0') { cpp_error (pfile, "token after `#line' is not an integer"); @@ -746,21 +668,22 @@ do_line (pfile) U_CHAR *end_name = CPP_PWRITTEN (pfile) - 1; int action_number = 0; - file_change = rename_file; - if (read_line_number (pfile, &action_number)) { if (CPP_PEDANTIC (pfile)) cpp_pedwarn (pfile, "garbage at end of `#line' command"); + /* This is somewhat questionable: change the buffer stack + depth so that output_line_command thinks we've stacked + another buffer. */ if (action_number == 1) { - file_change = enter_file; + pfile->buffer_stack_depth++; read_line_number (pfile, &action_number); } else if (action_number == 2) { - file_change = leave_file; + pfile->buffer_stack_depth--; read_line_number (pfile, &action_number); } if (action_number == 3) @@ -779,29 +702,11 @@ do_line (pfile) if (strcmp (fname, ip->nominal_fname)) { - const char *newname, *oldname; if (!strcmp (fname, ip->ihash->name)) - newname = ip->ihash->name; - else if (ip->last_nominal_fname - && !strcmp (fname, ip->last_nominal_fname)) - newname = ip->last_nominal_fname; + ip->nominal_fname = ip->ihash->name; else - newname = xstrdup (fname); - - oldname = ip->nominal_fname; - ip->nominal_fname = newname; - - if (ip->last_nominal_fname - && ip->last_nominal_fname != oldname - && ip->last_nominal_fname != newname - && ip->last_nominal_fname != ip->ihash->name) - free ((void *) ip->last_nominal_fname); - - if (newname == ip->ihash->name) - ip->last_nominal_fname = NULL; - else - ip->last_nominal_fname = oldname; - } + ip->nominal_fname = _cpp_fake_ihash (pfile, fname); + } } else if (token != CPP_VSPACE && token != CPP_EOF) { @@ -814,7 +719,6 @@ do_line (pfile) we must store a line number now that is one less. */ ip->lineno = new_lineno - 1; CPP_SET_WRITTEN (pfile, old_written); - _cpp_output_line_command (pfile, file_change); return 0; bad_line_directive: @@ -1259,7 +1163,7 @@ do_elif (pfile) if (pfile->if_stack->type == T_ELSE) { cpp_error (pfile, "`#elif' after `#else'"); - cpp_error_with_line (pfile, pfile->if_stack->lineno, -1, + cpp_error_with_line (pfile, pfile->if_stack->lineno, 0, "the conditional began here"); } pfile->if_stack->type = T_ELIF; @@ -1506,7 +1410,6 @@ skip_if_group (pfile) old_written = CPP_WRITTEN (pfile); pfile->no_macro_expand++; - CPP_OPTION (pfile, no_line_commands)++; for (;;) { /* We are at the end of a line. Only cpp_get_token knows how to @@ -1514,7 +1417,6 @@ skip_if_group (pfile) token = cpp_get_token (pfile); if (token == CPP_POP) break; /* Caller will issue error. */ - else if (token != CPP_VSPACE) cpp_ice (pfile, "cpp_get_token returned %d in skip_if_group", token); CPP_SET_WRITTEN (pfile, old_written); @@ -1533,7 +1435,6 @@ skip_if_group (pfile) } CPP_SET_WRITTEN (pfile, old_written); pfile->no_macro_expand--; - CPP_OPTION (pfile, no_line_commands)--; return ret; } @@ -1565,7 +1466,7 @@ do_else (pfile) if (pfile->if_stack->type == T_ELSE) { cpp_error (pfile, "`#else' after `#else'"); - cpp_error_with_line (pfile, pfile->if_stack->lineno, -1, + cpp_error_with_line (pfile, pfile->if_stack->lineno, 0, "the conditional began here"); } pfile->if_stack->type = T_ELSE; @@ -1628,7 +1529,6 @@ void _cpp_handle_eof (pfile) cpp_reader *pfile; { - cpp_buffer *next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile)); struct if_stack *ifs, *nifs; /* Unwind the conditional stack and generate error messages. */ @@ -1636,7 +1536,7 @@ _cpp_handle_eof (pfile) ifs != CPP_BUFFER (pfile)->if_stack; ifs = nifs) { - cpp_error_with_line (pfile, ifs->lineno, -1, + cpp_error_with_line (pfile, ifs->lineno, 0, "unterminated `#%s' conditional", dtable[ifs->type].name); @@ -1644,26 +1544,6 @@ _cpp_handle_eof (pfile) free (ifs); } pfile->if_stack = ifs; - - if (pfile->potential_control_macro) - { - CPP_BUFFER (pfile)->ihash->control_macro - = pfile->potential_control_macro; - pfile->potential_control_macro = 0; - } - - if (CPP_BUFFER (pfile)->nominal_fname && next_buf != NULL) - { - /* We're about to return from an #include file. - Emit #line information now (as part of the CPP_POP) result. - But the #line refers to the file we will pop to. */ - cpp_buffer *cur_buffer = CPP_BUFFER (pfile); - CPP_BUFFER (pfile) = next_buf; - pfile->input_stack_listing_current = 0; - _cpp_output_line_command (pfile, leave_file); - CPP_BUFFER (pfile) = cur_buffer; - } - CPP_BUFFER (pfile)->seen_eof = 1; } diff --git a/gcc/cpplib.h b/gcc/cpplib.h index 1465349698f..366196d686a 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -31,6 +31,7 @@ extern "C" { typedef struct cpp_reader cpp_reader; typedef struct cpp_buffer cpp_buffer; typedef struct cpp_options cpp_options; +typedef struct cpp_printer cpp_printer; enum cpp_ttype { @@ -74,8 +75,6 @@ struct cpp_buffer /* Filename specified with #line command. */ const char *nominal_fname; - /* Last filename specified with #line command. */ - const char *last_nominal_fname; /* Actual directory of this file, used only for "" includes */ struct file_name_list *actual_dir; @@ -98,6 +97,8 @@ struct cpp_buffer /* True if this is a header file included using . */ char system_header_p; + + /* True if end-of-file has already been hit once in this buffer. */ char seen_eof; /* True if buffer contains escape sequences. @@ -352,8 +353,6 @@ struct cpp_reader struct if_stack *if_stack; const unsigned char *potential_control_macro; - unsigned int lineno; - /* Buffer of -M output. */ struct deps *deps; @@ -402,6 +401,19 @@ struct cpp_reader unsigned char done_initializing; }; +/* struct cpp_printer encapsulates state used to convert the stream of + tokens coming from cpp_get_token back into a text file. Not + everyone wants to do that, hence we separate the function. */ + +struct cpp_printer +{ + FILE *outf; /* stream to write to */ + const char *last_fname; /* previous file name */ + unsigned int last_bsd; /* did we just push? */ + unsigned int lineno; /* line currently being written */ + unsigned int written; /* low water mark in token buffer */ +}; + #define CPP_FATAL_LIMIT 1000 /* True if we have seen a "fatal" error. */ #define CPP_FATAL_ERRORS(READER) ((READER)->errors >= CPP_FATAL_LIMIT) @@ -427,9 +439,11 @@ extern enum cpp_ttype cpp_get_token PARAMS ((cpp_reader *)); extern enum cpp_ttype cpp_get_non_space_token PARAMS ((cpp_reader *)); extern void cpp_reader_init PARAMS ((cpp_reader *)); -extern int cpp_start_read PARAMS ((cpp_reader *, const char *)); -extern void cpp_finish PARAMS ((cpp_reader *)); -extern void cpp_cleanup PARAMS ((cpp_reader *PFILE)); +extern cpp_printer *cpp_printer_init PARAMS ((cpp_reader *, cpp_printer *)); +extern int cpp_start_read PARAMS ((cpp_reader *, cpp_printer *, const char *)); +extern void cpp_output_tokens PARAMS ((cpp_reader *, cpp_printer *)); +extern void cpp_finish PARAMS ((cpp_reader *, cpp_printer *)); +extern void cpp_cleanup PARAMS ((cpp_reader *)); extern cpp_buffer *cpp_file_buffer PARAMS((cpp_reader *)); extern void cpp_define PARAMS ((cpp_reader *, const char *)); @@ -463,17 +477,19 @@ extern void cpp_pedwarn_with_line PARAMS ((cpp_reader *, int, int, const char *m ATTRIBUTE_PRINTF_4; extern void cpp_pedwarn_with_file_and_line PARAMS ((cpp_reader *, const char *, int, int, const char *msgid, ...)) ATTRIBUTE_PRINTF_5; -extern void cpp_error_from_errno PARAMS ((cpp_reader *, const char *)); -extern void cpp_notice_from_errno PARAMS ((cpp_reader *, const char *)); +extern void cpp_error_from_errno PARAMS ((cpp_reader *, const char *)); +extern void cpp_notice_from_errno PARAMS ((cpp_reader *, const char *)); -extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *, - const unsigned char *, long)); -extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *)); -extern int cpp_defined PARAMS ((cpp_reader *, const unsigned char *, int)); +/* In cpplex.c */ +extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *, + const unsigned char *, long)); +extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *)); +extern void cpp_scan_buffer PARAMS ((cpp_reader *, cpp_printer *)); +extern void cpp_scan_buffer_nooutput PARAMS ((cpp_reader *)); -extern void cpp_expand_to_buffer PARAMS ((cpp_reader *, +/* In cpphash.c */ +extern int cpp_defined PARAMS ((cpp_reader *, const unsigned char *, int)); -extern void cpp_scan_buffer PARAMS ((cpp_reader *)); /* In cppfiles.c */ extern int cpp_included PARAMS ((cpp_reader *, const char *)); diff --git a/gcc/cppmain.c b/gcc/cppmain.c index 2e85ebfb722..ef636cbe025 100644 --- a/gcc/cppmain.c +++ b/gcc/cppmain.c @@ -28,6 +28,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. const char *progname; cpp_reader parse_in; +cpp_printer parse_out; extern int main PARAMS ((int, char **)); @@ -38,10 +39,8 @@ main (argc, argv) { char *p; cpp_reader *pfile = &parse_in; + cpp_printer *print; int argi = 1; /* Next argument to handle. */ - enum cpp_ttype kind; - FILE *out; - const char *out_fname; p = argv[0] + strlen (argv[0]); while (p != argv[0] && p[-1] != '/') --p; @@ -63,64 +62,24 @@ main (argc, argv) if (CPP_FATAL_ERRORS (pfile)) return (FATAL_EXIT_CODE); - if (! cpp_start_read (pfile, CPP_OPTION (pfile, in_fname))) + /* Open the output now. We must do so even if no_output is on, + because there may be other output than from the actual + preprocessing (e.g. from -dM). */ + print = cpp_printer_init (pfile, &parse_out); + if (! print) return (FATAL_EXIT_CODE); - /* Now that we know the input file is valid, open the output. */ - out_fname = CPP_OPTION (pfile, out_fname); - if (*out_fname == '\0') - { - out_fname = "stdout"; - out = stdout; - } + if (! cpp_start_read (pfile, print, CPP_OPTION (pfile, in_fname))) + return (FATAL_EXIT_CODE); + + if (CPP_OPTION (pfile, no_output)) + while (CPP_BUFFER (pfile) != NULL) + cpp_scan_buffer_nooutput (pfile); else - { - out = fopen (out_fname, "w"); - if (!out) - { - cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); - return (FATAL_EXIT_CODE); - } - } - - if (! CPP_OPTION (pfile, no_output)) - { - do - { - kind = cpp_get_token (pfile); - if (CPP_WRITTEN (pfile) >= BUFSIZ || kind == CPP_EOF) - { - size_t rem, count = CPP_WRITTEN (pfile); - - rem = fwrite (parse_in.token_buffer, 1, count, out); - if (rem < count) - /* Write error. */ - cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); - - CPP_SET_WRITTEN (pfile, 0); - } - } - while (kind != CPP_EOF); - } - else - { - do - { - cpp_scan_buffer (pfile); - kind = cpp_get_token (pfile); - } - while (kind != CPP_EOF); - CPP_SET_WRITTEN (pfile, 0); - } - - cpp_finish (pfile); - if (fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (pfile), out) - < CPP_WRITTEN (pfile)) - cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); - - if (ferror (out) || fclose (out)) - cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); + while (CPP_BUFFER (pfile) != NULL) + cpp_scan_buffer (pfile, print); + cpp_finish (pfile, print); cpp_cleanup (pfile); if (parse_in.errors) diff --git a/gcc/fix-header.c b/gcc/fix-header.c index 35e74339328..73e7bb6a6b7 100644 --- a/gcc/fix-header.c +++ b/gcc/fix-header.c @@ -628,14 +628,13 @@ read_scan_file (in_fname, argc, argv) so ignore warnings and errors. */ CPP_OPTION (&scan_in, inhibit_warnings) = 1; CPP_OPTION (&scan_in, inhibit_errors) = 1; - CPP_OPTION (&scan_in, no_line_commands) = 1; i = cpp_handle_options (&scan_in, argc, argv); if (i < argc && ! CPP_FATAL_ERRORS (&scan_in)) cpp_fatal (&scan_in, "Invalid option `%s'", argv[i]); if (CPP_FATAL_ERRORS (&scan_in)) exit (FATAL_EXIT_CODE); - if (! cpp_start_read (&scan_in, in_fname)) + if (! cpp_start_read (&scan_in, 0, in_fname)) exit (FATAL_EXIT_CODE); scan_decls (&scan_in, argc, argv);