00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <ctype.h>
00029 #include <stdlib.h>
00030
00031 #include "v8.h"
00032
00033 #include "platform.h"
00034
00035 namespace v8 { namespace internal {
00036
00037
00038 #define FLAG_MODE_DEFINE
00039 #include "flag-definitions.h"
00040
00041
00042 #define FLAG_MODE_DEFINE_DEFAULTS
00043 #include "flag-definitions.h"
00044
00045 namespace {
00046
00047
00048
00049
00050 struct Flag {
00051 enum FlagType { TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING };
00052
00053 FlagType type_;
00054 const char* name_;
00055 void* valptr_;
00056 const void* defptr_;
00057 const char* cmt_;
00058
00059 FlagType type() const { return type_; }
00060
00061 const char* name() const { return name_; }
00062
00063 const char* comment() const { return cmt_; }
00064
00065 bool* bool_variable() const {
00066 ASSERT(type_ == TYPE_BOOL);
00067 return reinterpret_cast<bool*>(valptr_);
00068 }
00069
00070 int* int_variable() const {
00071 ASSERT(type_ == TYPE_INT);
00072 return reinterpret_cast<int*>(valptr_);
00073 }
00074
00075 double* float_variable() const {
00076 ASSERT(type_ == TYPE_FLOAT);
00077 return reinterpret_cast<double*>(valptr_);
00078 }
00079
00080 const char** string_variable() const {
00081 ASSERT(type_ == TYPE_STRING);
00082 return reinterpret_cast<const char**>(valptr_);
00083 }
00084
00085 bool bool_default() const {
00086 ASSERT(type_ == TYPE_BOOL);
00087 return *reinterpret_cast<const bool*>(defptr_);
00088 }
00089
00090 int int_default() const {
00091 ASSERT(type_ == TYPE_INT);
00092 return *reinterpret_cast<const int*>(defptr_);
00093 }
00094
00095 double float_default() const {
00096 ASSERT(type_ == TYPE_FLOAT);
00097 return *reinterpret_cast<const double*>(defptr_);
00098 }
00099
00100 const char* string_default() const {
00101 ASSERT(type_ == TYPE_STRING);
00102 return *reinterpret_cast<const char* const *>(defptr_);
00103 }
00104
00105
00106 bool IsDefault() const {
00107 switch (type_) {
00108 case TYPE_BOOL:
00109 return *bool_variable() == bool_default();
00110 case TYPE_INT:
00111 return *int_variable() == int_default();
00112 case TYPE_FLOAT:
00113 return *float_variable() == float_default();
00114 case TYPE_STRING:
00115 const char* str1 = *string_variable();
00116 const char* str2 = string_default();
00117 if (str2 == NULL) return str1 == NULL;
00118 if (str1 == NULL) return str2 == NULL;
00119 return strcmp(str1, str2) == 0;
00120 }
00121 UNREACHABLE();
00122 return true;
00123 }
00124
00125
00126 void Reset() {
00127 switch (type_) {
00128 case TYPE_BOOL:
00129 *bool_variable() = bool_default();
00130 break;
00131 case TYPE_INT:
00132 *int_variable() = int_default();
00133 break;
00134 case TYPE_FLOAT:
00135 *float_variable() = float_default();
00136 break;
00137 case TYPE_STRING:
00138 *string_variable() = string_default();
00139 break;
00140 }
00141 }
00142 };
00143
00144 Flag flags[] = {
00145 #define FLAG_MODE_META
00146 #include "flag-definitions.h"
00147 };
00148
00149 const size_t num_flags = sizeof(flags) / sizeof(*flags);
00150
00151 }
00152
00153
00154 static const char* Type2String(Flag::FlagType type) {
00155 switch (type) {
00156 case Flag::TYPE_BOOL: return "bool";
00157 case Flag::TYPE_INT: return "int";
00158 case Flag::TYPE_FLOAT: return "float";
00159 case Flag::TYPE_STRING: return "string";
00160 }
00161 UNREACHABLE();
00162 return NULL;
00163 }
00164
00165
00166 static char* ToString(Flag* flag) {
00167 Vector<char> value;
00168 switch (flag->type()) {
00169 case Flag::TYPE_BOOL:
00170 value = Vector<char>::New(6);
00171 OS::SNPrintF(value, "%s", (*flag->bool_variable() ? "true" : "false"));
00172 break;
00173 case Flag::TYPE_INT:
00174 value = Vector<char>::New(12);
00175 OS::SNPrintF(value, "%d", *flag->int_variable());
00176 break;
00177 case Flag::TYPE_FLOAT:
00178 value = Vector<char>::New(20);
00179 OS::SNPrintF(value, "%f", *flag->float_variable());
00180 break;
00181 case Flag::TYPE_STRING:
00182 const char* str = *flag->string_variable();
00183 if (str) {
00184 int length = strlen(str) + 1;
00185 value = Vector<char>::New(length);
00186 OS::SNPrintF(value, "%s", str);
00187 } else {
00188 value = Vector<char>::New(5);
00189 OS::SNPrintF(value, "NULL");
00190 }
00191 break;
00192 }
00193 ASSERT(!value.is_empty());
00194 return value.start();
00195 }
00196
00197
00198
00199 List<char *>* FlagList::argv() {
00200 List<char *>* args = new List<char*>(8);
00201 for (size_t i = 0; i < num_flags; ++i) {
00202 Flag* f = &flags[i];
00203 if (!f->IsDefault()) {
00204 Vector<char> cmdline_flag;
00205 if (f->type() != Flag::TYPE_BOOL || *(f->bool_variable())) {
00206 int length = strlen(f->name()) + 2 + 1;
00207 cmdline_flag = Vector<char>::New(length);
00208 OS::SNPrintF(cmdline_flag, "--%s", f->name());
00209 } else {
00210 int length = strlen(f->name()) + 4 + 1;
00211 cmdline_flag = Vector<char>::New(length);
00212 OS::SNPrintF(cmdline_flag, "--no%s", f->name());
00213 }
00214 args->Add(cmdline_flag.start());
00215 if (f->type() != Flag::TYPE_BOOL) {
00216 args->Add(ToString(f));
00217 }
00218 }
00219 }
00220
00221 return args;
00222 }
00223
00224
00225
00226
00227
00228
00229 static void SplitArgument(const char* arg,
00230 char* buffer,
00231 int buffer_size,
00232 const char** name,
00233 const char** value,
00234 bool* is_bool) {
00235 *name = NULL;
00236 *value = NULL;
00237 *is_bool = false;
00238
00239 if (*arg == '-') {
00240
00241 arg++;
00242 if (*arg == '-')
00243 arg++;
00244 if (arg[0] == 'n' && arg[1] == 'o') {
00245 arg += 2;
00246 *is_bool = true;
00247 }
00248 *name = arg;
00249
00250
00251 while (*arg != '\0' && *arg != '=')
00252 arg++;
00253
00254
00255 if (*arg == '=') {
00256
00257 int n = arg - *name;
00258 CHECK(n < buffer_size);
00259 memcpy(buffer, *name, n);
00260 buffer[n] = '\0';
00261 *name = buffer;
00262
00263 *value = arg + 1;
00264 }
00265 }
00266 }
00267
00268
00269 inline char NormalizeChar(char ch) {
00270 return ch == '_' ? '-' : ch;
00271 }
00272
00273
00274 static bool EqualNames(const char* a, const char* b) {
00275 for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
00276 if (a[i] == '\0') {
00277 return true;
00278 }
00279 }
00280 return false;
00281 }
00282
00283
00284 static Flag* FindFlag(const char* name) {
00285 for (size_t i = 0; i < num_flags; ++i) {
00286 if (EqualNames(name, flags[i].name()))
00287 return &flags[i];
00288 }
00289 return NULL;
00290 }
00291
00292
00293
00294 int FlagList::SetFlagsFromCommandLine(int* argc,
00295 char** argv,
00296 bool remove_flags) {
00297
00298 for (int i = 1; i < *argc;) {
00299 int j = i;
00300 const char* arg = argv[i++];
00301
00302
00303 char buffer[1*KB];
00304 const char* name;
00305 const char* value;
00306 bool is_bool;
00307 SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
00308
00309 if (name != NULL) {
00310
00311 Flag* flag = FindFlag(name);
00312 if (flag == NULL) {
00313 if (remove_flags) {
00314
00315
00316
00317
00318 continue;
00319 } else {
00320 fprintf(stderr, "Error: unrecognized flag %s\n", arg);
00321 return j;
00322 }
00323 }
00324
00325
00326 if (flag->type() != Flag::TYPE_BOOL && value == NULL) {
00327 if (i < *argc) {
00328 value = argv[i++];
00329 } else {
00330 fprintf(stderr, "Error: missing value for flag %s of type %s\n",
00331 arg, Type2String(flag->type()));
00332 return j;
00333 }
00334 }
00335
00336
00337 char* endp = const_cast<char*>("");
00338 switch (flag->type()) {
00339 case Flag::TYPE_BOOL:
00340 *flag->bool_variable() = !is_bool;
00341 break;
00342 case Flag::TYPE_INT:
00343 *flag->int_variable() = strtol(value, &endp, 10);
00344 break;
00345 case Flag::TYPE_FLOAT:
00346 *flag->float_variable() = strtod(value, &endp);
00347 break;
00348 case Flag::TYPE_STRING:
00349 *flag->string_variable() = value;
00350 break;
00351 }
00352
00353
00354 if ((flag->type() == Flag::TYPE_BOOL && value != NULL) ||
00355 (flag->type() != Flag::TYPE_BOOL && is_bool) ||
00356 *endp != '\0') {
00357 fprintf(stderr, "Error: illegal value for flag %s of type %s\n",
00358 arg, Type2String(flag->type()));
00359 return j;
00360 }
00361
00362
00363 if (remove_flags)
00364 while (j < i)
00365 argv[j++] = NULL;
00366 }
00367 }
00368
00369
00370 if (remove_flags) {
00371 int j = 1;
00372 for (int i = 1; i < *argc; i++) {
00373 if (argv[i] != NULL)
00374 argv[j++] = argv[i];
00375 }
00376 *argc = j;
00377 }
00378
00379
00380 return 0;
00381 }
00382
00383
00384 static char* SkipWhiteSpace(char* p) {
00385 while (*p != '\0' && isspace(*p) != 0) p++;
00386 return p;
00387 }
00388
00389
00390 static char* SkipBlackSpace(char* p) {
00391 while (*p != '\0' && isspace(*p) == 0) p++;
00392 return p;
00393 }
00394
00395
00396
00397 int FlagList::SetFlagsFromString(const char* str, int len) {
00398
00399 char* copy0 = NewArray<char>(len + 1);
00400 memcpy(copy0, str, len);
00401 copy0[len] = '\0';
00402
00403
00404 char* copy = SkipWhiteSpace(copy0);
00405
00406
00407 int argc = 1;
00408 for (char* p = copy; *p != '\0'; argc++) {
00409 p = SkipBlackSpace(p);
00410 p = SkipWhiteSpace(p);
00411 }
00412
00413
00414 char** argv = NewArray<char*>(argc);
00415
00416
00417 argc = 1;
00418 for (char* p = copy; *p != '\0'; argc++) {
00419 argv[argc] = p;
00420 p = SkipBlackSpace(p);
00421 if (*p != '\0') *p++ = '\0';
00422 p = SkipWhiteSpace(p);
00423 }
00424
00425
00426 int result = SetFlagsFromCommandLine(&argc, argv, false);
00427
00428
00429 DeleteArray(argv);
00430
00431
00432
00433
00434
00435
00436 return result;
00437 }
00438
00439
00440
00441 void FlagList::ResetAllFlags() {
00442 for (size_t i = 0; i < num_flags; ++i) {
00443 flags[i].Reset();
00444 }
00445 }
00446
00447
00448
00449 void FlagList::PrintHelp() {
00450 for (size_t i = 0; i < num_flags; ++i) {
00451 Flag* f = &flags[i];
00452 char* value = ToString(f);
00453 printf(" --%s (%s) type: %s default: %s\n",
00454 f->name(), f->comment(), Type2String(f->type()), value);
00455 DeleteArray(value);
00456 }
00457 }
00458
00459 } }