pkgsrc/lang/gcc/patches/patch-ag
jtb 3f9c40bb8e Add some patches against basesrc gcc implementing the "if-exists"
function in the specs file.  Enables the linker to pick
up crti.o and crtn.o if they exist.
2003-07-12 08:53:40 +00:00

361 lines
9.6 KiB
Text
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

$NetBSD: patch-ag,v 1.8 2003/07/12 08:53:40 jtb Exp $
--- ../gcc-2.95.3/gcc/gcc.c.orig
+++ ../gcc-2.95.3/gcc/gcc.c
@@ -189,9 +189,13 @@
static void clear_failure_queue PROTO((void));
static int check_live_switch PROTO((int, int));
static const char *handle_braces PROTO((const char *));
+static const struct spec_function *lookup_spec_function PROTO((const char *));
+static const char *eval_spec_function PROTO((const char *, const char *));
+static const char *handle_spec_function PROTO((const char *));
static char *save_string PROTO((const char *, int));
extern int do_spec PROTO((const char *));
static int do_spec_1 PROTO((const char *, int, const char *));
+static int do_spec_2 PROTO((const char *));
static const char *find_file PROTO((const char *));
static int is_directory PROTO((const char *, const char *, int));
static void validate_switches PROTO((const char *));
@@ -216,6 +220,7 @@
static void process_command PROTO ((int, char **));
static int execute PROTO ((void));
static void unused_prefix_warnings PROTO ((struct path_prefix *));
+static void alloc_args PROTO ((void));
static void clear_args PROTO ((void));
static void fatal_error PROTO ((int));
@@ -231,6 +236,8 @@
/* Number of extra output files that lang_specific_pre_link may generate. */
extern int lang_specific_extra_outfiles;
+static const char *if_exists_spec_function PROTO ((int, const char **));
+
/* Specs are strings containing lines, each of which (if not blank)
is made up of a program name, and arguments separated by spaces.
The program name must be exact and start from root, since no path
@@ -335,6 +342,12 @@
%* 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.
@@ -1162,6 +1175,24 @@
static struct spec_list *specs = (struct spec_list *)0;
+/* The mapping of a spec function name to the C function that
+ implements it. */
+struct spec_function
+{
+ const char *name;
+ const char *(*func) PROTO ((int, const char **));
+};
+
+/* 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;
+
/* Initialize the specs lookup routines. */
static void
@@ -1404,6 +1435,15 @@
static const char *multilib_dir;
+/* Allocate the argument vector. */
+
+static void
+alloc_args ()
+{
+ argbuf_length = 10;
+ argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
+}
+
/* Clear out the vector of arguments (after a command is executed). */
static void
@@ -2211,6 +2251,9 @@
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)
@@ -3360,14 +3403,7 @@
{
int value;
- clear_args ();
- arg_going = 0;
- delete_this_arg = 0;
- this_is_output_file = 0;
- this_is_library_file = 0;
- input_from_pipe = 0;
-
- value = do_spec_1 (spec, 0, NULL_PTR);
+ value = do_spec_2 (spec);
/* Force out any unfinished command.
If -pipe, this forces out the last command if it ended in `|'. */
@@ -3383,6 +3419,20 @@
return value;
}
+static int
+do_spec_2 (spec)
+ const char *spec;
+{
+ clear_args ();
+ arg_going = 0;
+ delete_this_arg = 0;
+ this_is_output_file = 0;
+ this_is_library_file = 0;
+ input_from_pipe = 0;
+
+ return do_spec_1 (spec, 0, NULL_PTR);
+}
+
/* Process the sub-spec SPEC as a portion of a larger spec.
This is like processing a whole spec except that we do
not initialize at the beginning and we do not supply a
@@ -4068,6 +4118,12 @@
return -1;
break;
+ case ':':
+ p = handle_spec_function (p);
+ if (p == 0)
+ return -1;
+ break;
+
case '%':
obstack_1grow (&obstack, '%');
break;
@@ -4222,7 +4278,173 @@
arg_going = 1;
}
- return 0; /* 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,
+ };
+ 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;
+ 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;
+
+
+ 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;
+
+ /* 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, (const char **) 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;
+
+ 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. */
@@ -4674,8 +4896,8 @@
signal (SIGPIPE, fatal_error);
#endif
- argbuf_length = 10;
- argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
+ /* Allocate the argument vector. */
+ alloc_args ();
obstack_init (&obstack);
@@ -5846,3 +6068,25 @@
++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). */
+
+#define IS_ABSOLUTE_PATHNAME(cp) ((cp)[0] == '/')
+
+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;
+}