]>
Commit | Line | Data |
---|---|---|
1eee94d3 GM |
1 | /* gm2spec.cc specific flags and argument handling within GNU Modula-2. |
2 | ||
83ffe9cd | 3 | Copyright (C) 2007-2023 Free Software Foundation, Inc. |
1eee94d3 GM |
4 | Contributed by Gaius Mulley <gaius@glam.ac.uk>. |
5 | ||
6 | This file is part of GNU Modula-2. | |
7 | ||
8 | GNU Modula-2 is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU Modula-2 is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU Modula-2; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
26 | #include "xregex.h" | |
27 | #include "obstack.h" | |
28 | #include "intl.h" | |
29 | #include "prefix.h" | |
30 | #include "opt-suggestions.h" | |
31 | #include "gcc.h" | |
32 | #include "opts.h" | |
33 | #include "vec.h" | |
34 | ||
35 | #include "m2/gm2config.h" | |
36 | ||
37 | #ifdef HAVE_DIRENT_H | |
38 | #include <dirent.h> | |
39 | #else | |
40 | #ifdef HAVE_SYS_NDIR_H | |
41 | #include <sys/ndir.h> | |
42 | #endif | |
43 | #ifdef HAVE_SYS_DIR_H | |
44 | #include <sys/dir.h> | |
45 | #endif | |
46 | #ifdef HAVE_NDIR_H | |
47 | #include <ndir.h> | |
48 | #endif | |
49 | #endif | |
50 | ||
51 | /* This bit is set if we saw a `-xfoo' language specification. */ | |
52 | #define LANGSPEC (1<<1) | |
53 | /* This bit is set if they did `-lm' or `-lmath'. */ | |
54 | #define MATHLIB (1<<2) | |
55 | /* This bit is set if they did `-lc'. */ | |
56 | #define WITHLIBC (1<<3) | |
57 | /* Skip this option. */ | |
58 | #define SKIPOPT (1<<4) | |
59 | ||
60 | #ifndef MATH_LIBRARY | |
61 | #define MATH_LIBRARY "m" | |
62 | #endif | |
63 | #ifndef MATH_LIBRARY_PROFILE | |
64 | #define MATH_LIBRARY_PROFILE MATH_LIBRARY | |
65 | #endif | |
66 | ||
67 | #ifndef LIBSTDCXX | |
68 | #define LIBSTDCXX "stdc++" | |
69 | #endif | |
70 | #ifndef LIBSTDCXX_PROFILE | |
71 | #define LIBSTDCXX_PROFILE LIBSTDCXX | |
72 | #endif | |
73 | #ifndef LIBSTDCXX_STATIC | |
74 | #define LIBSTDCXX_STATIC NULL | |
75 | #endif | |
76 | ||
77 | #ifndef LIBCXX | |
78 | #define LIBCXX "c++" | |
79 | #endif | |
80 | #ifndef LIBCXX_PROFILE | |
81 | #define LIBCXX_PROFILE LIBCXX | |
82 | #endif | |
83 | #ifndef LIBCXX_STATIC | |
84 | #define LIBCXX_STATIC NULL | |
85 | #endif | |
86 | ||
87 | #ifndef LIBCXXABI | |
88 | #define LIBCXXABI "c++abi" | |
89 | #endif | |
90 | #ifndef LIBCXXABI_PROFILE | |
91 | #define LIBCXXABI_PROFILE LIBCXXABI | |
92 | #endif | |
93 | #ifndef LIBCXXABI_STATIC | |
94 | #define LIBCXXABI_STATIC NULL | |
95 | #endif | |
96 | ||
97 | /* The values used here must match those of the stdlib_kind enumeration | |
98 | in c.opt. */ | |
99 | enum stdcxxlib_kind | |
100 | { | |
101 | USE_LIBSTDCXX = 1, | |
102 | USE_LIBCXX = 2 | |
103 | }; | |
104 | ||
105 | #define DEFAULT_DIALECT "pim" | |
106 | #undef DEBUG_ARG | |
107 | ||
108 | typedef enum { iso, pim, min, logitech, pimcoroutine, maxlib } libs; | |
109 | ||
110 | /* These are the library names which are installed as part of gm2 and reflect | |
111 | -flibs=name. The -flibs= option provides the user with a short cut to add | |
112 | libraries without having to know the include and link path. */ | |
113 | ||
114 | static const char *library_name[maxlib] | |
115 | = { "m2iso", "m2pim", "m2min", "m2log", "m2cor" }; | |
116 | ||
117 | /* They match the installed archive name for example libm2iso.a, | |
118 | libm2pim.a, libm2min.a, libm2log.a and libm2cor.a. They also match a | |
119 | subdirectory name where the definition modules are kept. The driver | |
120 | checks the argument to -flibs= for an entry in library_name or | |
121 | alternatively the existance of the subdirectory (to allow for third | |
122 | party libraries to coexist). */ | |
123 | ||
124 | static const char *library_abbrev[maxlib] | |
125 | = { "iso", "pim", "min", "log", "cor" }; | |
126 | ||
127 | /* Users may specifiy -flibs=pim,iso etc which are mapped onto | |
128 | -flibs=m2pim,m2iso respectively. This provides a match between | |
129 | the dialect of Modula-2 and the library set. */ | |
130 | ||
131 | static const char *add_include (const char *libpath, const char *library); | |
132 | ||
133 | static bool seen_scaffold_static = false; | |
134 | static bool seen_scaffold_dynamic = false; | |
135 | static bool scaffold_static = false; | |
136 | static bool scaffold_dynamic = true; // Default uses -fscaffold-dynamic. | |
137 | static bool seen_gen_module_list = false; | |
138 | static bool seen_uselist = false; | |
139 | static bool uselist = false; | |
140 | static bool gen_module_list = true; // Default uses -fgen-module-list=-. | |
141 | static const char *gen_module_filename = "-"; | |
142 | static const char *multilib_dir = NULL; | |
143 | /* The original argument list and related info is copied here. */ | |
144 | static unsigned int gm2_xargc; | |
145 | static const struct cl_decoded_option *gm2_x_decoded_options; | |
146 | static void append_arg (const struct cl_decoded_option *); | |
147 | ||
148 | /* The new argument list will be built here. */ | |
149 | static unsigned int gm2_newargc; | |
150 | static struct cl_decoded_option *gm2_new_decoded_options; | |
151 | ||
152 | ||
153 | /* Return whether strings S1 and S2 are both NULL or both the same | |
154 | string. */ | |
155 | ||
156 | static bool | |
157 | strings_same (const char *s1, const char *s2) | |
158 | { | |
159 | return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0); | |
160 | } | |
161 | ||
162 | bool | |
163 | options_same (const struct cl_decoded_option *opt1, | |
164 | const struct cl_decoded_option *opt2) | |
165 | { | |
166 | return (opt1->opt_index == opt2->opt_index | |
167 | && strings_same (opt1->arg, opt2->arg) | |
168 | && strings_same (opt1->orig_option_with_args_text, | |
169 | opt2->orig_option_with_args_text) | |
170 | && strings_same (opt1->canonical_option[0], | |
171 | opt2->canonical_option[0]) | |
172 | && strings_same (opt1->canonical_option[1], | |
173 | opt2->canonical_option[1]) | |
174 | && strings_same (opt1->canonical_option[2], | |
175 | opt2->canonical_option[2]) | |
176 | && strings_same (opt1->canonical_option[3], | |
177 | opt2->canonical_option[3]) | |
178 | && (opt1->canonical_option_num_elements | |
179 | == opt2->canonical_option_num_elements) | |
180 | && opt1->value == opt2->value | |
181 | && opt1->errors == opt2->errors); | |
182 | } | |
183 | ||
184 | /* Append another argument to the list being built. */ | |
185 | ||
186 | static void | |
187 | append_arg (const struct cl_decoded_option *arg) | |
188 | { | |
189 | static unsigned int newargsize; | |
190 | ||
191 | if (gm2_new_decoded_options == gm2_x_decoded_options | |
192 | && gm2_newargc < gm2_xargc | |
193 | && options_same (arg, &gm2_x_decoded_options[gm2_newargc])) | |
194 | { | |
195 | ++gm2_newargc; | |
196 | return; /* Nothing new here. */ | |
197 | } | |
198 | ||
199 | if (gm2_new_decoded_options == gm2_x_decoded_options) | |
200 | { /* Make new arglist. */ | |
201 | unsigned int i; | |
202 | ||
203 | newargsize = (gm2_xargc << 2) + 20; /* This should handle all. */ | |
204 | gm2_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize); | |
205 | ||
206 | /* Copy what has been done so far. */ | |
207 | for (i = 0; i < gm2_newargc; ++i) | |
208 | gm2_new_decoded_options[i] = gm2_x_decoded_options[i]; | |
209 | } | |
210 | ||
211 | if (gm2_newargc == newargsize) | |
212 | fatal_error (input_location, "overflowed output argument list for %qs", | |
213 | arg->orig_option_with_args_text); | |
214 | ||
215 | gm2_new_decoded_options[gm2_newargc++] = *arg; | |
216 | } | |
217 | ||
218 | /* Append an option described by OPT_INDEX, ARG and VALUE to the list | |
219 | being built. */ | |
220 | ||
221 | static void | |
222 | append_option (size_t opt_index, const char *arg, int value) | |
223 | { | |
224 | struct cl_decoded_option decoded; | |
225 | ||
226 | generate_option (opt_index, arg, value, CL_DRIVER, &decoded); | |
227 | append_arg (&decoded); | |
228 | } | |
229 | ||
230 | /* build_archive_path returns a string containing the path to the | |
231 | archive defined by libpath and dialectLib. */ | |
232 | ||
233 | static const char * | |
234 | build_archive_path (const char *libpath, const char *library) | |
235 | { | |
236 | if (library != NULL) | |
237 | { | |
238 | const char *libdir = (const char *)library; | |
239 | ||
240 | if (libdir != NULL) | |
241 | { | |
242 | int machine_length = 0; | |
243 | char dir_sep[2]; | |
244 | ||
245 | dir_sep[0] = DIR_SEPARATOR; | |
246 | dir_sep[1] = (char)0; | |
247 | ||
248 | if (multilib_dir != NULL) | |
249 | { | |
250 | machine_length = strlen (multilib_dir); | |
251 | machine_length += strlen (dir_sep); | |
252 | } | |
253 | ||
254 | int l = strlen (libpath) + 1 + strlen ("m2") + 1 | |
255 | + strlen (libdir) + 1 + machine_length + 1; | |
256 | char *s = (char *)xmalloc (l); | |
257 | ||
258 | strcpy (s, libpath); | |
259 | strcat (s, dir_sep); | |
260 | if (machine_length > 0) | |
261 | { | |
262 | strcat (s, multilib_dir); | |
263 | strcat (s, dir_sep); | |
264 | } | |
265 | strcat (s, "m2"); | |
266 | strcat (s, dir_sep); | |
267 | strcat (s, libdir); | |
268 | return s; | |
269 | } | |
270 | } | |
271 | return NULL; | |
272 | } | |
273 | ||
274 | /* safe_strdup safely duplicates a string. */ | |
275 | ||
276 | static char * | |
277 | safe_strdup (const char *s) | |
278 | { | |
279 | if (s != NULL) | |
280 | return xstrdup (s); | |
281 | return NULL; | |
282 | } | |
283 | ||
284 | /* add_default_combination adds the correct link path and then the | |
285 | library name. */ | |
286 | ||
287 | static bool | |
288 | add_default_combination (const char *libpath, const char *library) | |
289 | { | |
290 | if (library != NULL) | |
291 | { | |
292 | append_option (OPT_L, build_archive_path (libpath, library), 1); | |
293 | append_option (OPT_l, safe_strdup (library), 1); | |
294 | return true; | |
295 | } | |
296 | return false; | |
297 | } | |
298 | ||
299 | /* add_default_archives adds the default archives to the end of the | |
300 | current command line. */ | |
301 | ||
302 | static int | |
303 | add_default_archives (const char *libpath, const char *libraries) | |
304 | { | |
305 | const char *l = libraries; | |
306 | const char *e; | |
307 | char *libname; | |
308 | unsigned int libcount = 0; | |
309 | ||
310 | do | |
311 | { | |
312 | e = index (l, ','); | |
313 | if (e == NULL) | |
314 | { | |
315 | libname = xstrdup (l); | |
316 | l = NULL; | |
317 | if (add_default_combination (libpath, libname)) | |
318 | libcount++; | |
319 | free (libname); | |
320 | } | |
321 | else | |
322 | { | |
323 | libname = xstrndup (l, e - l); | |
324 | l = e + 1; | |
325 | if (add_default_combination (libpath, libname)) | |
326 | libcount++; | |
327 | free (libname); | |
328 | } | |
329 | } | |
330 | while ((l != NULL) && (l[0] != (char)0)); | |
331 | return libcount; | |
332 | } | |
333 | ||
334 | /* build_include_path builds the component of the include path | |
335 | referenced by the library. */ | |
336 | ||
337 | static const char * | |
338 | build_include_path (const char *libpath, const char *library) | |
339 | { | |
340 | char dir_sep[2]; | |
341 | char *gm2libs; | |
342 | unsigned int machine_length = 0; | |
343 | ||
344 | dir_sep[0] = DIR_SEPARATOR; | |
345 | dir_sep[1] = (char)0; | |
346 | ||
347 | if (multilib_dir != NULL) | |
348 | { | |
349 | machine_length = strlen (multilib_dir); | |
350 | machine_length += strlen (dir_sep); | |
351 | } | |
352 | ||
353 | gm2libs = (char *)alloca (strlen (libpath) + strlen (dir_sep) + strlen ("m2") | |
354 | + strlen (dir_sep) + strlen (library) + 1 | |
355 | + machine_length + 1); | |
356 | strcpy (gm2libs, libpath); | |
357 | strcat (gm2libs, dir_sep); | |
358 | if (machine_length > 0) | |
359 | { | |
360 | strcat (gm2libs, multilib_dir); | |
361 | strcat (gm2libs, dir_sep); | |
362 | } | |
363 | strcat (gm2libs, "m2"); | |
364 | strcat (gm2libs, dir_sep); | |
365 | strcat (gm2libs, library); | |
366 | ||
367 | return xstrdup (gm2libs); | |
368 | } | |
369 | ||
370 | /* add_include add the correct include path given the libpath and | |
371 | library. The new path is returned. */ | |
372 | ||
373 | static const char * | |
374 | add_include (const char *libpath, const char *library) | |
375 | { | |
376 | if (library == NULL) | |
377 | return NULL; | |
378 | else | |
379 | return build_include_path (libpath, library); | |
380 | } | |
381 | ||
382 | /* add_default_includes add the appropriate default include paths | |
383 | depending upon the style of libraries chosen. */ | |
384 | ||
385 | static void | |
386 | add_default_includes (const char *libpath, const char *libraries) | |
387 | { | |
388 | const char *l = libraries; | |
389 | const char *e; | |
390 | const char *c; | |
391 | const char *path; | |
392 | ||
393 | do | |
394 | { | |
395 | e = index (l, ','); | |
396 | if (e == NULL) | |
397 | { | |
398 | c = xstrdup (l); | |
399 | l = NULL; | |
400 | } | |
401 | else | |
402 | { | |
403 | c = xstrndup (l, e - l); | |
404 | l = e + 1; | |
405 | } | |
406 | path = add_include (libpath, c); | |
407 | append_option (OPT_I, path, 1); | |
408 | } | |
409 | while ((l != NULL) && (l[0] != (char)0)); | |
410 | } | |
411 | ||
412 | /* library_installed returns true if directory library is found under | |
413 | libpath. */ | |
414 | ||
415 | static bool | |
416 | library_installed (const char *libpath, const char *library) | |
417 | { | |
418 | #if defined(HAVE_OPENDIR) && defined(HAVE_DIRENT_H) | |
419 | const char *complete = build_archive_path (libpath, library); | |
420 | DIR *directory = opendir (complete); | |
421 | ||
422 | if (directory == NULL || (errno == ENOENT)) | |
423 | return false; | |
424 | /* Directory exists and therefore the library also exists. */ | |
425 | closedir (directory); | |
426 | return true; | |
427 | #else | |
428 | return false; | |
429 | #endif | |
430 | } | |
431 | ||
432 | /* check_valid check to see that the library is valid. | |
433 | It check the library against the default library set in gm2 and | |
434 | also against any additional libraries installed in the prefix tree. */ | |
435 | ||
436 | static bool | |
437 | check_valid_library (const char *libpath, const char *library) | |
438 | { | |
439 | /* Firstly check against the default libraries (which might not be | |
440 | installed yet). */ | |
441 | for (int i = 0; i < maxlib; i++) | |
442 | if (strcmp (library, library_name[i]) == 0) | |
443 | return true; | |
444 | /* Secondly check whether it is installed (a third party library). */ | |
445 | return library_installed (libpath, library); | |
446 | } | |
447 | ||
448 | /* check_valid_list check to see that the libraries specified are valid. | |
449 | It checks against the default library set in gm2 and also against | |
450 | any additional libraries installed in the libpath tree. */ | |
451 | ||
452 | static bool | |
453 | check_valid_list (const char *libpath, const char *libraries) | |
454 | { | |
455 | const char *start = libraries; | |
456 | const char *end; | |
457 | const char *copy; | |
458 | ||
459 | do | |
460 | { | |
461 | end = index (start, ','); | |
462 | if (end == NULL) | |
463 | { | |
464 | copy = xstrdup (start); | |
465 | start = NULL; | |
466 | } | |
467 | else | |
468 | { | |
469 | copy = xstrndup (start, end - start); | |
470 | start = end + 1; | |
471 | } | |
472 | if (! check_valid_library (libpath, copy)) | |
473 | { | |
474 | error ("library specified %sq is either not installed or does not exist", | |
475 | copy); | |
476 | return false; | |
477 | } | |
478 | } | |
479 | while ((start != NULL) && (start[0] != (char)0)); | |
480 | return true; | |
481 | } | |
482 | ||
483 | /* add_word returns a new string which has the contents of lib | |
484 | appended to list. If list is NULL then lib is duplicated and | |
485 | returned otherwise the list is appended by "," and the contents of | |
486 | lib. */ | |
487 | ||
488 | static const char * | |
489 | add_word (const char *list, const char *lib) | |
490 | { | |
491 | char *copy; | |
492 | if (list == NULL) | |
493 | return xstrdup (lib); | |
494 | copy = (char *) xmalloc (strlen (list) + strlen (lib) + 1 + 1); | |
495 | strcpy (copy, list); | |
496 | strcat (copy, ","); | |
497 | strcat (copy, lib); | |
498 | return copy; | |
499 | } | |
500 | ||
501 | /* convert_abbreviation checks abbreviation against known library | |
502 | abbreviations. If an abbreviation is found it converts the element | |
503 | to the full library name, otherwise the user supplied name is added | |
504 | to the full_libraries list. A new string is returned. */ | |
505 | ||
506 | static const char * | |
507 | convert_abbreviation (const char *full_libraries, const char *abbreviation) | |
508 | { | |
509 | for (int i = 0; i < maxlib; i++) | |
510 | if (strcmp (abbreviation, library_abbrev[i]) == 0) | |
511 | return add_word (full_libraries, library_name[i]); | |
512 | /* No abbreviation found therefore assume user specified full library name. */ | |
513 | return add_word (full_libraries, abbreviation); | |
514 | } | |
515 | ||
516 | /* convert_abbreviations checks each element in the library list to | |
517 | see if an a known library abbreviation was used. If found it | |
518 | converts the element to the full library name, otherwise the | |
519 | element is copied into the list. A new string is returned. */ | |
520 | ||
521 | static const char * | |
522 | convert_abbreviations (const char *libraries) | |
523 | { | |
524 | const char *start = libraries; | |
525 | const char *end; | |
526 | const char *full_libraries = NULL; | |
527 | ||
528 | do | |
529 | { | |
530 | end = index (start, ','); | |
531 | if (end == NULL) | |
532 | { | |
533 | full_libraries = convert_abbreviation (full_libraries, start); | |
534 | start = NULL; | |
535 | } | |
536 | else | |
537 | { | |
538 | full_libraries = convert_abbreviation (full_libraries, xstrndup (start, end - start)); | |
539 | start = end + 1; | |
540 | } | |
541 | } | |
542 | while ((start != NULL) && (start[0] != (char)0)); | |
543 | return full_libraries; | |
544 | } | |
545 | ||
546 | ||
547 | void | |
548 | lang_specific_driver (struct cl_decoded_option **in_decoded_options, | |
549 | unsigned int *in_decoded_options_count, | |
550 | int *in_added_libraries) | |
551 | { | |
552 | unsigned int argc = *in_decoded_options_count; | |
553 | struct cl_decoded_option *decoded_options = *in_decoded_options; | |
554 | unsigned int i; | |
555 | ||
556 | /* True if we saw a `-xfoo' language specification on the command | |
557 | line. This function will add a -xmodula-2 if the user has not | |
558 | already placed one onto the command line. */ | |
559 | bool seen_x_flag = false; | |
560 | const char *language = NULL; | |
561 | ||
562 | /* If nonzero, the user gave us the `-p' or `-pg' flag. */ | |
563 | int saw_profile_flag = 0; | |
564 | ||
565 | /* What action to take for the c++ runtime library: | |
566 | -1 means we should not link it in. | |
567 | 0 means we should link it if it is needed. | |
568 | 1 means it is needed and should be linked in. | |
569 | 2 means it is needed but should be linked statically. */ | |
570 | int library = 0; | |
571 | ||
572 | /* Which c++ runtime library to link. */ | |
573 | stdcxxlib_kind which_library = USE_LIBSTDCXX; | |
574 | ||
575 | const char *libraries = NULL; | |
576 | const char *dialect = DEFAULT_DIALECT; | |
577 | const char *libpath = LIBSUBDIR; | |
578 | ||
579 | /* An array used to flag each argument that needs a bit set for | |
580 | LANGSPEC, MATHLIB, or WITHLIBC. */ | |
581 | int *args; | |
582 | ||
583 | /* Have we seen -fmod=? */ | |
584 | bool seen_module_extension = false; | |
585 | ||
586 | /* Should the driver perform a link? */ | |
587 | bool linking = true; | |
588 | ||
dd77b049 IS |
589 | /* Should the driver link the shared gm2 libs? */ |
590 | bool shared_libgm2 = true; | |
591 | ||
1eee94d3 GM |
592 | /* "-lm" or "-lmath" if it appears on the command line. */ |
593 | const struct cl_decoded_option *saw_math = NULL; | |
594 | ||
595 | /* "-lc" if it appears on the command line. */ | |
596 | const struct cl_decoded_option *saw_libc = NULL; | |
597 | ||
598 | /* By default, we throw on the math library if we have one. */ | |
599 | int need_math = (MATH_LIBRARY[0] != '\0'); | |
600 | ||
dd77b049 IS |
601 | /* 1 if we should add -lpthread to the command-line. |
602 | FIXME: the default should be a configuration choice. */ | |
1eee94d3 GM |
603 | int need_pthread = 1; |
604 | ||
605 | /* True if we saw -static. */ | |
606 | int static_link = 0; | |
607 | ||
608 | /* True if we should add -shared-libgcc to the command-line. */ | |
609 | int shared_libgcc = 1; | |
610 | ||
611 | /* Have we seen the -v flag? */ | |
612 | bool verbose = false; | |
613 | ||
614 | /* The number of libraries added in. */ | |
615 | int added_libraries; | |
616 | ||
617 | #ifdef ENABLE_PLUGIN | |
618 | /* True if we should add -fplugin=m2rte to the command-line. */ | |
619 | bool need_plugin = true; | |
620 | #else | |
621 | bool need_plugin = false; | |
622 | #endif | |
623 | ||
624 | /* True if we should set up include paths and library paths. */ | |
625 | bool allow_libraries = true; | |
626 | ||
627 | #if defined(DEBUG_ARG) | |
628 | printf ("argc = %d\n", argc); | |
629 | fprintf (stderr, "Incoming:"); | |
630 | for (i = 0; i < argc; i++) | |
631 | fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text); | |
632 | fprintf (stderr, "\n"); | |
633 | #endif | |
634 | ||
635 | gm2_xargc = argc; | |
636 | gm2_x_decoded_options = decoded_options; | |
637 | gm2_newargc = 0; | |
638 | gm2_new_decoded_options = decoded_options; | |
639 | added_libraries = *in_added_libraries; | |
640 | args = XCNEWVEC (int, argc); | |
641 | ||
642 | /* First pass through arglist. | |
643 | ||
644 | If -nostdlib or a "turn-off-linking" option is anywhere in the | |
645 | command line, don't do any library-option processing (except | |
646 | relating to -x). */ | |
647 | ||
648 | for (i = 1; i < argc; i++) | |
649 | { | |
650 | const char *arg = decoded_options[i].arg; | |
651 | args[i] = 0; | |
652 | #if defined(DEBUG_ARG) | |
653 | printf ("1st pass: %s\n", | |
654 | decoded_options[i].orig_option_with_args_text); | |
655 | #endif | |
656 | switch (decoded_options[i].opt_index) | |
657 | { | |
658 | case OPT_fiso: | |
659 | dialect = "iso"; | |
660 | break; | |
661 | case OPT_fpim2: | |
662 | dialect = "pim2"; | |
663 | break; | |
664 | case OPT_fpim3: | |
665 | dialect = "pim3"; | |
666 | break; | |
667 | case OPT_fpim4: | |
668 | dialect = "pim4"; | |
669 | break; | |
670 | case OPT_fpim: | |
671 | dialect = "pim"; | |
672 | break; | |
673 | case OPT_flibs_: | |
674 | libraries = xstrdup (arg); | |
675 | allow_libraries = decoded_options[i].value; | |
676 | break; | |
677 | case OPT_fmod_: | |
678 | seen_module_extension = true; | |
679 | break; | |
680 | case OPT_fpthread: | |
681 | need_pthread = decoded_options[i].value; | |
682 | break; | |
683 | case OPT_fm2_plugin: | |
684 | need_plugin = decoded_options[i].value; | |
685 | #ifndef ENABLE_PLUGIN | |
686 | if (need_plugin) | |
687 | error ("plugin support is disabled; configure with " | |
688 | "%<--enable-plugin%>"); | |
689 | #endif | |
690 | break; | |
691 | case OPT_fscaffold_dynamic: | |
692 | seen_scaffold_dynamic = true; | |
693 | scaffold_dynamic = decoded_options[i].value; | |
694 | break; | |
695 | case OPT_fscaffold_static: | |
696 | seen_scaffold_static = true; | |
697 | scaffold_static = decoded_options[i].value; | |
698 | break; | |
699 | case OPT_fgen_module_list_: | |
700 | seen_gen_module_list = true; | |
701 | gen_module_list = decoded_options[i].value; | |
702 | if (gen_module_list) | |
703 | gen_module_filename = decoded_options[i].arg; | |
704 | break; | |
705 | case OPT_fuse_list_: | |
706 | seen_uselist = true; | |
707 | uselist = decoded_options[i].value; | |
708 | break; | |
709 | ||
710 | case OPT_nostdlib: | |
711 | case OPT_nostdlib__: | |
712 | case OPT_nodefaultlibs: | |
713 | library = -1; | |
714 | break; | |
715 | ||
716 | case OPT_l: | |
717 | if (strcmp (arg, MATH_LIBRARY) == 0) | |
718 | { | |
719 | args[i] |= MATHLIB; | |
720 | need_math = 0; | |
721 | } | |
722 | else if (strcmp (arg, "c") == 0) | |
723 | args[i] |= WITHLIBC; | |
724 | else | |
725 | /* Unrecognized libraries (e.g. -lfoo) may require libstdc++. */ | |
726 | library = (library == 0) ? 1 : library; | |
727 | break; | |
728 | ||
729 | case OPT_pg: | |
730 | case OPT_p: | |
731 | saw_profile_flag++; | |
732 | break; | |
733 | ||
734 | case OPT_x: | |
735 | seen_x_flag = true; | |
736 | language = arg; | |
737 | break; | |
738 | ||
739 | case OPT_v: | |
740 | verbose = true; | |
741 | break; | |
742 | ||
743 | case OPT_Xlinker: | |
744 | case OPT_Wl_: | |
745 | /* Arguments that go directly to the linker might be .o files, | |
746 | or something, and so might cause libstdc++ to be needed. */ | |
747 | if (library == 0) | |
748 | library = 1; | |
749 | break; | |
750 | ||
751 | case OPT_c: | |
752 | case OPT_r: | |
753 | case OPT_S: | |
754 | case OPT_E: | |
755 | case OPT_M: | |
756 | case OPT_MM: | |
757 | case OPT_fsyntax_only: | |
758 | /* Don't specify libraries if we won't link, since that would | |
759 | cause a warning. */ | |
760 | linking = false; | |
761 | library = -1; | |
762 | break; | |
763 | ||
764 | case OPT_static: | |
765 | static_link = 1; | |
766 | break; | |
767 | ||
768 | case OPT_static_libgcc: | |
769 | shared_libgcc = 0; | |
770 | break; | |
771 | ||
772 | case OPT_static_libstdc__: | |
773 | library = library >= 0 ? 2 : library; | |
24214708 IS |
774 | #ifdef HAVE_LD_STATIC_DYNAMIC |
775 | /* Remove -static-libstdc++ from the command only if target supports | |
776 | LD_STATIC_DYNAMIC. When not supported, it is left in so that a | |
777 | back-end target can use outfile substitution. */ | |
1eee94d3 | 778 | args[i] |= SKIPOPT; |
24214708 | 779 | #endif |
1eee94d3 GM |
780 | break; |
781 | ||
dd77b049 IS |
782 | case OPT_static_libgm2: |
783 | shared_libgm2 = false; | |
784 | #ifdef HAVE_LD_STATIC_DYNAMIC | |
785 | /* Remove -static-libgm2 from the command only if target supports | |
786 | LD_STATIC_DYNAMIC. When not supported, it is left in so that a | |
787 | back-end target can use outfile substitution. */ | |
788 | args[i] |= SKIPOPT; | |
789 | #endif | |
790 | break; | |
791 | ||
1eee94d3 GM |
792 | case OPT_stdlib_: |
793 | which_library = (stdcxxlib_kind) decoded_options[i].value; | |
794 | break; | |
795 | ||
796 | default: | |
797 | if ((decoded_options[i].orig_option_with_args_text != NULL) | |
798 | && (strncmp (decoded_options[i].orig_option_with_args_text, | |
799 | "-m", 2) == 0)) | |
800 | multilib_dir = xstrdup (decoded_options[i].orig_option_with_args_text | |
801 | + 2); | |
802 | } | |
803 | } | |
804 | if (language != NULL && (strcmp (language, "modula-2") != 0)) | |
805 | return; | |
806 | ||
807 | if (scaffold_static && scaffold_dynamic) | |
808 | { | |
809 | if (! seen_scaffold_dynamic) | |
810 | scaffold_dynamic = false; | |
811 | if (scaffold_dynamic && scaffold_static) | |
812 | error ("%qs and %qs cannot both be enabled", | |
813 | "-fscaffold-dynamic", "-fscaffold-static"); | |
814 | } | |
815 | if (uselist && gen_module_list) | |
816 | { | |
817 | if (! seen_gen_module_list) | |
818 | gen_module_list = false; | |
819 | if (uselist && gen_module_list) | |
820 | error ("%qs and %qs cannot both be enabled", | |
821 | "-fgen-module-list=", "-fuse-list="); | |
822 | } | |
823 | ||
824 | ||
825 | /* There's no point adding -shared-libgcc if we don't have a shared | |
826 | libgcc. */ | |
827 | #ifndef ENABLE_SHARED_LIBGCC | |
828 | shared_libgcc = 0; | |
829 | #endif | |
830 | ||
831 | /* Second pass through arglist, transforming arguments as appropriate. */ | |
832 | ||
833 | append_arg (&decoded_options[0]); /* Start with command name, of course. */ | |
834 | for (i = 1; i < argc; ++i) | |
835 | { | |
836 | #if defined(DEBUG_ARG) | |
837 | printf ("2nd pass: %s\n", | |
838 | decoded_options[i].orig_option_with_args_text); | |
839 | #endif | |
840 | if ((args[i] & SKIPOPT) == 0) | |
841 | { | |
842 | append_arg (&decoded_options[i]); | |
843 | /* Make sure -lstdc++ is before the math library, since libstdc++ | |
844 | itself uses those math routines. */ | |
845 | if (!saw_math && (args[i] & MATHLIB) && library > 0) | |
846 | saw_math = &decoded_options[i]; | |
847 | ||
848 | if (!saw_libc && (args[i] & WITHLIBC) && library > 0) | |
849 | saw_libc = &decoded_options[i]; | |
850 | } | |
851 | #if defined(DEBUG_ARG) | |
852 | else | |
853 | printf ("skipping: %s\n", | |
854 | decoded_options[i].orig_option_with_args_text); | |
855 | #endif | |
856 | } | |
857 | ||
858 | /* We now add in extra arguments to facilitate a successful | |
859 | compile or link. For example include paths for dialect of Modula-2, | |
860 | library paths and default scaffold linking options. */ | |
861 | ||
862 | /* If we have not seen either uselist or gen_module_list and we need | |
863 | to link then we turn on -fgen_module_list=- as the default. */ | |
864 | if ((! (seen_uselist || seen_gen_module_list)) && linking) | |
865 | append_option (OPT_fgen_module_list_, "-", 1); | |
866 | ||
867 | if (allow_libraries) | |
868 | { | |
869 | /* If the libraries have not been specified by the user but the | |
870 | dialect has been specified then select the appropriate libraries. */ | |
871 | if (libraries == NULL) | |
872 | { | |
873 | if (strcmp (dialect, "iso") == 0) | |
874 | libraries = xstrdup ("m2iso,m2pim"); | |
875 | else | |
876 | /* Default to pim libraries if none specified. */ | |
877 | libraries = xstrdup ("m2pim,m2log,m2iso"); | |
878 | } | |
879 | libraries = convert_abbreviations (libraries); | |
880 | if (! check_valid_list (libpath, libraries)) | |
881 | return; | |
882 | add_default_includes (libpath, libraries); | |
883 | } | |
884 | if ((! seen_x_flag) && seen_module_extension) | |
885 | append_option (OPT_x, "modula-2", 1); | |
886 | ||
887 | if (need_plugin) | |
888 | append_option (OPT_fplugin_, "m2rte", 1); | |
889 | ||
890 | if (linking) | |
891 | { | |
dd77b049 IS |
892 | #ifdef HAVE_LD_STATIC_DYNAMIC |
893 | if (allow_libraries && !shared_libgm2) | |
894 | append_option (OPT_Wl_, LD_STATIC_OPTION, 1); | |
895 | #endif | |
1eee94d3 GM |
896 | if (allow_libraries) |
897 | add_default_archives (libpath, libraries); | |
dd77b049 IS |
898 | #ifdef HAVE_LD_STATIC_DYNAMIC |
899 | if (allow_libraries && !shared_libgm2) | |
900 | append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1); | |
901 | #endif | |
1eee94d3 GM |
902 | /* Add `-lstdc++' if we haven't already done so. */ |
903 | #ifdef HAVE_LD_STATIC_DYNAMIC | |
904 | if (library > 1 && !static_link) | |
905 | append_option (OPT_Wl_, LD_STATIC_OPTION, 1); | |
906 | #endif | |
907 | if (which_library == USE_LIBCXX) | |
908 | { | |
909 | append_option (OPT_l, saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1); | |
910 | added_libraries++; | |
911 | if (LIBCXXABI != NULL) | |
912 | { | |
913 | append_option (OPT_l, saw_profile_flag ? LIBCXXABI_PROFILE | |
914 | : LIBCXXABI, 1); | |
915 | added_libraries++; | |
916 | } | |
917 | } | |
918 | else | |
919 | { | |
920 | append_option (OPT_l, saw_profile_flag ? LIBSTDCXX_PROFILE | |
921 | : LIBSTDCXX, 1); | |
922 | added_libraries++; | |
923 | } | |
924 | /* Add target-dependent static library, if necessary. */ | |
925 | if ((static_link || library > 1) && LIBSTDCXX_STATIC != NULL) | |
926 | { | |
927 | append_option (OPT_l, LIBSTDCXX_STATIC, 1); | |
928 | added_libraries++; | |
929 | } | |
930 | #ifdef HAVE_LD_STATIC_DYNAMIC | |
931 | if (library > 1 && !static_link) | |
932 | append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1); | |
933 | #endif | |
934 | } | |
935 | if (need_math) | |
936 | { | |
937 | append_option (OPT_l, saw_profile_flag ? MATH_LIBRARY_PROFILE : | |
938 | MATH_LIBRARY, 1); | |
939 | added_libraries++; | |
940 | } | |
941 | if (need_pthread) | |
942 | { | |
943 | append_option (OPT_l, "pthread", 1); | |
944 | added_libraries++; | |
945 | } | |
946 | if (shared_libgcc && !static_link) | |
947 | append_option (OPT_shared_libgcc, NULL, 1); | |
948 | ||
949 | if (verbose && gm2_new_decoded_options != gm2_x_decoded_options) | |
950 | { | |
951 | fprintf (stderr, _("Driving:")); | |
952 | for (i = 0; i < gm2_newargc; i++) | |
953 | fprintf (stderr, " %s", | |
954 | gm2_new_decoded_options[i].orig_option_with_args_text); | |
955 | fprintf (stderr, "\n"); | |
956 | fprintf (stderr, "new argc = %d, added_libraries = %d\n", | |
957 | gm2_newargc, added_libraries); | |
958 | } | |
959 | ||
960 | *in_decoded_options_count = gm2_newargc; | |
961 | *in_decoded_options = gm2_new_decoded_options; | |
962 | *in_added_libraries = added_libraries; | |
963 | } | |
964 | ||
965 | /* Called before linking. Returns 0 on success and -1 on failure. */ | |
966 | int | |
967 | lang_specific_pre_link (void) /* Not used for M2. */ | |
968 | { | |
969 | return 0; | |
970 | } | |
971 | ||
972 | /* Number of extra output files that lang_specific_pre_link may generate. */ | |
973 | int lang_specific_extra_outfiles = 0; |