aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcc.c
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1997-03-25 22:03:18 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1997-03-25 22:03:18 +0000
commit20df0482b5ef474e00bdae865e6daf33b6fc6266 (patch)
tree409f91918e72c5bc1386f20febe92012e2bb6aae /gcc/gcc.c
parentae998c9a69a3cfa88fe8157eb72db36036a7a7b2 (diff)
downloadgcc-20df0482b5ef474e00bdae865e6daf33b6fc6266.zip
gcc-20df0482b5ef474e00bdae865e6daf33b6fc6266.tar.gz
gcc-20df0482b5ef474e00bdae865e6daf33b6fc6266.tar.bz2
Add %include, %include_noerr, %rename support to specs
From-SVN: r13803
Diffstat (limited to 'gcc/gcc.c')
-rw-r--r--gcc/gcc.c390
1 files changed, 266 insertions, 124 deletions
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 04ab4df..8e50517 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -231,7 +231,8 @@ extern char *version_string;
/* Forward declaration for prototypes. */
struct path_prefix;
-static void init_spec PROTO(());
+static void init_spec PROTO((void));
+static void read_specs PROTO((char *, int));
static void set_spec PROTO((char *, char *));
static struct compiler *lookup_compiler PROTO((char *, int, char *));
static char *build_search_list PROTO((struct path_prefix *, char *, int));
@@ -1026,126 +1027,6 @@ my_strerror(e)
#endif
}
-/* Read compilation specs from a file named FILENAME,
- replacing the default ones.
-
- A suffix which starts with `*' is a definition for
- one of the machine-specific sub-specs. The "suffix" should be
- *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
- The corresponding spec is stored in asm_spec, etc.,
- rather than in the `compilers' vector.
-
- Anything invalid in the file is a fatal error. */
-
-static void
-read_specs (filename)
- char *filename;
-{
- int desc;
- int readlen;
- struct stat statbuf;
- char *buffer;
- register char *p;
-
- if (verbose_flag)
- fprintf (stderr, "Reading specs from %s\n", filename);
-
- /* Open and stat the file. */
- desc = open (filename, O_RDONLY, 0);
- if (desc < 0)
- pfatal_with_name (filename);
- if (stat (filename, &statbuf) < 0)
- pfatal_with_name (filename);
-
- /* Read contents of file into BUFFER. */
- buffer = xmalloc ((unsigned) statbuf.st_size + 1);
- readlen = read (desc, buffer, (unsigned) statbuf.st_size);
- if (readlen < 0)
- pfatal_with_name (filename);
- buffer[readlen] = 0;
- close (desc);
-
- /* Scan BUFFER for specs, putting them in the vector. */
- p = buffer;
- while (1)
- {
- char *suffix;
- char *spec;
- char *in, *out, *p1, *p2;
-
- /* Advance P in BUFFER to the next nonblank nocomment line. */
- p = skip_whitespace (p);
- if (*p == 0)
- break;
-
- /* Find the colon that should end the suffix. */
- p1 = p;
- while (*p1 && *p1 != ':' && *p1 != '\n') p1++;
- /* The colon shouldn't be missing. */
- if (*p1 != ':')
- fatal ("specs file malformed after %d characters", p1 - buffer);
- /* Skip back over trailing whitespace. */
- p2 = p1;
- while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--;
- /* Copy the suffix to a string. */
- suffix = save_string (p, p2 - p);
- /* Find the next line. */
- p = skip_whitespace (p1 + 1);
- if (p[1] == 0)
- fatal ("specs file malformed after %d characters", p - buffer);
- p1 = p;
- /* Find next blank line. */
- while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++;
- /* Specs end at the blank line and do not include the newline. */
- spec = save_string (p, p1 - p);
- p = p1;
-
- /* Delete backslash-newline sequences from the spec. */
- in = spec;
- out = spec;
- while (*in != 0)
- {
- if (in[0] == '\\' && in[1] == '\n')
- in += 2;
- else if (in[0] == '#')
- {
- while (*in && *in != '\n') in++;
- }
- else
- *out++ = *in++;
- }
- *out = 0;
-
- if (suffix[0] == '*')
- {
- if (! strcmp (suffix, "*link_command"))
- link_command_spec = spec;
- else
- set_spec (suffix + 1, spec);
- }
- else
- {
- /* Add this pair to the vector. */
- compilers
- = ((struct compiler *)
- xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
- compilers[n_compilers].suffix = suffix;
- bzero ((char *) compilers[n_compilers].spec,
- sizeof compilers[n_compilers].spec);
- compilers[n_compilers].spec[0] = spec;
- n_compilers++;
- bzero ((char *) &compilers[n_compilers],
- sizeof compilers[n_compilers]);
- }
-
- if (*suffix == 0)
- link_command_spec = spec;
- }
-
- if (link_command_spec == 0)
- fatal ("spec file has no spec for linking");
-}
-
static char *
skip_whitespace (p)
char *p;
@@ -1236,6 +1117,9 @@ init_spec ()
if (specs)
return; /* already initialized */
+ if (verbose_flag)
+ fprintf (stderr, "Using builtin specs.\n");
+
#ifdef EXTRA_SPECS
for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
{
@@ -1272,6 +1156,19 @@ set_spec (name, spec)
int name_len = strlen (name);
int i;
+ /* If this is the first call, initialize the statically allocated specs */
+ if (!specs)
+ {
+ struct spec_list *next = (struct spec_list *)0;
+ for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--)
+ {
+ sl = &static_specs[i];
+ sl->next = next;
+ next = sl;
+ }
+ specs = sl;
+ }
+
/* See if the spec already exists */
for (sl = specs; sl; sl = sl->next)
if (name_len == sl->name_len && !strcmp (sl->name, name))
@@ -1295,6 +1192,11 @@ set_spec (name, spec)
? concat (old_spec, spec + 1, NULL_PTR)
: save_string (spec, strlen (spec)));
+#ifdef DEBUG_SPECS
+ if (verbose_flag)
+ fprintf (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
+#endif
+
/* Free the old spec */
if (old_spec && sl->alloc_p)
free (old_spec);
@@ -1459,6 +1361,241 @@ store_arg (arg, delete_always, delete_failure)
record_temp_file (arg, delete_always, delete_failure);
}
+/* Read compilation specs from a file named FILENAME,
+ replacing the default ones.
+
+ A suffix which starts with `*' is a definition for
+ one of the machine-specific sub-specs. The "suffix" should be
+ *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
+ The corresponding spec is stored in asm_spec, etc.,
+ rather than in the `compilers' vector.
+
+ Anything invalid in the file is a fatal error. */
+
+static void
+read_specs (filename, main_p)
+ char *filename;
+ int main_p;
+{
+ int desc;
+ int readlen;
+ struct stat statbuf;
+ char *buffer;
+ register char *p;
+
+ if (verbose_flag)
+ fprintf (stderr, "Reading specs from %s\n", filename);
+
+ /* Open and stat the file. */
+ desc = open (filename, O_RDONLY, 0);
+ if (desc < 0)
+ pfatal_with_name (filename);
+ if (stat (filename, &statbuf) < 0)
+ pfatal_with_name (filename);
+
+ /* Read contents of file into BUFFER. */
+ buffer = xmalloc ((unsigned) statbuf.st_size + 1);
+ readlen = read (desc, buffer, (unsigned) statbuf.st_size);
+ if (readlen < 0)
+ pfatal_with_name (filename);
+ buffer[readlen] = 0;
+ close (desc);
+
+ /* Scan BUFFER for specs, putting them in the vector. */
+ p = buffer;
+ while (1)
+ {
+ char *suffix;
+ char *spec;
+ char *in, *out, *p1, *p2, *p3;
+
+ /* Advance P in BUFFER to the next nonblank nocomment line. */
+ p = skip_whitespace (p);
+ if (*p == 0)
+ break;
+
+ /* Is this a special command that starts with '%'? */
+ /* Don't allow this for the main specs file, since it would
+ encourage people to overwrite it. */
+ if (*p == '%' && !main_p)
+ {
+ p1 = p;
+ while (*p && *p != '\n') p++;
+ p++; /* skip \n */
+
+ if (!strncmp (p1, "%include", sizeof ("%include")-1)
+ && (p1[ sizeof ("%include")-1 ] == ' '
+ || p1[ sizeof ("%include")-1 ] == '\t'))
+ {
+ char *new_filename;
+
+ p1 += sizeof ("%include");
+ while (*p1 == ' ' || *p1 == '\t') p1++;
+
+ if (*p1++ != '<' || p[-2] != '>')
+ fatal ("specs %%include syntax malformed after %d characters",
+ p1 - buffer + 1);
+
+ p[-2] = '\0';
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
+ read_specs (new_filename ? new_filename : p1, FALSE);
+ continue;
+ }
+ else if (!strncmp (p1, "%include_noerr", sizeof ("%include_noerr")-1)
+ && (p1[ sizeof ("%include_noerr")-1 ] == ' '
+ || p1[ sizeof ("%include_noerr")-1 ] == '\t'))
+ {
+ char *new_filename;
+
+ p1 += sizeof ("%include_noerr");
+ while (*p1 == ' ' || *p1 == '\t') p1++;
+
+ if (*p1++ != '<' || p[-2] != '>')
+ fatal ("specs %%include syntax malformed after %d characters",
+ p1 - buffer + 1);
+
+ p[-2] = '\0';
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
+ if (new_filename)
+ read_specs (new_filename, FALSE);
+ else if (verbose_flag)
+ fprintf (stderr, "Could not find specs file %s\n", p1);
+ continue;
+ }
+ else if (!strncmp (p1, "%rename", sizeof ("%rename")-1)
+ && (p1[ sizeof ("%rename")-1 ] == ' '
+ || p1[ sizeof ("%rename")-1 ] == '\t'))
+ {
+ int name_len;
+ struct spec_list *sl;
+
+ /* Get original name */
+ p1 += sizeof ("%rename");
+ while (*p1 == ' ' || *p1 == '\t') p1++;
+ if (!isalpha (*p1))
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p1 - buffer);
+
+ p2 = p1;
+ while (*p2 && !isspace (*p2)) p2++;
+ if (*p2 != ' ' && *p2 != '\t')
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p2 - buffer);
+
+ name_len = p2 - p1;
+ *p2++ = '\0';
+ while (*p2 == ' ' || *p2 == '\t') p2++;
+ if (!isalpha (*p2))
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p2 - buffer);
+
+ /* Get new spec name */
+ p3 = p2;
+ while (*p3 && !isspace (*p3)) p3++;
+ if (p3 != p-1)
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p3 - buffer);
+ *p3 = '\0';
+
+ for (sl = specs; sl; sl = sl->next)
+ if (name_len == sl->name_len && !strcmp (sl->name, p1))
+ break;
+
+ if (!sl)
+ fatal ("specs %s spec was not found to be renamed", p1);
+
+ if (!strcmp (p1, p2))
+ continue;
+
+ if (verbose_flag)
+ {
+ fprintf (stderr, "rename spec %s to %s\n", p1, p2);
+#ifdef DEBUG_SPECS
+ fprintf (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
+#endif
+ }
+
+ set_spec (p2, *(sl->ptr_spec));
+ if (sl->alloc_p)
+ free (*(sl->ptr_spec));
+
+ *(sl->ptr_spec) = "";
+ sl->alloc_p = 0;
+ continue;
+ }
+ else
+ fatal ("specs unknown %% command after %d characters",
+ p1 - buffer);
+ }
+
+ /* Find the colon that should end the suffix. */
+ p1 = p;
+ while (*p1 && *p1 != ':' && *p1 != '\n') p1++;
+ /* The colon shouldn't be missing. */
+ if (*p1 != ':')
+ fatal ("specs file malformed after %d characters", p1 - buffer);
+ /* Skip back over trailing whitespace. */
+ p2 = p1;
+ while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--;
+ /* Copy the suffix to a string. */
+ suffix = save_string (p, p2 - p);
+ /* Find the next line. */
+ p = skip_whitespace (p1 + 1);
+ if (p[1] == 0)
+ fatal ("specs file malformed after %d characters", p - buffer);
+ p1 = p;
+ /* Find next blank line. */
+ while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++;
+ /* Specs end at the blank line and do not include the newline. */
+ spec = save_string (p, p1 - p);
+ p = p1;
+
+ /* Delete backslash-newline sequences from the spec. */
+ in = spec;
+ out = spec;
+ while (*in != 0)
+ {
+ if (in[0] == '\\' && in[1] == '\n')
+ in += 2;
+ else if (in[0] == '#')
+ {
+ while (*in && *in != '\n') in++;
+ }
+ else
+ *out++ = *in++;
+ }
+ *out = 0;
+
+ if (suffix[0] == '*')
+ {
+ if (! strcmp (suffix, "*link_command"))
+ link_command_spec = spec;
+ else
+ set_spec (suffix + 1, spec);
+ }
+ else
+ {
+ /* Add this pair to the vector. */
+ compilers
+ = ((struct compiler *)
+ xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
+ compilers[n_compilers].suffix = suffix;
+ bzero ((char *) compilers[n_compilers].spec,
+ sizeof compilers[n_compilers].spec);
+ compilers[n_compilers].spec[0] = spec;
+ n_compilers++;
+ bzero ((char *) &compilers[n_compilers],
+ sizeof compilers[n_compilers]);
+ }
+
+ if (*suffix == 0)
+ link_command_spec = spec;
+ }
+
+ if (link_command_spec == 0)
+ fatal ("spec file has no spec for linking");
+}
+
/* Record the names of temporary files we tell compilers to write,
and delete them at the end of the run. */
@@ -3615,6 +3752,10 @@ do_spec_1 (spec, inswitch, soft_matched_part)
if (sl->name_len == len && !strncmp (sl->name, name, len))
{
name = *(sl->ptr_spec);
+#ifdef DEBUG_SPECS
+ fprintf (stderr, "Processing spec %c%s%c, which is '%s'\n",
+ c, sl->name, (c == '(') ? ')' : ']', name);
+#endif
break;
}
@@ -4238,18 +4379,19 @@ main (argc, argv)
spec_version, dir_separator_str, NULL_PTR);
just_machine_suffix = concat (spec_machine, dir_separator_str, NULL_PTR);
- init_spec ();
specs_file = find_a_file (&startfile_prefixes, "specs", R_OK);
/* Read the specs file unless it is a default one. */
if (specs_file != 0 && strcmp (specs_file, "specs"))
- read_specs (specs_file);
+ read_specs (specs_file, TRUE);
+ else
+ init_spec ();
/* Process any user specified specs in the order given on the command
line. */
for (uptr = user_specs_head; uptr; uptr = uptr->next)
{
char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
- read_specs (filename ? filename : uptr->filename);
+ read_specs (filename ? filename : uptr->filename, FALSE);
}
/* If not cross-compiling, look for startfiles in the standard places. */