10a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Copyright (c) 2006, Google Inc.
20a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// All rights reserved.
30a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
40a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Redistribution and use in source and binary forms, with or without
50a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// modification, are permitted provided that the following conditions are
60a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// met:
70a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
80a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//     * Redistributions of source code must retain the above copyright
90a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// notice, this list of conditions and the following disclaimer.
100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//     * Redistributions in binary form must reproduce the above
110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// copyright notice, this list of conditions and the following disclaimer
120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// in the documentation and/or other materials provided with the
130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// distribution.
140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//     * Neither the name of Google Inc. nor the names of its
150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// contributors may be used to endorse or promote products derived from
160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// this software without specific prior written permission.
170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ---
310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Author: Ray Sidney
320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Revamped and reorganized by Craig Silverstein
330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This file contains the implementation of all our command line flags
350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// stuff.  Here's how everything fits together
360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// * FlagRegistry owns CommandLineFlags owns FlagValue.
380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// * FlagSaver holds a FlagRegistry (saves it at construct time,
390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//     restores it at destroy time).
400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// * CommandLineFlagParser lives outside that hierarchy, but works on
410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//     CommandLineFlags (modifying the FlagValues).
420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// * Free functions like SetCommandLineOption() work via one of the
430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//     above (such as CommandLineFlagParser).
440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// In more detail:
460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -- The main classes that hold flag data:
480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagValue holds the current value of a flag.  It's
500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// pseudo-templatized: every operation on a FlagValue is typed.  It
510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// also deals with storage-lifetime issues (so flag values don't go
520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// away in a destructor), which is why we need a whole class to hold a
530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// variable's value.
540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandLineFlag is all the information about a single command-line
560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// flag.  It has a FlagValue for the flag's current value, but also
570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// the flag's name, type, etc.
580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagRegistry is a collection of CommandLineFlags.  There's the
600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// global registry, which is where flags defined via DEFINE_foo()
610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// live.  But it's possible to define your own flag, manually, in a
620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// different registry you create.  (In practice, multiple registries
630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// are used only by FlagSaver).
640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// A given FlagValue is owned by exactly one CommandLineFlag.  A given
660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandLineFlag is owned by exactly one FlagRegistry.  FlagRegistry
670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// has a lock; any operation that writes to a FlagValue or
680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandLineFlag owned by that registry must acquire the
690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagRegistry lock before doing so.
700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --- Some other classes and free functions:
720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandLineFlagInfo is a client-exposed version of CommandLineFlag.
740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Once it's instantiated, it has no dependencies or relationships
750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// with any other part of this file.
760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagRegisterer is the helper class used by the DEFINE_* macros to
780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// allow work to be done at global initialization time.
790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandLineFlagParser is the class that reads from the commandline
810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// and instantiates flag values based on that.  It needs to poke into
820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// the innards of the FlagValue->CommandLineFlag->FlagRegistry class
830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// hierarchy to do that.  It's careful to acquire the FlagRegistry
840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// lock before doing any writing or other non-const actions.
850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//
860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetCommandLineOption is just a hook into registry routines to
870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// retrieve a flag based on its name.  SetCommandLineOption, on the
880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// other hand, hooks into CommandLineFlagParser.  Other API functions
890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// are, similarly, mostly hooks into the functionality described above.
900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "config.h"
920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This comes first to ensure we define __STDC_FORMAT_MACROS in time.
930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef HAVE_INTTYPES_H
940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifndef __STDC_FORMAT_MACROS
950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define __STDC_FORMAT_MACROS 1   // gcc requires this to get PRId64, etc.
960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif
970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <inttypes.h>
980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif  // HAVE_INTTYPES_H
990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <stdio.h>     // for snprintf
1000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <ctype.h>
1010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <errno.h>
1020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <stdio.h>
1030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <stdarg.h> // For va_list and related operations
1040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string.h>
1050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <assert.h>
1060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef HAVE_FNMATCH_H
1070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <fnmatch.h>
1080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif  // HAVE_FNMATCH_H
1090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <iostream>    // for cerr
1100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string>
1110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <map>
1120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <vector>
1130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <utility>     // for pair<>
1140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <algorithm>
1150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <gflags/gflags.h>
1160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "mutex.h"
1170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifndef PATH_SEPARATOR
1190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#define PATH_SEPARATOR  '/'
1200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif
1210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Work properly if either strtoll or strtoq is on this system
1230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef HAVE_STRTOLL
1240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define strtoint64  strtoll
1250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define strtouint64  strtoull
1260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#elif HAVE_STRTOQ
1270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define strtoint64  strtoq
1280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define strtouint64  strtouq
1290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#else
1300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Neither strtoll nor strtoq are defined.  I hope strtol works!
1310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define strtoint64 strtol
1320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define strtouint64 strtoul
1330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif
1340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// If we have inttypes.h, it will have defined PRId32/etc for us.  If
1360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// not, take our best guess.
1370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifndef PRId32
1380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define PRId32 "d"
1390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif
1400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifndef PRId64
1410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define PRId64 "lld"
1420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif
1430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifndef PRIu64
1440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# define PRIu64 "llu"
1450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif
1460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Special flags, type 1: the 'recursive' flags.  They set another flag's val.
1480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(flagfile, "",
1490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              "load flags from file");
1500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(fromenv, "",
1510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              "set flags from the environment"
1520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              " [use 'export FLAGS_flag1=value']");
1530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(tryfromenv, "",
1540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              "set flags from the environment if present");
1550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Special flags, type 2: the 'parsing' flags.  They modify how we parse.
1570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(undefok, "",
1580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              "comma-separated list of flag names that it is okay to specify "
1590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              "on the command line even if the program does not define a flag "
1600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              "with that name.  IMPORTANT: flags in this list that have "
1610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath              "arguments MUST use the flag=value format");
1620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath_START_GOOGLE_NAMESPACE_
1640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::cerr;
1660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::map;
1670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::pair;
1680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::sort;
1690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::string;
1700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::vector;
1710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The help message indicating that the commandline flag has been
1730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 'stripped'. It will not show up when doing "-help" and its
1740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
1750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// before including gflags/gflags.h.
1760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This is used by this file, and also in commandlineflags_reporting.cc
1780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
1790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This is used by the unittest to test error-exit code
1810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid GFLAGS_DLL_DECL (*commandlineflags_exitfunc)(int) = &exit;   // from stdlib.h
1820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathnamespace {
1840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// There are also 'reporting' flags, in commandlineflags_reporting.cc.
1860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const char kError[] = "ERROR: ";
1880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Indicates that undefined options are to be ignored.
1900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Enables deferred processing of flags in dynamically loaded libraries.
1910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic bool allow_command_line_reparsing = false;
1920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic bool logging_is_probably_set_up = false;
1940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
1950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This is a 'prototype' validate-function.  'Real' validate
1960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// functions, take a flag-value as an argument: ValidateFn(bool) or
1970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ValidateFn(uint64).  However, for easier storage, we strip off this
1980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// argument and then restore it when actually calling the function on
1990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// a flag value.
2000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathtypedef bool (*ValidateFnProto)();
2010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Whether we should die when reporting an error.
2030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathenum DieWhenReporting { DIE, DO_NOT_DIE };
2040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Report Error and exit if requested.
2060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void ReportError(DieWhenReporting should_die, const char* format, ...) {
2070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  va_list ap;
2080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  va_start(ap, format);
2090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vfprintf(stderr, format, ap);
2100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  va_end(ap);
2110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (should_die == DIE)
2120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    commandlineflags_exitfunc(1);   // almost certainly exit()
2130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
2140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
2170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagValue
2180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    This represent the value a single flag might have.  The major
2190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    functionality is to convert from a string to an object of a
2200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    given type, and back.  Thread-compatible.
2210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
2220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass CommandLineFlag;
2240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass FlagValue {
2250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public:
2260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue(void* valbuf, const char* type);
2270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ~FlagValue();
2280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool ParseFrom(const char* spec);
2300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string ToString() const;
2310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private:
2330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend class CommandLineFlag;  // for many things, including Validate()
2340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend class GOOGLE_NAMESPACE::FlagSaverImpl;  // calls New()
2350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend class FlagRegistry;     // checks value_buffer_ for flags_by_ptr_ map
2360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  template <typename T> friend T GetFromEnv(const char*, const char*, T);
2370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
2380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                             const char*, string*);  // for New(), CopyFrom()
2390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  enum ValueType {FV_BOOL, FV_INT32, FV_INT64, FV_UINT64, FV_DOUBLE, FV_STRING};
2410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* TypeName() const;
2430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool Equal(const FlagValue& x) const;
2440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue* New() const;   // creates a new one with default value
2450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void CopyFrom(const FlagValue& x);
2460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Calls the given validate-fn on value_buffer_, and returns
2480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // whatever it returns.  But first casts validate_fn_proto to a
2490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // function that takes our value as an argument (eg void
2500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // (*validate_fn)(bool) for a bool flag).
2510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const;
2520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void* value_buffer_;          // points to the buffer holding our data
2540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ValueType type_;              // how to interpret value_
2550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue(const FlagValue&);   // no copying!
2570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void operator=(const FlagValue&);
2580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
2590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This could be a templated method of FlagValue, but doing so adds to the
2620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// size of the .o.  Since there's no type-safety here anyway, macro is ok.
2630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#define VALUE_AS(type)  *reinterpret_cast<type*>(value_buffer_)
2640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#define OTHER_VALUE_AS(fv, type)  *reinterpret_cast<type*>(fv.value_buffer_)
2650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#define SET_VALUE_AS(type, value)  VALUE_AS(type) = (value)
2660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagValue::FlagValue(void* valbuf, const char* type) : value_buffer_(valbuf) {
2680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if      (strcmp(type, "bool") == 0)  type_ = FV_BOOL;
2690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  else if (strcmp(type, "int32") == 0)  type_ = FV_INT32;
2700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  else if (strcmp(type, "int64") == 0)  type_ = FV_INT64;
2710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  else if (strcmp(type, "uint64") == 0)  type_ = FV_UINT64;
2720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  else if (strcmp(type, "double") == 0)  type_ = FV_DOUBLE;
2730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  else if (strcmp(type, "string") == 0)  type_ = FV_STRING;
2740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  else assert(false); // Unknown typename
2750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
2760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagValue::~FlagValue() {
2780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
2790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_BOOL: delete reinterpret_cast<bool*>(value_buffer_); break;
2800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32: delete reinterpret_cast<int32*>(value_buffer_); break;
2810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64: delete reinterpret_cast<int64*>(value_buffer_); break;
2820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64: delete reinterpret_cast<uint64*>(value_buffer_); break;
2830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE: delete reinterpret_cast<double*>(value_buffer_); break;
2840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_STRING: delete reinterpret_cast<string*>(value_buffer_); break;
2850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
2860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
2870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
2880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool FlagValue::ParseFrom(const char* value) {
2890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (type_ == FV_BOOL) {
2900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const char* kTrue[] = { "1", "t", "true", "y", "yes" };
2910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const char* kFalse[] = { "0", "f", "false", "n", "no" };
2920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) {
2930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (strcasecmp(value, kTrue[i]) == 0) {
2940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        SET_VALUE_AS(bool, true);
2950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        return true;
2960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      } else if (strcasecmp(value, kFalse[i]) == 0) {
2970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        SET_VALUE_AS(bool, false);
2980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        return true;
2990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
3000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
3010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;   // didn't match a legal input
3020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
3030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else if (type_ == FV_STRING) {
3040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    SET_VALUE_AS(string, value);
3050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return true;
3060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
3070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
3080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // OK, it's likely to be numeric, and we'll be using a strtoXXX method.
3090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (value[0] == '\0')   // empty-string is only allowed for string type.
3100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
3110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  char* end;
3120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Leading 0x puts us in base 16.  But leading 0 does not put us in base 8!
3130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // It caused too many bugs when we had that behavior.
3140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  int base = 10;    // by default
3150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
3160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    base = 16;
3170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  errno = 0;
3180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
3190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
3200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32: {
3210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const int64 r = strtoint64(value, &end, base);
3220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (errno || end != value + strlen(value))  return false;  // bad parse
3230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (static_cast<int32>(r) != r)  // worked, but number out of range
3240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        return false;
3250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      SET_VALUE_AS(int32, static_cast<int32>(r));
3260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return true;
3270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
3280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64: {
3290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const int64 r = strtoint64(value, &end, base);
3300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (errno || end != value + strlen(value))  return false;  // bad parse
3310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      SET_VALUE_AS(int64, r);
3320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return true;
3330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
3340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64: {
3350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      while (*value == ' ') value++;
3360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (*value == '-') return false;  // negative number
3370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const uint64 r = strtouint64(value, &end, base);
3380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (errno || end != value + strlen(value))  return false;  // bad parse
3390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      SET_VALUE_AS(uint64, r);
3400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return true;
3410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
3420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE: {
3430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const double r = strtod(value, &end);
3440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (errno || end != value + strlen(value))  return false;  // bad parse
3450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      SET_VALUE_AS(double, r);
3460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return true;
3470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
3480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default: {
3490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      assert(false);  // unknown type
3500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return false;
3510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
3520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
3530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
3540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
3550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring FlagValue::ToString() const {
3560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  char intbuf[64];    // enough to hold even the biggest number
3570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
3580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_BOOL:
3590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return VALUE_AS(bool) ? "true" : "false";
3600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32:
3610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      snprintf(intbuf, sizeof(intbuf), "%"PRId32, VALUE_AS(int32));
3620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return intbuf;
3630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64:
3640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      snprintf(intbuf, sizeof(intbuf), "%"PRId64, VALUE_AS(int64));
3650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return intbuf;
3660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64:
3670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      snprintf(intbuf, sizeof(intbuf), "%"PRIu64, VALUE_AS(uint64));
3680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return intbuf;
3690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE:
3700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
3710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return intbuf;
3720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_STRING:
3730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return VALUE_AS(string);
3740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default:
3750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      assert(false);
3760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return "";  // unknown type
3770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
3780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
3790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
3800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool FlagValue::Validate(const char* flagname,
3810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                         ValidateFnProto validate_fn_proto) const {
3820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
3830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_BOOL:
3840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return reinterpret_cast<bool (*)(const char*, bool)>(
3850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          validate_fn_proto)(flagname, VALUE_AS(bool));
3860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32:
3870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return reinterpret_cast<bool (*)(const char*, int32)>(
3880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          validate_fn_proto)(flagname, VALUE_AS(int32));
3890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64:
3900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return reinterpret_cast<bool (*)(const char*, int64)>(
3910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          validate_fn_proto)(flagname, VALUE_AS(int64));
3920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64:
3930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return reinterpret_cast<bool (*)(const char*, uint64)>(
3940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          validate_fn_proto)(flagname, VALUE_AS(uint64));
3950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE:
3960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return reinterpret_cast<bool (*)(const char*, double)>(
3970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          validate_fn_proto)(flagname, VALUE_AS(double));
3980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_STRING:
3990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return reinterpret_cast<bool (*)(const char*, const string&)>(
4000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          validate_fn_proto)(flagname, VALUE_AS(string));
4010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default:
4020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      assert(false);  // unknown type
4030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return false;
4040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
4050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
4060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* FlagValue::TypeName() const {
4080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
4090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_BOOL:   return "bool";
4100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32:  return "int32";
4110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64:  return "int64";
4120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64: return "uint64";
4130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE: return "double";
4140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_STRING: return "string";
4150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default: assert(false); return "";  // unknown type
4160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
4170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
4180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool FlagValue::Equal(const FlagValue& x) const {
4200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (type_ != x.type_)
4210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
4220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
4230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_BOOL:   return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool);
4240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32:  return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32);
4250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64:  return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64);
4260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64);
4270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double);
4280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string);
4290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default: assert(false); return false;  // unknown type
4300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
4310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
4320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagValue* FlagValue::New() const {
4340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
4350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_BOOL:   return new FlagValue(new bool(false), "bool");
4360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32:  return new FlagValue(new int32(0), "int32");
4370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64:  return new FlagValue(new int64(0), "int64");
4380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64: return new FlagValue(new uint64(0), "uint64");
4390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE: return new FlagValue(new double(0.0), "double");
4400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_STRING: return new FlagValue(new string, "string");
4410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default: assert(false); return NULL;  // unknown type
4420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
4430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
4440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid FlagValue::CopyFrom(const FlagValue& x) {
4460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  assert(type_ == x.type_);
4470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (type_) {
4480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_BOOL:   SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool));      break;
4490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT32:  SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32));    break;
4500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_INT64:  SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64));    break;
4510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64));  break;
4520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double));  break;
4530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string));  break;
4540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default: assert(false);  // unknown type
4550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
4560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
4570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
4590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandLineFlag
4600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    This represents a single flag, including its name, description,
4610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    default value, and current value.  Mostly this serves as a
4620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    struct, though it also knows how to register itself.
4630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//       All CommandLineFlags are owned by a (exactly one)
4640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    FlagRegistry.  If you wish to modify fields in this class, you
4650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    should acquire the FlagRegistry lock for the registry that owns
4660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    this flag.
4670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
4680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass CommandLineFlag {
4700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public:
4710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Note: we take over memory-ownership of current_val and default_val.
4720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag(const char* name, const char* help, const char* filename,
4730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  FlagValue* current_val, FlagValue* default_val);
4740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ~CommandLineFlag();
4750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* name() const { return name_; }
4770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* help() const { return help_; }
4780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* filename() const { return file_; }
4790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* CleanFileName() const;  // nixes irrelevant prefix such as homedir
4800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string current_value() const { return current_->ToString(); }
4810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string default_value() const { return defvalue_->ToString(); }
4820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* type_name() const { return defvalue_->TypeName(); }
4830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ValidateFnProto validate_function() const { return validate_fn_proto_; }
4840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result);
4860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // If validate_fn_proto_ is non-NULL, calls it on value, returns result.
4880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool Validate(const FlagValue& value) const;
4890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool ValidateCurrent() const { return Validate(*current_); }
4900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private:
4920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // for SetFlagLocked() and setting flags_by_ptr_
4930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend class FlagRegistry;
4940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend class GOOGLE_NAMESPACE::FlagSaverImpl;  // for cloning the values
4950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend bool GetCommandLineOption(const char*, string*, bool*);
4960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // set validate_fn
4970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend bool AddFlagValidator(const void*, ValidateFnProto);
4980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
4990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // This copies all the non-const members: modified, processed, defvalue, etc.
5000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void CopyFrom(const CommandLineFlag& src);
5010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void UpdateModifiedBit();
5030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* const name_;     // Flag name
5050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* const help_;     // Help message
5060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* const file_;     // Which file did this come from?
5070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool modified_;              // Set after default assignment?
5080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue* defvalue_;        // Default value for flag
5090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue* current_;         // Current value for flag
5100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // This is a casted, 'generic' version of validate_fn, which actually
5110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // takes a flag-value as an arg (void (*validate_fn)(bool), say).
5120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // When we pass this to current_->Validate(), it will cast it back to
5130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // the proper type.  This may be NULL to mean we have no validate_fn.
5140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ValidateFnProto validate_fn_proto_;
5150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag(const CommandLineFlag&);   // no copying!
5170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void operator=(const CommandLineFlag&);
5180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
5190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathCommandLineFlag::CommandLineFlag(const char* name, const char* help,
5210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                 const char* filename,
5220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                 FlagValue* current_val, FlagValue* default_val)
5230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    : name_(name), help_(help), file_(filename), modified_(false),
5240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      defvalue_(default_val), current_(current_val), validate_fn_proto_(NULL) {
5250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
5260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathCommandLineFlag::~CommandLineFlag() {
5280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  delete current_;
5290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  delete defvalue_;
5300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
5310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* CommandLineFlag::CleanFileName() const {
5330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Compute top-level directory & file that this appears in
5340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // search full path backwards.
5350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Stop going backwards at kRootDir; and skip by the first slash.
5360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  static const char kRootDir[] = "";    // can set this to root directory,
5370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                        // e.g. "myproject"
5380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (sizeof(kRootDir)-1 == 0)          // no prefix to strip
5400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return filename();
5410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* clean_name = filename() + strlen(filename()) - 1;
5430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  while ( clean_name > filename() ) {
5440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (*clean_name == PATH_SEPARATOR) {
5450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) {
5460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // ".../myproject/base/logging.cc" ==> "base/logging.cc"
5470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        clean_name += sizeof(kRootDir)-1;    // past "/myproject/"
5480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        break;
5490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
5500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
5510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    --clean_name;
5520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
5530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  while ( *clean_name == PATH_SEPARATOR ) ++clean_name;  // Skip any slashes
5540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return clean_name;
5550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
5560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid CommandLineFlag::FillCommandLineFlagInfo(
5580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    CommandLineFlagInfo* result) {
5590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->name = name();
5600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->type = type_name();
5610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->description = help();
5620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->current_value = current_value();
5630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->default_value = default_value();
5640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->filename = CleanFileName();
5650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  UpdateModifiedBit();
5660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->is_default = !modified_;
5670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  result->has_validator_fn = validate_function() != NULL;
5680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
5690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid CommandLineFlag::UpdateModifiedBit() {
5710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Update the "modified" bit in case somebody bypassed the
5720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Flags API and wrote directly through the FLAGS_name variable.
5730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!modified_ && !current_->Equal(*defvalue_)) {
5740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    modified_ = true;
5750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
5760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
5770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid CommandLineFlag::CopyFrom(const CommandLineFlag& src) {
5790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Note we only copy the non-const members; others are fixed at construct time
5800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (modified_ != src.modified_) modified_ = src.modified_;
5810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!current_->Equal(*src.current_)) current_->CopyFrom(*src.current_);
5820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!defvalue_->Equal(*src.defvalue_)) defvalue_->CopyFrom(*src.defvalue_);
5830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (validate_fn_proto_ != src.validate_fn_proto_)
5840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    validate_fn_proto_ = src.validate_fn_proto_;
5850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
5860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool CommandLineFlag::Validate(const FlagValue& value) const {
5880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (validate_function() == NULL)
5890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return true;
5900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  else
5910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return value.Validate(name(), validate_function());
5920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
5930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
5950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
5960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagRegistry
5970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    A FlagRegistry singleton object holds all flag objects indexed
5980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    by their names so that if you know a flag's name (as a C
5990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    string), you can access or set it.  If the function is named
6000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    FooLocked(), you must own the registry lock before calling
6010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    the function; otherwise, you should *not* hold the lock, and
6020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    the function will acquire it itself if needed.
6030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
6040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstruct StringCmp {  // Used by the FlagRegistry map class to compare char*'s
6060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool operator() (const char* s1, const char* s2) const {
6070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return (strcmp(s1, s2) < 0);
6080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
6090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
6100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass FlagRegistry {
6120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public:
6130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry() { }
6140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void Lock() { lock_.Lock(); }
6160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void Unlock() { lock_.Unlock(); }
6170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Store a flag in this registry.  Takes ownership of the given pointer.
6190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void RegisterFlag(CommandLineFlag* flag);
6200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Returns the flag object for the specified name, or NULL if not found.
6220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* FindFlagLocked(const char* name);
6230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Returns the flag object whose current-value is stored at flag_ptr.
6250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // That is, for whom current_->value_buffer_ == flag_ptr
6260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr);
6270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // A fancier form of FindFlag that works correctly if name is of the
6290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // form flag=value.  In that case, we set key to point to flag, and
6300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // modify v to point to the value (if present), and return the flag
6310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // with the given name.  If the flag does not exist, returns NULL
6320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // and sets error_message.
6330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* SplitArgumentLocked(const char* argument,
6340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                       string* key, const char** v,
6350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                       string* error_message);
6360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Set the value of a flag.  If the flag was successfully set to
6380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // value, set msg to indicate the new flag-value, and return true.
6390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Otherwise, set msg to indicate the error, leave flag unchanged,
6400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // and return false.  msg can be NULL.
6410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool SetFlagLocked(CommandLineFlag* flag, const char* value,
6420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                     FlagSettingMode set_mode, string* msg);
6430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  static FlagRegistry* GlobalRegistry();   // returns a singleton registry
6450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private:
6470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend class GOOGLE_NAMESPACE::FlagSaverImpl;  // reads all the flags in order to copy them
6480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend class CommandLineFlagParser;    // for ValidateAllFlags
6490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  friend void GOOGLE_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
6500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // The map from name to flag, for FindFlagLocked().
6520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap;
6530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  typedef FlagMap::iterator FlagIterator;
6540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  typedef FlagMap::const_iterator FlagConstIterator;
6550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagMap flags_;
6560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // The map from current-value pointer to flag, fo FindFlagViaPtrLocked().
6580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  typedef map<const void*, CommandLineFlag*> FlagPtrMap;
6590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagPtrMap flags_by_ptr_;
6600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  Mutex lock_;
6620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  static FlagRegistry* global_registry_;   // a singleton registry
6640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  static Mutex global_registry_lock_;  // guards creation of global_registry_
6650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Disallow
6670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry(const FlagRegistry&);
6680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry& operator=(const FlagRegistry&);
6690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
6700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagRegistry* FlagRegistry::global_registry_ = NULL;
6720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathMutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
6730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagRegistry* FlagRegistry::GlobalRegistry() {
6750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  MutexLock acquire_lock(&global_registry_lock_);
6760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!global_registry_) {
6770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    global_registry_ = new FlagRegistry;
6780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
6790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return global_registry_;
6800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
6810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
6820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
6830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  Lock();
6840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  pair<FlagIterator, bool> ins =
6850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    flags_.insert(pair<const char*, CommandLineFlag*>(flag->name(), flag));
6860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (ins.second == false) {   // means the name was already in the map
6870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (strcmp(ins.first->second->filename(), flag->filename()) != 0) {
6880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      ReportError(DIE, "ERROR: flag '%s' was defined more than once "
6890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  "(in files '%s' and '%s').\n",
6900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  flag->name(),
6910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  ins.first->second->filename(),
6920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  flag->filename());
6930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    } else {
6940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      ReportError(DIE, "ERROR: something wrong with flag '%s' in file '%s'.  "
6950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  "One possibility: file '%s' is being linked both statically "
6960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  "and dynamically into this executable.\n",
6970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  flag->name(),
6980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  flag->filename(), flag->filename());
6990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
7000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
7010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Also add to the flags_by_ptr_ map.
7020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  flags_by_ptr_[flag->current_->value_buffer_] = flag;
7030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  Unlock();
7040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
7050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathCommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) {
7070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagConstIterator i = flags_.find(name);
7080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (i == flags_.end()) {
7090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return NULL;
7100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else {
7110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return i->second;
7120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
7130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
7140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathCommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) {
7160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagPtrMap::const_iterator i = flags_by_ptr_.find(flag_ptr);
7170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (i == flags_by_ptr_.end()) {
7180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return NULL;
7190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else {
7200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return i->second;
7210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
7220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
7230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathCommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg,
7250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                   string* key,
7260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                   const char** v,
7270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                   string* error_message) {
7280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Find the flag object for this option
7290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* flag_name;
7300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* value = strchr(arg, '=');
7310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (value == NULL) {
7320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    key->assign(arg);
7330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    *v = NULL;
7340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else {
7350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // Strip out the "=value" portion from arg
7360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    key->assign(arg, value-arg);
7370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    *v = ++value;    // advance past the '='
7380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
7390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  flag_name = key->c_str();
7400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* flag = FindFlagLocked(flag_name);
7420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (flag == NULL) {
7440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // If we can't find the flag-name, then we should return an error.
7450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // The one exception is if 1) the flag-name is 'nox', 2) there
7460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // exists a flag named 'x', and 3) 'x' is a boolean flag.
7470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // In that case, we want to return flag 'x'.
7480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) {
7490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // flag-name is not 'nox', so we're not in the exception case.
7500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      *error_message = (string(kError) +
7510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                        "unknown command line flag '" + *key + "'\n");
7520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return NULL;
7530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
7540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    flag = FindFlagLocked(flag_name+2);
7550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (flag == NULL) {
7560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // No flag named 'x' exists, so we're not in the exception case.
7570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      *error_message = (string(kError) +
7580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                        "unknown command line flag '" + *key + "'\n");
7590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return NULL;
7600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
7610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (strcmp(flag->type_name(), "bool") != 0) {
7620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // 'x' exists but is not boolean, so we're not in the exception case.
7630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      *error_message = (string(kError) +
7640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                        "boolean value (" + *key + ") specified for " +
7650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                        flag->type_name() + " command line flag\n");
7660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return NULL;
7670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
7680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // We're in the exception case!
7690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // Make up a fake value to replace the "no" we stripped out
7700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    key->assign(flag_name+2);   // the name without the "no"
7710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    *v = "0";
7720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
7730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Assign a value if this is a boolean flag
7750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) {
7760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    *v = "1";    // the --nox case was already handled, so this is the --x case
7770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
7780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return flag;
7800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
7810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
7820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value,
7830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                    const char* value, string* msg) {
7840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Use tenative_value, not flag_value, until we know value is valid.
7850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue* tentative_value = flag_value->New();
7860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!tentative_value->ParseFrom(value)) {
7870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (msg) {
7880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      *msg += (string(kError) + "illegal value '" + value +
7890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath               + "' specified for " + flag->type_name() + " flag '"
7900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath               + flag->name() + "'\n");
7910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
7920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    delete tentative_value;
7930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
7940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else if (!flag->Validate(*tentative_value)) {
7950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (msg) {
7960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      *msg += (string(kError) + "failed validation of new value "
7970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath               + "'" + tentative_value->ToString() + "' for flag '" +
7980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath               + flag->name() + "'\n");
7990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
8000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    delete tentative_value;
8010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
8020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else {
8030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    flag_value->CopyFrom(*tentative_value);
8040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (msg) {
8050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      *msg += (string(flag->name()) + " set to " + flag_value->ToString()
8060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath               + "\n");
8070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
8080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    delete tentative_value;
8090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return true;
8100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
8110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
8120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
8140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                 const char* value,
8150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                 FlagSettingMode set_mode,
8160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                 string* msg) {
8170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  flag->UpdateModifiedBit();
8180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  switch (set_mode) {
8190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case SET_FLAGS_VALUE: {
8200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // set or modify the flag's value
8210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (!TryParseLocked(flag, flag->current_, value, msg))
8220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        return false;
8230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      flag->modified_ = true;
8240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      break;
8250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
8260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case SET_FLAG_IF_DEFAULT: {
8270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // set the flag's value, but only if it hasn't been set by someone else
8280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (!flag->modified_) {
8290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        if (!TryParseLocked(flag, flag->current_, value, msg))
8300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          return false;
8310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        flag->modified_ = true;
8320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      } else {
8330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        *msg = string(flag->name()) + " set to " + flag->current_value();
8340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
8350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      break;
8360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
8370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    case SET_FLAGS_DEFAULT: {
8380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // modify the flag's default-value
8390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (!TryParseLocked(flag, flag->defvalue_, value, msg))
8400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        return false;
8410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (!flag->modified_) {
8420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // Need to set both defvalue *and* current, in this case
8430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        TryParseLocked(flag, flag->current_, value, NULL);
8440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
8450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      break;
8460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
8470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    default: {
8480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // unknown set_mode
8490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      assert(false);
8500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      return false;
8510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
8520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
8530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return true;
8550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
8560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass FlagRegistryLock {
8580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public:
8590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
8600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ~FlagRegistryLock() { fr_->Unlock(); }
8610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private:
8620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry *const fr_;
8630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
8640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
8660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandLineFlagParser
8670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    Parsing is done in two stages.  In the first, we go through
8680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    argv.  For every flag-like arg we can make sense of, we parse
8690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    it and set the appropriate FLAGS_* variable.  For every flag-
8700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    like arg we can't make sense of, we store it in a vector,
8710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    along with an explanation of the trouble.  In stage 2, we
8720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    handle the 'reporting' flags like --help and --mpm_version.
8730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    (This is via a call to HandleCommandLineHelpFlags(), in
8740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    gflags_reporting.cc.)
8750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    An optional stage 3 prints out the error messages.
8760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//       This is a bit of a simplification.  For instance, --flagfile
8770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    is handled as soon as it's seen in stage 1, not in stage 2.
8780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
8790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass CommandLineFlagParser {
8810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public:
8820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // The argument is the flag-registry to register the parsed flags in
8830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {}
8840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ~CommandLineFlagParser() {}
8850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Stage 1: Every time this is called, it reads all flags in argv.
8870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // However, it ignores all flags that have been successfully set
8880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // before.  Typically this is only called once, so this 'reparsing'
8890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // behavior isn't important.  It can be useful when trying to
8900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // reparse after loading a dll, though.
8910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags);
8920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Stage 2: print reporting info and exit, if requested.
8940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // In gflags_reporting.cc:HandleCommandLineHelpFlags().
8950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
8960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Stage 3: validate all the commandline flags that have validators
8970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // registered.
8980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void ValidateAllFlags();
8990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Stage 4: report any errors and return true if any were found.
9010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool ReportErrors();
9020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Set a particular command line option.  "newval" is a string
9040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // describing the new value that the option has been set to.  If
9050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // option_name does not specify a valid option name, or value is not
9060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // a valid value for option_name, newval is empty.  Does recursive
9070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // processing for --flagfile and --fromenv.  Returns the new value
9080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // if everything went ok, or empty-string if not.  (Actually, the
9090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // return-string could hold many flag/value pairs due to --flagfile.)
9100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // NB: Must have called registry_->Lock() before calling this function.
9110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string ProcessSingleOptionLocked(CommandLineFlag* flag,
9120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                   const char* value,
9130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                   FlagSettingMode set_mode);
9140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Set a whole batch of command line options as specified by contentdata,
9160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // which is in flagfile format (and probably has been read from a flagfile).
9170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Returns the new value if everything went ok, or empty-string if
9180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // not.  (Actually, the return-string could hold many flag/value
9190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // pairs due to --flagfile.)
9200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // NB: Must have called registry_->Lock() before calling this function.
9210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string ProcessOptionsFromStringLocked(const string& contentdata,
9220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                        FlagSettingMode set_mode);
9230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // These are the 'recursive' flags, defined at the top of this file.
9250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Whenever we see these flags on the commandline, we must take action.
9260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // These are called by ProcessSingleOptionLocked and, similarly, return
9270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // new values if everything went ok, or the empty-string if not.
9280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode);
9290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // diff fromenv/tryfromenv
9300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode,
9310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                              bool errors_are_fatal);
9320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private:
9340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry_;
9350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  map<string, string> error_flags_;      // map from name to error message
9360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // This could be a set<string>, but we reuse the map to minimize the .o size
9370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  map<string, string> undefined_names_;  // --[flag] name was not registered
9380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
9390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Parse a list of (comma-separated) flags.
9420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void ParseFlagList(const char* value, vector<string>* flags) {
9430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (const char *p = value; p && *p; value = p) {
9440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    p = strchr(value, ',');
9450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    int len;
9460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (p) {
9470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      len = static_cast<int>(p - value);
9480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      p++;
9490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    } else {
9500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      len = static_cast<int>(strlen(value));
9510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
9520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (len == 0)
9540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      ReportError(DIE, "ERROR: empty flaglist entry\n");
9550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (value[0] == '-')
9560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      ReportError(DIE, "ERROR: flag \"%*s\" begins with '-'\n", len, value);
9570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    flags->push_back(string(value, len));
9590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
9600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
9610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Snarf an entire file into a C++ string.  This is just so that we
9630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// can do all the I/O in one place and not worry about it everywhere.
9640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Plus, it's convenient to have the whole file contents at hand.
9650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Adds a newline at the end of the file.
9660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#define PFATAL(s)  do { perror(s); commandlineflags_exitfunc(1); } while (0)
9670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic string ReadFileIntoString(const char* filename) {
9690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const int kBufSize = 8092;
9700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  char buffer[kBufSize];
9710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string s;
9720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FILE* fp = fopen(filename, "r");
9730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!fp)  PFATAL(filename);
9740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  size_t n;
9750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) {
9760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (ferror(fp))  PFATAL(filename);
9770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    s.append(buffer, n);
9780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
9790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  fclose(fp);
9800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return s;
9810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
9820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathuint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
9840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                       bool remove_flags) {
9850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char *program_name = strrchr((*argv)[0], PATH_SEPARATOR);   // nix path
9860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  program_name = (program_name == NULL ? (*argv)[0] : program_name+1);
9870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  int first_nonopt = *argc;        // for non-options moved to the end
9890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry_->Lock();
9910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (int i = 1; i < first_nonopt; i++) {
9920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    char* arg = (*argv)[i];
9930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
9940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // Like getopt(), we permute non-option flags to be at the end.
9950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (arg[0] != '-' ||           // must be a program argument
9960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        (arg[0] == '-' && arg[1] == '\0')) {  // "-" is an argument, not a flag
9970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i]));
9980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      (*argv)[*argc-1] = arg;      // we go last
9990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      first_nonopt--;              // we've been pushed onto the stack
10000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      i--;                         // to undo the i++ in the loop
10010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      continue;
10020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
10030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (arg[0] == '-') arg++;      // allow leading '-'
10050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (arg[0] == '-') arg++;      // or leading '--'
10060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // -- alone means what it does for GNU: stop options parsing
10080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (*arg == '\0') {
10090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      first_nonopt = i+1;
10100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      break;
10110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
10120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // Find the flag object for this option
10140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    string key;
10150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const char* value;
10160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    string error_message;
10170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value,
10180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                           &error_message);
10190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (flag == NULL) {
10200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      undefined_names_[key] = "";    // value isn't actually used
10210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      error_flags_[key] = error_message;
10220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      continue;
10230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
10240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (value == NULL) {
10260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // Boolean options are always assigned a value by SplitArgumentLocked()
10270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      assert(strcmp(flag->type_name(), "bool") != 0);
10280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (i+1 >= first_nonopt) {
10290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // This flag needs a value, but there is nothing available
10300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'"
10310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                             + " is missing its argument");
10320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        if (flag->help() && flag->help()[0] > '\001') {
10330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          // Be useful in case we have a non-stripped description.
10340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          error_flags_[key] += string("; flag description: ") + flag->help();
10350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        }
10360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        error_flags_[key] += "\n";
10370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        break;    // we treat this as an unrecoverable error
10380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      } else {
10390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        value = (*argv)[++i];                   // read next arg for value
10400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // Heuristic to detect the case where someone treats a string arg
10420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // like a bool:
10430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // --my_string_var --foo=bar
10440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // We look for a flag of string type, whose value begins with a
10450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // dash, and where the flag-name and value are separated by a
10460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // space rather than an '='.
10470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // To avoid false positives, we also require the word "true"
10480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // or "false" in the help string.  Without this, a valid usage
10490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // "-lat -30.5" would trigger the warning.  The common cases we
10500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // want to solve talk about true and false as values.
10510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        if (value[0] == '-'
10520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath            && strcmp(flag->type_name(), "string") == 0
10530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath            && (strstr(flag->help(), "true")
10540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                || strstr(flag->help(), "false"))) {
10550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          fprintf(stderr, "Did you really mean to set flag '%s'"
10560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  " to the value '%s'?\n",
10570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  flag->name(), value);
10580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        }
10590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
10600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
10610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // TODO(csilvers): only set a flag if we hadn't set it before here
10630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE);
10640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
10650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry_->Unlock();
10660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (remove_flags) {   // Fix up argc and argv by removing command line flags
10680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    (*argv)[first_nonopt-1] = (*argv)[0];
10690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    (*argv) += (first_nonopt-1);
10700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    (*argc) -= (first_nonopt-1);
10710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    first_nonopt = 1;   // because we still don't count argv[0]
10720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
10730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  logging_is_probably_set_up = true;   // because we've parsed --logdir, etc.
10750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return first_nonopt;
10770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
10780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval,
10800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                    FlagSettingMode set_mode) {
10810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (flagval.empty())
10820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return "";
10830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string msg;
10850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vector<string> filename_list;
10860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ParseFlagList(flagval.c_str(), &filename_list);  // take a list of filenames
10870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (size_t i = 0; i < filename_list.size(); ++i) {
10880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const char* file = filename_list[i].c_str();
10890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode);
10900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
10910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return msg;
10920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
10930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
10940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
10950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                   FlagSettingMode set_mode,
10960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                   bool errors_are_fatal) {
10970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (flagval.empty())
10980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return "";
10990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string msg;
11010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vector<string> flaglist;
11020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ParseFlagList(flagval.c_str(), &flaglist);
11030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (size_t i = 0; i < flaglist.size(); ++i) {
11050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const char* flagname = flaglist[i].c_str();
11060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    CommandLineFlag* flag = registry_->FindFlagLocked(flagname);
11070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (flag == NULL) {
11080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      error_flags_[flagname] = (string(kError) + "unknown command line flag"
11090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                + " '" + flagname + "'"
11100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                + " (via --fromenv or --tryfromenv)\n");
11110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      undefined_names_[flagname] = "";
11120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      continue;
11130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
11140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const string envname = string("FLAGS_") + string(flagname);
11160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const char* envval = getenv(envname.c_str());
11170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (!envval) {
11180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (errors_are_fatal) {
11190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        error_flags_[flagname] = (string(kError) + envname +
11200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                  " not found in environment\n");
11210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
11220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      continue;
11230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
11240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // Avoid infinite recursion.
11260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if ((strcmp(envval, "fromenv") == 0) ||
11270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        (strcmp(envval, "tryfromenv") == 0)) {
11280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      error_flags_[flagname] = (string(kError) + "infinite recursion on " +
11290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                "environment flag '" + envval + "'\n");
11300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      continue;
11310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
11320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    msg += ProcessSingleOptionLocked(flag, envval, set_mode);
11340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
11350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return msg;
11360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
11370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring CommandLineFlagParser::ProcessSingleOptionLocked(
11390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) {
11400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string msg;
11410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) {
11420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    error_flags_[flag->name()] = msg;
11430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return "";
11440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
11450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // The recursive flags, --flagfile and --fromenv and --tryfromenv,
11470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // must be dealt with as soon as they're seen.  They will emit
11480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // messages of their own.
11490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (strcmp(flag->name(), "flagfile") == 0) {
11500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode);
11510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else if (strcmp(flag->name(), "fromenv") == 0) {
11530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // last arg indicates envval-not-found is fatal (unlike in --tryfromenv)
11540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true);
11550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else if (strcmp(flag->name(), "tryfromenv") == 0) {
11570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false);
11580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
11590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return msg;
11610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
11620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid CommandLineFlagParser::ValidateAllFlags() {
11640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistryLock frl(registry_);
11650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin();
11660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath       i != registry_->flags_.end(); ++i) {
11670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (!i->second->ValidateCurrent()) {
11680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // only set a message if one isn't already there.  (If there's
11690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // an error message, our job is done, even if it's not exactly
11700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // the same error.)
11710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (error_flags_[i->second->name()].empty())
11720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        error_flags_[i->second->name()] =
11730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath            string(kError) + "--" + i->second->name() +
11740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath            " must be set on the commandline"
11750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath            " (default value fails validation)\n";
11760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
11770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
11780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
11790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
11800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool CommandLineFlagParser::ReportErrors() {
11810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // error_flags_ indicates errors we saw while parsing.
11820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // But we ignore undefined-names if ok'ed by --undef_ok
11830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!FLAGS_undefok.empty()) {
11840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    vector<string> flaglist;
11850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    ParseFlagList(FLAGS_undefok.c_str(), &flaglist);
11860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    for (size_t i = 0; i < flaglist.size(); ++i) {
11870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // We also deal with --no<flag>, in case the flagname was boolean
11880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const string no_version = string("no") + flaglist[i];
11890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) {
11900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        error_flags_[flaglist[i]] = "";    // clear the error message
11910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      } else if (undefined_names_.find(no_version) != undefined_names_.end()) {
11920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        error_flags_[no_version] = "";
11930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
11940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
11950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
11960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Likewise, if they decided to allow reparsing, all undefined-names
11970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // are ok; we just silently ignore them now, and hope that a future
11980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // parse will pick them up somehow.
11990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (allow_command_line_reparsing) {
12000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    for (map<string, string>::const_iterator it = undefined_names_.begin();
12010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath         it != undefined_names_.end();  ++it)
12020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      error_flags_[it->first] = "";      // clear the error message
12030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
12040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool found_error = false;
12060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string error_message;
12070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (map<string, string>::const_iterator it = error_flags_.begin();
12080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath       it != error_flags_.end(); ++it) {
12090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (!it->second.empty()) {
12100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      error_message.append(it->second.data(), it->second.size());
12110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      found_error = true;
12120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
12130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
12140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (found_error)
12150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    ReportError(DO_NOT_DIE, "%s", error_message.c_str());
12160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return found_error;
12170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
12180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring CommandLineFlagParser::ProcessOptionsFromStringLocked(
12200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const string& contentdata, FlagSettingMode set_mode) {
12210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string retval;
12220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* flagfile_contents = contentdata.c_str();
12230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool flags_are_relevant = true;   // set to false when filenames don't match
12240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool in_filename_section = false;
12250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* line_end = flagfile_contents;
12270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // We read this file a line at a time.
12280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (; line_end; flagfile_contents = line_end + 1) {
12290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    while (*flagfile_contents && isspace(*flagfile_contents))
12300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      ++flagfile_contents;
12310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    line_end = strchr(flagfile_contents, '\n');
12320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    size_t len = line_end ? static_cast<size_t>(line_end - flagfile_contents)
12330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                          : strlen(flagfile_contents);
12340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    string line(flagfile_contents, len);
12350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // Each line can be one of four things:
12370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // 1) A comment line -- we skip it
12380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // 2) An empty line -- we skip it
12390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // 3) A list of filenames -- starts a new filenames+flags section
12400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // 4) A --flag=value line -- apply if previous filenames match
12410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (line.empty() || line[0] == '#') {
12420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // comment or empty line; just ignore
12430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    } else if (line[0] == '-') {    // flag
12450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      in_filename_section = false;  // instead, it was a flag-line
12460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (!flags_are_relevant)      // skip this flag; applies to someone else
12470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        continue;
12480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const char* name_and_val = line.c_str() + 1;    // skip the leading -
12500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (*name_and_val == '-')
12510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        name_and_val++;                               // skip second - too
12520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      string key;
12530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const char* value;
12540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      string error_message;
12550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val,
12560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                             &key, &value,
12570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                                             &error_message);
12580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // By API, errors parsing flagfile lines are silently ignored.
12590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (flag == NULL) {
12600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // "WARNING: flagname '" + key + "' not found\n"
12610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      } else if (value == NULL) {
12620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // "WARNING: flagname '" + key + "' missing a value\n"
12630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      } else {
12640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        retval += ProcessSingleOptionLocked(flag, value, set_mode);
12650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
12660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    } else {                        // a filename!
12680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (!in_filename_section) {   // start over: assume filenames don't match
12690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        in_filename_section = true;
12700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        flags_are_relevant = false;
12710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
12720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
12730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // Split the line up at spaces into glob-patterns
12740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const char* space = line.c_str();   // just has to be non-NULL
12750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      for (const char* word = line.c_str(); *space; word = space+1) {
12760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        if (flags_are_relevant)     // we can stop as soon as we match
12770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          break;
12780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        space = strchr(word, ' ');
12790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        if (space == NULL)
12800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          space = word + strlen(word);
12810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        const string glob(word, space - word);
12820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        // We try matching both against the full argv0 and basename(argv0)
12830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef HAVE_FNMATCH_H
12840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        if (fnmatch(glob.c_str(),
12850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                    ProgramInvocationName(),
12860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                    FNM_PATHNAME) == 0 ||
12870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath            fnmatch(glob.c_str(),
12880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                    ProgramInvocationShortName(),
12890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                    FNM_PATHNAME) == 0) {
12900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#else  // !HAVE_FNMATCH_H
12910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        if ((glob == ProgramInvocationName()) ||
12920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath            (glob == ProgramInvocationShortName())) {
12930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif  // HAVE_FNMATCH_H
12940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          flags_are_relevant = true;
12950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        }
12960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
12970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
12980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
12990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return retval;
13000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
13010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
13030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetFromEnv()
13040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// AddFlagValidator()
13050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    These are helper functions for routines like BoolFromEnv() and
13060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    RegisterFlagValidator, defined below.  They're defined here so
13070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    they can live in the unnamed namespace (which makes friendship
13080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    declarations for these classes possible).
13090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
13100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathtemplate<typename T>
13120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathT GetFromEnv(const char *varname, const char* type, T dflt) {
13130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* const valstr = getenv(varname);
13140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!valstr)
13150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return dflt;
13160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue ifv(new T, type);
13170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!ifv.ParseFrom(valstr))
13180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
13190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                varname, valstr);
13200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return OTHER_VALUE_AS(ifv, T);
13210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
13220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
13240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // We want a lock around this routine, in case two threads try to
13250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // add a validator (hopefully the same one!) at once.  We could use
13260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // our own thread, but we need to loook at the registry anyway, so
13270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // we just steal that one.
13280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
13290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistryLock frl(registry);
13300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // First, find the flag whose current-flag storage is 'flag'.
13310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // This is the CommandLineFlag whose current_->value_buffer_ == flag
13320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr);
13330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!flag) {
13340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // WARNING << "Ignoring RegisterValidateFunction() for flag pointer "
13350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    //         << flag_ptr << ": no flag found at that address";
13360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
13370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else if (validate_fn_proto == flag->validate_function()) {
13380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return true;    // ok to register the same function over and over again
13390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else if (validate_fn_proto != NULL && flag->validate_function() != NULL) {
13400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // WARNING << "Ignoring RegisterValidateFunction() for flag '"
13410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    //         << flag->name() << "': validate-fn already registered";
13420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
13430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else {
13440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    flag->validate_fn_proto_ = validate_fn_proto;
13450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return true;
13460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
13470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
13480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}  // end unnamed namespaces
13500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Now define the functions that are exported via the .h file
13530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
13550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagRegisterer
13560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    This class exists merely to have a global constructor (the
13570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    kind that runs before main(), that goes an initializes each
13580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    flag that's been declared.  Note that it's very important we
13590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    don't have a destructor that deletes flag_, because that would
13600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    cause us to delete current_storage/defvalue_storage as well,
13610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    which can cause a crash if anything tries to access the flag
13620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    values in a global destructor.
13630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
13640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagRegisterer::FlagRegisterer(const char* name, const char* type,
13660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                               const char* help, const char* filename,
13670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                               void* current_storage, void* defvalue_storage) {
13680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (help == NULL)
13690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    help = "";
13700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // FlagValue expects the type-name to not include any namespace
13710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // components, so we get rid of those, if any.
13720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (strchr(type, ':'))
13730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    type = strrchr(type, ':') + 1;
13740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue* current = new FlagValue(current_storage, type);
13750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagValue* defvalue = new FlagValue(defvalue_storage, type);
13760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Importantly, flag_ will never be deleted, so storage is always good.
13770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* flag = new CommandLineFlag(name, help, filename,
13780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                              current, defvalue);
13790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);   // default registry
13800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
13810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
13830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetAllFlags()
13840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    The main way the FlagRegistry class exposes its data.  This
13850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    returns, as strings, all the info about all the flags in
13860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    the main registry, sorted first by filename they are defined
13870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    in, and then by flagname.
13880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
13890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
13900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstruct FilenameFlagnameCmp {
13910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  bool operator()(const CommandLineFlagInfo& a,
13920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                  const CommandLineFlagInfo& b) const {
13930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    int cmp = strcmp(a.filename.c_str(), b.filename.c_str());
13940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (cmp == 0)
13950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      cmp = strcmp(a.name.c_str(), b.name.c_str());  // secondary sort key
13960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return cmp < 0;
13970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
13980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
13990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid GetAllFlags(vector<CommandLineFlagInfo>* OUTPUT) {
14010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
14020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry->Lock();
14030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
14040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath       i != registry->flags_.end(); ++i) {
14050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    CommandLineFlagInfo fi;
14060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    i->second->FillCommandLineFlagInfo(&fi);
14070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    OUTPUT->push_back(fi);
14080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
14090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry->Unlock();
14100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Now sort the flags, first by filename they occur in, then alphabetically
14110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp());
14120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
14130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
14150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// SetArgv()
14160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetArgvs()
14170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetArgv()
14180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetArgv0()
14190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ProgramInvocationName()
14200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ProgramInvocationShortName()
14210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// SetUsageMessage()
14220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ProgramUsage()
14230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    Functions to set and get argv.  Typically the setter is called
14240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    by ParseCommandLineFlags.  Also can get the ProgramUsage string,
14250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    set by SetUsageMessage.
14260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
14270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// These values are not protected by a Mutex because they are normally
14290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// set only once during program startup.
14300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const char* argv0 = "UNKNOWN";      // just the program name
14310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const char* cmdline = "";           // the entire command-line
14320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic vector<string> argvs;
14330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic uint32 argv_sum = 0;
14340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const char* program_usage = NULL;
14350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid SetArgv(int argc, const char** argv) {
14370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  static bool called_set_argv = false;
14380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (called_set_argv)         // we already have an argv for you
14390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return;
14400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  called_set_argv = true;
14420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  assert(argc > 0);            // every program has at least a progname
14440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  argv0 = strdup(argv[0]);     // small memory leak, but fn only called once
14450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  assert(argv0);
14460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string cmdline_string;       // easier than doing strcats
14480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (int i = 0; i < argc; i++) {
14490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (i != 0) {
14500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      cmdline_string += " ";
14510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
14520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    cmdline_string += argv[i];
14530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    argvs.push_back(argv[i]);
14540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
14550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  cmdline = strdup(cmdline_string.c_str());  // another small memory leak
14560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  assert(cmdline);
14570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Compute a simple sum of all the chars in argv
14590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (const char* c = cmdline; *c; c++)
14600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    argv_sum += *c;
14610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
14620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst vector<string>& GetArgvs() { return argvs; }
14640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* GetArgv()            { return cmdline; }
14650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* GetArgv0()           { return argv0; }
14660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathuint32 GetArgvSum()              { return argv_sum; }
14670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* ProgramInvocationName() {             // like the GNU libc fn
14680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return GetArgv0();
14690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
14700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* ProgramInvocationShortName() {        // like the GNU libc fn
14710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* slash = strrchr(argv0, '/');
14720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef OS_WINDOWS
14730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!slash)  slash = strrchr(argv0, '\\');
14740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif
14750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return slash ? slash + 1 : argv0;
14760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
14770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid SetUsageMessage(const string& usage) {
14790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (program_usage != NULL)
14800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    ReportError(DIE, "ERROR: SetUsageMessage() called twice\n");
14810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  program_usage = strdup(usage.c_str());      // small memory leak
14820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
14830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* ProgramUsage() {
14850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (program_usage) {
14860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return program_usage;
14870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
14880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return "Warning: SetUsageMessage() never called";
14890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
14900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
14910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
14920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetCommandLineOption()
14930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetCommandLineFlagInfo()
14940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// GetCommandLineFlagInfoOrDie()
14950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// SetCommandLineOption()
14960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// SetCommandLineOptionWithMode()
14970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    The programmatic way to set a flag's value, using a string
14980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    for its name rather than the variable itself (that is,
14990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    SetCommandLineOption("foo", x) rather than FLAGS_foo = x).
15000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    There's also a bit more flexibility here due to the various
15010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    set-modes, but typically these are used when you only have
15020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    that flag's name as a string, perhaps at runtime.
15030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    All of these work on the default, global registry.
15040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//       For GetCommandLineOption, return false if no such flag
15050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    is known, true otherwise.  We clear "value" if a suitable
15060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    flag is found.
15070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
15080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool GetCommandLineOption(const char* name, string* value) {
15110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (NULL == name)
15120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
15130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  assert(value);
15140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
15160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistryLock frl(registry);
15170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* flag = registry->FindFlagLocked(name);
15180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (flag == NULL) {
15190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
15200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else {
15210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    *value = flag->current_value();
15220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return true;
15230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
15240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
15250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) {
15270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (NULL == name) return false;
15280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
15290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistryLock frl(registry);
15300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* flag = registry->FindFlagLocked(name);
15310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (flag == NULL) {
15320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
15330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  } else {
15340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    assert(OUTPUT);
15350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    flag->FillCommandLineFlagInfo(OUTPUT);
15360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return true;
15370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
15380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
15390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathCommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
15410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlagInfo info;
15420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!GetCommandLineFlagInfo(name, &info)) {
15430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name);
15440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    commandlineflags_exitfunc(1);    // almost certainly exit()
15450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
15460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return info;
15470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
15480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring SetCommandLineOptionWithMode(const char* name, const char* value,
15500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                    FlagSettingMode set_mode) {
15510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string result;
15520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
15530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistryLock frl(registry);
15540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlag* flag = registry->FindFlagLocked(name);
15550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (flag) {
15560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    CommandLineFlagParser parser(registry);
15570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    result = parser.ProcessSingleOptionLocked(flag, value, set_mode);
15580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (!result.empty()) {   // in the error case, we've already logged
15590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // You could consider logging this change, if you wanted to know it:
15600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      //fprintf(stderr, "%sFLAGS_%s\n",
15610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      //        (set_mode == SET_FLAGS_DEFAULT ? "default value of " : ""),
15620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      //        result);
15630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
15640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
15650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // The API of this function is that we return empty string on error
15660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return result;
15670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
15680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring SetCommandLineOption(const char* name, const char* value) {
15700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE);
15710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
15720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
15740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagSaver
15750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// FlagSaverImpl
15760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    This class stores the states of all flags at construct time,
15770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    and restores all flags to that state at destruct time.
15780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    Its major implementation challenge is that it never modifies
15790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    pointers in the 'main' registry, so global FLAG_* vars always
15800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    point to the right place.
15810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
15820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass FlagSaverImpl {
15840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public:
15850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Constructs an empty FlagSaverImpl object.
15860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  explicit FlagSaverImpl(FlagRegistry* main_registry)
15870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      : main_registry_(main_registry) { }
15880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  ~FlagSaverImpl() {
15890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // reclaim memory from each of our CommandLineFlags
15900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    vector<CommandLineFlag*>::const_iterator it;
15910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it)
15920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      delete *it;
15930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
15940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
15950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Saves the flag states from the flag registry into this object.
15960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // It's an error to call this more than once.
15970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Must be called when the registry mutex is not held.
15980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void SaveFromRegistry() {
15990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    FlagRegistryLock frl(main_registry_);
16000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    assert(backup_registry_.empty());   // call only once!
16010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin();
16020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath         it != main_registry_->flags_.end();
16030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath         ++it) {
16040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      const CommandLineFlag* main = it->second;
16050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // Sets up all the const variables in backup correctly
16060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      CommandLineFlag* backup = new CommandLineFlag(
16070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          main->name(), main->help(), main->filename(),
16080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath          main->current_->New(), main->defvalue_->New());
16090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      // Sets up all the non-const variables in backup correctly
16100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      backup->CopyFrom(*main);
16110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      backup_registry_.push_back(backup);   // add it to a convenient list
16120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
16130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
16140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Restores the saved flag states into the flag registry.  We
16160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // assume no flags were added or deleted from the registry since
16170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // the SaveFromRegistry; if they were, that's trouble!  Must be
16180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // called when the registry mutex is not held.
16190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void RestoreToRegistry() {
16200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    FlagRegistryLock frl(main_registry_);
16210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    vector<CommandLineFlag*>::const_iterator it;
16220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) {
16230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name());
16240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      if (main != NULL) {       // if NULL, flag got deleted from registry(!)
16250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath        main->CopyFrom(**it);
16260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      }
16270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
16280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
16290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private:
16310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const main_registry_;
16320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vector<CommandLineFlag*> backup_registry_;
16330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagSaverImpl(const FlagSaverImpl&);  // no copying!
16350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  void operator=(const FlagSaverImpl&);
16360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath};
16370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagSaver::FlagSaver()
16390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    : impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) {
16400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  impl_->SaveFromRegistry();
16410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
16420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathFlagSaver::~FlagSaver() {
16440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  impl_->RestoreToRegistry();
16450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  delete impl_;
16460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
16470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
16500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// CommandlineFlagsIntoString()
16510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ReadFlagsFromString()
16520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// AppendFlagsIntoFile()
16530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ReadFromFlagsFile()
16540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    These are mostly-deprecated routines that stick the
16550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    commandline flags into a file/string and read them back
16560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    out again.  I can see a use for CommandlineFlagsIntoString,
16570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    for creating a flagfile, but the rest don't seem that useful
16580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    -- some, I think, are a poor-man's attempt at FlagSaver --
16590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    and are included only until we can delete them from callers.
16600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    Note they don't save --flagfile flags (though they do save
16610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    the result of having called the flagfile, of course).
16620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
16630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic string TheseCommandlineFlagsIntoString(
16650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    const vector<CommandLineFlagInfo>& flags) {
16660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vector<CommandLineFlagInfo>::const_iterator i;
16670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  size_t retval_space = 0;
16690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (i = flags.begin(); i != flags.end(); ++i) {
16700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // An (over)estimate of how much space it will take to print this flag
16710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    retval_space += i->name.length() + i->current_value.length() + 5;
16720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
16730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  string retval;
16750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  retval.reserve(retval_space);
16760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (i = flags.begin(); i != flags.end(); ++i) {
16770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    retval += "--";
16780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    retval += i->name;
16790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    retval += "=";
16800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    retval += i->current_value;
16810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    retval += "\n";
16820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
16830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return retval;
16840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
16850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring CommandlineFlagsIntoString() {
16870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vector<CommandLineFlagInfo> sorted_flags;
16880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  GetAllFlags(&sorted_flags);
16890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return TheseCommandlineFlagsIntoString(sorted_flags);
16900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
16910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool ReadFlagsFromString(const string& flagfilecontents,
16930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                         const char* /*prog_name*/,  // TODO(csilvers): nix this
16940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                         bool errors_are_fatal) {
16950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
16960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagSaverImpl saved_states(registry);
16970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  saved_states.SaveFromRegistry();
16980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
16990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlagParser parser(registry);
17000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry->Lock();
17010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE);
17020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry->Unlock();
17030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Should we handle --help and such when reading flags from a string?  Sure.
17040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  HandleCommandLineHelpFlags();
17050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (parser.ReportErrors()) {
17060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    // Error.  Restore all global flags to their previous values.
17070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (errors_are_fatal)
17080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      commandlineflags_exitfunc(1);    // almost certainly exit()
17090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    saved_states.RestoreToRegistry();
17100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
17110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
17120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return true;
17130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName()
17160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool AppendFlagsIntoFile(const string& filename, const char *prog_name) {
17170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FILE *fp = fopen(filename.c_str(), "a");
17180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (!fp) {
17190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    return false;
17200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
17210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (prog_name)
17230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    fprintf(fp, "%s\n", prog_name);
17240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vector<CommandLineFlagInfo> flags;
17260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  GetAllFlags(&flags);
17270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // But we don't want --flagfile, which leads to weird recursion issues
17280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  vector<CommandLineFlagInfo>::iterator i;
17290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (i = flags.begin(); i != flags.end(); ++i) {
17300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    if (strcmp(i->name.c_str(), "flagfile") == 0) {
17310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      flags.erase(i);
17320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath      break;
17330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    }
17340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  }
17350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str());
17360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  fclose(fp);
17380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return true;
17390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool ReadFromFlagsFile(const string& filename, const char* prog_name,
17420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                       bool errors_are_fatal) {
17430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return ReadFlagsFromString(ReadFileIntoString(filename.c_str()),
17440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                             prog_name, errors_are_fatal);
17450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
17490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// BoolFromEnv()
17500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Int32FromEnv()
17510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Int64FromEnv()
17520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Uint64FromEnv()
17530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// DoubleFromEnv()
17540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// StringFromEnv()
17550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    Reads the value from the environment and returns it.
17560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    We use an FlagValue to make the parsing easy.
17570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    Example usage:
17580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//       DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever");
17590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
17600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool BoolFromEnv(const char *v, bool dflt) {
17620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return GetFromEnv(v, "bool", dflt);
17630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathint32 Int32FromEnv(const char *v, int32 dflt) {
17650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return GetFromEnv(v, "int32", dflt);
17660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathint64 Int64FromEnv(const char *v, int64 dflt)    {
17680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return GetFromEnv(v, "int64", dflt);
17690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathuint64 Uint64FromEnv(const char *v, uint64 dflt) {
17710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return GetFromEnv(v, "uint64", dflt);
17720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathdouble DoubleFromEnv(const char *v, double dflt) {
17740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return GetFromEnv(v, "double", dflt);
17750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char *StringFromEnv(const char *varname, const char *dflt) {
17770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const char* const val = getenv(varname);
17780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return val ? val : dflt;
17790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
17830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// RegisterFlagValidator()
17840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    RegisterFlagValidator() is the function that clients use to
17850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    'decorate' a flag with a validation function.  Once this is
17860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    done, every time the flag is set (including when the flag
17870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    is parsed from argv), the validator-function is called.
17880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//       These functions return true if the validator was added
17890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    successfully, or false if not: the flag already has a validator,
17900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    (only one allowed per flag), the 1st arg isn't a flag, etc.
17910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//       This function is not thread-safe.
17920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
17930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
17940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool RegisterFlagValidator(const bool* flag,
17950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                           bool (*validate_fn)(const char*, bool)) {
17960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
17970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
17980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool RegisterFlagValidator(const int32* flag,
17990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                           bool (*validate_fn)(const char*, int32)) {
18000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
18010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool RegisterFlagValidator(const int64* flag,
18030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                           bool (*validate_fn)(const char*, int64)) {
18040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
18050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool RegisterFlagValidator(const uint64* flag,
18070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                           bool (*validate_fn)(const char*, uint64)) {
18080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
18090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool RegisterFlagValidator(const double* flag,
18110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                           bool (*validate_fn)(const char*, double)) {
18120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
18130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool RegisterFlagValidator(const string* flag,
18150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                           bool (*validate_fn)(const char*, const string&)) {
18160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
18170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
18210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ParseCommandLineFlags()
18220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ParseCommandLineNonHelpFlags()
18230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// HandleCommandLineHelpFlags()
18240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    This is the main function called from main(), to actually
18250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    parse the commandline.  It modifies argc and argv as described
18260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    at the top of gflags.h.  You can also divide this
18270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    function into two parts, if you want to do work between
18280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    the parsing of the flags and the printing of any help output.
18290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
18300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv,
18320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                            bool remove_flags, bool do_report) {
18330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  SetArgv(*argc, const_cast<const char**>(*argv));    // save it for later
18340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
18360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  CommandLineFlagParser parser(registry);
18370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // When we parse the commandline flags, we'll handle --flagfile,
18390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // --tryfromenv, etc. as we see them (since flag-evaluation order
18400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // may be important).  But sometimes apps set FLAGS_tryfromenv/etc.
18410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // manually before calling ParseCommandLineFlags.  We want to evaluate
18420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // those too, as if they were the first flags on the commandline.
18430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry->Lock();
18440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE);
18450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Last arg here indicates whether flag-not-found is a fatal error or not
18460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true);
18470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false);
18480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  registry->Unlock();
18490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // Now get the flags specified on the commandline
18510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags);
18520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (do_report)
18540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    HandleCommandLineHelpFlags();   // may cause us to exit on --help, etc.
18550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // See if any of the unset flags fail their validation checks
18570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  parser.ValidateAllFlags();
18580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  if (parser.ReportErrors())        // may cause us to exit on illegal flags
18600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    commandlineflags_exitfunc(1);   // almost certainly exit()
18610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return r;
18620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathuint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) {
18650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true);
18660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathuint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv,
18690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath                                    bool remove_flags) {
18700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false);
18710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
18740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// AllowCommandLineReparsing()
18750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ReparseCommandLineNonHelpFlags()
18760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    This is most useful for shared libraries.  The idea is if
18770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    a flag is defined in a shared library that is dlopen'ed
18780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    sometime after main(), you can ParseCommandLineFlags before
18790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    the dlopen, then ReparseCommandLineNonHelpFlags() after the
18800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    dlopen, to get the new flags.  But you have to explicitly
18810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    Allow() it; otherwise, you get the normal default behavior
18820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath//    of unrecognized flags calling a fatal error.
18830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// TODO(csilvers): this isn't used.  Just delete it?
18840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --------------------------------------------------------------------
18850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid AllowCommandLineReparsing() {
18870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  allow_command_line_reparsing = true;
18880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
18890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathuint32 ReparseCommandLineNonHelpFlags() {
18910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  // We make a copy of argc and argv to pass in
18920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const vector<string>& argvs = GetArgvs();
18930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  int tmp_argc = static_cast<int>(argvs.size());
18940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  char** tmp_argv = new char* [tmp_argc + 1];
18950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (int i = 0; i < tmp_argc; ++i)
18960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    tmp_argv[i] = strdup(argvs[i].c_str());   // TODO(csilvers): don't dup
18970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
18980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  const int retval = ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false);
18990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
19000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  for (int i = 0; i < tmp_argc; ++i)
19010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath    free(tmp_argv[i]);
19020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  delete[] tmp_argv;
19030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
19040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath  return retval;
19050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}
19060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath
19070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath_END_GOOGLE_NAMESPACE_
1908