Index: runtime/vm/flags.cc |
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc |
index 2c3cb13842c1d4ed6bf68bc9cf5b6390793b96df..a2703449be2d7ad552f9c0969d3dd786eaf0a4b0 100644 |
--- a/runtime/vm/flags.cc |
+++ b/runtime/vm/flags.cc |
@@ -5,6 +5,7 @@ |
#include "vm/flags.h" |
#include "platform/assert.h" |
+#include "vm/json_stream.h" |
#include "vm/os.h" |
namespace dart { |
@@ -13,11 +14,13 @@ DEFINE_FLAG(bool, print_flags, false, "Print flags as they are being parsed."); |
DEFINE_FLAG(bool, ignore_unrecognized_flags, false, |
"Ignore unrecognized flags."); |
-// List of registered flags. |
-Flag* Flags::flags_ = NULL; |
- |
bool Flags::initialized_ = false; |
+// List of registered flags. |
+Flag** Flags::flags_ = NULL; |
+intptr_t Flags::capacity_ = 0; |
+intptr_t Flags::num_flags_ = 0; |
+ |
class Flag { |
public: |
enum FlagType { |
@@ -72,7 +75,6 @@ class Flag { |
return (type_ == kBoolean) && (bool_ptr_ == NULL); |
} |
- Flag* next_; |
const char* name_; |
const char* comment_; |
union { |
@@ -83,16 +85,16 @@ class Flag { |
FlagHandler handler_; |
}; |
FlagType type_; |
+ bool changed_; |
}; |
Flag* Flags::Lookup(const char* name) { |
- Flag* cur = Flags::flags_; |
- while (cur != NULL) { |
- if (strcmp(cur->name_, name) == 0) { |
- return cur; |
+ for (intptr_t i = 0; i < num_flags_; i++) { |
+ Flag* flag = flags_[i]; |
+ if (strcmp(flag->name_, name) == 0) { |
+ return flag; |
} |
- cur = cur->next_; |
} |
return NULL; |
} |
@@ -107,6 +109,27 @@ bool Flags::IsSet(const char* name) { |
} |
+void Flags::AddFlag(Flag* flag) { |
+ ASSERT(!initialized_); |
+ if (num_flags_ == capacity_) { |
+ if (flags_ == NULL) { |
+ capacity_ = 256; |
+ flags_ = new Flag*[capacity_]; |
+ } else { |
+ intptr_t new_capacity = capacity_ * 2; |
+ Flag** new_flags = new Flag*[new_capacity]; |
+ for (intptr_t i = 0; i < num_flags_; i++) { |
+ new_flags[i] = flags_[i]; |
+ } |
+ delete [] flags_; |
+ flags_ = new_flags; |
+ capacity_ = new_capacity; |
+ } |
+ } |
+ flags_[num_flags_++] = flag; |
+} |
+ |
+ |
bool Flags::Register_bool(bool* addr, |
const char* name, |
bool default_value, |
@@ -117,9 +140,7 @@ bool Flags::Register_bool(bool* addr, |
return default_value; |
} |
flag = new Flag(name, comment, addr, Flag::kBoolean); |
- flag->next_ = Flags::flags_; |
- Flags::flags_ = flag; |
- |
+ AddFlag(flag); |
return default_value; |
} |
@@ -131,8 +152,7 @@ int Flags::Register_int(int* addr, |
ASSERT(Lookup(name) == NULL); |
Flag* flag = new Flag(name, comment, addr, Flag::kInteger); |
- flag->next_ = Flags::flags_; |
- Flags::flags_ = flag; |
+ AddFlag(flag); |
return default_value; |
} |
@@ -144,8 +164,7 @@ const char* Flags::Register_charp(charp* addr, |
const char* comment) { |
ASSERT(Lookup(name) == NULL); |
Flag* flag = new Flag(name, comment, addr, Flag::kString); |
- flag->next_ = Flags::flags_; |
- Flags::flags_ = flag; |
+ AddFlag(flag); |
return default_value; |
} |
@@ -155,8 +174,7 @@ bool Flags::Register_func(FlagHandler handler, |
const char* comment) { |
ASSERT(Lookup(name) == NULL); |
Flag* flag = new Flag(name, comment, handler); |
- flag->next_ = Flags::flags_; |
- Flags::flags_ = flag; |
+ AddFlag(flag); |
return false; |
} |
@@ -171,6 +189,51 @@ static void Normalize(char* s) { |
} |
+bool Flags::SetFlagFromString(Flag* flag, const char* argument) { |
+ ASSERT(!flag->IsUnrecognized()); |
+ switch (flag->type_) { |
+ case Flag::kBoolean: { |
+ if (strcmp(argument, "true") == 0) { |
+ *flag->bool_ptr_ = true; |
+ } else if (strcmp(argument, "false") == 0) { |
+ *flag->bool_ptr_ = false; |
+ } else { |
+ return false; |
+ } |
+ break; |
+ } |
+ case Flag::kString: { |
+ *flag->charp_ptr_ = argument == NULL ? NULL : strdup(argument); |
+ break; |
+ } |
+ case Flag::kInteger: { |
+ char* endptr = NULL; |
+ int val = strtol(argument, &endptr, 10); |
+ if (endptr != argument) { |
+ *flag->int_ptr_ = val; |
+ } |
+ break; |
+ } |
+ case Flag::kFunc: { |
+ if (strcmp(argument, "true") == 0) { |
+ (flag->handler_)(true); |
+ } else if (strcmp(argument, "false") == 0) { |
+ (flag->handler_)(false); |
+ } else { |
+ return false; |
+ } |
+ break; |
+ } |
+ default: { |
+ UNREACHABLE(); |
+ return false; |
+ } |
+ } |
+ flag->changed_ = true; |
+ return true; |
+} |
+ |
+ |
void Flags::Parse(const char* option) { |
// Find the beginning of the option argument, if it exists. |
const char* equals = option; |
@@ -220,43 +283,9 @@ void Flags::Parse(const char* option) { |
// Only set values for recognized flags, skip collected |
// unrecognized flags. |
if (!flag->IsUnrecognized()) { |
- switch (flag->type_) { |
- case Flag::kBoolean: { |
- if (strcmp(argument, "true") == 0) { |
- *flag->bool_ptr_ = true; |
- } else if (strcmp(argument, "false") == 0) { |
- *flag->bool_ptr_ = false; |
- } else { |
- OS::Print("Ignoring flag: %s is a bool flag.\n", name); |
- } |
- break; |
- } |
- case Flag::kString: { |
- *flag->charp_ptr_ = argument == NULL ? NULL : strdup(argument); |
- break; |
- } |
- case Flag::kInteger: { |
- char* endptr = NULL; |
- int val = strtol(argument, &endptr, 10); |
- if (endptr != argument) { |
- *flag->int_ptr_ = val; |
- } |
- break; |
- } |
- case Flag::kFunc: { |
- if (strcmp(argument, "true") == 0) { |
- (flag->handler_)(true); |
- } else if (strcmp(argument, "false") == 0) { |
- (flag->handler_)(false); |
- } else { |
- OS::Print("Ignoring flag: %s is a bool flag.\n", name); |
- } |
- break; |
- } |
- default: { |
- UNREACHABLE(); |
- break; |
- } |
+ if (!SetFlagFromString(flag, argument)) { |
+ OS::Print("Ignoring flag: %s is an invalid value for flag %s\n", |
+ argument, name); |
} |
} |
} |
@@ -274,13 +303,20 @@ static bool IsValidFlag(const char* name, |
} |
+int Flags::CompareFlagNames(const void* left, const void* right) { |
+ const Flag* left_flag = *reinterpret_cast<const Flag* const *>(left); |
+ const Flag* right_flag = *reinterpret_cast<const Flag* const *>(right); |
+ return strcmp(left_flag->name_, right_flag->name_); |
+} |
+ |
+ |
bool Flags::ProcessCommandLineFlags(int number_of_vm_flags, |
const char** vm_flags) { |
if (initialized_) { |
return false; |
} |
- initialized_ = true; |
+ qsort(flags_, num_flags_, sizeof flags_[0], CompareFlagNames); |
const char* kPrefix = "--"; |
const intptr_t kPrefixLen = strlen(kPrefix); |
@@ -295,8 +331,8 @@ bool Flags::ProcessCommandLineFlags(int number_of_vm_flags, |
if (!FLAG_ignore_unrecognized_flags) { |
int unrecognized_count = 0; |
- Flag* flag = Flags::flags_; |
- while (flag != NULL) { |
+ for (intptr_t j = 0; j < num_flags_; j++) { |
+ Flag* flag = flags_[j]; |
if (flag->IsUnrecognized()) { |
if (unrecognized_count == 0) { |
OS::PrintErr("Unrecognized flags: %s", flag->name_); |
@@ -305,7 +341,6 @@ bool Flags::ProcessCommandLineFlags(int number_of_vm_flags, |
} |
unrecognized_count++; |
} |
- flag = flag->next_; |
} |
if (unrecognized_count > 0) { |
OS::PrintErr("\n"); |
@@ -315,36 +350,93 @@ bool Flags::ProcessCommandLineFlags(int number_of_vm_flags, |
if (FLAG_print_flags) { |
PrintFlags(); |
} |
+ |
+ initialized_ = true; |
return true; |
} |
- |
-int Flags::CompareFlagNames(const void* left, const void* right) { |
- const Flag* left_flag = *reinterpret_cast<const Flag* const *>(left); |
- const Flag* right_flag = *reinterpret_cast<const Flag* const *>(right); |
- return strcmp(left_flag->name_, right_flag->name_); |
+bool Flags::SetFlag(const char* name, |
+ const char* value, |
+ const char** error) { |
+ Flag* flag = Lookup(name); |
+ if (flag == NULL) { |
+ *error = "Cannot set flag: flag not found"; |
+ return false; |
+ } |
+ if (!SetFlagFromString(flag, value)) { |
+ *error = "Cannot set flag: invalid value"; |
+ return false; |
+ } |
+ return true; |
} |
void Flags::PrintFlags() { |
- OS::Print("Flag settings:\n"); |
- Flag* flag = Flags::flags_; |
- int num_flags = 0; |
- while (flag != NULL) { |
- num_flags++; |
- flag = flag->next_; |
+ OS::Print("Flag settings:\n"); |
+ for (intptr_t i = 0; i < num_flags_; ++i) { |
+ flags_[i]->Print(); |
+ } |
+} |
+ |
+ |
+void Flags::PrintFlagToJSONArray(JSONArray* jsarr, const Flag* flag) { |
+ if (flag->IsUnrecognized() || flag->type_ == Flag::kFunc) { |
+ return; |
+ } |
+ JSONObject jsflag(jsarr); |
+ jsflag.AddProperty("name", flag->name_); |
+ jsflag.AddProperty("comment", flag->comment_); |
+ switch (flag->type_) { |
+ case Flag::kBoolean: { |
+ jsflag.AddProperty("flagType", "bool"); |
+ jsflag.AddProperty("valueAsString", |
+ (*flag->bool_ptr_ ? "true" : "false")); |
+ break; |
+ } |
+ case Flag::kInteger: { |
+ jsflag.AddProperty("flagType", "int"); |
+ jsflag.AddPropertyF("valueAsString", "%d", *flag->int_ptr_); |
+ break; |
} |
- Flag** flag_array = new Flag*[num_flags]; |
- flag = Flags::flags_; |
- for (int i = 0; i < num_flags; ++i, flag = flag->next_) { |
- flag_array[i] = flag; |
+ case Flag::kString: { |
+ jsflag.AddProperty("flagType", "string"); |
+ if (flag->charp_ptr_ != NULL) { |
+ jsflag.AddPropertyF("valueAsString", "%s", *flag->charp_ptr_); |
+ } else { |
+ // valueAsString missing means NULL. |
+ } |
+ break; |
} |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+} |
+ |
- qsort(flag_array, num_flags, sizeof flag_array[0], CompareFlagNames); |
+void Flags::PrintJSON(JSONStream* js) { |
+ JSONObject jsobj(js); |
+ jsobj.AddProperty("type", "FlagList"); |
+ jsobj.AddProperty("id", "flags"); |
- for (int i = 0; i < num_flags; ++i) { |
- flag_array[i]->Print(); |
+ { |
+ JSONArray jsarr(&jsobj, "unmodifiedFlags"); |
+ for (intptr_t i = 0; i < num_flags_; ++i) { |
+ Flag* flag = flags_[i]; |
+ if (!flag->changed_) { |
+ PrintFlagToJSONArray(&jsarr, flag); |
+ } |
+ } |
+ } |
+ { |
+ JSONArray jsarr(&jsobj, "modifiedFlags"); |
+ for (intptr_t i = 0; i < num_flags_; ++i) { |
+ Flag* flag = flags_[i]; |
+ if (flag->changed_) { |
+ PrintFlagToJSONArray(&jsarr, flag); |
+ } |
} |
- delete[] flag_array; |
} |
+} |
+ |
} // namespace dart |