Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Functions
flags.cc File Reference
#include "vm/flags.h"
#include "platform/assert.h"
#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/os.h"

Go to the source code of this file.

Classes

class  dart::Flag
 

Namespaces

namespace  dart
 

Macros

#define PRODUCT_FLAG_MACRO(name, type, default_value, comment)
 
#define DEBUG_FLAG_MACRO(name, type, default_value, comment)
 
#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment)
 
#define PRECOMPILE_FLAG_MACRO(name, pre_value, product_value, type, default_value, comment)
 

Functions

 dart::DEFINE_FLAG (bool, print_flags, false, "Print flags as they are being parsed.")
 
 dart::DEFINE_FLAG (bool, ignore_unrecognized_flags, false, "Ignore unrecognized flags.")
 
static void dart::Normalize (char *s)
 
static bool dart::IsValidFlag (const char *name, const char *prefix, intptr_t prefix_length)
 

Macro Definition Documentation

◆ DEBUG_FLAG_MACRO

#define DEBUG_FLAG_MACRO (   name,
  type,
  default_value,
  comment 
)

Definition at line 29 of file flags.cc.

◆ PRECOMPILE_FLAG_MACRO

#define PRECOMPILE_FLAG_MACRO (   name,
  pre_value,
  product_value,
  type,
  default_value,
  comment 
)
Value:
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);
const char * name
Definition fuchsia.cc:50

Definition at line 58 of file flags.cc.

82 {
83 public:
84 enum FlagType {
86 kInteger,
87 kUint64,
88 kString,
89 kFlagHandler,
90 kOptionHandler,
91 kNumFlagTypes
92 };
93
94 Flag(const char* name, const char* comment, void* addr, FlagType type)
95 : name_(name), comment_(comment), addr_(addr), type_(type) {}
96 Flag(const char* name, const char* comment, FlagHandler handler)
97 : name_(name),
98 comment_(comment),
99 flag_handler_(handler),
100 type_(kFlagHandler) {}
101 Flag(const char* name, const char* comment, OptionHandler handler)
102 : name_(name),
103 comment_(comment),
104 option_handler_(handler),
105 type_(kOptionHandler) {}
106
107 void Print() {
108 if (IsUnrecognized()) {
109 OS::PrintErr("%s: unrecognized\n", name_);
110 return;
111 }
112 switch (type_) {
113 case kBoolean: {
114 OS::Print("%s: %s (%s)\n", name_, *this->bool_ptr_ ? "true" : "false",
115 comment_);
116 break;
117 }
118 case kInteger: {
119 OS::Print("%s: %d (%s)\n", name_, *this->int_ptr_, comment_);
120 break;
121 }
122 case kUint64: {
123 OS::Print("%s: %" Pu64 " (%s)\n", name_, *this->uint64_ptr_, comment_);
124 break;
125 }
126 case kString: {
127 if (*this->charp_ptr_ != nullptr) {
128 OS::Print("%s: '%s' (%s)\n", name_, *this->charp_ptr_, comment_);
129 } else {
130 OS::Print("%s: (null) (%s)\n", name_, comment_);
131 }
132 break;
133 }
134 case kOptionHandler:
135 case kFlagHandler: {
136 OS::Print("%s: (%s)\n", name_, comment_);
137 break;
138 }
139 default:
140 UNREACHABLE();
141 break;
142 }
143 }
144
145 bool IsUnrecognized() const {
146 return (type_ == kBoolean) && (bool_ptr_ == nullptr);
147 }
148
149 const char* name_;
150 const char* comment_;
151
152 // For kString, kOptionHandler, kFlagHandler flags this stores the copy
153 // of the original flag value passed to SetFlagFromString
154 Utils::CStringUniquePtr string_value_ =
155 Utils::CreateCStringUniquePtr(nullptr);
156 union {
157 void* addr_;
158 bool* bool_ptr_;
159 int* int_ptr_;
160 uint64_t* uint64_ptr_;
161 charp* charp_ptr_;
162 FlagHandler flag_handler_;
163 OptionHandler option_handler_;
164 };
165 const FlagType type_;
166 bool changed_ = false;
167};
168
169Flag* Flags::Lookup(const char* name) {
170 for (intptr_t i = 0; i < num_flags_; i++) {
171 Flag* flag = flags_[i];
172 if (strcmp(flag->name_, name) == 0) {
173 return flag;
174 }
175 }
176 return nullptr;
177}
178
179bool Flags::IsSet(const char* name) {
180 Flag* flag = Lookup(name);
181 return (flag != nullptr) && (flag->type_ == Flag::kBoolean) &&
182 (flag->bool_ptr_ != nullptr) && (*flag->bool_ptr_ == true);
183}
184
185void Flags::Cleanup() {
186 ASSERT(initialized_);
187 initialized_ = false;
188}
189
190void Flags::AddFlag(Flag* flag) {
191 ASSERT(!initialized_);
192 if (num_flags_ == capacity_) {
193 if (flags_ == nullptr) {
194 capacity_ = 256;
195 flags_ = new Flag*[capacity_];
196 } else {
197 intptr_t new_capacity = capacity_ * 2;
198 Flag** new_flags = new Flag*[new_capacity];
199 for (intptr_t i = 0; i < num_flags_; i++) {
200 new_flags[i] = flags_[i];
201 }
202 delete[] flags_;
203 flags_ = new_flags;
204 capacity_ = new_capacity;
205 }
206 }
207 flags_[num_flags_++] = flag;
208}
209
210bool Flags::Register_bool(bool* addr,
211 const char* name,
212 bool default_value,
213 const char* comment) {
214 Flag* flag = Lookup(name);
215 if (flag != nullptr) {
216 ASSERT(flag->IsUnrecognized());
217 return default_value;
218 }
219 flag = new Flag(name, comment, addr, Flag::kBoolean);
220 AddFlag(flag);
221 return default_value;
222}
223
224int Flags::Register_int(int* addr,
225 const char* name,
226 int default_value,
227 const char* comment) {
228 ASSERT(Lookup(name) == nullptr);
229
230 Flag* flag = new Flag(name, comment, addr, Flag::kInteger);
231 AddFlag(flag);
232
233 return default_value;
234}
235
236uint64_t Flags::Register_uint64_t(uint64_t* addr,
237 const char* name,
238 uint64_t default_value,
239 const char* comment) {
240 ASSERT(Lookup(name) == nullptr);
241
242 Flag* flag = new Flag(name, comment, addr, Flag::kUint64);
243 AddFlag(flag);
244
245 return default_value;
246}
247
248const char* Flags::Register_charp(charp* addr,
249 const char* name,
250 const char* default_value,
251 const char* comment) {
252 ASSERT(Lookup(name) == nullptr);
253 Flag* flag = new Flag(name, comment, addr, Flag::kString);
254 AddFlag(flag);
255 return default_value;
256}
257
258bool Flags::RegisterFlagHandler(FlagHandler handler,
259 const char* name,
260 const char* comment) {
261 ASSERT(Lookup(name) == nullptr);
262 Flag* flag = new Flag(name, comment, handler);
263 AddFlag(flag);
264 return false;
265}
266
267bool Flags::RegisterOptionHandler(OptionHandler handler,
268 const char* name,
269 const char* comment) {
270 ASSERT(Lookup(name) == nullptr);
271 Flag* flag = new Flag(name, comment, handler);
272 AddFlag(flag);
273 return false;
274}
275
276static void Normalize(char* s) {
277 intptr_t len = strlen(s);
278 for (intptr_t i = 0; i < len; i++) {
279 if (s[i] == '-') {
280 s[i] = '_';
281 }
282 }
283}
284
285bool Flags::SetFlagFromString(Flag* flag, const char* argument) {
286 ASSERT(!flag->IsUnrecognized());
287 switch (flag->type_) {
288 case Flag::kBoolean: {
289 if (strcmp(argument, "true") == 0) {
290 *flag->bool_ptr_ = true;
291 } else if (strcmp(argument, "false") == 0) {
292 *flag->bool_ptr_ = false;
293 } else {
294 return false;
295 }
296 break;
297 }
298 case Flag::kString: {
299 flag->string_value_.reset(argument == nullptr ? nullptr
300 : Utils::StrDup(argument));
301 *flag->charp_ptr_ = flag->string_value_.get();
302 break;
303 }
304 case Flag::kInteger: {
305 char* endptr = nullptr;
306 const intptr_t len = strlen(argument);
307 int base = 10;
308 if ((len > 2) && (argument[0] == '0') && (argument[1] == 'x')) {
309 base = 16;
310 }
311 int val = strtol(argument, &endptr, base);
312 if (endptr == argument + len) {
313 *flag->int_ptr_ = val;
314 } else {
315 return false;
316 }
317 break;
318 }
319 case Flag::kUint64: {
320 char* endptr = nullptr;
321 const intptr_t len = strlen(argument);
322 int base = 10;
323 if ((len > 2) && (argument[0] == '0') && (argument[1] == 'x')) {
324 base = 16;
325 }
326 int64_t val = strtoll(argument, &endptr, base);
327 if (endptr == argument + len) {
328 *flag->uint64_ptr_ = static_cast<uint64_t>(val);
329 } else {
330 return false;
331 }
332 break;
333 }
334 case Flag::kFlagHandler: {
335 if (strcmp(argument, "true") == 0) {
336 (flag->flag_handler_)(true);
337 } else if (strcmp(argument, "false") == 0) {
338 (flag->flag_handler_)(false);
339 } else {
340 return false;
341 }
342 flag->string_value_.reset(Utils::StrDup(argument));
343 break;
344 }
345 case Flag::kOptionHandler: {
346 flag->string_value_.reset(Utils::StrDup(argument));
347 (flag->option_handler_)(argument);
348 break;
349 }
350 default: {
351 UNREACHABLE();
352 return false;
353 }
354 }
355 flag->changed_ = true;
356 return true;
357}
358
359void Flags::Parse(const char* option) {
360 // Find the beginning of the option argument, if it exists.
361 const char* equals = option;
362 while ((*equals != '\0') && (*equals != '=')) {
363 equals++;
364 }
365
366 const char* argument = nullptr;
367
368 // Determine if this is an option argument.
369 if (*equals != '=') {
370 // No explicit option argument. Determine if there is a "no_" prefix
371 // preceding the name.
372 const char* const kNo1Prefix = "no_";
373 const char* const kNo2Prefix = "no-";
374 const intptr_t kNo1PrefixLen = strlen(kNo1Prefix);
375 const intptr_t kNo2PrefixLen = strlen(kNo2Prefix);
376 if (strncmp(option, kNo1Prefix, kNo1PrefixLen) == 0) {
377 option += kNo1PrefixLen; // Skip the "no_" when looking up the name.
378 argument = "false";
379 } else if (strncmp(option, kNo2Prefix, kNo2PrefixLen) == 0) {
380 option += kNo2PrefixLen; // Skip the "no-" when looking up the name.
381 argument = "false";
382 } else {
383 argument = "true";
384 }
385 } else {
386 // The argument for the option starts right after the equals sign.
387 argument = equals + 1;
388 }
389
390 // Initialize the flag name.
391 intptr_t name_len = equals - option;
392 char* name = new char[name_len + 1];
393 strncpy(name, option, name_len);
394 name[name_len] = '\0';
396
397 Flag* flag = Flags::Lookup(name);
398 if (flag == nullptr) {
399 // Collect unrecognized flags.
400 char* new_flag = new char[name_len + 1];
401 strncpy(new_flag, option, name_len);
402 new_flag[name_len] = '\0';
403 Normalize(new_flag); // Or a later lookup may fail.
404 Flags::Register_bool(nullptr, new_flag, true, nullptr);
405 } else {
406 // Only set values for recognized flags, skip collected
407 // unrecognized flags.
408 if (!flag->IsUnrecognized()) {
409 if (!SetFlagFromString(flag, argument)) {
410 OS::PrintErr("Ignoring flag: %s is an invalid value for flag %s\n",
411 argument, name);
412 }
413 }
414 }
415
416 delete[] name;
417}
418
419static bool IsValidFlag(const char* name,
420 const char* prefix,
421 intptr_t prefix_length) {
422 intptr_t name_length = strlen(name);
423 return ((name_length > prefix_length) &&
424 (strncmp(name, prefix, prefix_length) == 0));
425}
426
427int Flags::CompareFlagNames(const void* left, const void* right) {
428 const Flag* left_flag = *reinterpret_cast<const Flag* const*>(left);
429 const Flag* right_flag = *reinterpret_cast<const Flag* const*>(right);
430 return strcmp(left_flag->name_, right_flag->name_);
431}
432
433char* Flags::ProcessCommandLineFlags(int number_of_vm_flags,
434 const char** vm_flags) {
435 if (initialized_) {
436 return Utils::StrDup("Flags already set");
437 }
438
439 qsort(flags_, num_flags_, sizeof flags_[0], CompareFlagNames);
440
441 const char* const kPrefix = "--";
442 const intptr_t kPrefixLen = strlen(kPrefix);
443
444 int i = 0;
445 while ((i < number_of_vm_flags) &&
446 IsValidFlag(vm_flags[i], kPrefix, kPrefixLen)) {
447 const char* option = vm_flags[i] + kPrefixLen;
448 Parse(option);
449 i++;
450 }
451
452 if (!FLAG_ignore_unrecognized_flags) {
453 int unrecognized_count = 0;
454 TextBuffer error(64);
455 for (intptr_t j = 0; j < num_flags_; j++) {
456 Flag* flag = flags_[j];
457 if (flag->IsUnrecognized()) {
458 if (unrecognized_count == 0) {
459 error.Printf("Unrecognized flags: %s", flag->name_);
460 } else {
461 error.Printf(", %s", flag->name_);
462 }
463 unrecognized_count++;
464 }
465 }
466 if (unrecognized_count > 0) {
467 return error.Steal();
468 }
469 }
470 if (FLAG_print_flags) {
471 PrintFlags();
472 }
473
474 initialized_ = true;
475 return nullptr;
476}
477
478bool Flags::SetFlag(const char* name, const char* value, const char** error) {
479 Flag* flag = Lookup(name);
480 if (flag == nullptr) {
481 *error = "Cannot set flag: flag not found";
482 return false;
483 }
484 if (!SetFlagFromString(flag, value)) {
485 *error = "Cannot set flag: invalid value";
486 return false;
487 }
488 return true;
489}
490
491void Flags::PrintFlags() {
492 OS::Print("Flag settings:\n");
493 for (intptr_t i = 0; i < num_flags_; ++i) {
494 flags_[i]->Print();
495 }
496}
497
498#ifndef PRODUCT
499void Flags::PrintFlagToJSONArray(JSONArray* jsarr, const Flag* flag) {
500 if (flag->IsUnrecognized()) {
501 return;
502 }
503 JSONObject jsflag(jsarr);
504 jsflag.AddProperty("name", flag->name_);
505 jsflag.AddProperty("comment", flag->comment_);
506 jsflag.AddProperty("modified", flag->changed_);
507 switch (flag->type_) {
508 case Flag::kBoolean: {
509 jsflag.AddProperty("_flagType", "Bool");
510 jsflag.AddProperty("valueAsString",
511 (*flag->bool_ptr_ ? "true" : "false"));
512 break;
513 }
514 case Flag::kInteger: {
515 jsflag.AddProperty("_flagType", "Int");
516 jsflag.AddPropertyF("valueAsString", "%d", *flag->int_ptr_);
517 break;
518 }
519 case Flag::kUint64: {
520 jsflag.AddProperty("_flagType", "UInt64");
521 jsflag.AddPropertyF("valueAsString", "%" Pu64, *flag->uint64_ptr_);
522 break;
523 }
524 case Flag::kString: {
525 jsflag.AddProperty("_flagType", "String");
526 if (flag->charp_ptr_ != nullptr) {
527 jsflag.AddPropertyF("valueAsString", "%s", *flag->charp_ptr_);
528 } else {
529 // valueAsString missing means nullptr.
530 }
531 break;
532 }
533 case Flag::kFlagHandler: {
534 jsflag.AddProperty("_flagType", "Bool");
535 const char* value = flag->string_value_.get();
536 jsflag.AddProperty("valueAsString", value == nullptr ? "false" : value);
537 break;
538 }
539 case Flag::kOptionHandler: {
540 jsflag.AddProperty("_flagType", "String");
541 if (flag->string_value_ != nullptr) {
542 jsflag.AddProperty("valueAsString", flag->string_value_.get());
543 } else {
544 // valueAsString missing means nullptr.
545 }
546 break;
547 }
548 default:
549 UNREACHABLE();
550 break;
551 }
552}
553
554void Flags::PrintJSON(JSONStream* js) {
555 JSONObject jsobj(js);
556 jsobj.AddProperty("type", "FlagList");
557 JSONArray jsarr(&jsobj, "flags");
558 for (intptr_t i = 0; i < num_flags_; ++i) {
559 PrintFlagToJSONArray(&jsarr, flags_[i]);
560 }
561}
562#endif // !PRODUCT
563
564} // namespace dart
static bool equals(T *a, T *b)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define UNREACHABLE()
Definition assert.h:248
#define ASSERT(E)
struct MyStruct s
FlutterSemanticsFlag flag
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
const char * charp
Definition flags.h:12
void(* FlagHandler)(bool value)
Definition flags.h:28
void(* OptionHandler)(const char *value)
Definition flags.h:29
static void Normalize(char *s)
Definition flags.cc:276
static bool IsValidFlag(const char *name, const char *prefix, intptr_t prefix_length)
Definition flags.cc:419
bool Parse(const skjson::Value &, T *)
#define Pu64
Definition globals.h:417

◆ PRODUCT_FLAG_MACRO

#define PRODUCT_FLAG_MACRO (   name,
  type,
  default_value,
  comment 
)
Value:
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);

Definition at line 20 of file flags.cc.

◆ RELEASE_FLAG_MACRO

#define RELEASE_FLAG_MACRO (   name,
  product_value,
  type,
  default_value,
  comment 
)
Value:
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);

Definition at line 55 of file flags.cc.