xref: /aosp_15_r20/external/abseil-cpp/absl/flags/parse.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker //
2*9356374aSAndroid Build Coastguard Worker // Copyright 2019 The Abseil Authors.
3*9356374aSAndroid Build Coastguard Worker //
4*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*9356374aSAndroid Build Coastguard Worker //
8*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
9*9356374aSAndroid Build Coastguard Worker //
10*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*9356374aSAndroid Build Coastguard Worker // limitations under the License.
15*9356374aSAndroid Build Coastguard Worker 
16*9356374aSAndroid Build Coastguard Worker #include "absl/flags/parse.h"
17*9356374aSAndroid Build Coastguard Worker 
18*9356374aSAndroid Build Coastguard Worker #include <stdlib.h>
19*9356374aSAndroid Build Coastguard Worker 
20*9356374aSAndroid Build Coastguard Worker #include <algorithm>
21*9356374aSAndroid Build Coastguard Worker #include <cstdint>
22*9356374aSAndroid Build Coastguard Worker #include <cstdlib>
23*9356374aSAndroid Build Coastguard Worker #include <fstream>
24*9356374aSAndroid Build Coastguard Worker #include <iostream>
25*9356374aSAndroid Build Coastguard Worker #include <ostream>
26*9356374aSAndroid Build Coastguard Worker #include <string>
27*9356374aSAndroid Build Coastguard Worker #include <tuple>
28*9356374aSAndroid Build Coastguard Worker #include <utility>
29*9356374aSAndroid Build Coastguard Worker #include <vector>
30*9356374aSAndroid Build Coastguard Worker 
31*9356374aSAndroid Build Coastguard Worker #ifdef _WIN32
32*9356374aSAndroid Build Coastguard Worker #include <windows.h>
33*9356374aSAndroid Build Coastguard Worker #endif
34*9356374aSAndroid Build Coastguard Worker 
35*9356374aSAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/base/const_init.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/base/thread_annotations.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/flags/commandlineflag.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/flags/config.h"
42*9356374aSAndroid Build Coastguard Worker #include "absl/flags/flag.h"
43*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/commandlineflag.h"
44*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/flag.h"
45*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/parse.h"
46*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/private_handle_accessor.h"
47*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/program_name.h"
48*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/usage.h"
49*9356374aSAndroid Build Coastguard Worker #include "absl/flags/reflection.h"
50*9356374aSAndroid Build Coastguard Worker #include "absl/flags/usage.h"
51*9356374aSAndroid Build Coastguard Worker #include "absl/flags/usage_config.h"
52*9356374aSAndroid Build Coastguard Worker #include "absl/strings/ascii.h"
53*9356374aSAndroid Build Coastguard Worker #include "absl/strings/internal/damerau_levenshtein_distance.h"
54*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
55*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_join.h"
56*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
57*9356374aSAndroid Build Coastguard Worker #include "absl/strings/strip.h"
58*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h"
59*9356374aSAndroid Build Coastguard Worker 
60*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
61*9356374aSAndroid Build Coastguard Worker 
62*9356374aSAndroid Build Coastguard Worker namespace absl {
63*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
64*9356374aSAndroid Build Coastguard Worker namespace flags_internal {
65*9356374aSAndroid Build Coastguard Worker namespace {
66*9356374aSAndroid Build Coastguard Worker 
67*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
68*9356374aSAndroid Build Coastguard Worker 
69*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT bool flagfile_needs_processing
70*9356374aSAndroid Build Coastguard Worker     ABSL_GUARDED_BY(processing_checks_guard) = false;
71*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT bool fromenv_needs_processing
72*9356374aSAndroid Build Coastguard Worker     ABSL_GUARDED_BY(processing_checks_guard) = false;
73*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT bool tryfromenv_needs_processing
74*9356374aSAndroid Build Coastguard Worker     ABSL_GUARDED_BY(processing_checks_guard) = false;
75*9356374aSAndroid Build Coastguard Worker 
76*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
77*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
78*9356374aSAndroid Build Coastguard Worker     ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
79*9356374aSAndroid Build Coastguard Worker 
80*9356374aSAndroid Build Coastguard Worker // Suggesting at most kMaxHints flags in case of misspellings.
81*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT const size_t kMaxHints = 100;
82*9356374aSAndroid Build Coastguard Worker // Suggesting only flags which have a smaller distance than kMaxDistance.
83*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT const size_t kMaxDistance = 3;
84*9356374aSAndroid Build Coastguard Worker 
85*9356374aSAndroid Build Coastguard Worker struct SpecifiedFlagsCompare {
operator ()absl::flags_internal::__anon3f9691520111::SpecifiedFlagsCompare86*9356374aSAndroid Build Coastguard Worker   bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
87*9356374aSAndroid Build Coastguard Worker     return a->Name() < b->Name();
88*9356374aSAndroid Build Coastguard Worker   }
operator ()absl::flags_internal::__anon3f9691520111::SpecifiedFlagsCompare89*9356374aSAndroid Build Coastguard Worker   bool operator()(const CommandLineFlag* a, absl::string_view b) const {
90*9356374aSAndroid Build Coastguard Worker     return a->Name() < b;
91*9356374aSAndroid Build Coastguard Worker   }
operator ()absl::flags_internal::__anon3f9691520111::SpecifiedFlagsCompare92*9356374aSAndroid Build Coastguard Worker   bool operator()(absl::string_view a, const CommandLineFlag* b) const {
93*9356374aSAndroid Build Coastguard Worker     return a < b->Name();
94*9356374aSAndroid Build Coastguard Worker   }
95*9356374aSAndroid Build Coastguard Worker };
96*9356374aSAndroid Build Coastguard Worker 
97*9356374aSAndroid Build Coastguard Worker }  // namespace
98*9356374aSAndroid Build Coastguard Worker }  // namespace flags_internal
99*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
100*9356374aSAndroid Build Coastguard Worker }  // namespace absl
101*9356374aSAndroid Build Coastguard Worker 
102*9356374aSAndroid Build Coastguard Worker // These flags influence how command line flags are parsed and are only intended
103*9356374aSAndroid Build Coastguard Worker // to be set on the command line.  Avoid reading or setting them from C++ code.
104*9356374aSAndroid Build Coastguard Worker ABSL_FLAG(std::vector<std::string>, flagfile, {},
105*9356374aSAndroid Build Coastguard Worker           "comma-separated list of files to load flags from")
__anon3f9691520202() 106*9356374aSAndroid Build Coastguard Worker     .OnUpdate([]() {
107*9356374aSAndroid Build Coastguard Worker       if (absl::GetFlag(FLAGS_flagfile).empty()) return;
108*9356374aSAndroid Build Coastguard Worker 
109*9356374aSAndroid Build Coastguard Worker       absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
110*9356374aSAndroid Build Coastguard Worker 
111*9356374aSAndroid Build Coastguard Worker       // Setting this flag twice before it is handled most likely an internal
112*9356374aSAndroid Build Coastguard Worker       // error and should be reviewed by developers.
113*9356374aSAndroid Build Coastguard Worker       if (absl::flags_internal::flagfile_needs_processing) {
114*9356374aSAndroid Build Coastguard Worker         ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled");
115*9356374aSAndroid Build Coastguard Worker       }
116*9356374aSAndroid Build Coastguard Worker 
117*9356374aSAndroid Build Coastguard Worker       absl::flags_internal::flagfile_needs_processing = true;
118*9356374aSAndroid Build Coastguard Worker     });
119*9356374aSAndroid Build Coastguard Worker ABSL_FLAG(std::vector<std::string>, fromenv, {},
120*9356374aSAndroid Build Coastguard Worker           "comma-separated list of flags to set from the environment"
121*9356374aSAndroid Build Coastguard Worker           " [use 'export FLAGS_flag1=value']")
__anon3f9691520302() 122*9356374aSAndroid Build Coastguard Worker     .OnUpdate([]() {
123*9356374aSAndroid Build Coastguard Worker       if (absl::GetFlag(FLAGS_fromenv).empty()) return;
124*9356374aSAndroid Build Coastguard Worker 
125*9356374aSAndroid Build Coastguard Worker       absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
126*9356374aSAndroid Build Coastguard Worker 
127*9356374aSAndroid Build Coastguard Worker       // Setting this flag twice before it is handled most likely an internal
128*9356374aSAndroid Build Coastguard Worker       // error and should be reviewed by developers.
129*9356374aSAndroid Build Coastguard Worker       if (absl::flags_internal::fromenv_needs_processing) {
130*9356374aSAndroid Build Coastguard Worker         ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled.");
131*9356374aSAndroid Build Coastguard Worker       }
132*9356374aSAndroid Build Coastguard Worker 
133*9356374aSAndroid Build Coastguard Worker       absl::flags_internal::fromenv_needs_processing = true;
134*9356374aSAndroid Build Coastguard Worker     });
135*9356374aSAndroid Build Coastguard Worker ABSL_FLAG(std::vector<std::string>, tryfromenv, {},
136*9356374aSAndroid Build Coastguard Worker           "comma-separated list of flags to try to set from the environment if "
137*9356374aSAndroid Build Coastguard Worker           "present")
__anon3f9691520402() 138*9356374aSAndroid Build Coastguard Worker     .OnUpdate([]() {
139*9356374aSAndroid Build Coastguard Worker       if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;
140*9356374aSAndroid Build Coastguard Worker 
141*9356374aSAndroid Build Coastguard Worker       absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
142*9356374aSAndroid Build Coastguard Worker 
143*9356374aSAndroid Build Coastguard Worker       // Setting this flag twice before it is handled most likely an internal
144*9356374aSAndroid Build Coastguard Worker       // error and should be reviewed by developers.
145*9356374aSAndroid Build Coastguard Worker       if (absl::flags_internal::tryfromenv_needs_processing) {
146*9356374aSAndroid Build Coastguard Worker         ABSL_INTERNAL_LOG(WARNING,
147*9356374aSAndroid Build Coastguard Worker                           "tryfromenv set twice before it is handled.");
148*9356374aSAndroid Build Coastguard Worker       }
149*9356374aSAndroid Build Coastguard Worker 
150*9356374aSAndroid Build Coastguard Worker       absl::flags_internal::tryfromenv_needs_processing = true;
151*9356374aSAndroid Build Coastguard Worker     });
152*9356374aSAndroid Build Coastguard Worker 
153*9356374aSAndroid Build Coastguard Worker // Rather than reading or setting --undefok from C++ code, please consider using
154*9356374aSAndroid Build Coastguard Worker // ABSL_RETIRED_FLAG instead.
155*9356374aSAndroid Build Coastguard Worker ABSL_FLAG(std::vector<std::string>, undefok, {},
156*9356374aSAndroid Build Coastguard Worker           "comma-separated list of flag names that it is okay to specify "
157*9356374aSAndroid Build Coastguard Worker           "on the command line even if the program does not define a flag "
158*9356374aSAndroid Build Coastguard Worker           "with that name");
159*9356374aSAndroid Build Coastguard Worker 
160*9356374aSAndroid Build Coastguard Worker namespace absl {
161*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
162*9356374aSAndroid Build Coastguard Worker namespace flags_internal {
163*9356374aSAndroid Build Coastguard Worker 
164*9356374aSAndroid Build Coastguard Worker namespace {
165*9356374aSAndroid Build Coastguard Worker 
166*9356374aSAndroid Build Coastguard Worker class ArgsList {
167*9356374aSAndroid Build Coastguard Worker  public:
ArgsList()168*9356374aSAndroid Build Coastguard Worker   ArgsList() : next_arg_(0) {}
ArgsList(int argc,char * argv[])169*9356374aSAndroid Build Coastguard Worker   ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}
ArgsList(const std::vector<std::string> & args)170*9356374aSAndroid Build Coastguard Worker   explicit ArgsList(const std::vector<std::string>& args)
171*9356374aSAndroid Build Coastguard Worker       : args_(args), next_arg_(0) {}
172*9356374aSAndroid Build Coastguard Worker 
173*9356374aSAndroid Build Coastguard Worker   // Returns success status: true if parsing successful, false otherwise.
174*9356374aSAndroid Build Coastguard Worker   bool ReadFromFlagfile(const std::string& flag_file_name);
175*9356374aSAndroid Build Coastguard Worker 
Size() const176*9356374aSAndroid Build Coastguard Worker   size_t Size() const { return args_.size() - next_arg_; }
FrontIndex() const177*9356374aSAndroid Build Coastguard Worker   size_t FrontIndex() const { return next_arg_; }
Front() const178*9356374aSAndroid Build Coastguard Worker   absl::string_view Front() const { return args_[next_arg_]; }
PopFront()179*9356374aSAndroid Build Coastguard Worker   void PopFront() { next_arg_++; }
180*9356374aSAndroid Build Coastguard Worker 
181*9356374aSAndroid Build Coastguard Worker  private:
182*9356374aSAndroid Build Coastguard Worker   std::vector<std::string> args_;
183*9356374aSAndroid Build Coastguard Worker   size_t next_arg_;
184*9356374aSAndroid Build Coastguard Worker };
185*9356374aSAndroid Build Coastguard Worker 
ReadFromFlagfile(const std::string & flag_file_name)186*9356374aSAndroid Build Coastguard Worker bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
187*9356374aSAndroid Build Coastguard Worker   std::ifstream flag_file(flag_file_name);
188*9356374aSAndroid Build Coastguard Worker 
189*9356374aSAndroid Build Coastguard Worker   if (!flag_file) {
190*9356374aSAndroid Build Coastguard Worker     flags_internal::ReportUsageError(
191*9356374aSAndroid Build Coastguard Worker         absl::StrCat("Can't open flagfile ", flag_file_name), true);
192*9356374aSAndroid Build Coastguard Worker 
193*9356374aSAndroid Build Coastguard Worker     return false;
194*9356374aSAndroid Build Coastguard Worker   }
195*9356374aSAndroid Build Coastguard Worker 
196*9356374aSAndroid Build Coastguard Worker   // This argument represents fake argv[0], which should be present in all arg
197*9356374aSAndroid Build Coastguard Worker   // lists.
198*9356374aSAndroid Build Coastguard Worker   args_.emplace_back("");
199*9356374aSAndroid Build Coastguard Worker 
200*9356374aSAndroid Build Coastguard Worker   std::string line;
201*9356374aSAndroid Build Coastguard Worker   bool success = true;
202*9356374aSAndroid Build Coastguard Worker 
203*9356374aSAndroid Build Coastguard Worker   while (std::getline(flag_file, line)) {
204*9356374aSAndroid Build Coastguard Worker     absl::string_view stripped = absl::StripLeadingAsciiWhitespace(line);
205*9356374aSAndroid Build Coastguard Worker 
206*9356374aSAndroid Build Coastguard Worker     if (stripped.empty() || stripped[0] == '#') {
207*9356374aSAndroid Build Coastguard Worker       // Comment or empty line; just ignore.
208*9356374aSAndroid Build Coastguard Worker       continue;
209*9356374aSAndroid Build Coastguard Worker     }
210*9356374aSAndroid Build Coastguard Worker 
211*9356374aSAndroid Build Coastguard Worker     if (stripped[0] == '-') {
212*9356374aSAndroid Build Coastguard Worker       if (stripped == "--") {
213*9356374aSAndroid Build Coastguard Worker         flags_internal::ReportUsageError(
214*9356374aSAndroid Build Coastguard Worker             "Flagfile can't contain position arguments or --", true);
215*9356374aSAndroid Build Coastguard Worker 
216*9356374aSAndroid Build Coastguard Worker         success = false;
217*9356374aSAndroid Build Coastguard Worker         break;
218*9356374aSAndroid Build Coastguard Worker       }
219*9356374aSAndroid Build Coastguard Worker 
220*9356374aSAndroid Build Coastguard Worker       args_.emplace_back(stripped);
221*9356374aSAndroid Build Coastguard Worker       continue;
222*9356374aSAndroid Build Coastguard Worker     }
223*9356374aSAndroid Build Coastguard Worker 
224*9356374aSAndroid Build Coastguard Worker     flags_internal::ReportUsageError(
225*9356374aSAndroid Build Coastguard Worker         absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ",
226*9356374aSAndroid Build Coastguard Worker                      line),
227*9356374aSAndroid Build Coastguard Worker         true);
228*9356374aSAndroid Build Coastguard Worker 
229*9356374aSAndroid Build Coastguard Worker     success = false;
230*9356374aSAndroid Build Coastguard Worker   }
231*9356374aSAndroid Build Coastguard Worker 
232*9356374aSAndroid Build Coastguard Worker   return success;
233*9356374aSAndroid Build Coastguard Worker }
234*9356374aSAndroid Build Coastguard Worker 
235*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
236*9356374aSAndroid Build Coastguard Worker 
237*9356374aSAndroid Build Coastguard Worker // Reads the environment variable with name `name` and stores results in
238*9356374aSAndroid Build Coastguard Worker // `value`. If variable is not present in environment returns false, otherwise
239*9356374aSAndroid Build Coastguard Worker // returns true.
GetEnvVar(const char * var_name,std::string & var_value)240*9356374aSAndroid Build Coastguard Worker bool GetEnvVar(const char* var_name, std::string& var_value) {
241*9356374aSAndroid Build Coastguard Worker #ifdef _WIN32
242*9356374aSAndroid Build Coastguard Worker   char buf[1024];
243*9356374aSAndroid Build Coastguard Worker   auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
244*9356374aSAndroid Build Coastguard Worker   if (get_res >= sizeof(buf)) {
245*9356374aSAndroid Build Coastguard Worker     return false;
246*9356374aSAndroid Build Coastguard Worker   }
247*9356374aSAndroid Build Coastguard Worker 
248*9356374aSAndroid Build Coastguard Worker   if (get_res == 0) {
249*9356374aSAndroid Build Coastguard Worker     return false;
250*9356374aSAndroid Build Coastguard Worker   }
251*9356374aSAndroid Build Coastguard Worker 
252*9356374aSAndroid Build Coastguard Worker   var_value = std::string(buf, get_res);
253*9356374aSAndroid Build Coastguard Worker #else
254*9356374aSAndroid Build Coastguard Worker   const char* val = ::getenv(var_name);
255*9356374aSAndroid Build Coastguard Worker   if (val == nullptr) {
256*9356374aSAndroid Build Coastguard Worker     return false;
257*9356374aSAndroid Build Coastguard Worker   }
258*9356374aSAndroid Build Coastguard Worker 
259*9356374aSAndroid Build Coastguard Worker   var_value = val;
260*9356374aSAndroid Build Coastguard Worker #endif
261*9356374aSAndroid Build Coastguard Worker 
262*9356374aSAndroid Build Coastguard Worker   return true;
263*9356374aSAndroid Build Coastguard Worker }
264*9356374aSAndroid Build Coastguard Worker 
265*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
266*9356374aSAndroid Build Coastguard Worker 
267*9356374aSAndroid Build Coastguard Worker // Returns:
268*9356374aSAndroid Build Coastguard Worker //  Flag name or empty if arg= --
269*9356374aSAndroid Build Coastguard Worker //  Flag value after = in --flag=value (empty if --foo)
270*9356374aSAndroid Build Coastguard Worker //  "Is empty value" status. True if arg= --foo=, false otherwise. This is
271*9356374aSAndroid Build Coastguard Worker //  required to separate --foo from --foo=.
272*9356374aSAndroid Build Coastguard Worker // For example:
273*9356374aSAndroid Build Coastguard Worker //      arg           return values
274*9356374aSAndroid Build Coastguard Worker //   "--foo=bar" -> {"foo", "bar", false}.
275*9356374aSAndroid Build Coastguard Worker //   "--foo"     -> {"foo", "", false}.
276*9356374aSAndroid Build Coastguard Worker //   "--foo="    -> {"foo", "", true}.
SplitNameAndValue(absl::string_view arg)277*9356374aSAndroid Build Coastguard Worker std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
278*9356374aSAndroid Build Coastguard Worker     absl::string_view arg) {
279*9356374aSAndroid Build Coastguard Worker   // Allow -foo and --foo
280*9356374aSAndroid Build Coastguard Worker   absl::ConsumePrefix(&arg, "-");
281*9356374aSAndroid Build Coastguard Worker 
282*9356374aSAndroid Build Coastguard Worker   if (arg.empty()) {
283*9356374aSAndroid Build Coastguard Worker     return std::make_tuple("", "", false);
284*9356374aSAndroid Build Coastguard Worker   }
285*9356374aSAndroid Build Coastguard Worker 
286*9356374aSAndroid Build Coastguard Worker   auto equal_sign_pos = arg.find('=');
287*9356374aSAndroid Build Coastguard Worker 
288*9356374aSAndroid Build Coastguard Worker   absl::string_view flag_name = arg.substr(0, equal_sign_pos);
289*9356374aSAndroid Build Coastguard Worker 
290*9356374aSAndroid Build Coastguard Worker   absl::string_view value;
291*9356374aSAndroid Build Coastguard Worker   bool is_empty_value = false;
292*9356374aSAndroid Build Coastguard Worker 
293*9356374aSAndroid Build Coastguard Worker   if (equal_sign_pos != absl::string_view::npos) {
294*9356374aSAndroid Build Coastguard Worker     value = arg.substr(equal_sign_pos + 1);
295*9356374aSAndroid Build Coastguard Worker     is_empty_value = value.empty();
296*9356374aSAndroid Build Coastguard Worker   }
297*9356374aSAndroid Build Coastguard Worker 
298*9356374aSAndroid Build Coastguard Worker   return std::make_tuple(flag_name, value, is_empty_value);
299*9356374aSAndroid Build Coastguard Worker }
300*9356374aSAndroid Build Coastguard Worker 
301*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
302*9356374aSAndroid Build Coastguard Worker 
303*9356374aSAndroid Build Coastguard Worker // Returns:
304*9356374aSAndroid Build Coastguard Worker //  found flag or nullptr
305*9356374aSAndroid Build Coastguard Worker //  is negative in case of --nofoo
LocateFlag(absl::string_view flag_name)306*9356374aSAndroid Build Coastguard Worker std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
307*9356374aSAndroid Build Coastguard Worker   CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
308*9356374aSAndroid Build Coastguard Worker   bool is_negative = false;
309*9356374aSAndroid Build Coastguard Worker 
310*9356374aSAndroid Build Coastguard Worker   if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
311*9356374aSAndroid Build Coastguard Worker     flag = absl::FindCommandLineFlag(flag_name);
312*9356374aSAndroid Build Coastguard Worker     is_negative = true;
313*9356374aSAndroid Build Coastguard Worker   }
314*9356374aSAndroid Build Coastguard Worker 
315*9356374aSAndroid Build Coastguard Worker   return std::make_tuple(flag, is_negative);
316*9356374aSAndroid Build Coastguard Worker }
317*9356374aSAndroid Build Coastguard Worker 
318*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
319*9356374aSAndroid Build Coastguard Worker 
320*9356374aSAndroid Build Coastguard Worker // Verify that default values of typed flags must be convertible to string and
321*9356374aSAndroid Build Coastguard Worker // back.
CheckDefaultValuesParsingRoundtrip()322*9356374aSAndroid Build Coastguard Worker void CheckDefaultValuesParsingRoundtrip() {
323*9356374aSAndroid Build Coastguard Worker #ifndef NDEBUG
324*9356374aSAndroid Build Coastguard Worker   flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
325*9356374aSAndroid Build Coastguard Worker     if (flag.IsRetired()) return;
326*9356374aSAndroid Build Coastguard Worker 
327*9356374aSAndroid Build Coastguard Worker #define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
328*9356374aSAndroid Build Coastguard Worker   if (flag.IsOfType<T>()) return;
329*9356374aSAndroid Build Coastguard Worker 
330*9356374aSAndroid Build Coastguard Worker     ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
331*9356374aSAndroid Build Coastguard Worker #undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE
332*9356374aSAndroid Build Coastguard Worker 
333*9356374aSAndroid Build Coastguard Worker     flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
334*9356374aSAndroid Build Coastguard Worker         flag);
335*9356374aSAndroid Build Coastguard Worker   });
336*9356374aSAndroid Build Coastguard Worker #endif
337*9356374aSAndroid Build Coastguard Worker }
338*9356374aSAndroid Build Coastguard Worker 
339*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
340*9356374aSAndroid Build Coastguard Worker 
341*9356374aSAndroid Build Coastguard Worker // Returns success status, which is true if we successfully read all flag files,
342*9356374aSAndroid Build Coastguard Worker // in which case new ArgLists are appended to the input_args in a reverse order
343*9356374aSAndroid Build Coastguard Worker // of file names in the input flagfiles list. This order ensures that flags from
344*9356374aSAndroid Build Coastguard Worker // the first flagfile in the input list are processed before the second flagfile
345*9356374aSAndroid Build Coastguard Worker // etc.
ReadFlagfiles(const std::vector<std::string> & flagfiles,std::vector<ArgsList> & input_args)346*9356374aSAndroid Build Coastguard Worker bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
347*9356374aSAndroid Build Coastguard Worker                    std::vector<ArgsList>& input_args) {
348*9356374aSAndroid Build Coastguard Worker   bool success = true;
349*9356374aSAndroid Build Coastguard Worker   for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
350*9356374aSAndroid Build Coastguard Worker     ArgsList al;
351*9356374aSAndroid Build Coastguard Worker 
352*9356374aSAndroid Build Coastguard Worker     if (al.ReadFromFlagfile(*it)) {
353*9356374aSAndroid Build Coastguard Worker       input_args.push_back(al);
354*9356374aSAndroid Build Coastguard Worker     } else {
355*9356374aSAndroid Build Coastguard Worker       success = false;
356*9356374aSAndroid Build Coastguard Worker     }
357*9356374aSAndroid Build Coastguard Worker   }
358*9356374aSAndroid Build Coastguard Worker 
359*9356374aSAndroid Build Coastguard Worker   return success;
360*9356374aSAndroid Build Coastguard Worker }
361*9356374aSAndroid Build Coastguard Worker 
362*9356374aSAndroid Build Coastguard Worker // Returns success status, which is true if were able to locate all environment
363*9356374aSAndroid Build Coastguard Worker // variables correctly or if fail_on_absent_in_env is false. The environment
364*9356374aSAndroid Build Coastguard Worker // variable names are expected to be of the form `FLAGS_<flag_name>`, where
365*9356374aSAndroid Build Coastguard Worker // `flag_name` is a string from the input flag_names list. If successful we
366*9356374aSAndroid Build Coastguard Worker // append a single ArgList at the end of the input_args.
ReadFlagsFromEnv(const std::vector<std::string> & flag_names,std::vector<ArgsList> & input_args,bool fail_on_absent_in_env)367*9356374aSAndroid Build Coastguard Worker bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
368*9356374aSAndroid Build Coastguard Worker                       std::vector<ArgsList>& input_args,
369*9356374aSAndroid Build Coastguard Worker                       bool fail_on_absent_in_env) {
370*9356374aSAndroid Build Coastguard Worker   bool success = true;
371*9356374aSAndroid Build Coastguard Worker   std::vector<std::string> args;
372*9356374aSAndroid Build Coastguard Worker 
373*9356374aSAndroid Build Coastguard Worker   // This argument represents fake argv[0], which should be present in all arg
374*9356374aSAndroid Build Coastguard Worker   // lists.
375*9356374aSAndroid Build Coastguard Worker   args.emplace_back("");
376*9356374aSAndroid Build Coastguard Worker 
377*9356374aSAndroid Build Coastguard Worker   for (const auto& flag_name : flag_names) {
378*9356374aSAndroid Build Coastguard Worker     // Avoid infinite recursion.
379*9356374aSAndroid Build Coastguard Worker     if (flag_name == "fromenv" || flag_name == "tryfromenv") {
380*9356374aSAndroid Build Coastguard Worker       flags_internal::ReportUsageError(
381*9356374aSAndroid Build Coastguard Worker           absl::StrCat("Infinite recursion on flag ", flag_name), true);
382*9356374aSAndroid Build Coastguard Worker 
383*9356374aSAndroid Build Coastguard Worker       success = false;
384*9356374aSAndroid Build Coastguard Worker       continue;
385*9356374aSAndroid Build Coastguard Worker     }
386*9356374aSAndroid Build Coastguard Worker 
387*9356374aSAndroid Build Coastguard Worker     const std::string envname = absl::StrCat("FLAGS_", flag_name);
388*9356374aSAndroid Build Coastguard Worker     std::string envval;
389*9356374aSAndroid Build Coastguard Worker     if (!GetEnvVar(envname.c_str(), envval)) {
390*9356374aSAndroid Build Coastguard Worker       if (fail_on_absent_in_env) {
391*9356374aSAndroid Build Coastguard Worker         flags_internal::ReportUsageError(
392*9356374aSAndroid Build Coastguard Worker             absl::StrCat(envname, " not found in environment"), true);
393*9356374aSAndroid Build Coastguard Worker 
394*9356374aSAndroid Build Coastguard Worker         success = false;
395*9356374aSAndroid Build Coastguard Worker       }
396*9356374aSAndroid Build Coastguard Worker 
397*9356374aSAndroid Build Coastguard Worker       continue;
398*9356374aSAndroid Build Coastguard Worker     }
399*9356374aSAndroid Build Coastguard Worker 
400*9356374aSAndroid Build Coastguard Worker     args.push_back(absl::StrCat("--", flag_name, "=", envval));
401*9356374aSAndroid Build Coastguard Worker   }
402*9356374aSAndroid Build Coastguard Worker 
403*9356374aSAndroid Build Coastguard Worker   if (success) {
404*9356374aSAndroid Build Coastguard Worker     input_args.emplace_back(args);
405*9356374aSAndroid Build Coastguard Worker   }
406*9356374aSAndroid Build Coastguard Worker 
407*9356374aSAndroid Build Coastguard Worker   return success;
408*9356374aSAndroid Build Coastguard Worker }
409*9356374aSAndroid Build Coastguard Worker 
410*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
411*9356374aSAndroid Build Coastguard Worker 
412*9356374aSAndroid Build Coastguard Worker // Returns success status, which is true if were able to handle all generator
413*9356374aSAndroid Build Coastguard Worker // flags (flagfile, fromenv, tryfromemv) successfully.
HandleGeneratorFlags(std::vector<ArgsList> & input_args,std::vector<std::string> & flagfile_value)414*9356374aSAndroid Build Coastguard Worker bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
415*9356374aSAndroid Build Coastguard Worker                           std::vector<std::string>& flagfile_value) {
416*9356374aSAndroid Build Coastguard Worker   bool success = true;
417*9356374aSAndroid Build Coastguard Worker 
418*9356374aSAndroid Build Coastguard Worker   absl::MutexLock l(&flags_internal::processing_checks_guard);
419*9356374aSAndroid Build Coastguard Worker 
420*9356374aSAndroid Build Coastguard Worker   // flagfile could have been set either on a command line or
421*9356374aSAndroid Build Coastguard Worker   // programmatically before invoking ParseCommandLine. Note that we do not
422*9356374aSAndroid Build Coastguard Worker   // actually process arguments specified in the flagfile, but instead
423*9356374aSAndroid Build Coastguard Worker   // create a secondary arguments list to be processed along with the rest
424*9356374aSAndroid Build Coastguard Worker   // of the command line arguments. Since we always the process most recently
425*9356374aSAndroid Build Coastguard Worker   // created list of arguments first, this will result in flagfile argument
426*9356374aSAndroid Build Coastguard Worker   // being processed before any other argument in the command line. If
427*9356374aSAndroid Build Coastguard Worker   // FLAGS_flagfile contains more than one file name we create multiple new
428*9356374aSAndroid Build Coastguard Worker   // levels of arguments in a reverse order of file names. Thus we always
429*9356374aSAndroid Build Coastguard Worker   // process arguments from first file before arguments containing in a
430*9356374aSAndroid Build Coastguard Worker   // second file, etc. If flagfile contains another
431*9356374aSAndroid Build Coastguard Worker   // --flagfile inside of it, it will produce new level of arguments and
432*9356374aSAndroid Build Coastguard Worker   // processed before the rest of the flagfile. We are also collecting all
433*9356374aSAndroid Build Coastguard Worker   // flagfiles set on original command line. Unlike the rest of the flags,
434*9356374aSAndroid Build Coastguard Worker   // this flag can be set multiple times and is expected to be handled
435*9356374aSAndroid Build Coastguard Worker   // multiple times. We are collecting them all into a single list and set
436*9356374aSAndroid Build Coastguard Worker   // the value of FLAGS_flagfile to that value at the end of the parsing.
437*9356374aSAndroid Build Coastguard Worker   if (flags_internal::flagfile_needs_processing) {
438*9356374aSAndroid Build Coastguard Worker     auto flagfiles = absl::GetFlag(FLAGS_flagfile);
439*9356374aSAndroid Build Coastguard Worker 
440*9356374aSAndroid Build Coastguard Worker     if (input_args.size() == 1) {
441*9356374aSAndroid Build Coastguard Worker       flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
442*9356374aSAndroid Build Coastguard Worker                             flagfiles.end());
443*9356374aSAndroid Build Coastguard Worker     }
444*9356374aSAndroid Build Coastguard Worker 
445*9356374aSAndroid Build Coastguard Worker     success &= ReadFlagfiles(flagfiles, input_args);
446*9356374aSAndroid Build Coastguard Worker 
447*9356374aSAndroid Build Coastguard Worker     flags_internal::flagfile_needs_processing = false;
448*9356374aSAndroid Build Coastguard Worker   }
449*9356374aSAndroid Build Coastguard Worker 
450*9356374aSAndroid Build Coastguard Worker   // Similar to flagfile fromenv/tryfromemv can be set both
451*9356374aSAndroid Build Coastguard Worker   // programmatically and at runtime on a command line. Unlike flagfile these
452*9356374aSAndroid Build Coastguard Worker   // can't be recursive.
453*9356374aSAndroid Build Coastguard Worker   if (flags_internal::fromenv_needs_processing) {
454*9356374aSAndroid Build Coastguard Worker     auto flags_list = absl::GetFlag(FLAGS_fromenv);
455*9356374aSAndroid Build Coastguard Worker 
456*9356374aSAndroid Build Coastguard Worker     success &= ReadFlagsFromEnv(flags_list, input_args, true);
457*9356374aSAndroid Build Coastguard Worker 
458*9356374aSAndroid Build Coastguard Worker     flags_internal::fromenv_needs_processing = false;
459*9356374aSAndroid Build Coastguard Worker   }
460*9356374aSAndroid Build Coastguard Worker 
461*9356374aSAndroid Build Coastguard Worker   if (flags_internal::tryfromenv_needs_processing) {
462*9356374aSAndroid Build Coastguard Worker     auto flags_list = absl::GetFlag(FLAGS_tryfromenv);
463*9356374aSAndroid Build Coastguard Worker 
464*9356374aSAndroid Build Coastguard Worker     success &= ReadFlagsFromEnv(flags_list, input_args, false);
465*9356374aSAndroid Build Coastguard Worker 
466*9356374aSAndroid Build Coastguard Worker     flags_internal::tryfromenv_needs_processing = false;
467*9356374aSAndroid Build Coastguard Worker   }
468*9356374aSAndroid Build Coastguard Worker 
469*9356374aSAndroid Build Coastguard Worker   return success;
470*9356374aSAndroid Build Coastguard Worker }
471*9356374aSAndroid Build Coastguard Worker 
472*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
473*9356374aSAndroid Build Coastguard Worker 
ResetGeneratorFlags(const std::vector<std::string> & flagfile_value)474*9356374aSAndroid Build Coastguard Worker void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) {
475*9356374aSAndroid Build Coastguard Worker   // Setting flagfile to the value which collates all the values set on a
476*9356374aSAndroid Build Coastguard Worker   // command line and programmatically. So if command line looked like
477*9356374aSAndroid Build Coastguard Worker   // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
478*9356374aSAndroid Build Coastguard Worker   // going to be {"f1", "f2"}
479*9356374aSAndroid Build Coastguard Worker   if (!flagfile_value.empty()) {
480*9356374aSAndroid Build Coastguard Worker     absl::SetFlag(&FLAGS_flagfile, flagfile_value);
481*9356374aSAndroid Build Coastguard Worker     absl::MutexLock l(&flags_internal::processing_checks_guard);
482*9356374aSAndroid Build Coastguard Worker     flags_internal::flagfile_needs_processing = false;
483*9356374aSAndroid Build Coastguard Worker   }
484*9356374aSAndroid Build Coastguard Worker 
485*9356374aSAndroid Build Coastguard Worker   // fromenv/tryfromenv are set to <undefined> value.
486*9356374aSAndroid Build Coastguard Worker   if (!absl::GetFlag(FLAGS_fromenv).empty()) {
487*9356374aSAndroid Build Coastguard Worker     absl::SetFlag(&FLAGS_fromenv, {});
488*9356374aSAndroid Build Coastguard Worker   }
489*9356374aSAndroid Build Coastguard Worker   if (!absl::GetFlag(FLAGS_tryfromenv).empty()) {
490*9356374aSAndroid Build Coastguard Worker     absl::SetFlag(&FLAGS_tryfromenv, {});
491*9356374aSAndroid Build Coastguard Worker   }
492*9356374aSAndroid Build Coastguard Worker 
493*9356374aSAndroid Build Coastguard Worker   absl::MutexLock l(&flags_internal::processing_checks_guard);
494*9356374aSAndroid Build Coastguard Worker   flags_internal::fromenv_needs_processing = false;
495*9356374aSAndroid Build Coastguard Worker   flags_internal::tryfromenv_needs_processing = false;
496*9356374aSAndroid Build Coastguard Worker }
497*9356374aSAndroid Build Coastguard Worker 
498*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
499*9356374aSAndroid Build Coastguard Worker 
500*9356374aSAndroid Build Coastguard Worker // Returns:
501*9356374aSAndroid Build Coastguard Worker //  success status
502*9356374aSAndroid Build Coastguard Worker //  deduced value
503*9356374aSAndroid Build Coastguard Worker // We are also mutating curr_list in case if we need to get a hold of next
504*9356374aSAndroid Build Coastguard Worker // argument in the input.
DeduceFlagValue(const CommandLineFlag & flag,absl::string_view value,bool is_negative,bool is_empty_value,ArgsList * curr_list)505*9356374aSAndroid Build Coastguard Worker std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
506*9356374aSAndroid Build Coastguard Worker                                                     absl::string_view value,
507*9356374aSAndroid Build Coastguard Worker                                                     bool is_negative,
508*9356374aSAndroid Build Coastguard Worker                                                     bool is_empty_value,
509*9356374aSAndroid Build Coastguard Worker                                                     ArgsList* curr_list) {
510*9356374aSAndroid Build Coastguard Worker   // Value is either an argument suffix after `=` in "--foo=<value>"
511*9356374aSAndroid Build Coastguard Worker   // or separate argument in case of "--foo" "<value>".
512*9356374aSAndroid Build Coastguard Worker 
513*9356374aSAndroid Build Coastguard Worker   // boolean flags have these forms:
514*9356374aSAndroid Build Coastguard Worker   //   --foo
515*9356374aSAndroid Build Coastguard Worker   //   --nofoo
516*9356374aSAndroid Build Coastguard Worker   //   --foo=true
517*9356374aSAndroid Build Coastguard Worker   //   --foo=false
518*9356374aSAndroid Build Coastguard Worker   //   --nofoo=<value> is not supported
519*9356374aSAndroid Build Coastguard Worker   //   --foo <value> is not supported
520*9356374aSAndroid Build Coastguard Worker 
521*9356374aSAndroid Build Coastguard Worker   // non boolean flags have these forms:
522*9356374aSAndroid Build Coastguard Worker   // --foo=<value>
523*9356374aSAndroid Build Coastguard Worker   // --foo <value>
524*9356374aSAndroid Build Coastguard Worker   // --nofoo is not supported
525*9356374aSAndroid Build Coastguard Worker 
526*9356374aSAndroid Build Coastguard Worker   if (flag.IsOfType<bool>()) {
527*9356374aSAndroid Build Coastguard Worker     if (value.empty()) {
528*9356374aSAndroid Build Coastguard Worker       if (is_empty_value) {
529*9356374aSAndroid Build Coastguard Worker         // "--bool_flag=" case
530*9356374aSAndroid Build Coastguard Worker         flags_internal::ReportUsageError(
531*9356374aSAndroid Build Coastguard Worker             absl::StrCat(
532*9356374aSAndroid Build Coastguard Worker                 "Missing the value after assignment for the boolean flag '",
533*9356374aSAndroid Build Coastguard Worker                 flag.Name(), "'"),
534*9356374aSAndroid Build Coastguard Worker             true);
535*9356374aSAndroid Build Coastguard Worker         return std::make_tuple(false, "");
536*9356374aSAndroid Build Coastguard Worker       }
537*9356374aSAndroid Build Coastguard Worker 
538*9356374aSAndroid Build Coastguard Worker       // "--bool_flag" case
539*9356374aSAndroid Build Coastguard Worker       value = is_negative ? "0" : "1";
540*9356374aSAndroid Build Coastguard Worker     } else if (is_negative) {
541*9356374aSAndroid Build Coastguard Worker       // "--nobool_flag=Y" case
542*9356374aSAndroid Build Coastguard Worker       flags_internal::ReportUsageError(
543*9356374aSAndroid Build Coastguard Worker           absl::StrCat("Negative form with assignment is not valid for the "
544*9356374aSAndroid Build Coastguard Worker                        "boolean flag '",
545*9356374aSAndroid Build Coastguard Worker                        flag.Name(), "'"),
546*9356374aSAndroid Build Coastguard Worker           true);
547*9356374aSAndroid Build Coastguard Worker       return std::make_tuple(false, "");
548*9356374aSAndroid Build Coastguard Worker     }
549*9356374aSAndroid Build Coastguard Worker   } else if (is_negative) {
550*9356374aSAndroid Build Coastguard Worker     // "--noint_flag=1" case
551*9356374aSAndroid Build Coastguard Worker     flags_internal::ReportUsageError(
552*9356374aSAndroid Build Coastguard Worker         absl::StrCat("Negative form is not valid for the flag '", flag.Name(),
553*9356374aSAndroid Build Coastguard Worker                      "'"),
554*9356374aSAndroid Build Coastguard Worker         true);
555*9356374aSAndroid Build Coastguard Worker     return std::make_tuple(false, "");
556*9356374aSAndroid Build Coastguard Worker   } else if (value.empty() && (!is_empty_value)) {
557*9356374aSAndroid Build Coastguard Worker     if (curr_list->Size() == 1) {
558*9356374aSAndroid Build Coastguard Worker       // "--int_flag" case
559*9356374aSAndroid Build Coastguard Worker       flags_internal::ReportUsageError(
560*9356374aSAndroid Build Coastguard Worker           absl::StrCat("Missing the value for the flag '", flag.Name(), "'"),
561*9356374aSAndroid Build Coastguard Worker           true);
562*9356374aSAndroid Build Coastguard Worker       return std::make_tuple(false, "");
563*9356374aSAndroid Build Coastguard Worker     }
564*9356374aSAndroid Build Coastguard Worker 
565*9356374aSAndroid Build Coastguard Worker     // "--int_flag" "10" case
566*9356374aSAndroid Build Coastguard Worker     curr_list->PopFront();
567*9356374aSAndroid Build Coastguard Worker     value = curr_list->Front();
568*9356374aSAndroid Build Coastguard Worker 
569*9356374aSAndroid Build Coastguard Worker     // Heuristic to detect the case where someone treats a string arg
570*9356374aSAndroid Build Coastguard Worker     // like a bool or just forgets to pass a value:
571*9356374aSAndroid Build Coastguard Worker     // --my_string_var --foo=bar
572*9356374aSAndroid Build Coastguard Worker     // We look for a flag of string type, whose value begins with a
573*9356374aSAndroid Build Coastguard Worker     // dash and corresponds to known flag or standalone --.
574*9356374aSAndroid Build Coastguard Worker     if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) {
575*9356374aSAndroid Build Coastguard Worker       auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
576*9356374aSAndroid Build Coastguard Worker 
577*9356374aSAndroid Build Coastguard Worker       if (maybe_flag_name.empty() ||
578*9356374aSAndroid Build Coastguard Worker           std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {
579*9356374aSAndroid Build Coastguard Worker         // "--string_flag" "--known_flag" case
580*9356374aSAndroid Build Coastguard Worker         ABSL_INTERNAL_LOG(
581*9356374aSAndroid Build Coastguard Worker             WARNING,
582*9356374aSAndroid Build Coastguard Worker             absl::StrCat("Did you really mean to set flag '", flag.Name(),
583*9356374aSAndroid Build Coastguard Worker                          "' to the value '", value, "'?"));
584*9356374aSAndroid Build Coastguard Worker       }
585*9356374aSAndroid Build Coastguard Worker     }
586*9356374aSAndroid Build Coastguard Worker   }
587*9356374aSAndroid Build Coastguard Worker 
588*9356374aSAndroid Build Coastguard Worker   return std::make_tuple(true, value);
589*9356374aSAndroid Build Coastguard Worker }
590*9356374aSAndroid Build Coastguard Worker 
591*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
592*9356374aSAndroid Build Coastguard Worker 
CanIgnoreUndefinedFlag(absl::string_view flag_name)593*9356374aSAndroid Build Coastguard Worker bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
594*9356374aSAndroid Build Coastguard Worker   auto undefok = absl::GetFlag(FLAGS_undefok);
595*9356374aSAndroid Build Coastguard Worker   if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
596*9356374aSAndroid Build Coastguard Worker     return true;
597*9356374aSAndroid Build Coastguard Worker   }
598*9356374aSAndroid Build Coastguard Worker 
599*9356374aSAndroid Build Coastguard Worker   if (absl::ConsumePrefix(&flag_name, "no") &&
600*9356374aSAndroid Build Coastguard Worker       std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
601*9356374aSAndroid Build Coastguard Worker     return true;
602*9356374aSAndroid Build Coastguard Worker   }
603*9356374aSAndroid Build Coastguard Worker 
604*9356374aSAndroid Build Coastguard Worker   return false;
605*9356374aSAndroid Build Coastguard Worker }
606*9356374aSAndroid Build Coastguard Worker 
607*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
608*9356374aSAndroid Build Coastguard Worker 
ReportUnrecognizedFlags(const std::vector<UnrecognizedFlag> & unrecognized_flags,bool report_as_fatal_error)609*9356374aSAndroid Build Coastguard Worker void ReportUnrecognizedFlags(
610*9356374aSAndroid Build Coastguard Worker     const std::vector<UnrecognizedFlag>& unrecognized_flags,
611*9356374aSAndroid Build Coastguard Worker     bool report_as_fatal_error) {
612*9356374aSAndroid Build Coastguard Worker   for (const auto& unrecognized : unrecognized_flags) {
613*9356374aSAndroid Build Coastguard Worker     // Verify if flag_name has the "no" already removed
614*9356374aSAndroid Build Coastguard Worker     std::vector<std::string> misspelling_hints;
615*9356374aSAndroid Build Coastguard Worker     if (unrecognized.source == UnrecognizedFlag::kFromArgv) {
616*9356374aSAndroid Build Coastguard Worker       misspelling_hints =
617*9356374aSAndroid Build Coastguard Worker           flags_internal::GetMisspellingHints(unrecognized.flag_name);
618*9356374aSAndroid Build Coastguard Worker     }
619*9356374aSAndroid Build Coastguard Worker 
620*9356374aSAndroid Build Coastguard Worker     if (misspelling_hints.empty()) {
621*9356374aSAndroid Build Coastguard Worker       flags_internal::ReportUsageError(
622*9356374aSAndroid Build Coastguard Worker           absl::StrCat("Unknown command line flag '", unrecognized.flag_name,
623*9356374aSAndroid Build Coastguard Worker                        "'"),
624*9356374aSAndroid Build Coastguard Worker           report_as_fatal_error);
625*9356374aSAndroid Build Coastguard Worker     } else {
626*9356374aSAndroid Build Coastguard Worker       flags_internal::ReportUsageError(
627*9356374aSAndroid Build Coastguard Worker           absl::StrCat("Unknown command line flag '", unrecognized.flag_name,
628*9356374aSAndroid Build Coastguard Worker                        "'. Did you mean: ",
629*9356374aSAndroid Build Coastguard Worker                        absl::StrJoin(misspelling_hints, ", "), " ?"),
630*9356374aSAndroid Build Coastguard Worker           report_as_fatal_error);
631*9356374aSAndroid Build Coastguard Worker     }
632*9356374aSAndroid Build Coastguard Worker   }
633*9356374aSAndroid Build Coastguard Worker }
634*9356374aSAndroid Build Coastguard Worker 
635*9356374aSAndroid Build Coastguard Worker }  // namespace
636*9356374aSAndroid Build Coastguard Worker 
637*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
638*9356374aSAndroid Build Coastguard Worker 
WasPresentOnCommandLine(absl::string_view flag_name)639*9356374aSAndroid Build Coastguard Worker bool WasPresentOnCommandLine(absl::string_view flag_name) {
640*9356374aSAndroid Build Coastguard Worker   absl::ReaderMutexLock l(&specified_flags_guard);
641*9356374aSAndroid Build Coastguard Worker   ABSL_INTERNAL_CHECK(specified_flags != nullptr,
642*9356374aSAndroid Build Coastguard Worker                       "ParseCommandLine is not invoked yet");
643*9356374aSAndroid Build Coastguard Worker 
644*9356374aSAndroid Build Coastguard Worker   return std::binary_search(specified_flags->begin(), specified_flags->end(),
645*9356374aSAndroid Build Coastguard Worker                             flag_name, SpecifiedFlagsCompare{});
646*9356374aSAndroid Build Coastguard Worker }
647*9356374aSAndroid Build Coastguard Worker 
648*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
649*9356374aSAndroid Build Coastguard Worker 
650*9356374aSAndroid Build Coastguard Worker struct BestHints {
BestHintsabsl::flags_internal::BestHints651*9356374aSAndroid Build Coastguard Worker   explicit BestHints(uint8_t _max) : best_distance(_max + 1) {}
AddHintabsl::flags_internal::BestHints652*9356374aSAndroid Build Coastguard Worker   bool AddHint(absl::string_view hint, uint8_t distance) {
653*9356374aSAndroid Build Coastguard Worker     if (hints.size() >= kMaxHints) return false;
654*9356374aSAndroid Build Coastguard Worker     if (distance == best_distance) {
655*9356374aSAndroid Build Coastguard Worker       hints.emplace_back(hint);
656*9356374aSAndroid Build Coastguard Worker     }
657*9356374aSAndroid Build Coastguard Worker     if (distance < best_distance) {
658*9356374aSAndroid Build Coastguard Worker       best_distance = distance;
659*9356374aSAndroid Build Coastguard Worker       hints = std::vector<std::string>{std::string(hint)};
660*9356374aSAndroid Build Coastguard Worker     }
661*9356374aSAndroid Build Coastguard Worker     return true;
662*9356374aSAndroid Build Coastguard Worker   }
663*9356374aSAndroid Build Coastguard Worker 
664*9356374aSAndroid Build Coastguard Worker   uint8_t best_distance;
665*9356374aSAndroid Build Coastguard Worker   std::vector<std::string> hints;
666*9356374aSAndroid Build Coastguard Worker };
667*9356374aSAndroid Build Coastguard Worker 
668*9356374aSAndroid Build Coastguard Worker // Return the list of flags with the smallest Damerau-Levenshtein distance to
669*9356374aSAndroid Build Coastguard Worker // the given flag.
GetMisspellingHints(const absl::string_view flag)670*9356374aSAndroid Build Coastguard Worker std::vector<std::string> GetMisspellingHints(const absl::string_view flag) {
671*9356374aSAndroid Build Coastguard Worker   const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance);
672*9356374aSAndroid Build Coastguard Worker   auto undefok = absl::GetFlag(FLAGS_undefok);
673*9356374aSAndroid Build Coastguard Worker   BestHints best_hints(static_cast<uint8_t>(maxCutoff));
674*9356374aSAndroid Build Coastguard Worker   flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
675*9356374aSAndroid Build Coastguard Worker     if (best_hints.hints.size() >= kMaxHints) return;
676*9356374aSAndroid Build Coastguard Worker     uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
677*9356374aSAndroid Build Coastguard Worker         flag, f.Name(), best_hints.best_distance);
678*9356374aSAndroid Build Coastguard Worker     best_hints.AddHint(f.Name(), distance);
679*9356374aSAndroid Build Coastguard Worker     // For boolean flags, also calculate distance to the negated form.
680*9356374aSAndroid Build Coastguard Worker     if (f.IsOfType<bool>()) {
681*9356374aSAndroid Build Coastguard Worker       const std::string negated_flag = absl::StrCat("no", f.Name());
682*9356374aSAndroid Build Coastguard Worker       distance = strings_internal::CappedDamerauLevenshteinDistance(
683*9356374aSAndroid Build Coastguard Worker           flag, negated_flag, best_hints.best_distance);
684*9356374aSAndroid Build Coastguard Worker       best_hints.AddHint(negated_flag, distance);
685*9356374aSAndroid Build Coastguard Worker     }
686*9356374aSAndroid Build Coastguard Worker   });
687*9356374aSAndroid Build Coastguard Worker   // Finally calculate distance to flags in "undefok".
688*9356374aSAndroid Build Coastguard Worker   absl::c_for_each(undefok, [&](const absl::string_view f) {
689*9356374aSAndroid Build Coastguard Worker     if (best_hints.hints.size() >= kMaxHints) return;
690*9356374aSAndroid Build Coastguard Worker     uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
691*9356374aSAndroid Build Coastguard Worker         flag, f, best_hints.best_distance);
692*9356374aSAndroid Build Coastguard Worker     best_hints.AddHint(absl::StrCat(f, " (undefok)"), distance);
693*9356374aSAndroid Build Coastguard Worker   });
694*9356374aSAndroid Build Coastguard Worker   return best_hints.hints;
695*9356374aSAndroid Build Coastguard Worker }
696*9356374aSAndroid Build Coastguard Worker 
697*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
698*9356374aSAndroid Build Coastguard Worker 
ParseCommandLineImpl(int argc,char * argv[],UsageFlagsAction usage_flag_action,OnUndefinedFlag undef_flag_action,std::ostream & error_help_output)699*9356374aSAndroid Build Coastguard Worker std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
700*9356374aSAndroid Build Coastguard Worker                                         UsageFlagsAction usage_flag_action,
701*9356374aSAndroid Build Coastguard Worker                                         OnUndefinedFlag undef_flag_action,
702*9356374aSAndroid Build Coastguard Worker                                         std::ostream& error_help_output) {
703*9356374aSAndroid Build Coastguard Worker   std::vector<char*> positional_args;
704*9356374aSAndroid Build Coastguard Worker   std::vector<UnrecognizedFlag> unrecognized_flags;
705*9356374aSAndroid Build Coastguard Worker 
706*9356374aSAndroid Build Coastguard Worker   auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
707*9356374aSAndroid Build Coastguard Worker       argc, argv, positional_args, unrecognized_flags, usage_flag_action);
708*9356374aSAndroid Build Coastguard Worker 
709*9356374aSAndroid Build Coastguard Worker   if (undef_flag_action != OnUndefinedFlag::kIgnoreUndefined) {
710*9356374aSAndroid Build Coastguard Worker     flags_internal::ReportUnrecognizedFlags(
711*9356374aSAndroid Build Coastguard Worker         unrecognized_flags,
712*9356374aSAndroid Build Coastguard Worker         (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined));
713*9356374aSAndroid Build Coastguard Worker 
714*9356374aSAndroid Build Coastguard Worker     if (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) {
715*9356374aSAndroid Build Coastguard Worker       if (!unrecognized_flags.empty()) {
716*9356374aSAndroid Build Coastguard Worker         flags_internal::HandleUsageFlags(error_help_output,
717*9356374aSAndroid Build Coastguard Worker         ProgramUsageMessage()); std::exit(1);
718*9356374aSAndroid Build Coastguard Worker       }
719*9356374aSAndroid Build Coastguard Worker     }
720*9356374aSAndroid Build Coastguard Worker   }
721*9356374aSAndroid Build Coastguard Worker 
722*9356374aSAndroid Build Coastguard Worker   flags_internal::MaybeExit(help_mode);
723*9356374aSAndroid Build Coastguard Worker 
724*9356374aSAndroid Build Coastguard Worker   return positional_args;
725*9356374aSAndroid Build Coastguard Worker }
726*9356374aSAndroid Build Coastguard Worker 
727*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
728*9356374aSAndroid Build Coastguard Worker 
729*9356374aSAndroid Build Coastguard Worker // This function handles all Abseil Flags and built-in usage flags and, if any
730*9356374aSAndroid Build Coastguard Worker // help mode was handled, it returns that help mode. The caller of this function
731*9356374aSAndroid Build Coastguard Worker // can decide to exit based on the returned help mode.
732*9356374aSAndroid Build Coastguard Worker // The caller may decide to handle unrecognized positional arguments and
733*9356374aSAndroid Build Coastguard Worker // unrecognized flags first before exiting.
734*9356374aSAndroid Build Coastguard Worker //
735*9356374aSAndroid Build Coastguard Worker // Returns:
736*9356374aSAndroid Build Coastguard Worker // * HelpMode::kFull if parsing errors were detected in recognized arguments
737*9356374aSAndroid Build Coastguard Worker // * The HelpMode that was handled in case when `usage_flag_action` is
738*9356374aSAndroid Build Coastguard Worker //   UsageFlagsAction::kHandleUsage and a usage flag was specified on the
739*9356374aSAndroid Build Coastguard Worker //   commandline
740*9356374aSAndroid Build Coastguard Worker // * Otherwise it returns HelpMode::kNone
ParseAbseilFlagsOnlyImpl(int argc,char * argv[],std::vector<char * > & positional_args,std::vector<UnrecognizedFlag> & unrecognized_flags,UsageFlagsAction usage_flag_action)741*9356374aSAndroid Build Coastguard Worker HelpMode ParseAbseilFlagsOnlyImpl(
742*9356374aSAndroid Build Coastguard Worker     int argc, char* argv[], std::vector<char*>& positional_args,
743*9356374aSAndroid Build Coastguard Worker     std::vector<UnrecognizedFlag>& unrecognized_flags,
744*9356374aSAndroid Build Coastguard Worker     UsageFlagsAction usage_flag_action) {
745*9356374aSAndroid Build Coastguard Worker   ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
746*9356374aSAndroid Build Coastguard Worker 
747*9356374aSAndroid Build Coastguard Worker   using flags_internal::ArgsList;
748*9356374aSAndroid Build Coastguard Worker   using flags_internal::specified_flags;
749*9356374aSAndroid Build Coastguard Worker 
750*9356374aSAndroid Build Coastguard Worker   std::vector<std::string> flagfile_value;
751*9356374aSAndroid Build Coastguard Worker   std::vector<ArgsList> input_args;
752*9356374aSAndroid Build Coastguard Worker 
753*9356374aSAndroid Build Coastguard Worker   // Once parsing has started we will not allow more flag registrations.
754*9356374aSAndroid Build Coastguard Worker   flags_internal::FinalizeRegistry();
755*9356374aSAndroid Build Coastguard Worker 
756*9356374aSAndroid Build Coastguard Worker   // This routine does not return anything since we abort on failure.
757*9356374aSAndroid Build Coastguard Worker   flags_internal::CheckDefaultValuesParsingRoundtrip();
758*9356374aSAndroid Build Coastguard Worker 
759*9356374aSAndroid Build Coastguard Worker   input_args.push_back(ArgsList(argc, argv));
760*9356374aSAndroid Build Coastguard Worker 
761*9356374aSAndroid Build Coastguard Worker   // Set program invocation name if it is not set before.
762*9356374aSAndroid Build Coastguard Worker   if (flags_internal::ProgramInvocationName() == "UNKNOWN") {
763*9356374aSAndroid Build Coastguard Worker     flags_internal::SetProgramInvocationName(argv[0]);
764*9356374aSAndroid Build Coastguard Worker   }
765*9356374aSAndroid Build Coastguard Worker   positional_args.push_back(argv[0]);
766*9356374aSAndroid Build Coastguard Worker 
767*9356374aSAndroid Build Coastguard Worker   absl::MutexLock l(&flags_internal::specified_flags_guard);
768*9356374aSAndroid Build Coastguard Worker   if (specified_flags == nullptr) {
769*9356374aSAndroid Build Coastguard Worker     specified_flags = new std::vector<const CommandLineFlag*>;
770*9356374aSAndroid Build Coastguard Worker   } else {
771*9356374aSAndroid Build Coastguard Worker     specified_flags->clear();
772*9356374aSAndroid Build Coastguard Worker   }
773*9356374aSAndroid Build Coastguard Worker 
774*9356374aSAndroid Build Coastguard Worker   // Iterate through the list of the input arguments. First level are
775*9356374aSAndroid Build Coastguard Worker   // arguments originated from argc/argv. Following levels are arguments
776*9356374aSAndroid Build Coastguard Worker   // originated from recursive parsing of flagfile(s).
777*9356374aSAndroid Build Coastguard Worker   bool success = true;
778*9356374aSAndroid Build Coastguard Worker   while (!input_args.empty()) {
779*9356374aSAndroid Build Coastguard Worker     // First we process the built-in generator flags.
780*9356374aSAndroid Build Coastguard Worker     success &= flags_internal::HandleGeneratorFlags(input_args, flagfile_value);
781*9356374aSAndroid Build Coastguard Worker 
782*9356374aSAndroid Build Coastguard Worker     // Select top-most (most recent) arguments list. If it is empty drop it
783*9356374aSAndroid Build Coastguard Worker     // and re-try.
784*9356374aSAndroid Build Coastguard Worker     ArgsList& curr_list = input_args.back();
785*9356374aSAndroid Build Coastguard Worker 
786*9356374aSAndroid Build Coastguard Worker     // Every ArgsList starts with real or fake program name, so we can always
787*9356374aSAndroid Build Coastguard Worker     // start by skipping it.
788*9356374aSAndroid Build Coastguard Worker     curr_list.PopFront();
789*9356374aSAndroid Build Coastguard Worker 
790*9356374aSAndroid Build Coastguard Worker     if (curr_list.Size() == 0) {
791*9356374aSAndroid Build Coastguard Worker       input_args.pop_back();
792*9356374aSAndroid Build Coastguard Worker       continue;
793*9356374aSAndroid Build Coastguard Worker     }
794*9356374aSAndroid Build Coastguard Worker 
795*9356374aSAndroid Build Coastguard Worker     // Handle the next argument in the current list. If the stack of argument
796*9356374aSAndroid Build Coastguard Worker     // lists contains only one element - we are processing an argument from
797*9356374aSAndroid Build Coastguard Worker     // the original argv.
798*9356374aSAndroid Build Coastguard Worker     absl::string_view arg(curr_list.Front());
799*9356374aSAndroid Build Coastguard Worker     bool arg_from_argv = input_args.size() == 1;
800*9356374aSAndroid Build Coastguard Worker 
801*9356374aSAndroid Build Coastguard Worker     // If argument does not start with '-' or is just "-" - this is
802*9356374aSAndroid Build Coastguard Worker     // positional argument.
803*9356374aSAndroid Build Coastguard Worker     if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) {
804*9356374aSAndroid Build Coastguard Worker       ABSL_INTERNAL_CHECK(arg_from_argv,
805*9356374aSAndroid Build Coastguard Worker                           "Flagfile cannot contain positional argument");
806*9356374aSAndroid Build Coastguard Worker 
807*9356374aSAndroid Build Coastguard Worker       positional_args.push_back(argv[curr_list.FrontIndex()]);
808*9356374aSAndroid Build Coastguard Worker       continue;
809*9356374aSAndroid Build Coastguard Worker     }
810*9356374aSAndroid Build Coastguard Worker 
811*9356374aSAndroid Build Coastguard Worker     // Split the current argument on '=' to deduce the argument flag name and
812*9356374aSAndroid Build Coastguard Worker     // value. If flag name is empty it means we've got an "--" argument. Value
813*9356374aSAndroid Build Coastguard Worker     // can be empty either if there were no '=' in argument string at all or
814*9356374aSAndroid Build Coastguard Worker     // an argument looked like "--foo=". In a latter case is_empty_value is
815*9356374aSAndroid Build Coastguard Worker     // true.
816*9356374aSAndroid Build Coastguard Worker     absl::string_view flag_name;
817*9356374aSAndroid Build Coastguard Worker     absl::string_view value;
818*9356374aSAndroid Build Coastguard Worker     bool is_empty_value = false;
819*9356374aSAndroid Build Coastguard Worker 
820*9356374aSAndroid Build Coastguard Worker     std::tie(flag_name, value, is_empty_value) =
821*9356374aSAndroid Build Coastguard Worker         flags_internal::SplitNameAndValue(arg);
822*9356374aSAndroid Build Coastguard Worker 
823*9356374aSAndroid Build Coastguard Worker     // Standalone "--" argument indicates that the rest of the arguments are
824*9356374aSAndroid Build Coastguard Worker     // positional. We do not support positional arguments in flagfiles.
825*9356374aSAndroid Build Coastguard Worker     if (flag_name.empty()) {
826*9356374aSAndroid Build Coastguard Worker       ABSL_INTERNAL_CHECK(arg_from_argv,
827*9356374aSAndroid Build Coastguard Worker                           "Flagfile cannot contain positional argument");
828*9356374aSAndroid Build Coastguard Worker 
829*9356374aSAndroid Build Coastguard Worker       curr_list.PopFront();
830*9356374aSAndroid Build Coastguard Worker       break;
831*9356374aSAndroid Build Coastguard Worker     }
832*9356374aSAndroid Build Coastguard Worker 
833*9356374aSAndroid Build Coastguard Worker     // Locate the flag based on flag name. Handle both --foo and --nofoo.
834*9356374aSAndroid Build Coastguard Worker     CommandLineFlag* flag = nullptr;
835*9356374aSAndroid Build Coastguard Worker     bool is_negative = false;
836*9356374aSAndroid Build Coastguard Worker     std::tie(flag, is_negative) = flags_internal::LocateFlag(flag_name);
837*9356374aSAndroid Build Coastguard Worker 
838*9356374aSAndroid Build Coastguard Worker     if (flag == nullptr) {
839*9356374aSAndroid Build Coastguard Worker       // Usage flags are not modeled as Abseil flags. Locate them separately.
840*9356374aSAndroid Build Coastguard Worker       if (flags_internal::DeduceUsageFlags(flag_name, value)) {
841*9356374aSAndroid Build Coastguard Worker         continue;
842*9356374aSAndroid Build Coastguard Worker       }
843*9356374aSAndroid Build Coastguard Worker       unrecognized_flags.emplace_back(arg_from_argv
844*9356374aSAndroid Build Coastguard Worker                                           ? UnrecognizedFlag::kFromArgv
845*9356374aSAndroid Build Coastguard Worker                                           : UnrecognizedFlag::kFromFlagfile,
846*9356374aSAndroid Build Coastguard Worker                                       flag_name);
847*9356374aSAndroid Build Coastguard Worker       continue;
848*9356374aSAndroid Build Coastguard Worker     }
849*9356374aSAndroid Build Coastguard Worker 
850*9356374aSAndroid Build Coastguard Worker     // Deduce flag's value (from this or next argument).
851*9356374aSAndroid Build Coastguard Worker     bool value_success = true;
852*9356374aSAndroid Build Coastguard Worker     std::tie(value_success, value) = flags_internal::DeduceFlagValue(
853*9356374aSAndroid Build Coastguard Worker         *flag, value, is_negative, is_empty_value, &curr_list);
854*9356374aSAndroid Build Coastguard Worker     success &= value_success;
855*9356374aSAndroid Build Coastguard Worker 
856*9356374aSAndroid Build Coastguard Worker     // Set the located flag to a new value, unless it is retired. Setting
857*9356374aSAndroid Build Coastguard Worker     // retired flag fails, but we ignoring it here while also reporting access
858*9356374aSAndroid Build Coastguard Worker     // to retired flag.
859*9356374aSAndroid Build Coastguard Worker     std::string error;
860*9356374aSAndroid Build Coastguard Worker     if (!flags_internal::PrivateHandleAccessor::ParseFrom(
861*9356374aSAndroid Build Coastguard Worker             *flag, value, flags_internal::SET_FLAGS_VALUE,
862*9356374aSAndroid Build Coastguard Worker             flags_internal::kCommandLine, error)) {
863*9356374aSAndroid Build Coastguard Worker       if (flag->IsRetired()) continue;
864*9356374aSAndroid Build Coastguard Worker 
865*9356374aSAndroid Build Coastguard Worker       flags_internal::ReportUsageError(error, true);
866*9356374aSAndroid Build Coastguard Worker       success = false;
867*9356374aSAndroid Build Coastguard Worker     } else {
868*9356374aSAndroid Build Coastguard Worker       specified_flags->push_back(flag);
869*9356374aSAndroid Build Coastguard Worker     }
870*9356374aSAndroid Build Coastguard Worker   }
871*9356374aSAndroid Build Coastguard Worker 
872*9356374aSAndroid Build Coastguard Worker   flags_internal::ResetGeneratorFlags(flagfile_value);
873*9356374aSAndroid Build Coastguard Worker 
874*9356374aSAndroid Build Coastguard Worker   // All the remaining arguments are positional.
875*9356374aSAndroid Build Coastguard Worker   if (!input_args.empty()) {
876*9356374aSAndroid Build Coastguard Worker     for (size_t arg_index = input_args.back().FrontIndex();
877*9356374aSAndroid Build Coastguard Worker          arg_index < static_cast<size_t>(argc); ++arg_index) {
878*9356374aSAndroid Build Coastguard Worker       positional_args.push_back(argv[arg_index]);
879*9356374aSAndroid Build Coastguard Worker     }
880*9356374aSAndroid Build Coastguard Worker   }
881*9356374aSAndroid Build Coastguard Worker 
882*9356374aSAndroid Build Coastguard Worker   // Trim and sort the vector.
883*9356374aSAndroid Build Coastguard Worker   specified_flags->shrink_to_fit();
884*9356374aSAndroid Build Coastguard Worker   std::sort(specified_flags->begin(), specified_flags->end(),
885*9356374aSAndroid Build Coastguard Worker             flags_internal::SpecifiedFlagsCompare{});
886*9356374aSAndroid Build Coastguard Worker 
887*9356374aSAndroid Build Coastguard Worker   // Filter out unrecognized flags, which are ok to ignore.
888*9356374aSAndroid Build Coastguard Worker   std::vector<UnrecognizedFlag> filtered;
889*9356374aSAndroid Build Coastguard Worker   filtered.reserve(unrecognized_flags.size());
890*9356374aSAndroid Build Coastguard Worker   for (const auto& unrecognized : unrecognized_flags) {
891*9356374aSAndroid Build Coastguard Worker     if (flags_internal::CanIgnoreUndefinedFlag(unrecognized.flag_name))
892*9356374aSAndroid Build Coastguard Worker       continue;
893*9356374aSAndroid Build Coastguard Worker     filtered.push_back(unrecognized);
894*9356374aSAndroid Build Coastguard Worker   }
895*9356374aSAndroid Build Coastguard Worker 
896*9356374aSAndroid Build Coastguard Worker   std::swap(unrecognized_flags, filtered);
897*9356374aSAndroid Build Coastguard Worker 
898*9356374aSAndroid Build Coastguard Worker   if (!success) {
899*9356374aSAndroid Build Coastguard Worker #if ABSL_FLAGS_STRIP_NAMES
900*9356374aSAndroid Build Coastguard Worker     flags_internal::ReportUsageError(
901*9356374aSAndroid Build Coastguard Worker         "NOTE: command line flags are disabled in this build", true);
902*9356374aSAndroid Build Coastguard Worker #else
903*9356374aSAndroid Build Coastguard Worker     flags_internal::HandleUsageFlags(std::cerr, ProgramUsageMessage());
904*9356374aSAndroid Build Coastguard Worker #endif
905*9356374aSAndroid Build Coastguard Worker     return HelpMode::kFull;  // We just need to make sure the exit with
906*9356374aSAndroid Build Coastguard Worker                              // code 1.
907*9356374aSAndroid Build Coastguard Worker   }
908*9356374aSAndroid Build Coastguard Worker 
909*9356374aSAndroid Build Coastguard Worker   return usage_flag_action == UsageFlagsAction::kHandleUsage
910*9356374aSAndroid Build Coastguard Worker              ? flags_internal::HandleUsageFlags(std::cout,
911*9356374aSAndroid Build Coastguard Worker                                                 ProgramUsageMessage())
912*9356374aSAndroid Build Coastguard Worker              : HelpMode::kNone;
913*9356374aSAndroid Build Coastguard Worker }
914*9356374aSAndroid Build Coastguard Worker 
915*9356374aSAndroid Build Coastguard Worker }  // namespace flags_internal
916*9356374aSAndroid Build Coastguard Worker 
ParseAbseilFlagsOnly(int argc,char * argv[],std::vector<char * > & positional_args,std::vector<UnrecognizedFlag> & unrecognized_flags)917*9356374aSAndroid Build Coastguard Worker void ParseAbseilFlagsOnly(int argc, char* argv[],
918*9356374aSAndroid Build Coastguard Worker                           std::vector<char*>& positional_args,
919*9356374aSAndroid Build Coastguard Worker                           std::vector<UnrecognizedFlag>& unrecognized_flags) {
920*9356374aSAndroid Build Coastguard Worker   auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
921*9356374aSAndroid Build Coastguard Worker       argc, argv, positional_args, unrecognized_flags,
922*9356374aSAndroid Build Coastguard Worker       flags_internal::UsageFlagsAction::kHandleUsage);
923*9356374aSAndroid Build Coastguard Worker 
924*9356374aSAndroid Build Coastguard Worker   flags_internal::MaybeExit(help_mode);
925*9356374aSAndroid Build Coastguard Worker }
926*9356374aSAndroid Build Coastguard Worker 
927*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
928*9356374aSAndroid Build Coastguard Worker 
ReportUnrecognizedFlags(const std::vector<UnrecognizedFlag> & unrecognized_flags)929*9356374aSAndroid Build Coastguard Worker void ReportUnrecognizedFlags(
930*9356374aSAndroid Build Coastguard Worker     const std::vector<UnrecognizedFlag>& unrecognized_flags) {
931*9356374aSAndroid Build Coastguard Worker   flags_internal::ReportUnrecognizedFlags(unrecognized_flags, true);
932*9356374aSAndroid Build Coastguard Worker }
933*9356374aSAndroid Build Coastguard Worker 
934*9356374aSAndroid Build Coastguard Worker // --------------------------------------------------------------------
935*9356374aSAndroid Build Coastguard Worker 
ParseCommandLine(int argc,char * argv[])936*9356374aSAndroid Build Coastguard Worker std::vector<char*> ParseCommandLine(int argc, char* argv[]) {
937*9356374aSAndroid Build Coastguard Worker   return flags_internal::ParseCommandLineImpl(
938*9356374aSAndroid Build Coastguard Worker       argc, argv, flags_internal::UsageFlagsAction::kHandleUsage,
939*9356374aSAndroid Build Coastguard Worker       flags_internal::OnUndefinedFlag::kAbortIfUndefined);
940*9356374aSAndroid Build Coastguard Worker }
941*9356374aSAndroid Build Coastguard Worker 
942*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
943*9356374aSAndroid Build Coastguard Worker }  // namespace absl
944