//===--- swift-demangle.cpp - Swift Demangler app -------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This is the entry point.
//
//===----------------------------------------------------------------------===//

#include "swift/Demangling/Demangle.h"
#include "swift/Demangling/ManglingMacros.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"

// For std::rand, to work around a bug if main()'s first function call passes
// argv[0].
#if defined(__CYGWIN__)
#include <cstdlib>
#endif

#include <iostream>

static llvm::cl::opt<bool>
ExpandMode("expand",
               llvm::cl::desc("Expand mode (show node structure of the demangling)"));

static llvm::cl::opt<bool>
CompactMode("compact",
          llvm::cl::desc("Compact mode (only emit the demangled names)"));

static llvm::cl::opt<bool>
TreeOnly("tree-only",
           llvm::cl::desc("Tree-only mode (do not show the demangled string)"));

static llvm::cl::opt<bool>
RemangleMode("test-remangle",
           llvm::cl::desc("Remangle test mode (show the remangled string)"));

static llvm::cl::opt<bool>
RemangleRtMode("remangle-objc-rt",
           llvm::cl::desc("Remangle to the ObjC runtime name mangling scheme"));

static llvm::cl::opt<bool>
RemangleNew("remangle-new",
           llvm::cl::desc("Remangle the symbol with new mangling scheme"));

static llvm::cl::opt<bool>
DisableSugar("no-sugar",
           llvm::cl::desc("No sugar mode (disable common language idioms such as ? and [] from the output)"));

static llvm::cl::opt<bool>
Simplified("simplified",
           llvm::cl::desc("Don't display module names or implicit self types"));

static llvm::cl::opt<bool>
Classify("classify",
           llvm::cl::desc("Display symbol classification characters"));

static llvm::cl::list<std::string>
InputNames(llvm::cl::Positional, llvm::cl::desc("[mangled name...]"),
               llvm::cl::ZeroOrMore);

static llvm::StringRef substrBefore(llvm::StringRef whole,
                                    llvm::StringRef part) {
  return whole.slice(0, part.data() - whole.data());
}

static llvm::StringRef substrAfter(llvm::StringRef whole,
                                   llvm::StringRef part) {
  return whole.substr((part.data() - whole.data()) + part.size());
}

static void demangle(llvm::raw_ostream &os, llvm::StringRef name,
                     swift::Demangle::Context &DCtx,
                     const swift::Demangle::DemangleOptions &options) {
  bool hadLeadingUnderscore = false;
  if (name.startswith("__")) {
    hadLeadingUnderscore = true;
    name = name.substr(1);
  }
  swift::Demangle::NodePointer pointer = DCtx.demangleSymbolAsNode(name);
  if (ExpandMode || TreeOnly) {
    llvm::outs() << "Demangling for " << name << '\n';
    llvm::outs() << getNodeTreeAsString(pointer);
  }
  if (RemangleMode) {
    std::string remangled;
    if (!pointer || !(name.startswith(MANGLING_PREFIX_STR) ||
                      name.startswith("_S"))) {
      // Just reprint the original mangled name if it didn't demangle or is in
      // the old mangling scheme.
      // This makes it easier to share the same database between the
      // mangling and demangling tests.
      remangled = name;
    } else {
      remangled = swift::Demangle::mangleNode(pointer);
      unsigned prefixLen = swift::Demangle::getManglingPrefixLength(remangled);
      assert(prefixLen > 0);
      // Replace the prefix if we remangled with a different prefix.
      if (!name.startswith(remangled.substr(0, prefixLen))) {
        unsigned namePrefixLen =
          swift::Demangle::getManglingPrefixLength(name);
        assert(namePrefixLen > 0);
        remangled = name.take_front(namePrefixLen).str() +
                      remangled.substr(prefixLen);
      }
      if (name != remangled) {
        llvm::errs() << "\nError: re-mangled name \n  " << remangled
                     << "\ndoes not match original name\n  " << name << '\n';
        exit(1);
      }
    }
    if (hadLeadingUnderscore) llvm::outs() << '_';
    llvm::outs() << remangled;
    return;
  } else if (RemangleRtMode) {
    std::string remangled = name;
    if (pointer) {
      remangled = swift::Demangle::mangleNodeOld(pointer);
    }
    llvm::outs() << remangled;
  }
  if (!TreeOnly) {
    if (RemangleNew) {
      if (!pointer) {
        llvm::errs() << "Can't de-mangle " << name << '\n';
        exit(1);
      }
      std::string remangled = swift::Demangle::mangleNode(pointer);
      llvm::outs() << remangled;
      return;
    }
    std::string string = swift::Demangle::nodeToString(pointer, options);
    if (!CompactMode)
      llvm::outs() << name << " ---> ";

    if (Classify) {
      std::string Classifications;
      if (!swift::Demangle::isSwiftSymbol(name))
        Classifications += 'N';
      if (DCtx.isThunkSymbol(name)) {
        if (!Classifications.empty())
          Classifications += ',';
        Classifications += "T:";
        Classifications += DCtx.getThunkTarget(name);
      } else {
        assert(DCtx.getThunkTarget(name).empty());
      }
      if (pointer && !DCtx.hasSwiftCallingConvention(name)) {
        if (!Classifications.empty())
          Classifications += ',';
        Classifications += 'C';
      }
      if (!Classifications.empty())
        llvm::outs() << '{' << Classifications << "} ";
    }
    llvm::outs() << (string.empty() ? name : llvm::StringRef(string));
  }
  DCtx.clear();
}

static int demangleSTDIN(const swift::Demangle::DemangleOptions &options) {
  // This doesn't handle Unicode symbols, but maybe that's okay.
  // Also accept the future mangling prefix.
  llvm::Regex maybeSymbol("(_T|_?\\$[Ss])[_a-zA-Z0-9$.]+");

  swift::Demangle::Context DCtx;
  for (std::string mangled; std::getline(std::cin, mangled);) {
    llvm::StringRef inputContents(mangled);

    llvm::SmallVector<llvm::StringRef, 1> matches;
    while (maybeSymbol.match(inputContents, &matches)) {
      llvm::outs() << substrBefore(inputContents, matches.front());
      demangle(llvm::outs(), matches.front(), DCtx, options);
      inputContents = substrAfter(inputContents, matches.front());
    }

    llvm::outs() << inputContents << '\n';
  }

  return EXIT_SUCCESS;
}

int main(int argc, char **argv) {
#if defined(__CYGWIN__)
  // Cygwin clang 3.5.2 with '-O3' generates CRASHING BINARY,
  // if main()'s first function call is passing argv[0].
  std::rand();
#endif
  llvm::cl::ParseCommandLineOptions(argc, argv);

  swift::Demangle::DemangleOptions options;
  options.SynthesizeSugarOnTypes = !DisableSugar;
  if (Simplified)
    options = swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions();

  if (InputNames.empty()) {
    CompactMode = true;
    return demangleSTDIN(options);
  } else {
    swift::Demangle::Context DCtx;
    for (llvm::StringRef name : InputNames) {
      if (name.startswith("S") || name.startswith("s") ) {
        std::string correctedName = std::string("$") + name.str();
        demangle(llvm::outs(), correctedName, DCtx, options);
      } else {
        demangle(llvm::outs(), name, DCtx, options);
      }
      llvm::outs() << '\n';
    }

    return EXIT_SUCCESS;
  }
}
