aboutsummaryrefslogtreecommitdiff
path: root/gold/options.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/options.cc')
-rw-r--r--gold/options.cc282
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())
{