1/* Command line option handling.
2 Copyright (C) 2006-2024 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#define INCLUDE_STRING
21#include "config.h"
22#include "system.h"
23#include "intl.h"
24#include "coretypes.h"
25#include "opts.h"
26#include "options.h"
27#include "diagnostic.h"
28#include "spellcheck.h"
29#include "opts-jobserver.h"
30
31static void prune_options (struct cl_decoded_option **, unsigned int *);
32
33/* An option that is undocumented, that takes a joined argument, and
34 that doesn't fit any of the classes of uses (language/common,
35 driver, target) is assumed to be a prefix used to catch
36 e.g. negated options, and stop them from being further shortened to
37 a prefix that could use the negated option as an argument. For
38 example, we want -gno-statement-frontiers to be taken as a negation
39 of -gstatement-frontiers, but without catching the gno- prefix and
40 signaling it's to be used for option remapping, it would end up
41 backtracked to g with no-statemnet-frontiers as the debug level. */
42
43static bool
44remapping_prefix_p (const struct cl_option *opt)
45{
46 return opt->flags & CL_UNDOCUMENTED
47 && opt->flags & CL_JOINED
48 && !(opt->flags & (CL_DRIVER | CL_TARGET | CL_COMMON | CL_LANG_ALL));
49}
50
51/* Perform a binary search to find which option the command-line INPUT
52 matches. Returns its index in the option array, and
53 OPT_SPECIAL_unknown on failure.
54
55 This routine is quite subtle. A normal binary search is not good
56 enough because some options can be suffixed with an argument, and
57 multiple sub-matches can occur, e.g. input of "-pedantic" matching
58 the initial substring of "-pedantic-errors".
59
60 A more complicated example is -gstabs. It should match "-g" with
61 an argument of "stabs". Suppose, however, that the number and list
62 of switches are such that the binary search tests "-gen-decls"
63 before having tested "-g". This doesn't match, and as "-gen-decls"
64 is less than "-gstabs", it will become the lower bound of the
65 binary search range, and "-g" will never be seen. To resolve this
66 issue, 'optc-gen.awk' makes "-gen-decls" point, via the back_chain member,
67 to "-g" so that failed searches that end between "-gen-decls" and
68 the lexicographically subsequent switch know to go back and see if
69 "-g" causes a match (which it does in this example).
70
71 This search is done in such a way that the longest match for the
72 front end in question wins. If there is no match for the current
73 front end, the longest match for a different front end is returned
74 (or N_OPTS if none) and the caller emits an error message. */
75size_t
76find_opt (const char *input, unsigned int lang_mask)
77{
78 size_t mn, mn_orig, mx, md, opt_len;
79 size_t match_wrong_lang;
80 int comp;
81
82 mn = 0;
83 mx = cl_options_count;
84
85 /* Find mn such this lexicographical inequality holds:
86 cl_options[mn] <= input < cl_options[mn + 1]. */
87 while (mx - mn > 1)
88 {
89 md = (mn + mx) / 2;
90 opt_len = cl_options[md].opt_len;
91 comp = strncmp (s1: input, s2: cl_options[md].opt_text + 1, n: opt_len);
92
93 if (comp < 0)
94 mx = md;
95 else
96 mn = md;
97 }
98
99 mn_orig = mn;
100
101 /* This is the switch that is the best match but for a different
102 front end, or OPT_SPECIAL_unknown if there is no match at all. */
103 match_wrong_lang = OPT_SPECIAL_unknown;
104
105 /* Backtrace the chain of possible matches, returning the longest
106 one, if any, that fits best. With current GCC switches, this
107 loop executes at most twice. */
108 do
109 {
110 const struct cl_option *opt = &cl_options[mn];
111
112 /* Is the input either an exact match or a prefix that takes a
113 joined argument? */
114 if (!strncmp (s1: input, s2: opt->opt_text + 1, n: opt->opt_len)
115 && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
116 {
117 /* If language is OK, return it. */
118 if (opt->flags & lang_mask)
119 return mn;
120
121 if (remapping_prefix_p (opt))
122 return OPT_SPECIAL_unknown;
123
124 /* If we haven't remembered a prior match, remember this
125 one. Any prior match is necessarily better. */
126 if (match_wrong_lang == OPT_SPECIAL_unknown)
127 match_wrong_lang = mn;
128 }
129
130 /* Try the next possibility. This is cl_options_count if there
131 are no more. */
132 mn = opt->back_chain;
133 }
134 while (mn != cl_options_count);
135
136 if (match_wrong_lang == OPT_SPECIAL_unknown && input[0] == '-')
137 {
138 /* Long options, starting "--", may be abbreviated if the
139 abbreviation is unambiguous. This only applies to options
140 not taking a joined argument, and abbreviations of "--option"
141 are permitted even if there is a variant "--option=". */
142 size_t mnc = mn_orig + 1;
143 size_t cmp_len = strlen (s: input);
144 while (mnc < cl_options_count
145 && strncmp (s1: input, s2: cl_options[mnc].opt_text + 1, n: cmp_len) == 0)
146 {
147 /* Option matching this abbreviation. OK if it is the first
148 match and that does not take a joined argument, or the
149 second match, taking a joined argument and with only '='
150 added to the first match; otherwise considered
151 ambiguous. */
152 if (mnc == mn_orig + 1
153 && !(cl_options[mnc].flags & CL_JOINED))
154 match_wrong_lang = mnc;
155 else if (mnc == mn_orig + 2
156 && match_wrong_lang == mn_orig + 1
157 && (cl_options[mnc].flags & CL_JOINED)
158 && (cl_options[mnc].opt_len
159 == cl_options[mn_orig + 1].opt_len + 1)
160 && strncmp (s1: cl_options[mnc].opt_text + 1,
161 s2: cl_options[mn_orig + 1].opt_text + 1,
162 n: cl_options[mn_orig + 1].opt_len) == 0)
163 ; /* OK, as long as there are no more matches. */
164 else
165 return OPT_SPECIAL_unknown;
166 mnc++;
167 }
168 }
169
170 /* Return the best wrong match, or OPT_SPECIAL_unknown if none. */
171 return match_wrong_lang;
172}
173
174/* If ARG is a non-negative decimal or hexadecimal integer representable
175 in HOST_WIDE_INT return its value, otherwise return -1. If ERR is not
176 null set *ERR to zero on success or to EINVAL or to the value of errno
177 otherwise. */
178
179HOST_WIDE_INT
180integral_argument (const char *arg, int *err, bool byte_size_suffix)
181{
182 if (!err)
183 err = &errno;
184
185 if (!ISDIGIT (*arg))
186 {
187 *err = EINVAL;
188 return -1;
189 }
190
191 *err = 0;
192 errno = 0;
193
194 char *end = NULL;
195 unsigned HOST_WIDE_INT unit = 1;
196 unsigned HOST_WIDE_INT value = strtoull (nptr: arg, endptr: &end, base: 10);
197
198 /* If the value is too large to be represented use the maximum
199 representable value that strtoull sets VALUE to (setting
200 errno to ERANGE). */
201
202 if (end && *end)
203 {
204 if (!byte_size_suffix)
205 {
206 errno = 0;
207 value = strtoull (nptr: arg, endptr: &end, base: 0);
208 if (*end)
209 {
210 if (errno)
211 *err = errno;
212 else
213 *err = EINVAL;
214 return -1;
215 }
216
217 return value;
218 }
219
220 /* Numeric option arguments are at most INT_MAX. Make it
221 possible to specify a larger value by accepting common
222 suffixes. */
223 if (!strcmp (s1: end, s2: "kB"))
224 unit = 1000;
225 else if (!strcasecmp (s1: end, s2: "KiB") || !strcmp (s1: end, s2: "KB"))
226 unit = 1024;
227 else if (!strcmp (s1: end, s2: "MB"))
228 unit = HOST_WIDE_INT_UC (1000) * 1000;
229 else if (!strcasecmp (s1: end, s2: "MiB"))
230 unit = HOST_WIDE_INT_UC (1024) * 1024;
231 else if (!strcasecmp (s1: end, s2: "GB"))
232 unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000;
233 else if (!strcasecmp (s1: end, s2: "GiB"))
234 unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024;
235 else if (!strcasecmp (s1: end, s2: "TB"))
236 unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000;
237 else if (!strcasecmp (s1: end, s2: "TiB"))
238 unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024;
239 else if (!strcasecmp (s1: end, s2: "PB"))
240 unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000;
241 else if (!strcasecmp (s1: end, s2: "PiB"))
242 unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024;
243 else if (!strcasecmp (s1: end, s2: "EB"))
244 unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000
245 * 1000;
246 else if (!strcasecmp (s1: end, s2: "EiB"))
247 unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024
248 * 1024;
249 else
250 {
251 /* This could mean an unknown suffix or a bad prefix, like
252 "+-1". */
253 *err = EINVAL;
254 return -1;
255 }
256 }
257
258 if (unit)
259 {
260 unsigned HOST_WIDE_INT prod = value * unit;
261 value = prod < value ? HOST_WIDE_INT_M1U : prod;
262 }
263
264 return value;
265}
266
267/* Return whether OPTION is OK for the language given by
268 LANG_MASK. */
269static bool
270option_ok_for_language (const struct cl_option *option,
271 unsigned int lang_mask)
272{
273 if (!(option->flags & lang_mask))
274 return false;
275 else if ((option->flags & CL_TARGET)
276 && (option->flags & (CL_LANG_ALL | CL_DRIVER))
277 && !(option->flags & (lang_mask & ~CL_COMMON & ~CL_TARGET)))
278 /* Complain for target flag language mismatches if any languages
279 are specified. */
280 return false;
281 return true;
282}
283
284/* Return whether ENUM_ARG is OK for the language given by
285 LANG_MASK. */
286
287static bool
288enum_arg_ok_for_language (const struct cl_enum_arg *enum_arg,
289 unsigned int lang_mask)
290{
291 return (lang_mask & CL_DRIVER) || !(enum_arg->flags & CL_ENUM_DRIVER_ONLY);
292}
293
294/* Look up ARG in ENUM_ARGS for language LANG_MASK, returning the cl_enum_arg
295 index and storing the value in *VALUE if found, and returning -1 without
296 modifying *VALUE if not found. */
297
298static int
299enum_arg_to_value (const struct cl_enum_arg *enum_args,
300 const char *arg, size_t len, HOST_WIDE_INT *value,
301 unsigned int lang_mask)
302{
303 unsigned int i;
304
305 for (i = 0; enum_args[i].arg != NULL; i++)
306 if ((len
307 ? (strncmp (s1: arg, s2: enum_args[i].arg, n: len) == 0
308 && enum_args[i].arg[len] == '\0')
309 : strcmp (s1: arg, s2: enum_args[i].arg) == 0)
310 && enum_arg_ok_for_language (enum_arg: &enum_args[i], lang_mask))
311 {
312 *value = enum_args[i].value;
313 return i;
314 }
315
316 return -1;
317}
318
319/* Look up ARG in the enum used by option OPT_INDEX for language
320 LANG_MASK, returning true and storing the value in *VALUE if found,
321 and returning false without modifying *VALUE if not found. */
322
323bool
324opt_enum_arg_to_value (size_t opt_index, const char *arg,
325 int *value, unsigned int lang_mask)
326{
327 const struct cl_option *option = &cl_options[opt_index];
328
329 gcc_assert (option->var_type == CLVC_ENUM);
330
331 HOST_WIDE_INT wideval;
332 if (enum_arg_to_value (enum_args: cl_enums[option->var_enum].values, arg, len: 0,
333 value: &wideval, lang_mask) >= 0)
334 {
335 *value = wideval;
336 return true;
337 }
338
339 return false;
340}
341
342/* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the
343 corresponding string in *ARGP, returning true if the found string
344 was marked as canonical, false otherwise. If VALUE is not found
345 (which may be the case for uninitialized values if the relevant
346 option has not been passed), set *ARGP to NULL and return
347 false. */
348
349bool
350enum_value_to_arg (const struct cl_enum_arg *enum_args,
351 const char **argp, int value, unsigned int lang_mask)
352{
353 unsigned int i;
354
355 for (i = 0; enum_args[i].arg != NULL; i++)
356 if (enum_args[i].value == value
357 && (enum_args[i].flags & CL_ENUM_CANONICAL)
358 && enum_arg_ok_for_language (enum_arg: &enum_args[i], lang_mask))
359 {
360 *argp = enum_args[i].arg;
361 return true;
362 }
363
364 for (i = 0; enum_args[i].arg != NULL; i++)
365 if (enum_args[i].value == value
366 && enum_arg_ok_for_language (enum_arg: &enum_args[i], lang_mask))
367 {
368 *argp = enum_args[i].arg;
369 return false;
370 }
371
372 *argp = NULL;
373 return false;
374}
375
376/* Fill in the canonical option part of *DECODED with an option
377 described by OPT_INDEX, ARG and VALUE. */
378
379static void
380generate_canonical_option (size_t opt_index, const char *arg,
381 HOST_WIDE_INT value,
382 struct cl_decoded_option *decoded)
383{
384 const struct cl_option *option = &cl_options[opt_index];
385 const char *opt_text = option->opt_text;
386
387 if (value == 0
388 && !option->cl_reject_negative
389 && (opt_text[1] == 'W' || opt_text[1] == 'f'
390 || opt_text[1] == 'g' || opt_text[1] == 'm'))
391 {
392 char *t = XOBNEWVEC (&opts_obstack, char, option->opt_len + 5);
393 t[0] = '-';
394 t[1] = opt_text[1];
395 t[2] = 'n';
396 t[3] = 'o';
397 t[4] = '-';
398 memcpy (dest: t + 5, src: opt_text + 2, n: option->opt_len);
399 opt_text = t;
400 }
401
402 decoded->canonical_option[2] = NULL;
403 decoded->canonical_option[3] = NULL;
404
405 if (arg)
406 {
407 if ((option->flags & CL_SEPARATE)
408 && !option->cl_separate_alias)
409 {
410 decoded->canonical_option[0] = opt_text;
411 decoded->canonical_option[1] = arg;
412 decoded->canonical_option_num_elements = 2;
413 }
414 else
415 {
416 gcc_assert (option->flags & CL_JOINED);
417 decoded->canonical_option[0] = opts_concat (first: opt_text, arg, NULL);
418 decoded->canonical_option[1] = NULL;
419 decoded->canonical_option_num_elements = 1;
420 }
421 }
422 else
423 {
424 decoded->canonical_option[0] = opt_text;
425 decoded->canonical_option[1] = NULL;
426 decoded->canonical_option_num_elements = 1;
427 }
428}
429
430/* Structure describing mappings from options on the command line to
431 options to look up with find_opt. */
432struct option_map
433{
434 /* Prefix of the option on the command line. */
435 const char *opt0;
436 /* If two argv elements are considered to be merged into one option,
437 prefix for the second element, otherwise NULL. */
438 const char *opt1;
439 /* The new prefix to map to. */
440 const char *new_prefix;
441 /* Whether at least one character is needed following opt1 or opt0
442 for this mapping to be used. (--optimize= is valid for -O, but
443 --warn- is not valid for -W.) */
444 bool another_char_needed;
445 /* Whether the original option is a negated form of the option
446 resulting from this map. */
447 bool negated;
448};
449static const struct option_map option_map[] =
450 {
451 { .opt0: "-Wno-", NULL, .new_prefix: "-W", .another_char_needed: false, .negated: true },
452 { .opt0: "-fno-", NULL, .new_prefix: "-f", .another_char_needed: false, .negated: true },
453 { .opt0: "-gno-", NULL, .new_prefix: "-g", .another_char_needed: false, .negated: true },
454 { .opt0: "-mno-", NULL, .new_prefix: "-m", .another_char_needed: false, .negated: true },
455 { .opt0: "--debug=", NULL, .new_prefix: "-g", .another_char_needed: false, .negated: false },
456 { .opt0: "--machine-", NULL, .new_prefix: "-m", .another_char_needed: true, .negated: false },
457 { .opt0: "--machine-no-", NULL, .new_prefix: "-m", .another_char_needed: false, .negated: true },
458 { .opt0: "--machine=", NULL, .new_prefix: "-m", .another_char_needed: false, .negated: false },
459 { .opt0: "--machine=no-", NULL, .new_prefix: "-m", .another_char_needed: false, .negated: true },
460 { .opt0: "--machine", .opt1: "", .new_prefix: "-m", .another_char_needed: false, .negated: false },
461 { .opt0: "--machine", .opt1: "no-", .new_prefix: "-m", .another_char_needed: false, .negated: true },
462 { .opt0: "--optimize=", NULL, .new_prefix: "-O", .another_char_needed: false, .negated: false },
463 { .opt0: "--std=", NULL, .new_prefix: "-std=", .another_char_needed: false, .negated: false },
464 { .opt0: "--std", .opt1: "", .new_prefix: "-std=", .another_char_needed: false, .negated: false },
465 { .opt0: "--warn-", NULL, .new_prefix: "-W", .another_char_needed: true, .negated: false },
466 { .opt0: "--warn-no-", NULL, .new_prefix: "-W", .another_char_needed: false, .negated: true },
467 { .opt0: "--", NULL, .new_prefix: "-f", .another_char_needed: true, .negated: false },
468 { .opt0: "--no-", NULL, .new_prefix: "-f", .another_char_needed: false, .negated: true }
469 };
470
471/* Given buffer P of size SZ, look for a prefix within OPTION_MAP;
472 if found, return the prefix and write the new prefix to *OUT_NEW_PREFIX.
473 Otherwise return nullptr. */
474
475const char *
476get_option_prefix_remapping (const char *p, size_t sz,
477 const char **out_new_prefix)
478{
479 for (unsigned i = 0; i < ARRAY_SIZE (option_map); i++)
480 {
481 const char * const old_prefix = option_map[i].opt0;
482 const size_t old_prefix_len = strlen (s: old_prefix);
483 if (old_prefix_len <= sz
484 && !memcmp (s1: p, s2: old_prefix, n: old_prefix_len))
485 {
486 *out_new_prefix = option_map[i].new_prefix;
487 return old_prefix;
488 }
489 }
490 return nullptr;
491}
492
493/* Helper function for gcc.cc's driver::suggest_option, for populating the
494 vec of suggestions for misspelled options.
495
496 option_map above provides various prefixes for spelling command-line
497 options, which decode_cmdline_option uses to map spellings of options
498 to specific options. We want to do the reverse: to find all the ways
499 that a user could validly spell an option.
500
501 Given valid OPT_TEXT (with a leading dash) for OPTION, add it and all
502 of its valid variant spellings to CANDIDATES, each without a leading
503 dash.
504
505 For example, given "-Wabi-tag", the following are added to CANDIDATES:
506 "Wabi-tag"
507 "Wno-abi-tag"
508 "-warn-abi-tag"
509 "-warn-no-abi-tag".
510
511 The added strings must be freed using free. */
512
513void
514add_misspelling_candidates (auto_vec<char *> *candidates,
515 const struct cl_option *option,
516 const char *opt_text)
517{
518 gcc_assert (candidates);
519 gcc_assert (option);
520 gcc_assert (opt_text);
521 if (remapping_prefix_p (opt: option))
522 return;
523 candidates->safe_push (obj: xstrdup (opt_text + 1));
524 for (unsigned i = 0; i < ARRAY_SIZE (option_map); i++)
525 {
526 const char *opt0 = option_map[i].opt0;
527 const char *new_prefix = option_map[i].new_prefix;
528 size_t new_prefix_len = strlen (s: new_prefix);
529
530 if (option->cl_reject_negative && option_map[i].negated)
531 continue;
532
533 if (strncmp (s1: opt_text, s2: new_prefix, n: new_prefix_len) == 0)
534 {
535 char *alternative = concat (opt0 + 1, opt_text + new_prefix_len,
536 NULL);
537 candidates->safe_push (obj: alternative);
538 }
539 }
540
541 /* For all params (e.g. --param=key=value),
542 include also '--param key=value'. */
543 const char *prefix = "--param=";
544 if (strstr (haystack: opt_text, needle: prefix) == opt_text)
545 {
546 char *param = xstrdup (opt_text + 1);
547 gcc_assert (param[6] == '=');
548 param[6] = ' ';
549 candidates->safe_push (obj: param);
550 }
551}
552
553/* Decode the switch beginning at ARGV for the language indicated by
554 LANG_MASK (including CL_COMMON and CL_TARGET if applicable), into
555 the structure *DECODED. Returns the number of switches
556 consumed. */
557
558static unsigned int
559decode_cmdline_option (const char *const *argv, unsigned int lang_mask,
560 struct cl_decoded_option *decoded)
561{
562 size_t opt_index;
563 const char *arg = 0;
564 HOST_WIDE_INT value = 1, mask = 0;
565 unsigned int result = 1, i, extra_args, separate_args = 0;
566 int adjust_len = 0;
567 size_t total_len;
568 char *p;
569 const struct cl_option *option;
570 int errors = 0;
571 const char *warn_message = NULL;
572 bool separate_arg_flag;
573 bool joined_arg_flag;
574 bool have_separate_arg = false;
575
576 extra_args = 0;
577
578 const char *opt_value = argv[0] + 1;
579 opt_index = find_opt (input: opt_value, lang_mask);
580 i = 0;
581 while (opt_index == OPT_SPECIAL_unknown
582 && i < ARRAY_SIZE (option_map))
583 {
584 const char *opt0 = option_map[i].opt0;
585 const char *opt1 = option_map[i].opt1;
586 const char *new_prefix = option_map[i].new_prefix;
587 bool another_char_needed = option_map[i].another_char_needed;
588 size_t opt0_len = strlen (s: opt0);
589 size_t opt1_len = (opt1 == NULL ? 0 : strlen (s: opt1));
590 size_t optn_len = (opt1 == NULL ? opt0_len : opt1_len);
591 size_t new_prefix_len = strlen (s: new_prefix);
592
593 extra_args = (opt1 == NULL ? 0 : 1);
594 value = !option_map[i].negated;
595
596 if (strncmp (s1: argv[0], s2: opt0, n: opt0_len) == 0
597 && (opt1 == NULL
598 || (argv[1] != NULL && strncmp (s1: argv[1], s2: opt1, n: opt1_len) == 0))
599 && (!another_char_needed
600 || argv[extra_args][optn_len] != 0))
601 {
602 size_t arglen = strlen (s: argv[extra_args]);
603 char *dup;
604
605 adjust_len = (int) optn_len - (int) new_prefix_len;
606 dup = XNEWVEC (char, arglen + 1 - adjust_len);
607 memcpy (dest: dup, src: new_prefix, n: new_prefix_len);
608 memcpy (dest: dup + new_prefix_len, src: argv[extra_args] + optn_len,
609 n: arglen - optn_len + 1);
610 opt_index = find_opt (input: dup + 1, lang_mask);
611 free (ptr: dup);
612 }
613 i++;
614 }
615
616 if (opt_index == OPT_SPECIAL_unknown)
617 {
618 arg = argv[0];
619 extra_args = 0;
620 value = 1;
621 goto done;
622 }
623
624 option = &cl_options[opt_index];
625
626 /* Reject negative form of switches that don't take negatives as
627 unrecognized. */
628 if (!value && option->cl_reject_negative)
629 {
630 opt_index = OPT_SPECIAL_unknown;
631 errors |= CL_ERR_NEGATIVE;
632 arg = argv[0];
633 goto done;
634 }
635
636 /* Clear the initial value for size options (it will be overwritten
637 later based on the Init(value) specification in the opt file. */
638 if (option->var_type == CLVC_SIZE)
639 value = 0;
640
641 result = extra_args + 1;
642 warn_message = option->warn_message;
643
644 /* Check to see if the option is disabled for this configuration. */
645 if (option->cl_disabled)
646 errors |= CL_ERR_DISABLED;
647
648 /* Determine whether there may be a separate argument based on
649 whether this option is being processed for the driver, and, if
650 so, how many such arguments. */
651 separate_arg_flag = ((option->flags & CL_SEPARATE)
652 && !(option->cl_no_driver_arg
653 && (lang_mask & CL_DRIVER)));
654 separate_args = (separate_arg_flag
655 ? option->cl_separate_nargs + 1
656 : 0);
657 joined_arg_flag = (option->flags & CL_JOINED) != 0;
658
659 /* Sort out any argument the switch takes. */
660 if (joined_arg_flag)
661 {
662 /* Have arg point to the original switch. This is because
663 some code, such as disable_builtin_function, expects its
664 argument to be persistent until the program exits. */
665 arg = argv[extra_args] + cl_options[opt_index].opt_len + 1 + adjust_len;
666
667 if (*arg == '\0' && !option->cl_missing_ok)
668 {
669 if (separate_arg_flag)
670 {
671 arg = argv[extra_args + 1];
672 result = extra_args + 2;
673 if (arg == NULL)
674 result = extra_args + 1;
675 else
676 have_separate_arg = true;
677 }
678 else
679 /* Missing argument. */
680 arg = NULL;
681 }
682 }
683 else if (separate_arg_flag)
684 {
685 arg = argv[extra_args + 1];
686 for (i = 0; i < separate_args; i++)
687 if (argv[extra_args + 1 + i] == NULL)
688 {
689 errors |= CL_ERR_MISSING_ARG;
690 break;
691 }
692 result = extra_args + 1 + i;
693 if (arg != NULL)
694 have_separate_arg = true;
695 }
696
697 if (arg == NULL && (separate_arg_flag || joined_arg_flag))
698 errors |= CL_ERR_MISSING_ARG;
699
700 /* Is this option an alias (or an ignored option, marked as an alias
701 of OPT_SPECIAL_ignore)? */
702 if (option->alias_target != N_OPTS
703 && (!option->cl_separate_alias || have_separate_arg))
704 {
705 size_t new_opt_index = option->alias_target;
706
707 if (new_opt_index == OPT_SPECIAL_ignore
708 || new_opt_index == OPT_SPECIAL_warn_removed)
709 {
710 gcc_assert (option->alias_arg == NULL);
711 gcc_assert (option->neg_alias_arg == NULL);
712 opt_index = new_opt_index;
713 arg = NULL;
714 }
715 else
716 {
717 const struct cl_option *new_option = &cl_options[new_opt_index];
718
719 /* The new option must not be an alias itself. */
720 gcc_assert (new_option->alias_target == N_OPTS
721 || new_option->cl_separate_alias);
722
723 if (option->neg_alias_arg)
724 {
725 gcc_assert (option->alias_arg != NULL);
726 gcc_assert (arg == NULL);
727 gcc_assert (!option->cl_negative_alias);
728 if (value)
729 arg = option->alias_arg;
730 else
731 arg = option->neg_alias_arg;
732 value = 1;
733 }
734 else if (option->alias_arg)
735 {
736 gcc_assert (value == 1);
737 gcc_assert (arg == NULL);
738 gcc_assert (!option->cl_negative_alias);
739 arg = option->alias_arg;
740 }
741
742 if (option->cl_negative_alias)
743 value = !value;
744
745 opt_index = new_opt_index;
746 option = new_option;
747
748 if (value == 0)
749 gcc_assert (!option->cl_reject_negative);
750
751 /* Recompute what arguments are allowed. */
752 separate_arg_flag = ((option->flags & CL_SEPARATE)
753 && !(option->cl_no_driver_arg
754 && (lang_mask & CL_DRIVER)));
755 joined_arg_flag = (option->flags & CL_JOINED) != 0;
756
757 if (separate_args > 1 || option->cl_separate_nargs)
758 gcc_assert (separate_args
759 == (unsigned int) option->cl_separate_nargs + 1);
760
761 if (!(errors & CL_ERR_MISSING_ARG))
762 {
763 if (separate_arg_flag || joined_arg_flag)
764 {
765 if (option->cl_missing_ok && arg == NULL)
766 arg = "";
767 gcc_assert (arg != NULL);
768 }
769 else
770 gcc_assert (arg == NULL);
771 }
772
773 /* Recheck for warnings and disabled options. */
774 if (option->warn_message)
775 {
776 gcc_assert (warn_message == NULL);
777 warn_message = option->warn_message;
778 }
779 if (option->cl_disabled)
780 errors |= CL_ERR_DISABLED;
781 }
782 }
783
784 /* Check if this is a switch for a different front end. */
785 if (!option_ok_for_language (option, lang_mask))
786 errors |= CL_ERR_WRONG_LANG;
787 else if (strcmp (s1: option->opt_text, s2: "-Werror=") == 0
788 && strchr (s: opt_value, c: ',') == NULL)
789 {
790 /* Verify that -Werror argument is a valid warning
791 for a language. */
792 char *werror_arg = xstrdup (opt_value + 6);
793 werror_arg[0] = 'W';
794
795 size_t warning_index = find_opt (input: werror_arg, lang_mask);
796 free (ptr: werror_arg);
797 if (warning_index != OPT_SPECIAL_unknown)
798 {
799 const struct cl_option *warning_option
800 = &cl_options[warning_index];
801 if (!option_ok_for_language (option: warning_option, lang_mask))
802 errors |= CL_ERR_WRONG_LANG;
803 }
804 }
805
806 /* Convert the argument to lowercase if appropriate. */
807 if (arg && option->cl_tolower)
808 {
809 size_t j;
810 size_t len = strlen (s: arg);
811 char *arg_lower = XOBNEWVEC (&opts_obstack, char, len + 1);
812
813 for (j = 0; j < len; j++)
814 arg_lower[j] = TOLOWER ((unsigned char) arg[j]);
815 arg_lower[len] = 0;
816 arg = arg_lower;
817 }
818
819 /* If the switch takes an integer argument, convert it. */
820 if (arg && (option->cl_uinteger || option->cl_host_wide_int))
821 {
822 int error = 0;
823 value = *arg ? integral_argument (arg, err: &error, byte_size_suffix: option->cl_byte_size) : 0;
824 if (error)
825 errors |= CL_ERR_UINT_ARG;
826
827 /* Reject value out of a range. */
828 if (option->range_max != -1
829 && (value < option->range_min || value > option->range_max))
830 errors |= CL_ERR_INT_RANGE_ARG;
831 }
832
833 /* If the switch takes an enumerated argument, convert it. */
834 if (arg && (option->var_type == CLVC_ENUM))
835 {
836 const struct cl_enum *e = &cl_enums[option->var_enum];
837
838 gcc_assert (option->var_value != CLEV_NORMAL || value == 1);
839 if (option->var_value != CLEV_NORMAL)
840 {
841 const char *p = arg;
842 HOST_WIDE_INT sum_value = 0;
843 unsigned HOST_WIDE_INT used_sets = 0;
844 do
845 {
846 const char *q = strchr (s: p, c: ',');
847 HOST_WIDE_INT this_value = 0;
848 if (q && q == p)
849 {
850 errors |= CL_ERR_ENUM_SET_ARG;
851 break;
852 }
853 int idx = enum_arg_to_value (enum_args: e->values, arg: p, len: q ? q - p : 0,
854 value: &this_value, lang_mask);
855 if (idx < 0)
856 {
857 errors |= CL_ERR_ENUM_SET_ARG;
858 break;
859 }
860
861 HOST_WIDE_INT this_mask = 0;
862 if (option->var_value == CLEV_SET)
863 {
864 unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT;
865 gcc_checking_assert (set >= 1
866 && set <= HOST_BITS_PER_WIDE_INT);
867 if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0)
868 {
869 errors |= CL_ERR_ENUM_SET_ARG;
870 break;
871 }
872 used_sets |= HOST_WIDE_INT_1U << (set - 1);
873
874 for (int i = 0; e->values[i].arg != NULL; i++)
875 if (set == (e->values[i].flags >> CL_ENUM_SET_SHIFT))
876 this_mask |= e->values[i].value;
877 }
878 else
879 {
880 gcc_assert (option->var_value == CLEV_BITSET
881 && ((e->values[idx].flags >> CL_ENUM_SET_SHIFT)
882 == 0));
883 this_mask = this_value;
884 }
885
886 sum_value |= this_value;
887 mask |= this_mask;
888 if (q == NULL)
889 break;
890 p = q + 1;
891 }
892 while (1);
893 if (value == 1)
894 value = sum_value;
895 else
896 gcc_checking_assert (value == 0);
897 }
898 else if (enum_arg_to_value (enum_args: e->values, arg, len: 0, value: &value, lang_mask) >= 0)
899 {
900 const char *carg = NULL;
901
902 if (enum_value_to_arg (enum_args: e->values, argp: &carg, value, lang_mask))
903 arg = carg;
904 gcc_assert (carg != NULL);
905 }
906 else
907 errors |= CL_ERR_ENUM_ARG;
908 }
909
910 done:
911 decoded->opt_index = opt_index;
912 decoded->arg = arg;
913 decoded->value = value;
914 decoded->mask = mask;
915 decoded->errors = errors;
916 decoded->warn_message = warn_message;
917
918 if (opt_index == OPT_SPECIAL_unknown)
919 gcc_assert (result == 1);
920
921 gcc_assert (result >= 1 && result <= ARRAY_SIZE (decoded->canonical_option));
922 decoded->canonical_option_num_elements = result;
923 total_len = 0;
924 for (i = 0; i < ARRAY_SIZE (decoded->canonical_option); i++)
925 {
926 if (i < result)
927 {
928 size_t len;
929 if (opt_index == OPT_SPECIAL_unknown)
930 decoded->canonical_option[i] = argv[i];
931 else
932 decoded->canonical_option[i] = NULL;
933 len = strlen (s: argv[i]);
934 /* If the argument is an empty string, we will print it as "" in
935 orig_option_with_args_text. */
936 total_len += (len != 0 ? len : 2) + 1;
937 }
938 else
939 decoded->canonical_option[i] = NULL;
940 }
941 if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore
942 && opt_index != OPT_SPECIAL_warn_removed)
943 {
944 generate_canonical_option (opt_index, arg, value, decoded);
945 if (separate_args > 1)
946 {
947 for (i = 0; i < separate_args; i++)
948 {
949 if (argv[extra_args + 1 + i] == NULL)
950 break;
951 else
952 decoded->canonical_option[1 + i] = argv[extra_args + 1 + i];
953 }
954 gcc_assert (result == 1 + i);
955 decoded->canonical_option_num_elements = result;
956 }
957 }
958 decoded->orig_option_with_args_text
959 = p = XOBNEWVEC (&opts_obstack, char, total_len);
960 for (i = 0; i < result; i++)
961 {
962 size_t len = strlen (s: argv[i]);
963
964 /* Print the empty string verbally. */
965 if (len == 0)
966 {
967 *p++ = '"';
968 *p++ = '"';
969 }
970 else
971 memcpy (dest: p, src: argv[i], n: len);
972 p += len;
973 if (i == result - 1)
974 *p++ = 0;
975 else
976 *p++ = ' ';
977 }
978
979 return result;
980}
981
982/* Obstack for option strings. */
983
984struct obstack opts_obstack;
985
986/* Like libiberty concat, but allocate using opts_obstack. */
987
988char *
989opts_concat (const char *first, ...)
990{
991 char *newstr, *end;
992 size_t length = 0;
993 const char *arg;
994 va_list ap;
995
996 /* First compute the size of the result and get sufficient memory. */
997 va_start (ap, first);
998 for (arg = first; arg; arg = va_arg (ap, const char *))
999 length += strlen (s: arg);
1000 newstr = XOBNEWVEC (&opts_obstack, char, length + 1);
1001 va_end (ap);
1002
1003 /* Now copy the individual pieces to the result string. */
1004 va_start (ap, first);
1005 for (arg = first, end = newstr; arg; arg = va_arg (ap, const char *))
1006 {
1007 length = strlen (s: arg);
1008 memcpy (dest: end, src: arg, n: length);
1009 end += length;
1010 }
1011 *end = '\0';
1012 va_end (ap);
1013 return newstr;
1014}
1015
1016/* Decode command-line options (ARGC and ARGV being the arguments of
1017 main) into an array, setting *DECODED_OPTIONS to a pointer to that
1018 array and *DECODED_OPTIONS_COUNT to the number of entries in the
1019 array. The first entry in the array is always one for the program
1020 name (OPT_SPECIAL_program_name). LANG_MASK indicates the language
1021 flags applicable for decoding (including CL_COMMON and CL_TARGET if
1022 those options should be considered applicable). Do not produce any
1023 diagnostics or set state outside of these variables. */
1024
1025void
1026decode_cmdline_options_to_array (unsigned int argc, const char **argv,
1027 unsigned int lang_mask,
1028 struct cl_decoded_option **decoded_options,
1029 unsigned int *decoded_options_count)
1030{
1031 unsigned int n, i;
1032 struct cl_decoded_option *opt_array;
1033 unsigned int num_decoded_options;
1034
1035 int opt_array_len = argc;
1036 opt_array = XNEWVEC (struct cl_decoded_option, opt_array_len);
1037
1038 opt_array[0].opt_index = OPT_SPECIAL_program_name;
1039 opt_array[0].warn_message = NULL;
1040 opt_array[0].arg = argv[0];
1041 opt_array[0].orig_option_with_args_text = argv[0];
1042 opt_array[0].canonical_option_num_elements = 1;
1043 opt_array[0].canonical_option[0] = argv[0];
1044 opt_array[0].canonical_option[1] = NULL;
1045 opt_array[0].canonical_option[2] = NULL;
1046 opt_array[0].canonical_option[3] = NULL;
1047 opt_array[0].value = 1;
1048 opt_array[0].mask = 0;
1049 opt_array[0].errors = 0;
1050 num_decoded_options = 1;
1051
1052 for (i = 1; i < argc; i += n)
1053 {
1054 const char *opt = argv[i];
1055
1056 /* Interpret "-" or a non-switch as a file name. */
1057 if (opt[0] != '-' || opt[1] == '\0')
1058 {
1059 generate_option_input_file (file: opt, decoded: &opt_array[num_decoded_options]);
1060 num_decoded_options++;
1061 n = 1;
1062 continue;
1063 }
1064
1065 /* Interpret "--param" "key=name" as "--param=key=name". */
1066 const char *needle = "--param";
1067 if (i + 1 < argc && strcmp (s1: opt, s2: needle) == 0)
1068 {
1069 const char *replacement
1070 = opts_concat (first: needle, "=", argv[i + 1], NULL);
1071 argv[++i] = replacement;
1072 }
1073
1074 /* Expand -fdiagnostics-plain-output to its constituents. This needs
1075 to happen here so that prune_options can handle -fdiagnostics-color
1076 specially. */
1077 if (!strcmp (s1: opt, s2: "-fdiagnostics-plain-output"))
1078 {
1079 /* If you have changed the default diagnostics output, and this new
1080 output is not appropriately "plain" (e.g., the change needs to be
1081 undone in order for the testsuite to work properly), then please do
1082 the following:
1083 1. Add the necessary option to undo the new behavior to
1084 the array below.
1085 2. Update the documentation for -fdiagnostics-plain-output
1086 in invoke.texi. */
1087 const char *const expanded_args[] = {
1088 "-fno-diagnostics-show-caret",
1089 "-fno-diagnostics-show-line-numbers",
1090 "-fdiagnostics-color=never",
1091 "-fdiagnostics-urls=never",
1092 "-fdiagnostics-path-format=separate-events",
1093 "-fdiagnostics-text-art-charset=none"
1094 };
1095 const int num_expanded = ARRAY_SIZE (expanded_args);
1096 opt_array_len += num_expanded - 1;
1097 opt_array = XRESIZEVEC (struct cl_decoded_option,
1098 opt_array, opt_array_len);
1099 for (int j = 0, nj; j < num_expanded; j += nj)
1100 {
1101 nj = decode_cmdline_option (argv: expanded_args + j, lang_mask,
1102 decoded: &opt_array[num_decoded_options]);
1103 num_decoded_options++;
1104 }
1105
1106 n = 1;
1107 continue;
1108 }
1109
1110 n = decode_cmdline_option (argv: argv + i, lang_mask,
1111 decoded: &opt_array[num_decoded_options]);
1112 num_decoded_options++;
1113 }
1114
1115 *decoded_options = opt_array;
1116 *decoded_options_count = num_decoded_options;
1117 prune_options (decoded_options, decoded_options_count);
1118}
1119
1120/* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the
1121 next one is the same as ORIG_NEXT_OPT_IDX. */
1122
1123static bool
1124cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx)
1125{
1126 /* An option can be canceled by the same option or an option with
1127 Negative. */
1128 if (cl_options [next_opt_idx].neg_index == opt_idx)
1129 return true;
1130
1131 if (cl_options [next_opt_idx].neg_index != orig_next_opt_idx)
1132 return cancel_option (opt_idx, next_opt_idx: cl_options [next_opt_idx].neg_index,
1133 orig_next_opt_idx);
1134
1135 return false;
1136}
1137
1138/* Filter out options canceled by the ones after them, and related
1139 rearrangement. */
1140
1141static void
1142prune_options (struct cl_decoded_option **decoded_options,
1143 unsigned int *decoded_options_count)
1144{
1145 unsigned int old_decoded_options_count = *decoded_options_count;
1146 struct cl_decoded_option *old_decoded_options = *decoded_options;
1147 unsigned int new_decoded_options_count;
1148 struct cl_decoded_option *new_decoded_options
1149 = XNEWVEC (struct cl_decoded_option, old_decoded_options_count);
1150 unsigned int i;
1151 const struct cl_option *option;
1152 unsigned int options_to_prepend = 0;
1153 unsigned int Wcomplain_wrong_lang_idx = 0;
1154 unsigned int fdiagnostics_color_idx = 0;
1155
1156 /* Remove arguments which are negated by others after them. */
1157 new_decoded_options_count = 0;
1158 for (i = 0; i < old_decoded_options_count; i++)
1159 {
1160 unsigned int j, opt_idx, next_opt_idx;
1161
1162 if (old_decoded_options[i].errors & ~CL_ERR_WRONG_LANG)
1163 goto keep;
1164
1165 opt_idx = old_decoded_options[i].opt_index;
1166 switch (opt_idx)
1167 {
1168 case OPT_SPECIAL_unknown:
1169 case OPT_SPECIAL_ignore:
1170 case OPT_SPECIAL_warn_removed:
1171 case OPT_SPECIAL_program_name:
1172 case OPT_SPECIAL_input_file:
1173 goto keep;
1174
1175 /* Do not handle the following yet, just remember the last one. */
1176 case OPT_Wcomplain_wrong_lang:
1177 gcc_checking_assert (i != 0);
1178 if (Wcomplain_wrong_lang_idx == 0)
1179 ++options_to_prepend;
1180 Wcomplain_wrong_lang_idx = i;
1181 continue;
1182 case OPT_fdiagnostics_color_:
1183 gcc_checking_assert (i != 0);
1184 if (fdiagnostics_color_idx == 0)
1185 ++options_to_prepend;
1186 fdiagnostics_color_idx = i;
1187 continue;
1188
1189 default:
1190 gcc_assert (opt_idx < cl_options_count);
1191 option = &cl_options[opt_idx];
1192 if (option->neg_index < 0)
1193 goto keep;
1194
1195 /* Skip joined switches. */
1196 if ((option->flags & CL_JOINED)
1197 && (!option->cl_reject_negative
1198 || (unsigned int) option->neg_index != opt_idx))
1199 goto keep;
1200
1201 for (j = i + 1; j < old_decoded_options_count; j++)
1202 {
1203 if (old_decoded_options[j].errors & ~CL_ERR_WRONG_LANG)
1204 continue;
1205 next_opt_idx = old_decoded_options[j].opt_index;
1206 if (next_opt_idx >= cl_options_count)
1207 continue;
1208 if (cl_options[next_opt_idx].neg_index < 0)
1209 continue;
1210 if ((cl_options[next_opt_idx].flags & CL_JOINED)
1211 && (!cl_options[next_opt_idx].cl_reject_negative
1212 || ((unsigned int) cl_options[next_opt_idx].neg_index
1213 != next_opt_idx)))
1214 continue;
1215 if (cancel_option (opt_idx, next_opt_idx, orig_next_opt_idx: next_opt_idx))
1216 break;
1217 }
1218 if (j == old_decoded_options_count)
1219 {
1220keep:
1221 new_decoded_options[new_decoded_options_count]
1222 = old_decoded_options[i];
1223 new_decoded_options_count++;
1224 }
1225 break;
1226 }
1227 }
1228
1229 /* For those not yet handled, put (only) the last at a front position after
1230 'argv[0]', so they can take effect immediately. */
1231 if (options_to_prepend)
1232 {
1233 const unsigned int argv_0 = 1;
1234 memmove (dest: new_decoded_options + argv_0 + options_to_prepend,
1235 src: new_decoded_options + argv_0,
1236 n: sizeof (struct cl_decoded_option)
1237 * (new_decoded_options_count - argv_0));
1238 unsigned int options_prepended = 0;
1239 if (Wcomplain_wrong_lang_idx != 0)
1240 {
1241 new_decoded_options[argv_0 + options_prepended++]
1242 = old_decoded_options[Wcomplain_wrong_lang_idx];
1243 new_decoded_options_count++;
1244 }
1245 if (fdiagnostics_color_idx != 0)
1246 {
1247 new_decoded_options[argv_0 + options_prepended++]
1248 = old_decoded_options[fdiagnostics_color_idx];
1249 new_decoded_options_count++;
1250 }
1251 gcc_checking_assert (options_to_prepend == options_prepended);
1252 }
1253
1254 free (ptr: old_decoded_options);
1255 new_decoded_options = XRESIZEVEC (struct cl_decoded_option,
1256 new_decoded_options,
1257 new_decoded_options_count);
1258 *decoded_options = new_decoded_options;
1259 *decoded_options_count = new_decoded_options_count;
1260}
1261
1262/* Handle option DECODED for the language indicated by LANG_MASK,
1263 using the handlers in HANDLERS and setting fields in OPTS and
1264 OPTS_SET. KIND is the diagnostic_t if this is a diagnostics
1265 option, DK_UNSPECIFIED otherwise, and LOC is the location of the
1266 option for options from the source file, UNKNOWN_LOCATION
1267 otherwise. GENERATED_P is true for an option generated as part of
1268 processing another option or otherwise generated internally, false
1269 for one explicitly passed by the user. control_warning_option
1270 generated options are considered explicitly passed by the user.
1271 Returns false if the switch was invalid. DC is the diagnostic
1272 context for options affecting diagnostics state, or NULL. */
1273
1274static bool
1275handle_option (struct gcc_options *opts,
1276 struct gcc_options *opts_set,
1277 const struct cl_decoded_option *decoded,
1278 unsigned int lang_mask, int kind, location_t loc,
1279 const struct cl_option_handlers *handlers,
1280 bool generated_p, diagnostic_context *dc)
1281{
1282 size_t opt_index = decoded->opt_index;
1283 const char *arg = decoded->arg;
1284 HOST_WIDE_INT value = decoded->value;
1285 HOST_WIDE_INT mask = decoded->mask;
1286 const struct cl_option *option = &cl_options[opt_index];
1287 void *flag_var = option_flag_var (opt_index, opts);
1288 size_t i;
1289
1290 if (flag_var)
1291 set_option (opts, opts_set: (generated_p ? NULL : opts_set),
1292 opt_index, value, arg, kind, loc, dc, mask);
1293
1294 for (i = 0; i < handlers->num_handlers; i++)
1295 if (option->flags & handlers->handlers[i].mask)
1296 {
1297 if (!handlers->handlers[i].handler (opts, opts_set, decoded,
1298 lang_mask, kind, loc,
1299 handlers, dc,
1300 handlers->target_option_override_hook))
1301 return false;
1302 }
1303
1304 return true;
1305}
1306
1307/* Like handle_option, but OPT_INDEX, ARG and VALUE describe the
1308 option instead of DECODED. This is used for callbacks when one
1309 option implies another instead of an option being decoded from the
1310 command line. */
1311
1312bool
1313handle_generated_option (struct gcc_options *opts,
1314 struct gcc_options *opts_set,
1315 size_t opt_index, const char *arg, HOST_WIDE_INT value,
1316 unsigned int lang_mask, int kind, location_t loc,
1317 const struct cl_option_handlers *handlers,
1318 bool generated_p, diagnostic_context *dc)
1319{
1320 struct cl_decoded_option decoded;
1321
1322 generate_option (opt_index, arg, value, lang_mask, decoded: &decoded);
1323 return handle_option (opts, opts_set, decoded: &decoded, lang_mask, kind, loc,
1324 handlers, generated_p, dc);
1325}
1326
1327/* Fill in *DECODED with an option described by OPT_INDEX, ARG and
1328 VALUE for a front end using LANG_MASK. This is used when the
1329 compiler generates options internally. */
1330
1331void
1332generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value,
1333 unsigned int lang_mask, struct cl_decoded_option *decoded)
1334{
1335 const struct cl_option *option = &cl_options[opt_index];
1336
1337 decoded->opt_index = opt_index;
1338 decoded->warn_message = NULL;
1339 decoded->arg = arg;
1340 decoded->value = value;
1341 decoded->mask = 0;
1342 decoded->errors = (option_ok_for_language (option, lang_mask)
1343 ? 0
1344 : CL_ERR_WRONG_LANG);
1345
1346 generate_canonical_option (opt_index, arg, value, decoded);
1347 switch (decoded->canonical_option_num_elements)
1348 {
1349 case 1:
1350 decoded->orig_option_with_args_text = decoded->canonical_option[0];
1351 break;
1352
1353 case 2:
1354 decoded->orig_option_with_args_text
1355 = opts_concat (first: decoded->canonical_option[0], " ",
1356 decoded->canonical_option[1], NULL);
1357 break;
1358
1359 default:
1360 gcc_unreachable ();
1361 }
1362}
1363
1364/* Fill in *DECODED with an option for input file FILE. */
1365
1366void
1367generate_option_input_file (const char *file,
1368 struct cl_decoded_option *decoded)
1369{
1370 decoded->opt_index = OPT_SPECIAL_input_file;
1371 decoded->warn_message = NULL;
1372 decoded->arg = file;
1373 decoded->orig_option_with_args_text = file;
1374 decoded->canonical_option_num_elements = 1;
1375 decoded->canonical_option[0] = file;
1376 decoded->canonical_option[1] = NULL;
1377 decoded->canonical_option[2] = NULL;
1378 decoded->canonical_option[3] = NULL;
1379 decoded->value = 1;
1380 decoded->mask = 0;
1381 decoded->errors = 0;
1382}
1383
1384/* Helper function for listing valid choices and hint for misspelled
1385 value. CANDIDATES is a vector containing all valid strings,
1386 STR is set to a heap allocated string that contains all those
1387 strings concatenated, separated by spaces, and the return value
1388 is the closest string from those to ARG, or NULL if nothing is
1389 close enough. Callers should XDELETEVEC (STR) after using it
1390 to avoid memory leaks. */
1391
1392const char *
1393candidates_list_and_hint (const char *arg, char *&str,
1394 const auto_vec <const char *> &candidates)
1395{
1396 size_t len = 0;
1397 int i;
1398 const char *candidate;
1399 char *p;
1400
1401 gcc_assert (!candidates.is_empty ());
1402
1403 FOR_EACH_VEC_ELT (candidates, i, candidate)
1404 len += strlen (s: candidate) + 1;
1405
1406 str = p = XNEWVEC (char, len);
1407 FOR_EACH_VEC_ELT (candidates, i, candidate)
1408 {
1409 len = strlen (s: candidate);
1410 memcpy (dest: p, src: candidate, n: len);
1411 p[len] = ' ';
1412 p += len + 1;
1413 }
1414 p[-1] = '\0';
1415 return find_closest_string (target: arg, candidates: &candidates);
1416}
1417
1418/* Perform diagnostics for read_cmdline_option and control_warning_option
1419 functions. Returns true if an error has been diagnosed.
1420 LOC and LANG_MASK arguments like in read_cmdline_option.
1421 OPTION is the option to report diagnostics for, OPT the name
1422 of the option as text, ARG the argument of the option (for joined
1423 options), ERRORS is bitmask of CL_ERR_* values. */
1424
1425static bool
1426cmdline_handle_error (location_t loc, const struct cl_option *option,
1427 const char *opt, const char *arg, int errors,
1428 unsigned int lang_mask)
1429{
1430 if (errors & CL_ERR_DISABLED)
1431 {
1432 error_at (loc, "command-line option %qs"
1433 " is not supported by this configuration", opt);
1434 return true;
1435 }
1436
1437 if (errors & CL_ERR_MISSING_ARG)
1438 {
1439 if (option->missing_argument_error)
1440 error_at (loc, option->missing_argument_error, opt);
1441 else
1442 error_at (loc, "missing argument to %qs", opt);
1443 return true;
1444 }
1445
1446 if (errors & CL_ERR_UINT_ARG)
1447 {
1448 if (option->cl_byte_size)
1449 error_at (loc, "argument to %qs should be a non-negative integer "
1450 "optionally followed by a size unit",
1451 option->opt_text);
1452 else
1453 error_at (loc, "argument to %qs should be a non-negative integer",
1454 option->opt_text);
1455 return true;
1456 }
1457
1458 if (errors & CL_ERR_INT_RANGE_ARG)
1459 {
1460 error_at (loc, "argument to %qs is not between %d and %d",
1461 option->opt_text, option->range_min, option->range_max);
1462 return true;
1463 }
1464
1465 if (errors & CL_ERR_ENUM_SET_ARG)
1466 {
1467 const struct cl_enum *e = &cl_enums[option->var_enum];
1468 const char *p = arg;
1469 unsigned HOST_WIDE_INT used_sets = 0;
1470 const char *second_opt = NULL;
1471 size_t second_opt_len = 0;
1472 errors = 0;
1473 do
1474 {
1475 const char *q = strchr (s: p, c: ',');
1476 HOST_WIDE_INT this_value = 0;
1477 if (q && q == p)
1478 {
1479 arg = "";
1480 errors = CL_ERR_ENUM_ARG;
1481 break;
1482 }
1483 int idx = enum_arg_to_value (enum_args: e->values, arg: p, len: q ? q - p : 0,
1484 value: &this_value, lang_mask);
1485 if (idx < 0)
1486 {
1487 if (q == NULL)
1488 q = strchr (s: p, c: '\0');
1489 char *narg = XALLOCAVEC (char, (q - p) + 1);
1490 memcpy (dest: narg, src: p, n: q - p);
1491 narg[q - p] = '\0';
1492 arg = narg;
1493 errors = CL_ERR_ENUM_ARG;
1494 break;
1495 }
1496
1497 if (option->var_value == CLEV_BITSET)
1498 {
1499 if (q == NULL)
1500 break;
1501 p = q + 1;
1502 continue;
1503 }
1504
1505 unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT;
1506 gcc_checking_assert (set >= 1 && set <= HOST_BITS_PER_WIDE_INT);
1507 if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0)
1508 {
1509 if (q == NULL)
1510 q = strchr (s: p, c: '\0');
1511 if (second_opt == NULL)
1512 {
1513 used_sets = HOST_WIDE_INT_1U << (set - 1);
1514 second_opt = p;
1515 second_opt_len = q - p;
1516 p = arg;
1517 continue;
1518 }
1519 char *args = XALLOCAVEC (char, (q - p) + 1 + second_opt_len + 1);
1520 memcpy (dest: args, src: p, n: q - p);
1521 args[q - p] = '\0';
1522 memcpy (dest: args + (q - p) + 1, src: second_opt, n: second_opt_len);
1523 args[(q - p) + 1 + second_opt_len] = '\0';
1524 error_at (loc, "invalid argument in option %qs", opt);
1525 if (strcmp (s1: args, s2: args + (q - p) + 1) == 0)
1526 inform (loc, "%qs specified multiple times in the same option",
1527 args);
1528 else
1529 inform (loc, "%qs is mutually exclusive with %qs and cannot be"
1530 " specified together", args, args + (q - p) + 1);
1531 return true;
1532 }
1533 used_sets |= HOST_WIDE_INT_1U << (set - 1);
1534 if (q == NULL)
1535 break;
1536 p = q + 1;
1537 }
1538 while (1);
1539 }
1540
1541 if (errors & CL_ERR_ENUM_ARG)
1542 {
1543 const struct cl_enum *e = &cl_enums[option->var_enum];
1544 unsigned int i;
1545 char *s;
1546
1547 auto_diagnostic_group d;
1548 if (e->unknown_error)
1549 error_at (loc, e->unknown_error, arg);
1550 else
1551 error_at (loc, "unrecognized argument in option %qs", opt);
1552
1553 auto_vec <const char *> candidates;
1554 for (i = 0; e->values[i].arg != NULL; i++)
1555 {
1556 if (!enum_arg_ok_for_language (enum_arg: &e->values[i], lang_mask))
1557 continue;
1558 candidates.safe_push (obj: e->values[i].arg);
1559 }
1560 const char *hint = candidates_list_and_hint (arg, str&: s, candidates);
1561 if (hint)
1562 inform (loc, "valid arguments to %qs are: %s; did you mean %qs?",
1563 option->opt_text, s, hint);
1564 else
1565 inform (loc, "valid arguments to %qs are: %s", option->opt_text, s);
1566 XDELETEVEC (s);
1567
1568 return true;
1569 }
1570
1571 return false;
1572}
1573
1574/* Handle the switch DECODED (location LOC) for the language indicated
1575 by LANG_MASK, using the handlers in *HANDLERS and setting fields in
1576 OPTS and OPTS_SET and using diagnostic context DC (if not NULL) for
1577 diagnostic options. */
1578
1579void
1580read_cmdline_option (struct gcc_options *opts,
1581 struct gcc_options *opts_set,
1582 struct cl_decoded_option *decoded,
1583 location_t loc,
1584 unsigned int lang_mask,
1585 const struct cl_option_handlers *handlers,
1586 diagnostic_context *dc)
1587{
1588 const struct cl_option *option;
1589 const char *opt = decoded->orig_option_with_args_text;
1590
1591 if (decoded->warn_message)
1592 warning_at (loc, 0, decoded->warn_message, opt);
1593
1594 if (decoded->opt_index == OPT_SPECIAL_unknown)
1595 {
1596 if (handlers->unknown_option_callback (decoded))
1597 error_at (loc, "unrecognized command-line option %qs", decoded->arg);
1598 return;
1599 }
1600
1601 if (decoded->opt_index == OPT_SPECIAL_ignore)
1602 return;
1603
1604 if (decoded->opt_index == OPT_SPECIAL_warn_removed)
1605 {
1606 /* Warn only about positive ignored options. */
1607 if (decoded->value)
1608 warning_at (loc, 0, "switch %qs is no longer supported", opt);
1609 return;
1610 }
1611
1612 option = &cl_options[decoded->opt_index];
1613
1614 if (decoded->errors
1615 && cmdline_handle_error (loc, option, opt, arg: decoded->arg,
1616 errors: decoded->errors, lang_mask))
1617 return;
1618
1619 if (decoded->errors & CL_ERR_WRONG_LANG)
1620 {
1621 handlers->wrong_lang_callback (decoded, lang_mask);
1622 return;
1623 }
1624
1625 gcc_assert (!decoded->errors);
1626
1627 if (!handle_option (opts, opts_set, decoded, lang_mask, kind: DK_UNSPECIFIED,
1628 loc, handlers, generated_p: false, dc))
1629 error_at (loc, "unrecognized command-line option %qs", opt);
1630}
1631
1632/* Set any field in OPTS, and OPTS_SET if not NULL, for option
1633 OPT_INDEX according to VALUE and ARG, diagnostic kind KIND,
1634 location LOC, using diagnostic context DC if not NULL for
1635 diagnostic classification. */
1636
1637void
1638set_option (struct gcc_options *opts, struct gcc_options *opts_set,
1639 int opt_index, HOST_WIDE_INT value, const char *arg, int kind,
1640 location_t loc, diagnostic_context *dc,
1641 HOST_WIDE_INT mask /* = 0 */)
1642{
1643 const struct cl_option *option = &cl_options[opt_index];
1644 void *flag_var = option_flag_var (opt_index, opts);
1645 void *set_flag_var = NULL;
1646
1647 if (!flag_var)
1648 return;
1649
1650 if ((diagnostic_t) kind != DK_UNSPECIFIED && dc != NULL)
1651 diagnostic_classify_diagnostic (context: dc, optidx: opt_index, kind: (diagnostic_t) kind, where: loc);
1652
1653 if (opts_set != NULL)
1654 set_flag_var = option_flag_var (opt_index, opts: opts_set);
1655
1656 switch (option->var_type)
1657 {
1658 case CLVC_INTEGER:
1659 if (option->cl_host_wide_int)
1660 {
1661 *(HOST_WIDE_INT *) flag_var = value;
1662 if (set_flag_var)
1663 *(HOST_WIDE_INT *) set_flag_var = 1;
1664 }
1665 else
1666 {
1667 if (value > INT_MAX)
1668 error_at (loc, "argument to %qs is bigger than %d",
1669 option->opt_text, INT_MAX);
1670 else
1671 {
1672 *(int *) flag_var = value;
1673 if (set_flag_var)
1674 *(int *) set_flag_var = 1;
1675 }
1676 }
1677
1678 break;
1679
1680 case CLVC_SIZE:
1681 if (option->cl_host_wide_int)
1682 {
1683 *(HOST_WIDE_INT *) flag_var = value;
1684 if (set_flag_var)
1685 *(HOST_WIDE_INT *) set_flag_var = value;
1686 }
1687 else
1688 {
1689 *(int *) flag_var = value;
1690 if (set_flag_var)
1691 *(int *) set_flag_var = value;
1692 }
1693
1694 break;
1695
1696 case CLVC_EQUAL:
1697 if (option->cl_host_wide_int)
1698 {
1699 *(HOST_WIDE_INT *) flag_var = (value
1700 ? option->var_value
1701 : !option->var_value);
1702 if (set_flag_var)
1703 *(HOST_WIDE_INT *) set_flag_var = 1;
1704 }
1705 else
1706 {
1707 *(int *) flag_var = (value
1708 ? option->var_value
1709 : !option->var_value);
1710 if (set_flag_var)
1711 *(int *) set_flag_var = 1;
1712 }
1713 break;
1714
1715 case CLVC_BIT_CLEAR:
1716 case CLVC_BIT_SET:
1717 if ((value != 0) == (option->var_type == CLVC_BIT_SET))
1718 {
1719 if (option->cl_host_wide_int)
1720 *(HOST_WIDE_INT *) flag_var |= option->var_value;
1721 else
1722 *(int *) flag_var |= option->var_value;
1723 }
1724 else
1725 {
1726 if (option->cl_host_wide_int)
1727 *(HOST_WIDE_INT *) flag_var &= ~option->var_value;
1728 else
1729 *(int *) flag_var &= ~option->var_value;
1730 }
1731 if (set_flag_var)
1732 {
1733 if (option->cl_host_wide_int)
1734 *(HOST_WIDE_INT *) set_flag_var |= option->var_value;
1735 else
1736 *(int *) set_flag_var |= option->var_value;
1737 }
1738 break;
1739
1740 case CLVC_STRING:
1741 *(const char **) flag_var = arg;
1742 if (set_flag_var)
1743 *(const char **) set_flag_var = "";
1744 break;
1745
1746 case CLVC_ENUM:
1747 {
1748 const struct cl_enum *e = &cl_enums[option->var_enum];
1749
1750 if (mask)
1751 e->set (flag_var, value | (e->get (flag_var) & ~mask));
1752 else
1753 e->set (flag_var, value);
1754 if (set_flag_var)
1755 e->set (set_flag_var, 1);
1756 }
1757 break;
1758
1759 case CLVC_DEFER:
1760 {
1761 vec<cl_deferred_option> *v
1762 = (vec<cl_deferred_option> *) *(void **) flag_var;
1763 cl_deferred_option p = {.opt_index: opt_index, .arg: arg, .value: value};
1764 if (!v)
1765 v = XCNEW (vec<cl_deferred_option>);
1766 v->safe_push (obj: p);
1767 *(void **) flag_var = v;
1768 if (set_flag_var)
1769 *(void **) set_flag_var = v;
1770 }
1771 break;
1772 }
1773}
1774
1775/* Return the address of the flag variable for option OPT_INDEX in
1776 options structure OPTS, or NULL if there is no flag variable. */
1777
1778void *
1779option_flag_var (int opt_index, struct gcc_options *opts)
1780{
1781 const struct cl_option *option = &cl_options[opt_index];
1782
1783 if (option->flag_var_offset == (unsigned short) -1)
1784 return NULL;
1785 return (void *)(((char *) opts) + option->flag_var_offset);
1786}
1787
1788/* Return 1 if option OPT_IDX is enabled in OPTS, 0 if it is disabled,
1789 or -1 if it isn't a simple on-off switch
1790 (or if the value is unknown, typically set later in target). */
1791
1792int
1793option_enabled (int opt_idx, unsigned lang_mask, void *opts)
1794{
1795 const struct cl_option *option = &(cl_options[opt_idx]);
1796
1797 /* A language-specific option can only be considered enabled when it's
1798 valid for the current language. */
1799 if (!(option->flags & CL_COMMON)
1800 && (option->flags & CL_LANG_ALL)
1801 && !(option->flags & lang_mask))
1802 return 0;
1803
1804 struct gcc_options *optsg = (struct gcc_options *) opts;
1805 void *flag_var = option_flag_var (opt_index: opt_idx, opts: optsg);
1806
1807 if (flag_var)
1808 switch (option->var_type)
1809 {
1810 case CLVC_INTEGER:
1811 if (option->cl_host_wide_int)
1812 {
1813 HOST_WIDE_INT v = *(HOST_WIDE_INT *) flag_var;
1814 return v != 0 ? (v < 0 ? -1 : 1) : 0;
1815 }
1816 else
1817 {
1818 int v = *(int *) flag_var;
1819 return v != 0 ? (v < 0 ? -1 : 1) : 0;
1820 }
1821
1822 case CLVC_EQUAL:
1823 if (option->cl_host_wide_int)
1824 return *(HOST_WIDE_INT *) flag_var == option->var_value;
1825 else
1826 return *(int *) flag_var == option->var_value;
1827
1828 case CLVC_BIT_CLEAR:
1829 if (option->cl_host_wide_int)
1830 return (*(HOST_WIDE_INT *) flag_var & option->var_value) == 0;
1831 else
1832 return (*(int *) flag_var & option->var_value) == 0;
1833
1834 case CLVC_BIT_SET:
1835 if (option->cl_host_wide_int)
1836 return (*(HOST_WIDE_INT *) flag_var & option->var_value) != 0;
1837 else
1838 return (*(int *) flag_var & option->var_value) != 0;
1839
1840 case CLVC_SIZE:
1841 if (option->cl_host_wide_int)
1842 return *(HOST_WIDE_INT *) flag_var != -1;
1843 else
1844 return *(int *) flag_var != -1;
1845
1846 case CLVC_STRING:
1847 case CLVC_ENUM:
1848 case CLVC_DEFER:
1849 break;
1850 }
1851 return -1;
1852}
1853
1854/* Fill STATE with the current state of option OPTION in OPTS. Return
1855 true if there is some state to store. */
1856
1857bool
1858get_option_state (struct gcc_options *opts, int option,
1859 struct cl_option_state *state)
1860{
1861 void *flag_var = option_flag_var (opt_index: option, opts);
1862
1863 if (flag_var == 0)
1864 return false;
1865
1866 switch (cl_options[option].var_type)
1867 {
1868 case CLVC_INTEGER:
1869 case CLVC_EQUAL:
1870 case CLVC_SIZE:
1871 state->data = flag_var;
1872 state->size = (cl_options[option].cl_host_wide_int
1873 ? sizeof (HOST_WIDE_INT)
1874 : sizeof (int));
1875 break;
1876
1877 case CLVC_BIT_CLEAR:
1878 case CLVC_BIT_SET:
1879 state->ch = option_enabled (opt_idx: option, lang_mask: -1, opts);
1880 state->data = &state->ch;
1881 state->size = 1;
1882 break;
1883
1884 case CLVC_STRING:
1885 state->data = *(const char **) flag_var;
1886 if (state->data == 0)
1887 state->data = "";
1888 state->size = strlen (s: (const char *) state->data) + 1;
1889 break;
1890
1891 case CLVC_ENUM:
1892 state->data = flag_var;
1893 state->size = cl_enums[cl_options[option].var_enum].var_size;
1894 break;
1895
1896 case CLVC_DEFER:
1897 return false;
1898 }
1899 return true;
1900}
1901
1902/* Set a warning option OPT_INDEX (language mask LANG_MASK, option
1903 handlers HANDLERS) to have diagnostic kind KIND for option
1904 structures OPTS and OPTS_SET and diagnostic context DC (possibly
1905 NULL), at location LOC (UNKNOWN_LOCATION for -Werror=). ARG is the
1906 argument of the option for joined options, or NULL otherwise. If IMPLY,
1907 the warning option in question is implied at this point. This is
1908 used by -Werror= and #pragma GCC diagnostic. */
1909
1910void
1911control_warning_option (unsigned int opt_index, int kind, const char *arg,
1912 bool imply, location_t loc, unsigned int lang_mask,
1913 const struct cl_option_handlers *handlers,
1914 struct gcc_options *opts,
1915 struct gcc_options *opts_set,
1916 diagnostic_context *dc)
1917{
1918 if (cl_options[opt_index].alias_target != N_OPTS)
1919 {
1920 gcc_assert (!cl_options[opt_index].cl_separate_alias
1921 && !cl_options[opt_index].cl_negative_alias);
1922 if (cl_options[opt_index].alias_arg)
1923 arg = cl_options[opt_index].alias_arg;
1924 opt_index = cl_options[opt_index].alias_target;
1925 }
1926 if (opt_index == OPT_SPECIAL_ignore || opt_index == OPT_SPECIAL_warn_removed)
1927 return;
1928 if (dc)
1929 diagnostic_classify_diagnostic (context: dc, optidx: opt_index, kind: (diagnostic_t) kind, where: loc);
1930 if (imply)
1931 {
1932 /* -Werror=foo implies -Wfoo. */
1933 const struct cl_option *option = &cl_options[opt_index];
1934 HOST_WIDE_INT value = 1;
1935
1936 if (option->var_type == CLVC_INTEGER
1937 || option->var_type == CLVC_ENUM
1938 || option->var_type == CLVC_SIZE)
1939 {
1940
1941 if (arg && *arg == '\0' && !option->cl_missing_ok)
1942 arg = NULL;
1943
1944 if ((option->flags & CL_JOINED) && arg == NULL)
1945 {
1946 cmdline_handle_error (loc, option, opt: option->opt_text, arg,
1947 CL_ERR_MISSING_ARG, lang_mask);
1948 return;
1949 }
1950
1951 /* If the switch takes an integer argument, convert it. */
1952 if (arg && (option->cl_uinteger || option->cl_host_wide_int))
1953 {
1954 int error = 0;
1955 value = *arg ? integral_argument (arg, err: &error,
1956 byte_size_suffix: option->cl_byte_size) : 0;
1957 if (error)
1958 {
1959 cmdline_handle_error (loc, option, opt: option->opt_text, arg,
1960 CL_ERR_UINT_ARG, lang_mask);
1961 return;
1962 }
1963 }
1964
1965 /* If the switch takes an enumerated argument, convert it. */
1966 if (arg && option->var_type == CLVC_ENUM)
1967 {
1968 const struct cl_enum *e = &cl_enums[option->var_enum];
1969
1970 if (enum_arg_to_value (enum_args: e->values, arg, len: 0, value: &value,
1971 lang_mask) >= 0)
1972 {
1973 const char *carg = NULL;
1974
1975 if (enum_value_to_arg (enum_args: e->values, argp: &carg, value, lang_mask))
1976 arg = carg;
1977 gcc_assert (carg != NULL);
1978 }
1979 else
1980 {
1981 cmdline_handle_error (loc, option, opt: option->opt_text, arg,
1982 CL_ERR_ENUM_ARG, lang_mask);
1983 return;
1984 }
1985 }
1986 }
1987
1988 handle_generated_option (opts, opts_set,
1989 opt_index, arg, value, lang_mask,
1990 kind, loc, handlers, generated_p: false, dc);
1991 }
1992}
1993
1994/* Parse options in COLLECT_GCC_OPTIONS and push them on ARGV_OBSTACK.
1995 Store number of arguments into ARGC_P. */
1996
1997void
1998parse_options_from_collect_gcc_options (const char *collect_gcc_options,
1999 obstack *argv_obstack,
2000 int *argc_p)
2001{
2002 char *argv_storage = xstrdup (collect_gcc_options);
2003 int j, k;
2004
2005 for (j = 0, k = 0; argv_storage[j] != '\0'; ++j)
2006 {
2007 if (argv_storage[j] == '\'')
2008 {
2009 obstack_ptr_grow (argv_obstack, &argv_storage[k]);
2010 ++j;
2011 do
2012 {
2013 if (argv_storage[j] == '\0')
2014 fatal_error (input_location,
2015 "malformed %<COLLECT_GCC_OPTIONS%>");
2016 else if (startswith (str: &argv_storage[j], prefix: "'\\''"))
2017 {
2018 argv_storage[k++] = '\'';
2019 j += 4;
2020 }
2021 else if (argv_storage[j] == '\'')
2022 break;
2023 else
2024 argv_storage[k++] = argv_storage[j++];
2025 }
2026 while (1);
2027 argv_storage[k++] = '\0';
2028 }
2029 }
2030
2031 obstack_ptr_grow (argv_obstack, NULL);
2032 *argc_p = obstack_object_size (argv_obstack) / sizeof (void *) - 1;
2033}
2034
2035/* Prepend -Xassembler for each option in COLLECT_AS_OPTIONS,
2036 and push on O. */
2037
2038void prepend_xassembler_to_collect_as_options (const char *collect_as_options,
2039 obstack *o)
2040{
2041 obstack opts_obstack;
2042 int opts_count;
2043
2044 obstack_init (&opts_obstack);
2045 parse_options_from_collect_gcc_options (collect_gcc_options: collect_as_options,
2046 argv_obstack: &opts_obstack, argc_p: &opts_count);
2047 const char **assembler_opts = XOBFINISH (&opts_obstack, const char **);
2048
2049 for (int i = 0; i < opts_count; i++)
2050 {
2051 obstack_grow (o, " '-Xassembler' ",
2052 strlen (" '-Xassembler' "));
2053 const char *opt = assembler_opts[i];
2054 obstack_1grow (o, '\'');
2055 obstack_grow (o, opt, strlen (opt));
2056 obstack_1grow (o, '\'');
2057 }
2058}
2059
2060jobserver_info::jobserver_info ()
2061{
2062 /* Traditionally, GNU make uses opened pipes for jobserver-auth,
2063 e.g. --jobserver-auth=3,4.
2064 Starting with GNU make 4.4, one can use --jobserver-style=fifo
2065 and then named pipe is used: --jobserver-auth=fifo:/tmp/hcsparta. */
2066
2067 /* Detect jobserver and drop it if it's not working. */
2068 string js_needle = "--jobserver-auth=";
2069 string fifo_prefix = "fifo:";
2070
2071 const char *envval = getenv (name: "MAKEFLAGS");
2072 if (envval != NULL)
2073 {
2074 string makeflags = envval;
2075 size_t n = makeflags.rfind (str: js_needle);
2076 if (n != string::npos)
2077 {
2078 string ending = makeflags.substr (pos: n + js_needle.size ());
2079 if (ending.find (str: fifo_prefix) == 0)
2080 {
2081 ending = ending.substr (pos: fifo_prefix.size ());
2082 pipe_path = ending.substr (pos: 0, n: ending.find (c: ' '));
2083 is_active = true;
2084 }
2085 else if (sscanf (s: makeflags.c_str () + n + js_needle.size (),
2086 format: "%d,%d", &rfd, &wfd) == 2
2087 && rfd > 0
2088 && wfd > 0
2089 && is_valid_fd (fd: rfd)
2090 && is_valid_fd (fd: wfd))
2091 is_active = true;
2092 else
2093 {
2094 string dup = makeflags.substr (pos: 0, n: n);
2095 size_t pos = makeflags.find (c: ' ', pos: n);
2096 if (pos != string::npos)
2097 dup += makeflags.substr (pos: pos);
2098 skipped_makeflags = "MAKEFLAGS=" + dup;
2099 error_msg
2100 = "cannot access %<" + js_needle + "%> file descriptors";
2101 }
2102 }
2103 error_msg = "%<" + js_needle + "%> is not present in %<MAKEFLAGS%>";
2104 }
2105 else
2106 error_msg = "%<MAKEFLAGS%> environment variable is unset";
2107
2108 if (!error_msg.empty ())
2109 error_msg = "jobserver is not available: " + error_msg;
2110}
2111
2112void
2113jobserver_info::connect ()
2114{
2115 if (!pipe_path.empty ())
2116 {
2117#if HOST_HAS_O_NONBLOCK
2118 pipefd = open (file: pipe_path.c_str (), O_RDWR | O_NONBLOCK);
2119 is_connected = true;
2120#else
2121 is_connected = false;
2122#endif
2123 }
2124 else
2125 is_connected = true;
2126}
2127
2128void
2129jobserver_info::disconnect ()
2130{
2131 if (!pipe_path.empty ())
2132 {
2133 gcc_assert (close (pipefd) == 0);
2134 pipefd = -1;
2135 }
2136}
2137
2138bool
2139jobserver_info::get_token ()
2140{
2141 int fd = pipe_path.empty () ? rfd : pipefd;
2142 char c;
2143 unsigned n = read (fd: fd, buf: &c, nbytes: 1);
2144 if (n != 1)
2145 {
2146 gcc_assert (errno == EAGAIN);
2147 return false;
2148 }
2149 else
2150 return true;
2151}
2152
2153void
2154jobserver_info::return_token ()
2155{
2156 int fd = pipe_path.empty () ? wfd : pipefd;
2157 char c = 'G';
2158 gcc_assert (write (fd, &c, 1) == 1);
2159}
2160

source code of gcc/opts-common.cc