// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <cstring>
#include <fstream>

#include "test/cctest/interpreter/bytecode-expectations-printer.h"

#include "include/libplatform/libplatform.h"
#include "include/v8.h"

#include "src/base/logging.h"
#include "src/base/smart-pointers.h"
#include "src/compiler.h"
#include "src/interpreter/interpreter.h"

using v8::internal::interpreter::BytecodeExpectationsPrinter;

namespace {

class ProgramOptions final {
 public:
  static ProgramOptions FromCommandLine(int argc, char** argv);

  ProgramOptions()
      : parsing_failed_(false),
        print_help_(false),
        read_raw_js_snippet_(false),
        read_from_stdin_(false),
        rebaseline_(false),
        wrap_(true),
        execute_(true),
        top_level_(false),
        legacy_const_(false),
        do_expressions_(false),
        const_pool_type_(
            BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}

  bool Validate() const;
  void UpdateFromHeader(std::istream& stream);   // NOLINT
  void PrintHeader(std::ostream& stream) const;  // NOLINT

  bool parsing_failed() const { return parsing_failed_; }
  bool print_help() const { return print_help_; }
  bool read_raw_js_snippet() const { return read_raw_js_snippet_; }
  bool read_from_stdin() const { return read_from_stdin_; }
  bool write_to_stdout() const {
    return output_filename_.empty() && !rebaseline_;
  }
  bool rebaseline() const { return rebaseline_; }
  bool wrap() const { return wrap_; }
  bool execute() const { return execute_; }
  bool top_level() const { return top_level_; }
  bool legacy_const() const { return legacy_const_; }
  bool do_expressions() const { return do_expressions_; }
  BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
    return const_pool_type_;
  }
  std::string input_filename() const { return input_filename_; }
  std::string output_filename() const { return output_filename_; }
  std::string test_function_name() const { return test_function_name_; }

 private:
  bool parsing_failed_;
  bool print_help_;
  bool read_raw_js_snippet_;
  bool read_from_stdin_;
  bool rebaseline_;
  bool wrap_;
  bool execute_;
  bool top_level_;
  bool legacy_const_;
  bool do_expressions_;
  BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
  std::string input_filename_;
  std::string output_filename_;
  std::string test_function_name_;
};

class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
 public:
  void* Allocate(size_t length) override {
    void* data = AllocateUninitialized(length);
    if (data != nullptr) memset(data, 0, length);
    return data;
  }
  void* AllocateUninitialized(size_t length) override { return malloc(length); }
  void Free(void* data, size_t) override { free(data); }
};

class V8InitializationScope final {
 public:
  explicit V8InitializationScope(const char* exec_path);
  ~V8InitializationScope();

  v8::Platform* platform() const { return platform_.get(); }
  v8::Isolate* isolate() const { return isolate_; }

 private:
  v8::base::SmartPointer<v8::Platform> platform_;
  v8::Isolate* isolate_;

  DISALLOW_COPY_AND_ASSIGN(V8InitializationScope);
};

BytecodeExpectationsPrinter::ConstantPoolType ParseConstantPoolType(
    const char* type_string) {
  if (strcmp(type_string, "number") == 0) {
    return BytecodeExpectationsPrinter::ConstantPoolType::kNumber;
  } else if (strcmp(type_string, "string") == 0) {
    return BytecodeExpectationsPrinter::ConstantPoolType::kString;
  } else if (strcmp(type_string, "mixed") == 0) {
    return BytecodeExpectationsPrinter::ConstantPoolType::kMixed;
  }
  return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown;
}

const char* ConstantPoolTypeToString(
    BytecodeExpectationsPrinter::ConstantPoolType type) {
  switch (type) {
    case BytecodeExpectationsPrinter::ConstantPoolType::kNumber:
      return "number";
    case BytecodeExpectationsPrinter::ConstantPoolType::kMixed:
      return "mixed";
    case BytecodeExpectationsPrinter::ConstantPoolType::kString:
      return "string";
    default:
      UNREACHABLE();
      return nullptr;
  }
}

bool ParseBoolean(const char* string) {
  if (strcmp(string, "yes") == 0) {
    return true;
  } else if (strcmp(string, "no") == 0) {
    return false;
  } else {
    UNREACHABLE();
    return false;
  }
}

const char* BooleanToString(bool value) { return value ? "yes" : "no"; }

// static
ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
  ProgramOptions options;

  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--help") == 0) {
      options.print_help_ = true;
    } else if (strcmp(argv[i], "--raw-js") == 0) {
      options.read_raw_js_snippet_ = true;
    } else if (strncmp(argv[i], "--pool-type=", 12) == 0) {
      options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12);
    } else if (strcmp(argv[i], "--stdin") == 0) {
      options.read_from_stdin_ = true;
    } else if (strcmp(argv[i], "--rebaseline") == 0) {
      options.rebaseline_ = true;
    } else if (strcmp(argv[i], "--no-wrap") == 0) {
      options.wrap_ = false;
    } else if (strcmp(argv[i], "--no-execute") == 0) {
      options.execute_ = false;
    } else if (strcmp(argv[i], "--top-level") == 0) {
      options.top_level_ = true;
    } else if (strcmp(argv[i], "--legacy-const") == 0) {
      options.legacy_const_ = true;
    } else if (strcmp(argv[i], "--do-expressions") == 0) {
      options.do_expressions_ = true;
    } else if (strncmp(argv[i], "--output=", 9) == 0) {
      options.output_filename_ = argv[i] + 9;
    } else if (strncmp(argv[i], "--test-function-name=", 21) == 0) {
      options.test_function_name_ = argv[i] + 21;
    } else if (strncmp(argv[i], "--", 2) != 0) {  // It doesn't start with --
      if (!options.input_filename_.empty()) {
        std::cerr << "ERROR: More than one input file specified\n";
        options.parsing_failed_ = true;
        break;
      }
      options.input_filename_ = argv[i];
    } else {
      std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n";
      options.parsing_failed_ = true;
      break;
    }
  }

  return options;
}

bool ProgramOptions::Validate() const {
  if (parsing_failed_) return false;
  if (print_help_) return true;

  if (const_pool_type_ ==
      BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) {
    std::cerr << "ERROR: Unknown constant pool type.\n";
    return false;
  }

  if (!read_from_stdin_ && input_filename_.empty()) {
    std::cerr << "ERROR: No input file specified.\n";
    return false;
  }

  if (read_from_stdin_ && !input_filename_.empty()) {
    std::cerr << "ERROR: Reading from stdin, but input files supplied.\n";
    return false;
  }

  if (rebaseline_ && read_raw_js_snippet_) {
    std::cerr << "ERROR: Cannot use --rebaseline on a raw JS snippet.\n";
    return false;
  }

  if (top_level_ && !test_function_name_.empty()) {
    std::cerr << "ERROR: test function name specified while processing "
                 "top level code.\n";
    return false;
  }

  return true;
}

void ProgramOptions::UpdateFromHeader(std::istream& stream) {
  std::string line;

  // Skip to the beginning of the options header
  while (std::getline(stream, line)) {
    if (line == "---") break;
  }

  while (std::getline(stream, line)) {
    if (line.compare(0, 11, "pool type: ") == 0) {
      const_pool_type_ = ParseConstantPoolType(line.c_str() + 11);
    } else if (line.compare(0, 9, "execute: ") == 0) {
      execute_ = ParseBoolean(line.c_str() + 9);
    } else if (line.compare(0, 6, "wrap: ") == 0) {
      wrap_ = ParseBoolean(line.c_str() + 6);
    } else if (line.compare(0, 20, "test function name: ") == 0) {
      test_function_name_ = line.c_str() + 20;
    } else if (line.compare(0, 11, "top level: ") == 0) {
      top_level_ = ParseBoolean(line.c_str() + 11);
    } else if (line.compare(0, 14, "legacy const: ") == 0) {
      legacy_const_ = ParseBoolean(line.c_str() + 14);
    } else if (line.compare(0, 16, "do expressions: ") == 0) {
      do_expressions_ = ParseBoolean(line.c_str() + 16);
    } else if (line == "---") {
      break;
    } else if (line.empty()) {
      continue;
    } else {
      UNREACHABLE();
      return;
    }
  }
}

void ProgramOptions::PrintHeader(std::ostream& stream) const {  // NOLINT
  stream << "---"
            "\npool type: "
         << ConstantPoolTypeToString(const_pool_type_)
         << "\nexecute: " << BooleanToString(execute_)
         << "\nwrap: " << BooleanToString(wrap_);

  if (!test_function_name_.empty()) {
    stream << "\ntest function name: " << test_function_name_;
  }

  if (top_level_) stream << "\ntop level: yes";
  if (legacy_const_) stream << "\nlegacy const: yes";
  if (do_expressions_) stream << "\ndo expressions: yes";

  stream << "\n\n";
}

V8InitializationScope::V8InitializationScope(const char* exec_path)
    : platform_(v8::platform::CreateDefaultPlatform()) {
  i::FLAG_ignition = true;
  i::FLAG_always_opt = false;
  i::FLAG_allow_natives_syntax = true;

  v8::V8::InitializeICU();
  v8::V8::InitializeExternalStartupData(exec_path);
  v8::V8::InitializePlatform(platform_.get());
  v8::V8::Initialize();

  ArrayBufferAllocator allocator;
  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = &allocator;

  isolate_ = v8::Isolate::New(create_params);
}

V8InitializationScope::~V8InitializationScope() {
  isolate_->Dispose();
  v8::V8::Dispose();
  v8::V8::ShutdownPlatform();
}

std::string ReadRawJSSnippet(std::istream& stream) {  // NOLINT
  std::stringstream body_buffer;
  CHECK(body_buffer << stream.rdbuf());
  return body_buffer.str();
}

bool ReadNextSnippet(std::istream& stream, std::string* string_out) {  // NOLINT
  std::string line;
  bool found_begin_snippet = false;
  string_out->clear();
  while (std::getline(stream, line)) {
    if (line == "snippet: \"") {
      found_begin_snippet = true;
      continue;
    }
    if (!found_begin_snippet) continue;
    if (line == "\"") return true;
    CHECK_GE(line.size(), 2u);  // We should have the indent
    string_out->append(line.begin() + 2, line.end());
    *string_out += '\n';
  }
  return false;
}

std::string UnescapeString(const std::string& escaped_string) {
  std::string unescaped_string;
  bool previous_was_backslash = false;
  for (char c : escaped_string) {
    if (previous_was_backslash) {
      // If it was not an escape sequence, emit the previous backslash
      if (c != '\\' && c != '"') unescaped_string += '\\';
      unescaped_string += c;
      previous_was_backslash = false;
    } else {
      if (c == '\\') {
        previous_was_backslash = true;
        // Defer emission to the point where we can check if it was an escape.
      } else {
        unescaped_string += c;
      }
    }
  }
  return unescaped_string;
}

void ExtractSnippets(std::vector<std::string>* snippet_list,
                     std::istream& body_stream,  // NOLINT
                     bool read_raw_js_snippet) {
  if (read_raw_js_snippet) {
    snippet_list->push_back(ReadRawJSSnippet(body_stream));
  } else {
    std::string snippet;
    while (ReadNextSnippet(body_stream, &snippet)) {
      snippet_list->push_back(UnescapeString(snippet));
    }
  }
}

void GenerateExpectationsFile(std::ostream& stream,  // NOLINT
                              const std::vector<std::string>& snippet_list,
                              const ProgramOptions& options,
                              const char* exec_path) {
  V8InitializationScope platform(exec_path);
  {
    v8::Isolate::Scope isolate_scope(platform.isolate());
    v8::HandleScope handle_scope(platform.isolate());
    v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
    v8::Context::Scope context_scope(context);

    BytecodeExpectationsPrinter printer(platform.isolate(),
                                        options.const_pool_type());
    printer.set_wrap(options.wrap());
    printer.set_execute(options.execute());
    printer.set_top_level(options.top_level());
    if (!options.test_function_name().empty()) {
      printer.set_test_function_name(options.test_function_name());
    }

    if (options.legacy_const()) i::FLAG_legacy_const = true;
    if (options.do_expressions()) i::FLAG_harmony_do_expressions = true;

    stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n";
    options.PrintHeader(stream);
    for (const std::string& snippet : snippet_list) {
      printer.PrintExpectation(stream, snippet);
    }
  }
}

void PrintUsage(const char* exec_path) {
  std::cerr
      << "\nUsage: " << exec_path
      << " [OPTIONS]... [INPUT FILE]\n\n"
         "Options:\n"
         "  --help    Print this help message.\n"
         "  --raw-js  Read raw JavaScript, instead of the output format.\n"
         "  --stdin   Read from standard input instead of file.\n"
         "  --rebaseline  Rebaseline input snippet file.\n"
         "  --no-wrap     Do not wrap the snippet in a function.\n"
         "  --no-execute  Do not execute after compilation.\n"
         "  --test-function-name=foo  "
         "Specify the name of the test function.\n"
         "  --top-level   Process top level code, not the top-level function."
         "  --legacy-const  Enable legacy_const flag.\n"
         "  --do-expressions  Enable harmony_do_expressions flag.\n"
         "  --output=file.name\n"
         "      Specify the output file. If not specified, output goes to "
         "stdout.\n"
         "  --pool-type=(int|double|string|mixed)\n"
         "      Specify the type of the entries in the constant pool "
         "(default: mixed).\n"
         "\n"
         "When using --rebaseline, flags --no-wrap, --no-execute, "
         "--test-function-name\nand --pool-type will be overridden by the "
         "options specified in the input file\nheader.\n\n"
         "Each raw JavaScript file is interpreted as a single snippet.\n\n"
         "This tool is intended as a help in writing tests.\n"
         "Please, DO NOT blindly copy and paste the output "
         "into the test suite.\n";
}

}  // namespace

int main(int argc, char** argv) {
  ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv);

  if (!options.Validate() || options.print_help()) {
    PrintUsage(argv[0]);
    return options.print_help() ? 0 : 1;
  }

  std::ifstream input_file_handle;
  if (!options.read_from_stdin()) {
    input_file_handle.open(options.input_filename().c_str());
    if (!input_file_handle.is_open()) {
      std::cerr << "ERROR: Could not open '" << options.input_filename()
                << "' for reading.\n";
      return 2;
    }
  }
  std::istream& input_stream =
      options.read_from_stdin() ? std::cin : input_file_handle;

  if (options.rebaseline()) {
    options.UpdateFromHeader(input_stream);
    CHECK(options.Validate());
  }

  std::vector<std::string> snippet_list;
  ExtractSnippets(&snippet_list, input_stream, options.read_raw_js_snippet());

  std::ofstream output_file_handle;
  if (!options.write_to_stdout()) {
    output_file_handle.open(options.rebaseline()
                                ? options.input_filename().c_str()
                                : options.output_filename().c_str());
    if (!output_file_handle.is_open()) {
      std::cerr << "ERROR: Could not open '" << options.output_filename()
                << "' for writing.\n";
      return 3;
    }
  }
  std::ostream& output_stream =
      options.write_to_stdout() ? std::cout : output_file_handle;

  GenerateExpectationsFile(output_stream, snippet_list, options, argv[0]);
}
