Separating CPP's "reader" and "printer" functionality

Zack Weinberg zack@wolery.cumb.org
Fri Apr 14 16:28:00 GMT 2000


This patch creates a new abstraction, a "printer" structure that
encapsulates all the state needed to go from a stream of preprocessed
tokens back to a text file.  Right now, all this does is stick in line
markers where necessary, but I anticipate it will end up doing a good
bit more.

Adding this structure means we can separate generating that stream
from generating the "intermediate file" which has historically been
the output of cpp.  That in turn means that a user of the library that
doesn't need an intermediate file, doesn't need to do any of that
work.  For example, look at all the places where I was able to remove
code to disable generation of linemarkers.

There's also a one-line bugfix in here for assertions, which were
broken by Jason's digraph patch.

zw

	* 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.


===================================================================
Index: cpperror.c
--- cpperror.c	2000/04/11 08:29:33	1.30
+++ cpperror.c	2000/04/14 23:08:09
@@ -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));
 }
===================================================================
Index: cppfiles.c
--- cppfiles.c	2000/04/06 07:56:14	1.53
+++ cppfiles.c	2000/04/14 23:08:09
@@ -34,6 +34,9 @@ Foundation, 59 Temple Place - Suite 330,
 
 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_
   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,
       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;
===================================================================
Index: cpphash.c
--- cpphash.c	2000/04/11 08:29:33	1.65
+++ cpphash.c	2000/04/14 23:08:09
@@ -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, d
      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, d
       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;
 }
 
===================================================================
Index: cpphash.h
--- cpphash.h	2000/04/11 08:29:33	1.30
+++ cpphash.h	2000/04/14 23:08:10
@@ -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 
 						 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
 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_to
 /* 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
===================================================================
Index: cppinit.c
--- cppinit.c	2000/04/10 03:27:21	1.73
+++ cppinit.c	2000/04/14 23:08:10
@@ -521,12 +521,11 @@ dump_special_to_buffer (pfile, macro_nam
 {
   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
===================================================================
Index: cpplex.c
--- cpplex.c	2000/04/13 08:26:36	1.12
+++ cpplex.c	2000/04/14 23:08:11
@@ -47,6 +47,10 @@ static U_CHAR *find_position	PARAMS ((U_
 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;
 	}
===================================================================
Index: cpplib.c
--- cpplib.c	2000/04/11 08:29:34	1.143
+++ cpplib.c	2000/04/14 23:08:11
@@ -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;
 }
 
===================================================================
Index: cpplib.h
--- cpplib.h	2000/04/11 08:29:34	1.77
+++ cpplib.h	2000/04/14 23:08:11
@@ -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 <FILENAME>.  */
   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 PARA
 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
   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 *));
===================================================================
Index: cppmain.c
--- cppmain.c	2000/04/11 08:29:34	1.25
+++ cppmain.c	2000/04/14 23:08:11
@@ -28,6 +28,7 @@ Foundation, 59 Temple Place - Suite 330,
 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;
-    }
-  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 (! cpp_start_read (pfile, print, CPP_OPTION (pfile, in_fname)))
+    return (FATAL_EXIT_CODE);
 
-  if (ferror (out) || fclose (out))
-    cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname));
+  if (CPP_OPTION (pfile, no_output))
+    while (CPP_BUFFER (pfile) != NULL)
+      cpp_scan_buffer_nooutput (pfile);
+  else
+    while (CPP_BUFFER (pfile) != NULL)
+      cpp_scan_buffer (pfile, print);
 
+  cpp_finish (pfile, print);
   cpp_cleanup (pfile);
 
   if (parse_in.errors)
===================================================================
Index: fix-header.c
--- fix-header.c	2000/04/11 08:29:34	1.40
+++ fix-header.c	2000/04/14 23:08:13
@@ -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);


More information about the Gcc-patches mailing list