<commit_before>//===- TreeView.cpp - diagtool tool for printing warning flags ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This diagnostic tool
//
//===----------------------------------------------------------------------===//

#include "DiagTool.h"
#include "DiagnosticNames.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Format.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/DenseSet.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/AllDiagnostics.h"

DEF_DIAGTOOL("tree",
             "Show warning flags in a tree view",
             TreeView)

using namespace clang;
using namespace diagtool;

static void printUsage() {
  llvm::errs() << "Usage: diagtool tree [--flags-only] [<diagnostic-group>]\n";
}

static void printGroup(llvm::raw_ostream &out, const GroupRecord &Group,
                       bool FlagsOnly, unsigned Indent = 0) {
  out.indent(Indent * 2);
  out << "-W" << Group.getName() << "\n";

  ++Indent;
  for (GroupRecord::subgroup_iterator I = Group.subgroup_begin(),
                                      E = Group.subgroup_end();
       I != E; ++I) {
    printGroup(out, *I, FlagsOnly, Indent);
  }

  if (!FlagsOnly) {
    for (GroupRecord::diagnostics_iterator I = Group.diagnostics_begin(),
                                           E = Group.diagnostics_end();
         I != E; ++I) {
      out.indent(Indent * 2);
      out << I->getName() << "\n";
    }
  }
}

static int showGroup(llvm::raw_ostream &out, StringRef RootGroup,
                     bool FlagsOnly) {
  ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();

  GroupRecord Key = { RootGroup.size(), RootGroup.data(), 0, 0 };
  const GroupRecord *Found =
    std::lower_bound(AllGroups.begin(), AllGroups.end(), Key);

  if (Found == AllGroups.end() || Found->getName() != RootGroup) {
    llvm::errs() << "No such diagnostic group exists\n";
    return 1;
  }

  printGroup(out, *Found, FlagsOnly);

  return 0;
}

static int showAll(llvm::raw_ostream &out, bool FlagsOnly) {
  ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
  llvm::DenseSet<unsigned> NonRootGroupIDs;

  for (ArrayRef<GroupRecord>::iterator I = AllGroups.begin(),
                                       E = AllGroups.end();
       I != E; ++I) {
    for (GroupRecord::subgroup_iterator SI = I->subgroup_begin(),
                                        SE = I->subgroup_end();
         SI != SE; ++SI) {
      NonRootGroupIDs.insert((unsigned)SI.getID());
    }
  }

  assert(NonRootGroupIDs.size() < AllGroups.size());

  for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) {
    if (!NonRootGroupIDs.count(i))
      printGroup(out, AllGroups[i], FlagsOnly);
  }

  return 0;
}

int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
  // First check our one flag (--flags-only).
  bool FlagsOnly = false;
  if (argc > 0) {
    StringRef FirstArg(*argv);
    if (FirstArg.equals("--flags-only")) {
      FlagsOnly = true;
      --argc;
      ++argv;
    }
  }

  bool ShowAll = false;
  StringRef RootGroup;

  switch (argc) {
  case 0:
    ShowAll = true;
    break;
  case 1:
    RootGroup = argv[0];
    if (RootGroup.startswith("-W"))
      RootGroup = RootGroup.substr(2);
    if (RootGroup == "everything")
      ShowAll = true;
    // FIXME: Handle other special warning flags, like -pedantic.
    break;
  default:
    printUsage();
    return -1;
  }

  if (ShowAll)
    return showAll(out, FlagsOnly);

  return showGroup(out, RootGroup, FlagsOnly);
}

<commit_msg>Add color output to 'diagtool tree' to show what warnings are enabled by default.<commit_after>//===- TreeView.cpp - diagtool tool for printing warning flags ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This diagnostic tool
//
//===----------------------------------------------------------------------===//

#include "DiagTool.h"
#include "DiagnosticNames.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Format.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/DenseSet.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/AllDiagnostics.h"
#include "llvm/Support/Process.h"

DEF_DIAGTOOL("tree",
             "Show warning flags in a tree view",
             TreeView)

using namespace clang;
using namespace diagtool;

static void printUsage() {
  llvm::errs() << "Usage: diagtool tree [--flags-only] [<diagnostic-group>]\n";
}

static bool showColors(llvm::raw_ostream &out) {
  if (&out != &llvm::errs() && &out != &llvm::outs())
    return false;
  return llvm::errs().is_displayed() && llvm::outs().is_displayed();
}

static void setColor(bool ShowColors, llvm::raw_ostream &out,
                     llvm::raw_ostream::Colors Color) {
  if (ShowColors)
    out << llvm::sys::Process::OutputColor(Color, false, false);
}

static void resetColor(bool ShowColors, llvm::raw_ostream &out) {
  if (ShowColors)
    out << llvm::sys::Process::ResetColor();
}

static clang::DiagnosticsEngine::Level getLevel(unsigned DiagID) {
  static clang::DiagnosticsEngine Diags(new DiagnosticIDs);
  return Diags.getDiagnosticLevel(DiagID, SourceLocation());
}

static void printGroup(llvm::raw_ostream &out, const GroupRecord &Group,
                       bool FlagsOnly, unsigned Indent = 0) {
  out.indent(Indent * 2);

  bool ShowColors = showColors(out);
  setColor(ShowColors, out, llvm::raw_ostream::YELLOW);
  out << "-W" << Group.getName() << "\n";
  resetColor(ShowColors, out);

  ++Indent;
  for (GroupRecord::subgroup_iterator I = Group.subgroup_begin(),
                                      E = Group.subgroup_end();
       I != E; ++I) {
    printGroup(out, *I, FlagsOnly, Indent);
  }

  if (!FlagsOnly) {
    for (GroupRecord::diagnostics_iterator I = Group.diagnostics_begin(),
                                           E = Group.diagnostics_end();
         I != E; ++I) {
      if (ShowColors) {
        if (getLevel(I->DiagID) != DiagnosticsEngine::Ignored) {
          setColor(ShowColors, out, llvm::raw_ostream::GREEN);
        }
      }
      out.indent(Indent * 2);
      out << I->getName();
      resetColor(ShowColors, out);
      out << "\n";
    }
  }
}

static int showGroup(llvm::raw_ostream &out, StringRef RootGroup,
                     bool FlagsOnly) {
  ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();

  GroupRecord Key = { RootGroup.size(), RootGroup.data(), 0, 0 };
  const GroupRecord *Found =
    std::lower_bound(AllGroups.begin(), AllGroups.end(), Key);

  if (Found == AllGroups.end() || Found->getName() != RootGroup) {
    llvm::errs() << "No such diagnostic group exists\n";
    return 1;
  }

  printGroup(out, *Found, FlagsOnly);

  return 0;
}

static int showAll(llvm::raw_ostream &out, bool FlagsOnly) {
  ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
  llvm::DenseSet<unsigned> NonRootGroupIDs;

  for (ArrayRef<GroupRecord>::iterator I = AllGroups.begin(),
                                       E = AllGroups.end();
       I != E; ++I) {
    for (GroupRecord::subgroup_iterator SI = I->subgroup_begin(),
                                        SE = I->subgroup_end();
         SI != SE; ++SI) {
      NonRootGroupIDs.insert((unsigned)SI.getID());
    }
  }

  assert(NonRootGroupIDs.size() < AllGroups.size());

  for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) {
    if (!NonRootGroupIDs.count(i))
      printGroup(out, AllGroups[i], FlagsOnly);
  }

  return 0;
}

int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
  // First check our one flag (--flags-only).
  bool FlagsOnly = false;
  if (argc > 0) {
    StringRef FirstArg(*argv);
    if (FirstArg.equals("--flags-only")) {
      FlagsOnly = true;
      --argc;
      ++argv;
    }
  }

  bool ShowAll = false;
  StringRef RootGroup;

  switch (argc) {
  case 0:
    ShowAll = true;
    break;
  case 1:
    RootGroup = argv[0];
    if (RootGroup.startswith("-W"))
      RootGroup = RootGroup.substr(2);
    if (RootGroup == "everything")
      ShowAll = true;
    // FIXME: Handle other special warning flags, like -pedantic.
    break;
  default:
    printUsage();
    return -1;
  }

  if (showColors(out)) {
    out << '\n';
    setColor(true, out, llvm::raw_ostream::GREEN);
    out << "GREEN";
    resetColor(true, out);
    out << " = enabled by default\n\n";
  }

  if (ShowAll)
    return showAll(out, FlagsOnly);

  return showGroup(out, RootGroup, FlagsOnly);
}

<|endoftext|>


<commit_before>//===- tools/dsymutil/DebugMap.cpp - Generic debug map representation -----===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DebugMap.h"
#include "BinaryHolder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

namespace llvm {
namespace dsymutil {

using namespace llvm::object;

DebugMapObject::DebugMapObject(StringRef ObjectFilename)
    : Filename(ObjectFilename) {}

bool DebugMapObject::addSymbol(StringRef Name, uint64_t ObjectAddress,
                               uint64_t LinkedAddress, uint32_t Size) {
  auto InsertResult = Symbols.insert(
      std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));

  if (InsertResult.second)
    AddressToMapping[ObjectAddress] = &*InsertResult.first;
  return InsertResult.second;
}

void DebugMapObject::print(raw_ostream &OS) const {
  OS << getObjectFilename() << ":\n";
  // Sort the symbols in alphabetical order, like llvm-nm (and to get
  // deterministic output for testing).
  typedef std::pair<StringRef, SymbolMapping> Entry;
  std::vector<Entry> Entries;
  Entries.reserve(Symbols.getNumItems());
  for (const auto &Sym : make_range(Symbols.begin(), Symbols.end()))
    Entries.push_back(std::make_pair(Sym.getKey(), Sym.getValue()));
  std::sort(
      Entries.begin(), Entries.end(),
      [](const Entry &LHS, const Entry &RHS) { return LHS.first < RHS.first; });
  for (const auto &Sym : Entries) {
    OS << format("\t%016" PRIx64 " => %016" PRIx64 "+0x%x\t%s\n",
                 uint64_t(Sym.second.ObjectAddress),
                 uint64_t(Sym.second.BinaryAddress), uint32_t(Sym.second.Size),
                 Sym.first.data());
  }
  OS << '\n';
}

#ifndef NDEBUG
void DebugMapObject::dump() const { print(errs()); }
#endif

DebugMapObject &DebugMap::addDebugMapObject(StringRef ObjectFilePath) {
  Objects.emplace_back(new DebugMapObject(ObjectFilePath));
  return *Objects.back();
}

const DebugMapObject::DebugMapEntry *
DebugMapObject::lookupSymbol(StringRef SymbolName) const {
  StringMap<SymbolMapping>::const_iterator Sym = Symbols.find(SymbolName);
  if (Sym == Symbols.end())
    return nullptr;
  return &*Sym;
}

const DebugMapObject::DebugMapEntry *
DebugMapObject::lookupObjectAddress(uint64_t Address) const {
  auto Mapping = AddressToMapping.find(Address);
  if (Mapping == AddressToMapping.end())
    return nullptr;
  return Mapping->getSecond();
}

void DebugMap::print(raw_ostream &OS) const {
  yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0);
  yout << const_cast<DebugMap &>(*this);
}

#ifndef NDEBUG
void DebugMap::dump() const { print(errs()); }
#endif

namespace {
struct YAMLContext {
  StringRef PrependPath;
  Triple Triple;
};
}

ErrorOr<std::unique_ptr<DebugMap>>
DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
                            bool Verbose) {
  auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
  if (auto Err = ErrOrFile.getError())
    return Err;

  YAMLContext Ctxt;

  Ctxt.PrependPath = PrependPath;

  std::unique_ptr<DebugMap> Res;
  yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
  yin >> Res;

  if (auto EC = yin.error())
    return EC;

  return std::move(Res);
}
}

namespace yaml {

// Normalize/Denormalize between YAML and a DebugMapObject.
struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO {
  YamlDMO(IO &io) {}
  YamlDMO(IO &io, dsymutil::DebugMapObject &Obj);
  dsymutil::DebugMapObject denormalize(IO &IO);

  std::string Filename;
  std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
};

void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
    mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
  io.mapRequired("sym", s.first);
  io.mapRequired("objAddr", s.second.ObjectAddress);
  io.mapRequired("binAddr", s.second.BinaryAddress);
  io.mapOptional("size", s.second.Size);
}

void MappingTraits<dsymutil::DebugMapObject>::mapping(
    IO &io, dsymutil::DebugMapObject &DMO) {
  MappingNormalization<YamlDMO, dsymutil::DebugMapObject> Norm(io, DMO);
  io.mapRequired("filename", Norm->Filename);
  io.mapRequired("symbols", Norm->Entries);
}

void ScalarTraits<Triple>::output(const Triple &val, void *,
                                  llvm::raw_ostream &out) {
  out << val.str();
}

StringRef ScalarTraits<Triple>::input(StringRef scalar, void *, Triple &value) {
  value = Triple(scalar);
  return StringRef();
}

size_t
SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::size(
    IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) {
  return seq.size();
}

dsymutil::DebugMapObject &
SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element(
    IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
    size_t index) {
  if (index >= seq.size()) {
    seq.resize(index + 1);
    seq[index].reset(new dsymutil::DebugMapObject);
  }
  return *seq[index];
}

void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
                                                dsymutil::DebugMap &DM) {
  io.mapRequired("triple", DM.BinaryTriple);
  io.mapOptional("objects", DM.Objects);
  if (void *Ctxt = io.getContext())
    reinterpret_cast<YAMLContext *>(Ctxt)->Triple = DM.BinaryTriple;
}

void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
    IO &io, std::unique_ptr<dsymutil::DebugMap> &DM) {
  if (!DM)
    DM.reset(new DebugMap());
  io.mapRequired("triple", DM->BinaryTriple);
  io.mapOptional("objects", DM->Objects);
  if (void *Ctxt = io.getContext())
    reinterpret_cast<YAMLContext *>(Ctxt)->Triple = DM->BinaryTriple;
}

MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
    IO &io, dsymutil::DebugMapObject &Obj) {
  Filename = Obj.Filename;
  Entries.reserve(Obj.Symbols.size());
  for (auto &Entry : Obj.Symbols)
    Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue()));
}

dsymutil::DebugMapObject
MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
  BinaryHolder BinHolder(/* Verbose =*/false);
  const auto &Ctxt = *reinterpret_cast<YAMLContext *>(IO.getContext());
  SmallString<80> Path(Ctxt.PrependPath);
  StringMap<uint64_t> SymbolAddresses;

  sys::path::append(Path, Filename);
  auto ErrOrObjectFile = BinHolder.GetObjectFile(Path);
  if (auto EC = ErrOrObjectFile.getError()) {
    llvm::errs() << "warning: Unable to open " << Path << " " << EC.message()
                 << '\n';
  } else {
    // Rewrite the object file symbol addresses in the debug map. The
    // YAML input is mainly used to test llvm-dsymutil without
    // requiring binaries checked-in. If we generate the object files
    // during the test, we can't hardcode the symbols addresses, so
    // look them up here and rewrite them.
    for (const auto &Sym : ErrOrObjectFile->symbols()) {
      StringRef Name;
      uint64_t Address;
      if (Sym.getName(Name) || Sym.getAddress(Address))
        continue;
      SymbolAddresses[Name] = Address;
    }
  }

  dsymutil::DebugMapObject Res(Path);
  for (auto &Entry : Entries) {
    auto &Mapping = Entry.second;
    uint64_t ObjAddress = Mapping.ObjectAddress;
    auto AddressIt = SymbolAddresses.find(Entry.first);
    if (AddressIt != SymbolAddresses.end())
      ObjAddress = AddressIt->getValue();
    Res.addSymbol(Entry.first, ObjAddress, Mapping.BinaryAddress, Mapping.Size);
  }
  return Res;
}
}
}
<commit_msg>[dsymutil] Rename a variable to appease some bots.<commit_after>//===- tools/dsymutil/DebugMap.cpp - Generic debug map representation -----===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DebugMap.h"
#include "BinaryHolder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

namespace llvm {
namespace dsymutil {

using namespace llvm::object;

DebugMapObject::DebugMapObject(StringRef ObjectFilename)
    : Filename(ObjectFilename) {}

bool DebugMapObject::addSymbol(StringRef Name, uint64_t ObjectAddress,
                               uint64_t LinkedAddress, uint32_t Size) {
  auto InsertResult = Symbols.insert(
      std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));

  if (InsertResult.second)
    AddressToMapping[ObjectAddress] = &*InsertResult.first;
  return InsertResult.second;
}

void DebugMapObject::print(raw_ostream &OS) const {
  OS << getObjectFilename() << ":\n";
  // Sort the symbols in alphabetical order, like llvm-nm (and to get
  // deterministic output for testing).
  typedef std::pair<StringRef, SymbolMapping> Entry;
  std::vector<Entry> Entries;
  Entries.reserve(Symbols.getNumItems());
  for (const auto &Sym : make_range(Symbols.begin(), Symbols.end()))
    Entries.push_back(std::make_pair(Sym.getKey(), Sym.getValue()));
  std::sort(
      Entries.begin(), Entries.end(),
      [](const Entry &LHS, const Entry &RHS) { return LHS.first < RHS.first; });
  for (const auto &Sym : Entries) {
    OS << format("\t%016" PRIx64 " => %016" PRIx64 "+0x%x\t%s\n",
                 uint64_t(Sym.second.ObjectAddress),
                 uint64_t(Sym.second.BinaryAddress), uint32_t(Sym.second.Size),
                 Sym.first.data());
  }
  OS << '\n';
}

#ifndef NDEBUG
void DebugMapObject::dump() const { print(errs()); }
#endif

DebugMapObject &DebugMap::addDebugMapObject(StringRef ObjectFilePath) {
  Objects.emplace_back(new DebugMapObject(ObjectFilePath));
  return *Objects.back();
}

const DebugMapObject::DebugMapEntry *
DebugMapObject::lookupSymbol(StringRef SymbolName) const {
  StringMap<SymbolMapping>::const_iterator Sym = Symbols.find(SymbolName);
  if (Sym == Symbols.end())
    return nullptr;
  return &*Sym;
}

const DebugMapObject::DebugMapEntry *
DebugMapObject::lookupObjectAddress(uint64_t Address) const {
  auto Mapping = AddressToMapping.find(Address);
  if (Mapping == AddressToMapping.end())
    return nullptr;
  return Mapping->getSecond();
}

void DebugMap::print(raw_ostream &OS) const {
  yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0);
  yout << const_cast<DebugMap &>(*this);
}

#ifndef NDEBUG
void DebugMap::dump() const { print(errs()); }
#endif

namespace {
struct YAMLContext {
  StringRef PrependPath;
  Triple BinaryTriple;
};
}

ErrorOr<std::unique_ptr<DebugMap>>
DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
                            bool Verbose) {
  auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
  if (auto Err = ErrOrFile.getError())
    return Err;

  YAMLContext Ctxt;

  Ctxt.PrependPath = PrependPath;

  std::unique_ptr<DebugMap> Res;
  yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
  yin >> Res;

  if (auto EC = yin.error())
    return EC;

  return std::move(Res);
}
}

namespace yaml {

// Normalize/Denormalize between YAML and a DebugMapObject.
struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO {
  YamlDMO(IO &io) {}
  YamlDMO(IO &io, dsymutil::DebugMapObject &Obj);
  dsymutil::DebugMapObject denormalize(IO &IO);

  std::string Filename;
  std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
};

void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
    mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
  io.mapRequired("sym", s.first);
  io.mapRequired("objAddr", s.second.ObjectAddress);
  io.mapRequired("binAddr", s.second.BinaryAddress);
  io.mapOptional("size", s.second.Size);
}

void MappingTraits<dsymutil::DebugMapObject>::mapping(
    IO &io, dsymutil::DebugMapObject &DMO) {
  MappingNormalization<YamlDMO, dsymutil::DebugMapObject> Norm(io, DMO);
  io.mapRequired("filename", Norm->Filename);
  io.mapRequired("symbols", Norm->Entries);
}

void ScalarTraits<Triple>::output(const Triple &val, void *,
                                  llvm::raw_ostream &out) {
  out << val.str();
}

StringRef ScalarTraits<Triple>::input(StringRef scalar, void *, Triple &value) {
  value = Triple(scalar);
  return StringRef();
}

size_t
SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::size(
    IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) {
  return seq.size();
}

dsymutil::DebugMapObject &
SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element(
    IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
    size_t index) {
  if (index >= seq.size()) {
    seq.resize(index + 1);
    seq[index].reset(new dsymutil::DebugMapObject);
  }
  return *seq[index];
}

void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
                                                dsymutil::DebugMap &DM) {
  io.mapRequired("triple", DM.BinaryTriple);
  io.mapOptional("objects", DM.Objects);
  if (void *Ctxt = io.getContext())
    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM.BinaryTriple;
}

void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
    IO &io, std::unique_ptr<dsymutil::DebugMap> &DM) {
  if (!DM)
    DM.reset(new DebugMap());
  io.mapRequired("triple", DM->BinaryTriple);
  io.mapOptional("objects", DM->Objects);
  if (void *Ctxt = io.getContext())
    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple;
}

MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
    IO &io, dsymutil::DebugMapObject &Obj) {
  Filename = Obj.Filename;
  Entries.reserve(Obj.Symbols.size());
  for (auto &Entry : Obj.Symbols)
    Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue()));
}

dsymutil::DebugMapObject
MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
  BinaryHolder BinHolder(/* Verbose =*/false);
  const auto &Ctxt = *reinterpret_cast<YAMLContext *>(IO.getContext());
  SmallString<80> Path(Ctxt.PrependPath);
  StringMap<uint64_t> SymbolAddresses;

  sys::path::append(Path, Filename);
  auto ErrOrObjectFile = BinHolder.GetObjectFile(Path);
  if (auto EC = ErrOrObjectFile.getError()) {
    llvm::errs() << "warning: Unable to open " << Path << " " << EC.message()
                 << '\n';
  } else {
    // Rewrite the object file symbol addresses in the debug map. The
    // YAML input is mainly used to test llvm-dsymutil without
    // requiring binaries checked-in. If we generate the object files
    // during the test, we can't hardcode the symbols addresses, so
    // look them up here and rewrite them.
    for (const auto &Sym : ErrOrObjectFile->symbols()) {
      StringRef Name;
      uint64_t Address;
      if (Sym.getName(Name) || Sym.getAddress(Address))
        continue;
      SymbolAddresses[Name] = Address;
    }
  }

  dsymutil::DebugMapObject Res(Path);
  for (auto &Entry : Entries) {
    auto &Mapping = Entry.second;
    uint64_t ObjAddress = Mapping.ObjectAddress;
    auto AddressIt = SymbolAddresses.find(Entry.first);
    if (AddressIt != SymbolAddresses.end())
      ObjAddress = AddressIt->getValue();
    Res.addSymbol(Entry.first, ObjAddress, Mapping.BinaryAddress, Mapping.Size);
  }
  return Res;
}
}
}
<|endoftext|>


<commit_before>//===-EDDisassembler.cpp - LLVM Enhanced Disassembler ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Enhanced Disassembly library's  disassembler class.
// The disassembler is responsible for vending individual instructions according
// to a given architecture and disassembly syntax.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/MC/MCParser/AsmParser.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Target/TargetAsmLexer.h"
#include "llvm/Target/TargetAsmParser.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSelect.h"

#include "EDDisassembler.h"
#include "EDInst.h"

#include "../../lib/Target/X86/X86GenEDInfo.inc"

using namespace llvm;

bool EDDisassembler::sInitialized = false;
EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers;

struct InfoMap {
  Triple::ArchType Arch;
  const char *String;
  const InstInfo *Info;
};

static struct InfoMap infomap[] = {
  { Triple::x86,          "i386-unknown-unknown",   instInfoX86 },
  { Triple::x86_64,       "x86_64-unknown-unknown", instInfoX86 },
  { Triple::InvalidArch,  NULL,                     NULL        }
};

/// infoFromArch - Returns the InfoMap corresponding to a given architecture,
///   or NULL if there is an error
///
/// @arg arch - The Triple::ArchType for the desired architecture
static const InfoMap *infoFromArch(Triple::ArchType arch) {
  unsigned int infoIndex;

  for (infoIndex = 0; infomap[infoIndex].String != NULL; ++infoIndex) {
    if(arch == infomap[infoIndex].Arch)
      return &infomap[infoIndex];
  }

  return NULL;
}

/// getLLVMSyntaxVariant - gets the constant to use to get an assembly printer
///   for the desired assembly syntax, suitable for passing to
///   Target::createMCInstPrinter()
///
/// @arg arch   - The target architecture
/// @arg syntax - The assembly syntax in sd form
static int getLLVMSyntaxVariant(Triple::ArchType arch,
                                EDAssemblySyntax_t syntax) {
  switch (syntax) {
  default:
    return -1;
  // Mappings below from X86AsmPrinter.cpp
  case kEDAssemblySyntaxX86ATT:
    if (arch == Triple::x86 || arch == Triple::x86_64)
      return 0;
    else
      return -1;
  case kEDAssemblySyntaxX86Intel:
    if (arch == Triple::x86 || arch == Triple::x86_64)
      return 1;
    else
      return -1;
  }
}

#define BRINGUP_TARGET(tgt)           \
  LLVMInitialize##tgt##TargetInfo();  \
  LLVMInitialize##tgt##Target();      \
  LLVMInitialize##tgt##AsmPrinter();  \
  LLVMInitialize##tgt##AsmParser();   \
  LLVMInitialize##tgt##Disassembler();

void EDDisassembler::initialize() {
  if (sInitialized)
    return;

  sInitialized = true;

  BRINGUP_TARGET(X86)
}

#undef BRINGUP_TARGET

EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch,
                                                EDAssemblySyntax_t syntax) {
  CPUKey key;
  key.Arch = arch;
  key.Syntax = syntax;

  EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key);

  if (i != sDisassemblers.end()) {
    return i->second;
  }
  else {
    EDDisassembler* sdd = new EDDisassembler(key);
    if(!sdd->valid()) {
      delete sdd;
      return NULL;
    }

    sDisassemblers[key] = sdd;

    return sdd;
  }

  return NULL;
}

EDDisassembler *EDDisassembler::getDisassembler(StringRef str,
                                                EDAssemblySyntax_t syntax) {
  Triple triple(str);

  return getDisassembler(triple.getArch(), syntax);
}

namespace {
  class EDAsmParser : public MCAsmParser {
    AsmLexer Lexer;
    MCContext Context;
    OwningPtr<MCStreamer> Streamer;
  public:
    // Mandatory functions
    EDAsmParser(const MCAsmInfo &MAI) : Lexer(MAI) {
      Streamer.reset(createNullStreamer(Context));
    }
    virtual ~EDAsmParser() { }
    MCAsmLexer &getLexer() { return Lexer; }
    MCContext &getContext() { return Context; }
    MCStreamer &getStreamer() { return *Streamer; }
    void Warning(SMLoc L, const Twine &Msg) { }
    bool Error(SMLoc L, const Twine &Msg) { return true; }
    const AsmToken &Lex() { return Lexer.Lex(); }
    bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
      AsmToken token = Lex();
      if(token.isNot(AsmToken::Integer))
        return true;
      Res = MCConstantExpr::Create(token.getIntVal(), Context);
      return false;
    }
    bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
      assert(0 && "I can't ParseParenExpression()s!");
    }
    bool ParseAbsoluteExpression(int64_t &Res) {
      assert(0 && "I can't ParseAbsoluteExpression()s!");
    }

    /// setBuffer - loads a buffer into the parser
    /// @arg buf  - The buffer to read tokens from
    void setBuffer(const MemoryBuffer &buf) { Lexer.setBuffer(&buf); }
    /// parseInstName - When the lexer is positioned befor an instruction
    ///   name (with possible intervening whitespace), reads past the name,
    ///   returning 0 on success and -1 on failure
    /// @arg name - A reference to a string that is filled in with the
    ///             instruction name
    /// @arg loc  - A reference to a location that is filled in with the
    ///             position of the instruction name
    int parseInstName(StringRef &name, SMLoc &loc) {
      AsmToken tok = Lexer.Lex();
      if(tok.isNot(AsmToken::Identifier)) {
        return -1;
      }
      name = tok.getString();
      loc = tok.getLoc();
      return 0;
    }
  };
}

EDDisassembler::EDDisassembler(CPUKey &key) :
  Valid(false), ErrorString(), ErrorStream(ErrorString), Key(key) {
  const InfoMap *infoMap = infoFromArch(key.Arch);

  if (!infoMap)
    return;

  const char *triple = infoMap->String;

  int syntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax);

  if (syntaxVariant < 0)
    return;

  std::string tripleString(triple);
  std::string errorString;

  Tgt = TargetRegistry::lookupTarget(tripleString,
                                     errorString);

  if (!Tgt)
    return;

  std::string featureString;

  OwningPtr<const TargetMachine>
    targetMachine(Tgt->createTargetMachine(tripleString,
                                           featureString));

  const TargetRegisterInfo *registerInfo = targetMachine->getRegisterInfo();

  if (!registerInfo)
    return;

  AsmInfo.reset(Tgt->createAsmInfo(tripleString));

  if (!AsmInfo)
    return;

  Disassembler.reset(Tgt->createMCDisassembler());

  if (!Disassembler)
    return;

  InstString.reset(new std::string);
  InstStream.reset(new raw_string_ostream(*InstString));

  InstPrinter.reset(Tgt->createMCInstPrinter(syntaxVariant,
                                                *AsmInfo,
                                                *InstStream));

  if (!InstPrinter)
    return;

  GenericAsmLexer.reset(new AsmLexer(*AsmInfo));
  SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo));
  SpecificAsmLexer->InstallLexer(*GenericAsmLexer);

  InstInfos = infoMap->Info;

  Valid = true;
}

EDDisassembler::~EDDisassembler() {
  if(!valid())
    return;
}

namespace {
  /// EDMemoryObject - a subclass of MemoryObject that allows use of a callback
  ///   as provided by the sd interface.  See MemoryObject.
  class EDMemoryObject : public llvm::MemoryObject {
  private:
    EDByteReaderCallback Callback;
    void *Arg;
  public:
    EDMemoryObject(EDByteReaderCallback callback,
                   void *arg) : Callback(callback), Arg(arg) { }
    ~EDMemoryObject() { }
    uint64_t getBase() const { return 0x0; }
    uint64_t getExtent() const { return (uint64_t)-1; }
    int readByte(uint64_t address, uint8_t *ptr) const {
      if(!Callback)
        return -1;

      if(Callback(ptr, address, Arg))
        return -1;

      return 0;
    }
  };
}

EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader,
                                   uint64_t address,
                                   void *arg) {
  EDMemoryObject memoryObject(byteReader, arg);

  MCInst* inst = new MCInst;
  uint64_t byteSize;

  if (!Disassembler->getInstruction(*inst,
                                    byteSize,
                                    memoryObject,
                                    address,
                                    ErrorStream)) {
    delete inst;
    return NULL;
  }
  else {
    const InstInfo *thisInstInfo = &InstInfos[inst->getOpcode()];

    EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
    return sdInst;
  }
}

void EDDisassembler::initMaps(const TargetRegisterInfo &registerInfo) {
  unsigned numRegisters = registerInfo.getNumRegs();
  unsigned registerIndex;

  for (registerIndex = 0; registerIndex < numRegisters; ++registerIndex) {
    const char* registerName = registerInfo.get(registerIndex).Name;

    RegVec.push_back(registerName);
    RegRMap[registerName] = registerIndex;
  }

  if (Key.Arch == Triple::x86 ||
      Key.Arch == Triple::x86_64) {
    stackPointers.insert(registerIDWithName("SP"));
    stackPointers.insert(registerIDWithName("ESP"));
    stackPointers.insert(registerIDWithName("RSP"));

    programCounters.insert(registerIDWithName("IP"));
    programCounters.insert(registerIDWithName("EIP"));
    programCounters.insert(registerIDWithName("RIP"));
  }
}

const char *EDDisassembler::nameWithRegisterID(unsigned registerID) const {
  if (registerID >= RegVec.size())
    return NULL;
  else
    return RegVec[registerID].c_str();
}

unsigned EDDisassembler::registerIDWithName(const char *name) const {
  regrmap_t::const_iterator iter = RegRMap.find(std::string(name));
  if (iter == RegRMap.end())
    return 0;
  else
    return (*iter).second;
}

bool EDDisassembler::registerIsStackPointer(unsigned registerID) {
  return (stackPointers.find(registerID) != stackPointers.end());
}

bool EDDisassembler::registerIsProgramCounter(unsigned registerID) {
  return (programCounters.find(registerID) != programCounters.end());
}

int EDDisassembler::printInst(std::string& str,
                              MCInst& inst) {
  PrinterMutex.acquire();

  InstPrinter->printInst(&inst);
  InstStream->flush();
  str = *InstString;
  InstString->clear();

  PrinterMutex.release();

  return 0;
}

int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
                              SmallVectorImpl<AsmToken> &tokens,
                              const std::string &str) {
  int ret = 0;

  const char *cStr = str.c_str();
  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr));

  StringRef instName;
  SMLoc instLoc;

  SourceMgr sourceMgr;
  sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
  MCContext context;
  OwningPtr<MCStreamer> streamer
    (createNullStreamer(context));
  AsmParser genericParser(sourceMgr, context, *streamer, *AsmInfo);
  OwningPtr<TargetAsmParser> specificParser
    (Tgt->createAsmParser(genericParser));

  AsmToken OpcodeToken = genericParser.Lex();

  if(OpcodeToken.is(AsmToken::Identifier)) {
    instName = OpcodeToken.getString();
    instLoc = OpcodeToken.getLoc();
    if (specificParser->ParseInstruction(instName, instLoc, operands))
      ret = -1;
  }
  else {
    ret = -1;
  }

  SmallVectorImpl<MCParsedAsmOperand*>::iterator oi;

  for(oi = operands.begin(); oi != operands.end(); ++oi) {
    printf("Operand start %p, end %p\n",
           (*oi)->getStartLoc().getPointer(),
           (*oi)->getEndLoc().getPointer());
  }

  ParserMutex.acquire();

  if (!ret) {
    GenericAsmLexer->setBuffer(buf);

    while (SpecificAsmLexer->Lex(),
           SpecificAsmLexer->isNot(AsmToken::Eof) &&
           SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) {
      if (SpecificAsmLexer->is(AsmToken::Error)) {
        ret = -1;
        break;
      }
      tokens.push_back(SpecificAsmLexer->getTok());
    }
  }

  ParserMutex.release();

  return ret;
}

int EDDisassembler::llvmSyntaxVariant() const {
  return LLVMSyntaxVariant;
}
<commit_msg>Whoops, left some debugging code in that broke a buildbot.  Removed.<commit_after>//===-EDDisassembler.cpp - LLVM Enhanced Disassembler ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Enhanced Disassembly library's  disassembler class.
// The disassembler is responsible for vending individual instructions according
// to a given architecture and disassembly syntax.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/MC/MCParser/AsmParser.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Target/TargetAsmLexer.h"
#include "llvm/Target/TargetAsmParser.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSelect.h"

#include "EDDisassembler.h"
#include "EDInst.h"

#include "../../lib/Target/X86/X86GenEDInfo.inc"

using namespace llvm;

bool EDDisassembler::sInitialized = false;
EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers;

struct InfoMap {
  Triple::ArchType Arch;
  const char *String;
  const InstInfo *Info;
};

static struct InfoMap infomap[] = {
  { Triple::x86,          "i386-unknown-unknown",   instInfoX86 },
  { Triple::x86_64,       "x86_64-unknown-unknown", instInfoX86 },
  { Triple::InvalidArch,  NULL,                     NULL        }
};

/// infoFromArch - Returns the InfoMap corresponding to a given architecture,
///   or NULL if there is an error
///
/// @arg arch - The Triple::ArchType for the desired architecture
static const InfoMap *infoFromArch(Triple::ArchType arch) {
  unsigned int infoIndex;

  for (infoIndex = 0; infomap[infoIndex].String != NULL; ++infoIndex) {
    if(arch == infomap[infoIndex].Arch)
      return &infomap[infoIndex];
  }

  return NULL;
}

/// getLLVMSyntaxVariant - gets the constant to use to get an assembly printer
///   for the desired assembly syntax, suitable for passing to
///   Target::createMCInstPrinter()
///
/// @arg arch   - The target architecture
/// @arg syntax - The assembly syntax in sd form
static int getLLVMSyntaxVariant(Triple::ArchType arch,
                                EDAssemblySyntax_t syntax) {
  switch (syntax) {
  default:
    return -1;
  // Mappings below from X86AsmPrinter.cpp
  case kEDAssemblySyntaxX86ATT:
    if (arch == Triple::x86 || arch == Triple::x86_64)
      return 0;
    else
      return -1;
  case kEDAssemblySyntaxX86Intel:
    if (arch == Triple::x86 || arch == Triple::x86_64)
      return 1;
    else
      return -1;
  }
}

#define BRINGUP_TARGET(tgt)           \
  LLVMInitialize##tgt##TargetInfo();  \
  LLVMInitialize##tgt##Target();      \
  LLVMInitialize##tgt##AsmPrinter();  \
  LLVMInitialize##tgt##AsmParser();   \
  LLVMInitialize##tgt##Disassembler();

void EDDisassembler::initialize() {
  if (sInitialized)
    return;

  sInitialized = true;

  BRINGUP_TARGET(X86)
}

#undef BRINGUP_TARGET

EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch,
                                                EDAssemblySyntax_t syntax) {
  CPUKey key;
  key.Arch = arch;
  key.Syntax = syntax;

  EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key);

  if (i != sDisassemblers.end()) {
    return i->second;
  }
  else {
    EDDisassembler* sdd = new EDDisassembler(key);
    if(!sdd->valid()) {
      delete sdd;
      return NULL;
    }

    sDisassemblers[key] = sdd;

    return sdd;
  }

  return NULL;
}

EDDisassembler *EDDisassembler::getDisassembler(StringRef str,
                                                EDAssemblySyntax_t syntax) {
  Triple triple(str);

  return getDisassembler(triple.getArch(), syntax);
}

namespace {
  class EDAsmParser : public MCAsmParser {
    AsmLexer Lexer;
    MCContext Context;
    OwningPtr<MCStreamer> Streamer;
  public:
    // Mandatory functions
    EDAsmParser(const MCAsmInfo &MAI) : Lexer(MAI) {
      Streamer.reset(createNullStreamer(Context));
    }
    virtual ~EDAsmParser() { }
    MCAsmLexer &getLexer() { return Lexer; }
    MCContext &getContext() { return Context; }
    MCStreamer &getStreamer() { return *Streamer; }
    void Warning(SMLoc L, const Twine &Msg) { }
    bool Error(SMLoc L, const Twine &Msg) { return true; }
    const AsmToken &Lex() { return Lexer.Lex(); }
    bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
      AsmToken token = Lex();
      if(token.isNot(AsmToken::Integer))
        return true;
      Res = MCConstantExpr::Create(token.getIntVal(), Context);
      return false;
    }
    bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
      assert(0 && "I can't ParseParenExpression()s!");
    }
    bool ParseAbsoluteExpression(int64_t &Res) {
      assert(0 && "I can't ParseAbsoluteExpression()s!");
    }

    /// setBuffer - loads a buffer into the parser
    /// @arg buf  - The buffer to read tokens from
    void setBuffer(const MemoryBuffer &buf) { Lexer.setBuffer(&buf); }
    /// parseInstName - When the lexer is positioned befor an instruction
    ///   name (with possible intervening whitespace), reads past the name,
    ///   returning 0 on success and -1 on failure
    /// @arg name - A reference to a string that is filled in with the
    ///             instruction name
    /// @arg loc  - A reference to a location that is filled in with the
    ///             position of the instruction name
    int parseInstName(StringRef &name, SMLoc &loc) {
      AsmToken tok = Lexer.Lex();
      if(tok.isNot(AsmToken::Identifier)) {
        return -1;
      }
      name = tok.getString();
      loc = tok.getLoc();
      return 0;
    }
  };
}

EDDisassembler::EDDisassembler(CPUKey &key) :
  Valid(false), ErrorString(), ErrorStream(ErrorString), Key(key) {
  const InfoMap *infoMap = infoFromArch(key.Arch);

  if (!infoMap)
    return;

  const char *triple = infoMap->String;

  int syntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax);

  if (syntaxVariant < 0)
    return;

  std::string tripleString(triple);
  std::string errorString;

  Tgt = TargetRegistry::lookupTarget(tripleString,
                                     errorString);

  if (!Tgt)
    return;

  std::string featureString;

  OwningPtr<const TargetMachine>
    targetMachine(Tgt->createTargetMachine(tripleString,
                                           featureString));

  const TargetRegisterInfo *registerInfo = targetMachine->getRegisterInfo();

  if (!registerInfo)
    return;

  AsmInfo.reset(Tgt->createAsmInfo(tripleString));

  if (!AsmInfo)
    return;

  Disassembler.reset(Tgt->createMCDisassembler());

  if (!Disassembler)
    return;

  InstString.reset(new std::string);
  InstStream.reset(new raw_string_ostream(*InstString));

  InstPrinter.reset(Tgt->createMCInstPrinter(syntaxVariant,
                                                *AsmInfo,
                                                *InstStream));

  if (!InstPrinter)
    return;

  GenericAsmLexer.reset(new AsmLexer(*AsmInfo));
  SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo));
  SpecificAsmLexer->InstallLexer(*GenericAsmLexer);

  InstInfos = infoMap->Info;

  Valid = true;
}

EDDisassembler::~EDDisassembler() {
  if(!valid())
    return;
}

namespace {
  /// EDMemoryObject - a subclass of MemoryObject that allows use of a callback
  ///   as provided by the sd interface.  See MemoryObject.
  class EDMemoryObject : public llvm::MemoryObject {
  private:
    EDByteReaderCallback Callback;
    void *Arg;
  public:
    EDMemoryObject(EDByteReaderCallback callback,
                   void *arg) : Callback(callback), Arg(arg) { }
    ~EDMemoryObject() { }
    uint64_t getBase() const { return 0x0; }
    uint64_t getExtent() const { return (uint64_t)-1; }
    int readByte(uint64_t address, uint8_t *ptr) const {
      if(!Callback)
        return -1;

      if(Callback(ptr, address, Arg))
        return -1;

      return 0;
    }
  };
}

EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader,
                                   uint64_t address,
                                   void *arg) {
  EDMemoryObject memoryObject(byteReader, arg);

  MCInst* inst = new MCInst;
  uint64_t byteSize;

  if (!Disassembler->getInstruction(*inst,
                                    byteSize,
                                    memoryObject,
                                    address,
                                    ErrorStream)) {
    delete inst;
    return NULL;
  }
  else {
    const InstInfo *thisInstInfo = &InstInfos[inst->getOpcode()];

    EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
    return sdInst;
  }
}

void EDDisassembler::initMaps(const TargetRegisterInfo &registerInfo) {
  unsigned numRegisters = registerInfo.getNumRegs();
  unsigned registerIndex;

  for (registerIndex = 0; registerIndex < numRegisters; ++registerIndex) {
    const char* registerName = registerInfo.get(registerIndex).Name;

    RegVec.push_back(registerName);
    RegRMap[registerName] = registerIndex;
  }

  if (Key.Arch == Triple::x86 ||
      Key.Arch == Triple::x86_64) {
    stackPointers.insert(registerIDWithName("SP"));
    stackPointers.insert(registerIDWithName("ESP"));
    stackPointers.insert(registerIDWithName("RSP"));

    programCounters.insert(registerIDWithName("IP"));
    programCounters.insert(registerIDWithName("EIP"));
    programCounters.insert(registerIDWithName("RIP"));
  }
}

const char *EDDisassembler::nameWithRegisterID(unsigned registerID) const {
  if (registerID >= RegVec.size())
    return NULL;
  else
    return RegVec[registerID].c_str();
}

unsigned EDDisassembler::registerIDWithName(const char *name) const {
  regrmap_t::const_iterator iter = RegRMap.find(std::string(name));
  if (iter == RegRMap.end())
    return 0;
  else
    return (*iter).second;
}

bool EDDisassembler::registerIsStackPointer(unsigned registerID) {
  return (stackPointers.find(registerID) != stackPointers.end());
}

bool EDDisassembler::registerIsProgramCounter(unsigned registerID) {
  return (programCounters.find(registerID) != programCounters.end());
}

int EDDisassembler::printInst(std::string& str,
                              MCInst& inst) {
  PrinterMutex.acquire();

  InstPrinter->printInst(&inst);
  InstStream->flush();
  str = *InstString;
  InstString->clear();

  PrinterMutex.release();

  return 0;
}

int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
                              SmallVectorImpl<AsmToken> &tokens,
                              const std::string &str) {
  int ret = 0;

  const char *cStr = str.c_str();
  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr));

  StringRef instName;
  SMLoc instLoc;

  SourceMgr sourceMgr;
  sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
  MCContext context;
  OwningPtr<MCStreamer> streamer
    (createNullStreamer(context));
  AsmParser genericParser(sourceMgr, context, *streamer, *AsmInfo);
  OwningPtr<TargetAsmParser> specificParser
    (Tgt->createAsmParser(genericParser));

  AsmToken OpcodeToken = genericParser.Lex();

  if(OpcodeToken.is(AsmToken::Identifier)) {
    instName = OpcodeToken.getString();
    instLoc = OpcodeToken.getLoc();
    if (specificParser->ParseInstruction(instName, instLoc, operands))
      ret = -1;
  }
  else {
    ret = -1;
  }

  ParserMutex.acquire();

  if (!ret) {
    GenericAsmLexer->setBuffer(buf);

    while (SpecificAsmLexer->Lex(),
           SpecificAsmLexer->isNot(AsmToken::Eof) &&
           SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) {
      if (SpecificAsmLexer->is(AsmToken::Error)) {
        ret = -1;
        break;
      }
      tokens.push_back(SpecificAsmLexer->getTok());
    }
  }

  ParserMutex.release();

  return ret;
}

int EDDisassembler::llvmSyntaxVariant() const {
  return LLVMSyntaxVariant;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  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 Willow Garage, 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.
 *
 * $Id: normal_estimation.cpp 1032 2011-05-18 22:43:27Z marton $
 *
 */

#include <sensor_msgs/PointCloud2.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

int    default_k = 0;
double default_radius = 0.0;

void
printHelp (int argc, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -radius X = use a radius of Xm around each point to determine the neighborhood (default: ");
  print_value ("%f", default_radius); print_info (")\n");
  print_info ("                     -k X      = use a fixed number of X-nearest neighbors around each point (default: ");
  print_value ("%f", default_k); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         int k, double radius)
{
  // Convert data to PointCloud<T>
  PointCloud<PointXYZ>::Ptr xyz (new PointCloud<PointXYZ>);
  fromROSMsg (*input, *xyz);

  // Estimate
  TicToc tt;
  tt.tic ();

  print_highlight (stderr, "Computing ");

  NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (xyz);
  ne.setSearchMethod (pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr (new pcl::KdTreeFLANN<pcl::PointXYZ>));
  ne.setKSearch (k);
  ne.setRadiusSearch (radius);

  PointCloud<Normal> normals;
  ne.compute (normals);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", normals.width * normals.height); print_info (" points]\n");

  // Convert data back
  sensor_msgs::PointCloud2 output_normals;
  toROSMsg (normals, output_normals);
  concatenateFields (*input, output_normals, output);
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  pcl::io::savePCDFile (filename, output);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Estimate surface normals using pcl::NormalEstimation. For more information, use: %s -h\n", argv[0]);

  if (argc < 3)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  int k = default_k;
  double radius = default_radius;
  parse_argument (argc, argv, "-k", k);
  parse_argument (argc, argv, "-radius", radius);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;
  compute (cloud, output, k, radius);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}

<commit_msg>saving files as binary in the normal estimation PCL_TOOL<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  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 Willow Garage, 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.
 *
 * $Id: normal_estimation.cpp 1032 2011-05-18 22:43:27Z marton $
 *
 */

#include <sensor_msgs/PointCloud2.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

int    default_k = 0;
double default_radius = 0.0;

Eigen::Vector4f    translation;
Eigen::Quaternionf orientation;

void
printHelp (int argc, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -radius X = use a radius of Xm around each point to determine the neighborhood (default: ");
  print_value ("%f", default_radius); print_info (")\n");
  print_info ("                     -k X      = use a fixed number of X-nearest neighbors around each point (default: ");
  print_value ("%f", default_k); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud, translation, orientation) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         int k, double radius)
{
  // Convert data to PointCloud<T>
  PointCloud<PointXYZ>::Ptr xyz (new PointCloud<PointXYZ>);
  fromROSMsg (*input, *xyz);

  // Estimate
  TicToc tt;
  tt.tic ();

  print_highlight (stderr, "Computing ");

  NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (xyz);
  ne.setSearchMethod (pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr (new pcl::KdTreeFLANN<pcl::PointXYZ>));
  ne.setKSearch (k);
  ne.setRadiusSearch (radius);

  PointCloud<Normal> normals;
  ne.compute (normals);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", normals.width * normals.height); print_info (" points]\n");

  // Convert data back
  sensor_msgs::PointCloud2 output_normals;
  toROSMsg (normals, output_normals);
  concatenateFields (*input, output_normals, output);
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  pcl::io::savePCDFile (filename, output, translation, orientation, true);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Estimate surface normals using pcl::NormalEstimation. For more information, use: %s -h\n", argv[0]);

  if (argc < 3)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  int k = default_k;
  double radius = default_radius;
  parse_argument (argc, argv, "-k", k);
  parse_argument (argc, argv, "-radius", radius);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;
  compute (cloud, output, k, radius);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: errinf.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 14:31:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <limits.h>
#include <shl.hxx>
#include <debug.hxx>
#include <errinf.hxx>
#include <string.hxx>

class ErrorHandler;

struct EDcrData
{
  public:

    ErrorHandler               *pFirstHdl;
    ErrorContext               *pFirstCtx;
    void                       *pDsp;
    BOOL                       bIsWindowDsp;

    DynamicErrorInfo            *ppDcr[ERRCODE_DYNAMIC_COUNT];
    USHORT                      nNextDcr;
                                EDcrData();

static  EDcrData                *GetData();

};

class EDcr_Impl
{
    ULONG                       lErrId;
    USHORT                      nMask;

    void                        RegisterEDcr(DynamicErrorInfo *);
    void                        UnRegisterEDcr(DynamicErrorInfo *);
    static ErrorInfo           *GetDynamicErrorInfo(ULONG lId);

friend class DynamicErrorInfo;
friend class ErrorInfo;
};

EDcrData::EDcrData()
{
    for(USHORT n=0;n<ERRCODE_DYNAMIC_COUNT;n++)
        ppDcr[n]=0;
    nNextDcr=0;
    pFirstHdl=0;
    pDsp=0;
    pFirstCtx=0;
}

EDcrData *EDcrData::GetData()
{
#ifdef BOOTSTRAP
    return 0x0;
#else
    EDcrData **ppDat=(EDcrData **)GetAppData(SHL_ERR);
    if(!*ppDat)
    {
        return (*ppDat=new EDcrData);
    }
    else
        return *ppDat;
#endif
}

void EDcr_Impl::RegisterEDcr(DynamicErrorInfo *pDcr)
{
    //Vergibt eine dynamische Id

    EDcrData* pData=EDcrData::GetData();
    lErrId= (((ULONG)pData->nNextDcr + 1) << ERRCODE_DYNAMIC_SHIFT) +
        pDcr->GetErrorCode();
    DynamicErrorInfo **ppDcr=pData->ppDcr;
    USHORT nNext=pData->nNextDcr;

    // bei einem Ringbuffer koennen wir uns das ASSERT wohl sparen!
    // DBG_ASSERT(ppDcr[nNext]==0,"ErrHdl: Alle Errors belegt");
    if(ppDcr[nNext])
    {
        delete ppDcr[nNext];
    }
    ppDcr[nNext]=pDcr;
    if(++pData->nNextDcr>=ERRCODE_DYNAMIC_COUNT)
        pData->nNextDcr=0;
}

void EDcr_Impl::UnRegisterEDcr(DynamicErrorInfo *pDcr)
{

    EDcrData* pData=EDcrData::GetData();
    DynamicErrorInfo **ppDcr=pData->ppDcr;
    ULONG lIdx=(
        ((ULONG)(*pDcr) & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
    DBG_ASSERT(ppDcr[lIdx]==pDcr,"ErrHdl: Error nicht gefunden");
    if(ppDcr[lIdx]==pDcr)
        ppDcr[lIdx]=0;
}

TYPEINIT0(ErrorInfo);
TYPEINIT1(DynamicErrorInfo, ErrorInfo);
TYPEINIT1(StandardErrorInfo, DynamicErrorInfo);
TYPEINIT1(StringErrorInfo, DynamicErrorInfo);
TYPEINIT1(TwoStringErrorInfo, DynamicErrorInfo);
TYPEINIT1(MessageInfo, DynamicErrorInfo);

ErrorInfo *ErrorInfo::GetErrorInfo(ULONG lId)
{
    if(lId & ERRCODE_DYNAMIC_MASK)
        return EDcr_Impl::GetDynamicErrorInfo(lId);
    else
        return new ErrorInfo(lId);
}

DynamicErrorInfo::operator ULONG() const
{
    return pImpl->lErrId;
}

DynamicErrorInfo::DynamicErrorInfo(ULONG lArgUserId, USHORT nMask)
: ErrorInfo(lArgUserId)
{
    pImpl=new EDcr_Impl;
    pImpl->RegisterEDcr(this);
    pImpl->nMask=nMask;
}

DynamicErrorInfo::~DynamicErrorInfo()
{
    pImpl->UnRegisterEDcr(this);
    delete pImpl;
}

ErrorInfo* EDcr_Impl::GetDynamicErrorInfo(ULONG lId)
{
    ULONG lIdx=((lId & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
    DynamicErrorInfo* pDcr=EDcrData::GetData()->ppDcr[lIdx];
    if(pDcr && (ULONG)(*pDcr)==lId)
        return pDcr;
    else
        return new ErrorInfo(lId & ~ERRCODE_DYNAMIC_MASK);
}

USHORT DynamicErrorInfo::GetDialogMask() const
{
    return pImpl->nMask;
}

StandardErrorInfo::StandardErrorInfo(
    ULONG lUserId, ULONG lArgExtId, USHORT nFlags)
: DynamicErrorInfo(lUserId, nFlags), lExtId(lArgExtId)
{
}

StringErrorInfo::StringErrorInfo(
    ULONG lUserId, const String& aStringP,  USHORT nFlags)
: DynamicErrorInfo(lUserId, nFlags), aString(aStringP)
{
}

class ErrHdl_Impl
{
  public:

    ErrorHandler        *pNext;
    static BOOL         CreateString(const ErrorHandler *pStart,
                                     const ErrorInfo*, String&, USHORT&);
};

static void aDspFunc(const String &rErr, const String &rAction)
{
    ByteString aErr("Aktion: ");
    aErr+= ByteString( rAction, RTL_TEXTENCODING_ASCII_US );
    aErr+=" Fehler: ";
    aErr+= ByteString( rErr, RTL_TEXTENCODING_ASCII_US );
    DBG_ERROR(aErr.GetBuffer());
}

ErrorContext::ErrorContext(Window *pWinP)
{
    EDcrData *pData=EDcrData::GetData();
    ErrorContext *&pHdl=pData->pFirstCtx;
    pWin=pWinP;
    pNext=pHdl;
    pHdl=this;
}

ErrorContext::~ErrorContext()
{
    ErrorContext **ppCtx=&(EDcrData::GetData()->pFirstCtx);
    while(*ppCtx && *ppCtx!=this)
        ppCtx=&((*ppCtx)->pNext);
    if(*ppCtx)
        *ppCtx=(*ppCtx)->pNext;
}

ErrorContext *ErrorContext::GetContext()
{
    return EDcrData::GetData()->pFirstCtx;
}

ErrorHandler::ErrorHandler()
{
    pImpl=new ErrHdl_Impl;
    EDcrData *pData=EDcrData::GetData();
    ErrorHandler *&pHdl=pData->pFirstHdl;
    pImpl->pNext=pHdl;
    pHdl=this;
    if(!pData->pDsp)
        RegisterDisplay(&aDspFunc);
}

ErrorHandler::~ErrorHandler()
{
    ErrorHandler **ppHdl=&(EDcrData::GetData()->pFirstHdl);
    while(*ppHdl && *ppHdl!=this)
        ppHdl=&((*ppHdl)->pImpl->pNext);
    if(*ppHdl)
        *ppHdl=(*ppHdl)->pImpl->pNext;
    delete pImpl;
}

void ErrorHandler::RegisterDisplay(WindowDisplayErrorFunc *aDsp)
{
    EDcrData *pData=EDcrData::GetData();
    pData->bIsWindowDsp=TRUE;
    pData->pDsp=(void*)aDsp;
}

void ErrorHandler::RegisterDisplay(BasicDisplayErrorFunc *aDsp)
{
    EDcrData *pData=EDcrData::GetData();
    pData->bIsWindowDsp=FALSE;
    pData->pDsp=(void*)aDsp;
}

USHORT ErrorHandler::HandleError(ULONG lId, USHORT nFlags)
{

/*  [Beschreibung]
    Handelt einen Fehler ab. lId ist die FehlerId, nFlags sind die
    ErrorFlags. Werden nFlags nicht abgegeben, so werden die in
    der DynamicErrorInfo angegebenen Flags bzw. die aus der Resource
    verwendet.

    Also:

    1. nFlags,
    2. Resource Flags
    3. Dynamic Flags
    4. Default ERRCODE_BUTTON_OK, ERRCODE_MSG_ERROR

    */

    String aErr;
    String aAction;
    if(!lId || lId == ERRCODE_ABORT)
        return 0;
    EDcrData *pData=EDcrData::GetData();
    ErrorInfo *pInfo=ErrorInfo::GetErrorInfo(lId);
    ErrorContext *pCtx=ErrorContext::GetContext();
    if(pCtx)
        pCtx->GetString(pInfo->GetErrorCode(), aAction);
    Window *pParent=0;
    //Nimm den Parent aus dem Konext
    for(;pCtx;pCtx=pCtx->pNext)
        if(pCtx->GetParent())
        {
            pParent=pCtx->GetParent();
            break;
        }

    USHORT nErrFlags = ERRCODE_BUTTON_DEF_OK | ERRCODE_BUTTON_OK |
        ERRCODE_MSG_ERROR;

    DynamicErrorInfo* pDynPtr=PTR_CAST(DynamicErrorInfo,pInfo);
    if(pDynPtr)
    {
        USHORT nDynFlags = pDynPtr->GetDialogMask();
        if( nDynFlags )
            nErrFlags = nDynFlags;
    }

    if(ErrHdl_Impl::CreateString(pData->pFirstHdl,pInfo,aErr,nErrFlags))
    {
        delete pInfo;
        if(!pData->pDsp)
        {

            ByteString aStr("Action: ");
            aStr += ByteString( aAction, RTL_TEXTENCODING_ASCII_US );
            aStr += ByteString("\nFehler: ");
            aStr += ByteString( aErr, RTL_TEXTENCODING_ASCII_US );
            DBG_ERROR( aStr.GetBuffer() );
        }
        else
            if(!pData->bIsWindowDsp)
            {
                (*(BasicDisplayErrorFunc*)pData->pDsp)(aErr,aAction);
                return 0;
            }
            else
            {
                if( nFlags != USHRT_MAX )
                    nErrFlags = nFlags;
                return (*(WindowDisplayErrorFunc*)pData->pDsp)(
                    pParent, nErrFlags, aErr, aAction);
            }
    }

    DBG_ERROR("Error nicht behandelt");
    // Error 1 ist General Error im Sfx
    if(pInfo->GetErrorCode()!=1)
        HandleError(1, USHRT_MAX);
    else
        DBG_ERROR("Error 1 nicht gehandeled");
    delete pInfo;
    return 0;
}

BOOL ErrorHandler::ForwCreateString(const ErrorInfo* pInfo, String& rStr, USHORT &rFlags) const
{
    return ErrHdl_Impl::CreateString(this->pImpl->pNext, pInfo, rStr, rFlags);
}

BOOL ErrHdl_Impl::CreateString( const ErrorHandler *pStart,
                                const ErrorInfo* pInfo, String& pStr,
                               USHORT &rFlags)
{
    for(const ErrorHandler *pHdl=pStart;pHdl;pHdl=pHdl->pImpl->pNext)
    {
        if(pHdl->CreateString( pInfo, pStr, rFlags))
            return TRUE;
    }
    return FALSE;
}

BOOL SimpleErrorHandler::CreateString(
    const ErrorInfo *pInfo, String &rStr, USHORT &) const
{
    ULONG nId = pInfo->GetErrorCode();
    ByteString aStr;
    aStr="Id ";
    aStr+=ByteString::CreateFromInt32(nId);
    aStr+=" only handled by SimpleErrorHandler";
    aStr+="\nErrorCode: ";
    aStr+=ByteString::CreateFromInt32(nId & ((1L <<  ERRCODE_CLASS_SHIFT)  - 1 ));
    aStr+="\nErrorClass: ";
    aStr+=ByteString::CreateFromInt32((nId & ERRCODE_CLASS_MASK) >> ERRCODE_CLASS_SHIFT);
    aStr+="\nErrorArea: ";
    aStr+=ByteString::CreateFromInt32((nId & ERRCODE_ERROR_MASK &
            ~((1 << ERRCODE_AREA_SHIFT ) -1 ) ) >> ERRCODE_AREA_SHIFT);
    DynamicErrorInfo *pDyn=PTR_CAST(DynamicErrorInfo,pInfo);
    if(pDyn)
    {
        aStr+="\nDId ";
        aStr+=ByteString::CreateFromInt32((ULONG)*pDyn);
    }
    StandardErrorInfo *pStd=PTR_CAST(StandardErrorInfo,pInfo);
    if(pStd)
    {
        aStr+="\nXId ";
        aStr+=ByteString::CreateFromInt32(pStd->GetExtendedErrorCode());
    }
    rStr = String( aStr, RTL_TEXTENCODING_ASCII_US );
    return TRUE;
}

SimpleErrorHandler::SimpleErrorHandler()
 : ErrorHandler()
{
}

<commit_msg>INTEGRATION: CWS c06 (1.1.1.1.436); FILE MERGED 2005/09/14 13:21:56 as 1.1.1.1.436.1: #i53536# use right icon for showing warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: errinf.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-11-11 12:15:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <limits.h>
#include <shl.hxx>
#include <debug.hxx>
#include <errinf.hxx>
#include <string.hxx>

class ErrorHandler;

struct EDcrData
{
  public:

    ErrorHandler               *pFirstHdl;
    ErrorContext               *pFirstCtx;
    void                       *pDsp;
    BOOL                       bIsWindowDsp;

    DynamicErrorInfo            *ppDcr[ERRCODE_DYNAMIC_COUNT];
    USHORT                      nNextDcr;
                                EDcrData();

static  EDcrData                *GetData();

};

class EDcr_Impl
{
    ULONG                       lErrId;
    USHORT                      nMask;

    void                        RegisterEDcr(DynamicErrorInfo *);
    void                        UnRegisterEDcr(DynamicErrorInfo *);
    static ErrorInfo           *GetDynamicErrorInfo(ULONG lId);

friend class DynamicErrorInfo;
friend class ErrorInfo;
};

EDcrData::EDcrData()
{
    for(USHORT n=0;n<ERRCODE_DYNAMIC_COUNT;n++)
        ppDcr[n]=0;
    nNextDcr=0;
    pFirstHdl=0;
    pDsp=0;
    pFirstCtx=0;
}

EDcrData *EDcrData::GetData()
{
#ifdef BOOTSTRAP
    return 0x0;
#else
    EDcrData **ppDat=(EDcrData **)GetAppData(SHL_ERR);
    if(!*ppDat)
    {
        return (*ppDat=new EDcrData);
    }
    else
        return *ppDat;
#endif
}

void EDcr_Impl::RegisterEDcr(DynamicErrorInfo *pDcr)
{
    //Vergibt eine dynamische Id

    EDcrData* pData=EDcrData::GetData();
    lErrId= (((ULONG)pData->nNextDcr + 1) << ERRCODE_DYNAMIC_SHIFT) +
        pDcr->GetErrorCode();
    DynamicErrorInfo **ppDcr=pData->ppDcr;
    USHORT nNext=pData->nNextDcr;

    // bei einem Ringbuffer koennen wir uns das ASSERT wohl sparen!
    // DBG_ASSERT(ppDcr[nNext]==0,"ErrHdl: Alle Errors belegt");
    if(ppDcr[nNext])
    {
        delete ppDcr[nNext];
    }
    ppDcr[nNext]=pDcr;
    if(++pData->nNextDcr>=ERRCODE_DYNAMIC_COUNT)
        pData->nNextDcr=0;
}

void EDcr_Impl::UnRegisterEDcr(DynamicErrorInfo *pDcr)
{

    EDcrData* pData=EDcrData::GetData();
    DynamicErrorInfo **ppDcr=pData->ppDcr;
    ULONG lIdx=(
        ((ULONG)(*pDcr) & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
    DBG_ASSERT(ppDcr[lIdx]==pDcr,"ErrHdl: Error nicht gefunden");
    if(ppDcr[lIdx]==pDcr)
        ppDcr[lIdx]=0;
}

TYPEINIT0(ErrorInfo);
TYPEINIT1(DynamicErrorInfo, ErrorInfo);
TYPEINIT1(StandardErrorInfo, DynamicErrorInfo);
TYPEINIT1(StringErrorInfo, DynamicErrorInfo);
TYPEINIT1(TwoStringErrorInfo, DynamicErrorInfo);
TYPEINIT1(MessageInfo, DynamicErrorInfo);

ErrorInfo *ErrorInfo::GetErrorInfo(ULONG lId)
{
    if(lId & ERRCODE_DYNAMIC_MASK)
        return EDcr_Impl::GetDynamicErrorInfo(lId);
    else
        return new ErrorInfo(lId);
}

DynamicErrorInfo::operator ULONG() const
{
    return pImpl->lErrId;
}

DynamicErrorInfo::DynamicErrorInfo(ULONG lArgUserId, USHORT nMask)
: ErrorInfo(lArgUserId)
{
    pImpl=new EDcr_Impl;
    pImpl->RegisterEDcr(this);
    pImpl->nMask=nMask;
}

DynamicErrorInfo::~DynamicErrorInfo()
{
    pImpl->UnRegisterEDcr(this);
    delete pImpl;
}

ErrorInfo* EDcr_Impl::GetDynamicErrorInfo(ULONG lId)
{
    ULONG lIdx=((lId & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
    DynamicErrorInfo* pDcr=EDcrData::GetData()->ppDcr[lIdx];
    if(pDcr && (ULONG)(*pDcr)==lId)
        return pDcr;
    else
        return new ErrorInfo(lId & ~ERRCODE_DYNAMIC_MASK);
}

USHORT DynamicErrorInfo::GetDialogMask() const
{
    return pImpl->nMask;
}

StandardErrorInfo::StandardErrorInfo(
    ULONG lUserId, ULONG lArgExtId, USHORT nFlags)
: DynamicErrorInfo(lUserId, nFlags), lExtId(lArgExtId)
{
}

StringErrorInfo::StringErrorInfo(
    ULONG lUserId, const String& aStringP,  USHORT nFlags)
: DynamicErrorInfo(lUserId, nFlags), aString(aStringP)
{
}

class ErrHdl_Impl
{
  public:

    ErrorHandler        *pNext;
    static BOOL         CreateString(const ErrorHandler *pStart,
                                     const ErrorInfo*, String&, USHORT&);
};

static void aDspFunc(const String &rErr, const String &rAction)
{
    ByteString aErr("Aktion: ");
    aErr+= ByteString( rAction, RTL_TEXTENCODING_ASCII_US );
    aErr+=" Fehler: ";
    aErr+= ByteString( rErr, RTL_TEXTENCODING_ASCII_US );
    DBG_ERROR(aErr.GetBuffer());
}

ErrorContext::ErrorContext(Window *pWinP)
{
    EDcrData *pData=EDcrData::GetData();
    ErrorContext *&pHdl=pData->pFirstCtx;
    pWin=pWinP;
    pNext=pHdl;
    pHdl=this;
}

ErrorContext::~ErrorContext()
{
    ErrorContext **ppCtx=&(EDcrData::GetData()->pFirstCtx);
    while(*ppCtx && *ppCtx!=this)
        ppCtx=&((*ppCtx)->pNext);
    if(*ppCtx)
        *ppCtx=(*ppCtx)->pNext;
}

ErrorContext *ErrorContext::GetContext()
{
    return EDcrData::GetData()->pFirstCtx;
}

ErrorHandler::ErrorHandler()
{
    pImpl=new ErrHdl_Impl;
    EDcrData *pData=EDcrData::GetData();
    ErrorHandler *&pHdl=pData->pFirstHdl;
    pImpl->pNext=pHdl;
    pHdl=this;
    if(!pData->pDsp)
        RegisterDisplay(&aDspFunc);
}

ErrorHandler::~ErrorHandler()
{
    ErrorHandler **ppHdl=&(EDcrData::GetData()->pFirstHdl);
    while(*ppHdl && *ppHdl!=this)
        ppHdl=&((*ppHdl)->pImpl->pNext);
    if(*ppHdl)
        *ppHdl=(*ppHdl)->pImpl->pNext;
    delete pImpl;
}

void ErrorHandler::RegisterDisplay(WindowDisplayErrorFunc *aDsp)
{
    EDcrData *pData=EDcrData::GetData();
    pData->bIsWindowDsp=TRUE;
    pData->pDsp=(void*)aDsp;
}

void ErrorHandler::RegisterDisplay(BasicDisplayErrorFunc *aDsp)
{
    EDcrData *pData=EDcrData::GetData();
    pData->bIsWindowDsp=FALSE;
    pData->pDsp=(void*)aDsp;
}

USHORT ErrorHandler::HandleError(ULONG lId, USHORT nFlags)
{

/*  [Beschreibung]
    Handelt einen Fehler ab. lId ist die FehlerId, nFlags sind die
    ErrorFlags. Werden nFlags nicht abgegeben, so werden die in
    der DynamicErrorInfo angegebenen Flags bzw. die aus der Resource
    verwendet.

    Also:

    1. nFlags,
    2. Resource Flags
    3. Dynamic Flags
    4. Default ERRCODE_BUTTON_OK, ERRCODE_MSG_ERROR

    */

    String aErr;
    String aAction;
    if(!lId || lId == ERRCODE_ABORT)
        return 0;
    EDcrData *pData=EDcrData::GetData();
    ErrorInfo *pInfo=ErrorInfo::GetErrorInfo(lId);
    ErrorContext *pCtx=ErrorContext::GetContext();
    if(pCtx)
        pCtx->GetString(pInfo->GetErrorCode(), aAction);
    Window *pParent=0;
    //Nimm den Parent aus dem Konext
    for(;pCtx;pCtx=pCtx->pNext)
        if(pCtx->GetParent())
        {
            pParent=pCtx->GetParent();
            break;
        }

    BOOL bWarning = ((lId & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK);
    USHORT nErrFlags = ERRCODE_BUTTON_DEF_OK | ERRCODE_BUTTON_OK;
    if (bWarning)
        nErrFlags |= ERRCODE_MSG_WARNING;
    else
        nErrFlags |= ERRCODE_MSG_ERROR;

    DynamicErrorInfo* pDynPtr=PTR_CAST(DynamicErrorInfo,pInfo);
    if(pDynPtr)
    {
        USHORT nDynFlags = pDynPtr->GetDialogMask();
        if( nDynFlags )
            nErrFlags = nDynFlags;
    }

    if(ErrHdl_Impl::CreateString(pData->pFirstHdl,pInfo,aErr,nErrFlags))
    {
        delete pInfo;
        if(!pData->pDsp)
        {

            ByteString aStr("Action: ");
            aStr += ByteString( aAction, RTL_TEXTENCODING_ASCII_US );
            aStr += ByteString("\nFehler: ");
            aStr += ByteString( aErr, RTL_TEXTENCODING_ASCII_US );
            DBG_ERROR( aStr.GetBuffer() );
        }
        else
            if(!pData->bIsWindowDsp)
            {
                (*(BasicDisplayErrorFunc*)pData->pDsp)(aErr,aAction);
                return 0;
            }
            else
            {
                if( nFlags != USHRT_MAX )
                    nErrFlags = nFlags;
                return (*(WindowDisplayErrorFunc*)pData->pDsp)(
                    pParent, nErrFlags, aErr, aAction);
            }
    }

    DBG_ERROR("Error nicht behandelt");
    // Error 1 ist General Error im Sfx
    if(pInfo->GetErrorCode()!=1)
        HandleError(1, USHRT_MAX);
    else
        DBG_ERROR("Error 1 nicht gehandeled");
    delete pInfo;
    return 0;
}

BOOL ErrorHandler::ForwCreateString(const ErrorInfo* pInfo, String& rStr, USHORT &rFlags) const
{
    return ErrHdl_Impl::CreateString(this->pImpl->pNext, pInfo, rStr, rFlags);
}

BOOL ErrHdl_Impl::CreateString( const ErrorHandler *pStart,
                                const ErrorInfo* pInfo, String& pStr,
                               USHORT &rFlags)
{
    for(const ErrorHandler *pHdl=pStart;pHdl;pHdl=pHdl->pImpl->pNext)
    {
        if(pHdl->CreateString( pInfo, pStr, rFlags))
            return TRUE;
    }
    return FALSE;
}

BOOL SimpleErrorHandler::CreateString(
    const ErrorInfo *pInfo, String &rStr, USHORT &) const
{
    ULONG nId = pInfo->GetErrorCode();
    ByteString aStr;
    aStr="Id ";
    aStr+=ByteString::CreateFromInt32(nId);
    aStr+=" only handled by SimpleErrorHandler";
    aStr+="\nErrorCode: ";
    aStr+=ByteString::CreateFromInt32(nId & ((1L <<  ERRCODE_CLASS_SHIFT)  - 1 ));
    aStr+="\nErrorClass: ";
    aStr+=ByteString::CreateFromInt32((nId & ERRCODE_CLASS_MASK) >> ERRCODE_CLASS_SHIFT);
    aStr+="\nErrorArea: ";
    aStr+=ByteString::CreateFromInt32((nId & ERRCODE_ERROR_MASK &
            ~((1 << ERRCODE_AREA_SHIFT ) -1 ) ) >> ERRCODE_AREA_SHIFT);
    DynamicErrorInfo *pDyn=PTR_CAST(DynamicErrorInfo,pInfo);
    if(pDyn)
    {
        aStr+="\nDId ";
        aStr+=ByteString::CreateFromInt32((ULONG)*pDyn);
    }
    StandardErrorInfo *pStd=PTR_CAST(StandardErrorInfo,pInfo);
    if(pStd)
    {
        aStr+="\nXId ";
        aStr+=ByteString::CreateFromInt32(pStd->GetExtendedErrorCode());
    }
    rStr = String( aStr, RTL_TEXTENCODING_ASCII_US );
    return TRUE;
}

SimpleErrorHandler::SimpleErrorHandler()
 : ErrorHandler()
{
}

<|endoftext|>


<commit_before>/***********************************************************************************************************************
**
** Copyright (c) 2015 ETH Zurich
** 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 the ETH Zurich 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 HOLDER 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 "InfoMethods.h"

#include "OOModel/src/allOOModelNodes.h"

namespace OOVisualization {

QString InfoMethods::numberOfCallees(Model::Node *node)
{
	if (auto method = DCast<OOModel::Method>(node))
	{
		QString html = expandButton("toggleCalleeTable", "calleeTable");
		html = "Number of called methods: " + QString::number(method->callees().size()) + "
" + html;
		html += classAndNameTable("calleeTable", method->callees());
		return html;
	}
	else return QString();
}

QString InfoMethods::numberOfUsages(Model::Node *node)
{

	if (auto method = DCast<OOModel::Method>(node))
	{
		QString html = expandButton("toggleCallerTable", "callerTable");
		auto callers = method->callers();
		html = "Number of callers: " + QString::number(callers.size()) + "
" + html;
		html += classAndNameTable("callerTable", callers);
		return html;
	}
	else if (auto someClass = DCast<OOModel::Class>(node))
	{
		QSet<Model::Node*> result;
		auto top = someClass->root();
		//Find all the places where this class is referenced
		QList<Model::Node*> toCheck{top};
		while (!toCheck.isEmpty())
		{
			auto check = toCheck.takeLast();
			if (auto expr = DCast<OOModel::ReferenceExpression>(check))
				if (expr->target() == someClass)
					result << expr->topMostExpressionParent();
			toCheck.append(check->children());
		}
		return "Number of usages: " + QString::number(result.size());
	}
	else return QString();
}

QString InfoMethods::fullName(Model::Node *node)
{
	if (auto method = DCast<OOModel::Method>(node))
		return "" + method->fullyQualifiedName() + "";
	else if (auto clazz = DCast<OOModel::Class>(node))
		return "" + clazz->name() + "";
	else return QString();
}

QString InfoMethods::expandButton(QString functionName, QString expandableId)
{
	QString html = "";
	html += "<button onclick=\"" + functionName + "()\">Details</button>";
	return html;
}

QString InfoMethods::classAndNameTable(QString tableId, QSet<OOModel::Method *> methods)
{
	QStringList tableRows{"
Class	Method
"};
	for (auto method : methods)
	{
		auto methodClass = method->firstAncestorOfType<OOModel::Class>();
		tableRows.append("
" + (methodClass ? methodClass->name() : "n/a") + "	"
						+ "" + method->name() + "
");
	}
	return hiddenTable(tableId, tableRows);
}

QString InfoMethods::hiddenTable(QString tableId, QStringList rows)
{
	QString html = "
";
	for (auto row : rows)
		html += row;
	html += "
";
	return html;
}

}
<commit_msg>Add a "Jump to" button for callees/callers<commit_after>/***********************************************************************************************************************
**
** Copyright (c) 2015 ETH Zurich
** 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 the ETH Zurich 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 HOLDER 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 "InfoMethods.h"

#include "OOModel/src/allOOModelNodes.h"

namespace OOVisualization {

QString InfoMethods::numberOfCallees(Model::Node *node)
{
	if (auto method = DCast<OOModel::Method>(node))
	{
		QString html = expandButton("toggleCalleeTable", "calleeTable");
		html = "Number of called methods: " + QString::number(method->callees().size()) + "
" + html;
		html += classAndNameTable("calleeTable", method->callees());
		return html;
	}
	else return QString();
}

QString InfoMethods::numberOfUsages(Model::Node *node)
{

	if (auto method = DCast<OOModel::Method>(node))
	{
		QString html = expandButton("toggleCallerTable", "callerTable");
		auto callers = method->callers();
		html = "Number of callers: " + QString::number(callers.size()) + "
" + html;
		html += classAndNameTable("callerTable", callers);
		return html;
	}
	else if (auto someClass = DCast<OOModel::Class>(node))
	{
		QSet<Model::Node*> result;
		auto top = someClass->root();
		//Find all the places where this class is referenced
		QList<Model::Node*> toCheck{top};
		while (!toCheck.isEmpty())
		{
			auto check = toCheck.takeLast();
			if (auto expr = DCast<OOModel::ReferenceExpression>(check))
				if (expr->target() == someClass)
					result << expr->topMostExpressionParent();
			toCheck.append(check->children());
		}
		return "Number of usages: " + QString::number(result.size());
	}
	else return QString();
}

QString InfoMethods::fullName(Model::Node *node)
{
	if (auto method = DCast<OOModel::Method>(node))
		return "" + method->fullyQualifiedName() + "";
	else if (auto clazz = DCast<OOModel::Class>(node))
		return "" + clazz->name() + "";
	else return QString();
}

QString InfoMethods::expandButton(QString functionName, QString expandableId)
{
	QString html = "";
	html += "<button onclick=\"" + functionName + "()\">Details</button>";
	return html;
}

QString InfoMethods::classAndNameTable(QString tableId, QSet<OOModel::Method *> methods)
{
	QStringList tableRows{"
Class	Method
"};
	for (auto method : methods)
	{
		auto methodClass = method->firstAncestorOfType<OOModel::Class>();
		tableRows.append("
" + (methodClass ? methodClass->name() : "n/a") + "	"
						+ "" + method->name() + "	"
						+ "<button onclick=\"operations.jumpToObject('" +
									method->fullyQualifiedName() + "')\">Jump to</button>
");
	}
	return hiddenTable(tableId, tableRows);
}

QString InfoMethods::hiddenTable(QString tableId, QStringList rows)
{
	QString html = "
";
	for (auto row : rows)
		html += row;
	html += "
";
	return html;
}

}
<|endoftext|>