// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <stdio.h>  // Need fileno
#include <unistd.h>
#endif

#include <cstdio>
#include <cstring>
#include <string>
#include <vector>

#include "spirv-tools/libspirv.h"
#include "tools/io.h"
#include "tools/util/flags.h"

static const std::string kHelpText = R"(%s - Disassemble a SPIR-V binary module

Usage: %s [options] [<filename>]

The SPIR-V binary is read from <filename>. If no file is specified,
or if the filename is "-", then the binary is read from standard input.

A text-based hex stream is also accepted as binary input, which should either
consist of 32-bit words or 8-bit bytes.  The 0x or x prefix is optional, but
should be consistently present in the stream.

Options:

  -h, --help        Print this help.
  --version         Display disassembler version information.

  -o <filename>     Set the output filename.
                    Output goes to standard output if this option is
                    not specified, or if the filename is "-".

  --color           Force color output.  The default when printing to a terminal.
                    Overrides a previous --no-color option.
  --no-color        Don't print in color.  Overrides a previous --color option.
                    The default when output goes to something other than a
                    terminal (e.g. a file, a pipe, or a shell redirection).

  --no-indent       Don't indent instructions.

  --no-header       Don't output the header as leading comments.

  --raw-id          Show raw Id values instead of friendly names.

  --nested-indent   Indentation is adjusted to indicate nesting in structured
                    control flow.

  --reorder-blocks  Reorder blocks to match the structured control flow of SPIR-V.
                    With this option, the order of instructions will no longer
                    match the input binary, but the result will be more readable.

  --offsets         Show byte offsets for each instruction.

  --comment         Add comments to make reading easier

  --handle-unknown-opcodes
                    Emit unknown opcodes and unknown extended instruction
                    numbers as OpUnknown with raw integer operands instead of
                    failing. The output can be re-assembled with spirv-as.
                    Note: the ID bound in the reassembled module may be
                    incorrect if any unknown instruction defines a result ID.
)";

// clang-format off
FLAG_SHORT_bool  (h,              /* default_value= */ false, /* required= */ false);
FLAG_SHORT_string(o,              /* default_value= */ "-",   /* required= */ false);
FLAG_LONG_bool   (help,           /* default_value= */ false, /* required= */false);
FLAG_LONG_bool   (version,        /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (color,          /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (no_color,       /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (no_indent,      /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (no_header,      /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (raw_id,         /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (nested_indent,  /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (reorder_blocks, /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (offsets,        /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (comment,        /* default_value= */ false, /* required= */ false);
FLAG_LONG_bool   (handle_unknown_opcodes, /* default_value= */ false, /* required= */ false);
// clang-format on

static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_5;

int main(int, const char** argv) {
  if (!flags::Parse(argv)) {
    return 1;
  }

  if (flags::h.value() || flags::help.value()) {
    printf(kHelpText.c_str(), argv[0], argv[0]);
    return 0;
  }

  if (flags::version.value()) {
    printf("%s\n", spvSoftwareVersionDetailsString());
    printf("Target: %s\n", spvTargetEnvDescription(kDefaultEnvironment));
    return 0;
  }

  if (flags::positional_arguments.size() > 1) {
    fprintf(stderr, "error: more than one input file specified.\n");
    return 1;
  }

  const std::string inFile = flags::positional_arguments.size() == 0
                                 ? "-"
                                 : flags::positional_arguments[0];
  const std::string outFile = flags::o.value();

  bool color_is_possible =
#if SPIRV_COLOR_TERMINAL
      true;
#else
      false;
#endif

  uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE;

  if (!flags::no_indent.value()) options |= SPV_BINARY_TO_TEXT_OPTION_INDENT;

  if (flags::offsets.value())
    options |= SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET;

  if (flags::no_header.value()) options |= SPV_BINARY_TO_TEXT_OPTION_NO_HEADER;

  if (!flags::raw_id.value())
    options |= SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;

  if (flags::nested_indent.value())
    options |= SPV_BINARY_TO_TEXT_OPTION_NESTED_INDENT;

  if (flags::reorder_blocks.value())
    options |= SPV_BINARY_TO_TEXT_OPTION_REORDER_BLOCKS;

  if (flags::comment.value()) options |= SPV_BINARY_TO_TEXT_OPTION_COMMENT;

  if (flags::handle_unknown_opcodes.value())
    options |= SPV_BINARY_TO_TEXT_OPTION_HANDLE_UNKNOWN_OPCODES;

  if (flags::o.value() == "-") {
    // Print to standard output.
    options |= SPV_BINARY_TO_TEXT_OPTION_PRINT;
    if (color_is_possible && !flags::no_color.value()) {
      bool output_is_tty = true;
#if defined(_POSIX_VERSION)
      output_is_tty = isatty(fileno(stdout));
#endif
      if (output_is_tty || flags::color.value()) {
        options |= SPV_BINARY_TO_TEXT_OPTION_COLOR;
      }
    }
  }

  // Read the input binary.
  std::vector<uint32_t> contents;
  if (!ReadBinaryFile(inFile.c_str(), &contents)) return 1;

  // If printing to standard output, then spvBinaryToText should
  // do the printing.  In particular, colour printing on Windows is
  // controlled by modifying console objects synchronously while
  // outputting to the stream rather than by injecting escape codes
  // into the output stream.
  // If the printing option is off, then save the text in memory, so
  // it can be emitted later in this function.
  const bool print_to_stdout = SPV_BINARY_TO_TEXT_OPTION_PRINT & options;
  spv_text text = nullptr;
  spv_text* textOrNull = print_to_stdout ? nullptr : &text;
  spv_diagnostic diagnostic = nullptr;
  spv_context context = spvContextCreate(kDefaultEnvironment);
  spv_result_t error =
      spvBinaryToText(context, contents.data(), contents.size(), options,
                      textOrNull, &diagnostic);
  spvContextDestroy(context);
  if (error) {
    spvDiagnosticPrint(diagnostic);
    spvDiagnosticDestroy(diagnostic);
    return error;
  }

  if (!print_to_stdout) {
    if (!WriteFile<char>(outFile.c_str(), "w", text->str, text->length)) {
      spvTextDestroy(text);
      return 1;
    }
  }
  spvTextDestroy(text);

  return 0;
}
