/* Specific flags and argument handling of the Fortran front-end.
- Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
- Foundation, Inc.
+ Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
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)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
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. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
/* This file is copied more or less verbatim from g77. */
/* This file contains a filter for the main `gcc' driver, which is
replicated for the `gfortran' driver by adding this filter. The purpose
#include "config.h"
#include "system.h"
+#include "coretypes.h"
#include "gcc.h"
+#include "opts.h"
-#include "coretypes.h"
#include "tm.h"
+#include "intl.h"
#ifndef MATH_LIBRARY
-#define MATH_LIBRARY "-lm"
-#endif
-
-#ifndef FORTRAN_INIT
-#define FORTRAN_INIT "-lgfortranbegin"
+#define MATH_LIBRARY "m"
#endif
#ifndef FORTRAN_LIBRARY
-#define FORTRAN_LIBRARY "-lgfortran"
+#define FORTRAN_LIBRARY "gfortran"
#endif
-/* 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_E, /* Aka --preprocess. */
- OPTION_help, /* --help. */
- OPTION_i, /* -imacros, -include, -include-*. */
- OPTION_l,
- OPTION_L, /* Aka --library-directory. */
- OPTION_nostdlib, /* Aka --no-standard-libraries, or
- -nodefaultlibs. */
- OPTION_o, /* Aka --output. */
- 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;
+/* Name of the spec file. */
+#define SPEC_FILE "libgfortran.spec"
/* The original argument list and related info is copied here. */
-static int g77_xargc;
-static const char *const *g77_xargv;
-static void lookup_option (Option *, int *, const char **, const char *);
-static void append_arg (const char *);
+static unsigned int g77_xargc;
+static const struct cl_decoded_option *g77_x_decoded_options;
+static void append_arg (const struct cl_decoded_option *);
/* The new argument list will be built here. */
-static int g77_newargc;
-static const char **g77_newargv;
-
-const struct spec_function lang_specific_spec_functions[] = {{0,0}};
+static unsigned int g77_newargc;
+static struct cl_decoded_option *g77_new_decoded_options;
-/* --- This comes from gcc.c (2.8.1) verbatim: */
+/* The path to the spec file. */
+char *spec_file = NULL;
-/* This defines which switch letters take arguments. */
-#ifndef SWITCH_TAKES_ARG
-#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
-#endif
-
-/* This defines which multi-letter switches take arguments. */
+/* Return full path name of spec file if it is in DIR, or NULL if
+ not. */
+static char *
+find_spec_file (const char *dir)
+{
+ const char dirsep_string[] = { DIR_SEPARATOR, '\0' };
+ char *spec;
+ struct stat sb;
+
+ spec = XNEWVEC (char, strlen (dir) + sizeof (SPEC_FILE) + 4);
+ strcpy (spec, dir);
+ strcat (spec, dirsep_string);
+ strcat (spec, SPEC_FILE);
+ if (!stat (spec, &sb))
+ return spec;
+ free (spec);
+ return NULL;
+}
-#ifndef WORD_SWITCH_TAKES_ARG
-#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
-#endif
-/* --- End of verbatim. */
+/* Return whether strings S1 and S2 are both NULL or both the same
+ string. */
-/* 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 bool
+strings_same (const char *s1, const char *s2)
+{
+ return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0);
+}
- Note that this also assumes gcc.c's pass converting long options
- to short ones, where available, has already been run. */
+/* Return whether decoded option structures OPT1 and OPT2 are the
+ same. */
-static void
-lookup_option (Option *xopt, int *xskip, const char **xarg, const char *text)
+static bool
+options_same (const struct cl_decoded_option *opt1,
+ const struct cl_decoded_option *opt2)
{
- Option opt = OPTION_;
- int skip;
- const char *arg = NULL;
-
- if ((skip = SWITCH_TAKES_ARG (text[1])))
- skip -= (text[2] != '\0'); /* See gcc.c. */
-
- 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, 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] == 'x')
- opt = OPTION_x, arg = text + 2;
- else
- {
- if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0) /* See gcc.c. */
- ;
- else if (!strcmp (text, "-fhelp")) /* Really --help!! */
- opt = OPTION_help;
- else if (!strcmp (text, "-nostdlib")
- || !strcmp (text, "-nodefaultlibs"))
- opt = OPTION_nostdlib;
- else if (!strcmp (text, "-fsyntax-only"))
- opt = OPTION_syntax_only;
- else if (!strcmp (text, "-dumpversion"))
- opt = OPTION_version;
- else if (!strcmp (text, "-fversion")) /* Really --version!! */
- opt = OPTION_version;
- else if (!strcmp (text, "-Xlinker") || !strcmp (text, "-specs"))
- skip = 1;
- 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;
- }
+ return (opt1->opt_index == opt2->opt_index
+ && strings_same (opt1->arg, opt2->arg)
+ && strings_same (opt1->orig_option_with_args_text,
+ opt2->orig_option_with_args_text)
+ && strings_same (opt1->canonical_option[0],
+ opt2->canonical_option[0])
+ && strings_same (opt1->canonical_option[1],
+ opt2->canonical_option[1])
+ && strings_same (opt1->canonical_option[2],
+ opt2->canonical_option[2])
+ && strings_same (opt1->canonical_option[3],
+ opt2->canonical_option[3])
+ && (opt1->canonical_option_num_elements
+ == opt2->canonical_option_num_elements)
+ && opt1->value == opt2->value
+ && opt1->errors == opt2->errors);
}
/* Append another argument to the list being built. As long as it is
the new arg count. Otherwise allocate a new list, etc. */
static void
-append_arg (const char *arg)
+append_arg (const struct cl_decoded_option *arg)
{
- static int newargsize;
-
-#if 0
- fprintf (stderr, "`%s'\n", arg);
-#endif
+ static unsigned int newargsize;
- if (g77_newargv == g77_xargv
+ if (g77_new_decoded_options == g77_x_decoded_options
&& g77_newargc < g77_xargc
- && (arg == g77_xargv[g77_newargc]
- || !strcmp (arg, g77_xargv[g77_newargc])))
+ && options_same (arg, &g77_x_decoded_options[g77_newargc]))
{
++g77_newargc;
- return; /* Nothing new here. */
+ return; /* Nothing new here. */
}
- if (g77_newargv == g77_xargv)
- { /* Make new arglist. */
- int i;
+ if (g77_new_decoded_options == g77_x_decoded_options)
+ { /* Make new arglist. */
+ unsigned int i;
- newargsize = (g77_xargc << 2) + 20; /* This should handle all. */
- g77_newargv = (const char **) xmalloc (newargsize * sizeof (char *));
+ newargsize = (g77_xargc << 2) + 20; /* This should handle all. */
+ g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
/* Copy what has been done so far. */
for (i = 0; i < g77_newargc; ++i)
- g77_newargv[i] = g77_xargv[i];
+ g77_new_decoded_options[i] = g77_x_decoded_options[i];
}
if (g77_newargc == newargsize)
- fatal ("overflowed output arg list for `%s'", arg);
+ fatal_error ("overflowed output arg list for %qs",
+ arg->orig_option_with_args_text);
+
+ g77_new_decoded_options[g77_newargc++] = *arg;
+}
+
+/* Append an option described by OPT_INDEX, ARG and VALUE to the list
+ being built. */
+static void
+append_option (size_t opt_index, const char *arg, int value)
+{
+ struct cl_decoded_option decoded;
- g77_newargv[g77_newargc++] = arg;
+ generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
+ append_arg (&decoded);
+}
+
+/* Append a libgfortran argument to the list being built. If
+ FORCE_STATIC, ensure the library is linked statically. */
+
+static void
+add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED)
+{
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ if (force_static)
+ append_option (OPT_Wl_, "-Bstatic", 1);
+#endif
+ append_option (OPT_l, FORTRAN_LIBRARY, 1);
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ if (force_static)
+ append_option (OPT_Wl_, "-Bdynamic", 1);
+#endif
}
void
-lang_specific_driver (int *in_argc, const char *const **in_argv,
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+ unsigned int *in_decoded_options_count,
int *in_added_libraries ATTRIBUTE_UNUSED)
{
- int argc = *in_argc;
- const char *const *argv = *in_argv;
- int i;
+ unsigned int argc = *in_decoded_options_count;
+ struct cl_decoded_option *decoded_options = *in_decoded_options;
+ unsigned int i;
int verbose = 0;
- Option opt;
- int skip;
- const char *arg;
/* This will be NULL if we encounter a situation where we should not
link in libf2c. */
2 => last two args were -l<library> -lm. */
int saw_library = 0;
- /* 0 => initial/reset state
- 1 => FORTRAN_INIT linked in */
- int use_init = 0;
-
/* By default, we throw on the math library if we have one. */
int need_math = (MATH_LIBRARY[0] != '\0');
+ /* Whether we should link a static libgfortran. */
+ int static_lib = 0;
+
+ /* Whether we need to link statically. */
+ int static_linking = 0;
+
/* The number of input and output files in the incoming arg list. */
int n_infiles = 0;
int n_outfiles = 0;
#if 0
fprintf (stderr, "Incoming:");
for (i = 0; i < argc; i++)
- fprintf (stderr, " %s", argv[i]);
+ fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text);
fprintf (stderr, "\n");
#endif
g77_xargc = argc;
- g77_xargv = argv;
+ g77_x_decoded_options = decoded_options;
g77_newargc = 0;
- g77_newargv = (const char **) argv;
+ g77_new_decoded_options = decoded_options;
/* 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. */
+ relating to -x). */
for (i = 1; i < argc; ++i)
{
- if ((argv[i][0] == '+') && (argv[i][1] == 'e'))
- {
- continue;
- }
-
- if ((argv[i][0] != '-') || (argv[i][1] == '\0'))
+ switch (decoded_options[i].opt_index)
{
+ case OPT_SPECIAL_input_file:
++n_infiles;
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 OPT_nostdlib:
+ case OPT_nodefaultlibs:
+ case OPT_c:
+ case OPT_S:
+ case OPT_fsyntax_only:
+ case OPT_E:
/* These options disable linking entirely or linking of the
standard libraries. */
library = 0;
break;
- case OPTION_l:
+ case OPT_static_libgfortran:
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ static_lib = 1;
+#endif
+ break;
+
+ case OPT_static:
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ static_linking = 1;
+#endif
+ break;
+
+ case OPT_l:
++n_infiles;
break;
- case OPTION_o:
+ case OPT_o:
++n_outfiles;
break;
- case OPTION_v:
+ case OPT_v:
verbose = 1;
break;
- case OPTION_b:
- case OPTION_B:
- case OPTION_L:
- 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 95 (GCC %s)\n\
-Copyright (C) 2004 Free Software Foundation, Inc.\n\
-\n\
-GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
+ case OPT__version:
+ printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
+ printf ("Copyright %s 2010 Free Software Foundation, Inc.\n\n",
+ _("(C)"));
+ printf (_("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\
-", version_string);
+For more information about these matters, see the file named COPYING\n\n"));
exit (0);
break;
- case OPTION_help:
+ case OPT__help:
/* Let gcc.c handle this, as it has a really
cool facility for handling --help and --verbose --help. */
return;
- default:
+ case OPT_L:
+ if (!spec_file)
+ spec_file = find_spec_file (decoded_options[i].arg);
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", argv[i]);
+ default:
+ break;
+ }
}
if ((n_outfiles != 0) && (n_infiles == 0))
- fatal ("no input files; unwilling to write output files");
+ fatal_error ("no input files; unwilling to write output files");
/* If there are no input files, no need for the library. */
if (n_infiles == 0)
/* Second pass through arglist, transforming arguments as appropriate. */
- append_arg (argv[0]); /* Start with command name, of course. */
+ append_arg (&decoded_options[0]); /* Start with command name, of course. */
for (i = 1; i < argc; ++i)
{
- if (argv[i][0] == '\0')
+ if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
{
- append_arg (argv[i]); /* Interesting. Just append as is. */
+ append_arg (&decoded_options[i]);
continue;
}
- if ((argv[i][0] == '-') && (argv[i][1] == 'M'))
- {
- char *p;
-
- if (argv[i][2] == '\0')
- {
- p = xmalloc (strlen (argv[i + 1]) + 2);
- p[0] = '-';
- p[1] = 'J';
- strcpy (&p[2], argv[i + 1]);
- i++;
- }
- else
- {
- p = xmalloc (strlen (argv[i]) + 1);
- strcpy (p, argv[i]);
- }
- append_arg (p);
- continue;
- }
-
- if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
+ if (decoded_options[i].opt_index == OPT_SPECIAL_input_file
+ && decoded_options[i].arg[0] == '\0')
{
- /* Not a filename or library. */
+ /* Interesting. Just append as is. */
+ append_arg (&decoded_options[i]);
+ continue;
+ }
- if (saw_library == 1 && need_math) /* -l<library>. */
- append_arg (MATH_LIBRARY);
+ if (decoded_options[i].opt_index != OPT_l
+ && (decoded_options[i].opt_index != OPT_SPECIAL_input_file
+ || strcmp (decoded_options[i].arg, "-") == 0))
+ {
+ /* Not a filename or library. */
- saw_library = 0;
+ if (saw_library == 1 && need_math) /* -l<library>. */
+ append_option (OPT_l, MATH_LIBRARY, 1);
- lookup_option (&opt, &skip, &arg, argv[i]);
+ saw_library = 0;
- if (argv[i][1] == '\0')
+ if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
{
- append_arg (argv[i]); /* "-" == Standard input. */
+ append_arg (&decoded_options[i]); /* "-" == Standard input. */
continue;
}
- if (opt == OPTION_x)
+ if (decoded_options[i].opt_index == OPT_x)
{
- /* Track input language. */
- const char *lang;
-
- if (arg == NULL)
- lang = argv[i + 1];
- else
- lang = arg;
+ /* Track input language. */
+ const char *lang = decoded_options[i].arg;
saw_speclang = (strcmp (lang, "none") != 0);
}
- append_arg (argv[i]);
-
- for (; skip != 0; --skip)
- append_arg (argv[++i]);
+ append_arg (&decoded_options[i]);
continue;
}
- /* A filename/library, not an option. */
+ /* A filename/library, not an option. */
if (saw_speclang)
- saw_library = 0; /* -xfoo currently active. */
+ saw_library = 0; /* -xfoo currently active. */
else
- { /* -lfoo or filename. */
- if (strcmp (argv[i], MATH_LIBRARY) == 0)
+ { /* -lfoo or filename. */
+ if (decoded_options[i].opt_index == OPT_l
+ && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
{
if (saw_library == 1)
- saw_library = 2; /* -l<library> -lm. */
+ saw_library = 2; /* -l<library> -lm. */
else
- {
- if (0 == use_init)
- {
- append_arg (FORTRAN_INIT);
- use_init = 1;
- }
- append_arg (FORTRAN_LIBRARY);
- }
+ add_arg_libgfortran (static_lib && !static_linking);
+ }
+ else if (decoded_options[i].opt_index == OPT_l
+ && strcmp (decoded_options[i].arg, FORTRAN_LIBRARY) == 0)
+ {
+ saw_library = 1; /* -l<library>. */
+ add_arg_libgfortran (static_lib && !static_linking);
+ continue;
}
- else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
- saw_library = 1; /* -l<library>. */
else
- { /* Other library, or filename. */
+ { /* Other library, or filename. */
if (saw_library == 1 && need_math)
- append_arg (MATH_LIBRARY);
+ append_option (OPT_l, MATH_LIBRARY, 1);
saw_library = 0;
}
}
- append_arg (argv[i]);
+ append_arg (&decoded_options[i]);
}
- /* Append `-lg2c -lm' as necessary. */
+ /* Append `-lgfortran -lm' as necessary. */
if (library)
- { /* Doing a link and no -nostdlib. */
+ { /* Doing a link and no -nostdlib. */
if (saw_speclang)
- append_arg ("-xnone");
+ append_option (OPT_x, "none", 1);
switch (saw_library)
{
case 0:
- if (0 == use_init)
- {
- append_arg (FORTRAN_INIT);
- use_init = 1;
- }
- append_arg (library);
+ add_arg_libgfortran (static_lib && !static_linking);
+ /* Fall through. */
+
case 1:
if (need_math)
- append_arg (MATH_LIBRARY);
+ append_option (OPT_l, MATH_LIBRARY, 1);
default:
break;
}
#ifdef ENABLE_SHARED_LIBGCC
if (library)
{
- int i;
+ unsigned int i;
for (i = 1; i < g77_newargc; i++)
- if (g77_newargv[i][0] == '-')
- if (strcmp (g77_newargv[i], "-static-libgcc") == 0
- || strcmp (g77_newargv[i], "-static") == 0)
- break;
+ if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
+ || g77_new_decoded_options[i].opt_index == OPT_static)
+ break;
if (i == g77_newargc)
- append_arg ("-shared-libgcc");
+ append_option (OPT_shared_libgcc, NULL, 1);
}
#endif
- if (verbose && g77_newargv != g77_xargv)
+ /* Read the specs file corresponding to libgfortran.
+ If we didn't find the spec file on the -L path, we load it
+ via lang_specific_pre_link. */
+ if (spec_file)
+ append_option (OPT_specs_, spec_file, 1);
+
+ if (verbose && g77_new_decoded_options != g77_x_decoded_options)
{
- fprintf (stderr, "Driving:");
+ fprintf (stderr, _("Driving:"));
for (i = 0; i < g77_newargc; i++)
- fprintf (stderr, " %s", g77_newargv[i]);
+ fprintf (stderr, " %s",
+ g77_new_decoded_options[i].orig_option_with_args_text);
fprintf (stderr, "\n");
}
- *in_argc = g77_newargc;
- *in_argv = g77_newargv;
+ *in_decoded_options_count = g77_newargc;
+ *in_decoded_options = g77_new_decoded_options;
}
-/* Called before linking. Returns 0 on success and -1 on failure. */
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
int
-lang_specific_pre_link (void) /* Not used for F77. */
+lang_specific_pre_link (void)
{
+ if (spec_file)
+ free (spec_file);
+ else
+ do_spec ("%:include(libgfortran.spec)");
+
return 0;
}
-/* Number of extra output files that lang_specific_pre_link may generate. */
-int lang_specific_extra_outfiles = 0; /* Not used for F77. */
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for F77. */