From 9abbaac7c252da5577d838c37fce4203563869f9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 13 Oct 1997 11:09:13 -0700 Subject: [PATCH] Make-lang.in (g77*): Copied from cp/Make-lang.in g++*. * Make-lang.in (g77*): Copied from cp/Make-lang.in g++*. * g77spec.c: New file, mostly copied from g++spec.c * g77.c: Removed. From-SVN: r15893 --- gcc/f/ChangeLog.egcs | 6 + gcc/f/Make-lang.in | 42 +- gcc/f/g77.c | 1557 -------------------------------------------------- gcc/f/g77spec.c | 269 +++++++++ 4 files changed, 300 insertions(+), 1574 deletions(-) delete mode 100644 gcc/f/g77.c create mode 100644 gcc/f/g77spec.c diff --git a/gcc/f/ChangeLog.egcs b/gcc/f/ChangeLog.egcs index 8d6969d..2c7d5c2 100644 --- a/gcc/f/ChangeLog.egcs +++ b/gcc/f/ChangeLog.egcs @@ -1,3 +1,9 @@ +Mon Oct 13 12:12:41 1997 Richard Henderson + + * Make-lang.in (g77*): Copied from cp/Make-lang.in g++*. + * g77spec.c: New file, mostly copied from g++spec.c + * g77.c: Removed. + Mon Oct 6 14:15:03 1997 Jeffrey A Law (law@cygnus.com) * Make-lang.in (f77.mostlyclean): Clean up stuff in the diff --git a/gcc/f/Make-lang.in b/gcc/f/Make-lang.in index c684770..972151f 100644 --- a/gcc/f/Make-lang.in +++ b/gcc/f/Make-lang.in @@ -109,23 +109,31 @@ F77 f77: f771 f77.maintainer-clean f77.realclean f77.stage1 f77.stage2 f77.stage3 \ f77.stage4 f77.distdir f77.rebuilt -# Create the compiler driver for g77 (only if `f77' is in LANGUAGES). -g77: $(srcdir)/f/g77.c $(srcdir)/f/version.c $(CONFIG_H) $(LIBDEPS) - case '$(LANGUAGES)' in \ - *f77*) \ - $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) \ - -o $@ $(srcdir)/f/g77.c $(srcdir)/f/version.c $(LIBS) ;; \ - esac - -# Create a version of the g77 driver which calls the cross-compiler -# (only if `f77' is in LANGUAGES). -g77-cross: $(srcdir)/f/g77.c $(srcdir)/f/version.c version.o $(LIBDEPS) - case '$(LANGUAGES)' in \ - *f77*) \ - $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) \ - -DGCC_NAME=\"$(GCC_CROSS_NAME)\" \ - -o $@ $(srcdir)/f/g77.c $(srcdir)/f/version.c $(LIBS) ;; \ - esac +g77.c: $(srcdir)/gcc.c + -rm -f $@ + $(LN_S) $(srcdir)/gcc.c $@ + +g77spec.o: $(srcdir)/f/g77spec.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/f/g77spec.c + +# N.B.: This is a copy of the gcc.o rule, with -DLANG_SPECIFIC_DRIVER added. +# It'd be nice if we could find an easier way to do this---rather than have +# to track changes to the toplevel gcc Makefile as well. +# We depend on g77.c last, to make it obvious where it came from. +g77.o: $(CONFIG_H) multilib.h config.status $(lang_specs_files) g77.c + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(DRIVER_DEFINES) \ + -DLANG_SPECIFIC_DRIVER -c g77.c + +# Create the compiler driver for g77. +g77$(exeext): g77.o g77spec.o version.o choose-temp.o pexecute.o $(LIBDEPS) $(EXTRA_GCC_OBJS) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ g77.o g77spec.o version.o \ + choose-temp.o pexecute.o $(EXTRA_GCC_OBJS) $(LIBS) + +# Create a version of the g77 driver which calls the cross-compiler. +g77-cross$(exeext): g77$(exeext) + -rm -f g77-cross$(exeext) + cp g77$(exeext) g77-cross$(exeext) F77_SRCS = \ $(srcdir)/f/assert.j \ diff --git a/gcc/f/g77.c b/gcc/f/g77.c deleted file mode 100644 index 1c0834f..0000000 --- a/gcc/f/g77.c +++ /dev/null @@ -1,1557 +0,0 @@ -/* G77 preliminary semantic processing for the compiler driver. - 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). - -This file is part of GNU Fortran. - -GNU Fortran is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Fortran is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Fortran; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ - -/* This program is a wrapper to the main `gcc' driver. The generic - goal of this program is to be basically identical to gcc (in that - it faithfully passes all of the original arguments to gcc) but, - unless explicitly overridden by the user in certain ways, ensure - that the needs of the language supported by this wrapper are met. - - For GNU Fortran (g77), we do the following to the argument list - before passing it to `gcc': - - 1. Put `-xf77', `-xf77-cpp-input' or `-xratfor' before each list - of foo.f, foo.F or foo.r source files and put `-xnone' after - that list, if necessary. This shouldn't normally be necessary, - but it is done in case gcc.c normally treats .f/.F files as, - say, to be compiled by f2c. - - 2. Make sure `-lf2c -lm' is at the end of the list. - - 3. Make sure each time `-lf2c' or `-lm' is seen, it forms - part of the series `-lf2c -lm'. - - #1 is not done if `-xfoo' is in effect (where foo is not "none"). - #2 and #3 are not done if `-nostdlib' or any option that disables - the linking phase is present, or if `-xfoo' is in effect. Note that - -v by itself disables linking. - - This program was originally made out of gcc/cp/g++.c, but the - way it builds the new argument list was rewritten so it is much - easier to maintain, improve the way it decides to add or not add - extra arguments, etc. And several improvements were made in the - handling of arguments, primarily to make it more consistent with - `gcc' itself. */ - -#ifndef LANGUAGE_F77 -#define LANGUAGE_F77 1 /* Assume f77 language wanted. */ -#endif - -#if LANGUAGE_F77 != 1 -#include - -int -main (argc, argv) - int argc; - char **argv; -{ - fprintf (stderr, "\ -g77: `f77' language not included in list of languages\n\ - built with this installation of gcc.\n"); - exit (1); -} - -#else /* LANGUAGE_F77 == 1 */ -#include "config.j" -#include "version.h" -#include -#include - -#ifndef _WIN32 -#include /* May get R_OK, etc. on some systems. */ -#else -#include -#endif - -#ifdef __STDC__ -#include -#else -#include -#endif -#include - -/* 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"). */ -#ifndef GCC_NAME -#define GCC_NAME "gcc" -#endif - -/* On MSDOS, write temp files in current dir - because there's no place else we can expect to use. */ -#ifdef __MSDOS__ -#ifndef P_tmpdir -#define P_tmpdir "." -#endif -#ifndef R_OK -#define R_OK 4 -#define W_OK 2 -#define X_OK 1 -#endif -#endif - -/* Add prototype support. */ -#ifndef PROTO -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#define PROTO(ARGS) ARGS -#else -#define PROTO(ARGS) () -#endif -#endif - -#ifndef VPROTO -#ifdef __STDC__ -#define PVPROTO(ARGS) ARGS -#define VPROTO(ARGS) ARGS -#define VA_START(va_list,var) va_start(va_list,var) -#else -#define PVPROTO(ARGS) () -#define VPROTO(ARGS) (va_alist) va_dcl -#define VA_START(va_list,var) va_start(va_list) -#endif -#endif - -/* Define a generic NULL if one hasn't already been defined. */ - -#ifndef NULL -#define NULL 0 -#endif - -/* Define O_RDONLY if the system hasn't defined it for us. */ -#ifndef O_RDONLY -#define O_RDONLY 0 -#endif - -#ifndef GENERIC_PTR -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#define GENERIC_PTR void * -#else -#define GENERIC_PTR char * -#endif -#endif - -#ifndef NULL_PTR -#define NULL_PTR ((GENERIC_PTR)0) -#endif - -#ifdef USG -#define vfork fork -#endif /* USG */ - -/* On MSDOS, write temp files in current dir - because there's no place else we can expect to use. */ -#ifdef __MSDOS__ -#ifndef P_tmpdir -#define P_tmpdir "." -#endif -#endif - -/* By default there is no special suffix for executables. */ -#ifndef EXECUTABLE_SUFFIX -#define EXECUTABLE_SUFFIX "" -#endif - -/* By default, colon separates directories in a path. */ -#ifndef PATH_SEPARATOR -#define PATH_SEPARATOR ':' -#endif - -#ifndef DIR_SEPARATOR -#define DIR_SEPARATOR '/' -#endif - -static char dir_separator_str[] = {DIR_SEPARATOR, 0}; - -extern char *getenv (); - -#ifndef errno -extern int errno; -#endif - -extern int sys_nerr; -#ifndef HAVE_STRERROR -#if defined(bsd4_4) -extern const char *const sys_errlist[]; -#else -extern char *sys_errlist[]; -#endif -#else -extern char *strerror(); -#endif - -/* Name with which this program was invoked. */ -static char *programname; - -/* argc, argv from main(). */ -static int xargc; -static char **xargv; - -/* The new argument list will be contained in these, though if identical - to the original list, these will be == xargc, xargv. */ -static int newargc; -static char **newargv; - -/* Options this driver needs to recognize, not just know how to - skip over. */ -typedef enum -{ - OPTION_b, /* Aka --prefix. */ - OPTION_B, /* Aka --target. */ - 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_syntax_only, /* -fsyntax-only. */ - OPTION_v, /* Aka --verbose. */ - OPTION_version, /* --version. */ - OPTION_V, /* Aka --use-version. */ - OPTION_x, /* Aka --language. */ - OPTION_ /* Unrecognized or unimportant. */ -} Option; - -/* THE FOLLOWING COMES STRAIGHT FROM prerelease gcc-2.8.0/gcc.c: */ - -/* This defines which switch letters take arguments. */ - -#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \ - ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \ - || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ - || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \ - || (CHAR) == 'L' || (CHAR) == 'A') - -#ifndef SWITCH_TAKES_ARG -#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) -#endif - -/* This defines which multi-letter switches take arguments. */ - -#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \ - (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ - || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ - || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ - || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \ - || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \ - || !strcmp (STR, "isystem")) - -#ifndef WORD_SWITCH_TAKES_ARG -#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) -#endif - -/* This is the common prefix we use to make temp file names. - It is chosen once for each run of this program. - It is substituted into a spec by %g. - Thus, all temp file names contain this prefix. - In practice, all temp file names start with this prefix. - - This prefix comes from the envvar TMPDIR if it is defined; - otherwise, from the P_tmpdir macro if that is defined; - 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 * -my_strerror(e) - int e; -{ - -#ifdef HAVE_STRERROR - return strerror(e); - -#else - - static char buffer[30]; - if (!e) - return ""; - - if (e > 0 && e < sys_nerr) - return sys_errlist[e]; - - sprintf (buffer, "Unknown error %d", e); - return buffer; -#endif -} - -#ifdef HAVE_VPRINTF -/* Output an error message and exit */ - -static void -fatal VPROTO((char *format, ...)) -{ -#ifndef __STDC__ - char *format; -#endif - va_list ap; - - VA_START (ap, format); - -#ifndef __STDC__ - format = va_arg (ap, char*); -#endif - - fprintf (stderr, "%s: ", programname); - vfprintf (stderr, format, ap); - va_end (ap); - fprintf (stderr, "\n"); -#if 0 - /* XXX Not needed for g77 driver. */ - delete_temp_files (); -#endif - exit (1); -} - -static void -error VPROTO((char *format, ...)) -{ -#ifndef __STDC__ - char *format; -#endif - va_list ap; - - VA_START (ap, format); - -#ifndef __STDC__ - format = va_arg (ap, char*); -#endif - - fprintf (stderr, "%s: ", programname); - vfprintf (stderr, format, ap); - va_end (ap); - - fprintf (stderr, "\n"); -} - -#else /* not HAVE_VPRINTF */ - -static void -error (msg, arg1, arg2) - char *msg, *arg1, *arg2; -{ - fprintf (stderr, "%s: ", programname); - fprintf (stderr, msg, arg1, arg2); - fprintf (stderr, "\n"); -} - -static void -fatal (msg, arg1, arg2) - char *msg, *arg1, *arg2; -{ - error (msg, arg1, arg2); -#if 0 - /* XXX Not needed for g77 driver. */ - delete_temp_files (); -#endif - exit (1); -} - -#endif /* not HAVE_VPRINTF */ - -/* More 'friendly' abort that prints the line and file. - config.h can #define abort fancy_abort if you like that sort of thing. */ - -void -fancy_abort () -{ - fatal ("Internal g77 abort."); -} - -char * -xmalloc (size) - unsigned size; -{ - register char *value = (char *) malloc (size); - if (value == 0) - fatal ("virtual memory exhausted"); - return value; -} - -static char * -concat (s1, s2) - char *s1, *s2; -{ - int len1 = strlen (s1); - int len2 = strlen (s2); - char *result = xmalloc (len1 + len2 + 1); - - strcpy (result, s1); - strcpy (result + len1, s2); - *(result + len1 + len2) = 0; - - return result; -} - -static char * -concat3 (s1, s2, s3) - char *s1, *s2, *s3; -{ - return concat (concat (s1, s2), s3); -} - -static char * -concat4 (s1, s2, s3, s4) - char *s1, *s2, *s3, *s4; -{ - return concat (concat (s1, s2), concat (s3, s4)); -} - -static char * -concat6 (s1, s2, s3, s4, s5, s6) - char *s1, *s2, *s3, *s4, *s5, *s6; -{ - return concat3 (concat (s1, s2), concat (s3, s4), concat (s5, s6)); -} - -static void -pfatal_with_name (name) - char *name; -{ - char *s; - - if (errno < sys_nerr) - s = concat ("%s: ", my_strerror (errno)); - else - 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. */ - -static char * -choose_temp_base_try (try, base) - char *try; - char *base; -{ - char *rv; - if (base) - rv = base; - else if (try == (char *)0) - rv = 0; - else if (access (try, R_OK | W_OK) != 0) - rv = 0; - else - rv = try; - return rv; -} - -static void -choose_temp_base () -{ - char *base = 0; - int len; - - base = choose_temp_base_try (getenv ("TMPDIR"), base); - base = choose_temp_base_try (getenv ("TMP"), base); - base = choose_temp_base_try (getenv ("TEMP"), base); - -#ifdef P_tmpdir - base = choose_temp_base_try (P_tmpdir, base); -#endif - - base = choose_temp_base_try (concat4 (dir_separator_str, "usr", - dir_separator_str, "tmp"), - base); - base = choose_temp_base_try (concat (dir_separator_str, "tmp"), base); - - /* If all else fails, use the current directory! */ - if (base == (char *)0) - base = concat (".", dir_separator_str); - - len = strlen (base); - temp_filename = xmalloc (len + strlen (concat (dir_separator_str, - "gfXXXXXX")) + 1); - strcpy (temp_filename, base); - if (len > 0 && temp_filename[len-1] != '/' - && temp_filename[len-1] != DIR_SEPARATOR) - temp_filename[len++] = DIR_SEPARATOR; - strcpy (temp_filename + len, "gfXXXXXX"); - - mktemp (temp_filename); - temp_filename_length = strlen (temp_filename); - if (temp_filename_length == 0) - abort (); - - 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 structure describes one mapping. */ -struct option_map -{ - /* The long option's name. */ - char *name; - /* The equivalent short option. */ - char *equivalent; - /* Argument info. A string of flag chars; NULL equals no options. - a => argument required. - o => argument optional. - j => join argument to equivalent, making one word. - * => require other text after NAME as an argument. */ - char *arg_info; -}; - -/* This is the table of mappings. Mappings are tried sequentially - for each option encountered; the first one that matches, wins. */ - -struct option_map option_map[] = - { - {"--all-warnings", "-Wall", 0}, - {"--ansi", "-ansi", 0}, - {"--assemble", "-S", 0}, - {"--assert", "-A", "a"}, - {"--comments", "-C", 0}, - {"--compile", "-c", 0}, - {"--debug", "-g", "oj"}, - {"--define-macro", "-D", "a"}, - {"--dependencies", "-M", 0}, - {"--driver", "", 0}, /* Wrapper-specific. */ - {"--dump", "-d", "a"}, - {"--dumpbase", "-dumpbase", "a"}, - {"--entry", "-e", 0}, - {"--extra-warnings", "-W", 0}, - {"--for-assembler", "-Wa", "a"}, - {"--for-linker", "-Xlinker", "a"}, - {"--force-link", "-u", "a"}, - {"--imacros", "-imacros", "a"}, - {"--include", "-include", "a"}, - {"--include-barrier", "-I-", 0}, - {"--include-directory", "-I", "a"}, - {"--include-directory-after", "-idirafter", "a"}, - {"--include-prefix", "-iprefix", "a"}, - {"--include-with-prefix", "-iwithprefix", "a"}, - {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, - {"--include-with-prefix-after", "-iwithprefix", "a"}, - {"--language", "-x", "a"}, - {"--library-directory", "-L", "a"}, - {"--machine", "-m", "aj"}, - {"--machine-", "-m", "*j"}, - {"--no-line-commands", "-P", 0}, - {"--no-precompiled-includes", "-noprecomp", 0}, - {"--no-standard-includes", "-nostdinc", 0}, - {"--no-standard-libraries", "-nostdlib", 0}, - {"--no-warnings", "-w", 0}, - {"--optimize", "-O", "oj"}, - {"--output", "-o", "a"}, - {"--pedantic", "-pedantic", 0}, - {"--pedantic-errors", "-pedantic-errors", 0}, - {"--pipe", "-pipe", 0}, - {"--prefix", "-B", "a"}, - {"--preprocess", "-E", 0}, - {"--print-file-name", "-print-file-name=", "aj"}, - {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, - {"--print-missing-file-dependencies", "-MG", 0}, - {"--print-multi-lib", "-print-multi-lib", 0}, - {"--print-multi-directory", "-print-multi-directory", 0}, - {"--print-prog-name", "-print-prog-name=", "aj"}, - {"--profile", "-p", 0}, - {"--profile-blocks", "-a", 0}, - {"--quiet", "-q", 0}, - {"--save-temps", "-save-temps", 0}, - {"--shared", "-shared", 0}, - {"--silent", "-q", 0}, - {"--static", "-static", 0}, - {"--symbolic", "-symbolic", 0}, - {"--target", "-b", "a"}, - {"--trace-includes", "-H", 0}, - {"--traditional", "-traditional", 0}, - {"--traditional-cpp", "-traditional-cpp", 0}, - {"--trigraphs", "-trigraphs", 0}, - {"--undefine-macro", "-U", "a"}, - {"--use-version", "-V", "a"}, - {"--user-dependencies", "-MM", 0}, - {"--verbose", "-v", 0}, - {"--version", "-dumpversion", 0}, - {"--warn-", "-W", "*j"}, - {"--write-dependencies", "-MD", 0}, - {"--write-user-dependencies", "-MMD", 0}, - {"--", "-f", "*j"} - }; - -/* Compares --options that take one arg. */ - -static int -opteq (xskip, xarg, opt, name) - int *xskip; - char **xarg; - char *opt; - char *name; -{ - int optlen; - int namelen; - int complen; - int i; - int cmp = strcmp (opt, name); - int skip = 1; - char *arg = NULL; - - if (cmp == 0) - { - /* Easy, a straight match. */ - *xskip = skip; - *xarg = arg; - return cmp; - } - - optlen = strlen (opt); - - for (i = 0; i < sizeof (option_map) / sizeof (option_map[0]); ++i) - { - char *arginfo; - int j; - - arginfo = option_map[i].arg_info; - if (arginfo == NULL) - arginfo = ""; - - namelen = strlen (option_map[i].name); - complen = optlen > namelen ? namelen : optlen; - - if (strncmp (opt, option_map[i].name, complen) == 0) - { - if (optlen < namelen) - { - for (j = i + 1; - j < sizeof (option_map) / sizeof (option_map[0]); - ++j) - if ((strlen (option_map[j].name) >= optlen) - && (strncmp (opt, option_map[j].name, optlen) == 0)) - fatal ("Ambiguous abbreviation `%s'", opt); - } - - if (optlen > namelen) - { - if (opt[namelen] == '=') - { - skip = 0; - arg = opt + namelen + 1; - } - else if (index (arginfo, '*') != 0) - ; - else - continue; - } - else if (index (arginfo, '*') != 0) - fatal ("Incomplete `%s' option", option_map[i].name); - - if (strcmp (name, option_map[i].name) != 0) - return 1; /* Not what is being looked for. */ - - *xskip = skip; - *xarg = arg; - return 0; - } - } - - return 1; -} - -/* Assumes text[0] == '-'. Returns number of argv items that belong to - (and follow) this one, an option id for options important to the - caller, and a pointer to the first char of the arg, if embedded (else - returns NULL, meaning no arg or it's the next argv). */ - -static void -lookup_option (xopt, xskip, xarg, text) - Option *xopt; - int *xskip; - char **xarg; - char *text; -{ - Option opt = OPTION_; - int skip; - char *arg = NULL; - - if ((skip = SWITCH_TAKES_ARG (text[1])) > (text[2] != '\0')) - skip -= (text[2] != '\0'); /* Usually one of "DUoeTuImLA". */ - - 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; - else if ((text[1] == 'c') && (text[2] == '\0')) - opt = OPTION_c, skip = 0; - else if ((text[1] == 'E') && (text[2] == '\0')) - 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 - { - if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0) - /* Usually one of "Tdata", "Ttext", "Tbss", "include", - "imacros", "aux-info", "idirafter", "iprefix", - "iwithprefix", "iwithprefixbefore", "isystem". */ - ; - - if (strcmp (text, "--assemble") == 0) - opt = OPTION_S; - else if (strcmp (text, "--compile") == 0) - opt = OPTION_c; - else if (opteq (&skip, &arg, text, "--driver") == 0) - opt = OPTION_driver; - else if (strcmp (text, "--help") == 0) - opt = OPTION_help; - else if ((opteq (&skip, &arg, text, "--imacros") == 0) - || (opteq (&skip, &arg, text, "--include") == 0) - || (opteq (&skip, &arg, text, "--include-directory-after") == 0) - || (opteq (&skip, &arg, text, "--include-prefix") == 0) - || (opteq (&skip, &arg, text, "--include-with-prefix") == 0) - || (opteq (&skip, &arg, text, "--include-with-prefix-before") == 0) - || (opteq (&skip, &arg, text, "--include-with-prefix-after") == 0)) - 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) - opt = OPTION_E; - else if ((opteq (&skip, &arg, text, "--print-file-name") == 0) - || (strcmp (text, "--print-libgcc-file-name") == 0) - || (strcmp (text, "--print-multi-lib") == 0) - || (strcmp (text, "--print-multi-directory") == 0) - || (opteq (&skip, &arg, text, "--print-prog-name") == 0)) - opt = OPTION_P; - else if ((strcmp (text, "-nostdlib") == 0) - || (strcmp (text, "--no-standard-libraries") == 0) - || (strcmp (text, "-nodefaultlibs") == 0)) - opt = OPTION_nostdlib; - else if (strcmp (text, "-fsyntax-only") == 0) - opt = OPTION_syntax_only; - else if (opteq (&skip, &arg, text, "--use-version") == 0) - opt = OPTION_V; - else if (strcmp (text, "--verbose") == 0) - opt = OPTION_v; - else if (strcmp (text, "--version") == 0) - opt = OPTION_version; - else if (strcmp (text, "-Xlinker") == 0) - skip = 1; - else if ((opteq (&skip, &arg, text, "--assert") == 0) - || (opteq (&skip, &arg, text, "--define-macro") == 0) - || (opteq (&skip, &arg, text, "--dump") == 0) - || (opteq (&skip, &arg, text, "--dumpbase") == 0) - || (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, "--machine") == 0) - || (opteq (&skip, &arg, text, "--target") == 0) - || (opteq (&skip, &arg, text, "--undefine-macro") == 0)) - ; - else - skip = 0; - } - - if (xopt != NULL) - *xopt = opt; - if (xskip != NULL) - *xskip = skip; - if (xarg != NULL) - { - if ((arg != NULL) - && (arg[0] == '\0')) - *xarg = NULL; - else - *xarg = arg; - } -} - -static void -append_arg (arg) - char *arg; -{ - static int newargsize; - -#if 0 - fprintf (stderr, "`%s'\n", arg); -#endif - - if ((newargv == xargv) - && (arg == xargv[newargc])) - { - ++newargc; - return; /* Nothing new here. */ - } - - if (newargv == xargv) - { /* Make new arglist. */ - int i; - - newargsize = (xargc << 2) + 20; - newargv = (char **) malloc (newargsize * sizeof (char *)); - - /* Copy what has been done so far. */ - for (i = 0; i < newargc; ++i) - newargv[i] = xargv[i]; - } - - if (newargc == newargsize) - fatal ("overflowed output arg list for `%s'", 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 -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)) || defined (__CYGWIN32__) - -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) && !defined (__CYGWIN32__) - -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 -#if defined(_WIN32) && !defined(__CYGWIN32__) - 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; - char **argv; -{ - register int i = 0; - register char *p; - int verbose = 0; - 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. */ - char *library = "-lf2c"; - - /* 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, 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; - - /* The name of the compiler we will want to run---by default, it - will be the definition of `GCC_NAME', e.g., `gcc'. */ - char *gcc = GCC_NAME; - - /* 0 => -xnone in effect on input/output - 1 => -xfoo in effect on input/output - 2 => -xnone in effect on input, -xf77 on output - 3 => -xnone in effect on input, -xf77-cpp-input on output. - 4 => -xnone in effect on input, -xratfor on output. */ - int saw_speclang = 0; - - /* 0 => initial/reset state - 1 => last arg was -l - 2 => last two args were -l -lm. */ - int saw_library = 0; - - /* Initialize for append_arg(). */ - xargc = argc; - newargv = xargv = argv; - newargc = 0; - - append_arg (argv[0]); - - p = argv[0] + strlen (argv[0]); - while (p != argv[0] && p[-1] != '/') - --p; - programname = p; - - if (argc == 1) - fatal ("No input files specified.\n"); - -#ifndef __MSDOS__ - /* We do a little magic to find out where the main gcc executable - is. If they ran us as /usr/local/bin/g77, then we will look - for /usr/local/bin/gcc; similarly, if they just ran us as `g77', - we'll just look for `gcc'. */ - if (p != argv[0]) - { - *--p = '\0'; - gcc = (char *) malloc ((strlen (argv[0]) + 1 + strlen (GCC_NAME) + 1) - * sizeof (char)); - sprintf (gcc, "%s/%s", argv[0], GCC_NAME); - } -#endif - - /* First pass through arglist. - - If -nostdlib or a "turn-off-linking" option is anywhere in the - command line, don't do any library-option processing (except - relating to -x). Also, if -v is specified, but no other options - that do anything special (allowing -V version, etc.), remember - to add special stuff to make gcc command actually invoke all - the different phases of the compilation process so all the version - numbers can be seen. - - Also, here is where all problems with missing arguments to options - are caught. If this loop is exited normally, it means all options - have the appropriate number of arguments as far as the rest of this - program is concerned. */ - - for (i = 1; i < argc; ++i) - { - 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]); - - switch (opt) - { - case OPTION_nostdlib: - case OPTION_c: - case OPTION_S: - case OPTION_syntax_only: - case OPTION_E: - case OPTION_M: - case OPTION_MM: - /* These options disable linking entirely or linking of the - standard libraries. */ - library = NULL; - 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) - fprintf (stderr, "g77 version %s\n", ffe_version_string); - verbose = 1; - break; - - case OPTION_b: - case OPTION_B: - case OPTION_L: - case OPTION_driver: - case OPTION_i: - case OPTION_V: - /* These options are useful in conjunction with -v to get - appropriate version info. */ - break; - - case OPTION_version: - printf ("\ -GNU Fortran %s\n\ -Copyright (C) 1997 Free Software Foundation, Inc.\n\ -For more version information on components of the GNU Fortran\n\ -compilation system, especially useful when reporting bugs,\n\ -type the command `g77 --verbose'.\n\ -\n\ -GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\ -You may redistribute copies of GNU Fortran\n\ -under the terms of the GNU General Public License.\n\ -For more information about these matters, see the file named COPYING\n\ -or type the command `info -f g77 Copying'.\n\ -", ffe_version_string); - exit (0); - break; - - case OPTION_help: - printf ("\ -Usage: g77 [OPTION]... FORTRAN-SOURCE...\n\ -\n\ -Compile and link Fortran source code to produce an executable program,\n\ -which by default is named `a.out', and can be invoked with the UNIX\n\ -command `./a.out'.\n\ -\n\ -Options:\n\ ---debug include debugging information in executable.\n\ ---driver=COMMAND specify preprocessor/compiler/linker driver\n\ - to use instead of the default `gcc'.\n\ ---help display this help and exit.\n\ ---optimize[=LEVEL] take extra time and memory to make generated\n\ - executable run faster. LEVEL is 0 for no\n\ - optimization, 1 for normal optimization, and\n\ - increases through 3 for more optimization.\n\ ---output=PROGRAM name the executable PROGRAM instead of a.out;\n\ - invoke with the command `./PROGRAM'.\n\ ---version display version information and exit.\n\ -\n\ -Many other options exist to tailor the compilation process, specify\n\ -the dialect of the Fortran source code, specify details of the\n\ -code-generation methodology, and so on.\n\ -\n\ -For more information on g77 and gcc, type the commands `info -f g77'\n\ -and `info -f gcc' to read the Info documentation on these commands.\n\ -\n\ -Report bugs to fortran@gnu.ai.mit.edu.\n"); - exit (0); - break; - - default: - add_version_magic = 0; - break; - } - - /* This is the one place we check for missing arguments in the - program. */ - - if (i + skip < argc) - i += skip; - else - fatal ("argument to `%s' missing\n", argv[i]); - } - - if ((n_outfiles != 0) && (n_infiles == 0)) - fatal ("No input files; unwilling to write output files"); - - /* Second pass through arglist, transforming arguments as appropriate. */ - - for (i = 1; i < argc; ++i) - { - if (argv[i][0] == '\0') - append_arg (argv[i]); /* Interesting. Just append as is. */ - - else if ((argv[i][0] == '-') && (argv[i][1] != 'l')) - { - /* Not a filename or library. */ - - if (saw_library == 1) /* -l. */ - append_arg ("-lm"); - saw_library = 0; - - lookup_option (&opt, &skip, &arg, argv[i]); - - if (argv[i][1] == '\0') - append_arg (argv[i]); /* "-" == Standard input. */ - - else if (opt == OPTION_x) - { - /* Track input language. */ - char *lang; - - if (arg == NULL) - lang = argv[i+1]; - else - lang = arg; - - saw_speclang = (strcmp (lang, "none") != 0); - } - else if (opt == OPTION_driver) - { - if (arg == NULL) - gcc = argv[i+1]; - else - gcc = arg; - i += skip; - continue; /* Don't append args to new list. */ - } - append_arg (argv[i]); - for (; skip != 0; --skip) - append_arg (argv[++i]); - } - else - { /* A filename/library, not an option. */ - int len; - int want_speclang; - - /* Here, always append the arg _after_ other stuff, possibly. */ - - if (saw_speclang == 1) - saw_library = 0; /* -xfoo currently active. */ - /* Put -xf77 and -xnone around list of filenames ending in - .F or .f, but don't include other filenames or libraries - in that list. */ - else if ((argv[i][0] != '-') /* Not a library. */ - && (len = strlen (argv[i])) > 2 - && ((argv[i][len - 1] == 'F') - || (argv[i][len - 1] == 'f') - || (argv[i][len - 1] == 'r')) - && argv[i][len - 2] == '.') - { /* filename.f or filename.F. or filename.r */ - if (saw_library == 1) /* -l. */ - append_arg ("-lm"); - saw_library = 0; - switch (argv[i][len - 1]) - { - case 'f': - want_speclang = 2; - break; - case 'F': - want_speclang = 3; - break; - case 'r': - want_speclang = 4; - break; - default: - break; - } - if (saw_speclang != want_speclang) - { - switch (want_speclang) - { - case 2: - append_arg ("-xf77"); - break; - case 3: - append_arg ("-xf77-cpp-input"); - break; - case 4: - append_arg ("-xratfor"); - break; - default: - break; - } - saw_speclang = want_speclang; - } - } - else - { /* -lfoo or "alien" filename. */ - if (saw_speclang) - append_arg ("-xnone"); - saw_speclang = 0; - - if (strcmp (argv[i], "-lm") == 0 - || strcmp (argv[i], "-lmath") == 0) - { - if (saw_library == 1) - saw_library = 2; /* -l -lm. */ - else if (library) - { - append_arg (library); - saw_library = 2; /* -l -lm. */ - } - } - else if ((library != NULL) - && (strcmp (argv[i], library) == 0)) - saw_library = 1; /* -l. */ - else - { /* "Alien" library or filename. */ - if (saw_library == 1) - append_arg ("-lm"); - saw_library = 0; - } - } - append_arg (argv[i]); - } - } - - /* Add -lf2c -lm as necessary. */ - - if (!add_version_magic && library) - { /* Doing a link and no -nostdlib. */ - if (saw_speclang) - append_arg ("-xnone"); - switch (saw_library) - { - case 0: - append_arg (library); - case 1: - append_arg ("-lm"); - default: - break; - } - } - 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 (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); - --newargc; /* Don't count null arg at end. */ - - newargv[0] = gcc; /* This is safe even if newargv == xargv. */ - - if (verbose) - { -#if 0 - if (newargv == xargv) - fprintf (stderr, "[Original:]"); -#endif - - for (i = 0; i < newargc; i++) - fprintf (stderr, " %s", newargv[i]); - fprintf (stderr, "\n"); - } - - 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 */ diff --git a/gcc/f/g77spec.c b/gcc/f/g77spec.c new file mode 100644 index 0000000..051d5d4 --- /dev/null +++ b/gcc/f/g77spec.c @@ -0,0 +1,269 @@ +/* Specific flags and argument handling of the Fortran front-end. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" + +#include +#include + +#include "gansidecl.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +/* This bit is set if we saw a `-xfoo' language specification. */ +#define LANGSPEC (1<<1) +/* This bit is set if they did `-lm' or `-lmath'. */ +#define MATHLIB (1<<2) +/* This bit is set if they did `-lc'. */ +#define WITHLIBC (1<<3) + +#ifndef MATH_LIBRARY +#define MATH_LIBRARY "-lm" +#endif + +#ifndef FORTRAN_LIBRARY +#define FORTRAN_LIBRARY "-lf2c" +#endif + +extern char *xmalloc PROTO((size_t)); + +void +lang_specific_driver (fn, in_argc, in_argv) + void (*fn)(); + int *in_argc; + char ***in_argv; +{ + int i, j; + + /* If non-zero, the user gave us the `-v' flag. */ + int saw_verbose_flag = 0; + + /* This will be 0 if we encounter a situation where we should not + link in libstdf77. */ + int library = 1; + + /* The number of arguments being added to what's in argv, other than + libraries. We use this to track the number of times we've inserted + -xf77/-xnone. */ + int added = 2; + + /* Used to track options that take arguments, so we don't go wrapping + those with -xf77/-xnone. */ + char *quote = NULL; + + /* The new argument list will be contained in this. */ + char **arglist; + + /* Non-zero if we saw a `-xfoo' language specification on the + command line. Used to avoid adding our own -xf77 if the user + already gave a language for the file. */ + int saw_speclang = 0; + + /* "-lm" or "-lmath" if it appears on the command line. */ + char *saw_math = 0; + + /* "-lc" if it appears on the command line. */ + char *saw_libc = 0; + + /* An array used to flag each argument that needs a bit set for + LANGSPEC, MATHLIB, or WITHLIBC. */ + int *args; + + /* By default, we throw on the math library. */ + int need_math = 1; + + /* The total number of arguments with the new stuff. */ + int argc; + + /* The argument list. */ + char **argv; + + /* The total number of arguments with the new stuff. */ + int num_args = 1; + + argc = *in_argc; + argv = *in_argv; + + args = (int *) xmalloc (argc * sizeof (int)); + bzero ((char *) args, argc * sizeof (int)); + + for (i = 1; i < argc; i++) + { + /* If the previous option took an argument, we swallow it here. */ + if (quote) + { + quote = NULL; + continue; + } + + /* We don't do this anymore, since we don't get them with minus + signs on them. */ + if (argv[i][0] == '\0' || argv[i][1] == '\0') + continue; + + if (argv[i][0] == '-') + { + if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0 + || strcmp (argv[i], "-nodefaultlibs") == 0)) + { + library = 0; + } + else if (strcmp (argv[i], "-lm") == 0 + || strcmp (argv[i], "-lmath") == 0 +#ifdef ALT_LIBM + || strcmp (argv[i], ALT_LIBM) == 0 +#endif + ) + { + args[i] |= MATHLIB; + need_math = 0; + } + else if (strcmp (argv[i], "-lc") == 0) + args[i] |= WITHLIBC; + else if (strcmp (argv[i], "-v") == 0) + { + saw_verbose_flag = 1; + if (argc == 2) + { + /* If they only gave us `-v', don't try to link in libf2c. */ + library = 0; + } + } + else if (strncmp (argv[i], "-x", 2) == 0) + saw_speclang = 1; + else if (((argv[i][2] == '\0' + && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL) + || strcmp (argv[i], "-Tdata") == 0)) + quote = argv[i]; + else if (library != 0 && ((argv[i][2] == '\0' + && (char *) strchr ("cSEM", argv[i][1]) != NULL) + || strcmp (argv[i], "-MM") == 0)) + { + /* Don't specify libraries if we won't link, since that would + cause a warning. */ + library = 0; + added -= 2; + } + else + /* Pass other options through. */ + continue; + } + else + { + int len; + + if (saw_speclang) + { + saw_speclang = 0; + continue; + } + + /* If the filename ends in .c or .i, put options around it. + But not if a specified -x option is currently active. */ + len = strlen (argv[i]); + if (len > 2 + && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i') + && argv[i][len - 2] == '.') + { + args[i] |= LANGSPEC; + added += 2; + } + } + } + + if (quote) + (*fn) ("argument to `%s' missing\n", quote); + + /* If we know we don't have to do anything, bail now. */ + if (! added && ! library) + { + free (args); + return; + } + + num_args = argc + added + need_math; + arglist = (char **) xmalloc (num_args * sizeof (char *)); + + /* NOTE: We start at 1 now, not 0. */ + for (i = 0, j = 0; i < argc; i++, j++) + { + arglist[j] = argv[i]; + + /* Make sure -lf2c is before the math library, since libf2c + itself uses those math routines. */ + if (!saw_math && (args[i] & MATHLIB) && library) + { + --j; + saw_math = argv[i]; + } + + if (!saw_libc && (args[i] & WITHLIBC) && library) + { + --j; + saw_libc = argv[i]; + } + + /* Wrap foo.c and foo.i files in a language specification to + force the gcc compiler driver to run cc1plus on them. */ + if (args[i] & LANGSPEC) + { + int len = strlen (argv[i]); + switch (argv[i][len - 1]) + { + case 'F': + arglist[j++] = "-xf77-cpp-input"; + break; + case 'r': + /* Don't do ratfor for ".for". */ + if (argv[i][len - 2] == '.') + { + arglist[j++] = "-xratfor"; + break; + } + default: + arglist[j++] = "-xf77"; + break; + } + arglist[j++] = argv[i]; + arglist[j] = "-xnone"; + } + } + + /* Add `-lf2c' if we haven't already done so. */ + if (library) + arglist[j++] = FORTRAN_LIBRARY; + if (saw_math) + arglist[j++] = saw_math; + else if (library) + arglist[j++] = MATH_LIBRARY; + if (saw_libc) + arglist[j++] = saw_libc; + + arglist[j] = NULL; + + *in_argc = j; + *in_argv = arglist; +} -- 2.7.4