From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- gcc/fortran/gfortranspec.c | 487 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 487 insertions(+) create mode 100644 gcc/fortran/gfortranspec.c (limited to 'gcc/fortran/gfortranspec.c') diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c new file mode 100644 index 000000000..36c7b4429 --- /dev/null +++ b/gcc/fortran/gfortranspec.c @@ -0,0 +1,487 @@ +/* Specific flags and argument handling of the Fortran front-end. + Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + +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 3, 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 GCC; see the file COPYING3. If not see +. */ + +/* 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 + of this filter 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 95(gfortran), we do the following to the argument list + before passing it to `gcc': + + 1. Make sure `-lgfortran -lm' is at the end of the list. + + 2. Make sure each time `-lgfortran' or `-lm' is seen, it forms + part of the series `-lgfortran -lm'. + + #1 and #2 are not done if `-nostdlib' or any option that disables + the linking phase is present, or if `-xfoo' is in effect. Note that + a lack of source files or -l options disables linking. + + This program was originally made out of gcc/cp/g++spec.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. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "gcc.h" +#include "opts.h" + +#include "tm.h" +#include "intl.h" + +#ifndef MATH_LIBRARY +#define MATH_LIBRARY "m" +#endif + +#ifndef FORTRAN_LIBRARY +#define FORTRAN_LIBRARY "gfortran" +#endif + +/* Name of the spec file. */ +#define SPEC_FILE "libgfortran.spec" + +/* The original argument list and related info is copied here. */ +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 unsigned int g77_newargc; +static struct cl_decoded_option *g77_new_decoded_options; + +/* The path to the spec file. */ +static char *spec_file = NULL; + +/* This will be NULL if we encounter a situation where we should not + link in the fortran libraries. */ +static const char *library = NULL; + + +/* 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; +} + + +/* Return whether strings S1 and S2 are both NULL or both the same + string. */ + +static bool +strings_same (const char *s1, const char *s2) +{ + return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0); +} + +/* Return whether decoded option structures OPT1 and OPT2 are the + same. */ + +static bool +options_same (const struct cl_decoded_option *opt1, + const struct cl_decoded_option *opt2) +{ + 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 + identical to the corresponding arg in the original list, just increment + the new arg count. Otherwise allocate a new list, etc. */ + +static void +append_arg (const struct cl_decoded_option *arg) +{ + static unsigned int newargsize; + + if (g77_new_decoded_options == g77_x_decoded_options + && g77_newargc < g77_xargc + && options_same (arg, &g77_x_decoded_options[g77_newargc])) + { + ++g77_newargc; + return; /* Nothing new here. */ + } + + 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_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize); + + /* Copy what has been done so far. */ + for (i = 0; i < g77_newargc; ++i) + g77_new_decoded_options[i] = g77_x_decoded_options[i]; + } + + if (g77_newargc == newargsize) + 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; + + 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_, LD_STATIC_OPTION, 1); +#endif + append_option (OPT_l, FORTRAN_LIBRARY, 1); +#ifdef HAVE_LD_STATIC_DYNAMIC + if (force_static) + append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1); +#endif +} + +void +lang_specific_driver (struct cl_decoded_option **in_decoded_options, + unsigned int *in_decoded_options_count, + int *in_added_libraries ATTRIBUTE_UNUSED) +{ + unsigned int argc = *in_decoded_options_count; + struct cl_decoded_option *decoded_options = *in_decoded_options; + unsigned int i; + int verbose = 0; + + /* 0 => -xnone in effect. + 1 => -xfoo in effect. */ + int saw_speclang = 0; + + /* 0 => initial/reset state + 1 => last arg was -l + 2 => last two args were -l -lm. */ + int saw_library = 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; + + library = FORTRAN_LIBRARY; + +#if 0 + fprintf (stderr, "Incoming:"); + for (i = 0; i < argc; i++) + fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text); + fprintf (stderr, "\n"); +#endif + + g77_xargc = argc; + g77_x_decoded_options = decoded_options; + g77_newargc = 0; + 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). */ + + for (i = 1; i < argc; ++i) + { + if (decoded_options[i].errors & CL_ERR_MISSING_ARG) + continue; + + switch (decoded_options[i].opt_index) + { + case OPT_SPECIAL_input_file: + ++n_infiles; + continue; + + 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 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 OPT_o: + ++n_outfiles; + break; + + case OPT_v: + verbose = 1; + break; + + case OPT__version: + printf ("GNU Fortran %s%s\n", pkgversion_string, version_string); + printf ("Copyright %s 2011 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\n")); + exit (0); + break; + + case OPT__help: + /* Let gcc.c handle this, as it has a really + cool facility for handling --help and --verbose --help. */ + return; + + case OPT_L: + if (!spec_file) + spec_file = find_spec_file (decoded_options[i].arg); + break; + + + default: + break; + } + } + + if ((n_outfiles != 0) && (n_infiles == 0)) + 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) + library = 0; + + /* Second pass through arglist, transforming arguments as appropriate. */ + + append_arg (&decoded_options[0]); /* Start with command name, of course. */ + + for (i = 1; i < argc; ++i) + { + if (decoded_options[i].errors & CL_ERR_MISSING_ARG) + { + append_arg (&decoded_options[i]); + continue; + } + + if (decoded_options[i].opt_index == OPT_SPECIAL_input_file + && decoded_options[i].arg[0] == '\0') + { + /* Interesting. Just append as is. */ + append_arg (&decoded_options[i]); + continue; + } + + 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. */ + + if (saw_library == 1 && need_math) /* -l. */ + append_option (OPT_l, MATH_LIBRARY, 1); + + saw_library = 0; + + if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) + { + append_arg (&decoded_options[i]); /* "-" == Standard input. */ + continue; + } + + if (decoded_options[i].opt_index == OPT_x) + { + /* Track input language. */ + const char *lang = decoded_options[i].arg; + + saw_speclang = (strcmp (lang, "none") != 0); + } + + append_arg (&decoded_options[i]); + + continue; + } + + /* A filename/library, not an option. */ + + if (saw_speclang) + saw_library = 0; /* -xfoo currently active. */ + else + { /* -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 -lm. */ + else + 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. */ + add_arg_libgfortran (static_lib && !static_linking); + continue; + } + else + { /* Other library, or filename. */ + if (saw_library == 1 && need_math) + append_option (OPT_l, MATH_LIBRARY, 1); + saw_library = 0; + } + } + append_arg (&decoded_options[i]); + } + + /* Append `-lgfortran -lm' as necessary. */ + + if (library) + { /* Doing a link and no -nostdlib. */ + if (saw_speclang) + append_option (OPT_x, "none", 1); + + switch (saw_library) + { + case 0: + add_arg_libgfortran (static_lib && !static_linking); + /* Fall through. */ + + case 1: + if (need_math) + append_option (OPT_l, MATH_LIBRARY, 1); + default: + break; + } + } + +#ifdef ENABLE_SHARED_LIBGCC + if (library) + { + unsigned int i; + + for (i = 1; i < g77_newargc; i++) + 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_option (OPT_shared_libgcc, NULL, 1); + } + +#endif + + /* 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:")); + for (i = 0; i < g77_newargc; i++) + fprintf (stderr, " %s", + g77_new_decoded_options[i].orig_option_with_args_text); + fprintf (stderr, "\n"); + } + + *in_decoded_options_count = g77_newargc; + *in_decoded_options = g77_new_decoded_options; +} + + +/* Called before linking. Returns 0 on success and -1 on failure. */ +int +lang_specific_pre_link (void) +{ + if (spec_file) + free (spec_file); + else if (library) + 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. */ -- cgit v1.2.3