1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 // Copyright (c) 2005, Google Inc.
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // ---
32 // This file is a compatibility layer that defines Google's version of
33 // command line flags that are used for configuration.
34 //
35 // We put flags into their own namespace.  It is purposefully
36 // named in an opaque way that people should have trouble typing
37 // directly.  The idea is that DEFINE puts the flag in the weird
38 // namespace, and DECLARE imports the flag from there into the
39 // current namespace.  The net result is to force people to use
40 // DECLARE to get access to a flag, rather than saying
41 //   extern bool FLAGS_logtostderr;
42 // or some such instead.  We want this so we can put extra
43 // functionality (like sanity-checking) in DECLARE if we want,
44 // and make sure it is picked up everywhere.
45 //
46 // We also put the type of the variable in the namespace, so that
47 // people can't DECLARE_int32 something that they DEFINE_bool'd
48 // elsewhere.
49 #ifndef BASE_COMMANDLINEFLAGS_H_
50 #define BASE_COMMANDLINEFLAGS_H_
51 
52 #include <config.h>
53 #include <string>
54 #include <string.h>               // for memchr
55 #include <stdlib.h>               // for getenv
56 #include "base/basictypes.h"
57 
58 #define DECLARE_VARIABLE(type, name)                                          \
59   namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead {  \
60   extern PERFTOOLS_DLL_DECL type FLAGS_##name;                                \
61   }                                                                           \
62   using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name
63 
64 #define DEFINE_VARIABLE(type, name, value, meaning) \
65   namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead {  \
66   PERFTOOLS_DLL_DECL type FLAGS_##name(value);                                \
67   char FLAGS_no##name;                                                        \
68   }                                                                           \
69   using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name
70 
71 // bool specialization
72 #define DECLARE_bool(name) \
73   DECLARE_VARIABLE(bool, name)
74 #define DEFINE_bool(name, value, meaning) \
75   DEFINE_VARIABLE(bool, name, value, meaning)
76 
77 // int32 specialization
78 #define DECLARE_int32(name) \
79   DECLARE_VARIABLE(int32, name)
80 #define DEFINE_int32(name, value, meaning) \
81   DEFINE_VARIABLE(int32, name, value, meaning)
82 
83 // int64 specialization
84 #define DECLARE_int64(name) \
85   DECLARE_VARIABLE(int64, name)
86 #define DEFINE_int64(name, value, meaning) \
87   DEFINE_VARIABLE(int64, name, value, meaning)
88 
89 #define DECLARE_uint64(name) \
90   DECLARE_VARIABLE(uint64, name)
91 #define DEFINE_uint64(name, value, meaning) \
92   DEFINE_VARIABLE(uint64, name, value, meaning)
93 
94 // double specialization
95 #define DECLARE_double(name) \
96   DECLARE_VARIABLE(double, name)
97 #define DEFINE_double(name, value, meaning) \
98   DEFINE_VARIABLE(double, name, value, meaning)
99 
100 // Special case for string, because we have to specify the namespace
101 // std::string, which doesn't play nicely with our FLAG__namespace hackery.
102 #define DECLARE_string(name)                                          \
103   namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead {  \
104   extern std::string FLAGS_##name;                                                   \
105   }                                                                           \
106   using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
107 #define DEFINE_string(name, value, meaning) \
108   namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead {  \
109   std::string FLAGS_##name(value);                                                   \
110   char FLAGS_no##name;                                                        \
111   }                                                                           \
112   using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
113 
114 // implemented in sysinfo.cc
115 namespace tcmalloc {
116   namespace commandlineflags {
117 
StringToBool(const char * value,bool def)118     inline bool StringToBool(const char *value, bool def) {
119       if (!value) {
120         return def;
121       }
122       switch (value[0]) {
123       case 't':
124       case 'T':
125       case 'y':
126       case 'Y':
127       case '1':
128       case '\0':
129         return true;
130       }
131       return false;
132     }
133 
StringToInt(const char * value,int def)134     inline int StringToInt(const char *value, int def) {
135       if (!value) {
136         return def;
137       }
138       return strtol(value, NULL, 10);
139     }
140 
StringToLongLong(const char * value,long long def)141     inline long long StringToLongLong(const char *value, long long def) {
142       if (!value) {
143         return def;
144       }
145       return strtoll(value, NULL, 10);
146     }
147 
StringToDouble(const char * value,double def)148     inline double StringToDouble(const char *value, double def) {
149       if (!value) {
150         return def;
151       }
152       return strtod(value, NULL);
153     }
154   }
155 }
156 
157 // These macros (could be functions, but I don't want to bother with a .cc
158 // file), make it easier to initialize flags from the environment.
159 
160 #define EnvToString(envname, dflt)   \
161   (!getenv(envname) ? (dflt) : getenv(envname))
162 
163 #define EnvToBool(envname, dflt)   \
164   tcmalloc::commandlineflags::StringToBool(getenv(envname), dflt)
165 
166 #define EnvToInt(envname, dflt)  \
167   tcmalloc::commandlineflags::StringToInt(getenv(envname), dflt)
168 
169 #define EnvToInt64(envname, dflt)  \
170   tcmalloc::commandlineflags::StringToLongLong(getenv(envname), dflt)
171 
172 #define EnvToDouble(envname, dflt)  \
173   tcmalloc::commandlineflags::StringToDouble(getenv(envname), dflt)
174 
175 #endif  // BASE_COMMANDLINEFLAGS_H_
176