This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

cpplib: take FILEs for preprocessed and deps output


This patch is a prerequisite for moving the -M* options out of
cpplib.  cpplib is no longer responsible for opening and closing
its streams; that is the responsibility of the client.  This makes
things cleaner, and solves that annoying testcase in gcc.dg/cpp
that has been failing ever since Jakub put it in.

There's a lot of work to do to finish cleaning up the cpplib
interface in this area; this is basically the minimum necessary
to supply cpplib with FILEs.

I'll apply this when the regtest has finished.

Neil.

	* c-common.c (c_common_init): Call preprocess_file instead.
	(c_common_finish): Move to c-opts.c.
	* c-common.h (preprocess_file): new.
	* c-opts.c (out_fname, out_stream, deps_append, preprocess_file,
	check_deps_environment_vars, c_common_finish): New.
	(c_common_decode_option): Update for out_fname and dependencies.
	* cppinit.c (init_dependency_output, output_deps): Remove.
	(cpp_destroy): Update prototype.
	(cpp_add_dependency_target): New.
	(cpp_read_main_file): Don't overlay a buffer.
	(cpp_finish): Take a deps output stream and write deps to it.
	Return the error count.
	(cpp_post_options): Don't canonicalize out_fname, or do anything
	with dependencies.
	* cpplib.h (struct cpp_options): Remove out_fname and
	preprocess_only.
	(cpp_add_dependency_target): New.
	(cpp_destroy, cpp_finish, cpp_preprocess_file): Update.
	* cppmain.c (cpp_preprocess_file): Update prototype.  Don't
	set preprocess_only.  Don't handle the output stream directly.

============================================================
Index: gcc/c-common.c
--- gcc/c-common.c	10 Aug 2002 02:18:26 -0000	1.363
+++ gcc/c-common.c	11 Aug 2002 20:02:41 -0000
@@ -4914,7 +4914,7 @@ c_common_init (filename)
   /* NULL is passed up to toplev.c and we exit quickly.  */
   if (flag_preprocess_only)
     {
-      cpp_preprocess_file (parse_in);
+      preprocess_file ();
       return NULL;
     }
 
@@ -4928,17 +4928,6 @@ c_common_init (filename)
     c_init_attributes ();
 
   return filename;
-}
-
-/* Common finish hook for the C, ObjC and C++ front ends.  */
-void
-c_common_finish ()
-{
-  cpp_finish (parse_in);
-
-  /* For performance, avoid tearing down cpplib's internal structures.
-     Call cpp_errors () instead of cpp_destroy ().  */
-  errorcount += cpp_errors (parse_in);
 }
 
 static void
============================================================
Index: gcc/c-common.h
--- gcc/c-common.h	11 Aug 2002 07:32:19 -0000	1.150
+++ gcc/c-common.h	11 Aug 2002 20:02:41 -0000
@@ -1209,6 +1209,8 @@ extern int c_common_unsafe_for_reeval		P
 
 extern const char *init_c_lex			PARAMS ((const char *));
 
+extern void preprocess_file			PARAMS ((void));
+
 /* Information recorded about each file examined during compilation.  */
 
 struct c_fileinfo
============================================================
Index: gcc/c-opts.c
--- gcc/c-opts.c	11 Aug 2002 07:32:19 -0000	1.6
+++ gcc/c-opts.c	11 Aug 2002 20:02:41 -0000
@@ -33,6 +33,13 @@ Software Foundation, 59 Temple Place - S
 
 static cpp_options *cpp_opts;
 
+/* Filename and stream for preprocessed output.  */
+static const char *out_fname;
+static FILE *out_stream;
+
+/* Append dependencies to deps_file.  */
+static bool deps_append;
+
 static void missing_arg PARAMS ((size_t));
 static size_t find_opt PARAMS ((const char *, int));
 static void set_Wimplicit PARAMS ((int));
@@ -43,6 +50,7 @@ static void handle_OPT_d PARAMS ((const 
 static void set_std_cxx98 PARAMS ((int));
 static void set_std_c89 PARAMS ((int, int));
 static void set_std_c99 PARAMS ((int));
+static void check_deps_environment_vars PARAMS ((void));
 
 #define CL_C_ONLY	(1 << 0) /* Only C.  */
 #define CL_OBJC_ONLY	(1 << 1) /* Only ObjC.  */
@@ -456,8 +464,8 @@ c_common_decode_option (argc, argv)
     {
       if (!cpp_opts->in_fname)
 	cpp_opts->in_fname = opt;
-      else if (!cpp_opts->out_fname)
-	cpp_opts->out_fname = opt;
+      else if (!out_fname)
+	out_fname = opt;
       else
 	{
 	  error ("too many filenames given.  Type %s --help for usage",
@@ -1110,8 +1118,8 @@ c_common_decode_option (argc, argv)
       break;
 
     case OPT_o:
-      if (!cpp_opts->out_fname)
-	cpp_opts->out_fname = arg;
+      if (!out_fname)
+	out_fname = arg;
       else
 	{
 	  error ("output filename specified twice");
@@ -1196,6 +1204,21 @@ c_common_decode_option (argc, argv)
 bool
 c_common_post_options ()
 {
+  /* Canonicalize the output filename.  */
+  if (out_fname == NULL || !strcmp (out_fname, "-"))
+    out_fname = "";
+
+  if (cpp_opts->print_deps == 0)
+    check_deps_environment_vars ();
+
+  /* If we're not outputting dependencies, complain if other -M
+     options have been given.  */
+  if (cpp_opts->print_deps
+      && (cpp_opts->print_deps_missing_files
+	  || cpp_opts->deps_file
+	  || cpp_opts->deps_phony_targets))
+      error ("you must additionally specify either -M or -MM");
+
   cpp_post_options (parse_in);
 
   flag_inline_trees = 1;
@@ -1239,6 +1262,56 @@ c_common_post_options ()
   return flag_preprocess_only;
 }
 
+/* Preprocess the input file.  */
+void
+preprocess_file ()
+{
+  /* 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).  */
+  if (out_fname[0] == '\0')
+    out_stream = stdout;
+  else
+    out_stream = fopen (out_fname, "w");
+
+  if (out_stream == NULL)
+    fatal_io_error ("opening output file %s", out_fname);
+  else
+    cpp_preprocess_file (parse_in, out_stream);
+}
+
+/* Common finish hook for the C, ObjC and C++ front ends.  */
+void
+c_common_finish ()
+{
+  FILE *deps_stream = NULL;
+
+  if (cpp_opts->print_deps)
+    {
+      /* If -M or -MM was seen without -MF, default output to the
+	 output stream.  */
+      if (!cpp_opts->deps_file)
+	deps_stream = out_stream;
+      else
+	{
+	  deps_stream = fopen (cpp_opts->deps_file, deps_append ? "a": "w");
+	  if (!deps_stream)
+	    fatal_io_error ("opening dependency file %s", cpp_opts->deps_file);
+	}
+    }
+
+  /* For performance, avoid tearing down cpplib's internal structures
+     with cpp_destroy ().  */
+  errorcount += cpp_finish (parse_in, deps_stream);
+
+  if (deps_stream && deps_stream != out_stream
+      && (ferror (deps_stream) || fclose (deps_stream)))
+    fatal_io_error ("closing dependency file %s", cpp_opts->deps_file);
+
+  if (out_stream && (ferror (out_stream) || fclose (out_stream)))
+    fatal_io_error ("when writing output to %s", out_fname);
+}
+
 /* Set the C 89 standard (with 1994 amendments if C94, without GNU
    extensions if ISO).  There is no concept of gnu94.  */
 static void
@@ -1254,6 +1327,46 @@ set_std_c89 (c94, iso)
   flag_isoc94 = c94;
   flag_isoc99 = 0;
   flag_writable_strings = 0;
+}
+
+/* Either of two environment variables can specify output of
+   dependencies.  Their value is either "OUTPUT_FILE" or "OUTPUT_FILE
+   DEPS_TARGET", where OUTPUT_FILE is the file to write deps info to
+   and DEPS_TARGET is the target to mention in the deps.  They also
+   result in dependency information being appended to the output file
+   rather than overwriting it.  */
+static void
+check_deps_environment_vars ()
+{
+  char *spec;
+
+  GET_ENVIRONMENT (spec, "DEPENDENCIES_OUTPUT");
+  if (spec)
+    cpp_opts->print_deps = 1;
+  else
+    {
+      GET_ENVIRONMENT (spec, "SUNPRO_DEPENDENCIES");
+      if (spec)
+	cpp_opts->print_deps = 2;
+    }
+
+  if (spec)
+    {
+      /* Find the space before the DEPS_TARGET, if there is one.  */
+      char *s = strchr (spec, ' ');
+      if (s)
+	{
+	  /* Let the caller perform MAKE quoting.  */
+	  cpp_add_dependency_target (parse_in, s + 1, 0);
+	  *s = '\0';
+	}
+
+      /* Command line -MF overrides environment variables and default.  */
+      if (!cpp_opts->deps_file)
+	cpp_opts->deps_file = spec;
+
+      cpp_opts->print_deps_append = 1;
+    }
 }
 
 /* Set the C 99 standard (without GNU extensions if ISO).  */
============================================================
Index: gcc/cppinit.c
--- gcc/cppinit.c	11 Aug 2002 07:32:19 -0000	1.254
+++ gcc/cppinit.c	11 Aug 2002 20:02:42 -0000
@@ -102,13 +102,11 @@ static void merge_include_chains	PARAMS 
 static bool push_include		PARAMS ((cpp_reader *,
 						 struct pending_option *));
 static void free_chain			PARAMS ((struct pending_option *));
-static void init_dependency_output	PARAMS ((cpp_reader *));
 static void init_standard_includes	PARAMS ((cpp_reader *));
 static void read_original_filename	PARAMS ((cpp_reader *));
 static void new_pending_directive	PARAMS ((struct cpp_pending *,
 						 const char *,
 						 cl_directive_handler));
-static void output_deps			PARAMS ((cpp_reader *));
 static int parse_option			PARAMS ((const char *));
 
 /* Fourth argument to append_include_chain: chain to use.
@@ -537,11 +535,10 @@ cpp_create_reader (lang)
 
 /* Free resources used by PFILE.  Accessing PFILE after this function
    returns leads to undefined behaviour.  Returns the error count.  */
-int
+void
 cpp_destroy (pfile)
      cpp_reader *pfile;
 {
-  int result;
   struct search_path *dir, *dirn;
   cpp_context *context, *contextn;
   tokenrun *run, *runn;
@@ -595,11 +592,7 @@ cpp_destroy (pfile)
     }
 
   free_line_maps (&pfile->line_maps);
-
-  result = pfile->errors;
   free (pfile);
-
-  return result;
 }
 
 /* This structure defines one built-in identifier.  A node will be
@@ -882,6 +875,21 @@ static void sanity_checks (pfile)
 # define sanity_checks(PFILE)
 #endif
 
+/* Add a dependency target.  Can be called any number of times before
+   cpp_read_main_file().  If no targets have been added before
+   cpp_read_main_file(), then the default target is used.  */
+void
+cpp_add_dependency_target (pfile, target, quote)
+     cpp_reader *pfile;
+     const char *target;
+     int quote;
+{
+  if (!pfile->deps)
+    pfile->deps = deps_init ();
+
+  deps_add_target (pfile->deps, target, quote);
+}
+
 /* This is called after options have been parsed, and partially
    processed.  Setup for processing input from the file named FNAME,
    or stdin if it is the empty string.  Return the original filename
@@ -936,10 +944,6 @@ cpp_read_main_file (pfile, fname, table)
      of the front ends.  */
   if (CPP_OPTION (pfile, preprocessed))
     read_original_filename (pfile);
-  /* Overlay an empty buffer to seed traditional preprocessing.  */
-  else if (CPP_OPTION (pfile, traditional)
-	   && !CPP_OPTION (pfile, preprocess_only))
-    _cpp_overlay_buffer (pfile, U"", 0);
 
   return pfile->map->to_file;
 }
@@ -1039,48 +1043,16 @@ _cpp_maybe_push_include_file (pfile)
     }
 }
 
-/* Use mkdeps.c to output dependency information.  */
-static void
-output_deps (pfile)
-     cpp_reader *pfile;
-{
-  /* Stream on which to print the dependency information.  */
-  FILE *deps_stream = 0;
-  const char *const deps_mode =
-    CPP_OPTION (pfile, print_deps_append) ? "a" : "w";
-
-  if (CPP_OPTION (pfile, deps_file)[0] == '\0')
-    deps_stream = stdout;
-  else
-    {
-      deps_stream = fopen (CPP_OPTION (pfile, deps_file), deps_mode);
-      if (deps_stream == 0)
-	{
-	  cpp_errno (pfile, DL_ERROR, CPP_OPTION (pfile, deps_file));
-	  return;
-	}
-    }
-
-  deps_write (pfile->deps, deps_stream, 72);
-
-  if (CPP_OPTION (pfile, deps_phony_targets))
-    deps_phony_targets (pfile->deps, deps_stream);
-
-  /* Don't close stdout.  */
-  if (deps_stream != stdout)
-    {
-      if (ferror (deps_stream) || fclose (deps_stream) != 0)
-	cpp_error (pfile, DL_ERROR, "I/O error on output");
-    }
-}
-
-/* This is called at the end of preprocessing.  It pops the
-   last buffer and writes dependency output.  It should also
-   clear macro definitions, such that you could call cpp_start_read
-   with a new filename to restart processing.  */
-void
-cpp_finish (pfile)
+/* This is called at the end of preprocessing.  It pops the last
+   buffer and writes dependency output, and returns the number of
+   errors.
+ 
+   Maybe it should also reset state, such that you could call
+   cpp_start_read with a new filename to restart processing.  */
+int
+cpp_finish (pfile, deps_stream)
      cpp_reader *pfile;
+     FILE *deps_stream;
 {
   /* Warn about unused macros before popping the final buffer.  */
   if (CPP_OPTION (pfile, warn_unused_macros))
@@ -1094,13 +1066,20 @@ cpp_finish (pfile)
   while (pfile->buffer)
     _cpp_pop_buffer (pfile);
 
-  /* Don't write the deps file if preprocessing has failed.  */
-  if (CPP_OPTION (pfile, print_deps) && pfile->errors == 0)
-    output_deps (pfile);
+  /* Don't write the deps file if there are errors.  */
+  if (deps_stream && CPP_OPTION (pfile, print_deps) && !pfile->errors)
+    {
+      deps_write (pfile->deps, deps_stream, 72);
+
+      if (CPP_OPTION (pfile, deps_phony_targets))
+	deps_phony_targets (pfile->deps, deps_stream);
+    }
 
   /* Report on headers that could use multiple include guards.  */
   if (CPP_OPTION (pfile, print_include_names))
     _cpp_report_missing_guards (pfile);
+
+  return pfile->errors;
 }
 
 /* Add a directive to be handled later in the initialization phase.  */
@@ -1479,10 +1458,6 @@ cpp_post_options (pfile)
       || !strcmp (CPP_OPTION (pfile, in_fname), "-"))
     CPP_OPTION (pfile, in_fname) = "";
 
-  if (CPP_OPTION (pfile, out_fname) == NULL
-      || !strcmp (CPP_OPTION (pfile, out_fname), "-"))
-    CPP_OPTION (pfile, out_fname) = "";
-
   /* -Wtraditional is not useful in C++ mode.  */
   if (CPP_OPTION (pfile, cplusplus))
     CPP_OPTION (pfile, warn_traditional) = 0;
@@ -1518,69 +1493,4 @@ cpp_post_options (pfile)
 	CPP_OPTION (pfile, dump_macros) = dump_none;
       CPP_OPTION (pfile, dump_includes) = 0;
     }
-
-  /* Intialize, and check environment variables for, dependency
-     output.  */
-  init_dependency_output (pfile);
-
-  /* If we're not outputting dependencies, complain if other -M
-     options have been given.  */
-  if (!CPP_OPTION (pfile, print_deps)
-      && (CPP_OPTION (pfile, print_deps_missing_files)
-	  || CPP_OPTION (pfile, deps_file)
-	  || CPP_OPTION (pfile, deps_phony_targets)))
-    cpp_error (pfile, DL_ERROR,
-	       "you must additionally specify either -M or -MM");
-}
-
-/* Set up dependency-file output.  On exit, if print_deps is non-zero
-   then deps_file is not NULL; stdout is the empty string.  */
-static void
-init_dependency_output (pfile)
-     cpp_reader *pfile;
-{
-  char *spec, *s, *output_file;
-
-  /* Either of two environment variables can specify output of deps.
-     Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
-     where OUTPUT_FILE is the file to write deps info to
-     and DEPS_TARGET is the target to mention in the deps.  */
-
-  if (CPP_OPTION (pfile, print_deps) == 0)
-    {
-      spec = getenv ("DEPENDENCIES_OUTPUT");
-      if (spec)
-	CPP_OPTION (pfile, print_deps) = 1;
-      else
-	{
-	  spec = getenv ("SUNPRO_DEPENDENCIES");
-	  if (spec)
-	    CPP_OPTION (pfile, print_deps) = 2;
-	  else
-	    return;
-	}
-
-      /* Find the space before the DEPS_TARGET, if there is one.  */
-      s = strchr (spec, ' ');
-      if (s)
-	{
-	  /* Let the caller perform MAKE quoting.  */
-	  deps_add_target (pfile->deps, s + 1, 0);
-	  output_file = (char *) xmalloc (s - spec + 1);
-	  memcpy (output_file, spec, s - spec);
-	  output_file[s - spec] = 0;
-	}
-      else
-	output_file = spec;
-
-      /* Command line -MF overrides environment variables and default.  */
-      if (CPP_OPTION (pfile, deps_file) == 0)
-	CPP_OPTION (pfile, deps_file) = output_file;
-
-      CPP_OPTION (pfile, print_deps_append) = 1;
-    }
-  else if (CPP_OPTION (pfile, deps_file) == 0)
-    /* If -M or -MM was seen without -MF, default output to wherever
-       was specified with -o.  out_fname is non-NULL here.  */
-    CPP_OPTION (pfile, deps_file) = CPP_OPTION (pfile, out_fname);
 }
============================================================
Index: gcc/cpplib.h
--- gcc/cpplib.h	10 Aug 2002 20:58:43 -0000	1.230
+++ gcc/cpplib.h	11 Aug 2002 20:02:42 -0000
@@ -223,7 +223,6 @@ struct cpp_options
 {
   /* Name of input and output files.  */
   const char *in_fname;
-  const char *out_fname;
 
   /* Characters between tab stops.  */
   unsigned int tabstop;
@@ -398,9 +397,6 @@ struct cpp_options
   /* True for traditional preprocessing.  */
   unsigned char traditional;
 
-  /* True if only preprocessing and not compiling.  */
-  unsigned char preprocess_only;
-
   /* Target-specific features set by the front end or client.  */
 
   /* Precision for target CPP arithmetic, target characters, target
@@ -508,6 +504,14 @@ extern cpp_reader *cpp_create_reader PAR
    command line options).  */
 extern void cpp_set_lang PARAMS ((cpp_reader *, enum c_lang));
 
+/* Add a dependency TARGET.  Quote it for "make" if QUOTE.  Can be
+   called any number of times before cpp_read_main_file().  If no
+   targets have been added before cpp_read_main_file(), then the
+   default target is used.  */
+extern void cpp_add_dependency_target PARAMS ((cpp_reader *,
+					       const char * target,
+					       int quote));
+
 /* Call these to get pointers to the options and callback structures
    for a given reader.  These pointers are good until you call
    cpp_finish on that reader.  You can either edit the callbacks
@@ -553,7 +557,7 @@ extern void cpp_finish_options PARAMS ((
 /* Call this to release the handle at the end of preprocessing.  Any
    use of the handle after this function returns is invalid.  Returns
    cpp_errors (pfile).  */
-extern int cpp_destroy PARAMS ((cpp_reader *));
+extern void cpp_destroy PARAMS ((cpp_reader *));
 
 /* Error count.  */
 extern unsigned int cpp_errors PARAMS ((cpp_reader *));
@@ -567,7 +571,7 @@ extern void cpp_register_pragma PARAMS (
 					 const char *, const char *,
 					 void (*) PARAMS ((cpp_reader *))));
 
-extern void cpp_finish PARAMS ((cpp_reader *));
+extern int cpp_finish PARAMS ((cpp_reader *, FILE *));
 extern int cpp_avoid_paste PARAMS ((cpp_reader *, const cpp_token *,
 				    const cpp_token *));
 extern const cpp_token *cpp_get_token PARAMS ((cpp_reader *));
@@ -722,7 +726,7 @@ extern int cpp_included	PARAMS ((cpp_rea
 extern void cpp_make_system_header PARAMS ((cpp_reader *, int, int));
 
 /* In cppmain.c */
-extern void cpp_preprocess_file PARAMS ((cpp_reader *));
+extern void cpp_preprocess_file PARAMS ((cpp_reader *, FILE *));
 
 #ifdef __cplusplus
 }
============================================================
Index: gcc/cppmain.c
--- gcc/cppmain.c	29 Jun 2002 15:49:23 -0000	1.101
+++ gcc/cppmain.c	11 Aug 2002 20:02:42 -0000
@@ -67,15 +67,12 @@ static struct printer print;
 
 /* Preprocess and output.  */
 void
-cpp_preprocess_file (pfile)
+cpp_preprocess_file (pfile, out_stream)
      cpp_reader *pfile;
+     FILE *out_stream;
 {
   options = cpp_get_options (pfile);
 
-  /* Let preprocessor know if it's only preprocessing.  It would be
-     nice to lose this somehow.  */
-  options->preprocess_only = 1;
-
   /* Initialize the printer structure.  Setting print.line to -1 here
      is a trick to guarantee that the first token of the file will
      cause a linemarker to be output by maybe_print_line.  */
@@ -83,21 +80,7 @@ cpp_preprocess_file (pfile)
   print.printed = 0;
   print.prev = 0;
   print.map = 0;
-
-  /* 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).  */
-  if (options->out_fname[0] == '\0')
-    print.outf = stdout;
-  else
-    {
-      print.outf = fopen (options->out_fname, "w");
-      if (print.outf == NULL)
-	{
-	  cpp_errno (pfile, DL_ERROR, options->out_fname);
-	  return;
-	}
-    }
+  print.outf = out_stream;
 
   setup_callbacks (pfile);
 
@@ -122,13 +105,6 @@ cpp_preprocess_file (pfile)
   /* Flush any pending output.  */
   if (print.printed)
     putc ('\n', print.outf);
-
-  /* Don't close stdout (dependencies have yet to be output).  */
-  if (print.outf != stdout)
-    {
-      if (ferror (print.outf) || fclose (print.outf))
-	cpp_errno (pfile, DL_ERROR, options->out_fname);
-    }
 }
 
 /* Set up the callbacks as appropriate.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]