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:
Jason Thorpe 2002-11-19 04:37:50 +00:00 committed by Jason Thorpe
parent 3b312ef46f
commit f3226a9001
14 changed files with 334 additions and 5 deletions

View File

@ -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.

View File

@ -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. */

View File

@ -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

View File

@ -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.

View File

@ -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 }
};

View File

@ -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 }
};

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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;
}

View File

@ -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;

View File

@ -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 }
};

View File

@ -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:

View File

@ -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 }
};