diff options
author | Nathan Froyd <froydnj@gcc.gnu.org> | 2007-05-08 00:37:39 +0000 |
---|---|---|
committer | Nathan Froyd <froydnj@gcc.gnu.org> | 2007-05-08 00:37:39 +0000 |
commit | 2091ff6689ae73c4b95338a435d1c6e7b743599e (patch) | |
tree | 3aff327d968d66aedb2dcdc719740c083d117e18 | |
parent | decc7c8a1cd784b2edeff50ee0f30572237b71f6 (diff) | |
download | gcc-2091ff6689ae73c4b95338a435d1c6e7b743599e.zip gcc-2091ff6689ae73c4b95338a435d1c6e7b743599e.tar.gz gcc-2091ff6689ae73c4b95338a435d1c6e7b743599e.tar.bz2 |
libiberty.h (writeargv): Declare.
include/
2007-05-07 Nathan Froyd <froydnj@codesourcery.com>
* libiberty.h (writeargv): Declare.
libiberty/
2007-05-07 Nathan Froyd <froydnj@codesourcery.com>
* argv.c (writeargv): New function.
gcc/
2007-05-07 Nathan Froyd <froydnj@codesourcery.com>
* gcc.c (at_file_supplied): New variable.
(main): Set it if we expanded argv.
(do_spec_1): Pass an @-file to the linker if we were called with
an @-file argument and HAVE_GNU_LD.
* collect2.c (at_file_supplied): New variable.
(response_file): New variable.
(collect_exit): Unlink response_file if necessary.
(handler): Likewise.
(do_wait): Likewise.
(main): Set at_file_supplied if we expanded argv.
(collect_execute): Pass an @-file to subprocesses if we were called
with an @-file argument.
* configure.ac: Add define for HAVE_GNU_LD.
* configure: Regenerate.
* config.in: Regenerate.
From-SVN: r124532
-rw-r--r-- | gcc/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/collect2.c | 71 | ||||
-rw-r--r-- | gcc/config.in | 6 | ||||
-rwxr-xr-x | gcc/configure | 9 | ||||
-rw-r--r-- | gcc/configure.ac | 3 | ||||
-rw-r--r-- | gcc/gcc.c | 68 | ||||
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/libiberty.h | 4 | ||||
-rw-r--r-- | libiberty/ChangeLog | 4 | ||||
-rw-r--r-- | libiberty/argv.c | 56 |
10 files changed, 238 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a7df7b0..c57813d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2007-05-07 Nathan Froyd <froydnj@codesourcery.com> + + * gcc.c (at_file_supplied): New variable. + (main): Set it if we expanded argv. + (do_spec_1): Pass an @-file to the linker if we were called with + an @-file argument and HAVE_GNU_LD. + * collect2.c (at_file_supplied): New variable. + (response_file): New variable. + (collect_exit): Unlink response_file if necessary. + (handler): Likewise. + (do_wait): Likewise. + (main): Set at_file_supplied if we expanded argv. + (collect_execute): Pass an @-file to subprocesses if we were called + with an @-file argument. + * configure.ac: Add define for HAVE_GNU_LD. + * configure: Regenerate. + * config.in: Regenerate. + 2007-05-07 Naveen.H.S <naveen.hs@kpitcummins.com> * config/m32c/muldiv.md (mulhisi3_c): Limit the mode of the 2nd @@ -28,7 +46,7 @@ ashrpsi3, lshrpsi3): Update shift count constraint. 2007-05-07 Danny Smith <dannysmith@users.sourceforge.net> - Nathan Froyd <froydnj@codesourcery.com + Nathan Froyd <froydnj@codesourcery.com> PR 22133 * c-incpath.c (add_path): Strip trailing path separators. diff --git a/gcc/collect2.c b/gcc/collect2.c index c6c1f3f..1ef174f 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -1,7 +1,7 @@ /* Collect static initialization info into data structures that can be traversed by C++ initialization and finalization routines. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. Contributed by Chris Smith (csmith@convex.com). Heavily modified by Michael Meissner (meissner@cygnus.com), Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com). @@ -202,6 +202,9 @@ static struct head exports; /* list of exported symbols */ #endif static struct head frame_tables; /* list of frame unwind info tables */ +static bool at_file_supplied; /* Whether to use @file arguments */ +static char *response_file; /* Name of any current response file */ + struct obstack temporary_obstack; char * temporary_firstobj; @@ -302,6 +305,9 @@ collect_exit (int status) if (status != 0 && output_file != 0 && output_file[0]) maybe_unlink (output_file); + if (response_file) + maybe_unlink (response_file); + exit (status); } @@ -393,6 +399,9 @@ handler (int signo) maybe_unlink (export_file); #endif + if (response_file) + maybe_unlink (response_file); + signal (signo, SIG_DFL); raise (signo); } @@ -793,7 +802,15 @@ main (int argc, char **argv) char **object_lst; const char **object; int first_file; - int num_c_args = argc+9; + int num_c_args; + char **old_argv; + + old_argv = argv; + expandargv (&argc, &argv); + if (argv != old_argv) + at_file_supplied = 1; + + num_c_args = argc + 9; no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); @@ -1513,6 +1530,12 @@ do_wait (const char *prog, struct pex_obj *pex) error ("%s returned %d exit status", prog, ret); collect_exit (ret); } + + if (response_file) + { + unlink (response_file); + response_file = NULL; + } } @@ -1525,6 +1548,47 @@ collect_execute (const char *prog, char **argv, const char *outname, struct pex_obj *pex; const char *errmsg; int err; + char *response_arg = NULL; + char *response_argv[3] ATTRIBUTE_UNUSED; + + if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL) + { + /* If using @file arguments, create a temporary file and put the + contents of argv into it. Then change argv to an array corresponding + to a single argument @FILE, where FILE is the temporary filename. */ + + char **current_argv = argv + 1; + char *argv0 = argv[0]; + int status; + FILE *f; + + /* Note: we assume argv contains at least one element; this is + checked above. */ + + response_file = make_temp_file (""); + + f = fopen (response_file, "w"); + + if (f == NULL) + fatal ("could not open response file %s", response_file); + + status = writeargv (current_argv, f); + + if (status) + fatal ("could not write to response file %s", response_file); + + status = fclose (f); + + if (EOF == status) + fatal ("could not close response file %s", response_file); + + response_arg = concat ("@", response_file, NULL); + response_argv[0] = argv0; + response_argv[1] = response_arg; + response_argv[2] = NULL; + + argv = response_argv; + } if (vflag || debug) { @@ -1568,6 +1632,9 @@ collect_execute (const char *prog, char **argv, const char *outname, fatal (errmsg); } + if (response_arg) + free (response_arg); + return pex; } diff --git a/gcc/config.in b/gcc/config.in index 7e60a3e..7864d8c 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -869,6 +869,12 @@ #endif +/* Define if using GNU ld. */ +#ifndef USED_FOR_TARGET +#undef HAVE_GNU_LD +#endif + + /* Define if you have the iconv() function. */ #ifndef USED_FOR_TARGET #undef HAVE_ICONV diff --git a/gcc/configure b/gcc/configure index 17e4fdc..b3aa2b0 100755 --- a/gcc/configure +++ b/gcc/configure @@ -1767,6 +1767,13 @@ _ACEOF fi +gnu_ld=`if test x"$gnu_ld_flag" = x"yes"; then echo 1; else echo 0; fi` + +cat >>confdefs.h <<_ACEOF +#define HAVE_GNU_LD $gnu_ld +_ACEOF + + echo "$as_me:$LINENO: checking whether a default linker was specified" >&5 echo $ECHO_N "checking whether a default linker was specified... $ECHO_C" >&6 if test x"${DEFAULT_LINKER+set}" = x"set"; then @@ -7665,7 +7672,7 @@ if test "${gcc_cv_prog_makeinfo_modern+set}" = set; then else ac_prog_version=`$MAKEINFO --version 2>&1 | sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'` - echo "configure:7668: version of makeinfo is $ac_prog_version" >&5 + echo "configure:7675: version of makeinfo is $ac_prog_version" >&5 case $ac_prog_version in '') gcc_cv_prog_makeinfo_modern=no;; 4.[4-9]*) diff --git a/gcc/configure.ac b/gcc/configure.ac index 9a7c563..708ce16 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -206,6 +206,9 @@ if test x"${DEFAULT_LINKER+set}" = x"set"; then [Define to enable the use of a default linker.]) fi +gnu_ld=`if test x"$gnu_ld_flag" = x"yes"; then echo 1; else echo 0; fi` +AC_DEFINE_UNQUOTED(HAVE_GNU_LD, $gnu_ld, [Define if using GNU ld.]) + AC_MSG_CHECKING([whether a default linker was specified]) if test x"${DEFAULT_LINKER+set}" = x"set"; then if test x"$gnu_ld_flag" = x"no"; then @@ -127,6 +127,9 @@ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; /* Flag set by cppspec.c to 1. */ int is_cpp_driver; +/* Flag set to non-zero if an @file argument has been supplied to gcc. */ +static bool at_file_supplied; + /* Flag saying to pass the greatest exit code returned by a sub-process to the calling program. */ static int pass_exit_codes; @@ -5009,9 +5012,63 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) int max = n_infiles; max += lang_specific_extra_outfiles; - for (i = 0; i < max; i++) - if (outfiles[i]) - store_arg (outfiles[i], 0, 0); + if (HAVE_GNU_LD && at_file_supplied) + { + /* We are going to expand `%o' to `@FILE', where FILE + is a newly-created temporary filename. The filenames + that would usually be expanded in place of %o will be + written to the temporary file. */ + + char *temp_file = make_temp_file (""); + char *at_argument; + char **argv; + int n_files, j, status; + FILE *f; + + at_argument = concat ("@", temp_file, NULL); + store_arg (at_argument, 0, 0); + + /* Convert OUTFILES into a form suitable for writeargv. */ + + /* Determine how many are non-NULL. */ + for (n_files = 0, i = 0; i < max; i++) + n_files += outfiles[i] != NULL; + + argv = alloca (sizeof (char *) * (n_files + 1)); + + /* Copy the strings over. */ + for (i = 0, j = 0; i < max; i++) + if (outfiles[i]) + { + argv[j] = (char *) outfiles[i]; + j++; + } + argv[j] = NULL; + + f = fopen (temp_file, "w"); + + if (f == NULL) + fatal ("could not open temporary response file %s", + temp_file); + + status = writeargv (argv, f); + + if (status) + fatal ("could not write to temporary response file %s", + temp_file); + + status = fclose (f); + + if (EOF == status) + fatal ("could not close temporary response file %s", + temp_file); + + record_temp_file (temp_file, !save_temps_flag, !save_temps_flag); + } + else + for (i = 0; i < max; i++) + if (outfiles[i]) + store_arg (outfiles[i], 0, 0); break; } @@ -6093,6 +6150,7 @@ main (int argc, char **argv) char *specs_file; const char *p; struct user_specs *uptr; + char **old_argv = argv; p = argv[0] + strlen (argv[0]); while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) @@ -6103,6 +6161,10 @@ main (int argc, char **argv) expandargv (&argc, &argv); + /* Determine if any expansions were made. */ + if (argv != old_argv) + at_file_supplied = true; + prune_options (&argc, &argv); #ifdef GCC_DRIVER_HOST_INITIALIZATION diff --git a/include/ChangeLog b/include/ChangeLog index 5fcce72..b4112bf 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2007-05-07 Nathan Froyd <froydnj@codesourcery.com> + + * libiberty.h (writeargv): Declare. + 2007-04-25 Mark Mitchell <mark@codesourcery.com> * demangle.h: Change license to LGPL + exception. diff --git a/include/libiberty.h b/include/libiberty.h index 7a58b71..4e69734 100644 --- a/include/libiberty.h +++ b/include/libiberty.h @@ -86,6 +86,10 @@ extern char **dupargv (char **) ATTRIBUTE_MALLOC; extern void expandargv PARAMS ((int *, char ***)); +/* Write argv to an @-file, inserting necessary quoting. */ + +extern int writeargv PARAMS ((char **, FILE *)); + /* Return the last component of a path name. Note that we can't use a prototype here because the parameter is declared inconsistently across different systems, sometimes as "char *" and sometimes as diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index c4e7072..a421784 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,7 @@ +2007-05-07 Nathan Froyd <froydnj@codesourcery.com> + + * argv.c (writeargv): New function. + 2007-05-05 Geoffrey Keating <geoffk@apple.com> * cp-demangle.c (d_name): Detect local-source-name. diff --git a/libiberty/argv.c b/libiberty/argv.c index e76c1f8..a04f50d 100644 --- a/libiberty/argv.c +++ b/libiberty/argv.c @@ -290,6 +290,62 @@ char **buildargv (const char *input) /* +@deftypefn Extension int writeargv (const char **@var{argv}, FILE *@{file}) + +Write each member of ARGV, handling all necessary quoting, to the file +named by FILE, separated by whitespace. Return 0 on success, non-zero +if an error occurred while writing to FILE. + +@end deftypefn + +*/ + +int +writeargv (char **argv, FILE *f) +{ + int status = 0; + + if (f == NULL) + return 1; + + while (*argv != NULL) + { + int ret; + const char *arg = *argv; + + while (*arg != EOS) + { + char c = *arg; + + if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"') + if (EOF == fputc ('\\', f)) + { + status = 1; + goto done; + } + + if (EOF == fputc (c, f)) + { + status = 1; + goto done; + } + arg++; + } + + if (EOF == fputc ('\n', f)) + { + status = 1; + goto done; + } + argv++; + } + + done: + return status; +} + +/* + @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp}) The @var{argcp} and @code{argvp} arguments are pointers to the usual |