00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #include "config.h"
00078 #include "system.h"
00079 #include "coretypes.h"
00080 #include "multilib.h"
00081 #include "tm.h"
00082 #include <signal.h>
00083 #if ! defined( SIGCHLD ) && defined( SIGCLD )
00084 # define SIGCHLD SIGCLD
00085 #endif
00086 #include "xregex.h"
00087 #include "obstack.h"
00088 #include "intl.h"
00089 #include "prefix.h"
00090 #include "gcc.h"
00091 #include "flags.h"
00092 #include "opts.h"
00093
00094
00095
00096 #if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
00097 #define HAVE_TARGET_EXECUTABLE_SUFFIX
00098 #endif
00099
00100
00101 #ifdef HOST_EXECUTABLE_SUFFIX
00102 #define HAVE_HOST_EXECUTABLE_SUFFIX
00103 #else
00104 #define HOST_EXECUTABLE_SUFFIX ""
00105 #endif
00106
00107
00108 #ifdef TARGET_OBJECT_SUFFIX
00109 #define HAVE_TARGET_OBJECT_SUFFIX
00110 #else
00111 #define TARGET_OBJECT_SUFFIX ".o"
00112 #endif
00113
00114 static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
00115
00116
00117 #ifndef LIBRARY_PATH_ENV
00118 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
00119 #endif
00120
00121 #ifndef HAVE_KILL
00122 #define kill(p,s) raise(s)
00123 #endif
00124
00125
00126
00127
00128 #define MIN_FATAL_STATUS 1
00129
00130
00131 int is_cpp_driver;
00132
00133
00134
00135 static int pass_exit_codes;
00136
00137
00138 #include "configargs.h"
00139
00140
00141
00142
00143 static int print_search_dirs;
00144
00145
00146
00147
00148 static const char *print_file_name = NULL;
00149
00150
00151
00152 static const char *print_prog_name = NULL;
00153
00154
00155
00156
00157 static int print_multi_directory;
00158
00159
00160
00161
00162 static int print_multi_os_directory;
00163
00164
00165
00166
00167 static int print_multi_lib;
00168
00169
00170
00171
00172 static int print_help_list;
00173
00174
00175
00176 static int verbose_flag;
00177
00178
00179
00180
00181
00182
00183 static int verbose_only_flag;
00184
00185
00186
00187 static int target_help_flag;
00188
00189
00190
00191
00192 static int report_times;
00193
00194 #ifdef KEY
00195
00196 static int flag_spin_file;
00197 #endif
00198
00199
00200
00201
00202 #ifdef TARGET_SYSTEM_ROOT
00203 static const char *target_system_root = TARGET_SYSTEM_ROOT;
00204 #else
00205 static const char *target_system_root = 0;
00206 #endif
00207
00208
00209
00210 static int target_system_root_changed;
00211
00212
00213
00214 static const char *target_sysroot_suffix = 0;
00215
00216
00217
00218 static const char *target_sysroot_hdrs_suffix = 0;
00219
00220
00221
00222
00223 static int save_temps_flag;
00224
00225
00226
00227 static int combine_flag = 0;
00228
00229
00230
00231
00232 static int use_pipes;
00233
00234
00235
00236 static const char *compiler_version;
00237
00238
00239
00240 static const char *const spec_version = DEFAULT_TARGET_VERSION;
00241
00242
00243
00244 static const char *spec_machine = DEFAULT_TARGET_MACHINE;
00245
00246
00247
00248
00249 #ifdef CROSS_COMPILE
00250 static const char *cross_compile = "1";
00251 #else
00252 static const char *cross_compile = "0";
00253 #endif
00254
00255 #ifdef MODIFY_TARGET_NAME
00256
00257
00258
00259
00260
00261 static const struct modify_target
00262 {
00263 const char *const sw;
00264 const enum add_del {ADD, DELETE} add_del;
00265 const char *const str;
00266 }
00267 modify_target[] = MODIFY_TARGET_NAME;
00268 #endif
00269
00270
00271
00272 static int error_count = 0;
00273
00274
00275
00276 static int greatest_status = 1;
00277
00278
00279
00280 static struct obstack obstack;
00281
00282
00283
00284
00285
00286
00287 static struct obstack collect_obstack;
00288
00289
00290 struct path_prefix;
00291 struct prefix_list;
00292
00293 static void init_spec (void);
00294 static void store_arg (const char *, int, int);
00295 static char *load_specs (const char *);
00296 static void read_specs (const char *, int);
00297 static void set_spec (const char *, const char *);
00298 static struct compiler *lookup_compiler (const char *, size_t, const char *);
00299 static char *build_search_list (const struct path_prefix *, const char *,
00300 bool, bool);
00301 static void putenv_from_prefixes (const struct path_prefix *, const char *,
00302 bool);
00303 static int access_check (const char *, int);
00304 static char *find_a_file (const struct path_prefix *, const char *, int, bool);
00305 static void add_prefix (struct path_prefix *, const char *, const char *,
00306 int, int, int);
00307 static void add_sysrooted_prefix (struct path_prefix *, const char *,
00308 const char *, int, int, int);
00309 static void translate_options (int *, const char *const **);
00310 static char *skip_whitespace (char *);
00311 static void delete_if_ordinary (const char *);
00312 static void delete_temp_files (void);
00313 static void delete_failure_queue (void);
00314 static void clear_failure_queue (void);
00315 static int check_live_switch (int, int);
00316 static const char *handle_braces (const char *);
00317 static inline bool input_suffix_matches (const char *, const char *);
00318 static inline bool switch_matches (const char *, const char *, int);
00319 static inline void mark_matching_switches (const char *, const char *, int);
00320 static inline void process_marked_switches (void);
00321 static const char *process_brace_body (const char *, const char *, const char *, int, int);
00322 static const struct spec_function *lookup_spec_function (const char *);
00323 static const char *eval_spec_function (const char *, const char *);
00324 static const char *handle_spec_function (const char *);
00325 static char *save_string (const char *, int);
00326 static void set_collect_gcc_options (void);
00327 static int do_spec_1 (const char *, int, const char *);
00328 static int do_spec_2 (const char *);
00329 static void do_option_spec (const char *, const char *);
00330 static void do_self_spec (const char *);
00331 static const char *find_file (const char *);
00332 static int is_directory (const char *, bool);
00333 static const char *validate_switches (const char *);
00334 static void validate_all_switches (void);
00335 static inline void validate_switches_from_spec (const char *);
00336 static void give_switch (int, int);
00337 static int used_arg (const char *, int);
00338 static int default_arg (const char *, int);
00339 static void set_multilib_dir (void);
00340 static void print_multilib_info (void);
00341 static void perror_with_name (const char *);
00342 static void fatal_ice (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
00343 static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
00344 static void display_help (void);
00345 static void add_preprocessor_option (const char *, int);
00346 static void add_assembler_option (const char *, int);
00347 static void add_linker_option (const char *, int);
00348 static void process_command (int, const char **);
00349 static int execute (void);
00350 static void alloc_args (void);
00351 static void clear_args (void);
00352 static void fatal_error (int);
00353 #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
00354 static void init_gcc_specs (struct obstack *, const char *, const char *,
00355 const char *);
00356 #endif
00357 #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
00358 static const char *convert_filename (const char *, int, int);
00359 #endif
00360
00361 static const char *if_exists_spec_function (int, const char **);
00362 static const char *if_exists_else_spec_function (int, const char **);
00363 static const char *replace_outfile_spec_function (int, const char **);
00364 static const char *version_compare_spec_function (int, const char **);
00365 static const char *include_spec_function (int, const char **);
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 #ifndef ASM_SPEC
00568 #define ASM_SPEC ""
00569 #endif
00570
00571
00572
00573 #ifndef ASM_FINAL_SPEC
00574 #define ASM_FINAL_SPEC ""
00575 #endif
00576
00577
00578
00579 #ifndef CPP_SPEC
00580 #define CPP_SPEC ""
00581 #endif
00582
00583
00584
00585 #ifndef CC1_SPEC
00586 #define CC1_SPEC ""
00587 #endif
00588
00589
00590
00591 #ifndef CC1PLUS_SPEC
00592 #define CC1PLUS_SPEC ""
00593 #endif
00594
00595
00596
00597 #ifndef LINK_SPEC
00598 #define LINK_SPEC ""
00599 #endif
00600
00601
00602 #ifndef LIB_SPEC
00603 #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
00604 #endif
00605
00606
00607 #ifndef MFWRAP_SPEC
00608
00609
00610 #define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
00611 --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
00612 --wrap=mmap --wrap=munmap --wrap=alloca\
00613 } %{fmudflapth: --wrap=pthread_create\
00614 }} %{fmudflap|fmudflapth: --wrap=main}"
00615 #endif
00616 #ifndef MFLIB_SPEC
00617 #define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}"
00618 #endif
00619
00620
00621
00622 #ifndef LIBGCC_SPEC
00623 #if defined(REAL_LIBGCC_SPEC)
00624 #define LIBGCC_SPEC REAL_LIBGCC_SPEC
00625 #elif defined(LINK_LIBGCC_SPECIAL_1)
00626
00627 #define LIBGCC_SPEC "libgcc.a%s"
00628 #else
00629 #define LIBGCC_SPEC "-lgcc"
00630 #endif
00631 #endif
00632
00633
00634 #ifndef STARTFILE_SPEC
00635 #define STARTFILE_SPEC \
00636 "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
00637 #endif
00638
00639
00640
00641 #ifndef SWITCHES_NEED_SPACES
00642 #define SWITCHES_NEED_SPACES ""
00643 #endif
00644
00645
00646 #ifndef ENDFILE_SPEC
00647 #define ENDFILE_SPEC ""
00648 #endif
00649
00650 #ifndef LINKER_NAME
00651 #define LINKER_NAME "collect2"
00652 #endif
00653
00654
00655
00656 #ifndef ASM_DEBUG_SPEC
00657 # if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
00658 && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
00659 # define ASM_DEBUG_SPEC \
00660 (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \
00661 ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \
00662 : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
00663 # else
00664 # if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
00665 # define ASM_DEBUG_SPEC "%{g*:--gstabs}"
00666 # endif
00667 # if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
00668 # define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
00669 # endif
00670 # endif
00671 #endif
00672 #ifndef ASM_DEBUG_SPEC
00673 # define ASM_DEBUG_SPEC ""
00674 #endif
00675
00676
00677
00678
00679
00680
00681 #ifndef LINK_GCC_C_SEQUENCE_SPEC
00682 #define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
00683 #endif
00684
00685 #ifndef LINK_SSP_SPEC
00686 #ifdef TARGET_LIBC_PROVIDES_SSP
00687 #define LINK_SSP_SPEC "%{fstack-protector:}"
00688 #else
00689 #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
00690 #endif
00691 #endif
00692
00693 #ifndef LINK_PIE_SPEC
00694 #ifdef HAVE_LD_PIE
00695 #define LINK_PIE_SPEC "%{pie:-pie} "
00696 #else
00697 #define LINK_PIE_SPEC "%{pie:} "
00698 #endif
00699 #endif
00700
00701
00702
00703
00704
00705
00706
00707 #ifndef LINK_COMMAND_SPEC
00708 #define LINK_COMMAND_SPEC "\
00709 %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
00710 %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
00711 %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
00712 %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
00713 %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
00714 %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
00715 %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
00716 %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
00717 #endif
00718
00719 #ifndef LINK_LIBGCC_SPEC
00720
00721 # define LINK_LIBGCC_SPEC "%D"
00722 #endif
00723
00724 #ifndef STARTFILE_PREFIX_SPEC
00725 # define STARTFILE_PREFIX_SPEC ""
00726 #endif
00727
00728 #ifndef SYSROOT_SPEC
00729 # define SYSROOT_SPEC "--sysroot=%R"
00730 #endif
00731
00732 #ifndef SYSROOT_SUFFIX_SPEC
00733 # define SYSROOT_SUFFIX_SPEC ""
00734 #endif
00735
00736 #ifndef SYSROOT_HEADERS_SUFFIX_SPEC
00737 # define SYSROOT_HEADERS_SUFFIX_SPEC ""
00738 #endif
00739
00740 static const char *asm_debug;
00741 static const char *cpp_spec = CPP_SPEC;
00742 static const char *cc1_spec = CC1_SPEC;
00743 static const char *cc1plus_spec = CC1PLUS_SPEC;
00744 static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
00745 static const char *link_ssp_spec = LINK_SSP_SPEC;
00746 static const char *asm_spec = ASM_SPEC;
00747 static const char *asm_final_spec = ASM_FINAL_SPEC;
00748 static const char *link_spec = LINK_SPEC;
00749 static const char *lib_spec = LIB_SPEC;
00750 static const char *mfwrap_spec = MFWRAP_SPEC;
00751 static const char *mflib_spec = MFLIB_SPEC;
00752 static const char *link_gomp_spec = "";
00753 static const char *libgcc_spec = LIBGCC_SPEC;
00754 static const char *endfile_spec = ENDFILE_SPEC;
00755 static const char *startfile_spec = STARTFILE_SPEC;
00756 static const char *switches_need_spaces = SWITCHES_NEED_SPACES;
00757 static const char *linker_name_spec = LINKER_NAME;
00758 static const char *link_command_spec = LINK_COMMAND_SPEC;
00759 static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
00760 static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
00761 static const char *sysroot_spec = SYSROOT_SPEC;
00762 static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
00763 static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 static const char *trad_capable_cpp =
00775 "cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}";
00776
00777
00778
00779
00780 static const char *cpp_unique_options =
00781 "%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\
00782 %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
00783 %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
00784 %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
00785 %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
00786 %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
00787 %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
00788 %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
00789 %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
00790 %{E|M|MM:%W{o*}}";
00791
00792
00793
00794
00795
00796
00797 static const char *cpp_options =
00798 "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
00799 %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
00800 %{undef} %{save-temps:-fpch-preprocess}";
00801
00802
00803
00804 static const char *cpp_debug_options = "%{d*}";
00805
00806
00807 static const char *cc1_options =
00808 "%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
00809 %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
00810 %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\
00811 %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
00812 %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
00813 %{Qn:-fno-ident} %{--help:--help}\
00814 %{--target-help:--target-help}\
00815 %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
00816 %{fsyntax-only:-o %j} %{-param*}\
00817 %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
00818 %{coverage:-fprofile-arcs -ftest-coverage}";
00819
00820 static const char *asm_options =
00821 "%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
00822
00823 static const char *invoke_as =
00824 #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
00825 "%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
00826 #else
00827 "%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
00828 #endif
00829
00830
00831
00832
00833 static struct obstack multilib_obstack;
00834 static const char *multilib_select;
00835 static const char *multilib_matches;
00836 static const char *multilib_defaults;
00837 static const char *multilib_exclusions;
00838
00839
00840
00841 #ifndef MULTILIB_DEFAULTS
00842 #define MULTILIB_DEFAULTS { "" }
00843 #endif
00844
00845 static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
00846
00847 #ifndef DRIVER_SELF_SPECS
00848 #define DRIVER_SELF_SPECS ""
00849 #endif
00850
00851
00852
00853 #ifndef GOMP_SELF_SPECS
00854 #define GOMP_SELF_SPECS "%{fopenmp: -pthread}"
00855 #endif
00856
00857 static const char *const driver_self_specs[] = {
00858 DRIVER_SELF_SPECS, GOMP_SELF_SPECS
00859 };
00860
00861 #ifndef OPTION_DEFAULT_SPECS
00862 #define OPTION_DEFAULT_SPECS { "", "" }
00863 #endif
00864
00865 struct default_spec
00866 {
00867 const char *name;
00868 const char *spec;
00869 };
00870
00871 static const struct default_spec
00872 option_default_specs[] = { OPTION_DEFAULT_SPECS };
00873
00874 struct user_specs
00875 {
00876 struct user_specs *next;
00877 const char *filename;
00878 };
00879
00880 static struct user_specs *user_specs_head, *user_specs_tail;
00881
00882 #ifndef SWITCH_TAKES_ARG
00883 #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
00884 #endif
00885
00886 #ifndef WORD_SWITCH_TAKES_ARG
00887 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
00888 #endif
00889
00890 #ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
00891
00892 #define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
00893 ((CHAR) == 'c' || (CHAR) == 'S')
00894
00895 #ifndef SWITCH_CURTAILS_COMPILATION
00896 #define SWITCH_CURTAILS_COMPILATION(CHAR) \
00897 DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
00898 #endif
00899 #endif
00900
00901
00902
00903 struct compiler
00904 {
00905 const char *suffix;
00906
00907
00908 const char *spec;
00909
00910 const char *cpp_spec;
00911
00912
00913 const int combinable;
00914
00915 const int needs_preprocessing;
00916
00917 };
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 static struct compiler *compilers;
00929
00930
00931
00932 static int n_compilers;
00933
00934
00935
00936 static const struct compiler default_compilers[] =
00937 {
00938
00939
00940
00941
00942 {".m", "#Objective-C", 0, 0, 0}, {".mi", "#Objective-C", 0, 0, 0},
00943 {".mm", "#Objective-C++", 0, 0, 0}, {".M", "#Objective-C++", 0, 0, 0},
00944 {".mii", "#Objective-C++", 0, 0, 0},
00945 {".cc", "#C++", 0, 0, 0}, {".cxx", "#C++", 0, 0, 0},
00946 {".cpp", "#C++", 0, 0, 0}, {".cp", "#C++", 0, 0, 0},
00947 {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
00948 {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
00949 {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
00950 {".f", "#Fortran", 0, 0, 0}, {".for", "#Fortran", 0, 0, 0},
00951 {".fpp", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
00952 {".FOR", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
00953 {".f90", "#Fortran", 0, 0, 0}, {".f95", "#Fortran", 0, 0, 0},
00954 {".F90", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
00955 {".r", "#Ratfor", 0, 0, 0},
00956 {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
00957 {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
00958 {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0},
00959
00960 {".c", "@c", 0, 1, 1},
00961 {"@c",
00962
00963
00964 "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
00965 %{!E:%{!M:%{!MM:\
00966 %{traditional|ftraditional:\
00967 %eGNU C no longer supports -traditional without -E}\
00968 %{!combine:\
00969 %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
00970 %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
00971 cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
00972 %(cc1_options)}\
00973 %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
00974 cc1 %(cpp_unique_options) %(cc1_options)}}}\
00975 %{!fsyntax-only:%(invoke_as)}} \
00976 %{combine:\
00977 %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
00978 %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i}}\
00979 %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
00980 cc1 %(cpp_unique_options) %(cc1_options)}}\
00981 %{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1},
00982 {"-",
00983 "%{!E:%e-E or -x required when input is from standard input}\
00984 %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0},
00985 {".h", "@c-header", 0, 0, 0},
00986 {"@c-header",
00987
00988
00989 "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
00990 %{!E:%{!M:%{!MM:\
00991 %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
00992 %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
00993 cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
00994 %(cc1_options)\
00995 -o %g.s %{!o*:--output-pch=%i.gch}\
00996 %W{o*:--output-pch=%*}%V}\
00997 %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
00998 cc1 %(cpp_unique_options) %(cc1_options)\
00999 -o %g.s %{!o*:--output-pch=%i.gch}\
01000 %W{o*:--output-pch=%*}%V}}}}}}", 0, 0, 0},
01001 {".i", "@cpp-output", 0, 1, 0},
01002 {"@cpp-output",
01003 "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
01004 {".s", "@assembler", 0, 1, 0},
01005 {"@assembler",
01006 "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0},
01007 {".S", "@assembler-with-cpp", 0, 1, 0},
01008 {"@assembler-with-cpp",
01009 #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
01010 "%(trad_capable_cpp) -lang-asm %(cpp_options)\
01011 %{E|M|MM:%(cpp_debug_options)}\
01012 %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
01013 as %(asm_debug) %(asm_options) %|.s %A }}}}"
01014 #else
01015 "%(trad_capable_cpp) -lang-asm %(cpp_options)\
01016 %{E|M|MM:%(cpp_debug_options)}\
01017 %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
01018 as %(asm_debug) %(asm_options) %m.s %A }}}}"
01019 #endif
01020 , 0, 1, 0},
01021
01022 #include "specs.h"
01023
01024 {0, 0, 0, 0, 0}
01025 };
01026
01027
01028
01029 static const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
01030
01031
01032
01033
01034 static int n_linker_options;
01035 static char **linker_options;
01036
01037
01038
01039
01040 static int n_assembler_options;
01041 static char **assembler_options;
01042
01043
01044
01045
01046 static int n_preprocessor_options;
01047 static char **preprocessor_options;
01048
01049
01050
01051
01052 struct option_map
01053 {
01054
01055 const char *const name;
01056
01057 const char *const equivalent;
01058
01059
01060
01061
01062
01063 const char *const arg_info;
01064 };
01065
01066
01067
01068
01069 static const struct option_map option_map[] =
01070 {
01071 {"--all-warnings", "-Wall", 0},
01072 {"--ansi", "-ansi", 0},
01073 {"--assemble", "-S", 0},
01074 {"--assert", "-A", "a"},
01075 {"--classpath", "-fclasspath=", "aj"},
01076 {"--bootclasspath", "-fbootclasspath=", "aj"},
01077 {"--CLASSPATH", "-fclasspath=", "aj"},
01078 {"--combine", "-combine", 0},
01079 {"--comments", "-C", 0},
01080 {"--comments-in-macros", "-CC", 0},
01081 {"--compile", "-c", 0},
01082 {"--debug", "-g", "oj"},
01083 {"--define-macro", "-D", "aj"},
01084 {"--dependencies", "-M", 0},
01085 {"--dump", "-d", "a"},
01086 {"--dumpbase", "-dumpbase", "a"},
01087 {"--encoding", "-fencoding=", "aj"},
01088 {"--entry", "-e", 0},
01089 {"--extra-warnings", "-W", 0},
01090 {"--extdirs", "-fextdirs=", "aj"},
01091 {"--for-assembler", "-Wa", "a"},
01092 {"--for-linker", "-Xlinker", "a"},
01093 {"--force-link", "-u", "a"},
01094 {"--coverage", "-coverage", 0},
01095 {"--imacros", "-imacros", "a"},
01096 {"--include", "-include", "a"},
01097 {"--include-barrier", "-I-", 0},
01098 {"--include-directory", "-I", "aj"},
01099 {"--include-directory-after", "-idirafter", "a"},
01100 {"--include-prefix", "-iprefix", "a"},
01101 {"--include-with-prefix", "-iwithprefix", "a"},
01102 {"--include-with-prefix-before", "-iwithprefixbefore", "a"},
01103 {"--include-with-prefix-after", "-iwithprefix", "a"},
01104 {"--language", "-x", "a"},
01105 {"--library-directory", "-L", "a"},
01106 {"--machine", "-m", "aj"},
01107 {"--machine-", "-m", "*j"},
01108 {"--no-integrated-cpp", "-no-integrated-cpp", 0},
01109 {"--no-line-commands", "-P", 0},
01110 {"--no-precompiled-includes", "-noprecomp", 0},
01111 {"--no-standard-includes", "-nostdinc", 0},
01112 {"--no-standard-libraries", "-nostdlib", 0},
01113 {"--no-warnings", "-w", 0},
01114 {"--optimize", "-O", "oj"},
01115 {"--output", "-o", "a"},
01116 {"--output-class-directory", "-foutput-class-dir=", "ja"},
01117 {"--param", "--param", "a"},
01118 {"--pass-exit-codes", "-pass-exit-codes", 0},
01119 {"--pedantic", "-pedantic", 0},
01120 {"--pedantic-errors", "-pedantic-errors", 0},
01121 {"--pie", "-pie", 0},
01122 {"--pipe", "-pipe", 0},
01123 {"--prefix", "-B", "a"},
01124 {"--preprocess", "-E", 0},
01125 {"--print-search-dirs", "-print-search-dirs", 0},
01126 {"--print-file-name", "-print-file-name=", "aj"},
01127 {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
01128 {"--print-missing-file-dependencies", "-MG", 0},
01129 {"--print-multi-lib", "-print-multi-lib", 0},
01130 {"--print-multi-directory", "-print-multi-directory", 0},
01131 {"--print-multi-os-directory", "-print-multi-os-directory", 0},
01132 {"--print-prog-name", "-print-prog-name=", "aj"},
01133 {"--profile", "-p", 0},
01134 {"--profile-blocks", "-a", 0},
01135 {"--quiet", "-q", 0},
01136 {"--resource", "-fcompile-resource=", "aj"},
01137 {"--save-temps", "-save-temps", 0},
01138 {"--shared", "-shared", 0},
01139 {"--silent", "-q", 0},
01140 {"--specs", "-specs=", "aj"},
01141 {"--static", "-static", 0},
01142 {"--std", "-std=", "aj"},
01143 {"--symbolic", "-symbolic", 0},
01144 {"--sysroot", "--sysroot=", "aj"},
01145 {"--time", "-time", 0},
01146 {"--trace-includes", "-H", 0},
01147 {"--traditional", "-traditional", 0},
01148 {"--traditional-cpp", "-traditional-cpp", 0},
01149 {"--trigraphs", "-trigraphs", 0},
01150 {"--undefine-macro", "-U", "aj"},
01151 {"--user-dependencies", "-MM", 0},
01152 {"--verbose", "-v", 0},
01153 {"--warn-", "-W", "*j"},
01154 {"--write-dependencies", "-MD", 0},
01155 {"--write-user-dependencies", "-MMD", 0},
01156 {"--", "-f", "*j"}
01157 };
01158
01159
01160 #ifdef TARGET_OPTION_TRANSLATE_TABLE
01161 static const struct {
01162 const char *const option_found;
01163 const char *const replacements;
01164 } target_option_translations[] =
01165 {
01166 TARGET_OPTION_TRANSLATE_TABLE,
01167 { 0, 0 }
01168 };
01169 #endif
01170
01171
01172
01173
01174
01175 static void
01176 translate_options (int *argcp, const char *const **argvp)
01177 {
01178 int i;
01179 int argc = *argcp;
01180 const char *const *argv = *argvp;
01181 int newvsize = (argc + 2) * 2 * sizeof (const char *);
01182 const char **newv = xmalloc (newvsize);
01183 int newindex = 0;
01184
01185 i = 0;
01186 newv[newindex++] = argv[i++];
01187
01188 while (i < argc)
01189 {
01190 #ifdef TARGET_OPTION_TRANSLATE_TABLE
01191 int tott_idx;
01192
01193 for (tott_idx = 0;
01194 target_option_translations[tott_idx].option_found;
01195 tott_idx++)
01196 {
01197 if (strcmp (target_option_translations[tott_idx].option_found,
01198 argv[i]) == 0)
01199 {
01200 int spaces = 1;
01201 const char *sp;
01202 char *np;
01203
01204 for (sp = target_option_translations[tott_idx].replacements;
01205 *sp; sp++)
01206 {
01207 if (*sp == ' ')
01208 spaces ++;
01209 }
01210
01211 newvsize += spaces * sizeof (const char *);
01212 newv = xrealloc (newv, newvsize);
01213
01214 sp = target_option_translations[tott_idx].replacements;
01215 np = xstrdup (sp);
01216
01217 while (1)
01218 {
01219 while (*np == ' ')
01220 np++;
01221 if (*np == 0)
01222 break;
01223 newv[newindex++] = np;
01224 while (*np != ' ' && *np)
01225 np++;
01226 if (*np == 0)
01227 break;
01228 *np++ = 0;
01229 }
01230
01231 i ++;
01232 break;
01233 }
01234 }
01235 if (target_option_translations[tott_idx].option_found)
01236 continue;
01237 #endif
01238
01239
01240 if (argv[i][0] == '-' && argv[i][1] == '-')
01241 {
01242 size_t j;
01243
01244 for (j = 0; j < ARRAY_SIZE (option_map); j++)
01245 {
01246 size_t optlen = strlen (option_map[j].name);
01247 size_t arglen = strlen (argv[i]);
01248 size_t complen = arglen > optlen ? optlen : arglen;
01249 const char *arginfo = option_map[j].arg_info;
01250
01251 if (arginfo == 0)
01252 arginfo = "";
01253
01254 if (!strncmp (argv[i], option_map[j].name, complen))
01255 {
01256 const char *arg = 0;
01257
01258 if (arglen < optlen)
01259 {
01260 size_t k;
01261 for (k = j + 1; k < ARRAY_SIZE (option_map); k++)
01262 if (strlen (option_map[k].name) >= arglen
01263 && !strncmp (argv[i], option_map[k].name, arglen))
01264 {
01265 error ("ambiguous abbreviation %s", argv[i]);
01266 break;
01267 }
01268
01269 if (k != ARRAY_SIZE (option_map))
01270 break;
01271 }
01272
01273 if (arglen > optlen)
01274 {
01275
01276 if (argv[i][optlen] == '=')
01277 arg = argv[i] + optlen + 1;
01278
01279
01280
01281 else if (strchr (arginfo, '*') != 0)
01282 arg = argv[i] + optlen;
01283
01284
01285
01286 else
01287 continue;
01288 }
01289
01290 else if (strchr (arginfo, '*') != 0)
01291 {
01292 error ("incomplete '%s' option", option_map[j].name);
01293 break;
01294 }
01295
01296
01297 if (strchr (arginfo, 'a') != 0)
01298 {
01299 if (arg == 0)
01300 {
01301 if (i + 1 == argc)
01302 {
01303 error ("missing argument to '%s' option",
01304 option_map[j].name);
01305 break;
01306 }
01307
01308 arg = argv[++i];
01309 }
01310 }
01311 else if (strchr (arginfo, '*') != 0)
01312 ;
01313 else if (strchr (arginfo, 'o') == 0)
01314 {
01315 if (arg != 0)
01316 error ("extraneous argument to '%s' option",
01317 option_map[j].name);
01318 arg = 0;
01319 }
01320
01321
01322 if (arg != 0 && strchr (arginfo, 'j') != 0)
01323 newv[newindex++] = concat (option_map[j].equivalent, arg,
01324 NULL);
01325 else if (arg != 0)
01326 {
01327 newv[newindex++] = option_map[j].equivalent;
01328 newv[newindex++] = arg;
01329 }
01330 else
01331 newv[newindex++] = option_map[j].equivalent;
01332
01333 break;
01334 }
01335 }
01336 i++;
01337 }
01338
01339
01340
01341 else if (argv[i][0] == '-')
01342 {
01343 const char *p = argv[i] + 1;
01344 int c = *p;
01345 int nskip = 1;
01346
01347 if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
01348 nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
01349 else if (WORD_SWITCH_TAKES_ARG (p))
01350 nskip += WORD_SWITCH_TAKES_ARG (p);
01351 else if ((c == 'B' || c == 'b' || c == 'x')
01352 && p[1] == 0)
01353 nskip += 1;
01354 else if (! strcmp (p, "Xlinker"))
01355 nskip += 1;
01356 else if (! strcmp (p, "Xpreprocessor"))
01357 nskip += 1;
01358 else if (! strcmp (p, "Xassembler"))
01359 nskip += 1;
01360
01361
01362
01363
01364 if (nskip + i > argc)
01365 nskip = argc - i;
01366
01367 while (nskip > 0)
01368 {
01369 newv[newindex++] = argv[i++];
01370 nskip--;
01371 }
01372 }
01373 else
01374
01375 newv[newindex++] = argv[i++];
01376 }
01377
01378 newv[newindex] = 0;
01379
01380 *argvp = newv;
01381 *argcp = newindex;
01382 }
01383
01384 static char *
01385 skip_whitespace (char *p)
01386 {
01387 while (1)
01388 {
01389
01390
01391 if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
01392 return p + 1;
01393 else if (*p == '\n' || *p == ' ' || *p == '\t')
01394 p++;
01395 else if (*p == '#')
01396 {
01397 while (*p != '\n')
01398 p++;
01399 p++;
01400 }
01401 else
01402 break;
01403 }
01404
01405 return p;
01406 }
01407
01408
01409 struct prefix_list
01410 {
01411 const char *prefix;
01412 struct prefix_list *next;
01413 int require_machine_suffix;
01414
01415 int priority;
01416 int os_multilib;
01417
01418 };
01419
01420 struct path_prefix
01421 {
01422 struct prefix_list *plist;
01423 int max_len;
01424 const char *name;
01425 };
01426
01427
01428
01429 static struct path_prefix exec_prefixes = { 0, 0, "exec" };
01430
01431
01432
01433 static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
01434
01435
01436
01437 static struct path_prefix include_prefixes = { 0, 0, "include" };
01438
01439
01440
01441
01442 static const char *machine_suffix = 0;
01443
01444
01445
01446
01447 static const char *just_machine_suffix = 0;
01448
01449
01450
01451 static const char *gcc_exec_prefix;
01452
01453
01454
01455 static const char *gcc_libexec_prefix;
01456
01457
01458
01459 #ifndef STANDARD_STARTFILE_PREFIX_1
01460 #define STANDARD_STARTFILE_PREFIX_1 "/lib/"
01461 #endif
01462 #ifndef STANDARD_STARTFILE_PREFIX_2
01463 #define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
01464 #endif
01465
01466 #ifdef CROSS_COMPILE
01467 #undef MD_EXEC_PREFIX
01468 #undef MD_STARTFILE_PREFIX
01469 #undef MD_STARTFILE_PREFIX_1
01470 #endif
01471
01472
01473 #ifndef MD_EXEC_PREFIX
01474 #define MD_EXEC_PREFIX ""
01475 #endif
01476 #ifndef MD_STARTFILE_PREFIX
01477 #define MD_STARTFILE_PREFIX ""
01478 #endif
01479 #ifndef MD_STARTFILE_PREFIX_1
01480 #define MD_STARTFILE_PREFIX_1 ""
01481 #endif
01482
01483 static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
01484 static const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
01485 static const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
01486 static const char *md_exec_prefix = MD_EXEC_PREFIX;
01487
01488 static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
01489 static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
01490 static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
01491 static const char *const standard_startfile_prefix_1
01492 = STANDARD_STARTFILE_PREFIX_1;
01493 static const char *const standard_startfile_prefix_2
01494 = STANDARD_STARTFILE_PREFIX_2;
01495
01496 static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
01497 static const char *tooldir_prefix;
01498
01499 static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
01500
01501 static const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
01502
01503
01504
01505
01506 static const char *multilib_dir;
01507
01508
01509
01510
01511 static const char *multilib_os_dir;
01512
01513
01514
01515
01516
01517 struct spec_list
01518 {
01519
01520
01521 const char *name;
01522 const char *ptr;
01523
01524
01525
01526 const char **ptr_spec;
01527 struct spec_list *next;
01528 int name_len;
01529 int alloc_p;
01530 };
01531
01532 #define INIT_STATIC_SPEC(NAME,PTR) \
01533 { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
01534
01535
01536 static struct spec_list static_specs[] =
01537 {
01538 INIT_STATIC_SPEC ("asm", &asm_spec),
01539 INIT_STATIC_SPEC ("asm_debug", &asm_debug),
01540 INIT_STATIC_SPEC ("asm_final", &asm_final_spec),
01541 INIT_STATIC_SPEC ("asm_options", &asm_options),
01542 INIT_STATIC_SPEC ("invoke_as", &invoke_as),
01543 INIT_STATIC_SPEC ("cpp", &cpp_spec),
01544 INIT_STATIC_SPEC ("cpp_options", &cpp_options),
01545 INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options),
01546 INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options),
01547 INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp),
01548 INIT_STATIC_SPEC ("cc1", &cc1_spec),
01549 INIT_STATIC_SPEC ("cc1_options", &cc1_options),
01550 INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
01551 INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec),
01552 INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec),
01553 INIT_STATIC_SPEC ("endfile", &endfile_spec),
01554 INIT_STATIC_SPEC ("link", &link_spec),
01555 INIT_STATIC_SPEC ("lib", &lib_spec),
01556 INIT_STATIC_SPEC ("mfwrap", &mfwrap_spec),
01557 INIT_STATIC_SPEC ("mflib", &mflib_spec),
01558 INIT_STATIC_SPEC ("link_gomp", &link_gomp_spec),
01559 INIT_STATIC_SPEC ("libgcc", &libgcc_spec),
01560 INIT_STATIC_SPEC ("startfile", &startfile_spec),
01561 INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces),
01562 INIT_STATIC_SPEC ("cross_compile", &cross_compile),
01563 INIT_STATIC_SPEC ("version", &compiler_version),
01564 INIT_STATIC_SPEC ("multilib", &multilib_select),
01565 INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults),
01566 INIT_STATIC_SPEC ("multilib_extra", &multilib_extra),
01567 INIT_STATIC_SPEC ("multilib_matches", &multilib_matches),
01568 INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions),
01569 INIT_STATIC_SPEC ("multilib_options", &multilib_options),
01570 INIT_STATIC_SPEC ("linker", &linker_name_spec),
01571 INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec),
01572 INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix),
01573 INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
01574 INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1),
01575 INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec),
01576 INIT_STATIC_SPEC ("sysroot_spec", &sysroot_spec),
01577 INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec),
01578 INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec),
01579 };
01580
01581 #ifdef EXTRA_SPECS
01582
01583
01584 struct spec_list_1
01585 {
01586 const char *const name;
01587 const char *const ptr;
01588 };
01589
01590 static const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
01591 static struct spec_list *extra_specs = (struct spec_list *) 0;
01592 #endif
01593
01594
01595
01596 static struct spec_list *specs = (struct spec_list *) 0;
01597
01598
01599
01600 static const struct spec_function static_spec_functions[] =
01601 {
01602 { "if-exists", if_exists_spec_function },
01603 { "if-exists-else", if_exists_else_spec_function },
01604 { "replace-outfile", replace_outfile_spec_function },
01605 { "version-compare", version_compare_spec_function },
01606 { "include", include_spec_function },
01607 #ifdef EXTRA_SPEC_FUNCTIONS
01608 EXTRA_SPEC_FUNCTIONS
01609 #endif
01610 { 0, 0 }
01611 };
01612
01613 static int processing_spec_function;
01614
01615
01616
01617
01618 #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
01619
01620 #ifndef USE_LD_AS_NEEDED
01621 #define USE_LD_AS_NEEDED 0
01622 #endif
01623
01624 static void
01625 init_gcc_specs (struct obstack *obstack, const char *shared_name,
01626 const char *static_name, const char *eh_name)
01627 {
01628 char *buf;
01629
01630 buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, "}"
01631 "%{!static:%{!static-libgcc:"
01632 #if USE_LD_AS_NEEDED
01633 "%{!shared-libgcc:",
01634 static_name, " --as-needed ", shared_name, " --no-as-needed"
01635 "}"
01636 "%{shared-libgcc:",
01637 shared_name, "%{!shared: ", static_name, "}"
01638 "}"
01639 #else
01640 "%{!shared:"
01641 "%{!shared-libgcc:", static_name, " ", eh_name, "}"
01642 "%{shared-libgcc:", shared_name, " ", static_name, "}"
01643 "}"
01644 #ifdef LINK_EH_SPEC
01645 "%{shared:"
01646 "%{shared-libgcc:", shared_name, "}"
01647 "%{!shared-libgcc:", static_name, "}"
01648 "}"
01649 #else
01650 "%{shared:", shared_name, "}"
01651 #endif
01652 #endif
01653 "}}", NULL);
01654
01655 obstack_grow (obstack, buf, strlen (buf));
01656 free (buf);
01657 }
01658 #endif
01659
01660
01661
01662 static void
01663 init_spec (void)
01664 {
01665 struct spec_list *next = (struct spec_list *) 0;
01666 struct spec_list *sl = (struct spec_list *) 0;
01667 int i;
01668
01669 if (specs)
01670 return;
01671
01672 if (verbose_flag)
01673 notice ("Using built-in specs.\n");
01674
01675 #ifdef EXTRA_SPECS
01676 extra_specs = xcalloc (sizeof (struct spec_list),
01677 ARRAY_SIZE (extra_specs_1));
01678
01679 for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
01680 {
01681 sl = &extra_specs[i];
01682 sl->name = extra_specs_1[i].name;
01683 sl->ptr = extra_specs_1[i].ptr;
01684 sl->next = next;
01685 sl->name_len = strlen (sl->name);
01686 sl->ptr_spec = &sl->ptr;
01687 next = sl;
01688 }
01689 #endif
01690
01691
01692
01693 asm_debug = ASM_DEBUG_SPEC;
01694
01695 for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
01696 {
01697 sl = &static_specs[i];
01698 sl->next = next;
01699 next = sl;
01700 }
01701
01702 #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730 {
01731 const char *p = libgcc_spec;
01732 int in_sep = 1;
01733
01734
01735
01736 while (*p)
01737 {
01738 if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
01739 {
01740 init_gcc_specs (&obstack,
01741 "-lgcc_s"
01742 #ifdef USE_LIBUNWIND_EXCEPTIONS
01743 " -lunwind"
01744 #endif
01745 ,
01746 "-lgcc",
01747 "-lgcc_eh"
01748 #ifdef USE_LIBUNWIND_EXCEPTIONS
01749 # ifdef HAVE_LD_STATIC_DYNAMIC
01750 " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}"
01751 # else
01752 " -lunwind"
01753 # endif
01754 #endif
01755 );
01756
01757 p += 5;
01758 in_sep = 0;
01759 }
01760 else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
01761 {
01762
01763
01764 init_gcc_specs (&obstack,
01765 "-lgcc_s",
01766 "libgcc.a%s",
01767 "libgcc_eh.a%s"
01768 #ifdef USE_LIBUNWIND_EXCEPTIONS
01769 " -lunwind"
01770 #endif
01771 );
01772 p += 10;
01773 in_sep = 0;
01774 }
01775 else
01776 {
01777 obstack_1grow (&obstack, *p);
01778 in_sep = (*p == ' ');
01779 p += 1;
01780 }
01781 }
01782
01783 obstack_1grow (&obstack, '\0');
01784 libgcc_spec = XOBFINISH (&obstack, const char *);
01785 }
01786 #endif
01787 #ifdef USE_AS_TRADITIONAL_FORMAT
01788
01789 {
01790 static const char tf[] = "--traditional-format ";
01791 obstack_grow (&obstack, tf, sizeof(tf) - 1);
01792 obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
01793 asm_spec = XOBFINISH (&obstack, const char *);
01794 }
01795 #endif
01796 #ifdef LINK_EH_SPEC
01797
01798 obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
01799 obstack_grow0 (&obstack, link_spec, strlen (link_spec));
01800 link_spec = XOBFINISH (&obstack, const char *);
01801 #endif
01802
01803 specs = sl;
01804 }
01805
01806
01807
01808
01809
01810 static void
01811 set_spec (const char *name, const char *spec)
01812 {
01813 struct spec_list *sl;
01814 const char *old_spec;
01815 int name_len = strlen (name);
01816 int i;
01817
01818
01819 if (!specs)
01820 {
01821 struct spec_list *next = (struct spec_list *) 0;
01822 for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
01823 {
01824 sl = &static_specs[i];
01825 sl->next = next;
01826 next = sl;
01827 }
01828 specs = sl;
01829 }
01830
01831
01832 for (sl = specs; sl; sl = sl->next)
01833 if (name_len == sl->name_len && !strcmp (sl->name, name))
01834 break;
01835
01836 if (!sl)
01837 {
01838
01839 sl = XNEW (struct spec_list);
01840 sl->name = xstrdup (name);
01841 sl->name_len = name_len;
01842 sl->ptr_spec = &sl->ptr;
01843 sl->alloc_p = 0;
01844 *(sl->ptr_spec) = "";
01845 sl->next = specs;
01846 specs = sl;
01847 }
01848
01849 old_spec = *(sl->ptr_spec);
01850 *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
01851 ? concat (old_spec, spec + 1, NULL)
01852 : xstrdup (spec));
01853
01854 #ifdef DEBUG_SPECS
01855 if (verbose_flag)
01856 notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
01857 #endif
01858
01859
01860 if (old_spec && sl->alloc_p)
01861 free ((void *) old_spec);
01862
01863 sl->alloc_p = 1;
01864 }
01865
01866
01867
01868
01869
01870 static const char **argbuf;
01871
01872
01873
01874 static int argbuf_length;
01875
01876
01877
01878 static int argbuf_index;
01879
01880
01881
01882
01883 static int have_o_argbuf_index = 0;
01884
01885
01886 static int have_c = 0;
01887
01888
01889 static int have_o = 0;
01890
01891
01892
01893
01894
01895 static struct temp_name {
01896 const char *suffix;
01897 int length;
01898 int unique;
01899 const char *filename;
01900 int filename_length;
01901 struct temp_name *next;
01902 } *temp_names;
01903
01904
01905
01906 static int execution_count;
01907
01908
01909
01910 static int signal_count;
01911
01912
01913
01914 static const char *programname;
01915
01916
01917
01918 static void
01919 alloc_args (void)
01920 {
01921 argbuf_length = 10;
01922 argbuf = XNEWVEC (const char *, argbuf_length);
01923 }
01924
01925
01926
01927 static void
01928 clear_args (void)
01929 {
01930 argbuf_index = 0;
01931 }
01932
01933
01934
01935
01936
01937
01938
01939
01940 static void
01941 store_arg (const char *arg, int delete_always, int delete_failure)
01942 {
01943 if (argbuf_index + 1 == argbuf_length)
01944 argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
01945
01946 argbuf[argbuf_index++] = arg;
01947 argbuf[argbuf_index] = 0;
01948
01949 if (strcmp (arg, "-o") == 0)
01950 have_o_argbuf_index = argbuf_index;
01951 if (delete_always || delete_failure)
01952 record_temp_file (arg, delete_always, delete_failure);
01953 }
01954
01955
01956
01957
01958
01959 static char *
01960 load_specs (const char *filename)
01961 {
01962 int desc;
01963 int readlen;
01964 struct stat statbuf;
01965 char *buffer;
01966 char *buffer_p;
01967 char *specs;
01968 char *specs_p;
01969
01970 if (verbose_flag)
01971 notice ("Reading specs from %s\n", filename);
01972
01973
01974 desc = open (filename, O_RDONLY, 0);
01975 if (desc < 0)
01976 pfatal_with_name (filename);
01977 if (stat (filename, &statbuf) < 0)
01978 pfatal_with_name (filename);
01979
01980
01981 buffer = XNEWVEC (char, statbuf.st_size + 1);
01982 readlen = read (desc, buffer, (unsigned) statbuf.st_size);
01983 if (readlen < 0)
01984 pfatal_with_name (filename);
01985 buffer[readlen] = 0;
01986 close (desc);
01987
01988 specs = XNEWVEC (char, readlen + 1);
01989 specs_p = specs;
01990 for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
01991 {
01992 int skip = 0;
01993 char c = *buffer_p;
01994 if (c == '\r')
01995 {
01996 if (buffer_p > buffer && *(buffer_p - 1) == '\n')
01997 skip = 1;
01998 else if (*(buffer_p + 1) == '\n')
01999 skip = 1;
02000 else
02001 c = '\n';
02002 }
02003 if (! skip)
02004 *specs_p++ = c;
02005 }
02006 *specs_p = '\0';
02007
02008 free (buffer);
02009 return (specs);
02010 }
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023 static void
02024 read_specs (const char *filename, int main_p)
02025 {
02026 char *buffer;
02027 char *p;
02028
02029 buffer = load_specs (filename);
02030
02031
02032 p = buffer;
02033 while (1)
02034 {
02035 char *suffix;
02036 char *spec;
02037 char *in, *out, *p1, *p2, *p3;
02038
02039
02040 p = skip_whitespace (p);
02041 if (*p == 0)
02042 break;
02043
02044
02045
02046
02047 if (*p == '%' && !main_p)
02048 {
02049 p1 = p;
02050 while (*p && *p != '\n')
02051 p++;
02052
02053
02054 p++;
02055
02056 if (!strncmp (p1, "%include", sizeof ("%include") - 1)
02057 && (p1[sizeof "%include" - 1] == ' '
02058 || p1[sizeof "%include" - 1] == '\t'))
02059 {
02060 char *new_filename;
02061
02062 p1 += sizeof ("%include");
02063 while (*p1 == ' ' || *p1 == '\t')
02064 p1++;
02065
02066 if (*p1++ != '<' || p[-2] != '>')
02067 fatal ("specs %%include syntax malformed after %ld characters",
02068 (long) (p1 - buffer + 1));
02069
02070 p[-2] = '\0';
02071 new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
02072 read_specs (new_filename ? new_filename : p1, FALSE);
02073 continue;
02074 }
02075 else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
02076 && (p1[sizeof "%include_noerr" - 1] == ' '
02077 || p1[sizeof "%include_noerr" - 1] == '\t'))
02078 {
02079 char *new_filename;
02080
02081 p1 += sizeof "%include_noerr";
02082 while (*p1 == ' ' || *p1 == '\t')
02083 p1++;
02084
02085 if (*p1++ != '<' || p[-2] != '>')
02086 fatal ("specs %%include syntax malformed after %ld characters",
02087 (long) (p1 - buffer + 1));
02088
02089 p[-2] = '\0';
02090 new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
02091 if (new_filename)
02092 read_specs (new_filename, FALSE);
02093 else if (verbose_flag)
02094 notice ("could not find specs file %s\n", p1);
02095 continue;
02096 }
02097 else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
02098 && (p1[sizeof "%rename" - 1] == ' '
02099 || p1[sizeof "%rename" - 1] == '\t'))
02100 {
02101 int name_len;
02102 struct spec_list *sl;
02103 struct spec_list *newsl;
02104
02105
02106 p1 += sizeof "%rename";
02107 while (*p1 == ' ' || *p1 == '\t')
02108 p1++;
02109
02110 if (! ISALPHA ((unsigned char) *p1))
02111 fatal ("specs %%rename syntax malformed after %ld characters",
02112 (long) (p1 - buffer));
02113
02114 p2 = p1;
02115 while (*p2 && !ISSPACE ((unsigned char) *p2))
02116 p2++;
02117
02118 if (*p2 != ' ' && *p2 != '\t')
02119 fatal ("specs %%rename syntax malformed after %ld characters",
02120 (long) (p2 - buffer));
02121
02122 name_len = p2 - p1;
02123 *p2++ = '\0';
02124 while (*p2 == ' ' || *p2 == '\t')
02125 p2++;
02126
02127 if (! ISALPHA ((unsigned char) *p2))
02128 fatal ("specs %%rename syntax malformed after %ld characters",
02129 (long) (p2 - buffer));
02130
02131
02132 p3 = p2;
02133 while (*p3 && !ISSPACE ((unsigned char) *p3))
02134 p3++;
02135
02136 if (p3 != p - 1)
02137 fatal ("specs %%rename syntax malformed after %ld characters",
02138 (long) (p3 - buffer));
02139 *p3 = '\0';
02140
02141 for (sl = specs; sl; sl = sl->next)
02142 if (name_len == sl->name_len && !strcmp (sl->name, p1))
02143 break;
02144
02145 if (!sl)
02146 fatal ("specs %s spec was not found to be renamed", p1);
02147
02148 if (strcmp (p1, p2) == 0)
02149 continue;
02150
02151 for (newsl = specs; newsl; newsl = newsl->next)
02152 if (strcmp (newsl->name, p2) == 0)
02153 fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'",
02154 filename, p1, p2);
02155
02156 if (verbose_flag)
02157 {
02158 notice ("rename spec %s to %s\n", p1, p2);
02159 #ifdef DEBUG_SPECS
02160 notice ("spec is '%s'\n\n", *(sl->ptr_spec));
02161 #endif
02162 }
02163
02164 set_spec (p2, *(sl->ptr_spec));
02165 if (sl->alloc_p)
02166 free ((void *) *(sl->ptr_spec));
02167
02168 *(sl->ptr_spec) = "";
02169 sl->alloc_p = 0;
02170 continue;
02171 }
02172 else
02173 fatal ("specs unknown %% command after %ld characters",
02174 (long) (p1 - buffer));
02175 }
02176
02177
02178 p1 = p;
02179 while (*p1 && *p1 != ':' && *p1 != '\n')
02180 p1++;
02181
02182
02183 if (*p1 != ':')
02184 fatal ("specs file malformed after %ld characters",
02185 (long) (p1 - buffer));
02186
02187
02188 p2 = p1;
02189 while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
02190 p2--;
02191
02192
02193 suffix = save_string (p, p2 - p);
02194
02195 p = skip_whitespace (p1 + 1);
02196 if (p[1] == 0)
02197 fatal ("specs file malformed after %ld characters",
02198 (long) (p - buffer));
02199
02200 p1 = p;
02201
02202 while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
02203 p1++;
02204
02205
02206 spec = save_string (p, p1 - p);
02207 p = p1;
02208
02209
02210 in = spec;
02211 out = spec;
02212 while (*in != 0)
02213 {
02214 if (in[0] == '\\' && in[1] == '\n')
02215 in += 2;
02216 else if (in[0] == '#')
02217 while (*in && *in != '\n')
02218 in++;
02219
02220 else
02221 *out++ = *in++;
02222 }
02223 *out = 0;
02224
02225 if (suffix[0] == '*')
02226 {
02227 if (! strcmp (suffix, "*link_command"))
02228 link_command_spec = spec;
02229 else
02230 set_spec (suffix + 1, spec);
02231 }
02232 else
02233 {
02234
02235 compilers
02236 = xrealloc (compilers,
02237 (n_compilers + 2) * sizeof (struct compiler));
02238
02239 compilers[n_compilers].suffix = suffix;
02240 compilers[n_compilers].spec = spec;
02241 n_compilers++;
02242 memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
02243 }
02244
02245 if (*suffix == 0)
02246 link_command_spec = spec;
02247 }
02248
02249 if (link_command_spec == 0)
02250 fatal ("spec file has no spec for linking");
02251 }
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267 static const char *temp_filename;
02268
02269
02270
02271 static int temp_filename_length;
02272
02273
02274
02275 struct temp_file
02276 {
02277 const char *name;
02278 struct temp_file *next;
02279 };
02280
02281
02282 static struct temp_file *always_delete_queue;
02283
02284 static struct temp_file *failure_delete_queue;
02285
02286
02287
02288
02289
02290
02291
02292 void
02293 record_temp_file (const char *filename, int always_delete, int fail_delete)
02294 {
02295 char *const name = xstrdup (filename);
02296
02297 if (always_delete)
02298 {
02299 struct temp_file *temp;
02300 for (temp = always_delete_queue; temp; temp = temp->next)
02301 if (! strcmp (name, temp->name))
02302 goto already1;
02303
02304 temp = XNEW (struct temp_file);
02305 temp->next = always_delete_queue;
02306 temp->name = name;
02307 always_delete_queue = temp;
02308
02309 already1:;
02310 }
02311
02312 if (fail_delete)
02313 {
02314 struct temp_file *temp;
02315 for (temp = failure_delete_queue; temp; temp = temp->next)
02316 if (! strcmp (name, temp->name))
02317 goto already2;
02318
02319 temp = XNEW (struct temp_file);
02320 temp->next = failure_delete_queue;
02321 temp->name = name;
02322 failure_delete_queue = temp;
02323
02324 already2:;
02325 }
02326 }
02327
02328
02329
02330 #ifndef DELETE_IF_ORDINARY
02331 #define DELETE_IF_ORDINARY(NAME,ST,VERBOSE_FLAG) \
02332 do \
02333 { \
02334 if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode)) \
02335 if (unlink (NAME) < 0) \
02336 if (VERBOSE_FLAG) \
02337 perror_with_name (NAME); \
02338 } while (0)
02339 #endif
02340
02341 static void
02342 delete_if_ordinary (const char *name)
02343 {
02344 struct stat st;
02345 #ifdef DEBUG
02346 int i, c;
02347
02348 printf ("Delete %s? (y or n) ", name);
02349 fflush (stdout);
02350 i = getchar ();
02351 if (i != '\n')
02352 while ((c = getchar ()) != '\n' && c != EOF)
02353 ;
02354
02355 if (i == 'y' || i == 'Y')
02356 #endif
02357 DELETE_IF_ORDINARY (name, st, verbose_flag);
02358 }
02359
02360 static void
02361 delete_temp_files (void)
02362 {
02363 struct temp_file *temp;
02364
02365 for (temp = always_delete_queue; temp; temp = temp->next)
02366 delete_if_ordinary (temp->name);
02367 always_delete_queue = 0;
02368 }
02369
02370
02371
02372 static void
02373 delete_failure_queue (void)
02374 {
02375 struct temp_file *temp;
02376
02377 for (temp = failure_delete_queue; temp; temp = temp->next)
02378 delete_if_ordinary (temp->name);
02379 }
02380
02381 static void
02382 clear_failure_queue (void)
02383 {
02384 failure_delete_queue = 0;
02385 }
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400 static void *
02401 for_each_path (const struct path_prefix *paths,
02402 bool do_multi,
02403 size_t extra_space,
02404 void *(*callback) (char *, void *),
02405 void *callback_info)
02406 {
02407 struct prefix_list *pl;
02408 const char *multi_dir = NULL;
02409 const char *multi_os_dir = NULL;
02410 const char *multi_suffix;
02411 const char *just_multi_suffix;
02412 char *path = NULL;
02413 void *ret = NULL;
02414 bool skip_multi_dir = false;
02415 bool skip_multi_os_dir = false;
02416
02417 multi_suffix = machine_suffix;
02418 just_multi_suffix = just_machine_suffix;
02419 if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
02420 {
02421 multi_dir = concat (multilib_dir, dir_separator_str, NULL);
02422 multi_suffix = concat (multi_suffix, multi_dir, NULL);
02423 just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
02424 }
02425 if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
02426 multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
02427
02428 while (1)
02429 {
02430 size_t multi_dir_len = 0;
02431 size_t multi_os_dir_len = 0;
02432 size_t suffix_len;
02433 size_t just_suffix_len;
02434 size_t len;
02435
02436 if (multi_dir)
02437 multi_dir_len = strlen (multi_dir);
02438 if (multi_os_dir)
02439 multi_os_dir_len = strlen (multi_os_dir);
02440 suffix_len = strlen (multi_suffix);
02441 just_suffix_len = strlen (just_multi_suffix);
02442
02443 if (path == NULL)
02444 {
02445 len = paths->max_len + extra_space + 1;
02446 if (suffix_len > multi_os_dir_len)
02447 len += suffix_len;
02448 else
02449 len += multi_os_dir_len;
02450 path = XNEWVEC (char, len);
02451 }
02452
02453 for (pl = paths->plist; pl != 0; pl = pl->next)
02454 {
02455 len = strlen (pl->prefix);
02456 memcpy (path, pl->prefix, len);
02457
02458
02459 if (!skip_multi_dir)
02460 {
02461 memcpy (path + len, multi_suffix, suffix_len + 1);
02462 ret = callback (path, callback_info);
02463 if (ret)
02464 break;
02465 }
02466
02467
02468
02469 if (!skip_multi_dir
02470 && pl->require_machine_suffix == 2)
02471 {
02472 memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
02473 ret = callback (path, callback_info);
02474 if (ret)
02475 break;
02476 }
02477
02478
02479 if (!pl->require_machine_suffix
02480 && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
02481 {
02482 const char *this_multi;
02483 size_t this_multi_len;
02484
02485 if (pl->os_multilib)
02486 {
02487 this_multi = multi_os_dir;
02488 this_multi_len = multi_os_dir_len;
02489 }
02490 else
02491 {
02492 this_multi = multi_dir;
02493 this_multi_len = multi_dir_len;
02494 }
02495
02496 if (this_multi_len)
02497 memcpy (path + len, this_multi, this_multi_len + 1);
02498 else
02499 path[len] = '\0';
02500
02501 ret = callback (path, callback_info);
02502 if (ret)
02503 break;
02504 }
02505 }
02506 if (pl)
02507 break;
02508
02509 if (multi_dir == NULL && multi_os_dir == NULL)
02510 break;
02511
02512
02513
02514 if (multi_dir)
02515 {
02516 free ((char *) multi_dir);
02517 multi_dir = NULL;
02518 free ((char *) multi_suffix);
02519 multi_suffix = machine_suffix;
02520 free ((char *) just_multi_suffix);
02521 just_multi_suffix = just_machine_suffix;
02522 }
02523 else
02524 skip_multi_dir = true;
02525 if (multi_os_dir)
02526 {
02527 free ((char *) multi_os_dir);
02528 multi_os_dir = NULL;
02529 }
02530 else
02531 skip_multi_os_dir = true;
02532 }
02533
02534 if (multi_dir)
02535 {
02536 free ((char *) multi_dir);
02537 free ((char *) multi_suffix);
02538 free ((char *) just_multi_suffix);
02539 }
02540 if (multi_os_dir)
02541 free ((char *) multi_os_dir);
02542 if (ret != path)
02543 free (path);
02544 return ret;
02545 }
02546
02547
02548
02549 struct add_to_obstack_info {
02550 struct obstack *ob;
02551 bool check_dir;
02552 bool first_time;
02553 };
02554
02555 static void *
02556 add_to_obstack (char *path, void *data)
02557 {
02558 struct add_to_obstack_info *info = data;
02559
02560 if (info->check_dir && !is_directory (path, false))
02561 return NULL;
02562
02563 if (!info->first_time)
02564 obstack_1grow (info->ob, PATH_SEPARATOR);
02565
02566 obstack_grow (info->ob, path, strlen (path));
02567
02568 info->first_time = false;
02569 return NULL;
02570 }
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580 static char *
02581 build_search_list (const struct path_prefix *paths, const char *prefix,
02582 bool check_dir, bool do_multi)
02583 {
02584 struct add_to_obstack_info info;
02585
02586 info.ob = &collect_obstack;
02587 info.check_dir = check_dir;
02588 info.first_time = true;
02589
02590 obstack_grow (&collect_obstack, prefix, strlen (prefix));
02591 obstack_1grow (&collect_obstack, '=');
02592
02593 for_each_path (paths, do_multi, 0, add_to_obstack, &info);
02594
02595 obstack_1grow (&collect_obstack, '\0');
02596 return XOBFINISH (&collect_obstack, char *);
02597 }
02598
02599
02600
02601
02602 static void
02603 putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
02604 bool do_multi)
02605 {
02606 putenv (build_search_list (paths, env_var, true, do_multi));
02607 }
02608
02609
02610
02611
02612 static int
02613 access_check (const char *name, int mode)
02614 {
02615 if (mode == X_OK)
02616 {
02617 struct stat st;
02618
02619 if (stat (name, &st) < 0
02620 || S_ISDIR (st.st_mode))
02621 return -1;
02622 }
02623
02624 return access (name, mode);
02625 }
02626
02627
02628
02629
02630
02631 struct file_at_path_info {
02632 const char *name;
02633 const char *suffix;
02634 int name_len;
02635 int suffix_len;
02636 int mode;
02637 };
02638
02639 static void *
02640 file_at_path (char *path, void *data)
02641 {
02642 struct file_at_path_info *info = data;
02643 size_t len = strlen (path);
02644
02645 memcpy (path + len, info->name, info->name_len);
02646 len += info->name_len;
02647
02648
02649
02650 if (info->suffix_len)
02651 {
02652 memcpy (path + len, info->suffix, info->suffix_len + 1);
02653 if (access_check (path, info->mode) == 0)
02654 return path;
02655 }
02656
02657 path[len] = '\0';
02658 if (access_check (path, info->mode) == 0)
02659 return path;
02660
02661 return NULL;
02662 }
02663
02664
02665
02666
02667
02668
02669 static char *
02670 find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
02671 bool do_multi)
02672 {
02673 struct file_at_path_info info;
02674
02675 #ifdef DEFAULT_ASSEMBLER
02676 if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
02677 return xstrdup (DEFAULT_ASSEMBLER);
02678 #endif
02679
02680 #ifdef DEFAULT_LINKER
02681 if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
02682 return xstrdup (DEFAULT_LINKER);
02683 #endif
02684
02685
02686
02687 if (IS_ABSOLUTE_PATH (name))
02688 {
02689 if (access (name, mode) == 0)
02690 return xstrdup (name);
02691
02692 return NULL;
02693 }
02694
02695 info.name = name;
02696 info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "";
02697 info.name_len = strlen (info.name);
02698 info.suffix_len = strlen (info.suffix);
02699 info.mode = mode;
02700
02701 return for_each_path (pprefix, do_multi, info.name_len + info.suffix_len,
02702 file_at_path, &info);
02703 }
02704
02705
02706
02707
02708 enum path_prefix_priority
02709 {
02710 PREFIX_PRIORITY_B_OPT,
02711 PREFIX_PRIORITY_LAST
02712 };
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728 static void
02729 add_prefix (struct path_prefix *pprefix, const char *prefix,
02730 const char *component, int priority,
02731 int require_machine_suffix, int os_multilib)
02732 {
02733 struct prefix_list *pl, **prev;
02734 int len;
02735
02736 for (prev = &pprefix->plist;
02737 (*prev) != NULL && (*prev)->priority <= priority;
02738 prev = &(*prev)->next)
02739 ;
02740
02741
02742
02743 prefix = update_path (prefix, component);
02744 len = strlen (prefix);
02745 if (len > pprefix->max_len)
02746 pprefix->max_len = len;
02747
02748 pl = XNEW (struct prefix_list);
02749 pl->prefix = prefix;
02750 pl->require_machine_suffix = require_machine_suffix;
02751 pl->priority = priority;
02752 pl->os_multilib = os_multilib;
02753
02754
02755 pl->next = (*prev);
02756 (*prev) = pl;
02757 }
02758
02759
02760 static void
02761 add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
02762 const char *component,
02763 int priority,
02764 int require_machine_suffix, int os_multilib)
02765 {
02766 if (!IS_ABSOLUTE_PATH (prefix))
02767 fatal ("system path '%s' is not absolute", prefix);
02768
02769 if (target_system_root)
02770 {
02771 if (target_sysroot_suffix)
02772 prefix = concat (target_sysroot_suffix, prefix, NULL);
02773 prefix = concat (target_system_root, prefix, NULL);
02774
02775
02776
02777 component = "GCC";
02778 }
02779
02780 add_prefix (pprefix, prefix, component, priority,
02781 require_machine_suffix, os_multilib);
02782 }
02783
02784
02785
02786
02787
02788
02789
02790 static int
02791 execute (void)
02792 {
02793 int i;
02794 int n_commands;
02795 char *string;
02796 struct pex_obj *pex;
02797 struct command
02798 {
02799 const char *prog;
02800 const char **argv;
02801 };
02802
02803 struct command *commands;
02804
02805 gcc_assert (!processing_spec_function);
02806
02807
02808 for (n_commands = 1, i = 0; i < argbuf_index; i++)
02809 if (strcmp (argbuf[i], "|") == 0)
02810 n_commands++;
02811
02812
02813 commands = alloca (n_commands * sizeof (struct command));
02814
02815
02816
02817
02818
02819 commands[0].prog = argbuf[0];
02820 commands[0].argv = &argbuf[0];
02821 string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
02822
02823 if (string)
02824 commands[0].argv[0] = string;
02825
02826 for (n_commands = 1, i = 0; i < argbuf_index; i++)
02827 if (strcmp (argbuf[i], "|") == 0)
02828 {
02829 #if defined (__MSDOS__) || defined (OS2) || defined (VMS)
02830 fatal ("-pipe not supported");
02831 #endif
02832 argbuf[i] = 0;
02833 commands[n_commands].prog = argbuf[i + 1];
02834 commands[n_commands].argv = &argbuf[i + 1];
02835 string = find_a_file (&exec_prefixes, commands[n_commands].prog,
02836 X_OK, false);
02837 if (string)
02838 commands[n_commands].argv[0] = string;
02839 n_commands++;
02840 }
02841
02842 argbuf[argbuf_index] = 0;
02843
02844
02845
02846 if (verbose_flag)
02847 {
02848
02849 if (print_help_list)
02850 fputc ('\n', stderr);
02851
02852
02853 for (i = 0; i < n_commands; i++)
02854 {
02855 const char *const *j;
02856
02857 if (verbose_only_flag)
02858 {
02859 for (j = commands[i].argv; *j; j++)
02860 {
02861 const char *p;
02862 fprintf (stderr, " \"");
02863 for (p = *j; *p; ++p)
02864 {
02865 if (*p == '"' || *p == '\\' || *p == '$')
02866 fputc ('\\', stderr);
02867 fputc (*p, stderr);
02868 }
02869 fputc ('"', stderr);
02870 }
02871 }
02872 else
02873 for (j = commands[i].argv; *j; j++)
02874 fprintf (stderr, " %s", *j);
02875
02876
02877 if (i + 1 != n_commands)
02878 fprintf (stderr, " |");
02879 fprintf (stderr, "\n");
02880 }
02881 fflush (stderr);
02882 if (verbose_only_flag != 0)
02883 {
02884
02885
02886
02887
02888 execution_count++;
02889 return 0;
02890 }
02891 #ifdef DEBUG
02892 notice ("\nGo ahead? (y or n) ");
02893 fflush (stderr);
02894 i = getchar ();
02895 if (i != '\n')
02896 while (getchar () != '\n')
02897 ;
02898
02899 if (i != 'y' && i != 'Y')
02900 return 0;
02901 #endif
02902 }
02903
02904 #ifdef ENABLE_VALGRIND_CHECKING
02905
02906
02907
02908
02909 for (i = 0; i < n_commands; i++)
02910 {
02911 const char **argv;
02912 int argc;
02913 int j;
02914
02915 for (argc = 0; commands[i].argv[argc] != NULL; argc++)
02916 ;
02917
02918 argv = alloca ((argc + 3) * sizeof (char *));
02919
02920 argv[0] = VALGRIND_PATH;
02921 argv[1] = "-q";
02922 for (j = 2; j < argc + 2; j++)
02923 argv[j] = commands[i].argv[j - 2];
02924 argv[j] = NULL;
02925
02926 commands[i].argv = argv;
02927 commands[i].prog = argv[0];
02928 }
02929 #endif
02930
02931
02932
02933 pex = pex_init (PEX_USE_PIPES | (report_times ? PEX_RECORD_TIMES : 0),
02934 programname, temp_filename);
02935 if (pex == NULL)
02936 pfatal_with_name (_("pex_init failed"));
02937
02938 for (i = 0; i < n_commands; i++)
02939 {
02940 const char *errmsg;
02941 int err;
02942 const char *string = commands[i].argv[0];
02943
02944 errmsg = pex_run (pex,
02945 ((i + 1 == n_commands ? PEX_LAST : 0)
02946 | (string == commands[i].prog ? PEX_SEARCH : 0)),
02947 string, (char * const *) commands[i].argv,
02948 NULL, NULL, &err);
02949 if (errmsg != NULL)
02950 {
02951 if (err == 0)
02952 fatal (errmsg);
02953 else
02954 {
02955 errno = err;
02956 pfatal_with_name (errmsg);
02957 }
02958 }
02959
02960 if (string != commands[i].prog)
02961 free ((void *) string);
02962 }
02963
02964 execution_count++;
02965
02966
02967
02968 {
02969 int *statuses;
02970 struct pex_time *times = NULL;
02971 int ret_code = 0;
02972
02973 statuses = alloca (n_commands * sizeof (int));
02974 if (!pex_get_status (pex, n_commands, statuses))
02975 pfatal_with_name (_("failed to get exit status"));
02976
02977 if (report_times)
02978 {
02979 times = alloca (n_commands * sizeof (struct pex_time));
02980 if (!pex_get_times (pex, n_commands, times))
02981 pfatal_with_name (_("failed to get process times"));
02982 }
02983
02984 pex_free (pex);
02985
02986 for (i = 0; i < n_commands; ++i)
02987 {
02988 int status = statuses[i];
02989
02990 if (WIFSIGNALED (status))
02991 {
02992 #ifdef SIGPIPE
02993
02994
02995
02996
02997
02998
02999 if (WTERMSIG (status) == SIGPIPE
03000 && (signal_count || greatest_status >= MIN_FATAL_STATUS))
03001 {
03002 signal_count++;
03003 ret_code = -1;
03004 }
03005 else
03006 #endif
03007 fatal_ice ("\
03008 Internal error: %s (program %s)\n\
03009 Please submit a full bug report.\n\
03010 See %s for instructions.",
03011 strsignal (WTERMSIG (status)), commands[i].prog,
03012 bug_report_url);
03013 }
03014 else if (WIFEXITED (status)
03015 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
03016 {
03017 if (WEXITSTATUS (status) > greatest_status)
03018 greatest_status = WEXITSTATUS (status);
03019 ret_code = -1;
03020 }
03021
03022 if (report_times)
03023 {
03024 struct pex_time *pt = ×[i];
03025 double ut, st;
03026
03027 ut = ((double) pt->user_seconds
03028 + (double) pt->user_microseconds / 1.0e6);
03029 st = ((double) pt->system_seconds
03030 + (double) pt->system_microseconds / 1.0e6);
03031
03032 if (ut + st != 0)
03033 notice ("# %s %.2f %.2f\n", commands[i].prog, ut, st);
03034 }
03035 }
03036
03037 return ret_code;
03038 }
03039 }
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055 #define SWITCH_OK 0
03056 #define SWITCH_FALSE -1
03057 #define SWITCH_IGNORE -2
03058 #define SWITCH_LIVE 1
03059
03060 struct switchstr
03061 {
03062 const char *part1;
03063 const char **args;
03064 int live_cond;
03065 unsigned char validated;
03066 unsigned char ordering;
03067 };
03068
03069 static struct switchstr *switches;
03070
03071 static int n_switches;
03072
03073
03074
03075
03076
03077
03078
03079
03080 struct infile
03081 {
03082 const char *name;
03083 const char *language;
03084 struct compiler *incompiler;
03085 bool compiled;
03086 bool preprocessed;
03087 };
03088
03089
03090
03091 static struct infile *infiles;
03092
03093 int n_infiles;
03094
03095
03096
03097
03098 static bool combine_inputs;
03099
03100
03101
03102
03103 static int added_libraries;
03104
03105
03106
03107 const char **outfiles;
03108
03109 #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
03110
03111
03112
03113
03114
03115 static const char *
03116 convert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
03117 int do_obj ATTRIBUTE_UNUSED)
03118 {
03119 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
03120 int i;
03121 #endif
03122 int len;
03123
03124 if (name == NULL)
03125 return NULL;
03126
03127 len = strlen (name);
03128
03129 #ifdef HAVE_TARGET_OBJECT_SUFFIX
03130
03131 if (do_obj && len > 2
03132 && name[len - 2] == '.'
03133 && name[len - 1] == 'o')
03134 {
03135 obstack_grow (&obstack, name, len - 2);
03136 obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
03137 name = XOBFINISH (&obstack, const char *);
03138 }
03139 #endif
03140
03141 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
03142
03143
03144 if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
03145 return name;
03146
03147 for (i = len - 1; i >= 0; i--)
03148 if (IS_DIR_SEPARATOR (name[i]))
03149 break;
03150
03151 for (i++; i < len; i++)
03152 if (name[i] == '.')
03153 return name;
03154
03155 obstack_grow (&obstack, name, len);
03156 obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
03157 strlen (TARGET_EXECUTABLE_SUFFIX));
03158 name = XOBFINISH (&obstack, const char *);
03159 #endif
03160
03161 return name;
03162 }
03163 #endif
03164
03165
03166 static void
03167 display_help (void)
03168 {
03169 printf (_("Usage: %s [options] file...\n"), programname);
03170 fputs (_("Options:\n"), stdout);
03171
03172 fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout);
03173 fputs (_(" --help Display this information\n"), stdout);
03174 fputs (_(" --target-help Display target specific command line options\n"), stdout);
03175 if (! verbose_flag)
03176 fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
03177 fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout);
03178 fputs (_(" -dumpversion Display the version of the compiler\n"), stdout);
03179 fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout);
03180 fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout);
03181 fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout);
03182 fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout);
03183 fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout);
03184 fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout);
03185 fputs (_("\
03186 -print-multi-lib Display the mapping between command line options and\n\
03187 multiple library search directories\n"), stdout);
03188 fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
03189 fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout);
03190 fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout);
03191 fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout);
03192 fputs (_(" -Xassembler <arg> Pass <arg> on to the assembler\n"), stdout);
03193 fputs (_(" -Xpreprocessor <arg> Pass <arg> on to the preprocessor\n"), stdout);
03194 fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout);
03195 fputs (_(" -combine Pass multiple source files to compiler at once\n"), stdout);
03196 fputs (_(" -save-temps Do not delete intermediate files\n"), stdout);
03197 fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout);
03198 fputs (_(" -time Time the execution of each subprocess\n"), stdout);
03199 fputs (_(" -specs=<file> Override built-in specs with the contents of <file>\n"), stdout);
03200 fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout);
03201 fputs (_("\
03202 --sysroot=<directory> Use <directory> as the root directory for headers\n\
03203 and libraries\n"), stdout);
03204 fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout);
03205 fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout);
03206 fputs (_(" -V <version> Run gcc version number <version>, if installed\n"), stdout);
03207 fputs (_(" -v Display the programs invoked by the compiler\n"), stdout);
03208 fputs (_(" -### Like -v but options quoted and commands not executed\n"), stdout);
03209 fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout);
03210 fputs (_(" -S Compile only; do not assemble or link\n"), stdout);
03211 fputs (_(" -c Compile and assemble, but do not link\n"), stdout);
03212 fputs (_(" -o <file> Place the output into <file>\n"), stdout);
03213 #ifdef KEY
03214 fputs (_(" -spinfile <file> Place the SPIN IR into <file> and exit\n"), stdout);
03215 #endif
03216 fputs (_("\
03217 -x <language> Specify the language of the following input files\n\
03218 Permissible languages include: c c++ assembler none\n\
03219 'none' means revert to the default behavior of\n\
03220 guessing the language based on the file's extension\n\
03221 "), stdout);
03222
03223 printf (_("\
03224 \nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
03225 passed on to the various sub-processes invoked by %s. In order to pass\n\
03226 other options on to these processes the -W<letter> options must be used.\n\
03227 "), programname);
03228
03229
03230
03231 }
03232
03233 static void
03234 add_preprocessor_option (const char *option, int len)
03235 {
03236 n_preprocessor_options++;
03237
03238 if (! preprocessor_options)
03239 preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
03240 else
03241 preprocessor_options = xrealloc (preprocessor_options,
03242 n_preprocessor_options * sizeof (char *));
03243
03244 preprocessor_options [n_preprocessor_options - 1] =
03245 save_string (option, len);
03246 }
03247
03248 static void
03249 add_assembler_option (const char *option, int len)
03250 {
03251 n_assembler_options++;
03252
03253 if (! assembler_options)
03254 assembler_options = XNEWVEC (char *, n_assembler_options);
03255 else
03256 assembler_options = xrealloc (assembler_options,
03257 n_assembler_options * sizeof (char *));
03258
03259 assembler_options [n_assembler_options - 1] = save_string (option, len);
03260 }
03261
03262 static void
03263 add_linker_option (const char *option, int len)
03264 {
03265 n_linker_options++;
03266
03267 if (! linker_options)
03268 linker_options = XNEWVEC (char *, n_linker_options);
03269 else
03270 linker_options = xrealloc (linker_options,
03271 n_linker_options * sizeof (char *));
03272
03273 linker_options [n_linker_options - 1] = save_string (option, len);
03274 }
03275
03276
03277
03278
03279 static void
03280 process_command (int argc, const char **argv)
03281 {
03282 int i;
03283 const char *temp;
03284 char *temp1;
03285 const char *spec_lang = 0;
03286 int last_language_n_infiles;
03287 int lang_n_infiles = 0;
03288 #ifdef MODIFY_TARGET_NAME
03289 int is_modify_target_name;
03290 unsigned int j;
03291 #endif
03292
03293 GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
03294
03295 n_switches = 0;
03296 n_infiles = 0;
03297 added_libraries = 0;
03298
03299
03300
03301 compiler_version = temp1 = xstrdup (version_string);
03302
03303 for (; *temp1; ++temp1)
03304 {
03305 if (*temp1 == ' ')
03306 {
03307 *temp1 = '\0';
03308 break;
03309 }
03310 }
03311
03312
03313
03314
03315
03316 if (argc > 1 && argv[1][0] == '-'
03317 && (argv[1][1] == 'V' ||
03318 ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
03319 {
03320 const char *new_version = DEFAULT_TARGET_VERSION;
03321 const char *new_machine = DEFAULT_TARGET_MACHINE;
03322 const char *progname = argv[0];
03323 char **new_argv;
03324 char *new_argv0;
03325 int baselen;
03326
03327 while (argc > 1 && argv[1][0] == '-'
03328 && (argv[1][1] == 'V' ||
03329 ((argv[1][1] == 'b') && ( NULL != strchr(argv[1] + 2,'-')))))
03330 {
03331 char opt = argv[1][1];
03332 const char *arg;
03333 if (argv[1][2] != '\0')
03334 {
03335 arg = argv[1] + 2;
03336 argc -= 1;
03337 argv += 1;
03338 }
03339 else if (argc > 2)
03340 {
03341 arg = argv[2];
03342 argc -= 2;
03343 argv += 2;
03344 }
03345 else
03346 fatal ("'-%c' option must have argument", opt);
03347 if (opt == 'V')
03348 new_version = arg;
03349 else
03350 new_machine = arg;
03351 }
03352
03353 for (baselen = strlen (progname); baselen > 0; baselen--)
03354 if (IS_DIR_SEPARATOR (progname[baselen-1]))
03355 break;
03356 new_argv0 = xmemdup (progname, baselen,
03357 baselen + concat_length (new_version, new_machine,
03358 "-gcc-", NULL) + 1);
03359 strcpy (new_argv0 + baselen, new_machine);
03360 strcat (new_argv0, "-gcc-");
03361 strcat (new_argv0, new_version);
03362
03363 new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
03364 (argc + 1) * sizeof (argv[0]));
03365 new_argv[0] = new_argv0;
03366
03367 execvp (new_argv0, new_argv);
03368 fatal ("couldn't run '%s': %s", new_argv0, xstrerror (errno));
03369 }
03370
03371
03372
03373
03374 gcc_libexec_prefix = standard_libexec_prefix;
03375 #ifndef VMS
03376
03377 if (!gcc_exec_prefix)
03378 {
03379 gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
03380 standard_exec_prefix);
03381 gcc_libexec_prefix = make_relative_prefix (argv[0],
03382 standard_bindir_prefix,
03383 standard_libexec_prefix);
03384 if (gcc_exec_prefix)
03385 putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
03386 }
03387 else
03388 {
03389
03390
03391
03392
03393 char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL);
03394 gcc_libexec_prefix = make_relative_prefix (tmp_prefix,
03395 standard_exec_prefix,
03396 standard_libexec_prefix);
03397 free (tmp_prefix);
03398 }
03399 #else
03400 #endif
03401
03402 if (gcc_exec_prefix)
03403 {
03404 int len = strlen (gcc_exec_prefix);
03405
03406 if (len > (int) sizeof ("/lib/gcc/") - 1
03407 && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
03408 {
03409 temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
03410 if (IS_DIR_SEPARATOR (*temp)
03411 && strncmp (temp + 1, "lib", 3) == 0
03412 && IS_DIR_SEPARATOR (temp[4])
03413 && strncmp (temp + 5, "gcc", 3) == 0)
03414 len -= sizeof ("/lib/gcc/") - 1;
03415 }
03416
03417 set_std_prefix (gcc_exec_prefix, len);
03418 add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
03419 PREFIX_PRIORITY_LAST, 0, 0);
03420 add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
03421 PREFIX_PRIORITY_LAST, 0, 0);
03422 }
03423
03424
03425
03426
03427 GET_ENVIRONMENT (temp, "COMPILER_PATH");
03428 if (temp)
03429 {
03430 const char *startp, *endp;
03431 char *nstore = alloca (strlen (temp) + 3);
03432
03433 startp = endp = temp;
03434 while (1)
03435 {
03436 if (*endp == PATH_SEPARATOR || *endp == 0)
03437 {
03438 strncpy (nstore, startp, endp - startp);
03439 if (endp == startp)
03440 strcpy (nstore, concat (".", dir_separator_str, NULL));
03441 else if (!IS_DIR_SEPARATOR (endp[-1]))
03442 {
03443 nstore[endp - startp] = DIR_SEPARATOR;
03444 nstore[endp - startp + 1] = 0;
03445 }
03446 else
03447 nstore[endp - startp] = 0;
03448 add_prefix (&exec_prefixes, nstore, 0,
03449 PREFIX_PRIORITY_LAST, 0, 0);
03450 add_prefix (&include_prefixes, nstore, 0,
03451 PREFIX_PRIORITY_LAST, 0, 0);
03452 if (*endp == 0)
03453 break;
03454 endp = startp = endp + 1;
03455 }
03456 else
03457 endp++;
03458 }
03459 }
03460
03461 GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV);
03462 if (temp && *cross_compile == '0')
03463 {
03464 const char *startp, *endp;
03465 char *nstore = alloca (strlen (temp) + 3);
03466
03467 startp = endp = temp;
03468 while (1)
03469 {
03470 if (*endp == PATH_SEPARATOR || *endp == 0)
03471 {
03472 strncpy (nstore, startp, endp - startp);
03473 if (endp == startp)
03474 strcpy (nstore, concat (".", dir_separator_str, NULL));
03475 else if (!IS_DIR_SEPARATOR (endp[-1]))
03476 {
03477 nstore[endp - startp] = DIR_SEPARATOR;
03478 nstore[endp - startp + 1] = 0;
03479 }
03480 else
03481 nstore[endp - startp] = 0;
03482 add_prefix (&startfile_prefixes, nstore, NULL,
03483 PREFIX_PRIORITY_LAST, 0, 1);
03484 if (*endp == 0)
03485 break;
03486 endp = startp = endp + 1;
03487 }
03488 else
03489 endp++;
03490 }
03491 }
03492
03493
03494 GET_ENVIRONMENT (temp, "LPATH");
03495 if (temp && *cross_compile == '0')
03496 {
03497 const char *startp, *endp;
03498 char *nstore = alloca (strlen (temp) + 3);
03499
03500 startp = endp = temp;
03501 while (1)
03502 {
03503 if (*endp == PATH_SEPARATOR || *endp == 0)
03504 {
03505 strncpy (nstore, startp, endp - startp);
03506 if (endp == startp)
03507 strcpy (nstore, concat (".", dir_separator_str, NULL));
03508 else if (!IS_DIR_SEPARATOR (endp[-1]))
03509 {
03510 nstore[endp - startp] = DIR_SEPARATOR;
03511 nstore[endp - startp + 1] = 0;
03512 }
03513 else
03514 nstore[endp - startp] = 0;
03515 add_prefix (&startfile_prefixes, nstore, NULL,
03516 PREFIX_PRIORITY_LAST, 0, 1);
03517 if (*endp == 0)
03518 break;
03519 endp = startp = endp + 1;
03520 }
03521 else
03522 endp++;
03523 }
03524 }
03525
03526
03527 translate_options (&argc, (const char *const **) &argv);
03528
03529
03530 lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
03531
03532
03533
03534
03535
03536 for (i = 1; i < argc; i++)
03537 {
03538 if (! strcmp (argv[i], "-dumpspecs"))
03539 {
03540 struct spec_list *sl;
03541 init_spec ();
03542 for (sl = specs; sl; sl = sl->next)
03543 printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
03544 if (link_command_spec)
03545 printf ("*link_command:\n%s\n\n", link_command_spec);
03546 exit (0);
03547 }
03548 else if (! strcmp (argv[i], "-dumpversion"))
03549 {
03550 printf ("%s\n", spec_version);
03551 exit (0);
03552 }
03553 else if (! strcmp (argv[i], "-dumpmachine"))
03554 {
03555 printf ("%s\n", spec_machine);
03556 exit (0);
03557 }
03558 else if (strcmp (argv[i], "-fversion") == 0)
03559 {
03560
03561 printf (_("%s (GCC) %s\n"), programname, version_string);
03562 printf ("Copyright %s 2007 Free Software Foundation, Inc.\n",
03563 _("(C)"));
03564 fputs (_("This is free software; see the source for copying conditions. There is NO\n\
03565 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
03566 stdout);
03567 exit (0);
03568 }
03569 else if (strcmp (argv[i], "-fhelp") == 0)
03570 {
03571
03572 print_help_list = 1;
03573
03574
03575 n_infiles++;
03576 n_switches++;
03577
03578
03579 if (is_cpp_driver)
03580 add_preprocessor_option ("--help", 6);
03581 add_assembler_option ("--help", 6);
03582 add_linker_option ("--help", 6);
03583 }
03584 else if (strcmp (argv[i], "-ftarget-help") == 0)
03585 {
03586
03587 target_help_flag = 1;
03588
03589
03590 n_infiles++;
03591 n_switches++;
03592
03593
03594 if (is_cpp_driver)
03595 add_preprocessor_option ("--target-help", 13);
03596 add_assembler_option ("--target-help", 13);
03597 add_linker_option ("--target-help", 13);
03598 }
03599 else if (! strcmp (argv[i], "-pass-exit-codes"))
03600 {
03601 pass_exit_codes = 1;
03602 n_switches++;
03603 }
03604 else if (! strcmp (argv[i], "-print-search-dirs"))
03605 print_search_dirs = 1;
03606 else if (! strcmp (argv[i], "-print-libgcc-file-name"))
03607 print_file_name = "libgcc.a";
03608 else if (! strncmp (argv[i], "-print-file-name=", 17))
03609 print_file_name = argv[i] + 17;
03610 else if (! strncmp (argv[i], "-print-prog-name=", 17))
03611 print_prog_name = argv[i] + 17;
03612 else if (! strcmp (argv[i], "-print-multi-lib"))
03613 print_multi_lib = 1;
03614 else if (! strcmp (argv[i], "-print-multi-directory"))
03615 print_multi_directory = 1;
03616 else if (! strcmp (argv[i], "-print-multi-os-directory"))
03617 print_multi_os_directory = 1;
03618 else if (! strncmp (argv[i], "-Wa,", 4))
03619 {
03620 int prev, j;
03621
03622
03623
03624 prev = 4;
03625 for (j = 4; argv[i][j]; j++)
03626 if (argv[i][j] == ',')
03627 {
03628 add_assembler_option (argv[i] + prev, j - prev);
03629 prev = j + 1;
03630 }
03631
03632
03633 add_assembler_option (argv[i] + prev, j - prev);
03634 }
03635 else if (! strncmp (argv[i], "-Wp,", 4))
03636 {
03637 int prev, j;
03638
03639
03640
03641 prev = 4;
03642 for (j = 4; argv[i][j]; j++)
03643 if (argv[i][j] == ',')
03644 {
03645 add_preprocessor_option (argv[i] + prev, j - prev);
03646 prev = j + 1;
03647 }
03648
03649
03650 add_preprocessor_option (argv[i] + prev, j - prev);
03651 }
03652 else if (argv[i][0] == '+' && argv[i][1] == 'e')
03653
03654 n_switches++;
03655 else if (strncmp (argv[i], "-Wl,", 4) == 0)
03656 {
03657 int j;
03658
03659 for (j = 3; argv[i][j]; j++)
03660 n_infiles += (argv[i][j] == ',');
03661 }
03662 else if (strcmp (argv[i], "-Xlinker") == 0)
03663 {
03664 if (i + 1 == argc)
03665 fatal ("argument to '-Xlinker' is missing");
03666
03667 n_infiles++;
03668 i++;
03669 }
03670 else if (strcmp (argv[i], "-Xpreprocessor") == 0)
03671 {
03672 if (i + 1 == argc)
03673 fatal ("argument to '-Xpreprocessor' is missing");
03674
03675 add_preprocessor_option (argv[i+1], strlen (argv[i+1]));
03676 }
03677 else if (strcmp (argv[i], "-Xassembler") == 0)
03678 {
03679 if (i + 1 == argc)
03680 fatal ("argument to '-Xassembler' is missing");
03681
03682 add_assembler_option (argv[i+1], strlen (argv[i+1]));
03683 }
03684 else if (strcmp (argv[i], "-l") == 0)
03685 {
03686 if (i + 1 == argc)
03687 fatal ("argument to '-l' is missing");
03688
03689 n_infiles++;
03690 i++;
03691 }
03692 else if (strncmp (argv[i], "-l", 2) == 0)
03693 n_infiles++;
03694 else if (strcmp (argv[i], "-save-temps") == 0)
03695 {
03696 save_temps_flag = 1;
03697 n_switches++;
03698 }
03699 else if (strcmp (argv[i], "-combine") == 0)
03700 {
03701 combine_flag = 1;
03702 n_switches++;
03703 }
03704 else if (strcmp (argv[i], "-specs") == 0)
03705 {
03706 struct user_specs *user = XNEW (struct user_specs);
03707 if (++i >= argc)
03708 fatal ("argument to '-specs' is missing");
03709
03710 user->next = (struct user_specs *) 0;
03711 user->filename = argv[i];
03712 if (user_specs_tail)
03713 user_specs_tail->next = user;
03714 else
03715 user_specs_head = user;
03716 user_specs_tail = user;
03717 }
03718 else if (strncmp (argv[i], "-specs=", 7) == 0)
03719 {
03720 struct user_specs *user = XNEW (struct user_specs);
03721 if (strlen (argv[i]) == 7)
03722 fatal ("argument to '-specs=' is missing");
03723
03724 user->next = (struct user_specs *) 0;
03725 user->filename = argv[i] + 7;
03726 if (user_specs_tail)
03727 user_specs_tail->next = user;
03728 else
03729 user_specs_head = user;
03730 user_specs_tail = user;
03731 }
03732 #ifdef KEY
03733 else if (strcmp (argv[i], "-spinfile") == 0)
03734 flag_spin_file = 1;
03735 #endif
03736 else if (strcmp (argv[i], "-time") == 0)
03737 report_times = 1;
03738 else if (strcmp (argv[i], "-pipe") == 0)
03739 {
03740
03741
03742 use_pipes = 1;
03743 n_switches++;
03744 }
03745 else if (strcmp (argv[i], "-###") == 0)
03746 {
03747
03748
03749
03750
03751 verbose_only_flag++;
03752 verbose_flag++;
03753 }
03754 else if (argv[i][0] == '-' && argv[i][1] != 0)
03755 {
03756 const char *p = &argv[i][1];
03757 int c = *p;
03758
03759 switch (c)
03760 {
03761 case 'b':
03762 if (NULL == strchr(argv[i] + 2, '-'))
03763 goto normal_switch;
03764
03765
03766 case 'V':
03767 fatal ("'-%c' must come at the start of the command line", c);
03768 break;
03769
03770 case 'B':
03771 {
03772 const char *value;
03773 int len;
03774
03775 if (p[1] == 0 && i + 1 == argc)
03776 fatal ("argument to '-B' is missing");
03777 if (p[1] == 0)
03778 value = argv[++i];
03779 else
03780 value = p + 1;
03781
03782 len = strlen (value);
03783
03784
03785
03786
03787
03788
03789
03790
03791 if (! IS_DIR_SEPARATOR (value [len - 1])
03792 && is_directory (value, false))
03793 {
03794 char *tmp = XNEWVEC (char, len + 2);
03795 strcpy (tmp, value);
03796 tmp[len] = DIR_SEPARATOR;
03797 tmp[++ len] = 0;
03798 value = tmp;
03799 }
03800
03801
03802
03803 if ((len == 7
03804 || (len > 7
03805 && (IS_DIR_SEPARATOR (value[len - 8]))))
03806 && strncmp (value + len - 7, "stage", 5) == 0
03807 && ISDIGIT (value[len - 2])
03808 && (IS_DIR_SEPARATOR (value[len - 1])))
03809 {
03810 if (len == 7)
03811 add_prefix (&include_prefixes, "./", NULL,
03812 PREFIX_PRIORITY_B_OPT, 0, 0);
03813 else
03814 {
03815 char *string = xmalloc (len - 6);
03816 memcpy (string, value, len - 7);
03817 string[len - 7] = 0;
03818 add_prefix (&include_prefixes, string, NULL,
03819 PREFIX_PRIORITY_B_OPT, 0, 0);
03820 }
03821 }
03822
03823 add_prefix (&exec_prefixes, value, NULL,
03824 PREFIX_PRIORITY_B_OPT, 0, 0);
03825 add_prefix (&startfile_prefixes, value, NULL,
03826 PREFIX_PRIORITY_B_OPT, 0, 0);
03827 add_prefix (&include_prefixes, value, NULL,
03828 PREFIX_PRIORITY_B_OPT, 0, 0);
03829 n_switches++;
03830 }
03831 break;
03832
03833 case 'v':
03834 n_switches++;
03835
03836
03837 if (p[1] != 0)
03838 break;
03839 verbose_flag++;
03840 break;
03841
03842 case 'S':
03843 case 'c':
03844 if (p[1] == 0)
03845 {
03846 have_c = 1;
03847 n_switches++;
03848 break;
03849 }
03850 goto normal_switch;
03851
03852 case 'o':
03853 have_o = 1;
03854 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
03855 if (! have_c)
03856 {
03857 int skip;
03858
03859
03860
03861 int j = i + 1;
03862 if (p[1] == 0)
03863 ++j;
03864 while (j < argc)
03865 {
03866 if (argv[j][0] == '-')
03867 {
03868 if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
03869 && argv[j][2] == 0)
03870 {
03871 have_c = 1;
03872 break;
03873 }
03874 else if ((skip = SWITCH_TAKES_ARG (argv[j][1])))
03875 j += skip - (argv[j][2] != 0);
03876 else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1)))
03877 j += skip;
03878 }
03879 j++;
03880 }
03881 }
03882 #endif
03883 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
03884 if (p[1] == 0)
03885 argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
03886 else
03887 argv[i] = convert_filename (argv[i], ! have_c, 0);
03888 #endif
03889 goto normal_switch;
03890
03891 default:
03892 normal_switch:
03893
03894 #ifdef MODIFY_TARGET_NAME
03895 is_modify_target_name = 0;
03896
03897 for (j = 0; j < ARRAY_SIZE (modify_target); j++)
03898 if (! strcmp (argv[i], modify_target[j].sw))
03899 {
03900 char *new_name = xmalloc (strlen (modify_target[j].str)
03901 + strlen (spec_machine));
03902 const char *p, *r;
03903 char *q;
03904 int made_addition = 0;
03905
03906 is_modify_target_name = 1;
03907 for (p = spec_machine, q = new_name; *p != 0; )
03908 {
03909 if (modify_target[j].add_del == DELETE
03910 && (! strncmp (q, modify_target[j].str,
03911 strlen (modify_target[j].str))))
03912 p += strlen (modify_target[j].str);
03913 else if (modify_target[j].add_del == ADD
03914 && ! made_addition && *p == '-')
03915 {
03916 for (r = modify_target[j].str; *r != 0; )
03917 *q++ = *r++;
03918 made_addition = 1;
03919 }
03920
03921 *q++ = *p++;
03922 }
03923
03924 spec_machine = new_name;
03925 }
03926
03927 if (is_modify_target_name)
03928 break;
03929 #endif
03930
03931 n_switches++;
03932
03933 if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
03934 i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
03935 else if (WORD_SWITCH_TAKES_ARG (p))
03936 i += WORD_SWITCH_TAKES_ARG (p);
03937 }
03938 }
03939 else
03940 {
03941 n_infiles++;
03942 lang_n_infiles++;
03943 }
03944 }
03945
03946 if (save_temps_flag && use_pipes)
03947 {
03948
03949 if (save_temps_flag)
03950 error ("warning: -pipe ignored because -save-temps specified");
03951 use_pipes = 0;
03952 }
03953
03954
03955
03956
03957
03958
03959
03960 #ifndef OS2
03961 add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
03962 PREFIX_PRIORITY_LAST, 1, 0);
03963 add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
03964 PREFIX_PRIORITY_LAST, 2, 0);
03965 add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
03966 PREFIX_PRIORITY_LAST, 2, 0);
03967 add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
03968 PREFIX_PRIORITY_LAST, 2, 0);
03969 add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
03970 PREFIX_PRIORITY_LAST, 2, 0);
03971 #endif
03972
03973 add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
03974 PREFIX_PRIORITY_LAST, 1, 0);
03975 add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
03976 PREFIX_PRIORITY_LAST, 1, 0);
03977
03978 tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
03979 dir_separator_str, NULL);
03980
03981
03982
03983
03984
03985
03986
03987
03988 if (!IS_ABSOLUTE_PATH (tooldir_prefix))
03989 {
03990 if (gcc_exec_prefix)
03991 {
03992 char *gcc_exec_tooldir_prefix
03993 = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
03994 spec_version, dir_separator_str, tooldir_prefix, NULL);
03995
03996 add_prefix (&exec_prefixes,
03997 concat (gcc_exec_tooldir_prefix, "bin",
03998 dir_separator_str, NULL),
03999 NULL, PREFIX_PRIORITY_LAST, 0, 0);
04000 add_prefix (&startfile_prefixes,
04001 concat (gcc_exec_tooldir_prefix, "lib",
04002 dir_separator_str, NULL),
04003 NULL, PREFIX_PRIORITY_LAST, 0, 1);
04004 }
04005
04006 tooldir_prefix = concat (standard_exec_prefix, spec_machine,
04007 dir_separator_str, spec_version,
04008 dir_separator_str, tooldir_prefix, NULL);
04009 }
04010
04011 add_prefix (&exec_prefixes,
04012 concat (tooldir_prefix, "bin", dir_separator_str, NULL),
04013 "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0);
04014 add_prefix (&startfile_prefixes,
04015 concat (tooldir_prefix, "lib", dir_separator_str, NULL),
04016 "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
04017
04018 #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
04019
04020
04021
04022
04023 if (target_system_root && gcc_exec_prefix)
04024 {
04025 char *tmp_prefix = make_relative_prefix (argv[0],
04026 standard_bindir_prefix,
04027 target_system_root);
04028 if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
04029 {
04030 target_system_root = tmp_prefix;
04031 target_system_root_changed = 1;
04032 }
04033 }
04034 #endif
04035
04036
04037
04038
04039
04040
04041 switches = XNEWVEC (struct switchstr, n_switches + 1);
04042 infiles = XNEWVEC (struct infile, n_infiles + 1);
04043 n_switches = 0;
04044 n_infiles = 0;
04045 last_language_n_infiles = -1;
04046
04047
04048
04049
04050
04051 for (i = 1; i < argc; i++)
04052 {
04053
04054 #ifdef MODIFY_TARGET_NAME
04055 is_modify_target_name = 0;
04056
04057 for (j = 0; j < ARRAY_SIZE (modify_target); j++)
04058 if (! strcmp (argv[i], modify_target[j].sw))
04059 is_modify_target_name = 1;
04060
04061 if (is_modify_target_name)
04062 ;
04063 else
04064 #endif
04065 if (! strncmp (argv[i], "-Wa,", 4))
04066 ;
04067 else if (! strncmp (argv[i], "-Wp,", 4))
04068 ;
04069 else if (! strcmp (argv[i], "-pass-exit-codes"))
04070 ;
04071 else if (! strcmp (argv[i], "-print-search-dirs"))
04072 ;
04073 else if (! strcmp (argv[i], "-print-libgcc-file-name"))
04074 ;
04075 else if (! strncmp (argv[i], "-print-file-name=", 17))
04076 ;
04077 else if (! strncmp (argv[i], "-print-prog-name=", 17))
04078 ;
04079 else if (! strcmp (argv[i], "-print-multi-lib"))
04080 ;
04081 else if (! strcmp (argv[i], "-print-multi-directory"))
04082 ;
04083 else if (! strcmp (argv[i], "-print-multi-os-directory"))
04084 ;
04085 else if (! strcmp (argv[i], "-ftarget-help"))
04086 ;
04087 else if (! strcmp (argv[i], "-fhelp"))
04088 ;
04089 else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot=")))
04090 {
04091 target_system_root = argv[i] + strlen ("--sysroot=");
04092 target_system_root_changed = 1;
04093 }
04094 else if (argv[i][0] == '+' && argv[i][1] == 'e')
04095 {
04096
04097
04098
04099
04100
04101 switches[n_switches].part1 = &argv[i][0];
04102 switches[n_switches].args = 0;
04103 switches[n_switches].live_cond = SWITCH_OK;
04104 switches[n_switches].validated = 0;
04105 n_switches++;
04106 }
04107 else if (strncmp (argv[i], "-Wl,", 4) == 0)
04108 {
04109 int prev, j;
04110
04111 prev = 4;
04112 for (j = 4; argv[i][j]; j++)
04113 if (argv[i][j] == ',')
04114 {
04115 infiles[n_infiles].language = "*";
04116 infiles[n_infiles++].name
04117 = save_string (argv[i] + prev, j - prev);
04118 prev = j + 1;
04119 }
04120
04121 infiles[n_infiles].language = "*";
04122 infiles[n_infiles++].name = argv[i] + prev;
04123 }
04124 else if (strcmp (argv[i], "-Xlinker") == 0)
04125 {
04126 infiles[n_infiles].language = "*";
04127 infiles[n_infiles++].name = argv[++i];
04128 }
04129
04130
04131 else if (strcmp (argv[i], "-Xassembler") == 0)
04132 i++;
04133 else if (strcmp (argv[i], "-Xpreprocessor") == 0)
04134 i++;
04135 else if (strcmp (argv[i], "-l") == 0)
04136 {
04137
04138 infiles[n_infiles].language = "*";
04139 infiles[n_infiles++].name = concat ("-l", argv[++i], NULL);
04140 }
04141 else if (strncmp (argv[i], "-l", 2) == 0)
04142 {
04143 infiles[n_infiles].language = "*";
04144 infiles[n_infiles++].name = argv[i];
04145 }
04146 else if (strcmp (argv[i], "-specs") == 0)
04147 i++;
04148 else if (strncmp (argv[i], "-specs=", 7) == 0)
04149 ;
04150 else if (strcmp (argv[i], "-time") == 0)
04151 ;
04152 else if (strcmp (argv[i], "-###") == 0)
04153 ;
04154 else if (argv[i][0] == '-' && argv[i][1] != 0)
04155 {
04156 const char *p = &argv[i][1];
04157 int c = *p;
04158
04159 if (c == 'x')
04160 {
04161 if (p[1] == 0 && i + 1 == argc)
04162 fatal ("argument to '-x' is missing");
04163 if (p[1] == 0)
04164 spec_lang = argv[++i];
04165 else
04166 spec_lang = p + 1;
04167 if (! strcmp (spec_lang, "none"))
04168
04169
04170
04171 spec_lang = 0;
04172 else
04173 last_language_n_infiles = n_infiles;
04174 continue;
04175 }
04176 switches[n_switches].part1 = p;
04177
04178 if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
04179 || WORD_SWITCH_TAKES_ARG (p))
04180 {
04181 int j = 0;
04182 int n_args = WORD_SWITCH_TAKES_ARG (p);
04183
04184 if (n_args == 0)
04185 {
04186
04187 n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
04188 }
04189 if (i + n_args >= argc)
04190 fatal ("argument to '-%s' is missing", p);
04191 switches[n_switches].args
04192 = XNEWVEC (const char *, n_args + 1);
04193 while (j < n_args)
04194 switches[n_switches].args[j++] = argv[++i];
04195
04196 switches[n_switches].args[j] = 0;
04197 }
04198 else if (strchr (switches_need_spaces, c))
04199 {
04200
04201
04202 char *part1 = XNEWVEC (char, 2);
04203 part1[0] = c;
04204 part1[1] = '\0';
04205
04206 switches[n_switches].part1 = part1;
04207 switches[n_switches].args = XNEWVEC (const char *, 2);
04208 switches[n_switches].args[0] = xstrdup (p+1);
04209 switches[n_switches].args[1] = 0;
04210 }
04211 else
04212 switches[n_switches].args = 0;
04213
04214 switches[n_switches].live_cond = SWITCH_OK;
04215 switches[n_switches].validated = 0;
04216 switches[n_switches].ordering = 0;
04217
04218 if (!strcmp (p, "save-temps")
04219 || !strcmp (p, "static-libgcc")
04220 || !strcmp (p, "shared-libgcc")
04221 || !strcmp (p, "pipe"))
04222 switches[n_switches].validated = 1;
04223 else
04224 {
04225 char ch = switches[n_switches].part1[0];
04226 if (ch == 'B')
04227 switches[n_switches].validated = 1;
04228 }
04229 n_switches++;
04230 }
04231 else
04232 {
04233 #ifdef HAVE_TARGET_OBJECT_SUFFIX
04234 argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
04235 #endif
04236
04237 if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
04238 {
04239 perror_with_name (argv[i]);
04240 error_count++;
04241 }
04242 else
04243 {
04244 infiles[n_infiles].language = spec_lang;
04245 infiles[n_infiles++].name = argv[i];
04246 }
04247 }
04248 }
04249
04250 if (n_infiles == last_language_n_infiles && spec_lang != 0)
04251 error ("warning: '-x %s' after last input file has no effect", spec_lang);
04252
04253
04254 if (target_help_flag || print_help_list)
04255 {
04256 n_infiles = 1;
04257
04258
04259
04260 infiles[0].language = "c";
04261 infiles[0].name = "help-dummy";
04262
04263 if (target_help_flag)
04264 {
04265 switches[n_switches].part1 = "--target-help";
04266 switches[n_switches].args = 0;
04267 switches[n_switches].live_cond = SWITCH_OK;
04268 switches[n_switches].validated = 0;
04269
04270 n_switches++;
04271 }
04272
04273 if (print_help_list)
04274 {
04275 switches[n_switches].part1 = "--help";
04276 switches[n_switches].args = 0;
04277 switches[n_switches].live_cond = SWITCH_OK;
04278 switches[n_switches].validated = 0;
04279
04280 n_switches++;
04281 }
04282 }
04283
04284 switches[n_switches].part1 = 0;
04285 infiles[n_infiles].name = 0;
04286 }
04287
04288
04289
04290
04291 static void
04292 set_collect_gcc_options (void)
04293 {
04294 int i;
04295 int first_time;
04296
04297
04298
04299 obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
04300 sizeof ("COLLECT_GCC_OPTIONS=") - 1);
04301
04302 first_time = TRUE;
04303 for (i = 0; (int) i < n_switches; i++)
04304 {
04305 const char *const *args;
04306 const char *p, *q;
04307 if (!first_time)
04308 obstack_grow (&collect_obstack, " ", 1);
04309
04310 first_time = FALSE;
04311
04312
04313 if (switches[i].live_cond == SWITCH_IGNORE)
04314 continue;
04315
04316 obstack_grow (&collect_obstack, "'-", 2);
04317 q = switches[i].part1;
04318 while ((p = strchr (q, '\'')))
04319 {
04320 obstack_grow (&collect_obstack, q, p - q);
04321 obstack_grow (&collect_obstack, "'\\''", 4);
04322 q = ++p;
04323 }
04324 obstack_grow (&collect_obstack, q, strlen (q));
04325 obstack_grow (&collect_obstack, "'", 1);
04326
04327 for (args = switches[i].args; args && *args; args++)
04328 {
04329 obstack_grow (&collect_obstack, " '", 2);
04330 q = *args;
04331 while ((p = strchr (q, '\'')))
04332 {
04333 obstack_grow (&collect_obstack, q, p - q);
04334 obstack_grow (&collect_obstack, "'\\''", 4);
04335 q = ++p;
04336 }
04337 obstack_grow (&collect_obstack, q, strlen (q));
04338 obstack_grow (&collect_obstack, "'", 1);
04339 }
04340 }
04341 obstack_grow (&collect_obstack, "\0", 1);
04342 putenv (XOBFINISH (&collect_obstack, char *));
04343 }
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354 static const char *input_filename;
04355 static int input_file_number;
04356 size_t input_filename_length;
04357 static int basename_length;
04358 static int suffixed_basename_length;
04359 static const char *input_basename;
04360 static const char *input_suffix;
04361 #ifndef HOST_LACKS_INODE_NUMBERS
04362 static struct stat input_stat;
04363 #endif
04364 static int input_stat_set;
04365
04366
04367 static struct compiler *input_file_compiler;
04368
04369
04370
04371
04372
04373 static int arg_going;
04374
04375
04376
04377 static int delete_this_arg;
04378
04379
04380
04381 static int this_is_output_file;
04382
04383
04384
04385
04386 static int this_is_library_file;
04387
04388
04389 static int input_from_pipe;
04390
04391
04392
04393 static const char *suffix_subst;
04394
04395
04396
04397
04398 int
04399 do_spec (const char *spec)
04400 {
04401 int value;
04402
04403 value = do_spec_2 (spec);
04404
04405
04406
04407 if (value == 0)
04408 {
04409 if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
04410 argbuf_index--;
04411
04412 set_collect_gcc_options ();
04413
04414 if (argbuf_index > 0)
04415 value = execute ();
04416 }
04417
04418 return value;
04419 }
04420
04421 static int
04422 do_spec_2 (const char *spec)
04423 {
04424 const char *string;
04425 int result;
04426
04427 clear_args ();
04428 arg_going = 0;
04429 delete_this_arg = 0;
04430 this_is_output_file = 0;
04431 this_is_library_file = 0;
04432 input_from_pipe = 0;
04433 suffix_subst = NULL;
04434
04435 result = do_spec_1 (spec, 0, NULL);
04436
04437
04438 if (arg_going)
04439 {
04440 obstack_1grow (&obstack, 0);
04441 string = XOBFINISH (&obstack, const char *);
04442 if (this_is_library_file)
04443 string = find_file (string);
04444 store_arg (string, delete_this_arg, this_is_output_file);
04445 if (this_is_output_file)
04446 outfiles[input_file_number] = string;
04447 arg_going = 0;
04448 }
04449
04450 return result;
04451 }
04452
04453
04454
04455
04456
04457 static void
04458 do_option_spec (const char *name, const char *spec)
04459 {
04460 unsigned int i, value_count, value_len;
04461 const char *p, *q, *value;
04462 char *tmp_spec, *tmp_spec_p;
04463
04464 if (configure_default_options[0].name == NULL)
04465 return;
04466
04467 for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
04468 if (strcmp (configure_default_options[i].name, name) == 0)
04469 break;
04470 if (i == ARRAY_SIZE (configure_default_options))
04471 return;
04472
04473 value = configure_default_options[i].value;
04474 value_len = strlen (value);
04475
04476
04477 value_count = 0;
04478 p = spec;
04479 while ((p = strstr (p, "%(VALUE)")) != NULL)
04480 {
04481 p ++;
04482 value_count ++;
04483 }
04484
04485
04486 tmp_spec = alloca (strlen (spec) + 1
04487 + value_count * (value_len - strlen ("%(VALUE)")));
04488 tmp_spec_p = tmp_spec;
04489 q = spec;
04490 while ((p = strstr (q, "%(VALUE)")) != NULL)
04491 {
04492 memcpy (tmp_spec_p, q, p - q);
04493 tmp_spec_p = tmp_spec_p + (p - q);
04494 memcpy (tmp_spec_p, value, value_len);
04495 tmp_spec_p += value_len;
04496 q = p + strlen ("%(VALUE)");
04497 }
04498 strcpy (tmp_spec_p, q);
04499
04500 do_self_spec (tmp_spec);
04501 }
04502
04503
04504
04505
04506 static void
04507 do_self_spec (const char *spec)
04508 {
04509 do_spec_2 (spec);
04510 do_spec_1 (" ", 0, NULL);
04511
04512 if (argbuf_index > 0)
04513 {
04514 int i, first;
04515
04516 first = n_switches;
04517 n_switches += argbuf_index;
04518 switches = xrealloc (switches,
04519 sizeof (struct switchstr) * (n_switches + 1));
04520
04521 switches[n_switches] = switches[first];
04522 for (i = 0; i < argbuf_index; i++)
04523 {
04524 struct switchstr *sw;
04525
04526
04527 if (argbuf[i][0] != '-')
04528 fatal ("switch '%s' does not start with '-'", argbuf[i]);
04529
04530 sw = &switches[i + first];
04531 sw->part1 = &argbuf[i][1];
04532 sw->args = 0;
04533 sw->live_cond = SWITCH_OK;
04534 sw->validated = 0;
04535 sw->ordering = 0;
04536 }
04537 }
04538 }
04539
04540
04541
04542 struct spec_path_info {
04543 const char *option;
04544 const char *append;
04545 size_t append_len;
04546 bool omit_relative;
04547 bool separate_options;
04548 };
04549
04550 static void *
04551 spec_path (char *path, void *data)
04552 {
04553 struct spec_path_info *info = data;
04554 size_t len = 0;
04555 char save = 0;
04556
04557 if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
04558 return NULL;
04559
04560 if (info->append_len != 0)
04561 {
04562 len = strlen (path);
04563 memcpy (path + len, info->append, info->append_len + 1);
04564 }
04565
04566 if (!is_directory (path, true))
04567 return NULL;
04568
04569 do_spec_1 (info->option, 1, NULL);
04570 if (info->separate_options)
04571 do_spec_1 (" ", 0, NULL);
04572
04573 if (info->append_len == 0)
04574 {
04575 len = strlen (path);
04576 save = path[len - 1];
04577 if (IS_DIR_SEPARATOR (path[len - 1]))
04578 path[len - 1] = '\0';
04579 }
04580
04581 do_spec_1 (path, 1, NULL);
04582 do_spec_1 (" ", 0, NULL);
04583
04584
04585 if (info->append_len == 0)
04586 path[len - 1] = save;
04587
04588 return NULL;
04589 }
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603 static int
04604 do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
04605 {
04606 const char *p = spec;
04607 int c;
04608 int i;
04609 const char *string;
04610 int value;
04611
04612 while ((c = *p++))
04613
04614
04615 switch (inswitch ? 'a' : c)
04616 {
04617 case '\n':
04618
04619
04620 if (arg_going)
04621 {
04622 obstack_1grow (&obstack, 0);
04623 string = XOBFINISH (&obstack, const char *);
04624 if (this_is_library_file)
04625 string = find_file (string);
04626 store_arg (string, delete_this_arg, this_is_output_file);
04627 if (this_is_output_file)
04628 outfiles[input_file_number] = string;
04629 }
04630 arg_going = 0;
04631
04632 if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
04633 {
04634
04635
04636
04637 if (use_pipes)
04638 {
04639 input_from_pipe = 1;
04640 break;
04641 }
04642 else
04643 argbuf_index--;
04644 }
04645
04646 set_collect_gcc_options ();
04647
04648 if (argbuf_index > 0)
04649 {
04650 value = execute ();
04651 if (value)
04652 return value;
04653 }
04654
04655 clear_args ();
04656 arg_going = 0;
04657 delete_this_arg = 0;
04658 this_is_output_file = 0;
04659 this_is_library_file = 0;
04660 input_from_pipe = 0;
04661 break;
04662
04663 case '|':
04664
04665 if (arg_going)
04666 {
04667 obstack_1grow (&obstack, 0);
04668 string = XOBFINISH (&obstack, const char *);
04669 if (this_is_library_file)
04670 string = find_file (string);
04671 store_arg (string, delete_this_arg, this_is_output_file);
04672 if (this_is_output_file)
04673 outfiles[input_file_number] = string;
04674 }
04675
04676
04677 obstack_1grow (&obstack, c);
04678 arg_going = 1;
04679 break;
04680
04681 case '\t':
04682 case ' ':
04683
04684 if (arg_going)
04685 {
04686 obstack_1grow (&obstack, 0);
04687 string = XOBFINISH (&obstack, const char *);
04688 if (this_is_library_file)
04689 string = find_file (string);
04690 store_arg (string, delete_this_arg, this_is_output_file);
04691 if (this_is_output_file)
04692 outfiles[input_file_number] = string;
04693 }
04694
04695 arg_going = 0;
04696 delete_this_arg = 0;
04697 this_is_output_file = 0;
04698 this_is_library_file = 0;
04699 break;
04700
04701 case '%':
04702 switch (c = *p++)
04703 {
04704 case 0:
04705 fatal ("spec '%s' invalid", spec);
04706
04707 case 'b':
04708 obstack_grow (&obstack, input_basename, basename_length);
04709 arg_going = 1;
04710 break;
04711
04712 case 'B':
04713 obstack_grow (&obstack, input_basename, suffixed_basename_length);
04714 arg_going = 1;
04715 break;
04716
04717 case 'd':
04718 delete_this_arg = 2;
04719 break;
04720
04721
04722
04723
04724 case 'D':
04725 {
04726 struct spec_path_info info;
04727
04728 info.option = "-L";
04729 info.append_len = 0;
04730 #ifdef RELATIVE_PREFIX_NOT_LINKDIR
04731
04732
04733
04734
04735
04736 info.omit_relative = true;
04737 #else
04738 info.omit_relative = false;
04739 #endif
04740 info.separate_options = false;
04741
04742 for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
04743 }
04744 break;
04745
04746 case 'e':
04747
04748
04749 {
04750 const char *q = p;
04751 char *buf;
04752 while (*p != 0 && *p != '\n')
04753 p++;
04754 buf = alloca (p - q + 1);
04755 strncpy (buf, q, p - q);
04756 buf[p - q] = 0;
04757 error ("%s", buf);
04758 return -1;
04759 }
04760 break;
04761 case 'n':
04762
04763 {
04764 const char *q = p;
04765 char *buf;
04766 while (*p != 0 && *p != '\n')
04767 p++;
04768 buf = alloca (p - q + 1);
04769 strncpy (buf, q, p - q);
04770 buf[p - q] = 0;
04771 notice ("%s\n", buf);
04772 if (*p)
04773 p++;
04774 }
04775 break;
04776
04777 case 'j':
04778 {
04779 struct stat st;
04780
04781
04782
04783
04784
04785
04786 if ((!save_temps_flag)
04787 && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
04788 && (access (HOST_BIT_BUCKET, W_OK) == 0))
04789 {
04790 obstack_grow (&obstack, HOST_BIT_BUCKET,
04791 strlen (HOST_BIT_BUCKET));
04792 delete_this_arg = 0;
04793 arg_going = 1;
04794 break;
04795 }
04796 }
04797 goto create_temp_file;
04798 case '|':
04799 if (use_pipes)
04800 {
04801 obstack_1grow (&obstack, '-');
04802 delete_this_arg = 0;
04803 arg_going = 1;
04804
04805
04806 while (*p == '.' || ISALNUM ((unsigned char) *p))
04807 p++;
04808 if (p[0] == '%' && p[1] == 'O')
04809 p += 2;
04810
04811 break;
04812 }
04813 goto create_temp_file;
04814 case 'm':
04815 if (use_pipes)
04816 {
04817
04818 while (*p == '.' || ISALNUM ((unsigned char) *p))
04819 p++;
04820 if (p[0] == '%' && p[1] == 'O')
04821 p += 2;
04822
04823 break;
04824 }
04825 goto create_temp_file;
04826 case 'g':
04827 case 'u':
04828 case 'U':
04829 create_temp_file:
04830 {
04831 struct temp_name *t;
04832 int suffix_length;
04833 const char *suffix = p;
04834 char *saved_suffix = NULL;
04835
04836 while (*p == '.' || ISALNUM ((unsigned char) *p))
04837 p++;
04838 suffix_length = p - suffix;
04839 if (p[0] == '%' && p[1] == 'O')
04840 {
04841 p += 2;
04842
04843 if (*p == '.' || ISALNUM ((unsigned char) *p))
04844 fatal ("spec '%s' has invalid '%%0%c'", spec, *p);
04845 if (suffix_length == 0)
04846 suffix = TARGET_OBJECT_SUFFIX;
04847 else
04848 {
04849 saved_suffix
04850 = XNEWVEC (char, suffix_length
04851 + strlen (TARGET_OBJECT_SUFFIX));
04852 strncpy (saved_suffix, suffix, suffix_length);
04853 strcpy (saved_suffix + suffix_length,
04854 TARGET_OBJECT_SUFFIX);
04855 }
04856 suffix_length += strlen (TARGET_OBJECT_SUFFIX);
04857 }
04858
04859
04860
04861
04862
04863
04864
04865
04866
04867 if (save_temps_flag)
04868 {
04869 temp_filename_length = basename_length + suffix_length;
04870 temp_filename = alloca (temp_filename_length + 1);
04871 strncpy ((char *) temp_filename, input_basename, basename_length);
04872 strncpy ((char *) temp_filename + basename_length, suffix,
04873 suffix_length);
04874 *((char *) temp_filename + temp_filename_length) = '\0';
04875 if (strcmp (temp_filename, input_filename) != 0)
04876 {
04877 #ifndef HOST_LACKS_INODE_NUMBERS
04878 struct stat st_temp;
04879
04880
04881 if (input_stat_set == 0)
04882 {
04883 input_stat_set = stat (input_filename, &input_stat);
04884 if (input_stat_set >= 0)
04885 input_stat_set = 1;
04886 }
04887
04888
04889
04890
04891
04892 if (input_stat_set != 1
04893 || stat (temp_filename, &st_temp) < 0
04894 || input_stat.st_dev != st_temp.st_dev
04895 || input_stat.st_ino != st_temp.st_ino)
04896 #else
04897
04898 char* input_realname = lrealpath (input_filename);
04899 char* temp_realname = lrealpath (temp_filename);
04900 bool files_differ = strcmp (input_realname, temp_realname);
04901 free (input_realname);
04902 free (temp_realname);
04903 if (files_differ)
04904 #endif
04905 {
04906 temp_filename = save_string (temp_filename,
04907 temp_filename_length + 1);
04908 obstack_grow (&obstack, temp_filename,
04909 temp_filename_length);
04910 arg_going = 1;
04911 delete_this_arg = 0;
04912 break;
04913 }
04914 }
04915 }
04916
04917
04918
04919 for (t = temp_names; t; t = t->next)
04920 if (t->length == suffix_length
04921 && strncmp (t->suffix, suffix, suffix_length) == 0
04922 && t->unique == (c == 'u' || c == 'U' || c == 'j'))
04923 break;
04924
04925
04926
04927 if (t == 0 || c == 'u' || c == 'j')
04928 {
04929 if (t == 0)
04930 {
04931 t = xmalloc (sizeof (struct temp_name));
04932 t->next = temp_names;
04933 temp_names = t;
04934 }
04935 t->length = suffix_length;
04936 if (saved_suffix)
04937 {
04938 t->suffix = saved_suffix;
04939 saved_suffix = NULL;
04940 }
04941 else
04942 t->suffix = save_string (suffix, suffix_length);
04943 t->unique = (c == 'u' || c == 'U' || c == 'j');
04944 temp_filename = make_temp_file (t->suffix);
04945 temp_filename_length = strlen (temp_filename);
04946 t->filename = temp_filename;
04947 t->filename_length = temp_filename_length;
04948 }
04949
04950 if (saved_suffix)
04951 free (saved_suffix);
04952
04953 obstack_grow (&obstack, t->filename, t->filename_length);
04954 delete_this_arg = 1;
04955 }
04956 arg_going = 1;
04957 break;
04958
04959 case 'i':
04960 if (combine_inputs)
04961 {
04962 for (i = 0; (int) i < n_infiles; i++)
04963 if ((!infiles[i].language) || (infiles[i].language[0] != '*'))
04964 if (infiles[i].incompiler == input_file_compiler)
04965 {
04966 store_arg (infiles[i].name, 0, 0);
04967 infiles[i].compiled = true;
04968 }
04969 }
04970 else
04971 {
04972 obstack_grow (&obstack, input_filename, input_filename_length);
04973 arg_going = 1;
04974 }
04975 break;
04976
04977 case 'I':
04978 {
04979 struct spec_path_info info;
04980
04981 if (multilib_dir)
04982 {
04983 do_spec_1 ("-imultilib", 1, NULL);
04984
04985 do_spec_1 (" ", 0, NULL);
04986 do_spec_1 (multilib_dir, 1, NULL);
04987 do_spec_1 (" ", 0, NULL);
04988 }
04989
04990 if (gcc_exec_prefix)
04991 {
04992 do_spec_1 ("-iprefix", 1, NULL);
04993
04994 do_spec_1 (" ", 0, NULL);
04995 do_spec_1 (gcc_exec_prefix, 1, NULL);
04996 do_spec_1 (" ", 0, NULL);
04997 }
04998
04999 if (target_system_root_changed ||
05000 (target_system_root && target_sysroot_hdrs_suffix))
05001 {
05002 do_spec_1 ("-isysroot", 1, NULL);
05003
05004 do_spec_1 (" ", 0, NULL);
05005 do_spec_1 (target_system_root, 1, NULL);
05006 if (target_sysroot_hdrs_suffix)
05007 do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
05008 do_spec_1 (" ", 0, NULL);
05009 }
05010
05011 info.option = "-isystem";
05012 info.append = "include";
05013 info.append_len = strlen (info.append);
05014 info.omit_relative = false;
05015 info.separate_options = true;
05016
05017 for_each_path (&include_prefixes, false, info.append_len,
05018 spec_path, &info);
05019 }
05020 break;
05021
05022 case 'o':
05023 {
05024 int max = n_infiles;
05025 max += lang_specific_extra_outfiles;
05026
05027 for (i = 0; i < max; i++)
05028 if (outfiles[i])
05029 store_arg (outfiles[i], 0, 0);
05030 break;
05031 }
05032
05033 case 'O':
05034 obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
05035 arg_going = 1;
05036 break;
05037
05038 case 's':
05039 this_is_library_file = 1;
05040 break;
05041
05042 case 'V':
05043 outfiles[input_file_number] = NULL;
05044 break;
05045
05046 case 'w':
05047 this_is_output_file = 1;
05048 break;
05049
05050 case 'W':
05051 {
05052 int cur_index = argbuf_index;
05053
05054 if (*p != '{')
05055 fatal ("spec '%s' has invalid '%%W%c", spec, *p);
05056 p = handle_braces (p + 1);
05057 if (p == 0)
05058 return -1;
05059
05060 if (arg_going)
05061 {
05062 obstack_1grow (&obstack, 0);
05063 string = XOBFINISH (&obstack, const char *);
05064 if (this_is_library_file)
05065 string = find_file (string);
05066 store_arg (string, delete_this_arg, this_is_output_file);
05067 if (this_is_output_file)
05068 outfiles[input_file_number] = string;
05069 arg_going = 0;
05070 }
05071
05072
05073 if (argbuf_index != cur_index)
05074 record_temp_file (argbuf[argbuf_index - 1], 0, 1);
05075 break;
05076 }
05077
05078
05079 case 'x':
05080 {
05081 const char *p1 = p;
05082 char *string;
05083
05084
05085 if (*p != '{')
05086 fatal ("spec '%s' has invalid '%%x%c'", spec, *p);
05087 while (*p++ != '}')
05088 ;
05089 string = save_string (p1 + 1, p - p1 - 2);
05090
05091
05092 for (i = 0; i < n_linker_options; i++)
05093 if (! strcmp (string, linker_options[i]))
05094 {
05095 free (string);
05096 return 0;
05097 }
05098
05099
05100 add_linker_option (string, strlen (string));
05101 }
05102 break;
05103
05104
05105 case 'X':
05106 for (i = 0; i < n_linker_options; i++)
05107 {
05108 do_spec_1 (linker_options[i], 1, NULL);
05109
05110 do_spec_1 (" ", 0, NULL);
05111 }
05112 break;
05113
05114
05115 case 'Y':
05116 for (i = 0; i < n_assembler_options; i++)
05117 {
05118 do_spec_1 (assembler_options[i], 1, NULL);
05119
05120 do_spec_1 (" ", 0, NULL);
05121 }
05122 break;
05123
05124
05125 case 'Z':
05126 for (i = 0; i < n_preprocessor_options; i++)
05127 {
05128 do_spec_1 (preprocessor_options[i], 1, NULL);
05129
05130 do_spec_1 (" ", 0, NULL);
05131 }
05132 break;
05133
05134
05135
05136
05137 case '1':
05138 value = do_spec_1 (cc1_spec, 0, NULL);
05139 if (value != 0)
05140 return value;
05141 break;
05142
05143 case '2':
05144 value = do_spec_1 (cc1plus_spec, 0, NULL);
05145 if (value != 0)
05146 return value;
05147 break;
05148
05149 case 'a':
05150 value = do_spec_1 (asm_spec, 0, NULL);
05151 if (value != 0)
05152 return value;
05153 break;
05154
05155 case 'A':
05156 value = do_spec_1 (asm_final_spec, 0, NULL);
05157 if (value != 0)
05158 return value;
05159 break;
05160
05161 case 'C':
05162 {
05163 const char *const spec
05164 = (input_file_compiler->cpp_spec
05165 ? input_file_compiler->cpp_spec
05166 : cpp_spec);
05167 value = do_spec_1 (spec, 0, NULL);
05168 if (value != 0)
05169 return value;
05170 }
05171 break;
05172
05173 case 'E':
05174 value = do_spec_1 (endfile_spec, 0, NULL);
05175 if (value != 0)
05176 return value;
05177 break;
05178
05179 case 'l':
05180 value = do_spec_1 (link_spec, 0, NULL);
05181 if (value != 0)
05182 return value;
05183 break;
05184
05185 case 'L':
05186 value = do_spec_1 (lib_spec, 0, NULL);
05187 if (value != 0)
05188 return value;
05189 break;
05190
05191 case 'G':
05192 value = do_spec_1 (libgcc_spec, 0, NULL);
05193 if (value != 0)
05194 return value;
05195 break;
05196
05197 case 'R':
05198
05199
05200 if (target_system_root)
05201 {
05202 obstack_grow (&obstack, target_system_root,
05203 strlen (target_system_root));
05204 if (target_sysroot_suffix)
05205 obstack_grow (&obstack, target_sysroot_suffix,
05206 strlen (target_sysroot_suffix));
05207 }
05208 break;
05209
05210 case 'S':
05211 value = do_spec_1 (startfile_spec, 0, NULL);
05212 if (value != 0)
05213 return value;
05214 break;
05215
05216
05217
05218 case '{':
05219 p = handle_braces (p);
05220 if (p == 0)
05221 return -1;
05222 break;
05223
05224 case ':':
05225 p = handle_spec_function (p);
05226 if (p == 0)
05227 return -1;
05228 break;
05229
05230 case '%':
05231 obstack_1grow (&obstack, '%');
05232 break;
05233
05234 case '.':
05235 {
05236 unsigned len = 0;
05237
05238 while (p[len] && p[len] != ' ' && p[len] != '%')
05239 len++;
05240 suffix_subst = save_string (p - 1, len + 1);
05241 p += len;
05242 }
05243 break;
05244
05245
05246
05247 case '<':
05248 {
05249 unsigned len = 0;
05250 int have_wildcard = 0;
05251 int i;
05252
05253 while (p[len] && p[len] != ' ' && p[len] != '\t')
05254 len++;
05255
05256 if (p[len-1] == '*')
05257 have_wildcard = 1;
05258
05259 for (i = 0; i < n_switches; i++)
05260 if (!strncmp (switches[i].part1, p, len - have_wildcard)
05261 && (have_wildcard || switches[i].part1[len] == '\0'))
05262 {
05263 switches[i].live_cond = SWITCH_IGNORE;
05264 switches[i].validated = 1;
05265 }
05266
05267 p += len;
05268 }
05269 break;
05270
05271 case '*':
05272 if (soft_matched_part)
05273 {
05274 do_spec_1 (soft_matched_part, 1, NULL);
05275 do_spec_1 (" ", 0, NULL);
05276 }
05277 else
05278
05279
05280
05281 error ("spec failure: '%%*' has not been initialized by pattern match");
05282 break;
05283
05284
05285
05286
05287
05288
05289 case '[':
05290 error ("warning: use of obsolete %%[ operator in specs");
05291 case '(':
05292 {
05293 const char *name = p;
05294 struct spec_list *sl;
05295 int len;
05296
05297
05298
05299 while (*p && *p != ')' && *p != ']')
05300 p++;
05301
05302
05303 for (len = p - name, sl = specs; sl; sl = sl->next)
05304 if (sl->name_len == len && !strncmp (sl->name, name, len))
05305 {
05306 name = *(sl->ptr_spec);
05307 #ifdef DEBUG_SPECS
05308 notice ("Processing spec %c%s%c, which is '%s'\n",
05309 c, sl->name, (c == '(') ? ')' : ']', name);
05310 #endif
05311 break;
05312 }
05313
05314 if (sl)
05315 {
05316 if (c == '(')
05317 {
05318 value = do_spec_1 (name, 0, NULL);
05319 if (value != 0)
05320 return value;
05321 }
05322 else
05323 {
05324 char *x = alloca (strlen (name) * 2 + 1);
05325 char *buf = x;
05326 const char *y = name;
05327 int flag = 0;
05328
05329
05330
05331 while (1)
05332 {
05333 if (! strncmp (y, "-D", 2))
05334 {
05335 *x++ = '-';
05336 *x++ = 'D';
05337 *x++ = '_';
05338 *x++ = '_';
05339 y += 2;
05340 flag = 1;
05341 continue;
05342 }
05343 else if (flag
05344 && (*y == ' ' || *y == '\t' || *y == '='
05345 || *y == '}' || *y == 0))
05346 {
05347 *x++ = '_';
05348 *x++ = '_';
05349 flag = 0;
05350 }
05351 if (*y == 0)
05352 break;
05353 else
05354 *x++ = *y++;
05355 }
05356 *x = 0;
05357
05358 value = do_spec_1 (buf, 0, NULL);
05359 if (value != 0)
05360 return value;
05361 }
05362 }
05363
05364
05365 if (*p)
05366 p++;
05367 }
05368 break;
05369
05370 default:
05371 error ("spec failure: unrecognized spec option '%c'", c);
05372 break;
05373 }
05374 break;
05375
05376 case '\\':
05377
05378 c = *p++;
05379
05380
05381 default:
05382
05383 obstack_1grow (&obstack, c);
05384 arg_going = 1;
05385 }
05386
05387
05388
05389 if (processing_spec_function && arg_going)
05390 {
05391 obstack_1grow (&obstack, 0);
05392 string = XOBFINISH (&obstack, const char *);
05393 if (this_is_library_file)
05394 string = find_file (string);
05395 store_arg (string, delete_this_arg, this_is_output_file);
05396 if (this_is_output_file)
05397 outfiles[input_file_number] = string;
05398 arg_going = 0;
05399 }
05400
05401 return 0;
05402 }
05403
05404
05405
05406 static const struct spec_function *
05407 lookup_spec_function (const char *name)
05408 {
05409 const struct spec_function *sf;
05410
05411 for (sf = static_spec_functions; sf->name != NULL; sf++)
05412 if (strcmp (sf->name, name) == 0)
05413 return sf;
05414
05415 return NULL;
05416 }
05417
05418
05419
05420 static const char *
05421 eval_spec_function (const char *func, const char *args)
05422 {
05423 const struct spec_function *sf;
05424 const char *funcval;
05425
05426
05427 int save_argbuf_index;
05428 int save_argbuf_length;
05429 const char **save_argbuf;
05430
05431 int save_arg_going;
05432 int save_delete_this_arg;
05433 int save_this_is_output_file;
05434 int save_this_is_library_file;
05435 int save_input_from_pipe;
05436 const char *save_suffix_subst;
05437
05438
05439 sf = lookup_spec_function (func);
05440 if (sf == NULL)
05441 fatal ("unknown spec function '%s'", func);
05442
05443
05444 save_argbuf_index = argbuf_index;
05445 save_argbuf_length = argbuf_length;
05446 save_argbuf = argbuf;
05447
05448 save_arg_going = arg_going;
05449 save_delete_this_arg = delete_this_arg;
05450 save_this_is_output_file = this_is_output_file;
05451 save_this_is_library_file = this_is_library_file;
05452 save_input_from_pipe = input_from_pipe;
05453 save_suffix_subst = suffix_subst;
05454
05455
05456
05457
05458 alloc_args ();
05459 if (do_spec_2 (args) < 0)
05460 fatal ("error in args to spec function '%s'", func);
05461
05462
05463
05464
05465 funcval = (*sf->func) (argbuf_index, argbuf);
05466
05467
05468 argbuf_index = save_argbuf_index;
05469 argbuf_length = save_argbuf_length;
05470 free (argbuf);
05471 argbuf = save_argbuf;
05472
05473 arg_going = save_arg_going;
05474 delete_this_arg = save_delete_this_arg;
05475 this_is_output_file = save_this_is_output_file;
05476 this_is_library_file = save_this_is_library_file;
05477 input_from_pipe = save_input_from_pipe;
05478 suffix_subst = save_suffix_subst;
05479
05480 return funcval;
05481 }
05482
05483
05484
05485
05486
05487
05488
05489
05490
05491
05492 static const char *
05493 handle_spec_function (const char *p)
05494 {
05495 char *func, *args;
05496 const char *endp, *funcval;
05497 int count;
05498
05499 processing_spec_function++;
05500
05501
05502 for (endp = p; *endp != '\0'; endp++)
05503 {
05504 if (*endp == '(')
05505 break;
05506
05507 if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
05508 fatal ("malformed spec function name");
05509 }
05510 if (*endp != '(')
05511 fatal ("no arguments for spec function");
05512 func = save_string (p, endp - p);
05513 p = ++endp;
05514
05515
05516 for (count = 0; *endp != '\0'; endp++)
05517 {
05518
05519 if (*endp == ')')
05520 {
05521 if (count == 0)
05522 break;
05523 count--;
05524 }
05525 else if (*endp == '(')
05526 count++;
05527 }
05528
05529 if (*endp != ')')
05530 fatal ("malformed spec function arguments");
05531 args = save_string (p, endp - p);
05532 p = ++endp;
05533
05534
05535
05536 funcval = eval_spec_function (func, args);
05537 if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
05538 p = NULL;
05539
05540 free (func);
05541 free (args);
05542
05543 processing_spec_function--;
05544
05545 return p;
05546 }
05547
05548
05549
05550 static inline bool
05551 input_suffix_matches (const char *atom, const char *end_atom)
05552 {
05553
05554
05555
05556
05557
05558
05559 if (atom + 1 == end_atom
05560 && input_file_compiler
05561 && input_file_compiler->suffix)
05562 {
05563 if (*atom == 's')
05564 return !strcmp (input_file_compiler->suffix, "@assembler");
05565 if (*atom == 'S')
05566 return !strcmp (input_file_compiler->suffix, "@assembler-with-cpp");
05567 }
05568
05569 return (input_suffix
05570 && !strncmp (input_suffix, atom, end_atom - atom)
05571 && input_suffix[end_atom - atom] == '\0');
05572 }
05573
05574
05575
05576
05577 static bool
05578 switch_matches (const char *atom, const char *end_atom, int starred)
05579 {
05580 int i;
05581 int len = end_atom - atom;
05582 int plen = starred ? len : -1;
05583
05584 for (i = 0; i < n_switches; i++)
05585 if (!strncmp (switches[i].part1, atom, len)
05586 && (starred || switches[i].part1[len] == '\0')
05587 && check_live_switch (i, plen))
05588 return true;
05589
05590 return false;
05591 }
05592
05593
05594
05595
05596 static inline void
05597 mark_matching_switches (const char *atom, const char *end_atom, int starred)
05598 {
05599 int i;
05600 int len = end_atom - atom;
05601 int plen = starred ? len : -1;
05602
05603 for (i = 0; i < n_switches; i++)
05604 if (!strncmp (switches[i].part1, atom, len)
05605 && (starred || switches[i].part1[len] == '\0')
05606 && check_live_switch (i, plen))
05607 switches[i].ordering = 1;
05608 }
05609
05610
05611
05612 static inline void
05613 process_marked_switches (void)
05614 {
05615 int i;
05616
05617 for (i = 0; i < n_switches; i++)
05618 if (switches[i].ordering == 1)
05619 {
05620 switches[i].ordering = 0;
05621 give_switch (i, 0);
05622 }
05623 }
05624
05625
05626
05627
05628
05629 static const char *
05630 handle_braces (const char *p)
05631 {
05632 const char *atom, *end_atom;
05633 const char *d_atom = NULL, *d_end_atom = NULL;
05634 const char *orig = p;
05635
05636 bool a_is_suffix;
05637 bool a_is_starred;
05638 bool a_is_negated;
05639 bool a_matched;
05640
05641 bool a_must_be_last = false;
05642 bool ordered_set = false;
05643 bool disjunct_set = false;
05644 bool disj_matched = false;
05645 bool disj_starred = true;
05646 bool n_way_choice = false;
05647 bool n_way_matched = false;
05648
05649 #define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
05650
05651 do
05652 {
05653 if (a_must_be_last)
05654 goto invalid;
05655
05656
05657
05658 a_matched = a_is_suffix = a_is_starred = a_is_negated = false;
05659
05660 SKIP_WHITE();
05661 if (*p == '!')
05662 p++, a_is_negated = true;
05663
05664 SKIP_WHITE();
05665 if (*p == '.')
05666 p++, a_is_suffix = true;
05667
05668 atom = p;
05669 while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
05670 || *p == ',' || *p == '.' || *p == '@')
05671 p++;
05672 end_atom = p;
05673
05674 if (*p == '*')
05675 p++, a_is_starred = 1;
05676
05677 SKIP_WHITE();
05678 switch (*p)
05679 {
05680 case '&': case '}':
05681
05682 ordered_set = true;
05683 if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
05684 || atom == end_atom)
05685 goto invalid;
05686
05687 mark_matching_switches (atom, end_atom, a_is_starred);
05688
05689 if (*p == '}')
05690 process_marked_switches ();
05691 break;
05692
05693 case '|': case ':':
05694
05695
05696 disjunct_set = true;
05697 if (ordered_set)
05698 goto invalid;
05699
05700 if (atom == end_atom)
05701 {
05702 if (!n_way_choice || disj_matched || *p == '|'
05703 || a_is_negated || a_is_suffix || a_is_starred)
05704 goto invalid;
05705
05706
05707
05708 a_must_be_last = true;
05709 disj_matched = !n_way_matched;
05710 disj_starred = false;
05711 }
05712 else
05713 {
05714 if (a_is_suffix && a_is_starred)
05715 goto invalid;
05716
05717 if (!a_is_starred)
05718 disj_starred = false;
05719
05720
05721
05722 if (!disj_matched && !n_way_matched)
05723 {
05724 if (a_is_suffix)
05725 a_matched = input_suffix_matches (atom, end_atom);
05726 else
05727 a_matched = switch_matches (atom, end_atom, a_is_starred);
05728
05729 if (a_matched != a_is_negated)
05730 {
05731 disj_matched = true;
05732 d_atom = atom;
05733 d_end_atom = end_atom;
05734 }
05735 }
05736 }
05737
05738 if (*p == ':')
05739 {
05740
05741
05742 p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
05743 disj_matched && !n_way_matched);
05744 if (p == 0)
05745 return 0;
05746
05747
05748
05749 if (*p == ';')
05750 {
05751 n_way_choice = true;
05752 n_way_matched |= disj_matched;
05753 disj_matched = false;
05754 disj_starred = true;
05755 d_atom = d_end_atom = NULL;
05756 }
05757 }
05758 break;
05759
05760 default:
05761 goto invalid;
05762 }
05763 }
05764 while (*p++ != '}');
05765
05766 return p;
05767
05768 invalid:
05769 fatal ("braced spec '%s' is invalid at '%c'", orig, *p);
05770
05771 #undef SKIP_WHITE
05772 }
05773
05774
05775
05776
05777
05778
05779
05780
05781
05782
05783
05784 static const char *
05785 process_brace_body (const char *p, const char *atom, const char *end_atom,
05786 int starred, int matched)
05787 {
05788 const char *body, *end_body;
05789 unsigned int nesting_level;
05790 bool have_subst = false;
05791
05792
05793
05794 body = p;
05795 nesting_level = 1;
05796 for (;;)
05797 {
05798 if (*p == '{')
05799 nesting_level++;
05800 else if (*p == '}')
05801 {
05802 if (!--nesting_level)
05803 break;
05804 }
05805 else if (*p == ';' && nesting_level == 1)
05806 break;
05807 else if (*p == '%' && p[1] == '*' && nesting_level == 1)
05808 have_subst = true;
05809 else if (*p == '\0')
05810 goto invalid;
05811 p++;
05812 }
05813
05814 end_body = p;
05815 while (end_body[-1] == ' ' || end_body[-1] == '\t')
05816 end_body--;
05817
05818 if (have_subst && !starred)
05819 goto invalid;
05820
05821 if (matched)
05822 {
05823
05824
05825
05826 char *string = save_string (body, end_body - body);
05827 if (!have_subst)
05828 {
05829 if (do_spec_1 (string, 0, NULL) < 0)
05830 return 0;
05831 }
05832 else
05833 {
05834
05835
05836
05837 unsigned int hard_match_len = end_atom - atom;
05838 int i;
05839
05840 for (i = 0; i < n_switches; i++)
05841 if (!strncmp (switches[i].part1, atom, hard_match_len)
05842 && check_live_switch (i, hard_match_len))
05843 {
05844 if (do_spec_1 (string, 0,
05845 &switches[i].part1[hard_match_len]) < 0)
05846 return 0;
05847
05848 give_switch (i, 1);
05849 suffix_subst = NULL;
05850 }
05851 }
05852 }
05853
05854 return p;
05855
05856 invalid:
05857 fatal ("braced spec body '%s' is invalid", body);
05858 }
05859
05860
05861
05862
05863
05864
05865
05866
05867
05868 static int
05869 check_live_switch (int switchnum, int prefix_length)
05870 {
05871 const char *name = switches[switchnum].part1;
05872 int i;
05873
05874
05875
05876
05877 if (prefix_length >= 0 && prefix_length <= 1)
05878 return 1;
05879
05880
05881
05882 if (switches[switchnum].live_cond != 0)
05883 return switches[switchnum].live_cond > 0;
05884
05885
05886 switch (*name)
05887 {
05888 case 'O':
05889 for (i = switchnum + 1; i < n_switches; i++)
05890 if (switches[i].part1[0] == 'O')
05891 {
05892 switches[switchnum].validated = 1;
05893 switches[switchnum].live_cond = SWITCH_FALSE;
05894 return 0;
05895 }
05896 break;
05897
05898 case 'W': case 'f': case 'm':
05899 if (! strncmp (name + 1, "no-", 3))
05900 {
05901
05902 for (i = switchnum + 1; i < n_switches; i++)
05903 if (switches[i].part1[0] == name[0]
05904 && ! strcmp (&switches[i].part1[1], &name[4]))
05905 {
05906 switches[switchnum].validated = 1;
05907 switches[switchnum].live_cond = SWITCH_FALSE;
05908 return 0;
05909 }
05910 }
05911 else
05912 {
05913
05914 for (i = switchnum + 1; i < n_switches; i++)
05915 if (switches[i].part1[0] == name[0]
05916 && switches[i].part1[1] == 'n'
05917 && switches[i].part1[2] == 'o'
05918 && switches[i].part1[3] == '-'
05919 && !strcmp (&switches[i].part1[4], &name[1]))
05920 {
05921 switches[switchnum].validated = 1;
05922 switches[switchnum].live_cond = SWITCH_FALSE;
05923 return 0;
05924 }
05925 }
05926 break;
05927 }
05928
05929
05930 switches[switchnum].live_cond = SWITCH_LIVE;
05931 return 1;
05932 }
05933
05934
05935
05936
05937
05938
05939
05940
05941
05942 static void
05943 give_switch (int switchnum, int omit_first_word)
05944 {
05945 if (switches[switchnum].live_cond == SWITCH_IGNORE)
05946 return;
05947
05948 if (!omit_first_word)
05949 {
05950 do_spec_1 ("-", 0, NULL);
05951 do_spec_1 (switches[switchnum].part1, 1, NULL);
05952 }
05953
05954 if (switches[switchnum].args != 0)
05955 {
05956 const char **p;
05957 for (p = switches[switchnum].args; *p; p++)
05958 {
05959 const char *arg = *p;
05960
05961 do_spec_1 (" ", 0, NULL);
05962 if (suffix_subst)
05963 {
05964 unsigned length = strlen (arg);
05965 int dot = 0;
05966
05967 while (length-- && !IS_DIR_SEPARATOR (arg[length]))
05968 if (arg[length] == '.')
05969 {
05970 ((char *)arg)[length] = 0;
05971 dot = 1;
05972 break;
05973 }
05974 do_spec_1 (arg, 1, NULL);
05975 if (dot)
05976 ((char *)arg)[length] = '.';
05977 do_spec_1 (suffix_subst, 1, NULL);
05978 }
05979 else
05980 do_spec_1 (arg, 1, NULL);
05981 }
05982 }
05983
05984 do_spec_1 (" ", 0, NULL);
05985 switches[switchnum].validated = 1;
05986 }
05987
05988
05989
05990
05991
05992 static const char *
05993 find_file (const char *name)
05994 {
05995 char *newname = find_a_file (&startfile_prefixes, name, R_OK, true);
05996 return newname ? newname : name;
05997 }
05998
05999
06000
06001
06002 static int
06003 is_directory (const char *path1, bool linker)
06004 {
06005 int len1;
06006 char *path;
06007 char *cp;
06008 struct stat st;
06009
06010
06011
06012 len1 = strlen (path1);
06013 path = alloca (3 + len1);
06014 memcpy (path, path1, len1);
06015 cp = path + len1;
06016 if (!IS_DIR_SEPARATOR (cp[-1]))
06017 *cp++ = DIR_SEPARATOR;
06018 *cp++ = '.';
06019 *cp = '\0';
06020
06021
06022 if (linker
06023 && IS_DIR_SEPARATOR (path[0])
06024 && ((cp - path == 6
06025 && strncmp (path + 1, "lib", 3) == 0)
06026 || (cp - path == 10
06027 && strncmp (path + 1, "usr", 3) == 0
06028 && IS_DIR_SEPARATOR (path[4])
06029 && strncmp (path + 5, "lib", 3) == 0)))
06030 return 0;
06031
06032 return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
06033 }
06034
06035
06036
06037
06038 void
06039 set_input (const char *filename)
06040 {
06041 const char *p;
06042
06043 input_filename = filename;
06044 input_filename_length = strlen (input_filename);
06045
06046 input_basename = input_filename;
06047 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
06048
06049 if (input_basename[1] == ':')
06050 input_basename += 2;
06051 #endif
06052 for (p = input_basename; *p; p++)
06053 if (IS_DIR_SEPARATOR (*p))
06054 input_basename = p + 1;
06055
06056
06057
06058 basename_length = strlen (input_basename);
06059 suffixed_basename_length = basename_length;
06060 p = input_basename + basename_length;
06061 while (p != input_basename && *p != '.')
06062 --p;
06063 if (*p == '.' && p != input_basename)
06064 {
06065 basename_length = p - input_basename;
06066 input_suffix = p + 1;
06067 }
06068 else
06069 input_suffix = "";
06070
06071
06072
06073
06074 input_stat_set = 0;
06075 }
06076
06077
06078
06079 static void
06080 fatal_error (int signum)
06081 {
06082 signal (signum, SIG_DFL);
06083 delete_failure_queue ();
06084 delete_temp_files ();
06085
06086
06087 kill (getpid (), signum);
06088 }
06089
06090 extern int main (int, char **);
06091
06092 int
06093 main (int argc, char **argv)
06094 {
06095 size_t i;
06096 int value;
06097 int linker_was_run = 0;
06098 int lang_n_infiles = 0;
06099 int num_linker_inputs = 0;
06100 char *explicit_link_files;
06101 char *specs_file;
06102 const char *p;
06103 struct user_specs *uptr;
06104
06105 p = argv[0] + strlen (argv[0]);
06106 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
06107 --p;
06108 programname = p;
06109
06110 xmalloc_set_program_name (programname);
06111
06112 expandargv (&argc, &argv);
06113
06114 prune_options (&argc, &argv);
06115
06116 #ifdef GCC_DRIVER_HOST_INITIALIZATION
06117
06118 GCC_DRIVER_HOST_INITIALIZATION;
06119 #endif
06120
06121
06122 unlock_std_streams ();
06123
06124 gcc_init_libintl ();
06125
06126 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
06127 signal (SIGINT, fatal_error);
06128 #ifdef SIGHUP
06129 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
06130 signal (SIGHUP, fatal_error);
06131 #endif
06132 if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
06133 signal (SIGTERM, fatal_error);
06134 #ifdef SIGPIPE
06135 if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
06136 signal (SIGPIPE, fatal_error);
06137 #endif
06138 #ifdef SIGCHLD
06139
06140
06141 signal (SIGCHLD, SIG_DFL);
06142 #endif
06143
06144
06145 alloc_args ();
06146
06147 obstack_init (&obstack);
06148
06149
06150
06151 {
06152 const char *const *q = multilib_raw;
06153 int need_space;
06154
06155 obstack_init (&multilib_obstack);
06156 while ((p = *q++) != (char *) 0)
06157 obstack_grow (&multilib_obstack, p, strlen (p));
06158
06159 obstack_1grow (&multilib_obstack, 0);
06160 multilib_select = XOBFINISH (&multilib_obstack, const char *);
06161
06162 q = multilib_matches_raw;
06163 while ((p = *q++) != (char *) 0)
06164 obstack_grow (&multilib_obstack, p, strlen (p));
06165
06166 obstack_1grow (&multilib_obstack, 0);
06167 multilib_matches = XOBFINISH (&multilib_obstack, const char *);
06168
06169 q = multilib_exclusions_raw;
06170 while ((p = *q++) != (char *) 0)
06171 obstack_grow (&multilib_obstack, p, strlen (p));
06172
06173 obstack_1grow (&multilib_obstack, 0);
06174 multilib_exclusions = XOBFINISH (&multilib_obstack, const char *);
06175
06176 need_space = FALSE;
06177 for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
06178 {
06179 if (need_space)
06180 obstack_1grow (&multilib_obstack, ' ');
06181 obstack_grow (&multilib_obstack,
06182 multilib_defaults_raw[i],
06183 strlen (multilib_defaults_raw[i]));
06184 need_space = TRUE;
06185 }
06186
06187 obstack_1grow (&multilib_obstack, 0);
06188 multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
06189 }
06190
06191
06192
06193
06194 obstack_init (&collect_obstack);
06195 obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
06196 obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
06197 putenv (XOBFINISH (&collect_obstack, char *));
06198
06199 #ifdef INIT_ENVIRONMENT
06200
06201 putenv (INIT_ENVIRONMENT);
06202 #endif
06203
06204
06205
06206
06207
06208 process_command (argc, (const char **) argv);
06209
06210
06211
06212
06213 compilers = xmalloc (sizeof default_compilers);
06214 memcpy (compilers, default_compilers, sizeof default_compilers);
06215 n_compilers = n_default_compilers;
06216
06217
06218
06219 machine_suffix = concat (spec_machine, dir_separator_str,
06220 spec_version, dir_separator_str, NULL);
06221 just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
06222
06223 specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
06224
06225 if (specs_file != 0 && strcmp (specs_file, "specs"))
06226 read_specs (specs_file, TRUE);
06227 else
06228 init_spec ();
06229
06230
06231
06232 specs_file = alloca (strlen (standard_exec_prefix)
06233 + strlen (just_machine_suffix) + sizeof ("specs"));
06234
06235 strcpy (specs_file, standard_exec_prefix);
06236 strcat (specs_file, just_machine_suffix);
06237 strcat (specs_file, "specs");
06238 if (access (specs_file, R_OK) == 0)
06239 read_specs (specs_file, TRUE);
06240
06241
06242
06243 for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
06244 do_option_spec (option_default_specs[i].name,
06245 option_default_specs[i].spec);
06246
06247
06248
06249
06250 for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
06251 do_self_spec (driver_self_specs[i]);
06252
06253
06254
06255 if (*cross_compile == '0')
06256 {
06257 if (*md_exec_prefix)
06258 {
06259 add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
06260 PREFIX_PRIORITY_LAST, 0, 0);
06261 }
06262 }
06263
06264
06265 if (*sysroot_suffix_spec != 0
06266 && do_spec_2 (sysroot_suffix_spec) == 0)
06267 {
06268 if (argbuf_index > 1)
06269 error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC");
06270 else if (argbuf_index == 1)
06271 target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]);
06272 }
06273
06274 #ifdef HAVE_LD_SYSROOT
06275
06276
06277
06278
06279 if (target_system_root)
06280 {
06281 obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
06282 obstack_grow0 (&obstack, link_spec, strlen (link_spec));
06283 set_spec ("link", XOBFINISH (&obstack, const char *));
06284 }
06285 #endif
06286
06287
06288 if (*sysroot_hdrs_suffix_spec != 0
06289 && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
06290 {
06291 if (argbuf_index > 1)
06292 error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC");
06293 else if (argbuf_index == 1)
06294 target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]);
06295 }
06296
06297
06298 if (*startfile_prefix_spec != 0
06299 && do_spec_2 (startfile_prefix_spec) == 0
06300 && do_spec_1 (" ", 0, NULL) == 0)
06301 {
06302 int ndx;
06303 for (ndx = 0; ndx < argbuf_index; ndx++)
06304 add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS",
06305 PREFIX_PRIORITY_LAST, 0, 1);
06306 }
06307
06308
06309 else if (*cross_compile == '0' || target_system_root)
06310 {
06311 if (*md_startfile_prefix)
06312 add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
06313 "GCC", PREFIX_PRIORITY_LAST, 0, 1);
06314
06315 if (*md_startfile_prefix_1)
06316 add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1,
06317 "GCC", PREFIX_PRIORITY_LAST, 0, 1);
06318
06319
06320
06321
06322
06323
06324
06325
06326 if (IS_ABSOLUTE_PATH (standard_startfile_prefix))
06327 add_sysrooted_prefix (&startfile_prefixes,
06328 standard_startfile_prefix, "BINUTILS",
06329 PREFIX_PRIORITY_LAST, 0, 1);
06330 else if (*cross_compile == '0')
06331 {
06332 if (gcc_exec_prefix)
06333 add_prefix (&startfile_prefixes,
06334 concat (gcc_exec_prefix, machine_suffix,
06335 standard_startfile_prefix, NULL),
06336 NULL, PREFIX_PRIORITY_LAST, 0, 1);
06337 add_prefix (&startfile_prefixes,
06338 concat (standard_exec_prefix,
06339 machine_suffix,
06340 standard_startfile_prefix, NULL),
06341 NULL, PREFIX_PRIORITY_LAST, 0, 1);
06342 }
06343
06344 if (*standard_startfile_prefix_1)
06345 add_sysrooted_prefix (&startfile_prefixes,
06346 standard_startfile_prefix_1, "BINUTILS",
06347 PREFIX_PRIORITY_LAST, 0, 1);
06348 if (*standard_startfile_prefix_2)
06349 add_sysrooted_prefix (&startfile_prefixes,
06350 standard_startfile_prefix_2, "BINUTILS",
06351 PREFIX_PRIORITY_LAST, 0, 1);
06352 }
06353
06354
06355
06356 for (uptr = user_specs_head; uptr; uptr = uptr->next)
06357 {
06358 char *filename = find_a_file (&startfile_prefixes, uptr->filename,
06359 R_OK, true);
06360 read_specs (filename ? filename : uptr->filename, FALSE);
06361 }
06362
06363
06364 if (gcc_exec_prefix)
06365 gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
06366 spec_version, dir_separator_str, NULL);
06367
06368
06369
06370
06371 validate_all_switches ();
06372
06373
06374
06375 set_multilib_dir ();
06376
06377
06378
06379 for (i = 0; (int) i < n_switches; i++)
06380 if (! switches[i].validated)
06381 error ("unrecognized option '-%s'", switches[i].part1);
06382
06383
06384
06385 if (print_search_dirs)
06386 {
06387 printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
06388 printf (_("programs: %s\n"),
06389 build_search_list (&exec_prefixes, "", false, false));
06390 printf (_("libraries: %s\n"),
06391 build_search_list (&startfile_prefixes, "", false, true));
06392 return (0);
06393 }
06394
06395 if (print_file_name)
06396 {
06397 printf ("%s\n", find_file (print_file_name));
06398 return (0);
06399 }
06400
06401 if (print_prog_name)
06402 {
06403 char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
06404 printf ("%s\n", (newname ? newname : print_prog_name));
06405 return (0);
06406 }
06407
06408 if (print_multi_lib)
06409 {
06410 print_multilib_info ();
06411 return (0);
06412 }
06413
06414 if (print_multi_directory)
06415 {
06416 if (multilib_dir == NULL)
06417 printf (".\n");
06418 else
06419 printf ("%s\n", multilib_dir);
06420 return (0);
06421 }
06422
06423 if (print_multi_os_directory)
06424 {
06425 if (multilib_os_dir == NULL)
06426 printf (".\n");
06427 else
06428 printf ("%s\n", multilib_os_dir);
06429 return (0);
06430 }
06431
06432 if (target_help_flag)
06433 {
06434
06435
06436
06437
06438
06439
06440 }
06441
06442 if (print_help_list)
06443 {
06444 display_help ();
06445
06446 if (! verbose_flag)
06447 {
06448 printf (_("\nFor bug reporting instructions, please see:\n"));
06449 printf ("%s.\n", bug_report_url);
06450
06451 return (0);
06452 }
06453
06454
06455
06456
06457 }
06458
06459 if (verbose_flag)
06460 {
06461 int n;
06462 const char *thrmod;
06463
06464 notice ("Target: %s\n", spec_machine);
06465 notice ("Configured with: %s\n", configuration_arguments);
06466
06467 #ifdef THREAD_MODEL_SPEC
06468
06469
06470
06471 obstack_init (&obstack);
06472 do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
06473 obstack_1grow (&obstack, '\0');
06474 thrmod = XOBFINISH (&obstack, const char *);
06475 #else
06476 thrmod = thread_model;
06477 #endif
06478
06479 notice ("Thread model: %s\n", thrmod);
06480
06481
06482
06483
06484 for (n = 0; version_string[n]; n++)
06485 if (version_string[n] == ' ')
06486 break;
06487
06488 if (! strncmp (version_string, compiler_version, n)
06489 && compiler_version[n] == 0)
06490 notice ("gcc version %s\n", version_string);
06491 else
06492 notice ("gcc driver version %s executing gcc version %s\n",
06493 version_string, compiler_version);
06494
06495 if (n_infiles == 0)
06496 return (0);
06497 }
06498
06499 if (n_infiles == added_libraries)
06500 fatal ("no input files");
06501
06502
06503
06504
06505 i = n_infiles;
06506 i += lang_specific_extra_outfiles;
06507 outfiles = XCNEWVEC (const char *, i);
06508
06509
06510
06511 explicit_link_files = XCNEWVEC (char, n_infiles);
06512
06513 if (combine_flag)
06514 combine_inputs = true;
06515 else
06516 combine_inputs = false;
06517
06518 for (i = 0; (int) i < n_infiles; i++)
06519 {
06520 const char *name = infiles[i].name;
06521 struct compiler *compiler = lookup_compiler (name,
06522 strlen (name),
06523 infiles[i].language);
06524
06525 if (compiler && !(compiler->combinable))
06526 combine_inputs = false;
06527
06528 if (lang_n_infiles > 0 && compiler != input_file_compiler
06529 && infiles[i].language && infiles[i].language[0] != '*')
06530 infiles[i].incompiler = compiler;
06531 else if (compiler)
06532 {
06533 lang_n_infiles++;
06534 input_file_compiler = compiler;
06535 infiles[i].incompiler = compiler;
06536 }
06537 else
06538 {
06539
06540
06541 explicit_link_files[i] = 1;
06542 infiles[i].incompiler = NULL;
06543 }
06544 infiles[i].compiled = false;
06545 infiles[i].preprocessed = false;
06546 }
06547
06548 if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
06549 fatal ("cannot specify -o with -c or -S with multiple files");
06550
06551 if (combine_flag && save_temps_flag)
06552 {
06553 bool save_combine_inputs = combine_inputs;
06554
06555
06556
06557 combine_inputs = false;
06558 for (i = 0; (int) i < n_infiles; i++)
06559 {
06560 int this_file_error = 0;
06561
06562 input_file_number = i;
06563 set_input (infiles[i].name);
06564 if (infiles[i].incompiler
06565 && (infiles[i].incompiler)->needs_preprocessing)
06566 input_file_compiler = infiles[i].incompiler;
06567 else
06568 continue;
06569
06570 if (input_file_compiler)
06571 {
06572 if (input_file_compiler->spec[0] == '#')
06573 {
06574 error ("%s: %s compiler not installed on this system",
06575 input_filename, &input_file_compiler->spec[1]);
06576 this_file_error = 1;
06577 }
06578 else
06579 {
06580 value = do_spec (input_file_compiler->spec);
06581 infiles[i].preprocessed = true;
06582 if (!have_o_argbuf_index)
06583 fatal ("spec '%s' is invalid", input_file_compiler->spec);
06584 infiles[i].name = argbuf[have_o_argbuf_index];
06585 infiles[i].incompiler
06586 = lookup_compiler (infiles[i].name,
06587 strlen (infiles[i].name),
06588 infiles[i].language);
06589
06590 if (value < 0)
06591 this_file_error = 1;
06592 }
06593 }
06594
06595 if (this_file_error)
06596 {
06597 delete_failure_queue ();
06598 error_count++;
06599 break;
06600 }
06601 clear_failure_queue ();
06602 }
06603 combine_inputs = save_combine_inputs;
06604 }
06605
06606 for (i = 0; (int) i < n_infiles; i++)
06607 {
06608 int this_file_error = 0;
06609
06610
06611
06612 input_file_number = i;
06613 set_input (infiles[i].name);
06614
06615 if (infiles[i].compiled)
06616 continue;
06617
06618
06619
06620 outfiles[i] = input_filename;
06621
06622
06623
06624 if (! combine_inputs)
06625 input_file_compiler
06626 = lookup_compiler (infiles[i].name, input_filename_length,
06627 infiles[i].language);
06628 else
06629 input_file_compiler = infiles[i].incompiler;
06630
06631 if (input_file_compiler)
06632 {
06633
06634
06635 if (input_file_compiler->spec[0] == '#')
06636 {
06637 error ("%s: %s compiler not installed on this system",
06638 input_filename, &input_file_compiler->spec[1]);
06639 this_file_error = 1;
06640 }
06641 else
06642 {
06643 value = do_spec (input_file_compiler->spec);
06644 infiles[i].compiled = true;
06645 if (value < 0)
06646 this_file_error = 1;
06647 }
06648 }
06649
06650
06651
06652
06653 else
06654 explicit_link_files[i] = 1;
06655
06656
06657
06658
06659 if (this_file_error)
06660 {
06661 delete_failure_queue ();
06662 error_count++;
06663 }
06664
06665 clear_failure_queue ();
06666 }
06667
06668 #ifdef KEY
06669 if (flag_spin_file)
06670 goto SPIN_EXIT;
06671 #endif
06672
06673
06674
06675
06676
06677 if (n_infiles > 0)
06678 {
06679 int i;
06680
06681 for (i = 0; i < n_infiles ; i++)
06682 if (infiles[i].language && infiles[i].language[0] != '*')
06683 {
06684 set_input (infiles[i].name);
06685 break;
06686 }
06687 }
06688
06689 if (error_count == 0)
06690 {
06691
06692
06693 input_file_number = n_infiles;
06694 if (lang_specific_pre_link ())
06695 error_count++;
06696 }
06697
06698
06699 num_linker_inputs = 0;
06700 for (i = 0; (int) i < n_infiles; i++)
06701 if (explicit_link_files[i] || outfiles[i] != NULL)
06702 num_linker_inputs++;
06703
06704
06705
06706 if (num_linker_inputs > 0 && error_count == 0)
06707 {
06708 int tmp = execution_count;
06709
06710
06711 if (! strcmp (linker_name_spec, "collect2"))
06712 {
06713 char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
06714 if (s == NULL)
06715 linker_name_spec = "ld";
06716 }
06717
06718
06719 putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
06720 putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true);
06721
06722 value = do_spec (link_command_spec);
06723 if (value < 0)
06724 error_count = 1;
06725 linker_was_run = (tmp != execution_count);
06726 }
06727
06728
06729
06730
06731 if (! linker_was_run && error_count == 0)
06732 for (i = 0; (int) i < n_infiles; i++)
06733 if (explicit_link_files[i])
06734 error ("%s: linker input file unused because linking not done",
06735 outfiles[i]);
06736
06737 #ifdef KEY
06738 SPIN_EXIT:
06739 #endif
06740
06741
06742
06743 if (error_count)
06744 delete_failure_queue ();
06745 delete_temp_files ();
06746
06747 if (print_help_list)
06748 {
06749 printf (("\nFor bug reporting instructions, please see:\n"));
06750 printf ("%s\n", bug_report_url);
06751 }
06752
06753 return (signal_count != 0 ? 2
06754 : error_count > 0 ? (pass_exit_codes ? greatest_status : 1)
06755 : 0);
06756 }
06757
06758
06759
06760
06761
06762 static struct compiler *
06763 lookup_compiler (const char *name, size_t length, const char *language)
06764 {
06765 struct compiler *cp;
06766
06767
06768 if (language != 0 && language[0] == '*')
06769 return 0;
06770
06771
06772 if (language != 0)
06773 {
06774 for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
06775 if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
06776 return cp;
06777
06778 error ("language %s not recognized", language);
06779 return 0;
06780 }
06781
06782
06783 for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
06784 {
06785 if (
06786 (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
06787 || (strlen (cp->suffix) < length
06788
06789 && !strcmp (cp->suffix,
06790 name + length - strlen (cp->suffix))
06791 ))
06792 break;
06793 }
06794
06795 #if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
06796
06797 if (cp < compilers)
06798 for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
06799 {
06800 if (
06801 (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
06802 || (strlen (cp->suffix) < length
06803
06804 && ((!strcmp (cp->suffix,
06805 name + length - strlen (cp->suffix))
06806 || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
06807 && !strcasecmp (cp->suffix,
06808 name + length - strlen (cp->suffix)))
06809 ))
06810 break;
06811 }
06812 #endif
06813
06814 if (cp >= compilers)
06815 {
06816 if (cp->spec[0] != '@')
06817
06818 return cp;
06819
06820
06821
06822
06823 return lookup_compiler (NULL, 0, cp->spec + 1);
06824 }
06825 return 0;
06826 }
06827
06828 static char *
06829 save_string (const char *s, int len)
06830 {
06831 char *result = XNEWVEC (char, len + 1);
06832
06833 memcpy (result, s, len);
06834 result[len] = 0;
06835 return result;
06836 }
06837
06838 void
06839 pfatal_with_name (const char *name)
06840 {
06841 perror_with_name (name);
06842 delete_temp_files ();
06843 exit (1);
06844 }
06845
06846 static void
06847 perror_with_name (const char *name)
06848 {
06849 error ("%s: %s", name, xstrerror (errno));
06850 }
06851
06852
06853
06854 void
06855 fancy_abort (const char *file, int line, const char *func)
06856 {
06857 fatal_ice ("internal gcc abort in %s, at %s:%d", func, file, line);
06858 }
06859
06860
06861
06862 void
06863 fatal_ice (const char *cmsgid, ...)
06864 {
06865 va_list ap;
06866
06867 va_start (ap, cmsgid);
06868
06869 fprintf (stderr, "%s: ", programname);
06870 vfprintf (stderr, _(cmsgid), ap);
06871 va_end (ap);
06872 fprintf (stderr, "\n");
06873 delete_temp_files ();
06874 exit (pass_exit_codes ? ICE_EXIT_CODE : 1);
06875 }
06876
06877 void
06878 fatal (const char *cmsgid, ...)
06879 {
06880 va_list ap;
06881
06882 va_start (ap, cmsgid);
06883
06884 fprintf (stderr, "%s: ", programname);
06885 vfprintf (stderr, _(cmsgid), ap);
06886 va_end (ap);
06887 fprintf (stderr, "\n");
06888 delete_temp_files ();
06889 exit (1);
06890 }
06891
06892
06893
06894
06895
06896
06897
06898 void
06899 error (const char *gmsgid, ...)
06900 {
06901 va_list ap;
06902
06903 va_start (ap, gmsgid);
06904 fprintf (stderr, "%s: ", programname);
06905 vfprintf (stderr, _(gmsgid), ap);
06906 va_end (ap);
06907
06908 fprintf (stderr, "\n");
06909 }
06910
06911 static void
06912 notice (const char *cmsgid, ...)
06913 {
06914 va_list ap;
06915
06916 va_start (ap, cmsgid);
06917 vfprintf (stderr, _(cmsgid), ap);
06918 va_end (ap);
06919 }
06920
06921 static inline void
06922 validate_switches_from_spec (const char *spec)
06923 {
06924 const char *p = spec;
06925 char c;
06926 while ((c = *p++))
06927 if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
06928
06929 p = validate_switches (p + 1);
06930 }
06931
06932 static void
06933 validate_all_switches (void)
06934 {
06935 struct compiler *comp;
06936 struct spec_list *spec;
06937
06938 for (comp = compilers; comp->spec; comp++)
06939 validate_switches_from_spec (comp->spec);
06940
06941
06942 for (spec = specs; spec; spec = spec->next)
06943 validate_switches_from_spec (*spec->ptr_spec);
06944
06945 validate_switches_from_spec (link_command_spec);
06946 }
06947
06948
06949
06950
06951 static const char *
06952 validate_switches (const char *start)
06953 {
06954 const char *p = start;
06955 const char *atom;
06956 size_t len;
06957 int i;
06958 bool suffix = false;
06959 bool starred = false;
06960
06961 #define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
06962
06963 next_member:
06964 SKIP_WHITE ();
06965
06966 if (*p == '!')
06967 p++;
06968
06969 SKIP_WHITE ();
06970 if (*p == '.')
06971 suffix = true, p++;
06972
06973 atom = p;
06974 while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
06975 || *p == ',' || *p == '.' || *p == '@')
06976 p++;
06977 len = p - atom;
06978
06979 if (*p == '*')
06980 starred = true, p++;
06981
06982 SKIP_WHITE ();
06983
06984 if (!suffix)
06985 {
06986
06987 for (i = 0; i < n_switches; i++)
06988 if (!strncmp (switches[i].part1, atom, len)
06989 && (starred || switches[i].part1[len] == 0))
06990 switches[i].validated = 1;
06991 }
06992
06993 if (*p) p++;
06994 if (*p && (p[-1] == '|' || p[-1] == '&'))
06995 goto next_member;
06996
06997 if (*p && p[-1] == ':')
06998 {
06999 while (*p && *p != ';' && *p != '}')
07000 {
07001 if (*p == '%')
07002 {
07003 p++;
07004 if (*p == '{' || *p == '<')
07005 p = validate_switches (p+1);
07006 else if (p[0] == 'W' && p[1] == '{')
07007 p = validate_switches (p+2);
07008 }
07009 else
07010 p++;
07011 }
07012
07013 if (*p) p++;
07014 if (*p && p[-1] == ';')
07015 goto next_member;
07016 }
07017
07018 return p;
07019 #undef SKIP_WHITE
07020 }
07021
07022 struct mdswitchstr
07023 {
07024 const char *str;
07025 int len;
07026 };
07027
07028 static struct mdswitchstr *mdswitches;
07029 static int n_mdswitches;
07030
07031
07032
07033
07034 static int
07035 used_arg (const char *p, int len)
07036 {
07037 struct mswitchstr
07038 {
07039 const char *str;
07040 const char *replace;
07041 int len;
07042 int rep_len;
07043 };
07044
07045 static struct mswitchstr *mswitches;
07046 static int n_mswitches;
07047 int i, j;
07048
07049 if (!mswitches)
07050 {
07051 struct mswitchstr *matches;
07052 const char *q;
07053 int cnt = 0;
07054
07055
07056
07057 for (q = multilib_matches; *q != '\0'; q++)
07058 if (*q == ';')
07059 cnt++;
07060
07061 matches = alloca ((sizeof (struct mswitchstr)) * cnt);
07062 i = 0;
07063 q = multilib_matches;
07064 while (*q != '\0')
07065 {
07066 matches[i].str = q;
07067 while (*q != ' ')
07068 {
07069 if (*q == '\0')
07070 {
07071 invalid_matches:
07072 fatal ("multilib spec '%s' is invalid", multilib_matches);
07073 }
07074 q++;
07075 }
07076 matches[i].len = q - matches[i].str;
07077
07078 matches[i].replace = ++q;
07079 while (*q != ';' && *q != '\0')
07080 {
07081 if (*q == ' ')
07082 goto invalid_matches;
07083 q++;
07084 }
07085 matches[i].rep_len = q - matches[i].replace;
07086 i++;
07087 if (*q == ';')
07088 q++;
07089 }
07090
07091
07092
07093
07094
07095 mswitches
07096 = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
07097 for (i = 0; i < n_switches; i++)
07098 if (switches[i].live_cond != SWITCH_IGNORE)
07099 {
07100 int xlen = strlen (switches[i].part1);
07101 for (j = 0; j < cnt; j++)
07102 if (xlen == matches[j].len
07103 && ! strncmp (switches[i].part1, matches[j].str, xlen))
07104 {
07105 mswitches[n_mswitches].str = matches[j].replace;
07106 mswitches[n_mswitches].len = matches[j].rep_len;
07107 mswitches[n_mswitches].replace = (char *) 0;
07108 mswitches[n_mswitches].rep_len = 0;
07109 n_mswitches++;
07110 break;
07111 }
07112 }
07113
07114
07115
07116
07117 for (i = 0; i < n_mdswitches; i++)
07118 {
07119 const char *r;
07120
07121 for (q = multilib_options; *q != '\0'; q++)
07122 {
07123 while (*q == ' ')
07124 q++;
07125
07126 r = q;
07127 while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
07128 || strchr (" /", q[mdswitches[i].len]) == NULL)
07129 {
07130 while (*q != ' ' && *q != '/' && *q != '\0')
07131 q++;
07132 if (*q != '/')
07133 break;
07134 q++;
07135 }
07136
07137 if (*q != ' ' && *q != '\0')
07138 {
07139 while (*r != ' ' && *r != '\0')
07140 {
07141 q = r;
07142 while (*q != ' ' && *q != '/' && *q != '\0')
07143 q++;
07144
07145 if (used_arg (r, q - r))
07146 break;
07147
07148 if (*q != '/')
07149 {
07150 mswitches[n_mswitches].str = mdswitches[i].str;
07151 mswitches[n_mswitches].len = mdswitches[i].len;
07152 mswitches[n_mswitches].replace = (char *) 0;
07153 mswitches[n_mswitches].rep_len = 0;
07154 n_mswitches++;
07155 break;
07156 }
07157
07158 r = q + 1;
07159 }
07160 break;
07161 }
07162 }
07163 }
07164 }
07165
07166 for (i = 0; i < n_mswitches; i++)
07167 if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
07168 return 1;
07169
07170 return 0;
07171 }
07172
07173 static int
07174 default_arg (const char *p, int len)
07175 {
07176 int i;
07177
07178 for (i = 0; i < n_mdswitches; i++)
07179 if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
07180 return 1;
07181
07182 return 0;
07183 }
07184
07185
07186
07187
07188
07189
07190
07191
07192
07193
07194
07195
07196 static void
07197 set_multilib_dir (void)
07198 {
07199 const char *p;
07200 unsigned int this_path_len;
07201 const char *this_path, *this_arg;
07202 const char *start, *end;
07203 int not_arg;
07204 int ok, ndfltok, first;
07205
07206 n_mdswitches = 0;
07207 start = multilib_defaults;
07208 while (*start == ' ' || *start == '\t')
07209 start++;
07210 while (*start != '\0')
07211 {
07212 n_mdswitches++;
07213 while (*start != ' ' && *start != '\t' && *start != '\0')
07214 start++;
07215 while (*start == ' ' || *start == '\t')
07216 start++;
07217 }
07218
07219 if (n_mdswitches)
07220 {
07221 int i = 0;
07222
07223 mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches);
07224 for (start = multilib_defaults; *start != '\0'; start = end + 1)
07225 {
07226 while (*start == ' ' || *start == '\t')
07227 start++;
07228
07229 if (*start == '\0')
07230 break;
07231
07232 for (end = start + 1;
07233 *end != ' ' && *end != '\t' && *end != '\0'; end++)
07234 ;
07235
07236 obstack_grow (&multilib_obstack, start, end - start);
07237 obstack_1grow (&multilib_obstack, 0);
07238 mdswitches[i].str = XOBFINISH (&multilib_obstack, const char *);
07239 mdswitches[i++].len = end - start;
07240
07241 if (*end == '\0')
07242 break;
07243 }
07244 }
07245
07246 p = multilib_exclusions;
07247 while (*p != '\0')
07248 {
07249
07250 if (*p == '\n')
07251 {
07252 ++p;
07253 continue;
07254 }
07255
07256
07257 ok = 1;
07258 while (*p != ';')
07259 {
07260 if (*p == '\0')
07261 {
07262 invalid_exclusions:
07263 fatal ("multilib exclusions '%s' is invalid",
07264 multilib_exclusions);
07265 }
07266
07267 if (! ok)
07268 {
07269 ++p;
07270 continue;
07271 }
07272
07273 this_arg = p;
07274 while (*p != ' ' && *p != ';')
07275 {
07276 if (*p == '\0')
07277 goto invalid_exclusions;
07278 ++p;
07279 }
07280
07281 if (*this_arg != '!')
07282 not_arg = 0;
07283 else
07284 {
07285 not_arg = 1;
07286 ++this_arg;
07287 }
07288
07289 ok = used_arg (this_arg, p - this_arg);
07290 if (not_arg)
07291 ok = ! ok;
07292
07293 if (*p == ' ')
07294 ++p;
07295 }
07296
07297 if (ok)
07298 return;
07299
07300 ++p;
07301 }
07302
07303 first = 1;
07304 p = multilib_select;
07305 while (*p != '\0')
07306 {
07307
07308 if (*p == '\n')
07309 {
07310 ++p;
07311 continue;
07312 }
07313
07314
07315 this_path = p;
07316 while (*p != ' ')
07317 {
07318 if (*p == '\0')
07319 {
07320 invalid_select:
07321 fatal ("multilib select '%s' is invalid",
07322 multilib_select);
07323 }
07324 ++p;
07325 }
07326 this_path_len = p - this_path;
07327
07328
07329 ok = 1;
07330 ndfltok = 1;
07331 ++p;
07332 while (*p != ';')
07333 {
07334 if (*p == '\0')
07335 goto invalid_select;
07336
07337 if (! ok)
07338 {
07339 ++p;
07340 continue;
07341 }
07342
07343 this_arg = p;
07344 while (*p != ' ' && *p != ';')
07345 {
07346 if (*p == '\0')
07347 goto invalid_select;
07348 ++p;
07349 }
07350
07351 if (*this_arg != '!')
07352 not_arg = 0;
07353 else
07354 {
07355 not_arg = 1;
07356 ++this_arg;
07357 }
07358
07359
07360
07361
07362
07363
07364
07365
07366 ok = used_arg (this_arg, p - this_arg);
07367 if (not_arg)
07368 ok = ! ok;
07369
07370 if (! ok)
07371 ndfltok = 0;
07372
07373 if (default_arg (this_arg, p - this_arg))
07374 ok = 1;
07375
07376 if (*p == ' ')
07377 ++p;
07378 }
07379
07380 if (ok && first)
07381 {
07382 if (this_path_len != 1
07383 || this_path[0] != '.')
07384 {
07385 char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
07386 char *q;
07387
07388 strncpy (new_multilib_dir, this_path, this_path_len);
07389 new_multilib_dir[this_path_len] = '\0';
07390 q = strchr (new_multilib_dir, ':');
07391 if (q != NULL)
07392 *q = '\0';
07393 multilib_dir = new_multilib_dir;
07394 }
07395 first = 0;
07396 }
07397
07398 if (ndfltok)
07399 {
07400 const char *q = this_path, *end = this_path + this_path_len;
07401
07402 while (q < end && *q != ':')
07403 q++;
07404 if (q < end)
07405 {
07406 char *new_multilib_os_dir = XNEWVEC (char, end - q);
07407 memcpy (new_multilib_os_dir, q + 1, end - q - 1);
07408 new_multilib_os_dir[end - q - 1] = '\0';
07409 multilib_os_dir = new_multilib_os_dir;
07410 break;
07411 }
07412 }
07413
07414 ++p;
07415 }
07416
07417 if (multilib_dir == NULL && multilib_os_dir != NULL
07418 && strcmp (multilib_os_dir, ".") == 0)
07419 {
07420 free ((char *) multilib_os_dir);
07421 multilib_os_dir = NULL;
07422 }
07423 else if (multilib_dir != NULL && multilib_os_dir == NULL)
07424 multilib_os_dir = multilib_dir;
07425 }
07426
07427
07428
07429
07430
07431
07432
07433
07434
07435
07436
07437 static void
07438 print_multilib_info (void)
07439 {
07440 const char *p = multilib_select;
07441 const char *last_path = 0, *this_path;
07442 int skip;
07443 unsigned int last_path_len = 0;
07444
07445 while (*p != '\0')
07446 {
07447 skip = 0;
07448
07449 if (*p == '\n')
07450 {
07451 ++p;
07452 continue;
07453 }
07454
07455
07456 this_path = p;
07457 while (*p != ' ')
07458 {
07459 if (*p == '\0')
07460 {
07461 invalid_select:
07462 fatal ("multilib select '%s' is invalid", multilib_select);
07463 }
07464
07465 ++p;
07466 }
07467
07468
07469
07470
07471 if (this_path[0] == '.' && this_path[1] == ':')
07472 skip = 1;
07473
07474
07475
07476
07477 {
07478 const char *e = multilib_exclusions;
07479 const char *this_arg;
07480
07481 while (*e != '\0')
07482 {
07483 int m = 1;
07484
07485 if (*e == '\n')
07486 {
07487 ++e;
07488 continue;
07489 }
07490
07491
07492 while (*e != ';')
07493 {
07494 const char *q;
07495 int mp = 0;
07496
07497 if (*e == '\0')
07498 {
07499 invalid_exclusion:
07500 fatal ("multilib exclusion '%s' is invalid",
07501 multilib_exclusions);
07502 }
07503
07504 if (! m)
07505 {
07506 ++e;
07507 continue;
07508 }
07509
07510 this_arg = e;
07511
07512 while (*e != ' ' && *e != ';')
07513 {
07514 if (*e == '\0')
07515 goto invalid_exclusion;
07516 ++e;
07517 }
07518
07519 q = p + 1;
07520 while (*q != ';')
07521 {
07522 const char *arg;
07523 int len = e - this_arg;
07524
07525 if (*q == '\0')
07526 goto invalid_select;
07527
07528 arg = q;
07529
07530 while (*q != ' ' && *q != ';')
07531 {
07532 if (*q == '\0')
07533 goto invalid_select;
07534 ++q;
07535 }
07536
07537 if (! strncmp (arg, this_arg,
07538 (len < q - arg) ? q - arg : len)
07539 || default_arg (this_arg, e - this_arg))
07540 {
07541 mp = 1;
07542 break;
07543 }
07544
07545 if (*q == ' ')
07546 ++q;
07547 }
07548
07549 if (! mp)
07550 m = 0;
07551
07552 if (*e == ' ')
07553 ++e;
07554 }
07555
07556 if (m)
07557 {
07558 skip = 1;
07559 break;
07560 }
07561
07562 if (*e != '\0')
07563 ++e;
07564 }
07565 }
07566
07567 if (! skip)
07568 {
07569
07570 skip = (last_path != 0
07571 && (unsigned int) (p - this_path) == last_path_len
07572 && ! strncmp (last_path, this_path, last_path_len));
07573
07574 last_path = this_path;
07575 last_path_len = p - this_path;
07576 }
07577
07578
07579
07580
07581 if (! skip)
07582 {
07583 const char *q;
07584
07585 q = p + 1;
07586 while (*q != ';')
07587 {
07588 const char *arg;
07589
07590 if (*q == '\0')
07591 goto invalid_select;
07592
07593 if (*q == '!')
07594 arg = NULL;
07595 else
07596 arg = q;
07597
07598 while (*q != ' ' && *q != ';')
07599 {
07600 if (*q == '\0')
07601 goto invalid_select;
07602 ++q;
07603 }
07604
07605 if (arg != NULL
07606 && default_arg (arg, q - arg))
07607 {
07608 skip = 1;
07609 break;
07610 }
07611
07612 if (*q == ' ')
07613 ++q;
07614 }
07615 }
07616
07617 if (! skip)
07618 {
07619 const char *p1;
07620
07621 for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
07622 putchar (*p1);
07623 putchar (';');
07624 }
07625
07626 ++p;
07627 while (*p != ';')
07628 {
07629 int use_arg;
07630
07631 if (*p == '\0')
07632 goto invalid_select;
07633
07634 if (skip)
07635 {
07636 ++p;
07637 continue;
07638 }
07639
07640 use_arg = *p != '!';
07641
07642 if (use_arg)
07643 putchar ('@');
07644
07645 while (*p != ' ' && *p != ';')
07646 {
07647 if (*p == '\0')
07648 goto invalid_select;
07649 if (use_arg)
07650 putchar (*p);
07651 ++p;
07652 }
07653
07654 if (*p == ' ')
07655 ++p;
07656 }
07657
07658 if (! skip)
07659 {
07660
07661 if (multilib_extra && *multilib_extra)
07662 {
07663 int print_at = TRUE;
07664 const char *q;
07665
07666 for (q = multilib_extra; *q != '\0'; q++)
07667 {
07668 if (*q == ' ')
07669 print_at = TRUE;
07670 else
07671 {
07672 if (print_at)
07673 putchar ('@');
07674 putchar (*q);
07675 print_at = FALSE;
07676 }
07677 }
07678 }
07679
07680 putchar ('\n');
07681 }
07682
07683 ++p;
07684 }
07685 }
07686
07687
07688
07689
07690
07691
07692
07693
07694
07695 static const char *
07696 if_exists_spec_function (int argc, const char **argv)
07697 {
07698
07699 if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
07700 return argv[0];
07701
07702 return NULL;
07703 }
07704
07705
07706
07707
07708
07709
07710 static const char *
07711 if_exists_else_spec_function (int argc, const char **argv)
07712 {
07713
07714 if (argc != 2)
07715 return NULL;
07716
07717 if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
07718 return argv[0];
07719
07720 return argv[1];
07721 }
07722
07723
07724
07725
07726
07727
07728 static const char *
07729 replace_outfile_spec_function (int argc, const char **argv)
07730 {
07731 int i;
07732
07733 if (argc != 2)
07734 abort ();
07735
07736 for (i = 0; i < n_infiles; i++)
07737 {
07738 if (outfiles[i] && !strcmp (outfiles[i], argv[0]))
07739 outfiles[i] = xstrdup (argv[1]);
07740 }
07741 return NULL;
07742 }
07743
07744
07745
07746
07747
07748 static int
07749 compare_version_strings (const char *v1, const char *v2)
07750 {
07751 int rresult;
07752 regex_t r;
07753
07754 if (regcomp (&r, "^([1-9][0-9]*|0)(\\.([1-9][0-9]*|0))*$",
07755 REG_EXTENDED | REG_NOSUB) != 0)
07756 abort ();
07757 rresult = regexec (&r, v1, 0, NULL, 0);
07758 if (rresult == REG_NOMATCH)
07759 fatal ("invalid version number `%s'", v1);
07760 else if (rresult != 0)
07761 abort ();
07762 rresult = regexec (&r, v2, 0, NULL, 0);
07763 if (rresult == REG_NOMATCH)
07764 fatal ("invalid version number `%s'", v2);
07765 else if (rresult != 0)
07766 abort ();
07767
07768 return strverscmp (v1, v2);
07769 }
07770
07771
07772
07773
07774
07775
07776
07777
07778
07779
07780
07781
07782
07783
07784
07785
07786
07787
07788
07789
07790
07791
07792
07793
07794
07795
07796
07797 static const char *
07798 version_compare_spec_function (int argc, const char **argv)
07799 {
07800 int comp1, comp2;
07801 size_t switch_len;
07802 const char *switch_value = NULL;
07803 int nargs = 1, i;
07804 bool result;
07805
07806 if (argc < 3)
07807 fatal ("too few arguments to %%:version-compare");
07808 if (argv[0][0] == '\0')
07809 abort ();
07810 if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!')
07811 nargs = 2;
07812 if (argc != nargs + 3)
07813 fatal ("too many arguments to %%:version-compare");
07814
07815 switch_len = strlen (argv[nargs + 1]);
07816 for (i = 0; i < n_switches; i++)
07817 if (!strncmp (switches[i].part1, argv[nargs + 1], switch_len)
07818 && check_live_switch (i, switch_len))
07819 switch_value = switches[i].part1 + switch_len;
07820
07821 if (switch_value == NULL)
07822 comp1 = comp2 = -1;
07823 else
07824 {
07825 comp1 = compare_version_strings (switch_value, argv[1]);
07826 if (nargs == 2)
07827 comp2 = compare_version_strings (switch_value, argv[2]);
07828 else
07829 comp2 = -1;
07830 }
07831
07832 switch (argv[0][0] << 8 | argv[0][1])
07833 {
07834 case '>' << 8 | '=':
07835 result = comp1 >= 0;
07836 break;
07837 case '!' << 8 | '<':
07838 result = comp1 >= 0 || switch_value == NULL;
07839 break;
07840 case '<' << 8:
07841 result = comp1 < 0;
07842 break;
07843 case '!' << 8 | '>':
07844 result = comp1 < 0 || switch_value == NULL;
07845 break;
07846 case '>' << 8 | '<':
07847 result = comp1 >= 0 && comp2 < 0;
07848 break;
07849 case '<' << 8 | '>':
07850 result = comp1 < 0 || comp2 >= 0;
07851 break;
07852
07853 default:
07854 fatal ("unknown operator '%s' in %%:version-compare", argv[0]);
07855 }
07856 if (! result)
07857 return NULL;
07858
07859 return argv[nargs + 2];
07860 }
07861
07862
07863
07864
07865
07866
07867 static const char *
07868 include_spec_function (int argc, const char **argv)
07869 {
07870 char *file;
07871
07872 if (argc != 1)
07873 abort ();
07874
07875 file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
07876 read_specs (file ? file : argv[0], FALSE);
07877
07878 return NULL;
07879 }