Move V8 to external/v8
Change-Id: If68025d67453785a651c5dfb34fad298c16676a4
diff --git a/src/flags.cc b/src/flags.cc
new file mode 100644
index 0000000..5df3afd
--- /dev/null
+++ b/src/flags.cc
@@ -0,0 +1,555 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+#include "smart-pointer.h"
+#include "string-stream.h"
+
+
+namespace v8 {
+namespace internal {
+
+// Define all of our flags.
+#define FLAG_MODE_DEFINE
+#include "flag-definitions.h"
+
+// Define all of our flags default values.
+#define FLAG_MODE_DEFINE_DEFAULTS
+#include "flag-definitions.h"
+
+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, TYPE_ARGS };
+
+ 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.
+ bool owns_ptr_; // Does the flag own its string value?
+
+ FlagType type() const { return type_; }
+
+ const char* name() const { return name_; }
+
+ const char* comment() const { return cmt_; }
+
+ bool* bool_variable() const {
+ ASSERT(type_ == TYPE_BOOL);
+ return reinterpret_cast<bool*>(valptr_);
+ }
+
+ int* int_variable() const {
+ ASSERT(type_ == TYPE_INT);
+ return reinterpret_cast<int*>(valptr_);
+ }
+
+ double* float_variable() const {
+ ASSERT(type_ == TYPE_FLOAT);
+ return reinterpret_cast<double*>(valptr_);
+ }
+
+ const char* string_value() const {
+ ASSERT(type_ == TYPE_STRING);
+ return *reinterpret_cast<const char**>(valptr_);
+ }
+
+ void set_string_value(const char* value, bool owns_ptr) {
+ ASSERT(type_ == TYPE_STRING);
+ const char** ptr = reinterpret_cast<const char**>(valptr_);
+ if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr);
+ *ptr = value;
+ owns_ptr_ = owns_ptr;
+ }
+
+ JSArguments* args_variable() const {
+ ASSERT(type_ == TYPE_ARGS);
+ return reinterpret_cast<JSArguments*>(valptr_);
+ }
+
+ bool bool_default() const {
+ ASSERT(type_ == TYPE_BOOL);
+ return *reinterpret_cast<const bool*>(defptr_);
+ }
+
+ 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_);
+ }
+
+ const char* string_default() const {
+ ASSERT(type_ == TYPE_STRING);
+ return *reinterpret_cast<const char* const *>(defptr_);
+ }
+
+ JSArguments args_default() const {
+ ASSERT(type_ == TYPE_ARGS);
+ return *reinterpret_cast<const JSArguments*>(defptr_);
+ }
+
+ // 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_value();
+ const char* str2 = string_default();
+ if (str2 == NULL) return str1 == NULL;
+ if (str1 == NULL) return str2 == NULL;
+ return strcmp(str1, str2) == 0;
+ }
+ case TYPE_ARGS:
+ return args_variable()->argc() == 0;
+ }
+ UNREACHABLE();
+ return true;
+ }
+
+ // 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:
+ set_string_value(string_default(), false);
+ break;
+ case TYPE_ARGS:
+ *args_variable() = args_default();
+ break;
+ }
+ }
+};
+
+Flag flags[] = {
+#define FLAG_MODE_META
+#include "flag-definitions.h"
+};
+
+const size_t num_flags = sizeof(flags) / sizeof(*flags);
+
+} // namespace
+
+
+static const char* Type2String(Flag::FlagType type) {
+ switch (type) {
+ case Flag::TYPE_BOOL: return "bool";
+ case Flag::TYPE_INT: return "int";
+ case Flag::TYPE_FLOAT: return "float";
+ case Flag::TYPE_STRING: return "string";
+ case Flag::TYPE_ARGS: return "arguments";
+ }
+ UNREACHABLE();
+ return NULL;
+}
+
+
+static SmartPointer<const char> ToString(Flag* flag) {
+ HeapStringAllocator string_allocator;
+ StringStream buffer(&string_allocator);
+ switch (flag->type()) {
+ case Flag::TYPE_BOOL:
+ buffer.Add("%s", (*flag->bool_variable() ? "true" : "false"));
+ break;
+ case Flag::TYPE_INT:
+ buffer.Add("%d", *flag->int_variable());
+ break;
+ case Flag::TYPE_FLOAT:
+ buffer.Add("%f", FmtElm(*flag->float_variable()));
+ break;
+ case Flag::TYPE_STRING: {
+ const char* str = flag->string_value();
+ buffer.Add("%s", str ? str : "NULL");
+ break;
+ }
+ case Flag::TYPE_ARGS: {
+ JSArguments args = *flag->args_variable();
+ if (args.argc() > 0) {
+ buffer.Add("%s", args[0]);
+ for (int i = 1; i < args.argc(); i++) {
+ buffer.Add(" %s", args[i]);
+ }
+ }
+ break;
+ }
+ }
+ return buffer.ToCString();
+}
+
+
+// static
+List<const char*>* FlagList::argv() {
+ List<const char*>* args = new List<const char*>(8);
+ Flag* args_flag = NULL;
+ for (size_t i = 0; i < num_flags; ++i) {
+ Flag* f = &flags[i];
+ if (!f->IsDefault()) {
+ if (f->type() == Flag::TYPE_ARGS) {
+ ASSERT(args_flag == NULL);
+ args_flag = f; // Must be last in arguments.
+ continue;
+ }
+ HeapStringAllocator string_allocator;
+ StringStream buffer(&string_allocator);
+ if (f->type() != Flag::TYPE_BOOL || *(f->bool_variable())) {
+ buffer.Add("--%s", f->name());
+ } else {
+ buffer.Add("--no%s", f->name());
+ }
+ args->Add(buffer.ToCString().Detach());
+ if (f->type() != Flag::TYPE_BOOL) {
+ args->Add(ToString(f).Detach());
+ }
+ }
+ }
+ if (args_flag != NULL) {
+ HeapStringAllocator string_allocator;
+ StringStream buffer(&string_allocator);
+ buffer.Add("--%s", args_flag->name());
+ args->Add(buffer.ToCString().Detach());
+ JSArguments jsargs = *args_flag->args_variable();
+ for (int j = 0; j < jsargs.argc(); j++) {
+ args->Add(StrDup(jsargs[j]));
+ }
+ }
+ return args;
+}
+
+
+// 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;
+
+ if (*arg == '-') {
+ // find the begin of the flag name
+ arg++; // remove 1st '-'
+ if (*arg == '-') {
+ arg++; // remove 2nd '-'
+ if (arg[0] == '\0') {
+ const char* kJSArgumentsFlagName = "js_arguments";
+ *name = kJSArgumentsFlagName;
+ return;
+ }
+ }
+ if (arg[0] == 'n' && arg[1] == 'o') {
+ arg += 2; // remove "no"
+ *is_bool = true;
+ }
+ *name = arg;
+
+ // find the end of the flag name
+ while (*arg != '\0' && *arg != '=')
+ arg++;
+
+ // get the value if any
+ if (*arg == '=') {
+ // make a copy so we can NUL-terminate flag name
+ int n = arg - *name;
+ CHECK(n < buffer_size); // buffer is too small
+ memcpy(buffer, *name, n);
+ buffer[n] = '\0';
+ *name = buffer;
+ // get the value
+ *value = arg + 1;
+ }
+ }
+}
+
+
+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) {
+ // parse arguments
+ for (int i = 1; i < *argc;) {
+ int j = i; // j > 0
+ const char* arg = argv[i++];
+
+ // split arg into flag components
+ char buffer[1*KB];
+ const char* name;
+ const char* value;
+ bool is_bool;
+ SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
+
+ if (name != NULL) {
+ // lookup the flag
+ Flag* flag = FindFlag(name);
+ if (flag == NULL) {
+ if (remove_flags) {
+ // We don't recognize this flag but since we're removing
+ // the flags we recognize we assume that the remaining flags
+ // will be processed somewhere else so this flag might make
+ // sense there.
+ continue;
+ } else {
+ fprintf(stderr, "Error: unrecognized flag %s\n"
+ "Try --help for options\n", arg);
+ return j;
+ }
+ }
+
+ // if we still need a flag value, use the next argument if available
+ if (flag->type() != Flag::TYPE_BOOL &&
+ flag->type() != Flag::TYPE_ARGS &&
+ value == NULL) {
+ if (i < *argc) {
+ value = argv[i++];
+ } else {
+ fprintf(stderr, "Error: missing value for flag %s of type %s\n"
+ "Try --help for options\n",
+ arg, Type2String(flag->type()));
+ return j;
+ }
+ }
+
+ // set the flag
+ char* endp = const_cast<char*>(""); // *endp is only read
+ switch (flag->type()) {
+ case Flag::TYPE_BOOL:
+ *flag->bool_variable() = !is_bool;
+ break;
+ case Flag::TYPE_INT:
+ *flag->int_variable() = strtol(value, &endp, 10); // NOLINT
+ break;
+ case Flag::TYPE_FLOAT:
+ *flag->float_variable() = strtod(value, &endp);
+ break;
+ case Flag::TYPE_STRING:
+ flag->set_string_value(value ? StrDup(value) : NULL, true);
+ break;
+ case Flag::TYPE_ARGS: {
+ int start_pos = (value == NULL) ? i : i - 1;
+ int js_argc = *argc - start_pos;
+ const char** js_argv = NewArray<const char*>(js_argc);
+ if (value != NULL) {
+ js_argv[0] = StrDup(value);
+ }
+ for (int k = i; k < *argc; k++) {
+ js_argv[k - start_pos] = StrDup(argv[k]);
+ }
+ *flag->args_variable() = JSArguments(js_argc, js_argv);
+ i = *argc; // Consume all arguments
+ break;
+ }
+ }
+
+ // handle errors
+ 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"
+ "Try --help for options\n",
+ arg, Type2String(flag->type()));
+ return j;
+ }
+
+ // remove the flag & value from the command
+ if (remove_flags) {
+ while (j < i) {
+ argv[j++] = NULL;
+ }
+ }
+ }
+ }
+
+ // shrink the argument list
+ if (remove_flags) {
+ int j = 1;
+ for (int i = 1; i < *argc; i++) {
+ if (argv[i] != NULL)
+ argv[j++] = argv[i];
+ }
+ *argc = j;
+ }
+
+ if (FLAG_help) {
+ PrintHelp();
+ exit(0);
+ }
+ // parsed all flags successfully
+ return 0;
+}
+
+
+static char* SkipWhiteSpace(char* p) {
+ while (*p != '\0' && isspace(*p) != 0) p++;
+ return p;
+}
+
+
+static char* SkipBlackSpace(char* p) {
+ while (*p != '\0' && isspace(*p) == 0) p++;
+ return p;
+}
+
+
+// static
+int FlagList::SetFlagsFromString(const char* str, int len) {
+ // make a 0-terminated copy of str
+ char* copy0 = NewArray<char>(len + 1);
+ memcpy(copy0, str, len);
+ copy0[len] = '\0';
+
+ // strip leading white space
+ char* copy = SkipWhiteSpace(copy0);
+
+ // count the number of 'arguments'
+ int argc = 1; // be compatible with SetFlagsFromCommandLine()
+ for (char* p = copy; *p != '\0'; argc++) {
+ p = SkipBlackSpace(p);
+ p = SkipWhiteSpace(p);
+ }
+
+ // allocate argument array
+ char** argv = NewArray<char*>(argc);
+
+ // split the flags string into arguments
+ argc = 1; // be compatible with SetFlagsFromCommandLine()
+ for (char* p = copy; *p != '\0'; argc++) {
+ argv[argc] = p;
+ p = SkipBlackSpace(p);
+ if (*p != '\0') *p++ = '\0'; // 0-terminate argument
+ p = SkipWhiteSpace(p);
+ }
+
+ // set the flags
+ int result = SetFlagsFromCommandLine(&argc, argv, false);
+
+ // cleanup
+ DeleteArray(argv);
+ DeleteArray(copy0);
+
+ return result;
+}
+
+
+// static
+void FlagList::ResetAllFlags() {
+ for (size_t i = 0; i < num_flags; ++i) {
+ flags[i].Reset();
+ }
+}
+
+
+// static
+void FlagList::PrintHelp() {
+ printf("Usage:\n");
+ printf(" shell [options] -e string\n");
+ printf(" execute string in V8\n");
+ printf(" shell [options] file1 file2 ... filek\n");
+ printf(" run JavaScript scripts in file1, file2, ..., filek\n");
+ printf(" shell [options]\n");
+ printf(" shell [options] --shell [file1 file2 ... filek]\n");
+ printf(" run an interactive JavaScript shell\n");
+ printf(" d8 [options] file1 file2 ... filek\n");
+ printf(" d8 [options]\n");
+ printf(" d8 [options] --shell [file1 file2 ... filek]\n");
+ printf(" run the new debugging shell\n\n");
+ printf("Options:\n");
+ for (size_t i = 0; i < num_flags; ++i) {
+ Flag* f = &flags[i];
+ SmartPointer<const char> value = ToString(f);
+ printf(" --%s (%s)\n type: %s default: %s\n",
+ f->name(), f->comment(), Type2String(f->type()), *value);
+ }
+}
+
+JSArguments::JSArguments()
+ : argc_(0), argv_(NULL) {}
+JSArguments::JSArguments(int argc, const char** argv)
+ : argc_(argc), argv_(argv) {}
+int JSArguments::argc() const { return argc_; }
+const char** JSArguments::argv() { return argv_; }
+const char*& JSArguments::operator[](int idx) { return argv_[idx]; }
+JSArguments& JSArguments::operator=(JSArguments args) {
+ argc_ = args.argc_;
+ argv_ = args.argv_;
+ return *this;
+}
+
+
+} } // namespace v8::internal