mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-30 17:35:05 +08:00
gcc.c (The Specs Language): Document spec functions.
* gcc.c (The Specs Language): Document spec functions. (static_spec_functions, lookup_spec_function) (eval_spec_function, handle_spec_function) (if_exists_spec_function, alloc_args): New. (execute): Abort if processing_spec_function is true. (do_spec_1): Hand off spec to handle_spec_function if %: is encountered. If processing_spec_function is true, end any pending argument when the end of the string is reached. (main): Use alloc_args to allocate the initial argument vector. * gcc.h (struct spec_function): New. (lang_specific_spec_functions): New extern. * config/netbsd-elf.h (STARTFILE_SPEC): Add if-exists(crti%O%s). (ENDFILE_SPEC): Add if-exists(crtn%O%s). * config/alpha/netbsd.h (ENDFILE_SPEC): Likewise. * doc/invoke.texi: Document spec functions. * cppspec.c (lang_specific_spec_functions): New. * gccspec.c: Likewise. * g++spec.c (lang_specific_spec_functions): New. * g77spec.c (lang_specific_spec_functions): New. * jvspec.c (lang_specific_spec_functions): New. From-SVN: r59241
This commit is contained in:
parent
3b312ef46f
commit
f3226a9001
@ -1,3 +1,26 @@
|
||||
2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
|
||||
|
||||
* gcc.c (The Specs Language): Document spec functions.
|
||||
(static_spec_functions, lookup_spec_function)
|
||||
(eval_spec_function, handle_spec_function)
|
||||
(if_exists_spec_function, alloc_args): New.
|
||||
(execute): Abort if processing_spec_function is true.
|
||||
(do_spec_1): Hand off spec to handle_spec_function if %:
|
||||
is encountered. If processing_spec_function is true,
|
||||
end any pending argument when the end of the string is reached.
|
||||
(main): Use alloc_args to allocate the initial argument vector.
|
||||
* gcc.h (struct spec_function): New.
|
||||
(lang_specific_spec_functions): New extern.
|
||||
|
||||
* config/netbsd-elf.h (STARTFILE_SPEC): Add if-exists(crti%O%s).
|
||||
(ENDFILE_SPEC): Add if-exists(crtn%O%s).
|
||||
* config/alpha/netbsd.h (ENDFILE_SPEC): Likewise.
|
||||
|
||||
* doc/invoke.texi: Document spec functions.
|
||||
|
||||
* cppspec.c (lang_specific_spec_functions): New.
|
||||
* gccspec.c: Likewise.
|
||||
|
||||
2002-11-18 Steve Ellcey <sje@cup.hp.com>
|
||||
|
||||
* config/ia64/hpux_longdouble.h (FIXUNS_TRUNCTFSI2_LIBCALL): New.
|
||||
|
@ -72,7 +72,8 @@ Boston, MA 02111-1307, USA. */
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC \
|
||||
"%{ffast-math|funsafe-math-optimizations:crtfm%O%s} \
|
||||
%{!shared:crtend%O%s} %{shared:crtendS%O%s}"
|
||||
%{!shared:crtend%O%s} %{shared:crtendS%O%s} \
|
||||
%:if-exists(crtn%O%s)"
|
||||
|
||||
|
||||
/* Attempt to enable execute permissions on the stack. */
|
||||
|
@ -53,6 +53,7 @@ Boston, MA 02111-1307, USA. */
|
||||
%{!pg: \
|
||||
%{p:gcrt0%O%s} \
|
||||
%{!p:crt0%O%s}}} \
|
||||
%:if-exists(crti%O%s) \
|
||||
%{!shared:crtbegin%O%s} %{shared:crtbeginS%O%s}"
|
||||
|
||||
|
||||
@ -62,7 +63,8 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC \
|
||||
"%{!shared:crtend%O%s} %{shared:crtendS%O%s}"
|
||||
"%{!shared:crtend%O%s} %{shared:crtendS%O%s} \
|
||||
%:if-exists(crtn%O%s)"
|
||||
|
||||
|
||||
/* Provide a LINK_SPEC appropriate for NetBSD ELF. Here we provide
|
||||
|
@ -1,3 +1,7 @@
|
||||
2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
|
||||
|
||||
* g++spec.c (lang_specific_spec_functions): New.
|
||||
|
||||
2002-11-15 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* ChangeLog: Follow spelling conventions.
|
||||
|
@ -307,3 +307,9 @@ int lang_specific_pre_link () /* Not used for C++. */
|
||||
|
||||
/* Number of extra output files that lang_specific_pre_link may generate. */
|
||||
int lang_specific_extra_outfiles = 0; /* Not used for C++. */
|
||||
|
||||
/* Table of language-specific spec functions. */
|
||||
const struct spec_function lang_specific_spec_functions[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -238,3 +238,9 @@ int lang_specific_pre_link ()
|
||||
|
||||
/* Number of extra output files that lang_specific_pre_link may generate. */
|
||||
int lang_specific_extra_outfiles = 0; /* Not used for cpp. */
|
||||
|
||||
/* Table of language-specific spec functions. */
|
||||
const struct spec_function lang_specific_spec_functions[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -4967,6 +4967,27 @@ Substitute the variable part of a matched option. See below.
|
||||
Note that each comma in the substituted string is replaced by
|
||||
a single space.
|
||||
|
||||
@item %:@var{function}(@var{args})
|
||||
Call the named function @var{function}, passing it @var{args}.
|
||||
@var{args} is first processed as a nested spec string, then split
|
||||
into an argument vector in the usual fashion. The function returns
|
||||
a string which is processed as if it had appeared literally as part
|
||||
of the current spec.
|
||||
|
||||
The following built-in spec functions are provided:
|
||||
|
||||
@table @code
|
||||
@item @code{if-exists}
|
||||
The @code{if-exists} spec function takes one argument, an absolute
|
||||
pathname to a file. If the file exists, @code{if-exists} returns the
|
||||
pathname. Here is a small example of its usage:
|
||||
|
||||
@smallexample
|
||||
*startfile:
|
||||
crt0%O%s %:if-exists(crti%O%s) crtbegin%O%s
|
||||
@end smallexample
|
||||
@end table
|
||||
|
||||
@item %@{@code{S}@}
|
||||
Substitutes the @code{-S} switch, if that switch was given to GCC@.
|
||||
If that switch was not specified, this substitutes nothing. Note that
|
||||
|
@ -1,3 +1,7 @@
|
||||
2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
|
||||
|
||||
* g77spec.c (lang_specific_spec_functions): New.
|
||||
|
||||
2002-11-02 Toon Moene <toon@moene.indiv.nluug.nl>
|
||||
|
||||
* g77.texi: Correct documentation on generating C++ prototypes
|
||||
|
@ -562,3 +562,9 @@ int lang_specific_pre_link () /* Not used for F77. */
|
||||
|
||||
/* Number of extra output files that lang_specific_pre_link may generate. */
|
||||
int lang_specific_extra_outfiles = 0; /* Not used for F77. */
|
||||
|
||||
/* Table of language-specific spec functions. */
|
||||
const struct spec_function lang_specific_spec_functions[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
235
gcc/gcc.c
235
gcc/gcc.c
@ -292,6 +292,9 @@ static void delete_failure_queue PARAMS ((void));
|
||||
static void clear_failure_queue PARAMS ((void));
|
||||
static int check_live_switch PARAMS ((int, int));
|
||||
static const char *handle_braces PARAMS ((const char *));
|
||||
static const struct spec_function *lookup_spec_function PARAMS ((const char *));
|
||||
static const char *eval_spec_function PARAMS ((const char *, const char *));
|
||||
static const char *handle_spec_function PARAMS ((const char *));
|
||||
static char *save_string PARAMS ((const char *, int));
|
||||
static void set_collect_gcc_options PARAMS ((void));
|
||||
static int do_spec_1 PARAMS ((const char *, int, const char *));
|
||||
@ -317,6 +320,7 @@ static void add_assembler_option PARAMS ((const char *, int));
|
||||
static void add_linker_option PARAMS ((const char *, int));
|
||||
static void process_command PARAMS ((int, const char *const *));
|
||||
static int execute PARAMS ((void));
|
||||
static void alloc_args PARAMS ((void));
|
||||
static void clear_args PARAMS ((void));
|
||||
static void fatal_error PARAMS ((int));
|
||||
#ifdef ENABLE_SHARED_LIBGCC
|
||||
@ -327,6 +331,8 @@ static void init_gcc_specs PARAMS ((struct obstack *,
|
||||
#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
|
||||
static const char *convert_filename PARAMS ((const char *, int, int));
|
||||
#endif
|
||||
|
||||
static const char *if_exists_spec_function PARAMS ((int, const char **));
|
||||
|
||||
/* The Specs Language
|
||||
|
||||
@ -450,6 +456,12 @@ or with constant text in a single argument.
|
||||
%* substitute the variable part of a matched option. (See below.)
|
||||
Note that each comma in the substituted string is replaced by
|
||||
a single space.
|
||||
%:function(args)
|
||||
Call the named function FUNCTION, passing it ARGS. ARGS is
|
||||
first processed as a nested spec string, then split into an
|
||||
argument vector in the usual fashion. The function returns
|
||||
a string which is processed as if it had appeared literally
|
||||
as part of the current spec.
|
||||
%{S} substitutes the -S switch, if that switch was given to CC.
|
||||
If that switch was not specified, this substitutes nothing.
|
||||
Here S is a metasyntactic variable.
|
||||
@ -1439,6 +1451,16 @@ static struct spec_list *extra_specs = (struct spec_list *) 0;
|
||||
|
||||
static struct spec_list *specs = (struct spec_list *) 0;
|
||||
|
||||
/* List of static spec functions. */
|
||||
|
||||
static const struct spec_function static_spec_functions[] =
|
||||
{
|
||||
{ "if-exists", if_exists_spec_function },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static int processing_spec_function;
|
||||
|
||||
/* Add appropriate libgcc specs to OBSTACK, taking into account
|
||||
various permutations of -shared-libgcc, -shared, and such. */
|
||||
|
||||
@ -1710,6 +1732,15 @@ static int signal_count;
|
||||
|
||||
static const char *programname;
|
||||
|
||||
/* Allocate the argument vector. */
|
||||
|
||||
static void
|
||||
alloc_args ()
|
||||
{
|
||||
argbuf_length = 10;
|
||||
argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
|
||||
}
|
||||
|
||||
/* Clear out the vector of arguments (after a command is executed). */
|
||||
|
||||
static void
|
||||
@ -2753,6 +2784,9 @@ execute ()
|
||||
|
||||
struct command *commands; /* each command buffer with above info. */
|
||||
|
||||
if (processing_spec_function)
|
||||
abort ();
|
||||
|
||||
/* Count # of piped commands. */
|
||||
for (n_commands = 1, i = 0; i < argbuf_index; i++)
|
||||
if (strcmp (argbuf[i], "|") == 0)
|
||||
@ -5118,6 +5152,12 @@ do_spec_1 (spec, inswitch, soft_matched_part)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
p = handle_spec_function (p);
|
||||
if (p == 0)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case '%':
|
||||
obstack_1grow (&obstack, '%');
|
||||
break;
|
||||
@ -5311,10 +5351,179 @@ do_spec_1 (spec, inswitch, soft_matched_part)
|
||||
arg_going = 1;
|
||||
}
|
||||
|
||||
/* End of string. */
|
||||
/* End of string. If we are processing a spec function, we need to
|
||||
end any pending argument. */
|
||||
if (processing_spec_function && arg_going)
|
||||
{
|
||||
obstack_1grow (&obstack, 0);
|
||||
string = obstack_finish (&obstack);
|
||||
if (this_is_library_file)
|
||||
string = find_file (string);
|
||||
store_arg (string, delete_this_arg, this_is_output_file);
|
||||
if (this_is_output_file)
|
||||
outfiles[input_file_number] = string;
|
||||
arg_going = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look up a spec function. */
|
||||
|
||||
static const struct spec_function *
|
||||
lookup_spec_function (name)
|
||||
const char *name;
|
||||
{
|
||||
static const struct spec_function * const spec_function_tables[] =
|
||||
{
|
||||
static_spec_functions,
|
||||
lang_specific_spec_functions,
|
||||
};
|
||||
const struct spec_function *sf;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++)
|
||||
{
|
||||
for (sf = spec_function_tables[i]; sf->name != NULL; sf++)
|
||||
if (strcmp (sf->name, name) == 0)
|
||||
return sf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Evaluate a spec function. */
|
||||
|
||||
static const char *
|
||||
eval_spec_function (func, args)
|
||||
const char *func, *args;
|
||||
{
|
||||
const struct spec_function *sf;
|
||||
const char *funcval;
|
||||
|
||||
/* Saved spec processing context. */
|
||||
int save_argbuf_index;
|
||||
int save_argbuf_length;
|
||||
const char **save_argbuf;
|
||||
|
||||
int save_arg_going;
|
||||
int save_delete_this_arg;
|
||||
int save_this_is_output_file;
|
||||
int save_this_is_library_file;
|
||||
int save_input_from_pipe;
|
||||
const char *save_suffix_subst;
|
||||
|
||||
|
||||
sf = lookup_spec_function (func);
|
||||
if (sf == NULL)
|
||||
fatal ("unknown spec function `%s'", func);
|
||||
|
||||
/* Push the spec processing context. */
|
||||
save_argbuf_index = argbuf_index;
|
||||
save_argbuf_length = argbuf_length;
|
||||
save_argbuf = argbuf;
|
||||
|
||||
save_arg_going = arg_going;
|
||||
save_delete_this_arg = delete_this_arg;
|
||||
save_this_is_output_file = this_is_output_file;
|
||||
save_this_is_library_file = this_is_library_file;
|
||||
save_input_from_pipe = input_from_pipe;
|
||||
save_suffix_subst = suffix_subst;
|
||||
|
||||
/* Create a new spec processing context, and build the function
|
||||
arguments. */
|
||||
|
||||
alloc_args ();
|
||||
if (do_spec_2 (args) < 0)
|
||||
fatal ("error in args to spec function `%s'", func);
|
||||
|
||||
/* argbuf_index is an index for the next argument to be inserted, and
|
||||
so contains the count of the args already inserted. */
|
||||
|
||||
funcval = (*sf->func) (argbuf_index, argbuf);
|
||||
|
||||
/* Pop the spec processing context. */
|
||||
argbuf_index = save_argbuf_index;
|
||||
argbuf_length = save_argbuf_length;
|
||||
free (argbuf);
|
||||
argbuf = save_argbuf;
|
||||
|
||||
arg_going = save_arg_going;
|
||||
delete_this_arg = save_delete_this_arg;
|
||||
this_is_output_file = save_this_is_output_file;
|
||||
this_is_library_file = save_this_is_library_file;
|
||||
input_from_pipe = save_input_from_pipe;
|
||||
suffix_subst = save_suffix_subst;
|
||||
|
||||
return funcval;
|
||||
}
|
||||
|
||||
/* Handle a spec function call of the form:
|
||||
|
||||
%:function(args)
|
||||
|
||||
ARGS is processed as a spec in a separate context and split into an
|
||||
argument vector in the normal fashion. The function returns a string
|
||||
containing a spec which we then process in the caller's context, or
|
||||
NULL if no processing is required. */
|
||||
|
||||
static const char *
|
||||
handle_spec_function (p)
|
||||
const char *p;
|
||||
{
|
||||
char *func, *args;
|
||||
const char *endp, *funcval;
|
||||
int count;
|
||||
|
||||
processing_spec_function++;
|
||||
|
||||
/* Get the function name. */
|
||||
for (endp = p; *endp != '\0'; endp++)
|
||||
{
|
||||
if (*endp == '(') /* ) */
|
||||
break;
|
||||
/* Only allow [A-Za-z0-9], -, and _ in function names. */
|
||||
if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
|
||||
fatal ("malformed spec function name");
|
||||
}
|
||||
if (*endp != '(') /* ) */
|
||||
fatal ("no arguments for spec function");
|
||||
func = save_string (p, endp - p);
|
||||
p = ++endp;
|
||||
|
||||
/* Get the arguments. */
|
||||
for (count = 0; *endp != '\0'; endp++)
|
||||
{
|
||||
/* ( */
|
||||
if (*endp == ')')
|
||||
{
|
||||
if (count == 0)
|
||||
break;
|
||||
count--;
|
||||
}
|
||||
else if (*endp == '(') /* ) */
|
||||
count++;
|
||||
}
|
||||
/* ( */
|
||||
if (*endp != ')')
|
||||
fatal ("malformed spec function arguments");
|
||||
args = save_string (p, endp - p);
|
||||
p = ++endp;
|
||||
|
||||
/* p now points to just past the end of the spec function expression. */
|
||||
|
||||
funcval = eval_spec_function (func, args);
|
||||
if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
|
||||
p = NULL;
|
||||
|
||||
free (func);
|
||||
free (args);
|
||||
|
||||
processing_spec_function--;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Return 0 if we call do_spec_1 and that returns -1. */
|
||||
|
||||
static const char *
|
||||
@ -5897,8 +6106,8 @@ main (argc, argv)
|
||||
signal (SIGCHLD, SIG_DFL);
|
||||
#endif
|
||||
|
||||
argbuf_length = 10;
|
||||
argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
|
||||
/* Allocate the argument vector. */
|
||||
alloc_args ();
|
||||
|
||||
obstack_init (&obstack);
|
||||
|
||||
@ -7253,3 +7462,23 @@ print_multilib_info ()
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
/* if-exists built-in spec function.
|
||||
|
||||
Checks to see if the file specified by the absolute pathname in
|
||||
ARGS exists. Returns that pathname if found.
|
||||
|
||||
The usual use for this function is to check for a library file
|
||||
(whose name has been expanded with %s). */
|
||||
|
||||
static const char *
|
||||
if_exists_spec_function (argc, argv)
|
||||
int argc;
|
||||
const char **argv;
|
||||
{
|
||||
/* Must have only one argument. */
|
||||
if (argc == 1 && IS_ABSOLUTE_PATHNAME (argv[0]) && ! access (argv[0], R_OK))
|
||||
return argv[0];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
11
gcc/gcc.h
11
gcc/gcc.h
@ -23,6 +23,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
#include "version.h"
|
||||
|
||||
/* The mapping of a spec function name to the C function that
|
||||
implements it. */
|
||||
struct spec_function
|
||||
{
|
||||
const char *name;
|
||||
const char *(*func) PARAMS ((int, const char **));
|
||||
};
|
||||
|
||||
/* These are exported by gcc.c. */
|
||||
extern int do_spec PARAMS ((const char *));
|
||||
extern void record_temp_file PARAMS ((const char *, int, int));
|
||||
@ -48,6 +56,9 @@ extern int n_infiles;
|
||||
/* Number of extra output files that lang_specific_pre_link may generate. */
|
||||
extern int lang_specific_extra_outfiles;
|
||||
|
||||
/* Table of language-specific spec functions. */
|
||||
extern const struct spec_function lang_specific_spec_functions[];
|
||||
|
||||
/* A vector of corresponding output files is made up later. */
|
||||
|
||||
extern const char **outfiles;
|
||||
|
@ -101,3 +101,9 @@ lang_specific_pre_link ()
|
||||
|
||||
/* Number of extra output files that lang_specific_pre_link may generate. */
|
||||
int lang_specific_extra_outfiles = 0; /* Not used for C. */
|
||||
|
||||
/* Table of language-specific spec functions. */
|
||||
const struct spec_function lang_specific_spec_functions[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -1,3 +1,7 @@
|
||||
2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
|
||||
|
||||
* jvspec.c (lang_specific_spec_functions): New.
|
||||
|
||||
2002-11-18 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
Fix for PR java/7912:
|
||||
|
@ -632,3 +632,9 @@ lang_specific_pre_link ()
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Table of language-specific spec functions. */
|
||||
const struct spec_function lang_specific_spec_functions[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user