1 /* Specific flags and argument handling of the Fortran front-end.
2    Copyright (C) 1997-2021 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10 
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 /* This file is copied more or less verbatim from g77.  */
21 /* This file contains a filter for the main `gcc' driver, which is
22    replicated for the `gfortran' driver by adding this filter.  The purpose
23    of this filter is to be basically identical to gcc (in that
24    it faithfully passes all of the original arguments to gcc) but,
25    unless explicitly overridden by the user in certain ways, ensure
26    that the needs of the language supported by this wrapper are met.
27 
28    For GNU Fortran 95(gfortran), we do the following to the argument list
29    before passing it to `gcc':
30 
31    1.  Make sure `-lgfortran -lm' is at the end of the list.
32 
33    2.  Make sure each time `-lgfortran' or `-lm' is seen, it forms
34        part of the series `-lgfortran -lm'.
35 
36    #1 and #2 are not done if `-nostdlib' or any option that disables
37    the linking phase is present, or if `-xfoo' is in effect.  Note that
38    a lack of source files or -l options disables linking.
39 
40    This program was originally made out of gcc/cp/g++spec.c, but the
41    way it builds the new argument list was rewritten so it is much
42    easier to maintain, improve the way it decides to add or not add
43    extra arguments, etc.  And several improvements were made in the
44    handling of arguments, primarily to make it more consistent with
45    `gcc' itself.  */
46 
47 #include "config.h"
48 #include "system.h"
49 #include "coretypes.h"
50 #include "opt-suggestions.h"
51 #include "gcc.h"
52 #include "opts.h"
53 
54 #include "tm.h"
55 #include "intl.h"
56 
57 #ifndef MATH_LIBRARY
58 #define MATH_LIBRARY "m"
59 #endif
60 
61 #ifndef FORTRAN_LIBRARY
62 #define FORTRAN_LIBRARY "gfortran"
63 #endif
64 
65 /* Name of the spec file.  */
66 #define SPEC_FILE "libgfortran.spec"
67 
68 /* The original argument list and related info is copied here.  */
69 static unsigned int g77_xargc;
70 static const struct cl_decoded_option *g77_x_decoded_options;
71 static void append_arg (const struct cl_decoded_option *);
72 
73 /* The new argument list will be built here.  */
74 static unsigned int g77_newargc;
75 static struct cl_decoded_option *g77_new_decoded_options;
76 
77 /* This will be NULL if we encounter a situation where we should not
78    link in the fortran libraries.  */
79 static const char *library = NULL;
80 
81 
82 /* Return whether strings S1 and S2 are both NULL or both the same
83    string.  */
84 
85 static bool
strings_same(const char * s1,const char * s2)86 strings_same (const char *s1, const char *s2)
87 {
88   return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0);
89 }
90 
91 /* Return whether decoded option structures OPT1 and OPT2 are the
92    same.  */
93 
94 static bool
options_same(const struct cl_decoded_option * opt1,const struct cl_decoded_option * opt2)95 options_same (const struct cl_decoded_option *opt1,
96 	      const struct cl_decoded_option *opt2)
97 {
98   return (opt1->opt_index == opt2->opt_index
99 	  && strings_same (opt1->arg, opt2->arg)
100 	  && strings_same (opt1->orig_option_with_args_text,
101 			   opt2->orig_option_with_args_text)
102 	  && strings_same (opt1->canonical_option[0],
103 			   opt2->canonical_option[0])
104 	  && strings_same (opt1->canonical_option[1],
105 			   opt2->canonical_option[1])
106 	  && strings_same (opt1->canonical_option[2],
107 			   opt2->canonical_option[2])
108 	  && strings_same (opt1->canonical_option[3],
109 			   opt2->canonical_option[3])
110 	  && (opt1->canonical_option_num_elements
111 	      == opt2->canonical_option_num_elements)
112 	  && opt1->value == opt2->value
113 	  && opt1->errors == opt2->errors);
114 }
115 
116 /* Append another argument to the list being built.  As long as it is
117    identical to the corresponding arg in the original list, just increment
118    the new arg count.  Otherwise allocate a new list, etc.  */
119 
120 static void
append_arg(const struct cl_decoded_option * arg)121 append_arg (const struct cl_decoded_option *arg)
122 {
123   static unsigned int newargsize;
124 
125   if (g77_new_decoded_options == g77_x_decoded_options
126       && g77_newargc < g77_xargc
127       && options_same (arg, &g77_x_decoded_options[g77_newargc]))
128     {
129       ++g77_newargc;
130       return;			/* Nothing new here.  */
131     }
132 
133   if (g77_new_decoded_options == g77_x_decoded_options)
134     {				/* Make new arglist.  */
135       unsigned int i;
136 
137       newargsize = (g77_xargc << 2) + 20;	/* This should handle all.  */
138       g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
139 
140       /* Copy what has been done so far.  */
141       for (i = 0; i < g77_newargc; ++i)
142 	g77_new_decoded_options[i] = g77_x_decoded_options[i];
143     }
144 
145   if (g77_newargc == newargsize)
146     fatal_error (input_location, "overflowed output argument list for %qs",
147 		 arg->orig_option_with_args_text);
148 
149   g77_new_decoded_options[g77_newargc++] = *arg;
150 }
151 
152 /* Append an option described by OPT_INDEX, ARG and VALUE to the list
153    being built.  */
154 static void
append_option(size_t opt_index,const char * arg,int value)155 append_option (size_t opt_index, const char *arg, int value)
156 {
157   struct cl_decoded_option decoded;
158 
159   generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
160   append_arg (&decoded);
161 }
162 
163 /* Append a libgfortran argument to the list being built.  If
164    FORCE_STATIC, ensure the library is linked statically.  */
165 
166 static void
add_arg_libgfortran(bool force_static ATTRIBUTE_UNUSED)167 add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED)
168 {
169 #ifdef HAVE_LD_STATIC_DYNAMIC
170   if (force_static)
171     append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
172 #endif
173   append_option (OPT_l, FORTRAN_LIBRARY, 1);
174 #ifdef HAVE_LD_STATIC_DYNAMIC
175   if (force_static)
176     append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
177 #endif
178 }
179 
180 void
lang_specific_driver(struct cl_decoded_option ** in_decoded_options,unsigned int * in_decoded_options_count,int * in_added_libraries ATTRIBUTE_UNUSED)181 lang_specific_driver (struct cl_decoded_option **in_decoded_options,
182 		      unsigned int *in_decoded_options_count,
183 		      int *in_added_libraries ATTRIBUTE_UNUSED)
184 {
185   unsigned int argc = *in_decoded_options_count;
186   struct cl_decoded_option *decoded_options = *in_decoded_options;
187   unsigned int i;
188   int verbose = 0;
189 
190   /* 0 => -xnone in effect.
191      1 => -xfoo in effect.  */
192   int saw_speclang = 0;
193 
194   /* 0 => initial/reset state
195      1 => last arg was -l<library>
196      2 => last two args were -l<library> -lm.  */
197   int saw_library = 0;
198 
199   /* By default, we throw on the math library if we have one.  */
200   int need_math = (MATH_LIBRARY[0] != '\0');
201 
202   /* Whether we should link a static libgfortran.  */
203   int static_lib = 0;
204 
205   /* Whether we need to link statically.  */
206   int static_linking = 0;
207 
208   /* The number of input and output files in the incoming arg list.  */
209   int n_infiles = 0;
210   int n_outfiles = 0;
211 
212   library = FORTRAN_LIBRARY;
213 
214 #if 0
215   fprintf (stderr, "Incoming:");
216   for (i = 0; i < argc; i++)
217     fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text);
218   fprintf (stderr, "\n");
219 #endif
220 
221   g77_xargc = argc;
222   g77_x_decoded_options = decoded_options;
223   g77_newargc = 0;
224   g77_new_decoded_options = decoded_options;
225 
226   /* First pass through arglist.
227 
228      If -nostdlib or a "turn-off-linking" option is anywhere in the
229      command line, don't do any library-option processing (except
230      relating to -x).  */
231 
232   for (i = 1; i < argc; ++i)
233     {
234       if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
235 	continue;
236 
237       switch (decoded_options[i].opt_index)
238 	{
239 	case OPT_SPECIAL_input_file:
240 	  ++n_infiles;
241 	  continue;
242 
243 	case OPT_nostdlib:
244 	case OPT_nodefaultlibs:
245 	case OPT_c:
246 	case OPT_r:
247 	case OPT_S:
248 	case OPT_fsyntax_only:
249 	case OPT_E:
250 	  /* These options disable linking entirely or linking of the
251 	     standard libraries.  */
252 	  library = 0;
253 	  break;
254 
255 	case OPT_static_libgfortran:
256 #ifdef HAVE_LD_STATIC_DYNAMIC
257 	  static_lib = 1;
258 #endif
259 	  break;
260 
261 	case OPT_static:
262 #ifdef HAVE_LD_STATIC_DYNAMIC
263 	  static_linking = 1;
264 #endif
265 	  break;
266 
267 	case OPT_l:
268 	  ++n_infiles;
269 	  break;
270 
271 	case OPT_o:
272 	  ++n_outfiles;
273 	  break;
274 
275 	case OPT_v:
276 	  verbose = 1;
277 	  break;
278 
279 	case OPT__version:
280 	  printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
281 	  printf ("Copyright %s 2021 Free Software Foundation, Inc.\n",
282 		  _("(C)"));
283 	  fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
284 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
285 		stdout);
286 	  exit (0);
287 	  break;
288 
289 	case OPT__help:
290 	  /* Let gcc.c handle this, as it has a really
291 	     cool facility for handling --help and --verbose --help.  */
292 	  return;
293 
294 	default:
295 	  break;
296 	}
297     }
298 
299   if ((n_outfiles != 0) && (n_infiles == 0))
300     fatal_error (input_location,
301 		 "no input files; unwilling to write output files");
302 
303   /* If there are no input files, no need for the library.  */
304   if (n_infiles == 0)
305     library = 0;
306 
307   /* Second pass through arglist, transforming arguments as appropriate.  */
308 
309   append_arg (&decoded_options[0]); /* Start with command name, of course.  */
310 
311   for (i = 1; i < argc; ++i)
312     {
313       if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
314 	{
315 	  append_arg (&decoded_options[i]);
316 	  continue;
317 	}
318 
319       if (decoded_options[i].opt_index == OPT_SPECIAL_input_file
320 	  && decoded_options[i].arg[0] == '\0')
321 	{
322 	  /* Interesting.  Just append as is.  */
323 	  append_arg (&decoded_options[i]);
324 	  continue;
325 	}
326 
327       if (decoded_options[i].opt_index != OPT_l
328 	  && (decoded_options[i].opt_index != OPT_SPECIAL_input_file
329 	      || strcmp (decoded_options[i].arg, "-") == 0))
330 	{
331 	  /* Not a filename or library.  */
332 
333 	  if (saw_library == 1 && need_math)	/* -l<library>.  */
334 	    append_option (OPT_l, MATH_LIBRARY, 1);
335 
336 	  saw_library = 0;
337 
338 	  if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
339 	    {
340 	      append_arg (&decoded_options[i]);	/* "-" == Standard input.  */
341 	      continue;
342 	    }
343 
344 	  if (decoded_options[i].opt_index == OPT_x)
345 	    {
346 	      /* Track input language.  */
347 	      const char *lang = decoded_options[i].arg;
348 
349 	      saw_speclang = (strcmp (lang, "none") != 0);
350 	    }
351 
352 	  append_arg (&decoded_options[i]);
353 
354 	  continue;
355 	}
356 
357       /* A filename/library, not an option.  */
358 
359       if (saw_speclang)
360 	saw_library = 0;	/* -xfoo currently active.  */
361       else
362 	{			/* -lfoo or filename.  */
363 	  if (decoded_options[i].opt_index == OPT_l
364 	      && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
365 	    {
366 	      if (saw_library == 1)
367 		saw_library = 2;	/* -l<library> -lm.  */
368 	      else
369 		add_arg_libgfortran (static_lib && !static_linking);
370 	    }
371 	  else if (decoded_options[i].opt_index == OPT_l
372 	      && strcmp (decoded_options[i].arg, FORTRAN_LIBRARY) == 0)
373 	    {
374 	      saw_library = 1;	/* -l<library>.  */
375 	      add_arg_libgfortran (static_lib && !static_linking);
376 	      continue;
377 	    }
378 	  else
379 	    {			/* Other library, or filename.  */
380 	      if (saw_library == 1 && need_math)
381 		append_option (OPT_l, MATH_LIBRARY, 1);
382 	      saw_library = 0;
383 	    }
384 	}
385       append_arg (&decoded_options[i]);
386     }
387 
388   /* Append `-lgfortran -lm' as necessary.  */
389 
390   if (library)
391     {				/* Doing a link and no -nostdlib.  */
392       if (saw_speclang)
393 	append_option (OPT_x, "none", 1);
394 
395       switch (saw_library)
396 	{
397 	case 0:
398 	  add_arg_libgfortran (static_lib && !static_linking);
399 	  /* Fall through.  */
400 
401 	case 1:
402 	  if (need_math)
403 	    append_option (OPT_l, MATH_LIBRARY, 1);
404 	default:
405 	  break;
406 	}
407     }
408 
409 #ifdef ENABLE_SHARED_LIBGCC
410   if (library)
411     {
412       unsigned int i;
413 
414       for (i = 1; i < g77_newargc; i++)
415 	if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
416 	    || g77_new_decoded_options[i].opt_index == OPT_static)
417 	  break;
418 
419       if (i == g77_newargc)
420 	append_option (OPT_shared_libgcc, NULL, 1);
421     }
422 
423 #endif
424 
425   if (verbose && g77_new_decoded_options != g77_x_decoded_options)
426     {
427       fprintf (stderr, _("Driving:"));
428       for (i = 0; i < g77_newargc; i++)
429 	fprintf (stderr, " %s",
430 		 g77_new_decoded_options[i].orig_option_with_args_text);
431       fprintf (stderr, "\n");
432     }
433 
434   *in_decoded_options_count = g77_newargc;
435   *in_decoded_options = g77_new_decoded_options;
436 }
437 
438 
439 /* Called before linking.  Returns 0 on success and -1 on failure.  */
440 int
lang_specific_pre_link(void)441 lang_specific_pre_link (void)
442 {
443   if (library)
444     do_spec ("%:include(libgfortran.spec)");
445 
446   return 0;
447 }
448 
449 /* Number of extra output files that lang_specific_pre_link may generate.  */
450 int lang_specific_extra_outfiles = 0;	/* Not used for F77.  */
451