root/trunk/whisperlib/common/base/third-party/gflags.cc

Revision 7, 57.3 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2006, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // ---
31 // Author: Ray Sidney
32 // Revamped and reorganized by Craig Silverstein
33 //
34 // This file contains the implementation of all our command line flags
35 // stuff.
36
37 #include <stdio.h>     // for snprintf
38 #include <ctype.h>
39 #include <errno.h>
40 #include <string.h>
41 #include <assert.h>
42 #include <pthread.h>
43 #include <fnmatch.h>
44 #include <pthread.h>
45 #include <string>
46 #include <map>
47 #include <vector>
48 #include <utility>     // for pair<>
49 #include <algorithm>
50 #include "common/base/gflags.h"
51 #include "common/base/log.h"
52 #include "common/base/system.h"
53
54 #ifndef PATH_SEPARATOR
55 #define PATH_SEPARATOR  '/'
56 #endif
57
58 //// Work properly if either strtoll or strtoq is on this system
59 //#ifdef HAVE_STRTOLL
60 # define strtoint64  strtoll
61 # define strtouint64  strtoull
62 //#elif HAVE_STRTOQ
63 //# define strtoint64  strtoq
64 //# define strtouint64  strtouq
65 //#else
66 //// Neither strtoll nor strtoq are defined.  I hope strtol works!
67 //# define strtoint64 strtol
68 //# define strtouint64 strtoul
69 //#endif
70
71 using std::string;
72 using std::map;
73 using std::vector;
74 using std::pair;
75
76 // Special flags, type 1: the 'recursive' flags.  They set another flag's val.
77 DEFINE_string(flagfile, "",
78               "load flags from file");
79 DEFINE_string(fromenv, "",
80               "set flags from the environment [use 'export FLAGS_flag1=value']");
81 DEFINE_string(tryfromenv, "",
82               "set flags from the environment if present");
83
84 // Special flags, type 2: the 'parsing' flags.  They modify how we parse.
85 DEFINE_string(undefok, "",
86               "comma-separated list of flag names that it is okay to specify "
87               "on the command line even if the program does not define a flag "
88               "with that name.  IMPORTANT: flags in this list that have "
89               "arguments MUST use the flag=value format");
90
91 namespace google {
92
93 // There are also 'reporting' flags, in commandlineflags_reporting.cc.
94
95 static const char kError[] = "ERROR: ";
96
97 // The help message indicating that the commandline flag has been
98 // 'stripped'. It will not show up when doing "-help" and its
99 // variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
100 // before including base/commandlineflags.h (or in
101 // base/global_strip_options.h).
102
103 const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
104
105 // Indicates that undefined options are to be ignored.
106 // Enables deferred processing of flags in dynamically loaded libraries.
107 static bool allow_command_line_reparsing = false;
108
109 // --------------------------------------------------------------------
110 // FlagValue
111 //    This represent the value a single flag might have.  The major
112 //    functionality is to convert from a string to an object of a
113 //    given type, and back.
114 // --------------------------------------------------------------------
115
116 class FlagValue {
117  public:
118   FlagValue(void* valbuf, const char* type);
119   ~FlagValue();
120
121   bool ParseFrom(const char* spec);
122   string ToString() const;
123
124  private:
125   friend class CommandLineFlag;
126   friend class FlagSaverImpl;  // calls New()
127   template <typename T> friend T GetFromEnv(const char*, const char*, T);
128
129   enum ValueType {FV_BOOL, FV_INT32, FV_INT64, FV_UINT64, FV_DOUBLE, FV_STRING};
130
131   const char* TypeName() const;
132   bool Equal(const FlagValue& x) const;
133   FlagValue* New() const;   // creates a new one with default value
134   void CopyFrom(const FlagValue& x);
135
136   void* value_buffer_;          // points to the buffer holding our data
137   bool we_own_buffer_;          // true iff we new-ed the buffer
138   ValueType type_;              // how to interpret value_
139
140   FlagValue(const FlagValue&);   // no copying!
141   void operator=(const FlagValue&);
142 };
143
144
145 // This could be a templated method of FlagValue, but doing so adds to the
146 // size of the .o.  Since there's no type-safety here anyway, macro is ok.
147 #define VALUE_AS(type)  *reinterpret_cast<type*>(value_buffer_)
148 #define OTHER_VALUE_AS(fv, type)  *reinterpret_cast<type*>(fv.value_buffer_)
149 #define SET_VALUE_AS(type, value)  VALUE_AS(type) = (value)
150
151 FlagValue::FlagValue(void* valbuf, const char* type) : value_buffer_(valbuf) {
152   if      (strcmp(type, "bool") == 0)  type_ = FV_BOOL;
153   else if (strcmp(type, "int32") == 0)  type_ = FV_INT32;
154   else if (strcmp(type, "int64") == 0)  type_ = FV_INT64;
155   else if (strcmp(type, "uint64") == 0)  type_ = FV_UINT64;
156   else if (strcmp(type, "double") == 0)  type_ = FV_DOUBLE;
157   else if (strcmp(type, "string") == 0)  type_ = FV_STRING;
158   else assert(false); // Unknown typename
159 }
160
161 FlagValue::~FlagValue() {
162   switch (type_) {
163     case FV_BOOL: delete reinterpret_cast<bool*>(value_buffer_); break;
164     case FV_INT32: delete reinterpret_cast<int32*>(value_buffer_); break;
165     case FV_INT64: delete reinterpret_cast<int64*>(value_buffer_); break;
166     case FV_UINT64: delete reinterpret_cast<uint64*>(value_buffer_); break;
167     case FV_DOUBLE: delete reinterpret_cast<double*>(value_buffer_); break;
168     case FV_STRING: delete reinterpret_cast<string*>(value_buffer_); break;
169   }
170 }
171
172 bool FlagValue::ParseFrom(const char* value) {
173   if (type_ == FV_BOOL) {
174     const char* kTrue[] = { "1", "t", "true", "y", "yes" };
175     const char* kFalse[] = { "0", "f", "false", "n", "no" };
176     for (int i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) {
177       if (strcasecmp(value, kTrue[i]) == 0) {
178         SET_VALUE_AS(bool, true);
179         return true;
180       } else if (strcasecmp(value, kFalse[i]) == 0) {
181         SET_VALUE_AS(bool, false);
182         return true;
183       }
184     }
185     return false;   // didn't match a legal input
186
187   } else if (type_ == FV_STRING) {
188     SET_VALUE_AS(string, value);
189     return true;
190   }
191
192   // OK, it's likely to be numeric, and we'll be using a strtoXXX method.
193   if (value[0] == '\0')   // empty-string is only allowed for string type.
194     return false;
195   char* end;
196   // Leading 0x puts us in base 16.  But leading 0 does not put us in base 8!
197   // It caused too many bugs when we had that behavior.
198   int base = 10;    // by default
199   if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
200     base = 16;
201   errno = 0;
202
203   switch (type_) {
204     case FV_INT32: {
205       const int64 r = strtoint64(value, &end, base);
206       if (errno || end != value + strlen(value))  return false;  // bad parse
207       if (static_cast<int32>(r) != r)  // worked, but number out of range
208         return false;
209       SET_VALUE_AS(int32, r);
210       return true;
211     }
212     case FV_INT64: {
213       const int64 r = strtoint64(value, &end, base);
214       if (errno || end != value + strlen(value))  return false;  // bad parse
215       SET_VALUE_AS(int64, r);
216       return true;
217     }
218     case FV_UINT64: {
219       while (*value == ' ') value++;
220       if (*value == '-') return false;  // negative number
221       const uint64 r = strtouint64(value, &end, base);
222       if (errno || end != value + strlen(value))  return false;  // bad parse
223       SET_VALUE_AS(uint64, r);
224       return true;
225     }
226     case FV_DOUBLE: {
227       const double r = strtod(value, &end);
228       if (errno || end != value + strlen(value))  return false;  // bad parse
229       SET_VALUE_AS(double, r);
230       return true;
231     }
232     default: {
233       assert(false); // unknown type
234       return false;
235     }
236   }
237 }
238
239 string FlagValue::ToString() const {
240   char intbuf[64];    // enough to hold even the biggest number
241   switch (type_) {
242     case FV_BOOL:
243       return VALUE_AS(bool) ? "true" : "false";
244     case FV_INT32:
245       snprintf(intbuf, sizeof(intbuf), "%d", VALUE_AS(int32));
246       return intbuf;
247
248     case FV_INT64:
249       snprintf(intbuf, sizeof(intbuf), "%lld",
250                (long long int)VALUE_AS(int64));
251       return intbuf;
252     case FV_UINT64:
253       snprintf(intbuf, sizeof(intbuf), "%llu",
254                (long long unsigned int)VALUE_AS(uint64));
255       return intbuf;
256     case FV_DOUBLE:
257       snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
258       return intbuf;
259     case FV_STRING:
260       return VALUE_AS(string);
261     default:
262       assert(false); return ""; // unknown type
263   }
264 }
265
266 const char* FlagValue::TypeName() const {
267   switch (type_) {
268     case FV_BOOL:   return "bool";
269     case FV_INT32:  return "int32";
270     case FV_INT64:  return "int64";
271     case FV_UINT64: return "uint64";
272     case FV_DOUBLE: return "double";
273     case FV_STRING: return "string";
274     default: assert(false); return ""; // unknown type
275   }
276 }
277
278 bool FlagValue::Equal(const FlagValue& x) const {
279   if (type_ != x.type_)
280     return false;
281   switch (type_) {
282     case FV_BOOL:   return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool);
283     case FV_INT32:  return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32);
284     case FV_INT64:  return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64);
285     case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64);
286     case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double);
287     case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string);
288     default: assert(false); return false; // unknown type
289   }
290 }
291
292 FlagValue* FlagValue::New() const {
293   switch (type_) {
294     case FV_BOOL:   return new FlagValue(new bool, "bool");
295     case FV_INT32:  return new FlagValue(new int32, "int32");
296     case FV_INT64:  return new FlagValue(new int64, "int64");
297     case FV_UINT64: return new FlagValue(new uint64, "uint64");
298     case FV_DOUBLE: return new FlagValue(new double, "double");
299     case FV_STRING: return new FlagValue(new string, "string");
300     default: assert(false); return NULL; // assert false
301   }
302 }
303
304 void FlagValue::CopyFrom(const FlagValue& x) {
305   assert(type_ == x.type_);
306   switch (type_) {
307     case FV_BOOL:   SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool));      break;
308     case FV_INT32:  SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32));    break;
309     case FV_INT64:  SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64));    break;
310     case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64));  break;
311     case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double));  break;
312     case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string));  break;
313     default: assert(false); // unknown type
314   }
315 }
316
317 // --------------------------------------------------------------------
318 // CommandLineFlag
319 //    This represents a single flag, including its name, description,
320 //    default value, and current value.  Mostly this serves as a
321 //    struct, though it also knows how to register itself.
322 // --------------------------------------------------------------------
323
324 class CommandLineFlag {
325  public:
326   // Note: we take over memory-ownership of current_val and default_val.
327   CommandLineFlag(const char* name, const char* help, const char* filename,
328                   FlagValue* current_val, FlagValue* default_val);
329   ~CommandLineFlag();
330
331   const char* name() const { return name_; }
332   const char* help() const { return help_; }
333   const char* filename() const { return file_; }
334   const char* CleanFileName() const;  // nixes irrelevant prefix such as homedir
335   string current_value() const { return current_->ToString(); }
336   string default_value() const { return defvalue_->ToString(); }
337   const char* type_name() const { return defvalue_->TypeName(); }
338
339   void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result);
340
341  private:
342   friend class FlagRegistry;   // for SetFlagLocked()
343   friend class FlagSaverImpl;  // for cloning the values
344   friend bool GetCommandLineOption(const char*, string*, bool*);
345
346   // This copies all the non-const members: modified, processed, defvalue, etc.
347   void CopyFrom(const CommandLineFlag& src);
348
349   void UpdateModifiedBit();
350
351   const char* const name_;     // Flag name
352   const char* const help_;     // Help message
353   const char* const file_;     // Which file did this come from?
354   bool modified_;              // Set after default assignment?
355   FlagValue* defvalue_;        // Default value for flag
356   FlagValue* current_;         // Current value for flag
357
358   CommandLineFlag(const CommandLineFlag&);   // no copying!
359   void operator=(const CommandLineFlag&);
360 };
361
362 CommandLineFlag::CommandLineFlag(const char* name, const char* help,
363                                  const char* filename,
364                                  FlagValue* current_val, FlagValue* default_val)
365     : name_(name), help_(help), file_(filename), modified_(false),
366       defvalue_(default_val), current_(current_val) {
367 }
368
369 CommandLineFlag::~CommandLineFlag() {
370   delete current_;
371   delete defvalue_;
372 }
373
374 const char* CommandLineFlag::CleanFileName() const {
375   // Compute top-level directory & file that this appears in
376   // search full path backwards.
377   // Stop going backwards at kGoogle; and skip by the first slash.
378   // E.g.
379   //   filename_where_defined = "froogle/wrapping/autowrap/clustering/**.cc"
380   //   filename_where_defined = "file/util/fileutil.cc"
381   static const char kGoogle[] = "";    // can set this to whatever
382
383   if (sizeof(kGoogle)-1 == 0)          // no prefix to strip
384     return filename();
385
386   const char* clean_name = filename() + strlen(filename()) - 1;
387   while ( clean_name > filename() ) {
388     if (*clean_name == PATH_SEPARATOR) {
389       if (strncmp(clean_name, kGoogle, sizeof(kGoogle)-1) == 0) {
390         // ".../google/base/logging.cc" ==> "base/logging.cc"
391         clean_name += sizeof(kGoogle)-1;    // past "/google/"
392         break;
393       }
394     }
395     --clean_name;
396   }
397   while ( *clean_name == PATH_SEPARATOR ) ++clean_name;  // Skip any slashes
398   return clean_name;
399 }
400
401 void CommandLineFlag::FillCommandLineFlagInfo(
402     CommandLineFlagInfo* result) {
403   result->name = name();
404   result->type = type_name();
405   result->description = help();
406   result->current_value = current_value();
407   result->default_value = default_value();
408   result->filename = CleanFileName();
409   UpdateModifiedBit();
410   result->is_default = !modified_;
411 }
412
413 void CommandLineFlag::UpdateModifiedBit() {
414   // Update the "modified" bit in case somebody bypassed the
415   // Flags API and wrote directly through the FLAGS_name variable.
416   if (!modified_ && !current_->Equal(*defvalue_)) {
417     modified_ = true;
418   }
419 }
420
421 void CommandLineFlag::CopyFrom(const CommandLineFlag& src) {
422   // Note we only copy the non-const members; others are fixed at construct time
423   modified_ = src.modified_;
424   current_->CopyFrom(*src.current_);
425   defvalue_->CopyFrom(*src.defvalue_);
426 }
427
428
429 // --------------------------------------------------------------------
430 // FlagRegistry
431 //    A FlagRegistry singleton object holds all flag objects indexed
432 //    by their names so that if you know a flag's name (as a C
433 //    string), you can access or set it.  If the function is named
434 //    FooLocked(), you must own the registry lock before calling
435 //    the function; otherwise, you should *not* hold the lock, and
436 //    the function will acquire it itself if needed.
437 // --------------------------------------------------------------------
438
439 struct StringCmp {  // Used by the FlagRegistry map class to compare char*'s
440   bool operator() (const char* s1, const char* s2) const {
441     return (strcmp(s1, s2) < 0);
442   }
443 };
444
445 #define SAFE_PTHREAD(fncall)  do { if ((fncall) != 0) abort(); } while (0)
446
447 class FlagRegistry {
448  public:
449   FlagRegistry() { SAFE_PTHREAD(pthread_mutex_init(&lock_, NULL)); }
450   ~FlagRegistry() { SAFE_PTHREAD(pthread_mutex_destroy(&lock_)); }
451
452   // Store a flag in this registry.  Takes ownership of the given pointer.
453   void RegisterFlag(CommandLineFlag* flag);
454
455   void Lock() { SAFE_PTHREAD(pthread_mutex_lock(&lock_)); }
456   void Unlock() { SAFE_PTHREAD(pthread_mutex_unlock(&lock_)); }
457
458   // Returns the flag object for the specified name, or NULL if not found.
459   CommandLineFlag* FindFlagLocked(const char* name);
460
461   // A fancier form of FindFlag that works correctly if name is of the
462   // form flag=value.  In that case, we set key to point to flag, and
463   // modify v to point to the value, and return the flag with the
464   // given name (or NULL if not found).
465   CommandLineFlag* SplitArgumentLocked(const char* argument,
466                                        string* key, const char** v);
467
468   // Set the value of a flag.  If the flag was successfully set to
469   // value, set msg to indicate the new flag-value, and return true.
470   // Otherwise, set msg to indicate the error, leave flag unchanged,
471   // and return false.  msg can be NULL.
472   bool SetFlagLocked(CommandLineFlag* flag, const char* value,
473                      FlagSettingMode set_mode, string* msg);
474
475   static FlagRegistry* GlobalRegistry();   // returns a singleton registry
476
477  private:
478   friend class FlagSaverImpl;  // reads all the flags in order to copy them
479   friend void GetAllFlags(vector<CommandLineFlagInfo>*);
480
481   typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap;
482   typedef FlagMap::iterator FlagIterator;
483   typedef FlagMap::const_iterator FlagConstIterator;
484   FlagMap flags_;
485   pthread_mutex_t lock_;
486   static FlagRegistry* global_registry_;   // a singleton registry
487   static pthread_once_t global_registry_once_;
488   static int global_registry_once_nothreads_;   // when we don't link pthreads
489
490   static void InitGlobalRegistry();
491
492   // Disallow
493   FlagRegistry(const FlagRegistry&);
494   FlagRegistry& operator=(const FlagRegistry&);
495 };
496
497 void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
498   Lock();
499   pair<FlagIterator, bool> ins =
500     flags_.insert(pair<const char*, CommandLineFlag*>(flag->name(), flag));
501   if (ins.second == false) {   // means the name was already in the map
502     if (strcmp(ins.first->second->filename(), flag->filename()) != 0) {
503       fprintf(stderr,
504               "ERROR: flag '%s' was defined more than once "
505               "(in files '%s' and '%s').\n",
506               flag->name(),
507               ins.first->second->filename(),
508               flag->filename());
509     } else {
510       fprintf(stderr,
511               "ERROR: something wrong with flag '%s' in file '%s'.  "
512               "One possibility: file '%s' is being linked both statically "
513               "and dynamically into this executable.\n",
514               flag->name(),
515               flag->filename(), flag->filename());
516     }
517     common::Exit(1);   // almost certainly exit()
518   }
519   Unlock();
520 }
521
522 CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) {
523   FlagConstIterator i = flags_.find(name);
524   if (i == flags_.end()) {
525     return NULL;
526   } else {
527     return i->second;
528   }
529 }
530
531 CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg,
532                                                    string* key,
533                                                    const char** v) {
534   // Find the flag object for this option
535   const char* flag_name;
536   const char* value = strchr(arg, '=');
537   if (value == NULL) {
538     key->assign(arg);
539     *v = NULL;
540   } else {
541     // Strip out the "=value" portion from arg
542     key->assign(arg, value-arg);
543     *v = ++value;    // advance past the '='
544   }
545   flag_name = key->c_str();
546
547   CommandLineFlag* flag = FindFlagLocked(flag_name);
548   if (flag == NULL && (flag_name[0] == 'n') && (flag_name[1] == 'o')) {
549     // See if we can find a boolean flag named "x" for an option
550     // named "nox".
551     flag = FindFlagLocked(flag_name+2);
552     if (flag != NULL) {
553       if (strcmp(flag->type_name(), "bool") != 0) {
554         // This is not a boolean flag, so we should not strip the "no" prefix
555         flag = NULL;
556       } else {
557         // Make up a fake value to replace the "no" we stripped out
558         key->assign(flag_name+2);   // the name without the "no"
559         *v = "0";
560       }
561     }
562   }
563
564   if (flag == NULL) {
565     return NULL;
566   }
567
568   // Assign a value if this is a boolean flag
569   if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) {
570     *v = "1";    // the --nox case was already handled, so this is the --x case
571   }
572
573   return flag;
574 }
575
576 // Can't make this static because of friendship.
577 inline bool TryParse(const CommandLineFlag* flag, FlagValue* flag_value,
578                      const char* value, string* msg) {
579   if (flag_value->ParseFrom(value)) {
580     if (msg)
581       *msg += (string(flag->name()) + " set to " + flag_value->ToString()
582                + "\n");
583     return true;
584   } else {
585     if (msg)
586       *msg += (string(kError) + "illegal value '" + value +
587                + "' specified for " + flag->type_name() + " flag '"
588                + flag->name() + "'\n");
589     return false;
590   }
591 }
592
593 bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
594                                  const char* value,
595                                  FlagSettingMode set_mode,
596                                  string* msg) {
597   flag->UpdateModifiedBit();
598   switch (set_mode) {
599     case SET_FLAGS_VALUE: {
600       // set or modify the flag's value
601       if (!TryParse(flag, flag->current_, value, msg))
602         return false;
603       flag->modified_ = true;
604       break;
605     }
606     case SET_FLAG_IF_DEFAULT: {
607       // set the flag's value, but only if it hasn't been set by someone else
608       if (!flag->modified_) {
609         if (!TryParse(flag, flag->current_, value, msg))
610           return false;
611         flag->modified_ = true;
612       } else {
613         *msg = string(flag->name()) + " set to " + flag->current_value();
614       }
615       break;
616     }
617     case SET_FLAGS_DEFAULT: {
618       // modify the flag's default-value
619       if (!TryParse(flag, flag->defvalue_, value, msg))
620         return false;
621       if (!flag->modified_) {
622         // Need to set both defvalue *and* current, in this case
623         TryParse(flag, flag->current_, value, NULL);
624       }
625       break;
626     }
627     default: {
628       // unknown set_mode
629       assert(false); return false;
630     }
631   }
632
633   return true;
634 }
635
636 // Get the singleton FlagRegistry object
637 FlagRegistry* FlagRegistry::global_registry_ = NULL;
638 pthread_once_t FlagRegistry::global_registry_once_ = PTHREAD_ONCE_INIT;
639 int FlagRegistry::global_registry_once_nothreads_ = 0;
640
641 void FlagRegistry::InitGlobalRegistry() {
642   global_registry_ = new FlagRegistry;
643 }
644
645 // We want to use pthread_once here, for safety, but have to worry about
646 // whether libpthread is linked in or not.  We declare a weak version of
647 // the function, so we'll always compile (if the weak version is the only
648 // one that ends up existing, then pthread_once will be equal to NULL).
649 #ifdef HAVE___ATTRIBUTE__
650   // __THROW is defined in glibc systems.  It means, counter-intuitively,
651   // "This function will never throw an exception."  It's an optional
652   // optimization tool, but we may need to use it to match glibc prototypes.
653 # ifndef __THROW     // I guess we're not on a glibc system
654 #   define __THROW   // __THROW is just an optimization, so ok to make it ""
655 # endif
656 extern "C" int pthread_once(pthread_once_t *, void (*)(void))
657     __THROW __attribute__((weak));
658 #endif
659
660 FlagRegistry* FlagRegistry::GlobalRegistry() {
661   pthread_once(&global_registry_once_, &FlagRegistry::InitGlobalRegistry);
662   return global_registry_;
663 }
664
665
666 void FlagsTypeWarn(const char *name) {
667   fprintf(stderr, "ERROR: Flag %s is of type bool, "
668           "but its default value is not a boolean.\n", name);
669   // This can (and one day should) become a compilations error
670   //commandlineflags_exitfunc(1);   // almost certainly exit()
671 }
672
673 // --------------------------------------------------------------------
674 // FlagRegisterer
675 //    This class exists merely to have a global constructor (the
676 //    kind that runs before main(), that goes an initializes each
677 //    flag that's been declared.  Note that it's very important we
678 //    don't have a destructor that deletes flag_, because that would
679 //    cause us to delete current_storage/defvalue_storage as well,
680 //    which can cause a crash if anything tries to access the flag
681 //    values in a global destructor.
682 // --------------------------------------------------------------------
683
684 FlagRegisterer::FlagRegisterer(const char* name, const char* type,
685                                const char* help, const char* filename,
686                                void* current_storage, void* defvalue_storage) {
687   FlagValue* current = new FlagValue(current_storage, type);
688   FlagValue* defvalue = new FlagValue(defvalue_storage, type);
689   // Importantly, flag_ will never be deleted, so storage is always good.
690   flag_ = new CommandLineFlag(name, help, filename, current, defvalue);
691   FlagRegistry::GlobalRegistry()->RegisterFlag(flag_);   // default registry
692 }
693
694
695 // --------------------------------------------------------------------
696 // GetAllFlags()
697 //    The main way the FlagRegistry class exposes its data.  This
698 //    returns, as strings, all the info about all the flags in
699 //    the main registry, sorted first by filename they are defined
700 //    in, and then by flagname.
701 // --------------------------------------------------------------------
702
703 struct FilenameFlagnameCmp {
704   bool operator()(const CommandLineFlagInfo& a,
705                   const CommandLineFlagInfo& b) const {
706     int cmp = strcmp(a.filename.c_str(), b.filename.c_str());
707     if (cmp == 0)
708       cmp = strcmp(a.name.c_str(), b.name.c_str());  // secondary sort key
709     return cmp < 0;
710   }
711 };
712
713 void GetAllFlags(vector<CommandLineFlagInfo>* OUTPUT) {
714   FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
715   registry->Lock();
716   for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
717        i != registry->flags_.end(); ++i) {
718     CommandLineFlagInfo fi;
719     i->second->FillCommandLineFlagInfo(&fi);
720     OUTPUT->push_back(fi);
721   }
722   registry->Unlock();
723   // Now sort the flags, first by filename they occur in, then alphabetically
724   sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp());
725 }
726
727 // --------------------------------------------------------------------
728 // SetArgv()
729 // GetArgvs()
730 // GetArgv()
731 // GetArgv0()
732 // ProgramInvocationName()
733 // ProgramInvocationShortName()
734 // SetUsageMessage()
735 // ProgramUsage()
736 //    Functions to set and get argv.  Typically the setter is called
737 //    by ParseCommandLineFlags.  Also can get the ProgramUsage string,
738 //    set by SetUsageMessage.
739 // --------------------------------------------------------------------
740
741 // These values are not protected by a Mutex because they are normally
742 // set only once during program startup.
743 static const char* argv0 = "UNKNOWN";      // just the program name
744 static const char* cmdline = "";           // the entire command-line
745 static vector<string> argvs;
746 static uint32 argv_sum = 0;
747 static const char* program_usage = "Warning: SetUsageMessage() never called";
748 static bool program_usage_set = false;
749
750 void SetArgv(int argc, const char** argv) {
751   static bool called_set_argv = false;
752   if (called_set_argv)         // we already have an argv for you
753     return;
754
755   called_set_argv = true;
756
757   assert(argc > 0);            // every program has at least a progname
758   argv0 = strdup(argv[0]);     // small memory leak, but fn only called once
759   assert(argv0);
760
761   string cmdline_string = string("");        // easier than doing strcats
762   argvs.clear();
763   for (int i = 0; i < argc; i++) {
764     if (i != 0)
765       cmdline_string += " ";
766     cmdline_string += argv[i];
767     argvs.push_back(argv[i]);
768   }
769   cmdline = strdup(cmdline_string.c_str());  // another small memory leak
770   assert(cmdline);
771
772   // Compute a simple sum of all the chars in argv
773   argv_sum = 0;
774   for (const char* c = cmdline; *c; c++)
775     argv_sum += *c;
776 }
777
778 const vector<string>& GetArgvs() { return argvs; }
779 const char* GetArgv()            { return cmdline; }
780 const char* GetArgv0()           { return argv0; }
781 uint32 GetArgvSum()              { return argv_sum; }
782 const char* ProgramInvocationName() {             // like the GNU libc fn
783   return GetArgv0();
784 }
785 const char* ProgramInvocationShortName() {        // like the GNU libc fn
786   const char* slash = strrchr(argv0, '/');
787 #ifdef OS_WINDOWS
788   if (!slash)  slash = strrchr(argv0, '\\');
789 #endif
790   return slash ? slash + 1 : argv0;
791 }
792
793 void SetUsageMessage(const string& usage) {
794   if (program_usage_set) {
795     fprintf(stderr, "ERROR: SetUsageMessage() called more than once\n");
796     common::Exit(1);   // almost certainly exit()
797   }
798
799   program_usage = strdup(usage.c_str());      // small memory leak
800   program_usage_set = true;
801 }
802
803 const char* ProgramUsage() {
804   return program_usage;
805 }
806
807 // --------------------------------------------------------------------
808 // CommandLineFlagParser
809 //    Parsing is done in two stages.  In the first, we go through
810 //    argv.  For every flag-like arg we can make sense of, we parse
811 //    it and set the appropriate FLAGS_* variable.  For every flag-
812 //    like arg we can't make sense of, we store it in a vector,
813 //    along with an explanation of the trouble.  In stage 2, we
814 //    handle the 'reporting' flags like --help and --mpm_version.
815 //    (This is via a call to HandleCommandLineHelpFlags(), in
816 //    commandlineflags_reporting.cc.)
817 //    An optional stage 3 prints out the error messages.
818 //       This is a bit of a simplification.  For instance, --flagfile
819 //    is handled as soon as it's seen in stage 1, not in stage 2.
820 // --------------------------------------------------------------------
821
822 class CommandLineFlagParser {
823  public:
824   // The argument is the flag-registry to register the parsed flags in
825   explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {}
826   ~CommandLineFlagParser() {}
827
828   // Stage 1: Every time this is called, it reads all flags in argv.
829   // However, it ignores all flags that have been successfully set
830   // before.  Typically this is only called once, so this 'reparsing'
831   // behavior isn't important.  It can be useful when trying to
832   // reparse after loading a dll, though.
833   uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags);
834
835   // Stage 2: print reporting info and exit, if requested.
836   // In commandlineflags_reporting.cc:HandleCommandLineHelpFlags().
837
838   // Stage 3: report any errors and return true if any were found.
839   bool ReportErrors();
840
841   // Set a particular command line option.  "newval" is a string
842   // describing the new value that the option has been set to.  If
843   // option_name does not specify a valid option name, or value is not
844   // a valid value for option_name, newval is empty.  Does recursive
845   // processing for --flagfile and --fromenv.  Returns the new value
846   // if everything went ok, or empty-string if not.  (Actually, the
847   // return-string could hold many flag/value pairs due to --flagfile.)
848   // NB: Must have called registry_->Lock() before calling this function.
849   string ProcessSingleOptionLocked(CommandLineFlag* flag,
850                                    const char* value,
851                                    FlagSettingMode set_mode);
852
853   // Set a whole batch of command line options as specified by contentdata,
854   // which is in flagfile format (and probably has been read from a flagfile).
855   // Returns the new value if everything went ok, or empty-string if
856   // not.  (Actually, the return-string could hold many flag/value
857   // pairs due to --flagfile.)
858   // NB: Must have called registry_->Lock() before calling this function.
859   string ProcessOptionsFromStringLocked(const string& contentdata,
860                                         FlagSettingMode set_mode);
861
862   // These are the 'recursive' flags, defined at the top of this file.
863   // Whenever we see these flags on the commandline, we must take action.
864   // These are called by ProcessSingleOptionLocked and, similarly, return
865   // new values if everything went ok, or the empty-string if not.
866   string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode);
867   string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode,
868                               bool errors_are_fatal); // diff fromenv/tryfromenv
869
870  private:
871   FlagRegistry* const registry_;
872   map<string, string> error_flags_;     // map from name to error message
873   // This could be a set<string>, but we reuse the map to minimize the .o size
874   map<string, string> undefined_names_; // --name for name that's not registered
875 };
876
877
878 // Parse a list of (comma-separated) flags.
879 static void ParseFlagList(const char* value, vector<string>* flags) {
880   for (const char *p = value; p && *p; value = p) {
881     p = strchr(value, ',');
882     int len;
883     if (p) {
884       len = p - value;
885       p++;
886     } else {
887       len = strlen(value);
888     }
889
890     if (len == 0) {
891       fprintf(stderr, "ERROR: empty flaglist entry\n");
892       common::Exit(1);   // almost certainly exit()
893     }
894     if (value[0] == '-') {
895       fprintf(stderr, "ERROR: flag \"%*s\" begins with '-'\n", len, value);
896       common::Exit(1);
897     }
898
899     flags->push_back(string(value, len));
900   }
901 }
902
903 // Snarf an entire file into a C++ string.  This is just so that we
904 // can do all the I/O in one place and not worry about it everywhere.
905 // Plus, it's convenient to have the whole file contents at hand.
906 // Adds a newline at the end of the file.
907
908 static string ReadFileIntoString(const char* filename) {
909   const int bufsize = 8092;
910   char buffer[bufsize];
911   string s;
912   FILE* fp = fopen(filename, "r");
913   CHECK(fp) << "Error opening flags file " << filename;
914   int n;
915   while ( (n=fread(buffer, 1, bufsize, fp)) > 0 ) {
916     CHECK(!ferror(fp)) << "Error reading flags from " << filename;
917     s.append(buffer, n);
918   }
919   fclose(fp);
920   return s;
921 }
922
923 uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
924                                                        bool remove_flags) {
925   const char *program_name = strrchr((*argv)[0], PATH_SEPARATOR);   // nix path
926   program_name = (program_name == NULL ? (*argv)[0] : program_name+1);
927
928   int first_nonopt = *argc;        // for non-options moved to the end
929
930   registry_->Lock();
931   for (int i = 1; i < first_nonopt; i++) {
932     char* arg = (*argv)[i];
933
934     // Like getopt(), we permute non-option flags to be at the end.
935     if (arg[0] != '-') {           // must be a program argument
936       memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i]));
937       (*argv)[*argc-1] = arg;      // we go last
938       first_nonopt--;              // we've been pushed onto the stack
939       i--;                         // to undo the i++ in the loop
940       continue;
941     }
942
943     if (arg[0] == '-') arg++;      // allow leading '-'
944     if (arg[0] == '-') arg++;      // or leading '--'
945
946     // - and -- alone mean what they do for GNU: stop options parsing
947     if (*arg == '\0') {
948       first_nonopt = i+1;
949       break;
950     }
951
952     // Find the flag object for this option
953     string key;
954     const char* value;
955     CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value);
956     if (flag == NULL) {
957       undefined_names_[key] = "";    // value isn't actually used
958       error_flags_[key] = (string(kError) +
959                            "unknown command line flag '" + key + "'\n");
960       continue;
961     }
962
963     if (value == NULL) {
964       // Boolean options are always assigned a value by SplitArgumentLocked()
965       assert(strcmp(flag->type_name(), "bool") != 0);
966       if (i+1 >= first_nonopt) {
967         // This flag needs a value, but there is nothing available
968         error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'" +
969                             + " is missing its argument\n");
970         break;    // we treat this as an unrecoverable error
971       } else {
972         value = (*argv)[++i];                   // read next arg for value
973       }
974     }
975
976     // TODO(csilvers): only set a flag if we hadn't set it before here
977     ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE);
978   }
979   registry_->Unlock();
980
981   if (remove_flags) {   // Fix up argc and argv by removing command line flags
982     (*argv)[first_nonopt-1] = (*argv)[0];
983     (*argv) += (first_nonopt-1);
984     (*argc) -= (first_nonopt-1);
985     first_nonopt = 1;   // because we still don't count argv[0]
986   }
987
988   return first_nonopt;
989 }
990
991 string CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval,
992                                                     FlagSettingMode set_mode) {
993   if (flagval.empty())
994     return "";
995
996   string msg;
997   vector<string> filename_list;
998   ParseFlagList(flagval.c_str(), &filename_list);  // take a list of filenames
999   for (int i = 0; i < filename_list.size(); ++i) {
1000     const char* file = filename_list[i].c_str();
1001     msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode);
1002   }
1003   return msg;
1004 }
1005
1006 string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
1007                                                    FlagSettingMode set_mode,
1008                                                    bool errors_are_fatal) {
1009   if (flagval.empty())
1010     return "";
1011
1012   string msg;
1013   vector<string> flaglist;
1014   ParseFlagList(flagval.c_str(), &flaglist);
1015
1016   for (int i = 0; i < flaglist.size(); ++i) {
1017     const char* flagname = flaglist[i].c_str();
1018     CommandLineFlag* flag = registry_->FindFlagLocked(flagname);
1019     if (flag == NULL) {
1020       error_flags_[flagname] = (string(kError) + "unknown command line flag"
1021                                 + " '" + flagname + "'"
1022                                 + " (via --fromenv or --tryfromenv)\n");
1023       undefined_names_[flagname] = "";
1024       continue;
1025     }
1026
1027     const string envname = string("FLAGS_") + string(flagname);
1028     const char* envval = getenv(envname.c_str());
1029     if (!envval) {
1030       if (errors_are_fatal) {
1031         error_flags_[flagname] = (string(kError) + envname +
1032                                   " not found in environment\n");
1033       }
1034       continue;
1035     }
1036
1037     // Avoid infinite recursion.
1038     if ((strcmp(envval, "fromenv") == 0) ||
1039         (strcmp(envval, "tryfromenv") == 0)) {
1040       error_flags_[flagname] = (string(kError) + "infinite recursion on " +
1041                                 "environment flag '" + envval + "'\n");
1042       continue;
1043     }
1044
1045     msg += ProcessSingleOptionLocked(flag, envval, set_mode);
1046   }
1047   return msg;
1048 }
1049
1050 string CommandLineFlagParser::ProcessSingleOptionLocked(
1051     CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) {
1052   string msg;
1053   if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) {
1054     error_flags_[flag->name()] = msg;
1055     return "";
1056   }
1057
1058   // The recursive flags, --flagfile and --fromenv and --tryfromenv,
1059   // must be dealt with as soon as they're seen.  They will emit
1060   // messages of their own.
1061   if (strcmp(flag->name(), "flagfile") == 0) {
1062     msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode);
1063
1064   } else if (strcmp(flag->name(), "fromenv") == 0) {
1065     // last arg indicates envval-not-found is fatal (unlike in --tryfromenv)
1066     msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true);
1067
1068   } else if (strcmp(flag->name(), "tryfromenv") == 0) {
1069     msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false);
1070
1071   }
1072
1073   return msg;
1074 }
1075
1076 bool CommandLineFlagParser::ReportErrors() {
1077   // error_flags_ indicates errors we saw while parsing.
1078   // But we ignore undefined-names if ok'ed by --undef_ok
1079   if (!FLAGS_undefok.empty()) {
1080     vector<string> flaglist;
1081     ParseFlagList(FLAGS_undefok.c_str(), &flaglist);
1082     for (int i = 0; i < flaglist.size(); ++i)
1083       if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) {
1084         error_flags_[flaglist[i]] = "";    // clear the error message
1085       }
1086   }
1087   // Likewise, if they decided to allow reparsing, all undefined-names
1088   // are ok; we just silently ignore them now, and hope that a future
1089   // parse will pick them up somehow.
1090   if (allow_command_line_reparsing) {
1091     for (map<string,string>::const_iterator it = undefined_names_.begin();
1092          it != undefined_names_.end();  ++it)
1093       error_flags_[it->first] = "";      // clear the error message
1094   }
1095
1096   bool found_error = false;
1097   for (map<string,string>::const_iterator it = error_flags_.begin();
1098        it != error_flags_.end(); ++it) {
1099     if (!it->second.empty()) {
1100       fprintf(stderr, "%s", it->second.c_str());
1101       found_error = true;
1102     }
1103   }
1104   return found_error;
1105 }
1106
1107 string CommandLineFlagParser::ProcessOptionsFromStringLocked(
1108     const string& contentdata, FlagSettingMode set_mode) {
1109   string retval;
1110   const char* flagfile_contents = contentdata.c_str();
1111   bool flags_are_relevant = true;   // set to false when filenames don't match
1112   bool in_filename_section = false;
1113
1114   const char* line_end = flagfile_contents;
1115   // We read this file a line at a time.
1116   for (; line_end; flagfile_contents = line_end + 1) {
1117     while (*flagfile_contents && isspace(*flagfile_contents))
1118       ++flagfile_contents;
1119     // MIHAI: Added the standard \\n line splitter...
1120     string line;
1121     while (true) {
1122       line_end = strchr(flagfile_contents, '\n');
1123       int len = line_end ? line_end-flagfile_contents : strlen(flagfile_contents);
1124       if (line_end) {
1125         if (line_end > flagfile_contents) {
1126           if (*(line_end-1) == '\\') {
1127             line += string(flagfile_contents, len-1);
1128             flagfile_contents = line_end + 1;
1129             continue;
1130           }
1131         }
1132       }
1133       line += string(flagfile_contents, len);
1134       break;
1135     }
1136
1137     // Each line can be one of four things:
1138     // 1) A comment line -- we skip it
1139     // 2) An empty line -- we skip it
1140     // 3) A list of filenames -- starts a new filenames+flags section
1141     // 4) A --flag=value line -- apply if previous filenames match
1142     if (line.empty() || line[0] == '#') {
1143       // comment or empty line; just ignore
1144
1145     } else if (line[0] == '-') {    // flag
1146       in_filename_section = false;  // instead, it was a flag-line
1147       if (!flags_are_relevant)      // skip this flag; applies to someone else
1148         continue;
1149
1150       const char* name_and_val = line.c_str() + 1;    // skip the leading -
1151       if (*name_and_val == '-')
1152         name_and_val++;                               // skip second - too
1153       string key;
1154       const char* value;
1155       CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val,
1156                                                              &key, &value);
1157       // By API, errors parsing flagfile lines are silently ignored.
1158       if (flag == NULL) {
1159         // "WARNING: flagname '" + key + "' not found\n"
1160       } else if (value == NULL) {
1161         // "WARNING: flagname '" + key + "' missing a value\n"
1162       } else {
1163         retval += ProcessSingleOptionLocked(flag, value, set_mode);
1164       }
1165
1166     } else {                        // a filename!
1167       if (!in_filename_section) {   // start over: assume filenames don't match
1168         in_filename_section = true;
1169         flags_are_relevant = false;
1170       }
1171
1172       // Split the line up at spaces into glob-patterns
1173       const char* space = line.c_str();   // just has to be non-NULL
1174       for (const char* word = line.c_str(); *space; word = space+1) {
1175         if (flags_are_relevant)     // we can stop as soon as we match
1176           break;
1177         space = strchr(word, ' ');
1178         if (space == NULL)
1179           space = word + strlen(word);
1180         const string glob(word, space - word);
1181         // We try matching both against the full argv0 and basename(argv0)
1182         if (fnmatch(glob.c_str(), ProgramInvocationName(), FNM_PATHNAME) == 0 ||
1183             fnmatch(glob.c_str(), ProgramInvocationShortName(), FNM_PATHNAME) == 0) {
1184           flags_are_relevant = true;
1185         }
1186       }
1187     }
1188   }
1189   return retval;
1190 }
1191
1192
1193 // --------------------------------------------------------------------
1194 // GetCommandLineOption()
1195 // GetCommandLineFlagInfo()
1196 // GetCommandLineFlagInfoOrDie()
1197 // SetCommandLineOption()
1198 // SetCommandLineOptionWithMode()
1199 //    The programmatic way to set a flag's value, using a string
1200 //    for its name rather than the variable itself (that is,
1201 //    SetCommandLineOption("foo", x) rather than FLAGS_foo = x).
1202 //    There's also a bit more flexibility here due to the various
1203 //    set-modes, but typically these are used when you only have
1204 //    that flag's name as a string, perhaps at runtime.
1205 //    All of these work on the default, global registry.
1206 //       For GetCommandLineOption, return false if no such flag
1207 //    is known, true otherwise.  We clear "value" if a suitable
1208 //    flag is found.
1209 // --------------------------------------------------------------------
1210
1211
1212 bool GetCommandLineOption(const char* name, string* value) {
1213   if (NULL == name)
1214     return false;
1215   assert(value);
1216
1217   FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
1218   registry->Lock();
1219   CommandLineFlag* flag = registry->FindFlagLocked(name);
1220   if (flag == NULL) {
1221     registry->Unlock();
1222     return false;
1223   } else {
1224     *value = flag->current_value();
1225     registry->Unlock();
1226     return true;
1227   }
1228 }
1229
1230 bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) {
1231   if (NULL == name) return false;
1232   FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
1233   registry->Lock();
1234   CommandLineFlag* flag = registry->FindFlagLocked(name);
1235   if (flag == NULL) {
1236     registry->Unlock();
1237     return false;
1238   } else {
1239     assert(OUTPUT);
1240     flag->FillCommandLineFlagInfo(OUTPUT);
1241     registry->Unlock();
1242     return true;
1243   }
1244 }
1245
1246 CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
1247   CommandLineFlagInfo info;
1248   if (!GetCommandLineFlagInfo(name, &info)) {
1249     fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exit", name);
1250     common::Exit(1);    // almost certainly exit()
1251   }
1252   return info;
1253 }
1254
1255 string SetCommandLineOptionWithMode(const char* name, const char* value,
1256                                     FlagSettingMode set_mode) {
1257   string result;
1258   FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
1259   registry->Lock();
1260   CommandLineFlag* flag = registry->FindFlagLocked(name);
1261   if (flag) {
1262     CommandLineFlagParser parser(registry);
1263     result = parser.ProcessSingleOptionLocked(flag, value, set_mode);
1264     if (!result.empty()) {   // in the error case, we've already logged
1265       // You could consider logging this change, if you wanted to know it:
1266       //fprintf(stderr, "%sFLAGS_%s\n",
1267       //        (set_mode == SET_FLAGS_DEFAULT ? "default value of " : ""),
1268       //        result);
1269     }
1270   }
1271   registry->Unlock();
1272   // The API of this function is that we return empty string on error
1273   return result;
1274 }
1275
1276 string SetCommandLineOption(const char* name, const char* value) {
1277   return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE);
1278 }
1279
1280
1281 // --------------------------------------------------------------------
1282 // FlagSaver
1283 // FlagSaverImpl
1284 //    This class stores the states of all flags at construct time,
1285 //    and restores all flags to that state at destruct time.
1286 //    Its major implementation challenge is that it never modifies
1287 //    pointers in the 'main' registry, so global FLAG_* vars always
1288 //    point to the right place.
1289 // --------------------------------------------------------------------
1290
1291 class FlagSaverImpl {
1292  public:
1293   // Constructs an empty FlagSaverImpl object.
1294   explicit FlagSaverImpl(FlagRegistry* main_registry)
1295       : main_registry_(main_registry) { }
1296   ~FlagSaverImpl() {
1297     // reclaim memory from each of our CommandLineFlags
1298     vector<CommandLineFlag*>::const_iterator it;
1299     for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it)
1300       delete *it;
1301   }
1302
1303   // Saves the flag states from the flag registry into this object.
1304   // It's an error to call this more than once.
1305   // Must be called when the registry mutex is not held.
1306   void SaveFromRegistry() {
1307     main_registry_->Lock();
1308     assert(backup_registry_.empty());   // call only once!
1309     for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin();
1310          it != main_registry_->flags_.end();
1311          ++it) {
1312       const CommandLineFlag* main = it->second;
1313       // Sets up all the const variables in backup correctly
1314       CommandLineFlag* backup = new CommandLineFlag(
1315           main->name(), main->help(), main->filename(),
1316           main->current_->New(), main->defvalue_->New());
1317       // Sets up all the non-const variables in backup correctly
1318       backup->CopyFrom(*main);
1319       backup_registry_.push_back(backup);   // add it to a convenient list
1320     }
1321     main_registry_->Unlock();
1322   }
1323
1324   // Restores the saved flag states into the flag registry.  We
1325   // assume no flags were added or deleted from the registry since
1326   // the SaveFromRegistry; if they were, that's trouble!  Must be
1327   // called when the registry mutex is not held.
1328   void RestoreToRegistry() {
1329     main_registry_->Lock();
1330     vector<CommandLineFlag*>::const_iterator it;
1331     for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) {
1332       CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name());
1333       if (main != NULL) {       // if NULL, flag got deleted from registry(!)
1334         main->CopyFrom(**it);
1335       }
1336     }
1337     main_registry_->Unlock();
1338   }
1339
1340  private:
1341   FlagRegistry* const main_registry_;
1342   vector<CommandLineFlag*> backup_registry_;
1343
1344   FlagSaverImpl(const FlagSaverImpl&);  // no copying!
1345   void operator=(const FlagSaverImpl&);
1346 };
1347
1348 FlagSaver::FlagSaver() : impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) {
1349   impl_->SaveFromRegistry();
1350 }
1351
1352 FlagSaver::~FlagSaver() {
1353   impl_->RestoreToRegistry();
1354   delete impl_;
1355 }
1356
1357
1358 // --------------------------------------------------------------------
1359 // CommandlineFlagsIntoString()
1360 // ReadFlagsFromString()
1361 // AppendFlagsIntoFile()
1362 // ReadFromFlagsFile()
1363 //    These are mostly-deprecated routines that stick the
1364 //    commandline flags into a file/string and read them back
1365 //    out again.  I can see a use for CommandlineFlagsIntoString,
1366 //    for creating a flagfile, but the rest don't seem that useful
1367 //    -- some, I think, are a poor-man's attempt at FlagSaver --
1368 //    and are included only until we can delete them from callers.
1369 //    Note they don't save --flagfile flags (though they do save
1370 //    the result of having called the flagfile, of course).
1371 // --------------------------------------------------------------------
1372
1373 static string TheseCommandlineFlagsIntoString(
1374     const vector<CommandLineFlagInfo>& flags) {
1375   vector<CommandLineFlagInfo>::const_iterator i;
1376
1377   int retval_space = 0;
1378   for (i = flags.begin(); i != flags.end(); ++i) {
1379     // An (over)estimate of how much space it will take to print this flag
1380     retval_space += i->name.length() + i->current_value.length() + 5;
1381   }
1382
1383   string retval;
1384   retval.reserve(retval_space);
1385   for (i = flags.begin(); i != flags.end(); ++i) {
1386     retval += "--";
1387     retval += i->name;
1388     retval += "=";
1389     retval += i->current_value;
1390     retval += "\n";
1391   }
1392   return retval;
1393 }
1394
1395 string CommandlineFlagsIntoString() {
1396   vector<CommandLineFlagInfo> sorted_flags;
1397   GetAllFlags(&sorted_flags);
1398   return TheseCommandlineFlagsIntoString(sorted_flags);
1399 }
1400
1401 bool ReadFlagsFromString(const string& flagfilecontents,
1402                          const char* prog_name,   // TODO(csilvers): nix this
1403                          bool errors_are_fatal) {
1404   FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
1405   FlagSaverImpl saved_states(registry);
1406   saved_states.SaveFromRegistry();
1407
1408   CommandLineFlagParser parser(registry);
1409   registry->Lock();
1410   parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE);
1411   registry->Unlock();
1412   // Should we handle --help and such when reading flags from a string?  Sure.
1413   HandleCommandLineHelpFlags();
1414   if (parser.ReportErrors()) {
1415     // Error.  Restore all global flags to their previous values.
1416     if (errors_are_fatal)
1417       common::Exit(1);    // almost certainly exit()
1418     saved_states.RestoreToRegistry();
1419     return false;
1420   }
1421   return true;
1422 }
1423
1424 // TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName()
1425 bool AppendFlagsIntoFile(const string& filename, const char *prog_name) {
1426   FILE *fp = fopen(filename.c_str(), "a");
1427   if (!fp) {
1428     return false;
1429   }
1430
1431   if (prog_name)
1432     fprintf(fp, "%s\n", prog_name);
1433
1434   vector<CommandLineFlagInfo> flags;
1435   GetAllFlags(&flags);
1436   // But we don't want --flagfile, which leads to weird recursion issues
1437   vector<CommandLineFlagInfo>::iterator i;
1438   for (i = flags.begin(); i != flags.end(); ++i) {
1439     if (strcmp(i->name.c_str(), "flagfile") == 0) {
1440       flags.erase(i);
1441       break;
1442     }
1443   }
1444   fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str());
1445
1446   fclose(fp);
1447   return true;
1448 }
1449
1450 bool ReadFromFlagsFile(const string& filename, const char* prog_name,
1451                        bool errors_are_fatal) {
1452   return ReadFlagsFromString(ReadFileIntoString(filename.c_str()),
1453                              prog_name, errors_are_fatal);
1454 }
1455
1456
1457 // --------------------------------------------------------------------
1458 // BoolFromEnv()
1459 // Int32FromEnv()
1460 // Int64FromEnv()
1461 // Uint64FromEnv()
1462 // DoubleFromEnv()
1463 // StringFromEnv()
1464 //    Reads the value from the environment and returns it.
1465 //    We use an FlagValue to make the parsing easy.
1466 //    Example usage:
1467 //       DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever");
1468 // --------------------------------------------------------------------
1469
1470 template<typename T>
1471 T GetFromEnv(const char *varname, const char* type, T dflt) {
1472   const char* const valstr = getenv(varname);
1473   if (!valstr)
1474     return dflt;
1475   FlagValue ifv(new T, type);
1476   if (!ifv.ParseFrom(valstr)) {
1477     fprintf(stderr, "ERROR: error parsing env variable '%s' with value '%s'\n",
1478             varname, valstr);
1479     common::Exit(1);   // almost certainly exit()
1480   }
1481   return OTHER_VALUE_AS(ifv, T);
1482 }
1483
1484 bool BoolFromEnv(const char *v, bool dflt) {
1485   return GetFromEnv(v, "bool", dflt);
1486 }
1487 int32 Int32FromEnv(const char *v, int32 dflt) {
1488   return GetFromEnv(v, "int32", dflt);
1489 }
1490 int64 Int64FromEnv(const char *v, int64 dflt)    {
1491   return GetFromEnv(v, "int64", dflt);
1492 }
1493 uint64 Uint64FromEnv(const char *v, uint64 dflt) {
1494   return GetFromEnv(v, "uint64", dflt);
1495 }
1496 double DoubleFromEnv(const char *v, double dflt) {
1497   return GetFromEnv(v, "double", dflt);
1498 }
1499 const char *StringFromEnv(const char *varname, const char *dflt) {
1500   const char* const val = getenv(varname);
1501   return val ? val : dflt;
1502 }
1503
1504
1505 // --------------------------------------------------------------------
1506 // ParseCommandLineFlags()
1507 // ParseCommandLineNonHelpFlags()
1508 // HandleCommandLineHelpFlags()
1509 //    This is the main function called from main(), to actually
1510 //    parse the commandline.  It modifies argc and argv as described
1511 //    at the top of commandlineflags.h.  You can also divide this
1512 //    function into two parts, if you want to do work between
1513 //    the parsing of the flags and the printing of any help output.
1514 // --------------------------------------------------------------------
1515
1516 static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv,
1517                                             bool remove_flags, bool do_report) {
1518   SetArgv(*argc, const_cast<const char**>(*argv));    // save it for later
1519
1520   FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
1521   CommandLineFlagParser parser(registry);
1522
1523   // When we parse the commandline flags, we'll handle --flagfile,
1524   // --tryfromenv, etc. as we see them (since flag-evaluation order
1525   // may be important).  But sometimes apps set FLAGS_tryfromenv/etc.
1526   // manually before calling ParseCommandLineFlags.  We want to evaluate
1527   // those too, as if they were the first flags on the commandline.
1528   registry->Lock();
1529   parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE);
1530   // Last arg here indicates whether flag-not-found is a fatal error or not
1531   parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true);
1532   parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false);
1533   registry->Unlock();
1534
1535   // Now get the flags specified on the commandline
1536   const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags);
1537
1538   if (do_report)
1539     HandleCommandLineHelpFlags();   // may cause us to exit on --help, etc.
1540   if (parser.ReportErrors())        // may cause us to exit on illegal flags
1541     common::Exit(1);   // almost certainly exit()
1542   return r;
1543 }
1544
1545 uint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) {
1546   return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true);
1547 }
1548
1549 uint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv,
1550                                     bool remove_flags) {
1551   return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false);
1552 }
1553
1554 // --------------------------------------------------------------------
1555 // AllowCommandLineReparsing()
1556 // ReparseCommandLineNonHelpFlags()
1557 //    This is most useful for shared libraries.  The idea is if
1558 //    a flag is defined in a shared library that is dlopen'ed
1559 //    sometime after main(), you can ParseCommandLineFlags before
1560 //    the dlopen, then ReparseCommandLineNonHelpFlags() after the
1561 //    dlopen, to get the new flags.  But you have to explicitly
1562 //    Allow() it; otherwise, you get the normal default behavior
1563 //    of unrecognized flags calling a fatal error.
1564 //    TODO(csilvers): this isn't used.  Just delete it?
1565 // --------------------------------------------------------------------
1566
1567 void AllowCommandLineReparsing() {
1568   allow_command_line_reparsing = true;
1569 }
1570
1571 uint32 ReparseCommandLineNonHelpFlags() {
1572   // We make a copy of argc and argv to pass in
1573   const vector<string>& argvs = GetArgvs();
1574   int tmp_argc = argvs.size();
1575   char** tmp_argv = new char* [tmp_argc + 1];
1576   for (int i = 0; i < tmp_argc; ++i)
1577     tmp_argv[i] = strdup(argvs[i].c_str());   // TODO(csilvers): don't dup
1578
1579   const int retval = ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false);
1580
1581   for (int i = 0; i < tmp_argc; ++i)
1582     free(tmp_argv[i]);
1583   delete[] tmp_argv;
1584
1585   return retval;
1586 }
1587
1588 }
Note: See TracBrowser for help on using the browser.