summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/config/alpha/netbsd.h3
-rw-r--r--gcc/config/netbsd-elf.h4
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/g++spec.c6
-rw-r--r--gcc/cppspec.c6
-rw-r--r--gcc/doc/invoke.texi21
-rw-r--r--gcc/f/ChangeLog4
-rw-r--r--gcc/f/g77spec.c6
-rw-r--r--gcc/gcc.c235
-rw-r--r--gcc/gcc.h11
-rw-r--r--gcc/gccspec.c6
-rw-r--r--gcc/java/ChangeLog4
-rw-r--r--gcc/java/jvspec.c6
14 files changed, 334 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 87eb85beea7..07ea2be266b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/alpha/netbsd.h b/gcc/config/alpha/netbsd.h
index 4dc713ba537..f56f7807bed 100644
--- a/gcc/config/alpha/netbsd.h
+++ b/gcc/config/alpha/netbsd.h
@@ -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. */
diff --git a/gcc/config/netbsd-elf.h b/gcc/config/netbsd-elf.h
index 40ed3aa0798..a35f46af18b 100644
--- a/gcc/config/netbsd-elf.h
+++ b/gcc/config/netbsd-elf.h
@@ -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
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f4f98e094a6..e3c47ab3fe7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index 6e5de08e031..d46244857b2 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -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 }
+};
diff --git a/gcc/cppspec.c b/gcc/cppspec.c
index ee19b722635..e79968ab510 100644
--- a/gcc/cppspec.c
+++ b/gcc/cppspec.c
@@ -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 }
+};
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1df52deca44..45fee6f0fbf 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/f/ChangeLog b/gcc/f/ChangeLog
index cd79362e383..4960f2f278d 100644
--- a/gcc/f/ChangeLog
+++ b/gcc/f/ChangeLog
@@ -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
diff --git a/gcc/f/g77spec.c b/gcc/f/g77spec.c
index 6aea81b3c47..1bf20d266b4 100644
--- a/gcc/f/g77spec.c
+++ b/gcc/f/g77spec.c
@@ -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 }
+};
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 291712dcfa1..56cb08f8fbc 100644
--- a/gcc/gcc.c
+++ b/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;
+}
diff --git a/gcc/gcc.h b/gcc/gcc.h
index 77033879631..feab0ef0710 100644
--- a/gcc/gcc.h
+++ b/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;
diff --git a/gcc/gccspec.c b/gcc/gccspec.c
index 79f3d667d5e..6e538b1b744 100644
--- a/gcc/gccspec.c
+++ b/gcc/gccspec.c
@@ -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 }
+};
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index e8c9d514044..31379a17134 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -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:
diff --git a/gcc/java/jvspec.c b/gcc/java/jvspec.c
index 8638ac38f6d..c3efe58de3a 100644
--- a/gcc/java/jvspec.c
+++ b/gcc/java/jvspec.c
@@ -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 }
+};