aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/collect2.c71
-rw-r--r--gcc/config.in6
-rwxr-xr-xgcc/configure9
-rw-r--r--gcc/configure.ac3
-rw-r--r--gcc/gcc.c68
-rw-r--r--include/ChangeLog4
-rw-r--r--include/libiberty.h4
-rw-r--r--libiberty/ChangeLog4
-rw-r--r--libiberty/argv.c56
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
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 1046802..5ed41bd 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -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