summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/gcc/f/g77.c
diff options
context:
space:
mode:
authorThomas Graichen <graichen@cvs.openbsd.org>1997-04-04 13:21:36 +0000
committerThomas Graichen <graichen@cvs.openbsd.org>1997-04-04 13:21:36 +0000
commit50325cbab454647a313ba68279c844e2bc6143af (patch)
tree0e52e902317bb4442448c5c61ab6d2162111a240 /gnu/usr.bin/gcc/f/g77.c
parentb2ad87cb6f8d3d16576e4e93251e0228f0672cdc (diff)
sync g77 to version 0.5.20 - i hope i got everything right because there
is no patch from 0.5.19 to 0.5.20 - so i did it by diffing two gcc trees looking carefully at the results what does the new g77 give us: * now it completely works on the alpha (64bit) * faster * less bugs :-)
Diffstat (limited to 'gnu/usr.bin/gcc/f/g77.c')
-rw-r--r--gnu/usr.bin/gcc/f/g77.c459
1 files changed, 370 insertions, 89 deletions
diff --git a/gnu/usr.bin/gcc/f/g77.c b/gnu/usr.bin/gcc/f/g77.c
index bc924176ead..f7b982199d7 100644
--- a/gnu/usr.bin/gcc/f/g77.c
+++ b/gnu/usr.bin/gcc/f/g77.c
@@ -1,5 +1,5 @@
/* G77 preliminary semantic processing for the compiler driver.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993-1997 Free Software Foundation, Inc.
Contributed by Brendan Kehoe (brendan@cygnus.com), with significant
modifications for GNU Fortran by James Craig Burley (burley@gnu.ai.mit.edu).
@@ -88,12 +88,28 @@ g77: `f77' language not included in list of languages\n\
#endif
#include <stdio.h>
+/* Include multi-lib information. */
+#include "multilib.h"
+
#ifndef R_OK
#define R_OK 4
#define W_OK 2
#define X_OK 1
#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(S) ((S) & 0x7f)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(S) (((S) & 0xff) == 0)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
+#endif
+
/* Defined to the name of the compiler; if using a cross compiler, the
Makefile should compile this file with the proper name
(e.g., "i386-aout-gcc"). */
@@ -224,12 +240,16 @@ typedef enum
OPTION_c, /* Aka --compile. */
OPTION_driver, /* Wrapper-specific option. */
OPTION_E, /* Aka --preprocess. */
+ OPTION_for_linker, /* Aka `-Xlinker' and `-Wl,'. */
OPTION_help, /* --help. */
OPTION_i, /* -imacros, -include, -include-*. */
+ OPTION_l,
+ OPTION_L, /* Aka --library-directory. */
OPTION_M, /* Aka --dependencies. */
OPTION_MM, /* Aka --user-dependencies. */
OPTION_nostdlib, /* Aka --no-standard-libraries, or
-nodefaultlibs. */
+ OPTION_o, /* Aka --output. */
OPTION_P, /* Aka --print-*-name. */
OPTION_S, /* Aka --assemble. */
OPTION_v, /* Aka --verbose. */
@@ -278,11 +298,20 @@ typedef enum
otherwise, in /usr/tmp or /tmp. */
static char *temp_filename;
+static char *temp_filename_f; /* Same with ".f" appended. */
/* Length of the prefix. */
static int temp_filename_length;
+/* The number of errors that have occurred; the link phase will not be
+ run if this is non-zero. */
+static int error_count = 0;
+
+/* Number of commands that exited with a signal. */
+
+static int signal_count = 0;
+
/* END OF STUFF FROM gcc-2.7.0/gcc.c. */
char *
@@ -443,12 +472,26 @@ pfatal_with_name (name)
char *s;
if (errno < sys_nerr)
- s = concat3 ("%s: ", sys_errlist[errno], "");
+ s = concat ("%s: ", my_strerror (errno));
else
- s = "cannot open %s";
+ s = "cannot open `%s'";
fatal (s, name);
}
+static void
+perror_exec (name)
+ char *name;
+{
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat ("installation problem, cannot exec `%s': ",
+ my_strerror (errno));
+ else
+ s = "installation problem, cannot exec `%s'";
+ error (s, name);
+}
+
/* Compute a string to use as the base of all temporary file names.
It is substituted for %g. */
@@ -505,65 +548,14 @@ choose_temp_base ()
temp_filename_length = strlen (temp_filename);
if (temp_filename_length == 0)
abort ();
-}
-#ifdef __MSDOS__
-static void
-perror_exec (name)
- char *name;
-{
- char *s;
-
- if (errno < sys_nerr)
- s = concat3 ("installation problem, cannot exec %s: ",
- my_strerror( errno ), "");
- else
- s = "installation problem, cannot exec %s";
- error (s, name);
+ temp_filename_f = xmalloc (temp_filename_length + 2);
+ strcpy (temp_filename_f, temp_filename);
+ temp_filename_f[temp_filename_length] = '.';
+ temp_filename_f[temp_filename_length + 1] = 'f';
+ temp_filename_f[temp_filename_length + 2] = '\0';
}
-/* This is almost exactly what's in gcc.c:pexecute for MSDOS. */
-void
-run_dos (program, argv)
- char *program;
- char *argv[];
-{
- char *scmd, *rf;
- FILE *argfile;
- int i;
-
- choose_temp_base (); /* not in gcc.c */
-
- scmd = (char *) malloc (strlen (program) + strlen (temp_filename) + 10);
- rf = scmd + strlen (program) + 6;
- sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
-
- argfile = fopen (rf, "w");
- if (argfile == 0)
- pfatal_with_name (rf);
-
- for (i=1; argv[i]; i++)
- {
- char *cp;
- for (cp = argv[i]; *cp; cp++)
- {
- if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
- fputc ('\\', argfile);
- fputc (*cp, argfile);
- }
- fputc ('\n', argfile);
- }
- fclose (argfile);
-
- i = system (scmd);
-
- remove (rf);
-
- if (i == -1)
- perror_exec (program);
-}
-#endif /* __MSDOS__ */
-
/* This structure describes one mapping. */
struct option_map
{
@@ -747,12 +739,13 @@ lookup_option (xopt, xskip, xarg, text)
char *text;
{
Option opt = OPTION_;
- int skip = -1;
+ int skip;
char *arg = NULL;
if ((skip = SWITCH_TAKES_ARG (text[1])) > (text[2] != '\0'))
skip -= (text[2] != '\0'); /* Usually one of "DUoeTuImLA". */
- else if (text[1] == 'B')
+
+ if (text[1] == 'B')
opt = OPTION_B, skip = (text[2] == '\0'), arg = text + 2;
else if (text[1] == 'b')
opt = OPTION_b, skip = (text[2] == '\0'), arg = text + 2;
@@ -762,12 +755,20 @@ lookup_option (xopt, xskip, xarg, text)
opt = OPTION_E, skip = 0;
else if (text[1] == 'i')
opt = OPTION_i, skip = 0;
+ else if (text[1] == 'l')
+ opt = OPTION_l;
+ else if (text[1] == 'L')
+ opt = OPTION_L, skip = (text[2] == '\0'), arg = text + 2;
+ else if (text[1] == 'o')
+ opt = OPTION_o;
else if ((text[1] == 'S') && (text[2] == '\0'))
opt = OPTION_S, skip = 0;
else if (text[1] == 'V')
opt = OPTION_V, skip = (text[2] == '\0');
else if ((text[1] == 'v') && (text[2] == '\0'))
opt = OPTION_v, skip = 0;
+ else if ((text[1] == 'W') && (text[2] == 'l') && (text[3] == ','))
+ opt = OPTION_for_linker, skip = 0;
else if (text[1] == 'x')
opt = OPTION_x, skip = (text[2] == '\0'), arg = text + 2;
else
@@ -777,7 +778,8 @@ lookup_option (xopt, xskip, xarg, text)
"imacros", "aux-info", "idirafter", "iprefix",
"iwithprefix", "iwithprefixbefore", "isystem". */
;
- else if (text[1] != '-')
+
+ if (text[1] != '-')
skip = 0;
else if (strcmp (text, "--assemble") == 0)
opt = OPTION_S;
@@ -797,12 +799,16 @@ lookup_option (xopt, xskip, xarg, text)
opt = OPTION_i;
else if (opteq (&skip, &arg, text, "--language") == 0)
opt = OPTION_x;
+ else if (opteq (&skip, &arg, text, "--library-directory") == 0)
+ opt = OPTION_L;
else if ((strcmp (text, "-M") == 0)
|| (strcmp (text, "--dependencies") == 0))
opt = OPTION_M;
else if ((strcmp (text, "-MM") == 0)
|| (strcmp (text, "--user-dependencies") == 0))
opt = OPTION_MM;
+ else if (strcmp (text, "--output") == 0)
+ opt = OPTION_o;
else if (opteq (&skip, &arg, text, "--prefix") == 0)
opt = OPTION_B;
else if (strcmp (text, "--preprocess") == 0)
@@ -832,9 +838,7 @@ lookup_option (xopt, xskip, xarg, text)
|| (opteq (&skip, &arg, text, "--for-assembler") == 0)
|| (opteq (&skip, &arg, text, "--for-linker") == 0)
|| (opteq (&skip, &arg, text, "--force-link") == 0)
- || (opteq (&skip, &arg, text, "--library-directory") == 0)
|| (opteq (&skip, &arg, text, "--machine") == 0)
- || (opteq (&skip, &arg, text, "--output") == 0)
|| (opteq (&skip, &arg, text, "--target") == 0)
|| (opteq (&skip, &arg, text, "--undefine-macro") == 0))
;
@@ -847,7 +851,13 @@ lookup_option (xopt, xskip, xarg, text)
if (xskip != NULL)
*xskip = skip;
if (xarg != NULL)
- *xarg = arg;
+ {
+ if ((arg != NULL)
+ && (arg[0] == '\0'))
+ *xarg = NULL;
+ else
+ *xarg = arg;
+ }
}
static void
@@ -884,6 +894,245 @@ append_arg (arg)
newargv[newargc++] = arg;
}
+extern int execv (), execvp ();
+
+/* If a stage of compilation returns an exit status >= 1,
+ compilation of that file ceases. */
+
+#define MIN_FATAL_STATUS 1
+
+/* stdin file number. */
+#define STDIN_FILE_NO 0
+
+/* stdout file number. */
+#define STDOUT_FILE_NO 1
+
+/* value of `pipe': port index for reading. */
+#define READ_PORT 0
+
+/* value of `pipe': port index for writing. */
+#define WRITE_PORT 1
+
+/* Pipe waiting from last process, to be used as input for the next one.
+ Value is STDIN_FILE_NO if no pipe is waiting
+ (i.e. the next command is the first of a group). */
+
+static int last_pipe_input;
+
+/* Fork one piped subcommand. FUNC is the system call to use
+ (either execv or execvp). ARGV is the arg vector to use.
+ NOT_LAST is nonzero if this is not the last subcommand
+ (i.e. its output should be piped to the next one.) */
+
+#ifdef __MSDOS__
+
+#include <process.h>
+static int
+pexecute (search_flag, program, argv, not_last)
+ int search_flag;
+ char *program;
+ char *argv[];
+ int not_last;
+{
+#ifdef __GO32__
+ int i = (search_flag ? spawnv : spawnvp) (1, program, argv);
+#else
+ char *scmd, *rf;
+ FILE *argfile;
+ int i, el = search_flag ? 0 : 4;
+
+ scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 6 + el);
+ rf = scmd + strlen(program) + 2 + el;
+ sprintf (scmd, "%s%s @%s.gp", program,
+ (search_flag ? "" : ".exe"), temp_filename);
+ argfile = fopen (rf, "w");
+ if (argfile == 0)
+ pfatal_with_name (rf);
+
+ for (i=1; argv[i]; i++)
+ {
+ char *cp;
+ for (cp = argv[i]; *cp; cp++)
+ {
+ if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
+ fputc ('\\', argfile);
+ fputc (*cp, argfile);
+ }
+ fputc ('\n', argfile);
+ }
+ fclose (argfile);
+
+ i = system (scmd);
+
+ remove (rf);
+#endif
+
+ if (i == -1)
+ {
+ perror_exec (program);
+ return MIN_FATAL_STATUS << 8;
+ }
+ return i << 8;
+}
+
+#endif
+
+#if !defined(__MSDOS__) && !defined(OS2) && !defined(_WIN32)
+
+static int
+pexecute (search_flag, program, argv, not_last)
+ int search_flag;
+ char *program;
+ char *argv[];
+ int not_last;
+{
+ int (*func)() = (search_flag ? execv : execvp);
+ int pid;
+ int pdes[2];
+ int input_desc = last_pipe_input;
+ int output_desc = STDOUT_FILE_NO;
+ int retries, sleep_interval;
+
+ /* If this isn't the last process, make a pipe for its output,
+ and record it as waiting to be the input to the next process. */
+
+ if (not_last)
+ {
+ if (pipe (pdes) < 0)
+ pfatal_with_name ("pipe");
+ output_desc = pdes[WRITE_PORT];
+ last_pipe_input = pdes[READ_PORT];
+ }
+ else
+ last_pipe_input = STDIN_FILE_NO;
+
+ /* Fork a subprocess; wait and retry if it fails. */
+ sleep_interval = 1;
+ for (retries = 0; retries < 4; retries++)
+ {
+ pid = vfork ();
+ if (pid >= 0)
+ break;
+ sleep (sleep_interval);
+ sleep_interval *= 2;
+ }
+
+ switch (pid)
+ {
+ case -1:
+#ifdef vfork
+ pfatal_with_name ("fork");
+#else
+ pfatal_with_name ("vfork");
+#endif
+ /* NOTREACHED */
+ return 0;
+
+ case 0: /* child */
+ /* Move the input and output pipes into place, if nec. */
+ if (input_desc != STDIN_FILE_NO)
+ {
+ close (STDIN_FILE_NO);
+ dup (input_desc);
+ close (input_desc);
+ }
+ if (output_desc != STDOUT_FILE_NO)
+ {
+ close (STDOUT_FILE_NO);
+ dup (output_desc);
+ close (output_desc);
+ }
+
+ /* Close the parent's descs that aren't wanted here. */
+ if (last_pipe_input != STDIN_FILE_NO)
+ close (last_pipe_input);
+
+ /* Exec the program. */
+ (*func) (program, argv);
+ perror_exec (program);
+ exit (-1);
+ /* NOTREACHED */
+ return 0;
+
+ default:
+ /* In the parent, after forking.
+ Close the descriptors that we made for this child. */
+ if (input_desc != STDIN_FILE_NO)
+ close (input_desc);
+ if (output_desc != STDOUT_FILE_NO)
+ close (output_desc);
+
+ /* Return child's process number. */
+ return pid;
+ }
+}
+
+#endif /* not __MSDOS__ and not OS2 and not _WIN32 */
+
+#if defined(OS2)
+
+static int
+pexecute (search_flag, program, argv, not_last)
+ int search_flag;
+ char *program;
+ char *argv[];
+ int not_last;
+{
+ return (search_flag ? spawnv : spawnvp) (1, program, argv);
+}
+#endif /* OS2 */
+
+#if defined(_WIN32)
+
+static int
+pexecute (search_flag, program, argv, not_last)
+ int search_flag;
+ char *program;
+ char *argv[];
+ int not_last;
+{
+ return (search_flag ? __spawnv : __spawnvp) (1, program, argv);
+}
+#endif /* _WIN32 */
+
+static int
+doit (char *program, char **argv)
+{
+ int pid;
+ int status;
+ int ret_code = 0;
+
+ pid = pexecute (0, program, argv, 0);
+
+#ifdef __MSDOS__
+ status = pid;
+#else
+#ifdef _WIN32
+ pid = cwait (&status, pid, WAIT_CHILD);
+#else
+ pid = wait (&status);
+#endif
+#endif
+ if (pid < 0)
+ abort ();
+
+ if (status != 0)
+ {
+ if (WIFSIGNALED (status))
+ {
+ fatal ("Internal compiler error: program %s got fatal signal %d",
+ program, WTERMSIG (status));
+ signal_count++;
+ ret_code = -1;
+ }
+ else if (WIFEXITED (status)
+ && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
+ ret_code = -1;
+ }
+
+ return ret_code;
+}
+
int
main (argc, argv)
int argc;
@@ -895,6 +1144,8 @@ main (argc, argv)
Option opt;
int skip;
char *arg;
+ int n_infiles = 0;
+ int n_outfiles = 0;
/* This will be NULL if we encounter a situation where we should not
link in libf2c. */
@@ -902,7 +1153,7 @@ main (argc, argv)
/* This will become 0 if anything other than -v and kin (like -V)
is seen, meaning the user is trying to accomplish something.
- If it remains nonzero, the user wants version info, so add stuff to
+ If it remains nonzero, and the user wants version info, add stuff to
the command line to make gcc invoke all the appropriate phases
to get all the version info. */
int add_version_magic = 1;
@@ -968,11 +1219,17 @@ main (argc, argv)
for (i = 1; i < argc; ++i)
{
- if (argv[i][0] != '-')
+ if ((argv[i][0] == '+') && (argv[i][1] == 'e'))
{
add_version_magic = 0;
continue;
}
+ else if ((argv[i][0] != '-') || (argv[i][1] == 0))
+ {
+ ++n_infiles;
+ add_version_magic = 0;
+ continue;
+ }
lookup_option (&opt, &skip, NULL, argv[i]);
@@ -990,13 +1247,26 @@ main (argc, argv)
add_version_magic = 0;
break;
+ case OPTION_for_linker:
+ case OPTION_l:
+ ++n_infiles;
+ add_version_magic = 0;
+ break;
+
+ case OPTION_o:
+ ++n_outfiles;
+ add_version_magic = 0;
+ break;
+
case OPTION_v:
+ if (!verbose)
+ printf ("g77 version %s\n", ffezzz_version_string);
verbose = 1;
- printf ("g77 version %s\n", ffezzz_version_string);
break;
case OPTION_b:
case OPTION_B:
+ case OPTION_L:
case OPTION_driver:
case OPTION_i:
case OPTION_V:
@@ -1067,11 +1337,8 @@ Report bugs to fortran@gnu.ai.mit.edu.\n");
fatal ("argument to `%s' missing\n", argv[i]);
}
- /* If only -v and related options (like -V), don't link the standard
- libraries. */
-
- if (add_version_magic)
- library = NULL;
+ if ((n_outfiles != 0) && (n_infiles == 0))
+ fatal ("No input files; unwilling to write output files");
/* Second pass through arglist, transforming arguments as appropriate. */
@@ -1098,8 +1365,6 @@ Report bugs to fortran@gnu.ai.mit.edu.\n");
/* Track input language. */
char *lang;
- append_arg (argv[i]);
-
if (arg == NULL)
lang = argv[i+1];
else
@@ -1185,7 +1450,7 @@ Report bugs to fortran@gnu.ai.mit.edu.\n");
/* Add -lf2c -lm as necessary. */
- if (library)
+ if (!add_version_magic && library)
{ /* Doing a link and no -nostdlib. */
if (saw_speclang)
append_arg ("-xnone");
@@ -1199,21 +1464,29 @@ Report bugs to fortran@gnu.ai.mit.edu.\n");
break;
}
}
- else if (verbose && add_version_magic)
+ else if (add_version_magic && verbose)
{
+ FILE *fsrc;
+
choose_temp_base ();
append_arg ("-fnull-version");
append_arg ("-o");
append_arg (temp_filename);
append_arg ("-xf77-cpp-input");
- append_arg ("/dev/null");
+ append_arg (temp_filename_f);
append_arg ("-xnone");
if (library)
{
append_arg (library);
append_arg ("-lm");
}
+
+ fsrc = fopen (temp_filename_f, "w");
+ if (fsrc == 0)
+ pfatal_with_name (fsrc);
+ fputs (" call g77__fvers;call g77__ivers;call g77__uvers;end\n", fsrc);
+ fclose (fsrc);
}
append_arg (NULL);
@@ -1232,18 +1505,26 @@ Report bugs to fortran@gnu.ai.mit.edu.\n");
fprintf (stderr, " %s", newargv[i]);
fprintf (stderr, "\n");
}
-#if !defined(OS2) && !defined (_WIN32)
-#ifdef __MSDOS__
- run_dos (gcc, newargv);
-#else /* !__MSDOS__ */
- if (execvp (gcc, newargv) < 0)
- pfatal_with_name (gcc);
-#endif /* __MSDOS__ */
-#else /* OS2 or _WIN32 */
- if (spawnvp (1, gcc, newargv) < 0)
- pfatal_with_name (gcc);
-#endif
+ if (doit (gcc, newargv) < 0)
+ ++error_count;
+ else if (add_version_magic && verbose)
+ {
+ char *outargv[2];
+
+ outargv[0] = temp_filename;
+ outargv[1] = 0;
+
+ if (doit (temp_filename, outargv) < 0)
+ ++error_count;
+
+ remove (temp_filename);
+ remove (temp_filename_f);
+ }
+
+ exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
+ /* NOTREACHED */
return 0;
}
+
#endif /* LANGUAGE_F77 == 1 */