abseil-cpp/absl/flags/parse.cc
Go to the documentation of this file.
1 //
2 // Copyright 2019 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "absl/flags/parse.h"
17 
18 #include <stdlib.h>
19 
20 #include <algorithm>
21 #include <fstream>
22 #include <iostream>
23 #include <iterator>
24 #include <string>
25 #include <tuple>
26 #include <utility>
27 #include <vector>
28 
29 #ifdef _WIN32
30 #include <windows.h>
31 #endif
32 
33 #include "absl/base/attributes.h"
34 #include "absl/base/config.h"
35 #include "absl/base/const_init.h"
36 #include "absl/base/thread_annotations.h"
37 #include "absl/flags/commandlineflag.h"
38 #include "absl/flags/config.h"
39 #include "absl/flags/flag.h"
40 #include "absl/flags/internal/commandlineflag.h"
41 #include "absl/flags/internal/flag.h"
42 #include "absl/flags/internal/parse.h"
43 #include "absl/flags/internal/private_handle_accessor.h"
44 #include "absl/flags/internal/program_name.h"
45 #include "absl/flags/internal/usage.h"
46 #include "absl/flags/reflection.h"
47 #include "absl/flags/usage.h"
48 #include "absl/flags/usage_config.h"
49 #include "absl/strings/ascii.h"
50 #include "absl/strings/str_cat.h"
51 #include "absl/strings/string_view.h"
52 #include "absl/strings/strip.h"
53 #include "absl/synchronization/mutex.h"
54 
55 // --------------------------------------------------------------------
56 
57 namespace absl {
59 namespace flags_internal {
60 namespace {
61 
62 ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
63 
64 ABSL_CONST_INIT bool flagfile_needs_processing
65  ABSL_GUARDED_BY(processing_checks_guard) = false;
66 ABSL_CONST_INIT bool fromenv_needs_processing
67  ABSL_GUARDED_BY(processing_checks_guard) = false;
68 ABSL_CONST_INIT bool tryfromenv_needs_processing
69  ABSL_GUARDED_BY(processing_checks_guard) = false;
70 
71 ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
72 ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
73  ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
74 
75 struct SpecifiedFlagsCompare {
76  bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
77  return a->Name() < b->Name();
78  }
79  bool operator()(const CommandLineFlag* a, absl::string_view b) const {
80  return a->Name() < b;
81  }
82  bool operator()(absl::string_view a, const CommandLineFlag* b) const {
83  return a < b->Name();
84  }
85 };
86 
87 } // namespace
88 } // namespace flags_internal
90 } // namespace absl
91 
92 ABSL_FLAG(std::vector<std::string>, flagfile, {},
93  "comma-separated list of files to load flags from")
94  .OnUpdate([]() {
95  if (absl::GetFlag(FLAGS_flagfile).empty()) return;
96 
97  absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
98 
99  // Setting this flag twice before it is handled most likely an internal
100  // error and should be reviewed by developers.
101  if (absl::flags_internal::flagfile_needs_processing) {
102  ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled");
103  }
104 
105  absl::flags_internal::flagfile_needs_processing = true;
106  });
107 ABSL_FLAG(std::vector<std::string>, fromenv, {},
108  "comma-separated list of flags to set from the environment"
109  " [use 'export FLAGS_flag1=value']")
110  .OnUpdate([]() {
111  if (absl::GetFlag(FLAGS_fromenv).empty()) return;
112 
113  absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
114 
115  // Setting this flag twice before it is handled most likely an internal
116  // error and should be reviewed by developers.
117  if (absl::flags_internal::fromenv_needs_processing) {
118  ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled.");
119  }
120 
121  absl::flags_internal::fromenv_needs_processing = true;
122  });
123 ABSL_FLAG(std::vector<std::string>, tryfromenv, {},
124  "comma-separated list of flags to try to set from the environment if "
125  "present")
126  .OnUpdate([]() {
127  if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;
128 
129  absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
130 
131  // Setting this flag twice before it is handled most likely an internal
132  // error and should be reviewed by developers.
133  if (absl::flags_internal::tryfromenv_needs_processing) {
135  "tryfromenv set twice before it is handled.");
136  }
137 
138  absl::flags_internal::tryfromenv_needs_processing = true;
139  });
140 
141 ABSL_FLAG(std::vector<std::string>, undefok, {},
142  "comma-separated list of flag names that it is okay to specify "
143  "on the command line even if the program does not define a flag "
144  "with that name");
145 
146 namespace absl {
148 namespace flags_internal {
149 
150 namespace {
151 
152 class ArgsList {
153  public:
154  ArgsList() : next_arg_(0) {}
155  ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}
156  explicit ArgsList(const std::vector<std::string>& args)
157  : args_(args), next_arg_(0) {}
158 
159  // Returns success status: true if parsing successful, false otherwise.
160  bool ReadFromFlagfile(const std::string& flag_file_name);
161 
162  int Size() const { return args_.size() - next_arg_; }
163  int FrontIndex() const { return next_arg_; }
164  absl::string_view Front() const { return args_[next_arg_]; }
165  void PopFront() { next_arg_++; }
166 
167  private:
168  std::vector<std::string> args_;
170 };
171 
172 bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
173  std::ifstream flag_file(flag_file_name);
174 
175  if (!flag_file) {
177  absl::StrCat("Can't open flagfile ", flag_file_name), true);
178 
179  return false;
180  }
181 
182  // This argument represents fake argv[0], which should be present in all arg
183  // lists.
184  args_.push_back("");
185 
187  bool success = true;
188 
189  while (std::getline(flag_file, line)) {
191 
192  if (stripped.empty() || stripped[0] == '#') {
193  // Comment or empty line; just ignore.
194  continue;
195  }
196 
197  if (stripped[0] == '-') {
198  if (stripped == "--") {
200  "Flagfile can't contain position arguments or --", true);
201 
202  success = false;
203  break;
204  }
205 
206  args_.push_back(std::string(stripped));
207  continue;
208  }
209 
211  absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ",
212  line),
213  true);
214 
215  success = false;
216  }
217 
218  return success;
219 }
220 
221 // --------------------------------------------------------------------
222 
223 // Reads the environment variable with name `name` and stores results in
224 // `value`. If variable is not present in environment returns false, otherwise
225 // returns true.
226 bool GetEnvVar(const char* var_name, std::string& var_value) {
227 #ifdef _WIN32
228  char buf[1024];
229  auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
230  if (get_res >= sizeof(buf)) {
231  return false;
232  }
233 
234  if (get_res == 0) {
235  return false;
236  }
237 
238  var_value = std::string(buf, get_res);
239 #else
240  const char* val = ::getenv(var_name);
241  if (val == nullptr) {
242  return false;
243  }
244 
245  var_value = val;
246 #endif
247 
248  return true;
249 }
250 
251 // --------------------------------------------------------------------
252 
253 // Returns:
254 // Flag name or empty if arg= --
255 // Flag value after = in --flag=value (empty if --foo)
256 // "Is empty value" status. True if arg= --foo=, false otherwise. This is
257 // required to separate --foo from --foo=.
258 // For example:
259 // arg return values
260 // "--foo=bar" -> {"foo", "bar", false}.
261 // "--foo" -> {"foo", "", false}.
262 // "--foo=" -> {"foo", "", true}.
263 std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
265  // Allow -foo and --foo
266  absl::ConsumePrefix(&arg, "-");
267 
268  if (arg.empty()) {
269  return std::make_tuple("", "", false);
270  }
271 
272  auto equal_sign_pos = arg.find("=");
273 
274  absl::string_view flag_name = arg.substr(0, equal_sign_pos);
275 
277  bool is_empty_value = false;
278 
279  if (equal_sign_pos != absl::string_view::npos) {
280  value = arg.substr(equal_sign_pos + 1);
281  is_empty_value = value.empty();
282  }
283 
284  return std::make_tuple(flag_name, value, is_empty_value);
285 }
286 
287 // --------------------------------------------------------------------
288 
289 // Returns:
290 // found flag or nullptr
291 // is negative in case of --nofoo
292 std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
293  CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
294  bool is_negative = false;
295 
296  if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
297  flag = absl::FindCommandLineFlag(flag_name);
298  is_negative = true;
299  }
300 
301  return std::make_tuple(flag, is_negative);
302 }
303 
304 // --------------------------------------------------------------------
305 
306 // Verify that default values of typed flags must be convertible to string and
307 // back.
308 void CheckDefaultValuesParsingRoundtrip() {
309 #ifndef NDEBUG
310  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
311  if (flag.IsRetired()) return;
312 
314  if (flag.IsOfType<T>()) return;
315 
318 
320  flag);
321  });
322 #endif
323 }
324 
325 // --------------------------------------------------------------------
326 
327 // Returns success status, which is true if we successfully read all flag files,
328 // in which case new ArgLists are appended to the input_args in a reverse order
329 // of file names in the input flagfiles list. This order ensures that flags from
330 // the first flagfile in the input list are processed before the second flagfile
331 // etc.
332 bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
333  std::vector<ArgsList>& input_args) {
334  bool success = true;
335  for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
336  ArgsList al;
337 
338  if (al.ReadFromFlagfile(*it)) {
339  input_args.push_back(al);
340  } else {
341  success = false;
342  }
343  }
344 
345  return success;
346 }
347 
348 // Returns success status, which is true if were able to locate all environment
349 // variables correctly or if fail_on_absent_in_env is false. The environment
350 // variable names are expected to be of the form `FLAGS_<flag_name>`, where
351 // `flag_name` is a string from the input flag_names list. If successful we
352 // append a single ArgList at the end of the input_args.
353 bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
354  std::vector<ArgsList>& input_args,
355  bool fail_on_absent_in_env) {
356  bool success = true;
357  std::vector<std::string> args;
358 
359  // This argument represents fake argv[0], which should be present in all arg
360  // lists.
361  args.push_back("");
362 
363  for (const auto& flag_name : flag_names) {
364  // Avoid infinite recursion.
365  if (flag_name == "fromenv" || flag_name == "tryfromenv") {
367  absl::StrCat("Infinite recursion on flag ", flag_name), true);
368 
369  success = false;
370  continue;
371  }
372 
373  const std::string envname = absl::StrCat("FLAGS_", flag_name);
374  std::string envval;
375  if (!GetEnvVar(envname.c_str(), envval)) {
376  if (fail_on_absent_in_env) {
378  absl::StrCat(envname, " not found in environment"), true);
379 
380  success = false;
381  }
382 
383  continue;
384  }
385 
386  args.push_back(absl::StrCat("--", flag_name, "=", envval));
387  }
388 
389  if (success) {
390  input_args.emplace_back(args);
391  }
392 
393  return success;
394 }
395 
396 // --------------------------------------------------------------------
397 
398 // Returns success status, which is true if were able to handle all generator
399 // flags (flagfile, fromenv, tryfromemv) successfully.
400 bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
401  std::vector<std::string>& flagfile_value) {
402  bool success = true;
403 
404  absl::MutexLock l(&flags_internal::processing_checks_guard);
405 
406  // flagfile could have been set either on a command line or
407  // programmatically before invoking ParseCommandLine. Note that we do not
408  // actually process arguments specified in the flagfile, but instead
409  // create a secondary arguments list to be processed along with the rest
410  // of the comamnd line arguments. Since we always the process most recently
411  // created list of arguments first, this will result in flagfile argument
412  // being processed before any other argument in the command line. If
413  // FLAGS_flagfile contains more than one file name we create multiple new
414  // levels of arguments in a reverse order of file names. Thus we always
415  // process arguments from first file before arguments containing in a
416  // second file, etc. If flagfile contains another
417  // --flagfile inside of it, it will produce new level of arguments and
418  // processed before the rest of the flagfile. We are also collecting all
419  // flagfiles set on original command line. Unlike the rest of the flags,
420  // this flag can be set multiple times and is expected to be handled
421  // multiple times. We are collecting them all into a single list and set
422  // the value of FLAGS_flagfile to that value at the end of the parsing.
423  if (flags_internal::flagfile_needs_processing) {
424  auto flagfiles = absl::GetFlag(FLAGS_flagfile);
425 
426  if (input_args.size() == 1) {
427  flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
428  flagfiles.end());
429  }
430 
431  success &= ReadFlagfiles(flagfiles, input_args);
432 
433  flags_internal::flagfile_needs_processing = false;
434  }
435 
436  // Similar to flagfile fromenv/tryfromemv can be set both
437  // programmatically and at runtime on a command line. Unlike flagfile these
438  // can't be recursive.
439  if (flags_internal::fromenv_needs_processing) {
440  auto flags_list = absl::GetFlag(FLAGS_fromenv);
441 
442  success &= ReadFlagsFromEnv(flags_list, input_args, true);
443 
444  flags_internal::fromenv_needs_processing = false;
445  }
446 
447  if (flags_internal::tryfromenv_needs_processing) {
448  auto flags_list = absl::GetFlag(FLAGS_tryfromenv);
449 
450  success &= ReadFlagsFromEnv(flags_list, input_args, false);
451 
452  flags_internal::tryfromenv_needs_processing = false;
453  }
454 
455  return success;
456 }
457 
458 // --------------------------------------------------------------------
459 
460 void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) {
461  // Setting flagfile to the value which collates all the values set on a
462  // command line and programmatically. So if command line looked like
463  // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
464  // going to be {"f1", "f2"}
465  if (!flagfile_value.empty()) {
466  absl::SetFlag(&FLAGS_flagfile, flagfile_value);
467  absl::MutexLock l(&flags_internal::processing_checks_guard);
468  flags_internal::flagfile_needs_processing = false;
469  }
470 
471  // fromenv/tryfromenv are set to <undefined> value.
472  if (!absl::GetFlag(FLAGS_fromenv).empty()) {
473  absl::SetFlag(&FLAGS_fromenv, {});
474  }
475  if (!absl::GetFlag(FLAGS_tryfromenv).empty()) {
476  absl::SetFlag(&FLAGS_tryfromenv, {});
477  }
478 
479  absl::MutexLock l(&flags_internal::processing_checks_guard);
480  flags_internal::fromenv_needs_processing = false;
481  flags_internal::tryfromenv_needs_processing = false;
482 }
483 
484 // --------------------------------------------------------------------
485 
486 // Returns:
487 // success status
488 // deduced value
489 // We are also mutating curr_list in case if we need to get a hold of next
490 // argument in the input.
491 std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
493  bool is_negative,
494  bool is_empty_value,
495  ArgsList* curr_list) {
496  // Value is either an argument suffix after `=` in "--foo=<value>"
497  // or separate argument in case of "--foo" "<value>".
498 
499  // boolean flags have these forms:
500  // --foo
501  // --nofoo
502  // --foo=true
503  // --foo=false
504  // --nofoo=<value> is not supported
505  // --foo <value> is not supported
506 
507  // non boolean flags have these forms:
508  // --foo=<value>
509  // --foo <value>
510  // --nofoo is not supported
511 
512  if (flag.IsOfType<bool>()) {
513  if (value.empty()) {
514  if (is_empty_value) {
515  // "--bool_flag=" case
517  absl::StrCat(
518  "Missing the value after assignment for the boolean flag '",
519  flag.Name(), "'"),
520  true);
521  return std::make_tuple(false, "");
522  }
523 
524  // "--bool_flag" case
525  value = is_negative ? "0" : "1";
526  } else if (is_negative) {
527  // "--nobool_flag=Y" case
529  absl::StrCat("Negative form with assignment is not valid for the "
530  "boolean flag '",
531  flag.Name(), "'"),
532  true);
533  return std::make_tuple(false, "");
534  }
535  } else if (is_negative) {
536  // "--noint_flag=1" case
538  absl::StrCat("Negative form is not valid for the flag '", flag.Name(),
539  "'"),
540  true);
541  return std::make_tuple(false, "");
542  } else if (value.empty() && (!is_empty_value)) {
543  if (curr_list->Size() == 1) {
544  // "--int_flag" case
546  absl::StrCat("Missing the value for the flag '", flag.Name(), "'"),
547  true);
548  return std::make_tuple(false, "");
549  }
550 
551  // "--int_flag" "10" case
552  curr_list->PopFront();
553  value = curr_list->Front();
554 
555  // Heuristic to detect the case where someone treats a string arg
556  // like a bool or just forgets to pass a value:
557  // --my_string_var --foo=bar
558  // We look for a flag of string type, whose value begins with a
559  // dash and corresponds to known flag or standalone --.
560  if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) {
561  auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
562 
563  if (maybe_flag_name.empty() ||
564  std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {
565  // "--string_flag" "--known_flag" case
567  WARNING,
568  absl::StrCat("Did you really mean to set flag '", flag.Name(),
569  "' to the value '", value, "'?"));
570  }
571  }
572  }
573 
574  return std::make_tuple(true, value);
575 }
576 
577 // --------------------------------------------------------------------
578 
579 bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
580  auto undefok = absl::GetFlag(FLAGS_undefok);
581  if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
582  return true;
583  }
584 
585  if (absl::ConsumePrefix(&flag_name, "no") &&
586  std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
587  return true;
588  }
589 
590  return false;
591 }
592 
593 } // namespace
594 
595 // --------------------------------------------------------------------
596 
598  absl::MutexLock l(&specified_flags_guard);
599  ABSL_INTERNAL_CHECK(specified_flags != nullptr,
600  "ParseCommandLine is not invoked yet");
601 
602  return std::binary_search(specified_flags->begin(), specified_flags->end(),
603  flag_name, SpecifiedFlagsCompare{});
604 }
605 
606 // --------------------------------------------------------------------
607 
608 std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
609  ArgvListAction arg_list_act,
610  UsageFlagsAction usage_flag_act,
611  OnUndefinedFlag on_undef_flag) {
612  ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
613 
614  // Once parsing has started we will not have more flag registrations.
615  // If we did, they would be missing during parsing, which is a problem on
616  // itself.
618 
619  // This routine does not return anything since we abort on failure.
620  CheckDefaultValuesParsingRoundtrip();
621 
622  std::vector<std::string> flagfile_value;
623 
624  std::vector<ArgsList> input_args;
625  input_args.push_back(ArgsList(argc, argv));
626 
627  std::vector<char*> output_args;
628  std::vector<char*> positional_args;
629  output_args.reserve(argc);
630 
631  // This is the list of undefined flags. The element of the list is the pair
632  // consisting of boolean indicating if flag came from command line (vs from
633  // some flag file we've read) and flag name.
634  // TODO(rogeeff): Eliminate the first element in the pair after cleanup.
635  std::vector<std::pair<bool, std::string>> undefined_flag_names;
636 
637  // Set program invocation name if it is not set before.
638  if (ProgramInvocationName() == "UNKNOWN") {
640  }
641  output_args.push_back(argv[0]);
642 
643  absl::MutexLock l(&specified_flags_guard);
644  if (specified_flags == nullptr) {
645  specified_flags = new std::vector<const CommandLineFlag*>;
646  } else {
647  specified_flags->clear();
648  }
649 
650  // Iterate through the list of the input arguments. First level are arguments
651  // originated from argc/argv. Following levels are arguments originated from
652  // recursive parsing of flagfile(s).
653  bool success = true;
654  while (!input_args.empty()) {
655  // 10. First we process the built-in generator flags.
656  success &= HandleGeneratorFlags(input_args, flagfile_value);
657 
658  // 30. Select top-most (most recent) arguments list. If it is empty drop it
659  // and re-try.
660  ArgsList& curr_list = input_args.back();
661 
662  curr_list.PopFront();
663 
664  if (curr_list.Size() == 0) {
665  input_args.pop_back();
666  continue;
667  }
668 
669  // 40. Pick up the front remaining argument in the current list. If current
670  // stack of argument lists contains only one element - we are processing an
671  // argument from the original argv.
672  absl::string_view arg(curr_list.Front());
673  bool arg_from_argv = input_args.size() == 1;
674 
675  // 50. If argument does not start with - or is just "-" - this is
676  // positional argument.
677  if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) {
678  ABSL_INTERNAL_CHECK(arg_from_argv,
679  "Flagfile cannot contain positional argument");
680 
681  positional_args.push_back(argv[curr_list.FrontIndex()]);
682  continue;
683  }
684 
685  if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs)) {
686  output_args.push_back(argv[curr_list.FrontIndex()]);
687  }
688 
689  // 60. Split the current argument on '=' to figure out the argument
690  // name and value. If flag name is empty it means we've got "--". value
691  // can be empty either if there were no '=' in argument string at all or
692  // an argument looked like "--foo=". In a latter case is_empty_value is
693  // true.
694  absl::string_view flag_name;
696  bool is_empty_value = false;
697 
698  std::tie(flag_name, value, is_empty_value) = SplitNameAndValue(arg);
699 
700  // 70. "--" alone means what it does for GNU: stop flags parsing. We do
701  // not support positional arguments in flagfiles, so we just drop them.
702  if (flag_name.empty()) {
703  ABSL_INTERNAL_CHECK(arg_from_argv,
704  "Flagfile cannot contain positional argument");
705 
706  curr_list.PopFront();
707  break;
708  }
709 
710  // 80. Locate the flag based on flag name. Handle both --foo and --nofoo
711  CommandLineFlag* flag = nullptr;
712  bool is_negative = false;
713  std::tie(flag, is_negative) = LocateFlag(flag_name);
714 
715  if (flag == nullptr) {
716  // Usage flags are not modeled as Abseil flags. Locate them separately.
717  if (flags_internal::DeduceUsageFlags(flag_name, value)) {
718  continue;
719  }
720 
721  if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
722  undefined_flag_names.emplace_back(arg_from_argv,
723  std::string(flag_name));
724  }
725  continue;
726  }
727 
728  // 90. Deduce flag's value (from this or next argument)
729  auto curr_index = curr_list.FrontIndex();
730  bool value_success = true;
731  std::tie(value_success, value) =
732  DeduceFlagValue(*flag, value, is_negative, is_empty_value, &curr_list);
733  success &= value_success;
734 
735  // If above call consumed an argument, it was a standalone value
736  if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs) &&
737  (curr_index != curr_list.FrontIndex())) {
738  output_args.push_back(argv[curr_list.FrontIndex()]);
739  }
740 
741  // 100. Set the located flag to a new new value, unless it is retired.
742  // Setting retired flag fails, but we ignoring it here while also reporting
743  // access to retired flag.
747  if (flag->IsRetired()) continue;
748 
750  success = false;
751  } else {
752  specified_flags->push_back(flag);
753  }
754  }
755 
756  for (const auto& flag_name : undefined_flag_names) {
757  if (CanIgnoreUndefinedFlag(flag_name.second)) continue;
758 
760  absl::StrCat("Unknown command line flag '", flag_name.second, "'"),
761  true);
762 
763  success = false;
764  }
765 
766 #if ABSL_FLAGS_STRIP_NAMES
767  if (!success) {
769  "NOTE: command line flags are disabled in this build", true);
770  }
771 #endif
772 
773  if (!success) {
776  std::exit(1);
777  }
778 
779  if (usage_flag_act == UsageFlagsAction::kHandleUsage) {
781  std::cout, ProgramUsageMessage());
782 
783  if (exit_code != -1) {
784  std::exit(exit_code);
785  }
786  }
787 
788  ResetGeneratorFlags(flagfile_value);
789 
790  // Reinstate positional args which were intermixed with flags in the arguments
791  // list.
792  for (auto arg : positional_args) {
793  output_args.push_back(arg);
794  }
795 
796  // All the remaining arguments are positional.
797  if (!input_args.empty()) {
798  for (int arg_index = input_args.back().FrontIndex(); arg_index < argc;
799  ++arg_index) {
800  output_args.push_back(argv[arg_index]);
801  }
802  }
803 
804  // Trim and sort the vector.
805  specified_flags->shrink_to_fit();
806  std::sort(specified_flags->begin(), specified_flags->end(),
807  SpecifiedFlagsCompare{});
808  return output_args;
809 }
810 
811 } // namespace flags_internal
812 
813 // --------------------------------------------------------------------
814 
815 std::vector<char*> ParseCommandLine(int argc, char* argv[]) {
820 }
821 
823 } // namespace absl
absl::flags_internal::ProgramInvocationName
std::string ProgramInvocationName()
Definition: abseil-cpp/absl/flags/internal/program_name.cc:36
flag
uint32_t flag
Definition: ssl_versions.cc:162
absl::SetFlag
void SetFlag(absl::Flag< T > *flag, const T &v)
Definition: abseil-cpp/absl/flags/flag.h:110
regen-readme.it
it
Definition: regen-readme.py:15
ABSL_CONST_INIT
#define ABSL_CONST_INIT
Definition: abseil-cpp/absl/base/attributes.h:716
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
find
static void ** find(grpc_chttp2_stream_map *map, uint32_t key)
Definition: stream_map.cc:99
std::tr1::make_tuple
tuple make_tuple()
Definition: cares/cares/test/gmock-1.8.0/gtest/gtest.h:1619
absl::Mutex
Definition: abseil-cpp/absl/synchronization/mutex.h:131
args_
std::vector< std::string > args_
Definition: abseil-cpp/absl/flags/parse.cc:168
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
ABSL_INTERNAL_CHECK
#define ABSL_INTERNAL_CHECK(condition, message)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:85
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
absl::flags_internal::HandleUsageFlags
int HandleUsageFlags(std::ostream &out, absl::string_view program_usage_message)
Definition: abseil-cpp/absl/flags/internal/usage.cc:355
absl::ParseCommandLine
std::vector< char * > ParseCommandLine(int argc, char *argv[])
Definition: abseil-cpp/absl/flags/parse.cc:815
absl::flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip
static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag &flag)
Definition: abseil-cpp/absl/flags/internal/private_handle_accessor.cc:49
absl::FindCommandLineFlag
CommandLineFlag * FindCommandLineFlag(absl::string_view name)
Definition: abseil-cpp/absl/flags/reflection.cc:336
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
pump.PopFront
def PopFront(a_list)
Definition: bloaty/third_party/googletest/googletest/scripts/pump.py:443
absl::kConstInit
@ kConstInit
Definition: abseil-cpp/absl/base/const_init.h:70
absl::flags_internal::OnUndefinedFlag
OnUndefinedFlag
Definition: abseil-cpp/absl/flags/internal/parse.h:37
absl::flags_internal::ArgvListAction
ArgvListAction
Definition: abseil-cpp/absl/flags/internal/parse.h:35
absl::CommandLineFlag
Definition: abseil-cpp/absl/flags/commandlineflag.h:62
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
T
#define T(upbtypeconst, upbtype, ctype, default_value)
ABSL_FLAG
ABSL_FLAG(std::vector< std::string >, flagfile, {}, "comma-separated list of files to load flags from") .OnUpdate([]()
Definition: abseil-cpp/absl/flags/parse.cc:92
next_arg_
int next_arg_
Definition: abseil-cpp/absl/flags/parse.cc:169
absl::flags_internal::FinalizeRegistry
void FinalizeRegistry()
Definition: abseil-cpp/absl/flags/reflection.cc:196
absl::flags_internal::DeduceUsageFlags
bool DeduceUsageFlags(absl::string_view name, absl::string_view value)
Definition: abseil-cpp/absl/flags/internal/usage.cc:467
absl::MutexLock
Definition: abseil-cpp/absl/synchronization/mutex.h:525
absl::flags_internal::ParseCommandLineImpl
std::vector< char * > ParseCommandLineImpl(int argc, char *argv[], ArgvListAction arg_list_act, UsageFlagsAction usage_flag_act, OnUndefinedFlag on_undef_flag)
Definition: abseil-cpp/absl/flags/parse.cc:608
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
absl::flags_internal::ABSL_GUARDED_BY
static ABSL_CONST_INIT std::string *program_name ABSL_GUARDED_BY(program_name_guard)
absl::ProgramUsageMessage
absl::string_view ProgramUsageMessage()
Definition: abseil-cpp/absl/flags/usage.cc:56
absl::flags_internal::ReportUsageError
void ReportUsageError(absl::string_view msg, bool is_fatal)
Definition: abseil-cpp/absl/flags/usage_config.cc:128
gmock_output_test._
_
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
absl::StripLeadingAsciiWhitespace
ABSL_MUST_USE_RESULT absl::string_view StripLeadingAsciiWhitespace(absl::string_view str)
Definition: abseil-cpp/absl/strings/ascii.h:197
absl::flags_internal::SET_FLAGS_VALUE
@ SET_FLAGS_VALUE
Definition: abseil-cpp/absl/flags/internal/commandlineflag.h:36
arg
Definition: cmdline.cc:40
absl::flags_internal::ForEachFlag
void ForEachFlag(std::function< void(CommandLineFlag &)> visitor)
Definition: abseil-cpp/absl/flags/reflection.cc:178
absl::GetFlag
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag< T > &flag)
Definition: abseil-cpp/absl/flags/flag.h:98
google::protobuf::WARNING
static const LogLevel WARNING
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.h:71
absl::flags_internal::PrivateHandleAccessor::ParseFrom
static bool ParseFrom(CommandLineFlag &flag, absl::string_view value, flags_internal::FlagSettingMode set_mode, flags_internal::ValueSource source, std::string &error)
Definition: abseil-cpp/absl/flags/internal/private_handle_accessor.cc:54
absl::flags_internal::OnUndefinedFlag::kAbortIfUndefined
@ kAbortIfUndefined
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES
#define ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A)
Definition: third_party/abseil-cpp/absl/flags/config.h:63
google_benchmark.example.empty
def empty(state)
Definition: example.py:31
value
const char * value
Definition: hpack_parser_table.cc:165
absl::flags_internal::SetProgramInvocationName
void SetProgramInvocationName(absl::string_view prog_name_str)
Definition: abseil-cpp/absl/flags/internal/program_name.cc:49
absl::flags_internal::ArgvListAction::kRemoveParsedArgs
@ kRemoveParsedArgs
absl::flags_internal::UsageFlagsAction
UsageFlagsAction
Definition: abseil-cpp/absl/flags/internal/parse.h:36
regen-readme.line
line
Definition: regen-readme.py:30
arg
struct arg arg
ABSL_FLAGS_INTERNAL_IGNORE_TYPE
#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _)
absl::flags_internal::OnUndefinedFlag::kIgnoreUndefined
@ kIgnoreUndefined
absl::flags_internal::kCommandLine
@ kCommandLine
Definition: abseil-cpp/absl/flags/internal/commandlineflag.h:49
absl::flags_internal::WasPresentOnCommandLine
bool WasPresentOnCommandLine(absl::string_view flag_name)
Definition: abseil-cpp/absl/flags/parse.cc:597
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::string_view::npos
static constexpr size_type npos
Definition: abseil-cpp/absl/strings/string_view.h:182
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
absl::flags_internal::UsageFlagsAction::kHandleUsage
@ kHandleUsage
ABSL_INTERNAL_LOG
#define ABSL_INTERNAL_LOG(severity, message)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:75
getenv
#define getenv(ptr)
Definition: ares_private.h:106
absl::flags_internal::ArgvListAction::kKeepParsedArgs
@ kKeepParsedArgs
run_tests.exit_code
int exit_code
Definition: run_tests.py:1701
absl::ConsumePrefix
ABSL_NAMESPACE_BEGIN bool ConsumePrefix(absl::string_view *str, absl::string_view expected)
Definition: abseil-cpp/absl/strings/strip.h:46


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:39