Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Unified Diff: src/flags.cc

Issue 1935: New static flags system (Closed)
Patch Set: Merge, again. Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/flags.h ('k') | src/flags.defs » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/flags.cc
diff --git a/src/flags.cc b/src/flags.cc
index b8a9e99d87d722c6a3530244ed7a9dbec286565f..886824704299a306a7524933cbd28fc727ce1ea6 100644
--- a/src/flags.cc
+++ b/src/flags.cc
@@ -34,125 +34,155 @@
namespace v8 { namespace internal {
-// -----------------------------------------------------------------------------
-// Helpers
+// Define all of our flags.
+#define FLAG_MODE_DEFINE
+#include "flags.defs"
-static inline char NormalizeChar(char ch) {
- return ch == '_' ? '-' : ch;
-}
+// Define all of our flags default values.
+#define FLAG_MODE_DEFINE_DEFAULTS
+#include "flags.defs"
+
+namespace {
+
+// This structure represents a single entry in the flag system, with a pointer
+// to the actual flag, default value, comment, etc. This is designed to be POD
+// initialized as to avoid requiring static constructors.
+struct Flag {
+ enum FlagType { TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING };
+
+ FlagType type_; // What type of flag, bool, int, or string.
+ const char* name_; // Name of the flag, ex "my_flag".
+ void* valptr_; // Pointer to the global flag variable.
+ const void* defptr_; // Pointer to the default value.
+ const char* cmt_; // A comment about the flags purpose.
+
+ FlagType type() const { return type_; }
+ const char* name() const { return name_; }
-static const char* NormalizeName(const char* name) {
- int len = strlen(name);
- char* result = NewArray<char>(len + 1);
- for (int i = 0; i <= len; i++) {
- result[i] = NormalizeChar(name[i]);
+ const char* comment() const { return cmt_; }
+
+ bool* bool_variable() const {
+ ASSERT(type_ == TYPE_BOOL);
+ return reinterpret_cast<bool*>(valptr_);
}
- return const_cast<const char*>(result);
-}
+ int* int_variable() const {
+ ASSERT(type_ == TYPE_INT);
+ return reinterpret_cast<int*>(valptr_);
+ }
-static bool EqualNames(const char* a, const char* b) {
- for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
- if (a[i] == '\0') {
- return true;
- }
+ double* float_variable() const {
+ ASSERT(type_ == TYPE_FLOAT);
+ return reinterpret_cast<double*>(valptr_);
}
- return false;
-}
+ const char** string_variable() const {
+ ASSERT(type_ == TYPE_STRING);
+ return reinterpret_cast<const char**>(valptr_);
+ }
-// -----------------------------------------------------------------------------
-// Implementation of Flag
+ bool bool_default() const {
+ ASSERT(type_ == TYPE_BOOL);
+ return *reinterpret_cast<const bool*>(defptr_);
+ }
-Flag::Flag(const char* file, const char* name, const char* comment,
- Type type, void* variable, FlagValue default_) {
- file_ = file;
- name_ = NormalizeName(name);
- comment_ = comment;
- type_ = type;
- variable_ = reinterpret_cast<FlagValue*>(variable);
- this->default_ = default_;
- FlagList::Register(this);
-}
+ int int_default() const {
+ ASSERT(type_ == TYPE_INT);
+ return *reinterpret_cast<const int*>(defptr_);
+ }
+ double float_default() const {
+ ASSERT(type_ == TYPE_FLOAT);
+ return *reinterpret_cast<const double*>(defptr_);
+ }
-void Flag::SetToDefault() {
- // Note that we cannot simply do '*variable_ = default_;' since
- // flag variables are not really of type FlagValue and thus may
- // be smaller! The FlagValue union is simply 'overlayed' on top
- // of a flag variable for convenient access. Since union members
- // are guarantee to be aligned at the beginning, this works.
- switch (type_) {
- case Flag::BOOL:
- variable_->b = default_.b;
- return;
- case Flag::INT:
- variable_->i = default_.i;
- return;
- case Flag::FLOAT:
- variable_->f = default_.f;
- return;
- case Flag::STRING:
- variable_->s = default_.s;
- return;
+ const char* string_default() const {
+ ASSERT(type_ == TYPE_STRING);
+ return *reinterpret_cast<const char* const *>(defptr_);
}
- UNREACHABLE();
-}
+ // Compare this flag's current value against the default.
+ bool IsDefault() const {
+ switch (type_) {
+ case TYPE_BOOL:
+ return *bool_variable() == bool_default();
+ case TYPE_INT:
+ return *int_variable() == int_default();
+ case TYPE_FLOAT:
+ return *float_variable() == float_default();
+ case TYPE_STRING:
+ const char* str1 = *string_variable();
+ const char* str2 = string_default();
+ if (str2 == NULL) return str1 == NULL;
+ if (str1 == NULL) return str2 == NULL;
+ return strcmp(str1, str2) == 0;
+ }
+ return true; // NOTREACHED
+ }
-bool Flag::IsDefault() const {
- switch (type_) {
- case Flag::BOOL:
- return variable_->b == default_.b;
- case Flag::INT:
- return variable_->i == default_.i;
- case Flag::FLOAT:
- return variable_->f == default_.f;
- case Flag::STRING:
- if (variable_->s && default_.s) {
- return strcmp(variable_->s, default_.s) == 0;
- } else {
- return variable_->s == default_.s;
- }
+ // Set a flag back to it's default value.
+ void Reset() {
+ switch (type_) {
+ case TYPE_BOOL:
+ *bool_variable() = bool_default();
+ break;
+ case TYPE_INT:
+ *int_variable() = int_default();
+ break;
+ case TYPE_FLOAT:
+ *float_variable() = float_default();
+ break;
+ case TYPE_STRING:
+ *string_variable() = string_default();
+ break;
+ }
}
- UNREACHABLE();
- return false;
-}
+};
+
+Flag flags[] = {
+#define FLAG_MODE_META
+#include "flags.defs"
+};
+
+const size_t num_flags = sizeof(flags) / sizeof(*flags);
+
+} // namespace
-static const char* Type2String(Flag::Type type) {
+static const char* Type2String(Flag::FlagType type) {
switch (type) {
- case Flag::BOOL: return "bool";
- case Flag::INT: return "int";
- case Flag::FLOAT: return "float";
- case Flag::STRING: return "string";
+ case Flag::TYPE_BOOL: return "bool";
+ case Flag::TYPE_INT: return "int";
+ case Flag::TYPE_FLOAT: return "float";
+ case Flag::TYPE_STRING: return "string";
}
UNREACHABLE();
return NULL;
}
-static char* ToString(Flag::Type type, FlagValue* variable) {
+static char* ToString(Flag* flag) {
Vector<char> value;
- switch (type) {
- case Flag::BOOL:
+ switch (flag->type()) {
+ case Flag::TYPE_BOOL:
value = Vector<char>::New(6);
- OS::SNPrintF(value, "%s", (variable->b ? "true" : "false"));
+ OS::SNPrintF(value, "%s", (*flag->bool_variable() ? "true" : "false"));
break;
- case Flag::INT:
+ case Flag::TYPE_INT:
value = Vector<char>::New(12);
- OS::SNPrintF(value, "%d", variable->i);
+ OS::SNPrintF(value, "%d", *flag->int_variable());
break;
- case Flag::FLOAT:
+ case Flag::TYPE_FLOAT:
value = Vector<char>::New(20);
- OS::SNPrintF(value, "%f", variable->f);
+ OS::SNPrintF(value, "%f", *flag->float_variable());
break;
- case Flag::STRING:
- if (variable->s) {
- int length = strlen(variable->s) + 1;
+ case Flag::TYPE_STRING:
+ const char* str = *flag->string_variable();
+ if (str) {
+ int length = strlen(str) + 1;
value = Vector<char>::New(length);
- OS::SNPrintF(value, "%s", variable->s);
+ OS::SNPrintF(value, "%s", str);
} else {
value = Vector<char>::New(5);
OS::SNPrintF(value, "NULL");
@@ -164,42 +194,14 @@ static char* ToString(Flag::Type type, FlagValue* variable) {
}
-static void PrintFlagValue(Flag::Type type, FlagValue* variable) {
- char* value = ToString(type, variable);
- printf("%s", value);
- DeleteArray(value);
-}
-
-
-char* Flag::StringValue() const {
- return ToString(type_, variable_);
-}
-
-
-void Flag::Print(bool print_current_value) {
- printf(" --%s (%s) type: %s default: ", name_, comment_,
- Type2String(type_));
- PrintFlagValue(type_, &default_);
- if (print_current_value) {
- printf(" current value: ");
- PrintFlagValue(type_, variable_);
- }
- printf("\n");
-}
-
-
-// -----------------------------------------------------------------------------
-// Implementation of FlagList
-
-Flag* FlagList::list_ = NULL;
-
-
+// static
List<char *>* FlagList::argv() {
List<char *>* args = new List<char*>(8);
- for (Flag* f = list_; f != NULL; f = f->next()) {
+ for (size_t i = 0; i < num_flags; ++i) {
+ Flag* f = &flags[i];
if (!f->IsDefault()) {
Vector<char> cmdline_flag;
- if (f->type() != Flag::BOOL || *(f->bool_variable())) {
+ if (f->type() != Flag::TYPE_BOOL || *(f->bool_variable())) {
int length = strlen(f->name()) + 2 + 1;
cmdline_flag = Vector<char>::New(length);
OS::SNPrintF(cmdline_flag, "--%s", f->name());
@@ -209,45 +211,26 @@ List<char *>* FlagList::argv() {
OS::SNPrintF(cmdline_flag, "--no%s", f->name());
}
args->Add(cmdline_flag.start());
- if (f->type() != Flag::BOOL) {
- args->Add(f->StringValue());
- }
- }
- }
- return args;
-}
-
-
-void FlagList::Print(const char* file, bool print_current_value) {
- // Since flag registration is likely by file (= C++ file),
- // we don't need to sort by file and still get grouped output.
- const char* current = NULL;
- for (Flag* f = list_; f != NULL; f = f->next()) {
- if (file == NULL || file == f->file()) {
- if (current != f->file()) {
- printf("Flags from %s:\n", f->file());
- current = f->file();
+ if (f->type() != Flag::TYPE_BOOL) {
+ args->Add(ToString(f));
}
- f->Print(print_current_value);
}
}
-}
-
-Flag* FlagList::Lookup(const char* name) {
- Flag* f = list_;
- while (f != NULL && !EqualNames(name, f->name()))
- f = f->next();
- return f;
+ return args;
}
-void FlagList::SplitArgument(const char* arg,
- char* buffer,
- int buffer_size,
- const char** name,
- const char** value,
- bool* is_bool) {
+// Helper function to parse flags: Takes an argument arg and splits it into
+// a flag name and flag value (or NULL if they are missing). is_bool is set
+// if the arg started with "-no" or "--no". The buffer may be used to NUL-
+// terminate the name, it must be large enough to hold any possible name.
+static void SplitArgument(const char* arg,
+ char* buffer,
+ int buffer_size,
+ const char** name,
+ const char** value,
+ bool* is_bool) {
*name = NULL;
*value = NULL;
*is_bool = false;
@@ -282,6 +265,31 @@ void FlagList::SplitArgument(const char* arg,
}
+inline char NormalizeChar(char ch) {
+ return ch == '_' ? '-' : ch;
+}
+
+
+static bool EqualNames(const char* a, const char* b) {
+ for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
+ if (a[i] == '\0') {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+static Flag* FindFlag(const char* name) {
+ for (size_t i = 0; i < num_flags; ++i) {
+ if (EqualNames(name, flags[i].name()))
+ return &flags[i];
+ }
+ return NULL;
+}
+
+
+// static
int FlagList::SetFlagsFromCommandLine(int* argc,
char** argv,
bool remove_flags) {
@@ -299,7 +307,7 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
if (name != NULL) {
// lookup the flag
- Flag* flag = Lookup(name);
+ Flag* flag = FindFlag(name);
if (flag == NULL) {
if (remove_flags) {
// We don't recognize this flag but since we're removing
@@ -314,7 +322,7 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
}
// if we still need a flag value, use the next argument if available
- if (flag->type() != Flag::BOOL && value == NULL) {
+ if (flag->type() != Flag::TYPE_BOOL && value == NULL) {
if (i < *argc) {
value = argv[i++];
} else {
@@ -327,23 +335,23 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
// set the flag
char* endp = const_cast<char*>(""); // *endp is only read
switch (flag->type()) {
- case Flag::BOOL:
+ case Flag::TYPE_BOOL:
*flag->bool_variable() = !is_bool;
break;
- case Flag::INT:
+ case Flag::TYPE_INT:
*flag->int_variable() = strtol(value, &endp, 10); // NOLINT
break;
- case Flag::FLOAT:
+ case Flag::TYPE_FLOAT:
*flag->float_variable() = strtod(value, &endp);
break;
- case Flag::STRING:
+ case Flag::TYPE_STRING:
*flag->string_variable() = value;
break;
}
// handle errors
- if ((flag->type() == Flag::BOOL && value != NULL) ||
- (flag->type() != Flag::BOOL && is_bool) ||
+ if ((flag->type() == Flag::TYPE_BOOL && value != NULL) ||
+ (flag->type() != Flag::TYPE_BOOL && is_bool) ||
*endp != '\0') {
fprintf(stderr, "Error: illegal value for flag %s of type %s\n",
arg, Type2String(flag->type()));
@@ -384,6 +392,7 @@ static char* SkipBlackSpace(char* p) {
}
+// static
int FlagList::SetFlagsFromString(const char* str, int len) {
// make a 0-terminated copy of str
char* copy0 = NewArray<char>(len + 1);
@@ -427,12 +436,23 @@ int FlagList::SetFlagsFromString(const char* str, int len) {
}
-void FlagList::Register(Flag* flag) {
- ASSERT(flag != NULL && strlen(flag->name()) > 0);
- if (Lookup(flag->name()) != NULL)
- V8_Fatal(flag->file(), 0, "flag %s declared twice", flag->name());
- flag->next_ = list_;
- list_ = flag;
+// static
+void FlagList::ResetAllFlags() {
+ for (size_t i = 0; i < num_flags; ++i) {
+ flags[i].Reset();
+ }
+}
+
+
+// static
+void FlagList::PrintHelp() {
+ for (size_t i = 0; i < num_flags; ++i) {
+ Flag* f = &flags[i];
+ char* value = ToString(f);
+ printf(" --%s (%s) type: %s default: %s\n",
+ f->name(), f->comment(), Type2String(f->type()), value);
+ DeleteArray(value);
+ }
}
} } // namespace v8::internal
« no previous file with comments | « src/flags.h ('k') | src/flags.defs » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698