From e7aa92b2a1d420c944ff0c2e0ed5f0240638fa39 Mon Sep 17 00:00:00 2001 From: aoliva Date: Tue, 5 Aug 2003 21:15:57 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70189 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 25 ++++++++++++++++++ gcc/c-common.c | 7 +++++ gcc/c-common.h | 7 +++++ gcc/c-lex.c | 9 +++++++ gcc/c-opts.c | 15 ++++++++++- gcc/c.opt | 4 +++ gcc/cppinit.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/cpplib.h | 6 +++++ gcc/dbxout.c | 3 ++- gcc/doc/cpp.texi | 4 ++- gcc/doc/cppopts.texi | 18 ++++++++++++- gcc/doc/invoke.texi | 3 ++- gcc/dwarf2out.c | 2 +- gcc/dwarfout.c | 4 +-- gcc/gcc.c | 2 +- gcc/toplev.c | 35 +++++++++++++++++++++++++ gcc/toplev.h | 6 +++++ 17 files changed, 215 insertions(+), 9 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d7342a85c57..8aa7b430d19 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2003-08-05 Alexandre Oliva + + * 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. + 2003-08-05 Gabriel Dos Reis * pretty-print.h (pp_set_line_maximum_length): Make macro. diff --git a/gcc/c-common.c b/gcc/c-common.c index 60e980f62ec..267ede38197 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -559,6 +559,13 @@ int flag_new_for_scope = 1; 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. */ diff --git a/gcc/c-common.h b/gcc/c-common.h index bda560313e7..6230ac937ef 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -716,6 +716,13 @@ extern int flag_new_for_scope; 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. */ diff --git a/gcc/c-lex.c b/gcc/c-lex.c index 28f2e8d5c27..47515e7b703 100644 --- a/gcc/c-lex.c +++ b/gcc/c-lex.c @@ -72,6 +72,7 @@ static tree lex_charconst (const cpp_token *); static void update_header_times (const char *); static int dump_one_header (splay_tree_node, void *); static void cb_line_change (cpp_reader *, const cpp_token *, int); +static void cb_dir_change (cpp_reader *, const char *); static void cb_ident (cpp_reader *, unsigned int, const cpp_string *); static void cb_def_pragma (cpp_reader *, unsigned int); static void cb_define (cpp_reader *, unsigned int, cpp_hashnode *); @@ -98,6 +99,7 @@ init_c_lex (void) cb = cpp_get_callbacks (parse_in); cb->line_change = cb_line_change; + cb->dir_change = cb_dir_change; cb->ident = cb_ident; cb->def_pragma = cb_def_pragma; cb->valid_pch = c_common_valid_pch; @@ -200,6 +202,13 @@ cb_line_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const cpp_token *token, src_lineno = SOURCE_LINE (map, token->line); } +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 fe_file_change (const struct line_map *new_map) { diff --git a/gcc/c-opts.c b/gcc/c-opts.c index 012f24ba53a..e2a30430997 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -235,7 +235,7 @@ c_common_init_options (unsigned int argc, const char **argv ATTRIBUTE_UNUSED) return result; } -/* Handle switch SCODE with argument ARG. ON is true, unless no- +/* Handle switch SCODE with argument ARG. VALUE is true, unless no- form of an -f or -W option was given. Returns 0 if the switch was invalid, a negative number to prevent language-independent processing in toplev.c (a hack necessary for the short-term). */ @@ -335,6 +335,10 @@ c_common_handle_option (size_t scode, const char *arg, int value) flag_no_line_commands = 1; break; + case OPT_fworking_directory: + flag_working_directory = value; + break; + case OPT_U: defer_opt (code, arg); break; @@ -1329,6 +1333,15 @@ sanitize_cpp_opts (void) 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; } /* Add include path with a prefix at the front of its name. */ diff --git a/gcc/c.opt b/gcc/c.opt index 221fb678b3d..229414f6c1a 100644 --- a/gcc/c.opt +++ b/gcc/c.opt @@ -650,6 +650,10 @@ fwide-exec-charset= C ObjC C++ ObjC++ Joined RejectNegative -fwide-exec-charset= Convert all wide strings and character constants to character set +fworking-directory +C ObjC C++ ObjC++ +Generate a #line directive pointing at the current working directory + fxref C++ ObjC++ Emit cross referencing information diff --git a/gcc/cppinit.c b/gcc/cppinit.c index b719a85bb8c..4ef7e24998c 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -28,6 +28,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static void init_library (void); static void mark_named_operators (cpp_reader *); static void read_original_filename (cpp_reader *); +static void read_original_directory (cpp_reader *); static void post_options (cpp_reader *); /* If we have designated initializers (GCC >2.7) these tables can be @@ -470,6 +471,24 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname) 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; } @@ -494,6 +513,7 @@ read_original_filename (cpp_reader *pfile) if (token1->type == CPP_NUMBER) { _cpp_handle_directive (pfile, token->flags & PREV_WHITE); + read_original_directory (pfile); return; } } @@ -502,6 +522,60 @@ read_original_filename (cpp_reader *pfile) _cpp_backup_tokens (pfile, 1); } +/* For preprocessed files, if the tokens following the first filename + line is of the form # "/path/name//", handle the + directive so we know the original current directory. */ +static void +read_original_directory (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; +} + /* This is called at the end of preprocessing. It pops the last buffer and writes dependency output, and returns the number of errors. diff --git a/gcc/cpplib.h b/gcc/cpplib.h index ca3f81422ad..57fc0b13086 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -370,6 +370,11 @@ struct cpp_options /* 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 to cpplib client. */ @@ -378,6 +383,7 @@ struct cpp_callbacks /* Called when a new line of preprocessed output is started. */ void (*line_change) (cpp_reader *, const cpp_token *, int); void (*file_change) (cpp_reader *, const struct line_map *); + void (*dir_change) (cpp_reader *, const char *); void (*include) (cpp_reader *, unsigned int, const unsigned char *, const char *, int); void (*define) (cpp_reader *, unsigned int, cpp_hashnode *); diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 2501c947ef1..d257729d8f8 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -469,7 +469,8 @@ dbxout_init (const char *input_file_name) /* Put the current working directory in an N_SO symbol. */ if (use_gnu_debug_info_extensions) { - 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) { diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index a6ff40c53ef..2db1ee1ff11 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -4133,7 +4133,9 @@ without notice. 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} diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi index 8096763e6ed..4988227213d 100644 --- a/gcc/doc/cppopts.texi +++ b/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. @@ -513,6 +513,22 @@ corresponds to the width of @code{wchar_t}. As with by the system's @code{iconv} library routine; however, you will have problems with encodings that do not fit exactly in @code{wchar_t}. +@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 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 518b527a9bc..40cba57d005 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -301,7 +301,8 @@ in the following sections. -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} @gol -Xpreprocessor @var{option}} diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 48f0f92c08c..81cb7ecf5c9 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -9506,7 +9506,7 @@ add_name_attribute (dw_die_ref die, const char *name_string) static void add_comp_dir_attribute (dw_die_ref die) { - const char *wd = getpwd (); + const char *wd = get_src_pwd (); if (wd != NULL) add_AT_string (die, DW_AT_comp_dir, wd); } diff --git a/gcc/dwarfout.c b/gcc/dwarfout.c index 769c0eacb80..cd4dc050661 100644 --- a/gcc/dwarfout.c +++ b/gcc/dwarfout.c @@ -4043,7 +4043,7 @@ output_compile_unit_die (void *arg) stmt_list_attribute (LINE_BEGIN_LABEL); { - const char *wd = getpwd (); + const char *wd = get_src_pwd (); if (wd) comp_dir_attribute (wd); } @@ -6114,7 +6114,7 @@ dwarfout_init (const char *main_input_filename) 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) diff --git a/gcc/gcc.c b/gcc/gcc.c index 9f685252e24..f18b1684876 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -755,7 +755,7 @@ static const char *cpp_unique_options = 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. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 1e578778358..73d459ac5bf 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1219,6 +1219,41 @@ FILE *aux_info_file; 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) + 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; +} + /* Set up a default flag_random_seed and local_tick, unless the user already specified one. */ diff --git a/gcc/toplev.h b/gcc/toplev.h index c45105c760e..71a9fd5bfad 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -155,4 +155,10 @@ extern bool fast_math_flags_set_p (void); extern int exact_log2_wide (unsigned HOST_WIDE_INT); extern int floor_log2_wide (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 */ -- 2.11.4.GIT