Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / src / flags.cc
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <cctype>
6 #include <cstdlib>
7 #include <sstream>
8
9 #include "src/v8.h"
10
11 #include "src/assembler.h"
12 #include "src/base/platform/platform.h"
13 #include "src/ostreams.h"
14
15 namespace v8 {
16 namespace internal {
17
18 // Define all of our flags.
19 #define FLAG_MODE_DEFINE
20 #include "src/flag-definitions.h"  // NOLINT
21
22 // Define all of our flags default values.
23 #define FLAG_MODE_DEFINE_DEFAULTS
24 #include "src/flag-definitions.h"  // NOLINT
25
26 namespace {
27
28 // This structure represents a single entry in the flag system, with a pointer
29 // to the actual flag, default value, comment, etc.  This is designed to be POD
30 // initialized as to avoid requiring static constructors.
31 struct Flag {
32   enum FlagType { TYPE_BOOL, TYPE_MAYBE_BOOL, TYPE_INT, TYPE_FLOAT,
33                   TYPE_STRING, TYPE_ARGS };
34
35   FlagType type_;           // What type of flag, bool, int, or string.
36   const char* name_;        // Name of the flag, ex "my_flag".
37   void* valptr_;            // Pointer to the global flag variable.
38   const void* defptr_;      // Pointer to the default value.
39   const char* cmt_;         // A comment about the flags purpose.
40   bool owns_ptr_;           // Does the flag own its string value?
41
42   FlagType type() const { return type_; }
43
44   const char* name() const { return name_; }
45
46   const char* comment() const { return cmt_; }
47
48   bool* bool_variable() const {
49     DCHECK(type_ == TYPE_BOOL);
50     return reinterpret_cast<bool*>(valptr_);
51   }
52
53   MaybeBoolFlag* maybe_bool_variable() const {
54     DCHECK(type_ == TYPE_MAYBE_BOOL);
55     return reinterpret_cast<MaybeBoolFlag*>(valptr_);
56   }
57
58   int* int_variable() const {
59     DCHECK(type_ == TYPE_INT);
60     return reinterpret_cast<int*>(valptr_);
61   }
62
63   double* float_variable() const {
64     DCHECK(type_ == TYPE_FLOAT);
65     return reinterpret_cast<double*>(valptr_);
66   }
67
68   const char* string_value() const {
69     DCHECK(type_ == TYPE_STRING);
70     return *reinterpret_cast<const char**>(valptr_);
71   }
72
73   void set_string_value(const char* value, bool owns_ptr) {
74     DCHECK(type_ == TYPE_STRING);
75     const char** ptr = reinterpret_cast<const char**>(valptr_);
76     if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr);
77     *ptr = value;
78     owns_ptr_ = owns_ptr;
79   }
80
81   JSArguments* args_variable() const {
82     DCHECK(type_ == TYPE_ARGS);
83     return reinterpret_cast<JSArguments*>(valptr_);
84   }
85
86   bool bool_default() const {
87     DCHECK(type_ == TYPE_BOOL);
88     return *reinterpret_cast<const bool*>(defptr_);
89   }
90
91   int int_default() const {
92     DCHECK(type_ == TYPE_INT);
93     return *reinterpret_cast<const int*>(defptr_);
94   }
95
96   double float_default() const {
97     DCHECK(type_ == TYPE_FLOAT);
98     return *reinterpret_cast<const double*>(defptr_);
99   }
100
101   const char* string_default() const {
102     DCHECK(type_ == TYPE_STRING);
103     return *reinterpret_cast<const char* const *>(defptr_);
104   }
105
106   JSArguments args_default() const {
107     DCHECK(type_ == TYPE_ARGS);
108     return *reinterpret_cast<const JSArguments*>(defptr_);
109   }
110
111   // Compare this flag's current value against the default.
112   bool IsDefault() const {
113     switch (type_) {
114       case TYPE_BOOL:
115         return *bool_variable() == bool_default();
116       case TYPE_MAYBE_BOOL:
117         return maybe_bool_variable()->has_value == false;
118       case TYPE_INT:
119         return *int_variable() == int_default();
120       case TYPE_FLOAT:
121         return *float_variable() == float_default();
122       case TYPE_STRING: {
123         const char* str1 = string_value();
124         const char* str2 = string_default();
125         if (str2 == NULL) return str1 == NULL;
126         if (str1 == NULL) return str2 == NULL;
127         return strcmp(str1, str2) == 0;
128       }
129       case TYPE_ARGS:
130         return args_variable()->argc == 0;
131     }
132     UNREACHABLE();
133     return true;
134   }
135
136   // Set a flag back to it's default value.
137   void Reset() {
138     switch (type_) {
139       case TYPE_BOOL:
140         *bool_variable() = bool_default();
141         break;
142       case TYPE_MAYBE_BOOL:
143         *maybe_bool_variable() = MaybeBoolFlag::Create(false, false);
144         break;
145       case TYPE_INT:
146         *int_variable() = int_default();
147         break;
148       case TYPE_FLOAT:
149         *float_variable() = float_default();
150         break;
151       case TYPE_STRING:
152         set_string_value(string_default(), false);
153         break;
154       case TYPE_ARGS:
155         *args_variable() = args_default();
156         break;
157     }
158   }
159 };
160
161 Flag flags[] = {
162 #define FLAG_MODE_META
163 #include "src/flag-definitions.h"
164 };
165
166 const size_t num_flags = sizeof(flags) / sizeof(*flags);
167
168 }  // namespace
169
170
171 static const char* Type2String(Flag::FlagType type) {
172   switch (type) {
173     case Flag::TYPE_BOOL: return "bool";
174     case Flag::TYPE_MAYBE_BOOL: return "maybe_bool";
175     case Flag::TYPE_INT: return "int";
176     case Flag::TYPE_FLOAT: return "float";
177     case Flag::TYPE_STRING: return "string";
178     case Flag::TYPE_ARGS: return "arguments";
179   }
180   UNREACHABLE();
181   return NULL;
182 }
183
184
185 std::ostream& operator<<(std::ostream& os, const Flag& flag) {  // NOLINT
186   switch (flag.type()) {
187     case Flag::TYPE_BOOL:
188       os << (*flag.bool_variable() ? "true" : "false");
189       break;
190     case Flag::TYPE_MAYBE_BOOL:
191       os << (flag.maybe_bool_variable()->has_value
192                  ? (flag.maybe_bool_variable()->value ? "true" : "false")
193                  : "unset");
194       break;
195     case Flag::TYPE_INT:
196       os << *flag.int_variable();
197       break;
198     case Flag::TYPE_FLOAT:
199       os << *flag.float_variable();
200       break;
201     case Flag::TYPE_STRING: {
202       const char* str = flag.string_value();
203       os << (str ? str : "NULL");
204       break;
205     }
206     case Flag::TYPE_ARGS: {
207       JSArguments args = *flag.args_variable();
208       if (args.argc > 0) {
209         os << args[0];
210         for (int i = 1; i < args.argc; i++) {
211           os << args[i];
212         }
213       }
214       break;
215     }
216   }
217   return os;
218 }
219
220
221 // static
222 List<const char*>* FlagList::argv() {
223   List<const char*>* args = new List<const char*>(8);
224   Flag* args_flag = NULL;
225   for (size_t i = 0; i < num_flags; ++i) {
226     Flag* f = &flags[i];
227     if (!f->IsDefault()) {
228       if (f->type() == Flag::TYPE_ARGS) {
229         DCHECK(args_flag == NULL);
230         args_flag = f;  // Must be last in arguments.
231         continue;
232       }
233       {
234         bool disabled = f->type() == Flag::TYPE_BOOL && !*f->bool_variable();
235         std::ostringstream os;
236         os << (disabled ? "--no" : "--") << f->name();
237         args->Add(StrDup(os.str().c_str()));
238       }
239       if (f->type() != Flag::TYPE_BOOL) {
240         std::ostringstream os;
241         os << *f;
242         args->Add(StrDup(os.str().c_str()));
243       }
244     }
245   }
246   if (args_flag != NULL) {
247     std::ostringstream os;
248     os << "--" << args_flag->name();
249     args->Add(StrDup(os.str().c_str()));
250     JSArguments jsargs = *args_flag->args_variable();
251     for (int j = 0; j < jsargs.argc; j++) {
252       args->Add(StrDup(jsargs[j]));
253     }
254   }
255   return args;
256 }
257
258
259 inline char NormalizeChar(char ch) {
260   return ch == '_' ? '-' : ch;
261 }
262
263
264 // Helper function to parse flags: Takes an argument arg and splits it into
265 // a flag name and flag value (or NULL if they are missing). is_bool is set
266 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
267 // terminate the name, it must be large enough to hold any possible name.
268 static void SplitArgument(const char* arg,
269                           char* buffer,
270                           int buffer_size,
271                           const char** name,
272                           const char** value,
273                           bool* is_bool) {
274   *name = NULL;
275   *value = NULL;
276   *is_bool = false;
277
278   if (arg != NULL && *arg == '-') {
279     // find the begin of the flag name
280     arg++;  // remove 1st '-'
281     if (*arg == '-') {
282       arg++;  // remove 2nd '-'
283       if (arg[0] == '\0') {
284         const char* kJSArgumentsFlagName = "js_arguments";
285         *name = kJSArgumentsFlagName;
286         return;
287       }
288     }
289     if (arg[0] == 'n' && arg[1] == 'o') {
290       arg += 2;  // remove "no"
291       if (NormalizeChar(arg[0]) == '-') arg++;  // remove dash after "no".
292       *is_bool = true;
293     }
294     *name = arg;
295
296     // find the end of the flag name
297     while (*arg != '\0' && *arg != '=')
298       arg++;
299
300     // get the value if any
301     if (*arg == '=') {
302       // make a copy so we can NUL-terminate flag name
303       size_t n = arg - *name;
304       CHECK(n < static_cast<size_t>(buffer_size));  // buffer is too small
305       MemCopy(buffer, *name, n);
306       buffer[n] = '\0';
307       *name = buffer;
308       // get the value
309       *value = arg + 1;
310     }
311   }
312 }
313
314
315 static bool EqualNames(const char* a, const char* b) {
316   for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
317     if (a[i] == '\0') {
318       return true;
319     }
320   }
321   return false;
322 }
323
324
325 static Flag* FindFlag(const char* name) {
326   for (size_t i = 0; i < num_flags; ++i) {
327     if (EqualNames(name, flags[i].name()))
328       return &flags[i];
329   }
330   return NULL;
331 }
332
333
334 // static
335 int FlagList::SetFlagsFromCommandLine(int* argc,
336                                       char** argv,
337                                       bool remove_flags) {
338   int return_code = 0;
339   // parse arguments
340   for (int i = 1; i < *argc;) {
341     int j = i;  // j > 0
342     const char* arg = argv[i++];
343
344     // split arg into flag components
345     char buffer[1*KB];
346     const char* name;
347     const char* value;
348     bool is_bool;
349     SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
350
351     if (name != NULL) {
352       // lookup the flag
353       Flag* flag = FindFlag(name);
354       if (flag == NULL) {
355         if (remove_flags) {
356           // We don't recognize this flag but since we're removing
357           // the flags we recognize we assume that the remaining flags
358           // will be processed somewhere else so this flag might make
359           // sense there.
360           continue;
361         } else {
362           PrintF(stderr, "Error: unrecognized flag %s\n"
363                  "Try --help for options\n", arg);
364           return_code = j;
365           break;
366         }
367       }
368
369       // if we still need a flag value, use the next argument if available
370       if (flag->type() != Flag::TYPE_BOOL &&
371           flag->type() != Flag::TYPE_MAYBE_BOOL &&
372           flag->type() != Flag::TYPE_ARGS &&
373           value == NULL) {
374         if (i < *argc) {
375           value = argv[i++];
376         }
377         if (!value) {
378           PrintF(stderr, "Error: missing value for flag %s of type %s\n"
379                  "Try --help for options\n",
380                  arg, Type2String(flag->type()));
381           return_code = j;
382           break;
383         }
384       }
385
386       // set the flag
387       char* endp = const_cast<char*>("");  // *endp is only read
388       switch (flag->type()) {
389         case Flag::TYPE_BOOL:
390           *flag->bool_variable() = !is_bool;
391           break;
392         case Flag::TYPE_MAYBE_BOOL:
393           *flag->maybe_bool_variable() = MaybeBoolFlag::Create(true, !is_bool);
394           break;
395         case Flag::TYPE_INT:
396           *flag->int_variable() = strtol(value, &endp, 10);  // NOLINT
397           break;
398         case Flag::TYPE_FLOAT:
399           *flag->float_variable() = strtod(value, &endp);
400           break;
401         case Flag::TYPE_STRING:
402           flag->set_string_value(value ? StrDup(value) : NULL, true);
403           break;
404         case Flag::TYPE_ARGS: {
405           int start_pos = (value == NULL) ? i : i - 1;
406           int js_argc = *argc - start_pos;
407           const char** js_argv = NewArray<const char*>(js_argc);
408           if (value != NULL) {
409             js_argv[0] = StrDup(value);
410           }
411           for (int k = i; k < *argc; k++) {
412             js_argv[k - start_pos] = StrDup(argv[k]);
413           }
414           *flag->args_variable() = JSArguments::Create(js_argc, js_argv);
415           i = *argc;  // Consume all arguments
416           break;
417         }
418       }
419
420       // handle errors
421       bool is_bool_type = flag->type() == Flag::TYPE_BOOL ||
422           flag->type() == Flag::TYPE_MAYBE_BOOL;
423       if ((is_bool_type && value != NULL) || (!is_bool_type && is_bool) ||
424           *endp != '\0') {
425         PrintF(stderr, "Error: illegal value for flag %s of type %s\n"
426                "Try --help for options\n",
427                arg, Type2String(flag->type()));
428         return_code = j;
429         break;
430       }
431
432       // remove the flag & value from the command
433       if (remove_flags) {
434         while (j < i) {
435           argv[j++] = NULL;
436         }
437       }
438     }
439   }
440
441   // shrink the argument list
442   if (remove_flags) {
443     int j = 1;
444     for (int i = 1; i < *argc; i++) {
445       if (argv[i] != NULL)
446         argv[j++] = argv[i];
447     }
448     *argc = j;
449   }
450
451   if (FLAG_help) {
452     PrintHelp();
453     exit(0);
454   }
455   // parsed all flags successfully
456   return return_code;
457 }
458
459
460 static char* SkipWhiteSpace(char* p) {
461   while (*p != '\0' && isspace(*p) != 0) p++;
462   return p;
463 }
464
465
466 static char* SkipBlackSpace(char* p) {
467   while (*p != '\0' && isspace(*p) == 0) p++;
468   return p;
469 }
470
471
472 // static
473 int FlagList::SetFlagsFromString(const char* str, int len) {
474   // make a 0-terminated copy of str
475   ScopedVector<char> copy0(len + 1);
476   MemCopy(copy0.start(), str, len);
477   copy0[len] = '\0';
478
479   // strip leading white space
480   char* copy = SkipWhiteSpace(copy0.start());
481
482   // count the number of 'arguments'
483   int argc = 1;  // be compatible with SetFlagsFromCommandLine()
484   for (char* p = copy; *p != '\0'; argc++) {
485     p = SkipBlackSpace(p);
486     p = SkipWhiteSpace(p);
487   }
488
489   // allocate argument array
490   ScopedVector<char*> argv(argc);
491
492   // split the flags string into arguments
493   argc = 1;  // be compatible with SetFlagsFromCommandLine()
494   for (char* p = copy; *p != '\0'; argc++) {
495     argv[argc] = p;
496     p = SkipBlackSpace(p);
497     if (*p != '\0') *p++ = '\0';  // 0-terminate argument
498     p = SkipWhiteSpace(p);
499   }
500
501   // set the flags
502   int result = SetFlagsFromCommandLine(&argc, argv.start(), false);
503
504   return result;
505 }
506
507
508 // static
509 void FlagList::ResetAllFlags() {
510   for (size_t i = 0; i < num_flags; ++i) {
511     flags[i].Reset();
512   }
513 }
514
515
516 // static
517 void FlagList::PrintHelp() {
518   CpuFeatures::Probe(false);
519   CpuFeatures::PrintTarget();
520   CpuFeatures::PrintFeatures();
521
522   OFStream os(stdout);
523   os << "Usage:\n"
524      << "  shell [options] -e string\n"
525      << "    execute string in V8\n"
526      << "  shell [options] file1 file2 ... filek\n"
527      << "    run JavaScript scripts in file1, file2, ..., filek\n"
528      << "  shell [options]\n"
529      << "  shell [options] --shell [file1 file2 ... filek]\n"
530      << "    run an interactive JavaScript shell\n"
531      << "  d8 [options] file1 file2 ... filek\n"
532      << "  d8 [options]\n"
533      << "  d8 [options] --shell [file1 file2 ... filek]\n"
534      << "    run the new debugging shell\n\n"
535      << "Options:\n";
536   for (size_t i = 0; i < num_flags; ++i) {
537     Flag* f = &flags[i];
538     os << "  --" << f->name() << " (" << f->comment() << ")\n"
539        << "        type: " << Type2String(f->type()) << "  default: " << *f
540        << "\n";
541   }
542 }
543
544
545 // static
546 void FlagList::EnforceFlagImplications() {
547 #define FLAG_MODE_DEFINE_IMPLICATIONS
548 #include "src/flag-definitions.h"
549 #undef FLAG_MODE_DEFINE_IMPLICATIONS
550 }
551
552 } }  // namespace v8::internal