]>
Commit | Line | Data |
---|---|---|
696d846a MO |
1 | //===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===// |
2 | // | |
3 | // This file is distributed under the University of Illinois Open Source | |
4 | // License. See LICENSE.TXT for details. | |
5 | // | |
6 | //===----------------------------------------------------------------------===// | |
7 | // | |
8 | // This file is a part of ThreadSanitizer/AddressSanitizer runtime. | |
9 | // | |
10 | //===----------------------------------------------------------------------===// | |
11 | ||
12 | #ifndef SANITIZER_FLAG_REGISTRY_H | |
13 | #define SANITIZER_FLAG_REGISTRY_H | |
14 | ||
15 | #include "sanitizer_internal_defs.h" | |
16 | #include "sanitizer_libc.h" | |
17 | #include "sanitizer_common.h" | |
18 | ||
19 | namespace __sanitizer { | |
20 | ||
21 | class FlagHandlerBase { | |
22 | public: | |
23 | virtual bool Parse(const char *value) { return false; } | |
24 | }; | |
25 | ||
26 | template <typename T> | |
27 | class FlagHandler : public FlagHandlerBase { | |
28 | T *t_; | |
29 | ||
30 | public: | |
31 | explicit FlagHandler(T *t) : t_(t) {} | |
32 | bool Parse(const char *value) final; | |
33 | }; | |
34 | ||
5d3805fc | 35 | inline bool ParseBool(const char *value, bool *b) { |
696d846a MO |
36 | if (internal_strcmp(value, "0") == 0 || |
37 | internal_strcmp(value, "no") == 0 || | |
38 | internal_strcmp(value, "false") == 0) { | |
5d3805fc | 39 | *b = false; |
696d846a MO |
40 | return true; |
41 | } | |
42 | if (internal_strcmp(value, "1") == 0 || | |
43 | internal_strcmp(value, "yes") == 0 || | |
44 | internal_strcmp(value, "true") == 0) { | |
5d3805fc | 45 | *b = true; |
696d846a MO |
46 | return true; |
47 | } | |
5d3805fc JJ |
48 | return false; |
49 | } | |
50 | ||
51 | template <> | |
52 | inline bool FlagHandler<bool>::Parse(const char *value) { | |
53 | if (ParseBool(value, t_)) return true; | |
696d846a MO |
54 | Printf("ERROR: Invalid value for bool option: '%s'\n", value); |
55 | return false; | |
56 | } | |
57 | ||
5d3805fc JJ |
58 | template <> |
59 | inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) { | |
60 | bool b; | |
61 | if (ParseBool(value, &b)) { | |
62 | *t_ = b ? kHandleSignalYes : kHandleSignalNo; | |
63 | return true; | |
64 | } | |
65 | if (internal_strcmp(value, "2") == 0 || | |
66 | internal_strcmp(value, "exclusive") == 0) { | |
67 | *t_ = kHandleSignalExclusive; | |
68 | return true; | |
69 | } | |
70 | Printf("ERROR: Invalid value for signal handler option: '%s'\n", value); | |
71 | return false; | |
72 | } | |
73 | ||
696d846a MO |
74 | template <> |
75 | inline bool FlagHandler<const char *>::Parse(const char *value) { | |
5d3805fc | 76 | *t_ = value; |
696d846a MO |
77 | return true; |
78 | } | |
79 | ||
80 | template <> | |
81 | inline bool FlagHandler<int>::Parse(const char *value) { | |
eac97531 | 82 | const char *value_end; |
696d846a MO |
83 | *t_ = internal_simple_strtoll(value, &value_end, 10); |
84 | bool ok = *value_end == 0; | |
85 | if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value); | |
86 | return ok; | |
87 | } | |
88 | ||
89 | template <> | |
90 | inline bool FlagHandler<uptr>::Parse(const char *value) { | |
eac97531 | 91 | const char *value_end; |
696d846a MO |
92 | *t_ = internal_simple_strtoll(value, &value_end, 10); |
93 | bool ok = *value_end == 0; | |
94 | if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value); | |
95 | return ok; | |
96 | } | |
97 | ||
98 | class FlagParser { | |
99 | static const int kMaxFlags = 200; | |
100 | struct Flag { | |
101 | const char *name; | |
102 | const char *desc; | |
103 | FlagHandlerBase *handler; | |
104 | } *flags_; | |
105 | int n_flags_; | |
106 | ||
107 | const char *buf_; | |
108 | uptr pos_; | |
109 | ||
110 | public: | |
111 | FlagParser(); | |
112 | void RegisterHandler(const char *name, FlagHandlerBase *handler, | |
113 | const char *desc); | |
114 | void ParseString(const char *s); | |
115 | bool ParseFile(const char *path, bool ignore_missing); | |
116 | void PrintFlagDescriptions(); | |
117 | ||
118 | static LowLevelAllocator Alloc; | |
119 | ||
120 | private: | |
121 | void fatal_error(const char *err); | |
122 | bool is_space(char c); | |
123 | void skip_whitespace(); | |
124 | void parse_flags(); | |
125 | void parse_flag(); | |
126 | bool run_handler(const char *name, const char *value); | |
127 | char *ll_strndup(const char *s, uptr n); | |
128 | }; | |
129 | ||
130 | template <typename T> | |
131 | static void RegisterFlag(FlagParser *parser, const char *name, const char *desc, | |
132 | T *var) { | |
133 | FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var); // NOLINT | |
134 | parser->RegisterHandler(name, fh, desc); | |
135 | } | |
136 | ||
137 | void ReportUnrecognizedFlags(); | |
138 | ||
139 | } // namespace __sanitizer | |
140 | ||
141 | #endif // SANITIZER_FLAG_REGISTRY_H |