diff options
Diffstat (limited to 'gold/options.cc')
-rw-r--r-- | gold/options.cc | 282 |
1 files changed, 147 insertions, 135 deletions
diff --git a/gold/options.cc b/gold/options.cc index 08cbf2a..9a0b9f8 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -395,12 +395,13 @@ options::Command_line_options::options[] = NULL, TWO_DASHES, &General_options::set_stats), GENERAL_ARG('\0', "sysroot", N_("Set target system root directory"), N_("--sysroot DIR"), TWO_DASHES, &General_options::set_sysroot), - SPECIAL('T', "script", N_("Read linker script"), - N_("-T FILE, --script FILE"), TWO_DASHES, - &invoke_script), GENERAL_ARG('\0', "Ttext", N_("Set the address of the .text section"), N_("-Ttext ADDRESS"), ONE_DASH, &General_options::set_text_segment_address), + // This must come after -Ttext since it's a prefix of it. + SPECIAL('T', "script", N_("Read linker script"), + N_("-T FILE, --script FILE"), TWO_DASHES, + &invoke_script), GENERAL_NOARG('\0', "threads", N_("Run the linker multi-threaded"), NULL, TWO_DASHES, &General_options::set_threads), GENERAL_NOARG('\0', "no-threads", N_("Do not run the linker multi-threaded"), @@ -623,149 +624,160 @@ Command_line::Command_line() { } -// Process the command line options. +// Process the command line options. For process_one_option, +// i is the index of argv to process next, and the return value +// is the index of the next option to process (i+1 or i+2, or argc +// to indicate processing is done). no_more_options is set to true +// if (and when) "--" is seen as an option. -void -Command_line::process(int argc, char** argv) +int +Command_line::process_one_option(int argc, char** argv, int i, + bool* no_more_options) { const int options_size = options::Command_line_options::options_size; - const options::One_option* options = - options::Command_line_options::options; - bool no_more_options = false; - int i = 0; - while (i < argc) + const options::One_option* options = options::Command_line_options::options; + gold_assert(i < argc); + + if (argv[i][0] != '-' || *no_more_options) { - if (argv[i][0] != '-' || no_more_options) - { - this->add_file(argv[i], false); - ++i; - continue; - } + this->add_file(argv[i], false); + return i + 1; + } - // Option starting with '-'. - int dashes = 1; - if (argv[i][1] == '-') - { - dashes = 2; - if (argv[i][2] == '\0') - { - no_more_options = true; - continue; - } - } + // Option starting with '-'. + int dashes = 1; + if (argv[i][1] == '-') + { + dashes = 2; + if (argv[i][2] == '\0') + { + *no_more_options = true; + return i + 1; + } + } - // Look for a long option match. - char* opt = argv[i] + dashes; - char first = opt[0]; - int skiparg = 0; - char* arg = strchr(opt, '='); - bool argument_with_equals = arg != NULL; - if (arg != NULL) - { - *arg = '\0'; - ++arg; - } - else if (i + 1 < argc) - { - arg = argv[i + 1]; - skiparg = 1; - } + // Look for a long option match. + char* opt = argv[i] + dashes; + char first = opt[0]; + int skiparg = 0; + char* arg = strchr(opt, '='); + bool argument_with_equals = arg != NULL; + if (arg != NULL) + { + *arg = '\0'; + ++arg; + } + else if (i + 1 < argc) + { + arg = argv[i + 1]; + skiparg = 1; + } + int j; + for (j = 0; j < options_size; ++j) + { + if (options[j].long_option != NULL + && (dashes == 2 + || (options[j].dash + != options::One_option::EXACTLY_TWO_DASHES)) + && first == options[j].long_option[0] + && strcmp(opt, options[j].long_option) == 0) + { + if (options[j].special) + { + // Restore the '=' we clobbered above. + if (arg != NULL && skiparg == 0) + arg[-1] = '='; + i += options[j].special(argc - i, argv + i, opt, true, this); + } + else + { + if (!options[j].takes_argument()) + { + if (argument_with_equals) + this->usage(_("unexpected argument"), argv[i]); + arg = NULL; + skiparg = 0; + } + else + { + if (arg == NULL) + this->usage(_("missing argument"), argv[i]); + } + this->apply_option(options[j], arg); + i += skiparg + 1; + } + break; + } + } + if (j < options_size) + return i; + + // If we saw two dashes, we needed to have seen a long option. + if (dashes == 2) + this->usage(_("unknown option"), argv[i]); + + // Look for a short option match. There may be more than one + // short option in a given argument. + bool done = false; + char* s = argv[i] + 1; + ++i; + while (*s != '\0' && !done) + { + char opt = *s; int j; for (j = 0; j < options_size; ++j) - { - if (options[j].long_option != NULL - && (dashes == 2 - || (options[j].dash - != options::One_option::EXACTLY_TWO_DASHES)) - && first == options[j].long_option[0] - && strcmp(opt, options[j].long_option) == 0) - { - if (options[j].special) - { - // Restore the '=' we clobbered above. - if (arg != NULL && skiparg == 0) - arg[-1] = '='; - i += options[j].special(argc - i, argv + i, opt, true, this); - } - else - { - if (!options[j].takes_argument()) - { - if (argument_with_equals) - this->usage(_("unexpected argument"), argv[i]); - arg = NULL; - skiparg = 0; - } - else - { - if (arg == NULL) - this->usage(_("missing argument"), argv[i]); - } - this->apply_option(options[j], arg); - i += skiparg + 1; - } - break; - } - } - if (j < options_size) - continue; - - // If we saw two dashes, we need to see a long option. - if (dashes == 2) - this->usage(_("unknown option"), argv[i]); - - // Look for a short option match. There may be more than one - // short option in a given argument. - bool done = false; - char* s = argv[i] + 1; - ++i; - while (*s != '\0' && !done) - { - char opt = *s; - int j; - for (j = 0; j < options_size; ++j) - { - if (options[j].short_option == opt) - { - if (options[j].special) - { - // Undo the argument skip done above. - --i; - i += options[j].special(argc - i, argv + i, s, false, - this); - done = true; - } - else - { - arg = NULL; - if (options[j].takes_argument()) - { - if (s[1] != '\0') - { - arg = s + 1; - done = true; - } - else if (i < argc) - { - arg = argv[i]; - ++i; - } - else - this->usage(_("missing argument"), opt); - } - this->apply_option(options[j], arg); - } - break; - } - } + { + if (options[j].short_option == opt) + { + if (options[j].special) + { + // Undo the argument skip done above. + --i; + i += options[j].special(argc - i, argv + i, s, false, + this); + done = true; + } + else + { + arg = NULL; + if (options[j].takes_argument()) + { + if (s[1] != '\0') + { + arg = s + 1; + done = true; + } + else if (i < argc) + { + arg = argv[i]; + ++i; + } + else + this->usage(_("missing argument"), opt); + } + this->apply_option(options[j], arg); + } + break; + } + } + + if (j >= options_size) + this->usage(_("unknown option"), *s); + + ++s; + } + return i; +} - if (j >= options_size) - this->usage(_("unknown option"), *s); - ++s; - } - } +void +Command_line::process(int argc, char** argv) +{ + bool no_more_options = false; + int i = 0; + while (i < argc) + i = process_one_option(argc, argv, i, &no_more_options); if (this->inputs_.in_group()) { |