/* 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 . */ #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 PYTHON_LIBRARY #define PYTHON_LIBRARY "gpython" #endif /* The original argument list and related info is copied here. */ static unsigned int gpy_xargc; static const struct cl_decoded_option *gpy_x_decoded_options; static void append_arg (const struct cl_decoded_option *); /* The new argument list will be built here. */ static unsigned int gpy_newargc; static struct cl_decoded_option *gpy_new_decoded_options; /* 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 0 fprintf (stderr, "`%s'\n", arg); #endif if (gpy_new_decoded_options == gpy_x_decoded_options && gpy_newargc < gpy_xargc && options_same (arg, &gpy_x_decoded_options[gpy_newargc])) { ++gpy_newargc; return; /* Nothing new here. */ } if (gpy_new_decoded_options == gpy_x_decoded_options) { /* Make new arglist. */ unsigned int i; newargsize = (gpy_xargc << 2) + 20; /* This should handle all. */ gpy_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize); /* Copy what has been done so far. */ for (i = 0; i < gpy_newargc; ++i) gpy_new_decoded_options[i] = gpy_x_decoded_options[i]; } if (gpy_newargc == newargsize) fatal_error ("overflowed output arg list for %qs", arg->orig_option_with_args_text); gpy_new_decoded_options[gpy_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 libgpython argument to the list being built. If FORCE_STATIC, ensure the library is linked statically. */ static void add_arg_libgpython (bool force_static ATTRIBUTE_UNUSED) { #ifdef HAVE_LD_STATIC_DYNAMIC if (force_static) append_option (OPT_Wl_, "-Bstatic", 1); #endif append_option (OPT_l, PYTHON_LIBRARY, 1); #ifdef HAVE_LD_STATIC_DYNAMIC if (force_static) append_option (OPT_Wl_, "-Bdynamic", 1); #endif } /* Modeled closely of gcc/fortran/gfortranspec.c */ 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 i = 0; unsigned int argc = *in_decoded_options_count; struct cl_decoded_option *decoded_options = *in_decoded_options; int verbose = 0; /* This will be NULL if we encounter a situation where we should not link in libf2c. */ const char *library = PYTHON_LIBRARY; /* 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 libgpython. */ 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. */ 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_libgpython (static_lib && !static_linking); } else if (decoded_options[i].opt_index == OPT_l && strcmp (decoded_options[i].arg, PYTHON_LIBRARY) == 0) { saw_library = 1; /* -l. */ add_arg_libgpython (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 `-lgpython -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_libgpython (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 < gpy_newargc; i++) if (gpy_new_decoded_options[i].opt_index == OPT_static_libgcc || gpy_new_decoded_options[i].opt_index == OPT_static) break; if (i == gpy_newargc) append_option (OPT_shared_libgcc, NULL, 1); } #endif if (verbose && gpy_new_decoded_options != gpy_x_decoded_options) { fprintf (stderr, _("Driving:")); for (i = 0; i < gpy_newargc; i++) fprintf (stderr, " %s", gpy_new_decoded_options[i].orig_option_with_args_text); fprintf (stderr, "\n"); } *in_decoded_options_count = gpy_newargc; *in_decoded_options = gpy_new_decoded_options; } /* Called before linking. Returns 0 on success and -1 on failure. */ int lang_specific_pre_link( void ) { return 0; } /* Number of extra output files that lang_specific_pre_link may generate. */ int lang_specific_extra_outfiles = 0;