gcc.c: Document new %@{...} sequence.
* gcc.c: Document new %@{...} sequence. (LINK_COMMAND_SPEC): Use it for the -L switches. (cpp_unique_options): Use it for the -I switches. (at_file_argbuf): New global variable. (in_at_file): Likewise. (alloc_args): Create at_file_argbuf. (clear_args): Truncate at_file_argbuf. (store_arg): If in_at_file, push the argument onto at_file_argbuf. (open_at_file): New function. (close_at_file): Likewise. (create_at_file): Delete. (do_spec_1) <'i'>: Use open_at_file/close_at_file. <'o'>: Likewise. <'@'>: New case. (validate_switches_from_spec): Deal with %@{...} sequence. (validate_switches): Likewise. (driver::finalize): Call clear_args. From-SVN: r261474
This commit is contained in:
parent
bfad8f6640
commit
e7208389c8
|
@ -1,3 +1,23 @@
|
|||
2018-06-12 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gcc.c: Document new %@{...} sequence.
|
||||
(LINK_COMMAND_SPEC): Use it for the -L switches.
|
||||
(cpp_unique_options): Use it for the -I switches.
|
||||
(at_file_argbuf): New global variable.
|
||||
(in_at_file): Likewise.
|
||||
(alloc_args): Create at_file_argbuf.
|
||||
(clear_args): Truncate at_file_argbuf.
|
||||
(store_arg): If in_at_file, push the argument onto at_file_argbuf.
|
||||
(open_at_file): New function.
|
||||
(close_at_file): Likewise.
|
||||
(create_at_file): Delete.
|
||||
(do_spec_1) <'i'>: Use open_at_file/close_at_file.
|
||||
<'o'>: Likewise.
|
||||
<'@'>: New case.
|
||||
(validate_switches_from_spec): Deal with %@{...} sequence.
|
||||
(validate_switches): Likewise.
|
||||
(driver::finalize): Call clear_args.
|
||||
|
||||
2018-06-11 Rasmus Villemoes <rasmus.villemoes@prevas.dk>
|
||||
|
||||
* config/vx-common.h (USE_TM_CLONE_REGISTRY): #define to 0.
|
||||
|
|
237
gcc/gcc.c
237
gcc/gcc.c
|
@ -476,8 +476,11 @@ or with constant text in a single argument.
|
|||
into the sequence of arguments that %o will substitute later.
|
||||
%V indicates that this compilation produces no "output file".
|
||||
%W{...}
|
||||
like %{...} but mark last argument supplied within
|
||||
as a file to be deleted on failure.
|
||||
like %{...} but marks the last argument supplied within as a file
|
||||
to be deleted on failure.
|
||||
%@{...}
|
||||
like %{...} but puts the result into a FILE and substitutes @FILE
|
||||
if an @file argument has been supplied.
|
||||
%o substitutes the names of all the output files, with spaces
|
||||
automatically placed around them. You should write spaces
|
||||
around the %o as well or the results are undefined.
|
||||
|
@ -1034,7 +1037,7 @@ proper position among the other output files. */
|
|||
"%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
|
||||
"%X %{o*} %{e*} %{N} %{n} %{r}\
|
||||
%{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} \
|
||||
%{static|no-pie|static-pie:} %{L*} %(mfwrap) %(link_libgcc) " \
|
||||
%{static|no-pie|static-pie:} %@{L*} %(mfwrap) %(link_libgcc) " \
|
||||
VTABLE_VERIFICATION_SPEC " " SANITIZER_EARLY_SPEC " %o "" \
|
||||
%{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\
|
||||
%:include(libgomp.spec)%(link_gomp)}\
|
||||
|
@ -1109,7 +1112,7 @@ static const char *trad_capable_cpp =
|
|||
therefore no dependency entry, confuses make into thinking a .o
|
||||
file that happens to exist is up-to-date. */
|
||||
static const char *cpp_unique_options =
|
||||
"%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
|
||||
"%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %@{I*&F*} %{P} %I\
|
||||
%{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
|
||||
%{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
|
||||
%{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
|
||||
|
@ -1924,9 +1927,14 @@ set_spec (const char *name, const char *spec, bool user_p)
|
|||
typedef const char *const_char_p; /* For DEF_VEC_P. */
|
||||
|
||||
/* Vector of pointers to arguments in the current line of specifications. */
|
||||
|
||||
static vec<const_char_p> argbuf;
|
||||
|
||||
/* Likewise, but for the current @file. */
|
||||
static vec<const_char_p> at_file_argbuf;
|
||||
|
||||
/* Whether an @file is currently open. */
|
||||
static bool in_at_file = false;
|
||||
|
||||
/* Were the options -c, -S or -E passed. */
|
||||
static int have_c = 0;
|
||||
|
||||
|
@ -1966,6 +1974,7 @@ static void
|
|||
alloc_args (void)
|
||||
{
|
||||
argbuf.create (10);
|
||||
at_file_argbuf.create (10);
|
||||
}
|
||||
|
||||
/* Clear out the vector of arguments (after a command is executed). */
|
||||
|
@ -1974,6 +1983,7 @@ static void
|
|||
clear_args (void)
|
||||
{
|
||||
argbuf.truncate (0);
|
||||
at_file_argbuf.truncate (0);
|
||||
}
|
||||
|
||||
/* Add one argument to the vector at the end.
|
||||
|
@ -1986,7 +1996,10 @@ clear_args (void)
|
|||
static void
|
||||
store_arg (const char *arg, int delete_always, int delete_failure)
|
||||
{
|
||||
argbuf.safe_push (arg);
|
||||
if (in_at_file)
|
||||
at_file_argbuf.safe_push (arg);
|
||||
else
|
||||
argbuf.safe_push (arg);
|
||||
|
||||
if (delete_always || delete_failure)
|
||||
{
|
||||
|
@ -1999,6 +2012,67 @@ store_arg (const char *arg, int delete_always, int delete_failure)
|
|||
record_temp_file (arg, delete_always, delete_failure);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open a temporary @file into which subsequent arguments will be stored. */
|
||||
|
||||
static void
|
||||
open_at_file (void)
|
||||
{
|
||||
if (in_at_file)
|
||||
fatal_error (input_location, "cannot open nested response file");
|
||||
else
|
||||
in_at_file = true;
|
||||
}
|
||||
|
||||
/* Close the temporary @file and add @file to the argument list. */
|
||||
|
||||
static void
|
||||
close_at_file (void)
|
||||
{
|
||||
if (!in_at_file)
|
||||
fatal_error (input_location, "cannot close nonexistent response file");
|
||||
|
||||
in_at_file = false;
|
||||
|
||||
const unsigned int n_args = at_file_argbuf.length ();
|
||||
if (n_args == 0)
|
||||
return;
|
||||
|
||||
char **argv = (char **) alloca (sizeof (char *) * (n_args + 1));
|
||||
char *temp_file = make_temp_file ("");
|
||||
char *at_argument = concat ("@", temp_file, NULL);
|
||||
FILE *f = fopen (temp_file, "w");
|
||||
int status;
|
||||
unsigned int i;
|
||||
|
||||
/* Copy the strings over. */
|
||||
for (i = 0; i < n_args; i++)
|
||||
argv[i] = CONST_CAST (char *, at_file_argbuf[i]);
|
||||
argv[i] = NULL;
|
||||
|
||||
at_file_argbuf.truncate (0);
|
||||
|
||||
if (f == NULL)
|
||||
fatal_error (input_location, "could not open temporary response file %s",
|
||||
temp_file);
|
||||
|
||||
status = writeargv (argv, f);
|
||||
|
||||
if (status)
|
||||
fatal_error (input_location,
|
||||
"could not write to temporary response file %s",
|
||||
temp_file);
|
||||
|
||||
status = fclose (f);
|
||||
|
||||
if (status == EOF)
|
||||
fatal_error (input_location, "could not close temporary response file %s",
|
||||
temp_file);
|
||||
|
||||
store_arg (at_argument, 0, 0);
|
||||
|
||||
record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
|
||||
}
|
||||
|
||||
/* Load specs from a file name named FILENAME, replacing occurrences of
|
||||
various different types of line-endings, \r\n, \n\r and just \r, with
|
||||
|
@ -5081,39 +5155,6 @@ spec_path (char *path, void *data)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Create a temporary FILE with the contents of ARGV. Add @FILE to the
|
||||
argument list. */
|
||||
|
||||
static void
|
||||
create_at_file (char **argv)
|
||||
{
|
||||
char *temp_file = make_temp_file ("");
|
||||
char *at_argument = concat ("@", temp_file, NULL);
|
||||
FILE *f = fopen (temp_file, "w");
|
||||
int status;
|
||||
|
||||
if (f == NULL)
|
||||
fatal_error (input_location, "could not open temporary response file %s",
|
||||
temp_file);
|
||||
|
||||
status = writeargv (argv, f);
|
||||
|
||||
if (status)
|
||||
fatal_error (input_location,
|
||||
"could not write to temporary response file %s",
|
||||
temp_file);
|
||||
|
||||
status = fclose (f);
|
||||
|
||||
if (EOF == status)
|
||||
fatal_error (input_location, "could not close temporary response file %s",
|
||||
temp_file);
|
||||
|
||||
store_arg (at_argument, 0, 0);
|
||||
|
||||
record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
|
||||
}
|
||||
|
||||
/* True if we should compile INFILE. */
|
||||
|
||||
static bool
|
||||
|
@ -5526,41 +5567,22 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
|
|||
case 'i':
|
||||
if (combine_inputs)
|
||||
{
|
||||
/* We are going to expand `%i' into `@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. */
|
||||
if (at_file_supplied)
|
||||
{
|
||||
/* We are going to expand `%i' 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 **argv;
|
||||
int n_files = 0;
|
||||
int j;
|
||||
open_at_file ();
|
||||
|
||||
for (i = 0; i < n_infiles; i++)
|
||||
if (compile_input_file_p (&infiles[i]))
|
||||
n_files++;
|
||||
for (i = 0; (int) i < n_infiles; i++)
|
||||
if (compile_input_file_p (&infiles[i]))
|
||||
{
|
||||
store_arg (infiles[i].name, 0, 0);
|
||||
infiles[i].compiled = true;
|
||||
}
|
||||
|
||||
argv = (char **) alloca (sizeof (char *) * (n_files + 1));
|
||||
|
||||
/* Copy the strings over. */
|
||||
for (i = 0, j = 0; i < n_infiles; i++)
|
||||
if (compile_input_file_p (&infiles[i]))
|
||||
{
|
||||
argv[j] = CONST_CAST (char *, infiles[i].name);
|
||||
infiles[i].compiled = true;
|
||||
j++;
|
||||
}
|
||||
argv[j] = NULL;
|
||||
|
||||
create_at_file (argv);
|
||||
}
|
||||
else
|
||||
for (i = 0; (int) i < n_infiles; i++)
|
||||
if (compile_input_file_p (&infiles[i]))
|
||||
{
|
||||
store_arg (infiles[i].name, 0, 0);
|
||||
infiles[i].compiled = true;
|
||||
}
|
||||
if (at_file_supplied)
|
||||
close_at_file ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5633,45 +5655,20 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
|
|||
break;
|
||||
|
||||
case 'o':
|
||||
{
|
||||
int max = n_infiles;
|
||||
max += lang_specific_extra_outfiles;
|
||||
/* We are going to expand `%o' into `@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. */
|
||||
if (at_file_supplied)
|
||||
open_at_file ();
|
||||
|
||||
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. */
|
||||
for (i = 0; i < n_infiles + lang_specific_extra_outfiles; i++)
|
||||
if (outfiles[i])
|
||||
store_arg (outfiles[i], 0, 0);
|
||||
|
||||
char **argv;
|
||||
int n_files, j;
|
||||
|
||||
/* 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 = (char **) alloca (sizeof (char *) * (n_files + 1));
|
||||
|
||||
/* Copy the strings over. */
|
||||
for (i = 0, j = 0; i < max; i++)
|
||||
if (outfiles[i])
|
||||
{
|
||||
argv[j] = CONST_CAST (char *, outfiles[i]);
|
||||
j++;
|
||||
}
|
||||
argv[j] = NULL;
|
||||
|
||||
create_at_file (argv);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < max; i++)
|
||||
if (outfiles[i])
|
||||
store_arg (outfiles[i], 0, 0);
|
||||
break;
|
||||
}
|
||||
if (at_file_supplied)
|
||||
close_at_file ();
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
|
||||
|
@ -5712,6 +5709,20 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
|
|||
break;
|
||||
}
|
||||
|
||||
case '@':
|
||||
/* Handle the {...} following the %@. */
|
||||
if (*p != '{')
|
||||
fatal_error (input_location,
|
||||
"spec %qs has invalid %<%%@%c%>", spec, *p);
|
||||
if (at_file_supplied)
|
||||
open_at_file ();
|
||||
p = handle_braces (p + 1);
|
||||
if (at_file_supplied)
|
||||
close_at_file ();
|
||||
if (p == 0)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
/* %x{OPTION} records OPTION for %X to output. */
|
||||
case 'x':
|
||||
{
|
||||
|
@ -8501,7 +8512,11 @@ validate_switches_from_spec (const char *spec, bool user)
|
|||
const char *p = spec;
|
||||
char c;
|
||||
while ((c = *p++))
|
||||
if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
|
||||
if (c == '%'
|
||||
&& (*p == '{'
|
||||
|| *p == '<'
|
||||
|| (*p == 'W' && *++p == '{')
|
||||
|| (*p == '@' && *++p == '{')))
|
||||
/* We have a switch spec. */
|
||||
p = validate_switches (p + 1, user);
|
||||
}
|
||||
|
@ -8583,6 +8598,8 @@ next_member:
|
|||
p = validate_switches (p+1, user_spec);
|
||||
else if (p[0] == 'W' && p[1] == '{')
|
||||
p = validate_switches (p+2, user_spec);
|
||||
else if (p[0] == '@' && p[1] == '{')
|
||||
p = validate_switches (p+2, user_spec);
|
||||
}
|
||||
else
|
||||
p++;
|
||||
|
@ -10141,7 +10158,7 @@ driver::finalize ()
|
|||
|
||||
processing_spec_function = 0;
|
||||
|
||||
argbuf.truncate (0);
|
||||
clear_args ();
|
||||
|
||||
have_c = 0;
|
||||
have_o = 0;
|
||||
|
|
Loading…
Reference in New Issue