File fworking-directory.patch of Package compat-g77

2003-08-05  Alexandre Oliva  <aoliva@redhat.com>

	* c.opt: Introduce -fworking-directory.
	* doc/cpp.texi, doc/invoke.texi, doc/cppopts.texi: Document it.
	* c-common.h (flag_working_directory): Declare.
	* c-common.c (flag_working_directory): Define.
	* c-opts.c (c_common_handle_options): Set it.
	(sanitize_cpp_opts): Set...
	* cpplib.h (struct cpp_options): ... working_directory option.
	(struct cpp_callbacks): Add dir_change.
	* cppinit.c (read_original_filename): Call...
	(read_original_directory): New.  Look for # 1 "directory//"
	and process it.
	(cpp_read_main_file): Call dir_change callback if working_directory
	option is set.
	* gcc.c (cpp_unique_options): Pass -g*.
	* c-lex.c (cb_dir_change): New.
	(init_c_lex): Set dir_change callback.
	* toplev.c (src_pwd): New static variable.
	(set_src_pwd, get_src_pwd): New functions.
	* toplev.h (get_src_pwd, set_src_pwd): Declare.
	* dbxout.c (dbxout_init): Call get_src_pwd() instead of getpwd().
	* dwarf2out.c (gen_compile_unit_die): Likewise.
	* dwarfout.c (output_compile_unit_die, dwarfout_init): Likewise.

================================================================================
--- gcc-3.3.4/gcc/c-common.c
+++ gcc-3.3.4/gcc/c-common.c
@@ -548,6 +548,13 @@
 
 int flag_weak = 1;
 
+/* 0 means we want the preprocessor to not emit line directives for
+   the current working directory.  1 means we want it to do it.  -1
+   means we should decide depending on whether debugging information
+   is being emitted or not.  */
+
+int flag_working_directory = -1;
+
 /* Nonzero to use __cxa_atexit, rather than atexit, to register
    destructors for local statics and global objects.  */
 
--- gcc-3.3.4/gcc/c-common.h
+++ gcc-3.3.4/gcc/c-common.h
@@ -711,6 +711,13 @@
 
 extern int flag_weak;
 
+/* 0 means we want the preprocessor to not emit line directives for
+   the current working directory.  1 means we want it to do it.  -1
+   means we should decide depending on whether debugging information
+   is being emitted or not.  */
+
+extern int flag_working_directory;
+
 /* Nonzero to use __cxa_atexit, rather than atexit, to register
    destructors for local statics and global objects.  */
 
--- gcc-3.3.4/gcc/c-lex.c
+++ gcc-3.3.4/gcc/c-lex.c
@@ -82,6 +82,7 @@
 static void update_header_times	PARAMS ((const char *));
 static int dump_one_header	PARAMS ((splay_tree_node, void *));
 static void cb_line_change     PARAMS ((cpp_reader *, const cpp_token *, int));
+static void cb_dir_change	PARAMS ((cpp_reader *, const char *));
 static void cb_ident		PARAMS ((cpp_reader *, unsigned int,
 					 const cpp_string *));
 static void cb_file_change    PARAMS ((cpp_reader *, const struct line_map *));
@@ -119,6 +120,7 @@
   cb = cpp_get_callbacks (parse_in);
 
   cb->line_change = cb_line_change;
+  cb->dir_change = cb_dir_change;
   cb->ident = cb_ident;
   cb->file_change = cb_file_change;
   cb->def_pragma = cb_def_pragma;
@@ -206,6 +208,13 @@
   return 0;
 }
 
+static void
+cb_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
+{
+  if (! set_src_pwd (dir))
+    warning ("too late for # directive to set debug directory");
+}
+
 void
 dump_time_statistics ()
 {
--- gcc-3.3.4/gcc/c-opts.c
+++ gcc-3.3.4/gcc/c-opts.c
@@ -124,6 +124,7 @@
   OPT("MQ",                     CL_ALL | CL_ARG, OPT_MQ)		     \
   OPT("MT",                     CL_ALL | CL_ARG, OPT_MT)		     \
   OPT("P",                      CL_ALL,   OPT_P)			     \
+  OPT("fworking-directory",     CL_ALL,   OPT_fworking_directory)	     \
   OPT("Wabi",                   CL_CXX,   OPT_Wabi)                          \
   OPT("Wall",			CL_ALL,   OPT_Wall)			     \
   OPT("Wbad-function-cast",	CL_C,     OPT_Wbad_function_cast)	     \
@@ -686,6 +687,10 @@
       cpp_opts->no_line_commands = 1;
       break;
 
+    case OPT_fworking_directory:
+      flag_working_directory = on;
+      break;
+
     case OPT_Wabi:
       warn_abi = on;
       break;
@@ -1587,6 +1592,15 @@
      and/or -Wtraditional, whatever the ordering.  */
   cpp_opts->warn_long_long
     = warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional);
+
+  /* If we're generating preprocessor output, emit current directory
+     if explicitly requested or if debugging information is enabled.
+     ??? Maybe we should only do it for debugging formats that
+     actually output the current directory?  */
+  if (flag_working_directory == -1)
+    flag_working_directory = (debug_info_level != DINFO_LEVEL_NONE);
+  cpp_opts->working_directory
+    = flag_preprocess_only && flag_working_directory;
 }
 
 /* Set the C 89 standard (with 1994 amendments if C94, without GNU
@@ -1790,6 +1804,10 @@
   -dI                       Include #include directives in the output\n\
 "), stdout);
   fputs (_("\
+  -fworking-directory       Generate a #line directive pointing at the\n\
+                            current working directory\n\
+"), stdout);
+  fputs (_("\
   -f[no-]preprocessed       Treat the input file as already preprocessed\n\
   -ftabstop=<number>        Distance between tab stops for column reporting\n\
   -P                        Do not generate #line directives\n\
--- gcc-3.3.4/gcc/cppinit.c
+++ gcc-3.3.4/gcc/cppinit.c
@@ -107,6 +107,7 @@
 static void free_chain			PARAMS ((struct pending_option *));
 static void init_standard_includes	PARAMS ((cpp_reader *));
 static void read_original_filename	PARAMS ((cpp_reader *));
+static void read_original_directory	PARAMS ((cpp_reader *));
 static void new_pending_directive	PARAMS ((struct cpp_pending *,
 						 const char *,
 						 cl_directive_handler));
@@ -1026,6 +1027,24 @@
   if (CPP_OPTION (pfile, preprocessed))
     read_original_filename (pfile);
 
+  if (CPP_OPTION (pfile, working_directory))
+    {
+      const char *name = pfile->map->to_file;
+      const char *dir = getpwd ();
+      char *dir_with_slashes = alloca (strlen (dir) + 3);
+
+      memcpy (dir_with_slashes, dir, strlen (dir));
+      memcpy (dir_with_slashes + strlen (dir), "//", 3);
+
+      if (pfile->cb.dir_change)
+	pfile->cb.dir_change (pfile, dir);
+      /* Emit file renames that will be recognized by
+	 read_directory_filename, since dir_change doesn't output
+	 anything.  */
+      _cpp_do_file_change (pfile, LC_RENAME, dir_with_slashes, 1, 0);
+      _cpp_do_file_change (pfile, LC_RENAME, name, 1, 0);
+    }
+
   return pfile->map->to_file;
 }
 
@@ -1051,6 +1070,7 @@
       if (token1->type == CPP_NUMBER)
 	{
 	  _cpp_handle_directive (pfile, token->flags & PREV_WHITE);
+	  read_original_directory (pfile);
 	  return;
 	}
     }
@@ -1059,6 +1079,61 @@
   _cpp_backup_tokens (pfile, 1);
 }
 
+/* For preprocessed files, if the tokens following the first filename
+   line is of the form # <line> "/path/name//", handle the
+   directive so we know the original current directory.  */
+static void
+read_original_directory (pfile)
+     cpp_reader *pfile;
+{
+  const cpp_token *hash, *token;
+
+  /* Lex ahead; if the first tokens are of the form # NUM, then
+     process the directive, otherwise back up.  */
+  hash = _cpp_lex_direct (pfile);
+  if (hash->type != CPP_HASH)
+    {
+      _cpp_backup_tokens (pfile, 1);
+      return;
+    }
+
+  token = _cpp_lex_direct (pfile);
+
+  if (token->type != CPP_NUMBER)
+    {
+      _cpp_backup_tokens (pfile, 2);
+      return;
+    }
+
+  token = _cpp_lex_direct (pfile);
+
+  if (token->type != CPP_STRING
+      || ! (token->val.str.len >= 5
+	    && token->val.str.text[token->val.str.len-2] == '/'
+	    && token->val.str.text[token->val.str.len-3] == '/'))
+    {
+      _cpp_backup_tokens (pfile, 3);
+      return;
+    }
+
+  if (pfile->cb.dir_change)
+    {
+      char *debugdir = alloca (token->val.str.len - 3);
+
+      memcpy (debugdir, (const char *) token->val.str.text + 1,
+	      token->val.str.len - 4);
+      debugdir[token->val.str.len - 4] = '\0';
+
+      pfile->cb.dir_change (pfile, debugdir);
+    }      
+
+  /* We want to process the fake line changes as regular changes, to
+     get them output.  */
+  _cpp_backup_tokens (pfile, 3);
+
+  CPP_OPTION (pfile, working_directory) = false;
+}
+
 /* Handle pending command line options: -D, -U, -A, -imacros and
    -include.  This should be called after debugging has been properly
    set up in the front ends.  */
--- gcc-3.3.4/gcc/cpplib.h
+++ gcc-3.3.4/gcc/cpplib.h
@@ -407,6 +407,11 @@
 
   /* Nonzero means __STDC__ should have the value 0 in system headers.  */
   unsigned char stdc_0_in_system_headers;
+
+  /* Nonzero means output a directory line marker right after the
+     initial file name line marker, and before a duplicate initial
+     line marker.  */
+  bool working_directory;
 };
 
 /* Call backs.  */
@@ -415,6 +420,7 @@
   /* Called when a new line of preprocessed output is started.  */
   void (*line_change) PARAMS ((cpp_reader *, const cpp_token *, int));
   void (*file_change) PARAMS ((cpp_reader *, const struct line_map *));
+  void (*dir_change) PARAMS ((cpp_reader *, const char *));
   void (*include) PARAMS ((cpp_reader *, unsigned int,
 			   const unsigned char *, const cpp_token *));
   void (*define) PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
--- gcc-3.3.4/gcc/dbxout.c
+++ gcc-3.3.4/gcc/dbxout.c
@@ -438,7 +438,8 @@
   if (use_gnu_debug_info_extensions)
 #endif
     {
-      if (!cwd && (cwd = getpwd ()) && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
+      if (!cwd && (cwd = get_src_pwd ())
+	  && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
 	cwd = concat (cwd, FILE_NAME_JOINER, NULL);
       if (cwd)
 	{
--- gcc-3.3.4/gcc/doc/cpp.texi
+++ gcc-3.3.4/gcc/doc/cpp.texi
@@ -4066,7 +4066,9 @@
 cpp [@option{-D}@var{macro}[=@var{defn}]@dots{}] [@option{-U}@var{macro}]
     [@option{-I}@var{dir}@dots{}] [@option{-W}@var{warn}@dots{}]
     [@option{-M}|@option{-MM}] [@option{-MG}] [@option{-MF} @var{filename}]
-    [@option{-MP}] [@option{-MQ} @var{target}@dots{}] [@option{-MT} @var{target}@dots{}]
+    [@option{-MP}] [@option{-MQ} @var{target}@dots{}]
+    [@option{-MT} @var{target}@dots{}]
+    [@option{-P}] [@option{-fno-working-directory}] 
     [@option{-x} @var{language}] [@option{-std=}@var{standard}]
     @var{infile} @var{outfile}
 
--- gcc-3.3.4/gcc/doc/cppopts.texi
+++ gcc-3.3.4/gcc/doc/cppopts.texi
@@ -1,4 +1,4 @@
-@c Copyright (c) 1999, 2000, 2001, 2002
+@c Copyright (c) 1999, 2000, 2001, 2002, 2003
 @c Free Software Foundation, Inc.
 @c This is part of the CPP and GCC manuals.
 @c For copying conditions, see the file gcc.texi.
@@ -470,6 +470,22 @@
 line.  If the value is less than 1 or greater than 100, the option is
 ignored.  The default is 8.
 
+@item -fworking-directory
+@opindex fworking-directory
+@opindex fno-working-directory
+Enable generation of linemarkers in the preprocessor output that will
+let the compiler know the current working directory at the time of
+preprocessing.  When this option is enabled, the preprocessor will
+emit, after the initial linemarker, a second linemarker with the
+current working directory followed by two slashes.  GCC will use this
+directory, when it's present in the preprocessed input, as the
+directory emitted as the current working directory in some debugging
+information formats.  This option is implicitly enabled if debugging
+information is enabled, but this can be inhibited with the negated
+form @option{-fno-working-directory}.  If the @option{-P} flag is
+present in the command line, this option has no effect, since no
+@code{#line} directives are emitted whatsoever.
+
 @item -fno-show-column
 @opindex fno-show-column
 Do not print column numbers in diagnostics.  This may be necessary if
--- gcc-3.3.4/gcc/doc/invoke.texi
+++ gcc-3.3.4/gcc/doc/invoke.texi
@@ -294,7 +294,8 @@
 -include @var{file}  -imacros @var{file} @gol
 -iprefix @var{file}  -iwithprefix @var{dir} @gol
 -iwithprefixbefore @var{dir}  -isystem @var{dir} @gol
--M  -MM  -MF  -MG  -MP  -MQ  -MT  -nostdinc  -P  -remap @gol
+-M  -MM  -MF  -MG  -MP  -MQ  -MT  -nostdinc @gol
+-P  -fworking-directory  -remap @gol
 -trigraphs  -undef  -U@var{macro}  -Wp,@var{option}}
 
 @item Assembler Option
--- gcc-3.3.4/gcc/dwarf2out.c
+++ gcc-3.3.4/gcc/dwarf2out.c
@@ -11764,7 +11764,7 @@
 {
   dw_die_ref die;
   char producer[250];
-  const char *wd = getpwd ();
+  const char *wd = get_src_pwd ();
   const char *language_string = lang_hooks.name;
   int language;
 
@@ -13222,7 +13222,7 @@
 
   if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL)
     {
-      char *wd = getpwd ();
+      char *wd = get_src_pwd ();
       unsigned i;
 
       if (wd != NULL)
--- gcc-3.3.4/gcc/dwarfout.c
+++ gcc-3.3.4/gcc/dwarfout.c
@@ -4147,7 +4147,7 @@
     stmt_list_attribute (LINE_BEGIN_LABEL);
 
   {
-    const char *wd = getpwd ();
+    const char *wd = get_src_pwd ();
     if (wd)
       comp_dir_attribute (wd);
   }
@@ -6272,7 +6272,7 @@
 	  ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SFNAMES_SECTION);
 	  ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
 	  {
-	    const char *pwd = getpwd ();
+	    const char *pwd = get_src_pwd ();
 	    char *dirname;
 
 	    if (!pwd)
--- gcc-3.3.4/gcc/gcc.c
+++ gcc-3.3.4/gcc/gcc.c
@@ -725,7 +725,7 @@
    in turn cause preprocessor symbols to be defined specially.  */
 static const char *cpp_options =
 "%(cpp_unique_options) %1 %{m*} %{std*} %{ansi} %{W*&pedantic*} %{w} %{f*}\
- %{O*} %{undef}";
+ %{g*} %{O*} %{undef}";
 
 /* This contains cpp options which are not passed when the preprocessor
    output will be used by another program.  */
--- gcc-3.3.4/gcc/toplev.c
+++ gcc-3.3.4/gcc/toplev.c
@@ -1711,6 +1711,46 @@
 FILE *rtl_dump_file = NULL;
 FILE *cgraph_dump_file = NULL;
 
+/* The current working directory of a translation.  It's generally the
+   directory from which compilation was initiated, but a preprocessed
+   file may specify the original directory in which it was
+   created.  */
+
+static const char *src_pwd;
+
+/* Initialize src_pwd with the given string, and return true.  If it
+   was already initialized, return false.  As a special case, it may
+   be called with a NULL argument to test whether src_pwd has NOT been
+   initialized yet.  */
+
+bool
+set_src_pwd (const char *pwd)
+{
+  if (src_pwd)
+    {
+      if (strcmp (src_pwd, pwd) == 0)
+	return true;
+      else
+	return false;
+    }
+
+  src_pwd = xstrdup (pwd);
+  return true;
+}
+
+/* Return the directory from which the translation unit was initiated,
+   in case set_src_pwd() was not called before to assign it a
+   different value.  */
+
+const char *
+get_src_pwd (void)
+{
+  if (! src_pwd)
+    src_pwd = getpwd ();
+
+   return src_pwd;
+}
+
 /* Decode the string P as an integral parameter.
    If the string is indeed an integer return its numeric value else
    issue an Invalid Option error for the option PNAME and return DEFVAL.
--- gcc-3.3.4/gcc/toplev.h
+++ gcc-3.3.4/gcc/toplev.h
@@ -133,4 +133,10 @@
 extern int exact_log2_wide             PARAMS ((unsigned HOST_WIDE_INT));
 extern int floor_log2_wide             PARAMS ((unsigned HOST_WIDE_INT));
 
+/* Functions used to get and set GCC's notion of in what directory
+   compilation was started.  */
+
+extern const char *get_src_pwd	       (void);
+extern bool set_src_pwd		       (const char *);
+
 #endif /* ! GCC_TOPLEV_H */
openSUSE Build Service is sponsored by