1 | // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_BIN_OPTIONS_H_ |
6 | #define RUNTIME_BIN_OPTIONS_H_ |
7 | |
8 | #include "bin/dartutils.h" |
9 | #include "platform/globals.h" |
10 | #include "platform/hashmap.h" |
11 | #include "platform/syslog.h" |
12 | |
13 | namespace dart { |
14 | namespace bin { |
15 | |
16 | typedef bool (*OptionProcessorCallback)(const char* arg, |
17 | CommandLineOptions* vm_options); |
18 | |
19 | class OptionProcessor { |
20 | public: |
21 | OptionProcessor() : next_(first_) { first_ = this; } |
22 | |
23 | virtual ~OptionProcessor() {} |
24 | |
25 | static bool IsValidFlag(const char* name, |
26 | const char* prefix, |
27 | intptr_t prefix_length); |
28 | |
29 | virtual bool Process(const char* option, CommandLineOptions* options) = 0; |
30 | |
31 | static bool TryProcess(const char* option, CommandLineOptions* options); |
32 | |
33 | static const char* ProcessOption(const char* option, const char* name); |
34 | |
35 | static bool ProcessEnvironmentOption(const char* arg, |
36 | CommandLineOptions* vm_options, |
37 | dart::SimpleHashMap** environment); |
38 | |
39 | private: |
40 | static OptionProcessor* first_; |
41 | OptionProcessor* next_; |
42 | |
43 | DISALLOW_ALLOCATION(); |
44 | DISALLOW_COPY_AND_ASSIGN(OptionProcessor); |
45 | }; |
46 | |
47 | class CallbackOptionProcessor : public OptionProcessor { |
48 | public: |
49 | explicit CallbackOptionProcessor(OptionProcessorCallback cb) : cb_(cb) {} |
50 | virtual bool Process(const char* option, CommandLineOptions* vm_options) { |
51 | return cb_(option, vm_options); |
52 | } |
53 | |
54 | private: |
55 | OptionProcessorCallback cb_; |
56 | }; |
57 | |
58 | #define DEFINE_CB_OPTION(callback) \ |
59 | static CallbackOptionProcessor option_##callback(&callback); |
60 | |
61 | #define DEFINE_STRING_OPTION_CB(name, callback) \ |
62 | class OptionProcessor_##name : public OptionProcessor { \ |
63 | public: \ |
64 | virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ |
65 | const char* value = \ |
66 | OptionProcessor::ProcessOption(option, "--" #name "="); \ |
67 | if (value == NULL) { \ |
68 | return false; \ |
69 | } \ |
70 | if (*value == '\0') { \ |
71 | Syslog::PrintErr("Empty value for option " #name "\n"); \ |
72 | return false; \ |
73 | } \ |
74 | callback; \ |
75 | return true; \ |
76 | } \ |
77 | }; \ |
78 | static OptionProcessor_##name option_##name; |
79 | |
80 | #define DEFINE_STRING_OPTION(name, variable) \ |
81 | DEFINE_STRING_OPTION_CB(name, { variable = value; }) |
82 | |
83 | #define DEFINE_ENUM_OPTION(name, enum_name, variable) \ |
84 | DEFINE_STRING_OPTION_CB(name, { \ |
85 | const char** kNames = k##enum_name##Names; \ |
86 | for (intptr_t i = 0; kNames[i] != NULL; i++) { \ |
87 | if (strcmp(value, kNames[i]) == 0) { \ |
88 | variable = static_cast<enum_name>(i); \ |
89 | return true; \ |
90 | } \ |
91 | } \ |
92 | Syslog::PrintErr( \ |
93 | "Unrecognized value for " #name ": '%s'\nValid values are: ", value); \ |
94 | for (intptr_t i = 0; kNames[i] != NULL; i++) { \ |
95 | Syslog::PrintErr("%s%s", i > 0 ? ", " : "", kNames[i]); \ |
96 | } \ |
97 | Syslog::PrintErr("\n"); \ |
98 | }) |
99 | |
100 | #define DEFINE_BOOL_OPTION_CB(name, callback) \ |
101 | class OptionProcessor_##name : public OptionProcessor { \ |
102 | public: \ |
103 | virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ |
104 | const char* value = OptionProcessor::ProcessOption(option, "--" #name); \ |
105 | if (value == NULL) { \ |
106 | return false; \ |
107 | } \ |
108 | if (*value == '=') { \ |
109 | Syslog::PrintErr("Non-empty value for option " #name "\n"); \ |
110 | return false; \ |
111 | } \ |
112 | if (*value != '\0') { \ |
113 | return false; \ |
114 | } \ |
115 | callback(vm_options); \ |
116 | return true; \ |
117 | } \ |
118 | }; \ |
119 | static OptionProcessor_##name option_##name; |
120 | |
121 | #define DEFINE_BOOL_OPTION(name, variable) \ |
122 | class OptionProcessor_##name : public OptionProcessor { \ |
123 | public: \ |
124 | virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ |
125 | const char* value = OptionProcessor::ProcessOption(option, "--" #name); \ |
126 | if (value == NULL) { \ |
127 | return false; \ |
128 | } \ |
129 | if (*value == '=') { \ |
130 | Syslog::PrintErr("Non-empty value for option " #name "\n"); \ |
131 | return false; \ |
132 | } \ |
133 | if (*value != '\0') { \ |
134 | return false; \ |
135 | } \ |
136 | variable = true; \ |
137 | return true; \ |
138 | } \ |
139 | }; \ |
140 | static OptionProcessor_##name option_##name; |
141 | |
142 | #define DEFINE_BOOL_OPTION_SHORT(short_name, long_name, variable) \ |
143 | class OptionProcessor_##long_name : public OptionProcessor { \ |
144 | public: \ |
145 | virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ |
146 | const char* value = \ |
147 | OptionProcessor::ProcessOption(option, "-" #short_name); \ |
148 | if (value == NULL) { \ |
149 | value = OptionProcessor::ProcessOption(option, "--" #long_name); \ |
150 | } \ |
151 | if (value == NULL) { \ |
152 | return false; \ |
153 | } \ |
154 | if (*value == '=') { \ |
155 | Syslog::PrintErr("Non-empty value for option " #long_name "\n"); \ |
156 | return false; \ |
157 | } \ |
158 | if (*value != '\0') { \ |
159 | return false; \ |
160 | } \ |
161 | variable = true; \ |
162 | return true; \ |
163 | } \ |
164 | }; \ |
165 | static OptionProcessor_##long_name option_##long_name; |
166 | |
167 | } // namespace bin |
168 | } // namespace dart |
169 | |
170 | #endif // RUNTIME_BIN_OPTIONS_H_ |
171 | |