diff gcc/fortran/gfortranspec.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/fortran/gfortranspec.c	Fri Oct 27 22:46:09 2017 +0900
@@ -0,0 +1,448 @@
+/* Specific flags and argument handling of the Fortran front-end.
+   Copyright (C) 1997-2017 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
+<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
+   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;
+
+/* This will be NULL if we encounter a situation where we should not
+   link in the fortran libraries.  */
+static const char *library = 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 (input_location, "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<library>
+     2 => last two args were -l<library> -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 2017 Free Software Foundation, Inc.\n",
+		  _("(C)"));
+	  fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
+		stdout);
+	  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;
+
+	default:
+	  break;
+	}
+    }
+
+  if ((n_outfiles != 0) && (n_infiles == 0))
+    fatal_error (input_location,
+		 "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<library>.  */
+	    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<library> -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<library>.  */
+	      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
+
+  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 (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.  */