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 #include <fstream>
20 #include <iostream>
21 #include <tuple>
22 
23 #ifdef _WIN32
24 #include <windows.h>
25 #endif
26 
27 #include "absl/flags/flag.h"
32 #include "absl/strings/str_cat.h"
33 #include "absl/strings/strip.h"
35 
36 // --------------------------------------------------------------------
37 
38 namespace absl {
39 namespace flags_internal {
40 namespace {
41 
42 ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
43 
44 ABSL_CONST_INIT bool flagfile_needs_processing
45  GUARDED_BY(processing_checks_guard) = false;
46 ABSL_CONST_INIT bool fromenv_needs_processing
47  GUARDED_BY(processing_checks_guard) = false;
48 ABSL_CONST_INIT bool tryfromenv_needs_processing
49  GUARDED_BY(processing_checks_guard) = false;
50 
51 } // namespace
52 } // namespace flags_internal
53 } // namespace absl
54 
55 ABSL_FLAG(std::vector<std::string>, flagfile, {},
56  "comma-separated list of files to load flags from")
57  .OnUpdate([]() {
58  if (absl::GetFlag(FLAGS_flagfile).empty()) return;
59 
60  absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
61 
62  // Setting this flag twice before it is handled most likely an internal
63  // error and should be reviewed by developers.
64  if (absl::flags_internal::flagfile_needs_processing) {
65  ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled");
66  }
67 
68  absl::flags_internal::flagfile_needs_processing = true;
69  });
70 ABSL_FLAG(std::vector<std::string>, fromenv, {},
71  "comma-separated list of flags to set from the environment"
72  " [use 'export FLAGS_flag1=value']")
73  .OnUpdate([]() {
74  if (absl::GetFlag(FLAGS_fromenv).empty()) return;
75 
76  absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
77 
78  // Setting this flag twice before it is handled most likely an internal
79  // error and should be reviewed by developers.
80  if (absl::flags_internal::fromenv_needs_processing) {
81  ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled.");
82  }
83 
84  absl::flags_internal::fromenv_needs_processing = true;
85  });
86 ABSL_FLAG(std::vector<std::string>, tryfromenv, {},
87  "comma-separated list of flags to try to set from the environment if "
88  "present")
89  .OnUpdate([]() {
90  if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;
91 
92  absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
93 
94  // Setting this flag twice before it is handled most likely an internal
95  // error and should be reviewed by developers.
96  if (absl::flags_internal::tryfromenv_needs_processing) {
97  ABSL_INTERNAL_LOG(WARNING,
98  "tryfromenv set twice before it is handled.");
99  }
100 
101  absl::flags_internal::tryfromenv_needs_processing = true;
102  });
103 
104 ABSL_FLAG(std::vector<std::string>, undefok, {},
105  "comma-separated list of flag names that it is okay to specify "
106  "on the command line even if the program does not define a flag "
107  "with that name");
108 
109 namespace absl {
110 namespace flags_internal {
111 
112 namespace {
113 
114 class ArgsList {
115  public:
116  ArgsList() : next_arg_(0) {}
117  ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}
118  explicit ArgsList(const std::vector<std::string>& args)
119  : args_(args), next_arg_(0) {}
120 
121  // Returns success status: true if parsing successful, false otherwise.
122  bool ReadFromFlagfile(const std::string& flag_file_name);
123 
124  int Size() const { return args_.size() - next_arg_; }
125  int FrontIndex() const { return next_arg_; }
126  absl::string_view Front() const { return args_[next_arg_]; }
127  void PopFront() { next_arg_++; }
128 
129  private:
130  std::vector<std::string> args_;
132 };
133 
134 bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
135  std::ifstream flag_file(flag_file_name);
136 
137  if (!flag_file) {
139  absl::StrCat("Can't open flagfile ", flag_file_name), true);
140 
141  return false;
142  }
143 
144  // This argument represents fake argv[0], which should be present in all arg
145  // lists.
146  args_.push_back("");
147 
148  std::string line;
149  bool success = true;
150 
151  while (std::getline(flag_file, line)) {
153 
154  if (stripped.empty() || stripped[0] == '#') {
155  // Comment or empty line; just ignore.
156  continue;
157  }
158 
159  if (stripped[0] == '-') {
160  if (stripped == "--") {
162  "Flagfile can't contain position arguments or --", true);
163 
164  success = false;
165  break;
166  }
167 
168  args_.push_back(std::string(stripped));
169  continue;
170  }
171 
173  absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ",
174  line),
175  true);
176 
177  success = false;
178  }
179 
180  return success;
181 }
182 
183 // --------------------------------------------------------------------
184 
185 // Reads the environment variable with name `name` and stores results in
186 // `value`. If variable is not present in environment returns false, otherwise
187 // returns true.
188 bool GetEnvVar(const char* var_name, std::string* var_value) {
189 #ifdef _WIN32
190  char buf[1024];
191  auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
192  if (get_res >= sizeof(buf)) {
193  return false;
194  }
195 
196  if (get_res == 0) {
197  return false;
198  }
199 
200  *var_value = std::string(buf, get_res);
201 #else
202  const char* val = ::getenv(var_name);
203  if (val == nullptr) {
204  return false;
205  }
206 
207  *var_value = val;
208 #endif
209 
210  return true;
211 }
212 
213 // --------------------------------------------------------------------
214 
215 // Returns:
216 // Flag name or empty if arg= --
217 // Flag value after = in --flag=value (empty if --foo)
218 // "Is empty value" status. True if arg= --foo=, false otherwise. This is
219 // required to separate --foo from --foo=.
220 // For example:
221 // arg return values
222 // "--foo=bar" -> {"foo", "bar", false}.
223 // "--foo" -> {"foo", "", false}.
224 // "--foo=" -> {"foo", "", true}.
225 std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
227  // Allow -foo and --foo
228  absl::ConsumePrefix(&arg, "-");
229 
230  if (arg.empty()) {
231  return std::make_tuple("", "", false);
232  }
233 
234  auto equal_sign_pos = arg.find("=");
235 
236  absl::string_view flag_name = arg.substr(0, equal_sign_pos);
237 
239  bool is_empty_value = false;
240 
241  if (equal_sign_pos != absl::string_view::npos) {
242  value = arg.substr(equal_sign_pos + 1);
243  is_empty_value = value.empty();
244  }
245 
246  return std::make_tuple(flag_name, value, is_empty_value);
247 }
248 
249 // --------------------------------------------------------------------
250 
251 // Returns:
252 // found flag or nullptr
253 // is negative in case of --nofoo
254 std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
255  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(flag_name);
256  bool is_negative = false;
257 
258  if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
259  flag = flags_internal::FindCommandLineFlag(flag_name);
260  is_negative = true;
261  }
262 
263  return std::make_tuple(flag, is_negative);
264 }
265 
266 // --------------------------------------------------------------------
267 
268 // Verify that default values of typed flags must be convertible to string and
269 // back.
270 void CheckDefaultValuesParsingRoundtrip() {
271 #ifndef NDEBUG
272  flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
273  if (flag->IsRetired()) return;
274 
275 #define IGNORE_TYPE(T) \
276  if (flag->IsOfType<T>()) return;
277 
279  IGNORE_TYPE(std::string)
280  IGNORE_TYPE(std::vector<std::string>)
281 #undef IGNORE_TYPE
282 
284 
285  std::string v = flag->DefaultValue();
286  void* dst = Clone(flag->op, flag->def);
287  std::string error;
288  if (!flags_internal::Parse(flag->marshalling_op, v, dst, &error)) {
290  FATAL,
291  absl::StrCat("Flag ", flag->Name(), " (from ", flag->Filename(),
292  "): std::string form of default value '", v,
293  "' could not be parsed; error=", error));
294  }
295 
296  // We do not compare dst to def since parsing/unparsing may make
297  // small changes, e.g., precision loss for floating point types.
298  Delete(flag->op, dst);
299  });
300 #endif
301 }
302 
303 // --------------------------------------------------------------------
304 
305 // Returns success status, which is true if we successfully read all flag files,
306 // in which case new ArgLists are appended to the input_args in a reverse order
307 // of file names in the input flagfiles list. This order ensures that flags from
308 // the first flagfile in the input list are processed before the second flagfile
309 // etc.
310 bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
311  std::vector<ArgsList>* input_args) {
312  bool success = true;
313  for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
314  ArgsList al;
315 
316  if (al.ReadFromFlagfile(*it)) {
317  input_args->push_back(al);
318  } else {
319  success = false;
320  }
321  }
322 
323  return success;
324 }
325 
326 // Returns success status, which is true if were able to locate all environment
327 // variables correctly or if fail_on_absent_in_env is false. The environment
328 // variable names are expected to be of the form `FLAGS_<flag_name>`, where
329 // `flag_name` is a string from the input flag_names list. If successful we
330 // append a single ArgList at the end of the input_args.
331 bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
332  std::vector<ArgsList>* input_args,
333  bool fail_on_absent_in_env) {
334  bool success = true;
335  std::vector<std::string> args;
336 
337  // This argument represents fake argv[0], which should be present in all arg
338  // lists.
339  args.push_back("");
340 
341  for (const auto& flag_name : flag_names) {
342  // Avoid infinite recursion.
343  if (flag_name == "fromenv" || flag_name == "tryfromenv") {
345  absl::StrCat("Infinite recursion on flag ", flag_name), true);
346 
347  success = false;
348  continue;
349  }
350 
351  const std::string envname = absl::StrCat("FLAGS_", flag_name);
352  std::string envval;
353  if (!GetEnvVar(envname.c_str(), &envval)) {
354  if (fail_on_absent_in_env) {
356  absl::StrCat(envname, " not found in environment"), true);
357 
358  success = false;
359  }
360 
361  continue;
362  }
363 
364  args.push_back(absl::StrCat("--", flag_name, "=", envval));
365  }
366 
367  if (success) {
368  input_args->emplace_back(args);
369  }
370 
371  return success;
372 }
373 
374 // --------------------------------------------------------------------
375 
376 // Returns success status, which is true if were able to handle all generator
377 // flags (flagfile, fromenv, tryfromemv) successfully.
378 bool HandleGeneratorFlags(std::vector<ArgsList>* input_args,
379  std::vector<std::string>* flagfile_value) {
380  bool success = true;
381 
382  absl::MutexLock l(&flags_internal::processing_checks_guard);
383 
384  // flagfile could have been set either on a command line or
385  // programmatically before invoking ParseCommandLine. Note that we do not
386  // actually process arguments specified in the flagfile, but instead
387  // create a secondary arguments list to be processed along with the rest
388  // of the comamnd line arguments. Since we always the process most recently
389  // created list of arguments first, this will result in flagfile argument
390  // being processed before any other argument in the command line. If
391  // FLAGS_flagfile contains more than one file name we create multiple new
392  // levels of arguments in a reverse order of file names. Thus we always
393  // process arguments from first file before arguments containing in a
394  // second file, etc. If flagfile contains another
395  // --flagfile inside of it, it will produce new level of arguments and
396  // processed before the rest of the flagfile. We are also collecting all
397  // flagfiles set on original command line. Unlike the rest of the flags,
398  // this flag can be set multiple times and is expected to be handled
399  // multiple times. We are collecting them all into a single list and set
400  // the value of FLAGS_flagfile to that value at the end of the parsing.
401  if (flags_internal::flagfile_needs_processing) {
402  auto flagfiles = absl::GetFlag(FLAGS_flagfile);
403 
404  if (input_args->size() == 1) {
405  flagfile_value->insert(flagfile_value->end(), flagfiles.begin(),
406  flagfiles.end());
407  }
408 
409  success &= ReadFlagfiles(flagfiles, input_args);
410 
411  flags_internal::flagfile_needs_processing = false;
412  }
413 
414  // Similar to flagfile fromenv/tryfromemv can be set both
415  // programmatically and at runtime on a command line. Unlike flagfile these
416  // can't be recursive.
417  if (flags_internal::fromenv_needs_processing) {
418  auto flags_list = absl::GetFlag(FLAGS_fromenv);
419 
420  success &= ReadFlagsFromEnv(flags_list, input_args, true);
421 
422  flags_internal::fromenv_needs_processing = false;
423  }
424 
425  if (flags_internal::tryfromenv_needs_processing) {
426  auto flags_list = absl::GetFlag(FLAGS_tryfromenv);
427 
428  success &= ReadFlagsFromEnv(flags_list, input_args, false);
429 
430  flags_internal::tryfromenv_needs_processing = false;
431  }
432 
433  return success;
434 }
435 
436 // --------------------------------------------------------------------
437 
438 void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) {
439  // Setting flagfile to the value which collates all the values set on a
440  // command line and programmatically. So if command line looked like
441  // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
442  // going to be {"f1", "f2"}
443  if (!flagfile_value.empty()) {
444  absl::SetFlag(&FLAGS_flagfile, flagfile_value);
445  absl::MutexLock l(&flags_internal::processing_checks_guard);
446  flags_internal::flagfile_needs_processing = false;
447  }
448 
449  // fromenv/tryfromenv are set to <undefined> value.
450  if (!absl::GetFlag(FLAGS_fromenv).empty()) {
451  absl::SetFlag(&FLAGS_fromenv, {});
452  }
453  if (!absl::GetFlag(FLAGS_tryfromenv).empty()) {
454  absl::SetFlag(&FLAGS_tryfromenv, {});
455  }
456 
457  absl::MutexLock l(&flags_internal::processing_checks_guard);
458  flags_internal::fromenv_needs_processing = false;
459  flags_internal::tryfromenv_needs_processing = false;
460 }
461 
462 // --------------------------------------------------------------------
463 
464 // Returns:
465 // success status
466 // deduced value
467 // We are also mutating curr_list in case if we need to get a hold of next
468 // argument in the input.
469 std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
471  bool is_negative,
472  bool is_empty_value,
473  ArgsList* curr_list) {
474  // Value is either an argument suffix after `=` in "--foo=<value>"
475  // or separate argument in case of "--foo" "<value>".
476 
477  // boolean flags have these forms:
478  // --foo
479  // --nofoo
480  // --foo=true
481  // --foo=false
482  // --nofoo=<value> is not supported
483  // --foo <value> is not supported
484 
485  // non boolean flags have these forms:
486  // --foo=<value>
487  // --foo <value>
488  // --nofoo is not supported
489 
490  if (flag.IsOfType<bool>()) {
491  if (value.empty()) {
492  if (is_empty_value) {
493  // "--bool_flag=" case
495  absl::StrCat(
496  "Missing the value after assignment for the boolean flag '",
497  flag.Name(), "'"),
498  true);
499  return std::make_tuple(false, "");
500  }
501 
502  // "--bool_flag" case
503  value = is_negative ? "0" : "1";
504  } else if (is_negative) {
505  // "--nobool_flag=Y" case
507  absl::StrCat("Negative form with assignment is not valid for the "
508  "boolean flag '",
509  flag.Name(), "'"),
510  true);
511  return std::make_tuple(false, "");
512  }
513  } else if (is_negative) {
514  // "--noint_flag=1" case
516  absl::StrCat("Negative form is not valid for the flag '", flag.Name(),
517  "'"),
518  true);
519  return std::make_tuple(false, "");
520  } else if (value.empty() && (!is_empty_value)) {
521  if (curr_list->Size() == 1) {
522  // "--int_flag" case
524  absl::StrCat("Missing the value for the flag '", flag.Name(), "'"),
525  true);
526  return std::make_tuple(false, "");
527  }
528 
529  // "--int_flag" "10" case
530  curr_list->PopFront();
531  value = curr_list->Front();
532 
533  // Heuristic to detect the case where someone treats a std::string arg
534  // like a bool or just forgets to pass a value:
535  // --my_string_var --foo=bar
536  // We look for a flag of std::string type, whose value begins with a
537  // dash and corresponds to known flag or standalone --.
538  if (value[0] == '-' && flag.IsOfType<std::string>()) {
539  auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
540 
541  if (maybe_flag_name.empty() ||
542  std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {
543  // "--string_flag" "--known_flag" case
545  WARNING,
546  absl::StrCat("Did you really mean to set flag '", flag.Name(),
547  "' to the value '", value, "'?"));
548  }
549  }
550  }
551 
552  return std::make_tuple(true, value);
553 }
554 
555 // --------------------------------------------------------------------
556 
557 bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
558  auto undefok = absl::GetFlag(FLAGS_undefok);
559  if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
560  return true;
561  }
562 
563  if (absl::ConsumePrefix(&flag_name, "no") &&
564  std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
565  return true;
566  }
567 
568  return false;
569 }
570 
571 } // namespace
572 
573 // --------------------------------------------------------------------
574 
575 std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
576  ArgvListAction arg_list_act,
577  UsageFlagsAction usage_flag_act,
578  OnUndefinedFlag on_undef_flag) {
579  ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
580 
581  // This routine does not return anything since we abort on failure.
582  CheckDefaultValuesParsingRoundtrip();
583 
584  std::vector<std::string> flagfile_value;
585 
586  std::vector<ArgsList> input_args;
587  input_args.push_back(ArgsList(argc, argv));
588 
589  std::vector<char*> output_args;
590  std::vector<char*> positional_args;
591  output_args.reserve(argc);
592 
593  // This is the list of undefined flags. The element of the list is the pair
594  // consisting of boolean indicating if flag came from command line (vs from
595  // some flag file we've read) and flag name.
596  // TODO(rogeeff): Eliminate the first element in the pair after cleanup.
597  std::vector<std::pair<bool, std::string>> undefined_flag_names;
598 
599  // Set program invocation name if it is not set before.
600  if (ProgramInvocationName() == "UNKNOWN") {
602  }
603  output_args.push_back(argv[0]);
604 
605  // Iterate through the list of the input arguments. First level are arguments
606  // originated from argc/argv. Following levels are arguments originated from
607  // recursive parsing of flagfile(s).
608  bool success = true;
609  while (!input_args.empty()) {
610  // 10. First we process the built-in generator flags.
611  success &= HandleGeneratorFlags(&input_args, &flagfile_value);
612 
613  // 30. Select top-most (most recent) arguments list. If it is empty drop it
614  // and re-try.
615  ArgsList& curr_list = input_args.back();
616 
617  curr_list.PopFront();
618 
619  if (curr_list.Size() == 0) {
620  input_args.pop_back();
621  continue;
622  }
623 
624  // 40. Pick up the front remaining argument in the current list. If current
625  // stack of argument lists contains only one element - we are processing an
626  // argument from the original argv.
627  absl::string_view arg(curr_list.Front());
628  bool arg_from_argv = input_args.size() == 1;
629 
630  // 50. If argument does not start with - or is just "-" - this is
631  // positional argument.
632  if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) {
633  ABSL_INTERNAL_CHECK(arg_from_argv,
634  "Flagfile cannot contain positional argument");
635 
636  positional_args.push_back(argv[curr_list.FrontIndex()]);
637  continue;
638  }
639 
640  if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs)) {
641  output_args.push_back(argv[curr_list.FrontIndex()]);
642  }
643 
644  // 60. Split the current argument on '=' to figure out the argument
645  // name and value. If flag name is empty it means we've got "--". value
646  // can be empty either if there were no '=' in argument std::string at all or
647  // an argument looked like "--foo=". In a latter case is_empty_value is
648  // true.
649  absl::string_view flag_name;
651  bool is_empty_value = false;
652 
653  std::tie(flag_name, value, is_empty_value) = SplitNameAndValue(arg);
654 
655  // 70. "--" alone means what it does for GNU: stop flags parsing. We do
656  // not support positional arguments in flagfiles, so we just drop them.
657  if (flag_name.empty()) {
658  ABSL_INTERNAL_CHECK(arg_from_argv,
659  "Flagfile cannot contain positional argument");
660 
661  curr_list.PopFront();
662  break;
663  }
664 
665  // 80. Locate the flag based on flag name. Handle both --foo and --nofoo
666  CommandLineFlag* flag = nullptr;
667  bool is_negative = false;
668  std::tie(flag, is_negative) = LocateFlag(flag_name);
669 
670  if (flag == nullptr) {
671  if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
672  undefined_flag_names.emplace_back(arg_from_argv,
673  std::string(flag_name));
674  }
675  continue;
676  }
677 
678  // 90. Deduce flag's value (from this or next argument)
679  auto curr_index = curr_list.FrontIndex();
680  bool value_success = true;
681  std::tie(value_success, value) =
682  DeduceFlagValue(*flag, value, is_negative, is_empty_value, &curr_list);
683  success &= value_success;
684 
685  // If above call consumed an argument, it was a standalone value
686  if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs) &&
687  (curr_index != curr_list.FrontIndex())) {
688  output_args.push_back(argv[curr_list.FrontIndex()]);
689  }
690 
691  // 100. Set the located flag to a new new value, unless it is retired.
692  // Setting retired flag fails, but we ignoring it here.
693  if (flag->IsRetired()) continue;
694 
695  std::string error;
696  if (!flag->SetFromString(value, SET_FLAGS_VALUE, kCommandLine, &error)) {
698  success = false;
699  }
700  }
701 
702  for (const auto& flag_name : undefined_flag_names) {
703  if (CanIgnoreUndefinedFlag(flag_name.second)) continue;
704 
706  absl::StrCat("Unknown command line flag '", flag_name.second, "'"),
707  true);
708 
709  success = false;
710  }
711 
712 #if ABSL_FLAGS_STRIP_NAMES
713  if (!success) {
715  "NOTE: command line flags are disabled in this build", true);
716  }
717 #endif
718 
719  if (!success) {
721  std::exit(1);
722  }
723 
724  if (usage_flag_act == UsageFlagsAction::kHandleUsage) {
725  int exit_code = flags_internal::HandleUsageFlags(std::cout);
726 
727  if (exit_code != -1) {
728  std::exit(exit_code);
729  }
730  }
731 
732  ResetGeneratorFlags(flagfile_value);
733 
734  // Reinstate positional args which were intermixed with flags in the arguments
735  // list.
736  for (auto arg : positional_args) {
737  output_args.push_back(arg);
738  }
739 
740  // All the remaining arguments are positional.
741  if (!input_args.empty()) {
742  for (int arg_index = input_args.back().FrontIndex(); arg_index < argc;
743  ++arg_index) {
744  output_args.push_back(argv[arg_index]);
745  }
746  }
747 
748  return output_args;
749 }
750 
751 } // namespace flags_internal
752 
753 // --------------------------------------------------------------------
754 
755 std::vector<char*> ParseCommandLine(int argc, char* argv[]) {
760 }
761 
762 } // namespace absl
int v
Definition: variant_test.cc:81
void Delete(FlagOpFn op, const void *obj)
bool Parse(FlagMarshallingOpFn op, absl::string_view text, void *dst, std::string *error)
std::vector< char * > ParseCommandLine(int argc, char *argv[])
Definition: parse.cc:755
string_view substr(size_type pos, size_type n=npos) const
Definition: string_view.h:354
absl::Mutex * InitFlagIfNecessary(CommandLineFlag *flag) LOCK_RETURNED(flag-> locks->primary_mu)
#define IGNORE_TYPE(T)
#define ABSL_CONST_INIT
Definition: attributes.h:605
size_type find(string_view s, size_type pos=0) const noexcept
Definition: string_view.cc:92
static constexpr size_type npos
Definition: string_view.h:159
#define ABSL_INTERNAL_CHECK(condition, message)
Definition: raw_logging.h:83
void * Clone(FlagOpFn op, const void *obj)
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: str_cat.cc:98
std::vector< char * > ParseCommandLineImpl(int argc, char *argv[], ArgvListAction arg_list_act, UsageFlagsAction usage_flag_act, OnUndefinedFlag on_undef_flag)
Definition: parse.cc:575
#define ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(A)
char buf[N]
std::vector< std::string > args_
Definition: parse.cc:130
Definition: algorithm.h:29
bool SetFromString(absl::string_view value, flags_internal::FlagSettingMode set_mode, flags_internal::ValueSource source, std::string *error)
std::string ProgramInvocationName()
Definition: program_name.cc:30
#define ABSL_INTERNAL_LOG(severity, message)
Definition: raw_logging.h:73
bool ConsumePrefix(absl::string_view *str, absl::string_view expected)
Definition: strip.h:44
size_t value
CommandLineFlag * FindCommandLineFlag(absl::string_view name)
Definition: registry.cc:427
int HandleUsageFlags(std::ostream &out)
Definition: usage.cc:334
ABSL_MUST_USE_RESULT absl::string_view StripLeadingAsciiWhitespace(absl::string_view str)
Definition: ascii.h:195
constexpr bool empty() const noexcept
Definition: string_view.h:277
void * arg
Definition: mutex.cc:292
void ReportUsageError(absl::string_view msg, bool is_fatal)
static ABSL_CONST_INIT std::string *program_name GUARDED_BY(program_name_guard)
void SetProgramInvocationName(absl::string_view prog_name_str)
Definition: program_name.cc:43
T GetFlag(const absl::Flag< T > &flag)
Definition: flag.h:86
ABSL_FLAG(std::vector< std::string >, flagfile,{},"comma-separated list of files to load flags from").OnUpdate([]()
Definition: parse.cc:55
void SetFlag(absl::Flag< T > *flag, const T &v)
Definition: flag.h:134
int next_arg_
Definition: parse.cc:131
void ForEachFlag(std::function< void(CommandLineFlag *)> visitor)
Definition: registry.cc:459


abseil_cpp
Author(s):
autogenerated on Tue Jun 18 2019 19:44:36