// Copyright 2006-2008 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 <errno.h>
#include <signal.h>
#include <stdio.h>

#include "src/v8.h"

#include "include/libplatform/libplatform.h"
#include "src/assembler.h"
#include "src/base/platform/platform.h"
#include "src/bootstrapper.h"
#include "src/flags.h"
#include "src/list.h"
#include "src/natives.h"
#include "src/serialize.h"


using namespace v8;

class SnapshotWriter {
 public:
  explicit SnapshotWriter(const char* snapshot_file)
      : fp_(GetFileDescriptorOrDie(snapshot_file)),
        startup_blob_file_(NULL) {}

  ~SnapshotWriter() {
    fclose(fp_);
    if (startup_blob_file_) fclose(startup_blob_file_);
  }

  void SetStartupBlobFile(const char* startup_blob_file) {
    if (startup_blob_file != NULL)
      startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file);
  }

  void WriteSnapshot(v8::StartupData blob) const {
    i::Vector<const i::byte> blob_vector(
        reinterpret_cast<const i::byte*>(blob.data), blob.raw_size);
    WriteSnapshotFile(blob_vector);
    MaybeWriteStartupBlob(blob_vector);
  }

 private:
  void MaybeWriteStartupBlob(const i::Vector<const i::byte>& blob) const {
    if (!startup_blob_file_) return;

    size_t written = fwrite(blob.begin(), 1, blob.length(), startup_blob_file_);
    if (written != static_cast<size_t>(blob.length())) {
      i::PrintF("Writing snapshot file failed.. Aborting.\n");
      exit(1);
    }
  }

  void WriteSnapshotFile(const i::Vector<const i::byte>& blob) const {
    WriteFilePrefix();
    WriteData(blob);
    WriteFileSuffix();
  }

  void WriteFilePrefix() const {
    fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n");
    fprintf(fp_, "#include \"src/v8.h\"\n");
    fprintf(fp_, "#include \"src/base/platform/platform.h\"\n\n");
    fprintf(fp_, "#include \"src/snapshot.h\"\n\n");
    fprintf(fp_, "namespace v8 {\n");
    fprintf(fp_, "namespace internal {\n\n");
  }

  void WriteFileSuffix() const {
    fprintf(fp_, "const v8::StartupData Snapshot::SnapshotBlob() {\n");
    fprintf(fp_, "  v8::StartupData blob;\n");
    fprintf(fp_, "  blob.data = reinterpret_cast<const char*>(blob_data);\n");
    fprintf(fp_, "  blob.raw_size = blob_size;\n");
    fprintf(fp_, "  return blob;\n");
    fprintf(fp_, "}\n\n");
    fprintf(fp_, "}  // namespace internal\n");
    fprintf(fp_, "}  // namespace v8\n");
  }

  void WriteData(const i::Vector<const i::byte>& blob) const {
    fprintf(fp_, "static const byte blob_data[] = {\n");
    WriteSnapshotData(blob);
    fprintf(fp_, "};\n");
    fprintf(fp_, "static const int blob_size = %d;\n", blob.length());
    fprintf(fp_, "\n");
  }

  void WriteSnapshotData(const i::Vector<const i::byte>& blob) const {
    for (int i = 0; i < blob.length(); i++) {
      if ((i & 0x1f) == 0x1f) fprintf(fp_, "\n");
      if (i > 0) fprintf(fp_, ",");
      fprintf(fp_, "%u", static_cast<unsigned char>(blob.at(i)));
    }
    fprintf(fp_, "\n");
  }

  FILE* GetFileDescriptorOrDie(const char* filename) {
    FILE* fp = base::OS::FOpen(filename, "wb");
    if (fp == NULL) {
      i::PrintF("Unable to open file \"%s\" for writing.\n", filename);
      exit(1);
    }
    return fp;
  }

  FILE* fp_;
  FILE* startup_blob_file_;
};


int main(int argc, char** argv) {
  // By default, log code create information in the snapshot.
  i::FLAG_log_code = true;

  // Omit from the snapshot natives for features that can be turned off
  // at runtime.
  i::FLAG_harmony_shipping = false;

  i::FLAG_logfile_per_isolate = false;

  // Print the usage if an error occurs when parsing the command line
  // flags or if the help flag is set.
  int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
  if (result > 0 || argc != 2 || i::FLAG_help) {
    ::printf("Usage: %s [flag] ... outfile\n", argv[0]);
    i::FlagList::PrintHelp();
    return !i::FLAG_help;
  }

  i::CpuFeatures::Probe(true);
  V8::InitializeICU();
  v8::Platform* platform = v8::platform::CreateDefaultPlatform();
  v8::V8::InitializePlatform(platform);
  v8::V8::Initialize();

  {
    SnapshotWriter writer(argv[1]);
    if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
    StartupData blob = v8::V8::CreateSnapshotDataBlob();
    CHECK(blob.data);
    writer.WriteSnapshot(blob);
    delete[] blob.data;
  }

  V8::Dispose();
  V8::ShutdownPlatform();
  delete platform;
  return 0;
}
