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