gcc.c: Include multilib.h.

* gcc.c: Include multilib.h.
	(print_multi_lib, print_multi_directory, multilib_select,
	multilib_dir): New static variables.
	(option_map): Added --print-multi-lib and --print-multi-directory.
	(set_spec): Get multilib_select from specs file.
	(process_command): Dump multilib_select into specs file.  Handle
	-print-multi-lib and -print-multi-directory.
	(do_spec_1): Try multilib_dir for %D case.
	(find_file): Try multilib_dir.
	(main): Call set_multilib_dir.  Handle print_multi_lib and
	print_multi_directory.
	(used_arg, set_multilib_dir, print_multilib_info): New functions.

From-SVN: r7491
This commit is contained in:
Doug Evans 1994-06-15 08:04:07 +00:00
parent f6cdc7ea0f
commit 60103a3482
1 changed files with 306 additions and 0 deletions

306
gcc/gcc.c
View File

@ -45,6 +45,9 @@ compilation is specified by a string called a "spec". */
#endif
#include <stdio.h>
/* Include multi-lib information. */
#include "multilib.h"
#ifndef R_OK
#define R_OK 4
#define W_OK 2
@ -151,6 +154,16 @@ static char *print_file_name = NULL;
static char *print_prog_name = NULL;
/* Flag saying to print the relative path we'd use to
find libgcc.a given the current compiler flags. */
static int print_multi_directory;
/* Flag saying to print the list of subdirectories and
compiler flags used to select them in a standard form. */
static int print_multi_lib;
/* Flag indicating whether we should print the command and arguments */
static int verbose_flag;
@ -224,6 +237,9 @@ static int is_directory PROTO((char *, char *, int));
static void validate_switches PROTO((char *));
static void validate_all_switches PROTO((void));
static void give_switch PROTO((int, int));
static int used_arg PROTO((char *, int));
static void set_multilib_dir PROTO((void));
static void print_multilib_info PROTO((void));
static void pfatal_with_name PROTO((char *));
static void perror_with_name PROTO((char *));
static void perror_exec PROTO((char *));
@ -304,6 +320,7 @@ or with constant text in a single argument.
used here. This can be used to run a post-processor after the
assembler has done it's job.
%D Dump out a -L option for each directory in startfile_prefix.
If multilib_dir is set, extra entries are generated with it affixed.
%l process LINK_SPEC as a spec.
%L process LIB_SPEC as a spec.
%S process STARTFILE_SPEC as a spec. A capital S is actually used here.
@ -433,6 +450,13 @@ proper position among the other output files. */
#endif
#endif
/* MULTILIB_SELECT comes from multilib.h. It gives a
string interpreted by set_multilib_dir to select a library
subdirectory based on the compiler options. */
#ifndef MULTILIB_SELECT
#define MULTILIB_SELECT ". ;"
#endif
static char *cpp_spec = CPP_SPEC;
static char *cpp_predefines = CPP_PREDEFINES;
static char *cc1_spec = CC1_SPEC;
@ -445,6 +469,7 @@ static char *lib_spec = LIB_SPEC;
static char *endfile_spec = ENDFILE_SPEC;
static char *startfile_spec = STARTFILE_SPEC;
static char *switches_need_spaces = SWITCHES_NEED_SPACES;
static char *multilib_select = MULTILIB_SELECT;
/* This defines which switch letters take arguments. */
@ -789,6 +814,8 @@ struct option_map option_map[] =
{"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
{"--print-file-name", "-print-file-name=", "aj"},
{"--print-prog-name", "-print-prog-name=", "aj"},
{"--print-multi-lib", "-print-multi-lib", 0},
{"--print-multi-directory", "-print-multi-directory", 0},
{"--static", "-static", 0},
{"--shared", "-shared", 0},
{"--symbolic", "-symbolic", 0},
@ -1144,6 +1171,8 @@ set_spec (name, spec)
switches_need_spaces = sl->spec;
else if (! strcmp (name, "cross_compile"))
cross_compile = atoi (sl->spec);
else if (! strcmp (name, "multilib"))
multilib_select = sl->spec;
/* Free the old spec */
if (old_spec)
free (old_spec);
@ -1269,6 +1298,11 @@ static char *standard_startfile_prefix_2 = "/usr/lib/";
static char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
static char *tooldir_prefix;
/* Subdirectory to use for locating libraries. Set by
set_multilib_dir based on the compilation options. */
static char *multilib_dir;
/* Clear out the vector of arguments (after a command is executed). */
static void
@ -2340,6 +2374,7 @@ process_command (argc, argv)
printf ("*signed_char:\n%s\n\n", signed_char_spec);
printf ("*predefines:\n%s\n\n", cpp_predefines);
printf ("*cross_compile:\n%d\n\n", cross_compile);
printf ("*multilib:\n%s\n\n", multilib_select);
exit (0);
}
@ -2354,6 +2389,10 @@ process_command (argc, argv)
print_file_name = argv[i] + 17;
else if (! strncmp (argv[i], "-print-prog-name=", 17))
print_prog_name = argv[i] + 17;
else if (! strcmp (argv[i], "-print-multi-lib"))
print_multi_lib = 1;
else if (! strcmp (argv[i], "-print-multi-directory"))
print_multi_directory = 1;
else if (! strcmp (argv[i], "-Xlinker"))
{
/* Pass the argument of this option to the linker when we link. */
@ -2597,6 +2636,10 @@ process_command (argc, argv)
;
else if (! strncmp (argv[i], "-print-prog-name=", 17))
;
else if (! strcmp (argv[i], "-print-multi-lib"))
;
else if (! strcmp (argv[i], "-print-multi-directory"))
;
else if (argv[i][0] == '+' && argv[i][1] == 'e')
{
/* Compensate for the +e options to the C++ front-end;
@ -2941,6 +2984,45 @@ do_spec_1 (spec, inswitch, soft_matched_part)
if (pl->prefix[0] != '/')
continue;
#endif
/* Try subdirectory if there is one. */
if (multilib_dir != NULL)
{
if (machine_suffix)
{
if (strlen (pl->prefix) + strlen (machine_suffix)
>= bufsize)
bufsize = (strlen (pl->prefix)
+ strlen (machine_suffix)) * 2 + 1;
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, pl->prefix);
strcat (buffer, machine_suffix);
if (is_directory (buffer, multilib_dir, 1))
{
do_spec_1 ("-L", 0, NULL_PTR);
#ifdef SPACE_AFTER_L_OPTION
do_spec_1 (" ", 0, NULL_PTR);
#endif
do_spec_1 (buffer, 1, NULL_PTR);
do_spec_1 (multilib_dir, 1, NULL_PTR);
/* Make this a separate argument. */
do_spec_1 (" ", 0, NULL_PTR);
}
}
if (!pl->require_machine_suffix)
{
if (is_directory (pl->prefix, multilib_dir, 1))
{
do_spec_1 ("-L", 0, NULL_PTR);
#ifdef SPACE_AFTER_L_OPTION
do_spec_1 (" ", 0, NULL_PTR);
#endif
do_spec_1 (pl->prefix, 1, NULL_PTR);
do_spec_1 (multilib_dir, 1, NULL_PTR);
/* Make this a separate argument. */
do_spec_1 (" ", 0, NULL_PTR);
}
}
}
if (machine_suffix)
{
if (is_directory (pl->prefix, machine_suffix, 1))
@ -3836,6 +3918,24 @@ find_file (name)
{
char *newname;
/* Try multilib_dir if it is defined. */
if (multilib_dir != NULL)
{
char *try;
try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2);
strcpy (try, multilib_dir);
strcat (try, "/");
strcat (try, name);
newname = find_a_file (&startfile_prefix, try, R_OK);
/* If we don't find it in the multi library dir, then fall
through and look for it in the normal places. */
if (newname != NULL)
return newname;
}
newname = find_a_file (&startfile_prefix, name, R_OK);
return newname ? newname : name;
}
@ -4022,6 +4122,10 @@ main (argc, argv)
validate_all_switches ();
/* Now that we have the switches and the specs, set
the subdirectory based on the options. */
set_multilib_dir ();
/* Warn about any switches that no pass was interested in. */
for (i = 0; i < n_switches; i++)
@ -4043,6 +4147,21 @@ main (argc, argv)
exit (0);
}
if (print_multi_lib)
{
print_multilib_info ();
exit (0);
}
if (print_multi_directory)
{
if (multilib_dir == NULL)
printf (".\n");
else
printf ("%s\n", multilib_dir);
exit (0);
}
if (verbose_flag)
{
fprintf (stderr, "gcc version %s\n", version_string);
@ -4585,3 +4704,190 @@ validate_switches (start)
}
}
}
/* Check whether a particular argument was used. */
static int
used_arg (p, len)
char *p;
int len;
{
int i;
for (i = 0; i < n_switches; i++)
if (! strncmp (switches[i].part1, p, len)
&& strlen (switches[i].part1) == len)
return 1;
return 0;
}
/* Work out the subdirectory to use based on the
options. The format of multilib_select is a list of elements.
Each element is a subdirectory name followed by a list of options
followed by a semicolon. gcc will consider each line in turn. If
none of the options beginning with an exclamation point are
present, and all of the other options are present, that
subdirectory will be used. */
static void
set_multilib_dir ()
{
char *p = multilib_select;
int this_path_len;
char *this_path, *this_arg;
int failed;
while (*p != '\0')
{
/* Ignore newlines. */
if (*p == '\n')
{
++p;
continue;
}
/* Get the initial path. */
this_path = p;
while (*p != ' ')
{
if (*p == '\0')
abort ();
++p;
}
this_path_len = p - this_path;
/* Check the arguments. */
failed = 0;
++p;
while (*p != ';')
{
if (*p == '\0')
abort ();
if (failed)
{
++p;
continue;
}
this_arg = p;
while (*p != ' ' && *p != ';')
{
if (*p == '\0')
abort ();
++p;
}
if (*this_arg == '!')
failed = used_arg (this_arg + 1, p - (this_arg + 1));
else
failed = ! used_arg (this_arg, p - this_arg);
if (*p == ' ')
++p;
}
if (! failed)
{
if (this_path_len != 1
|| this_path[0] != '.')
{
multilib_dir = xmalloc (this_path_len + 1);
strncpy (multilib_dir, this_path, this_path_len);
multilib_dir[this_path_len] = '\0';
}
break;
}
++p;
}
}
/* Print out the multiple library subdirectory selection
information. This prints out a series of lines. Each line looks
like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
required. Only the desired options are printed out, the negative
matches. The options are print without a leading dash. There are
no spaces to make it easy to use the information in the shell.
Each subdirectory is printed only once. This assumes the ordering
generated by the genmultilib script. */
static void
print_multilib_info ()
{
char *p = multilib_select;
char *last_path, *this_path;
int last_path_len, skip, use_arg;
while (*p != '\0')
{
/* Ignore newlines. */
if (*p == '\n')
{
++p;
continue;
}
/* Get the initial path. */
this_path = p;
while (*p != ' ')
{
if (*p == '\0')
abort ();
++p;
}
/* If this is a duplicate, skip it. */
skip = (p - this_path == last_path_len
&& ! strncmp (last_path, this_path, last_path_len));
last_path = this_path;
last_path_len = p - this_path;
if (! skip)
{
char *p1;
for (p1 = last_path; p1 < p; p1++)
putchar (*p1);
putchar (';');
}
++p;
while (*p != ';')
{
int use_arg;
if (*p == '\0')
abort ();
if (skip)
{
++p;
continue;
}
use_arg = *p != '!';
if (use_arg)
putchar ('@');
while (*p != ' ' && *p != ';')
{
if (*p == '\0')
abort ();
if (use_arg)
putchar (*p);
++p;
}
if (*p == ' ')
++p;
}
if (! skip)
putchar ('\n');
++p;
}
}