<commit_before>//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements functions to run clang tools standalone instead
//  of running them as a plugin.
//
//===----------------------------------------------------------------------===//

#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

#ifdef _WIN32
// For chdir, see the comment in ClangTool::run for more information.
#  include <direct.h>
#endif

namespace clang {
namespace tooling {

// Exists solely for the purpose of lookup of the resource path.
static int StaticSymbol;

FrontendActionFactory::~FrontendActionFactory() {}

// FIXME: This file contains structural duplication with other parts of the
// code that sets up a compiler to run tools on it, and we should refactor
// it to be based on the same framework.

/// \brief Builds a clang driver initialized for running clang tools.
static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics,
                                        const char *BinaryName) {
  const std::string DefaultOutputName = "a.out";
  // This just needs to be some symbol in the binary.
  void *const SymbolAddr = &StaticSymbol;
  // The driver detects the builtin header path based on the path of
  // the executable.
  // FIXME: On linux, GetMainExecutable is independent of the content
  // of BinaryName, thus allowing ClangTool and runToolOnCode to just
  // pass in made-up names here (in the case of ClangTool this being
  // the original compiler invocation). Make sure this works on other
  // platforms.
  llvm::sys::Path MainExecutable =
    llvm::sys::Path::GetMainExecutable(BinaryName, SymbolAddr);
  clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
    MainExecutable.str(), llvm::sys::getDefaultTargetTriple(),
    DefaultOutputName, false, *Diagnostics);
  CompilerDriver->setTitle("clang_based_tool");
  return CompilerDriver;
}

/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
///
/// Returns NULL on error.
static const clang::driver::ArgStringList *getCC1Arguments(
    clang::DiagnosticsEngine *Diagnostics,
    clang::driver::Compilation *Compilation) {
  // We expect to get back exactly one Command job, if we didn't something
  // failed. Extract that job from the Compilation.
  const clang::driver::JobList &Jobs = Compilation->getJobs();
  if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) {
    llvm::SmallString<256> error_msg;
    llvm::raw_svector_ostream error_stream(error_msg);
    Compilation->PrintJob(error_stream, Compilation->getJobs(), "; ", true);
    Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
        << error_stream.str();
    return NULL;
  }

  // The one job we find should be to invoke clang again.
  const clang::driver::Command *Cmd =
      cast<clang::driver::Command>(*Jobs.begin());
  if (StringRef(Cmd->getCreator().getName()) != "clang") {
    Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
    return NULL;
  }

  return &Cmd->getArguments();
}

/// \brief Returns a clang build invocation initialized from the CC1 flags.
static clang::CompilerInvocation *newInvocation(
    clang::DiagnosticsEngine *Diagnostics,
    const clang::driver::ArgStringList &CC1Args) {
  assert(!CC1Args.empty() && "Must at least contain the program name!");
  clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
  clang::CompilerInvocation::CreateFromArgs(
      *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
      *Diagnostics);
  Invocation->getFrontendOpts().DisableFree = false;
  return Invocation;
}

bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
                   const Twine &FileName) {
  SmallString<16> FileNameStorage;
  StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
  const char *const CommandLine[] = {
      "clang-tool", "-fsyntax-only", FileNameRef.data()
  };
  FileManager Files((FileSystemOptions()));
  ToolInvocation Invocation(
      std::vector<std::string>(
          CommandLine,
          CommandLine + llvm::array_lengthof(CommandLine)),
      ToolAction, &Files);

  SmallString<1024> CodeStorage;
  Invocation.mapVirtualFile(FileNameRef,
                            Code.toNullTerminatedStringRef(CodeStorage));
  return Invocation.run();
}

/// \brief Returns the absolute path of 'File', by prepending it with
/// 'BaseDirectory' if 'File' is not absolute.
///
/// Otherwise returns 'File'.
/// If 'File' starts with "./", the returned path will not contain the "./".
/// Otherwise, the returned path will contain the literal path-concatenation of
/// 'BaseDirectory' and 'File'.
///
/// \param File Either an absolute or relative path.
/// \param BaseDirectory An absolute path.
static std::string getAbsolutePath(
    StringRef File, StringRef BaseDirectory) {
  assert(llvm::sys::path::is_absolute(BaseDirectory));
  if (llvm::sys::path::is_absolute(File)) {
    return File;
  }
  StringRef RelativePath(File);
  if (RelativePath.startswith("./")) {
    RelativePath = RelativePath.substr(strlen("./"));
  }
  llvm::SmallString<1024> AbsolutePath(BaseDirectory);
  llvm::sys::path::append(AbsolutePath, RelativePath);
  return AbsolutePath.str();
}

ToolInvocation::ToolInvocation(
    ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
    FileManager *Files)
    : CommandLine(CommandLine.vec()), ToolAction(ToolAction), Files(Files) {
}

void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
  MappedFileContents[FilePath] = Content;
}

bool ToolInvocation::run() {
  std::vector<const char*> Argv;
  for (int I = 0, E = CommandLine.size(); I != E; ++I)
    Argv.push_back(CommandLine[I].c_str());
  const char *const BinaryName = Argv[0];
  DiagnosticOptions DefaultDiagnosticOptions;
  TextDiagnosticPrinter DiagnosticPrinter(
      llvm::errs(), DefaultDiagnosticOptions);
  DiagnosticsEngine Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(
      new DiagnosticIDs()), &DiagnosticPrinter, false);

  const llvm::OwningPtr<clang::driver::Driver> Driver(
      newDriver(&Diagnostics, BinaryName));
  // Since the input might only be virtual, don't check whether it exists.
  Driver->setCheckInputsExist(false);
  const llvm::OwningPtr<clang::driver::Compilation> Compilation(
      Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
  const clang::driver::ArgStringList *const CC1Args = getCC1Arguments(
      &Diagnostics, Compilation.get());
  if (CC1Args == NULL) {
    return false;
  }
  llvm::OwningPtr<clang::CompilerInvocation> Invocation(
      newInvocation(&Diagnostics, *CC1Args));
  return runInvocation(BinaryName, Compilation.get(),
                       Invocation.take(), *CC1Args, ToolAction.take());
}

bool ToolInvocation::runInvocation(
    const char *BinaryName,
    clang::driver::Compilation *Compilation,
    clang::CompilerInvocation *Invocation,
    const clang::driver::ArgStringList &CC1Args,
    clang::FrontendAction *ToolAction) {
  llvm::OwningPtr<clang::FrontendAction> ScopedToolAction(ToolAction);
  // Show the invocation, with -v.
  if (Invocation->getHeaderSearchOpts().Verbose) {
    llvm::errs() << "clang Invocation:\n";
    Compilation->PrintJob(llvm::errs(), Compilation->getJobs(), "\n", true);
    llvm::errs() << "\n";
  }

  // Create a compiler instance to handle the actual work.
  clang::CompilerInstance Compiler;
  Compiler.setInvocation(Invocation);
  Compiler.setFileManager(Files);
  // FIXME: What about LangOpts?

  // Create the compilers actual diagnostics engine.
  Compiler.createDiagnostics(CC1Args.size(),
                             const_cast<char**>(CC1Args.data()));
  if (!Compiler.hasDiagnostics())
    return false;

  Compiler.createSourceManager(*Files);
  addFileMappingsTo(Compiler.getSourceManager());

  // Infer the builtin include path if unspecified.
  if (Compiler.getHeaderSearchOpts().UseBuiltinIncludes &&
      Compiler.getHeaderSearchOpts().ResourceDir.empty()) {
    // This just needs to be some symbol in the binary.
    void *const SymbolAddr = &StaticSymbol;
    Compiler.getHeaderSearchOpts().ResourceDir =
        clang::CompilerInvocation::GetResourcesPath(BinaryName, SymbolAddr);
  }

  const bool Success = Compiler.ExecuteAction(*ToolAction);

  Compiler.resetAndLeakFileManager();
  return Success;
}

void ToolInvocation::addFileMappingsTo(SourceManager &Sources) {
  for (llvm::StringMap<StringRef>::const_iterator
           It = MappedFileContents.begin(), End = MappedFileContents.end();
       It != End; ++It) {
    // Inject the code as the given file name into the preprocessor options.
    const llvm::MemoryBuffer *Input =
        llvm::MemoryBuffer::getMemBuffer(It->getValue());
    // FIXME: figure out what '0' stands for.
    const FileEntry *FromFile = Files->getVirtualFile(
        It->getKey(), Input->getBufferSize(), 0);
    // FIXME: figure out memory management ('true').
    Sources.overrideFileContents(FromFile, Input, true);
  }
}

ClangTool::ClangTool(const CompilationDatabase &Compilations,
                     ArrayRef<std::string> SourcePaths)
    : Files((FileSystemOptions())) {
  llvm::SmallString<1024> BaseDirectory;
  if (const char *PWD = ::getenv("PWD"))
    BaseDirectory = PWD;
  else
    llvm::sys::fs::current_path(BaseDirectory);
  for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {
    llvm::SmallString<1024> File(getAbsolutePath(
        SourcePaths[I], BaseDirectory));

    std::vector<CompileCommand> CompileCommandsForFile =
      Compilations.getCompileCommands(File.str());
    if (!CompileCommandsForFile.empty()) {
      for (int I = 0, E = CompileCommandsForFile.size(); I != E; ++I) {
        CompileCommands.push_back(std::make_pair(File.str(),
                                  CompileCommandsForFile[I]));
      }
    } else {
      // FIXME: There are two use cases here: doing a fuzzy
      // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
      // about the .cc files that were not found, and the use case where I
      // specify all files I want to run over explicitly, where this should
      // be an error. We'll want to add an option for this.
      llvm::outs() << "Skipping " << File << ". Command line not found.\n";
    }
  }
}

void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
  MappedFileContents.push_back(std::make_pair(FilePath, Content));
}

int ClangTool::run(FrontendActionFactory *ActionFactory) {
  bool ProcessingFailed = false;
  for (unsigned I = 0; I < CompileCommands.size(); ++I) {
    std::string File = CompileCommands[I].first;
    // FIXME: chdir is thread hostile; on the other hand, creating the same
    // behavior as chdir is complex: chdir resolves the path once, thus
    // guaranteeing that all subsequent relative path operations work
    // on the same path the original chdir resulted in. This makes a difference
    // for example on network filesystems, where symlinks might be switched
    // during runtime of the tool. Fixing this depends on having a file system
    // abstraction that allows openat() style interactions.
    if (chdir(CompileCommands[I].second.Directory.c_str()))
      llvm::report_fatal_error("Cannot chdir into \"" +
                               CompileCommands[I].second.Directory + "\n!");
    std::vector<std::string> &CommandLine =
      CompileCommands[I].second.CommandLine;
    llvm::outs() << "Processing: " << File << ".\n";
    ToolInvocation Invocation(CommandLine, ActionFactory->create(), &Files);
    for (int I = 0, E = MappedFileContents.size(); I != E; ++I) {
      Invocation.mapVirtualFile(MappedFileContents[I].first,
                                MappedFileContents[I].second);
    }
    if (!Invocation.run()) {
      llvm::outs() << "Error while processing " << File << ".\n";
      ProcessingFailed = true;
    }
  }
  return ProcessingFailed ? 1 : 0;
}

} // end namespace tooling
} // end namespace clang
<commit_msg>Fix includes for unices that don't have chdir declared transitively.<commit_after>//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements functions to run clang tools standalone instead
//  of running them as a plugin.
//
//===----------------------------------------------------------------------===//

#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

// For chdir, see the comment in ClangTool::run for more information.
#ifdef _WIN32
#  include <direct.h>
#else
#  include <unistd.h>
#endif

namespace clang {
namespace tooling {

// Exists solely for the purpose of lookup of the resource path.
static int StaticSymbol;

FrontendActionFactory::~FrontendActionFactory() {}

// FIXME: This file contains structural duplication with other parts of the
// code that sets up a compiler to run tools on it, and we should refactor
// it to be based on the same framework.

/// \brief Builds a clang driver initialized for running clang tools.
static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics,
                                        const char *BinaryName) {
  const std::string DefaultOutputName = "a.out";
  // This just needs to be some symbol in the binary.
  void *const SymbolAddr = &StaticSymbol;
  // The driver detects the builtin header path based on the path of
  // the executable.
  // FIXME: On linux, GetMainExecutable is independent of the content
  // of BinaryName, thus allowing ClangTool and runToolOnCode to just
  // pass in made-up names here (in the case of ClangTool this being
  // the original compiler invocation). Make sure this works on other
  // platforms.
  llvm::sys::Path MainExecutable =
    llvm::sys::Path::GetMainExecutable(BinaryName, SymbolAddr);
  clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
    MainExecutable.str(), llvm::sys::getDefaultTargetTriple(),
    DefaultOutputName, false, *Diagnostics);
  CompilerDriver->setTitle("clang_based_tool");
  return CompilerDriver;
}

/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
///
/// Returns NULL on error.
static const clang::driver::ArgStringList *getCC1Arguments(
    clang::DiagnosticsEngine *Diagnostics,
    clang::driver::Compilation *Compilation) {
  // We expect to get back exactly one Command job, if we didn't something
  // failed. Extract that job from the Compilation.
  const clang::driver::JobList &Jobs = Compilation->getJobs();
  if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) {
    llvm::SmallString<256> error_msg;
    llvm::raw_svector_ostream error_stream(error_msg);
    Compilation->PrintJob(error_stream, Compilation->getJobs(), "; ", true);
    Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
        << error_stream.str();
    return NULL;
  }

  // The one job we find should be to invoke clang again.
  const clang::driver::Command *Cmd =
      cast<clang::driver::Command>(*Jobs.begin());
  if (StringRef(Cmd->getCreator().getName()) != "clang") {
    Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
    return NULL;
  }

  return &Cmd->getArguments();
}

/// \brief Returns a clang build invocation initialized from the CC1 flags.
static clang::CompilerInvocation *newInvocation(
    clang::DiagnosticsEngine *Diagnostics,
    const clang::driver::ArgStringList &CC1Args) {
  assert(!CC1Args.empty() && "Must at least contain the program name!");
  clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
  clang::CompilerInvocation::CreateFromArgs(
      *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
      *Diagnostics);
  Invocation->getFrontendOpts().DisableFree = false;
  return Invocation;
}

bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
                   const Twine &FileName) {
  SmallString<16> FileNameStorage;
  StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
  const char *const CommandLine[] = {
      "clang-tool", "-fsyntax-only", FileNameRef.data()
  };
  FileManager Files((FileSystemOptions()));
  ToolInvocation Invocation(
      std::vector<std::string>(
          CommandLine,
          CommandLine + llvm::array_lengthof(CommandLine)),
      ToolAction, &Files);

  SmallString<1024> CodeStorage;
  Invocation.mapVirtualFile(FileNameRef,
                            Code.toNullTerminatedStringRef(CodeStorage));
  return Invocation.run();
}

/// \brief Returns the absolute path of 'File', by prepending it with
/// 'BaseDirectory' if 'File' is not absolute.
///
/// Otherwise returns 'File'.
/// If 'File' starts with "./", the returned path will not contain the "./".
/// Otherwise, the returned path will contain the literal path-concatenation of
/// 'BaseDirectory' and 'File'.
///
/// \param File Either an absolute or relative path.
/// \param BaseDirectory An absolute path.
static std::string getAbsolutePath(
    StringRef File, StringRef BaseDirectory) {
  assert(llvm::sys::path::is_absolute(BaseDirectory));
  if (llvm::sys::path::is_absolute(File)) {
    return File;
  }
  StringRef RelativePath(File);
  if (RelativePath.startswith("./")) {
    RelativePath = RelativePath.substr(strlen("./"));
  }
  llvm::SmallString<1024> AbsolutePath(BaseDirectory);
  llvm::sys::path::append(AbsolutePath, RelativePath);
  return AbsolutePath.str();
}

ToolInvocation::ToolInvocation(
    ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
    FileManager *Files)
    : CommandLine(CommandLine.vec()), ToolAction(ToolAction), Files(Files) {
}

void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
  MappedFileContents[FilePath] = Content;
}

bool ToolInvocation::run() {
  std::vector<const char*> Argv;
  for (int I = 0, E = CommandLine.size(); I != E; ++I)
    Argv.push_back(CommandLine[I].c_str());
  const char *const BinaryName = Argv[0];
  DiagnosticOptions DefaultDiagnosticOptions;
  TextDiagnosticPrinter DiagnosticPrinter(
      llvm::errs(), DefaultDiagnosticOptions);
  DiagnosticsEngine Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(
      new DiagnosticIDs()), &DiagnosticPrinter, false);

  const llvm::OwningPtr<clang::driver::Driver> Driver(
      newDriver(&Diagnostics, BinaryName));
  // Since the input might only be virtual, don't check whether it exists.
  Driver->setCheckInputsExist(false);
  const llvm::OwningPtr<clang::driver::Compilation> Compilation(
      Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
  const clang::driver::ArgStringList *const CC1Args = getCC1Arguments(
      &Diagnostics, Compilation.get());
  if (CC1Args == NULL) {
    return false;
  }
  llvm::OwningPtr<clang::CompilerInvocation> Invocation(
      newInvocation(&Diagnostics, *CC1Args));
  return runInvocation(BinaryName, Compilation.get(),
                       Invocation.take(), *CC1Args, ToolAction.take());
}

bool ToolInvocation::runInvocation(
    const char *BinaryName,
    clang::driver::Compilation *Compilation,
    clang::CompilerInvocation *Invocation,
    const clang::driver::ArgStringList &CC1Args,
    clang::FrontendAction *ToolAction) {
  llvm::OwningPtr<clang::FrontendAction> ScopedToolAction(ToolAction);
  // Show the invocation, with -v.
  if (Invocation->getHeaderSearchOpts().Verbose) {
    llvm::errs() << "clang Invocation:\n";
    Compilation->PrintJob(llvm::errs(), Compilation->getJobs(), "\n", true);
    llvm::errs() << "\n";
  }

  // Create a compiler instance to handle the actual work.
  clang::CompilerInstance Compiler;
  Compiler.setInvocation(Invocation);
  Compiler.setFileManager(Files);
  // FIXME: What about LangOpts?

  // Create the compilers actual diagnostics engine.
  Compiler.createDiagnostics(CC1Args.size(),
                             const_cast<char**>(CC1Args.data()));
  if (!Compiler.hasDiagnostics())
    return false;

  Compiler.createSourceManager(*Files);
  addFileMappingsTo(Compiler.getSourceManager());

  // Infer the builtin include path if unspecified.
  if (Compiler.getHeaderSearchOpts().UseBuiltinIncludes &&
      Compiler.getHeaderSearchOpts().ResourceDir.empty()) {
    // This just needs to be some symbol in the binary.
    void *const SymbolAddr = &StaticSymbol;
    Compiler.getHeaderSearchOpts().ResourceDir =
        clang::CompilerInvocation::GetResourcesPath(BinaryName, SymbolAddr);
  }

  const bool Success = Compiler.ExecuteAction(*ToolAction);

  Compiler.resetAndLeakFileManager();
  return Success;
}

void ToolInvocation::addFileMappingsTo(SourceManager &Sources) {
  for (llvm::StringMap<StringRef>::const_iterator
           It = MappedFileContents.begin(), End = MappedFileContents.end();
       It != End; ++It) {
    // Inject the code as the given file name into the preprocessor options.
    const llvm::MemoryBuffer *Input =
        llvm::MemoryBuffer::getMemBuffer(It->getValue());
    // FIXME: figure out what '0' stands for.
    const FileEntry *FromFile = Files->getVirtualFile(
        It->getKey(), Input->getBufferSize(), 0);
    // FIXME: figure out memory management ('true').
    Sources.overrideFileContents(FromFile, Input, true);
  }
}

ClangTool::ClangTool(const CompilationDatabase &Compilations,
                     ArrayRef<std::string> SourcePaths)
    : Files((FileSystemOptions())) {
  llvm::SmallString<1024> BaseDirectory;
  if (const char *PWD = ::getenv("PWD"))
    BaseDirectory = PWD;
  else
    llvm::sys::fs::current_path(BaseDirectory);
  for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {
    llvm::SmallString<1024> File(getAbsolutePath(
        SourcePaths[I], BaseDirectory));

    std::vector<CompileCommand> CompileCommandsForFile =
      Compilations.getCompileCommands(File.str());
    if (!CompileCommandsForFile.empty()) {
      for (int I = 0, E = CompileCommandsForFile.size(); I != E; ++I) {
        CompileCommands.push_back(std::make_pair(File.str(),
                                  CompileCommandsForFile[I]));
      }
    } else {
      // FIXME: There are two use cases here: doing a fuzzy
      // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
      // about the .cc files that were not found, and the use case where I
      // specify all files I want to run over explicitly, where this should
      // be an error. We'll want to add an option for this.
      llvm::outs() << "Skipping " << File << ". Command line not found.\n";
    }
  }
}

void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
  MappedFileContents.push_back(std::make_pair(FilePath, Content));
}

int ClangTool::run(FrontendActionFactory *ActionFactory) {
  bool ProcessingFailed = false;
  for (unsigned I = 0; I < CompileCommands.size(); ++I) {
    std::string File = CompileCommands[I].first;
    // FIXME: chdir is thread hostile; on the other hand, creating the same
    // behavior as chdir is complex: chdir resolves the path once, thus
    // guaranteeing that all subsequent relative path operations work
    // on the same path the original chdir resulted in. This makes a difference
    // for example on network filesystems, where symlinks might be switched
    // during runtime of the tool. Fixing this depends on having a file system
    // abstraction that allows openat() style interactions.
    if (chdir(CompileCommands[I].second.Directory.c_str()))
      llvm::report_fatal_error("Cannot chdir into \"" +
                               CompileCommands[I].second.Directory + "\n!");
    std::vector<std::string> &CommandLine =
      CompileCommands[I].second.CommandLine;
    llvm::outs() << "Processing: " << File << ".\n";
    ToolInvocation Invocation(CommandLine, ActionFactory->create(), &Files);
    for (int I = 0, E = MappedFileContents.size(); I != E; ++I) {
      Invocation.mapVirtualFile(MappedFileContents[I].first,
                                MappedFileContents[I].second);
    }
    if (!Invocation.run()) {
      llvm::outs() << "Error while processing " << File << ".\n";
      ProcessingFailed = true;
    }
  }
  return ProcessingFailed ? 1 : 0;
}

} // end namespace tooling
} // end namespace clang
<|endoftext|>


<commit_before>//===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/DebugLoc.h"
#include "LLVMContextImpl.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// DebugLoc Implementation
//===----------------------------------------------------------------------===//

MDNode *NewDebugLoc::getScope(const LLVMContext &Ctx) const {
  if (ScopeIdx == 0) return 0;

  if (ScopeIdx > 0) {
    // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
    // position specified.
    assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
           "Invalid ScopeIdx!");
    return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
  }

  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
}

MDNode *NewDebugLoc::getInlinedAt(const LLVMContext &Ctx) const {
  // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
  // position specified.  Zero is invalid.
  if (ScopeIdx >= 0) return 0;

  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
}

/// Return both the Scope and the InlinedAt values.
void NewDebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
                                       const LLVMContext &Ctx) const {
  if (ScopeIdx == 0) {
    Scope = IA = 0;
    return;
  }

  if (ScopeIdx > 0) {
    // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
    // position specified.
    assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
           "Invalid ScopeIdx!");
    Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
    IA = 0;
    return;
  }

  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
  IA    = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
}

NewDebugLoc NewDebugLoc::get(unsigned Line, unsigned Col,
                             MDNode *Scope, MDNode *InlinedAt) {
  NewDebugLoc Result;

  // If no scope is available, this is an unknown location.
  if (Scope == 0) return Result;

  // Saturate line and col to "unknown".
  if (Col > 255) Col = 0;
  if (Line >= (1 << 24)) Line = 0;
  Result.LineCol = Line | (Col << 24);

  LLVMContext &Ctx = Scope->getContext();

  // If there is no inlined-at location, use the ScopeRecords array.
  if (InlinedAt == 0)
    Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0);
  else
    Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope,
                                                                InlinedAt, 0);

  return Result;
}

/// getAsMDNode - This method converts the compressed DebugLoc node into a
/// DILocation compatible MDNode.
MDNode *NewDebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
  if (isUnknown()) return 0;

  MDNode *Scope, *IA;
  getScopeAndInlinedAt(Scope, IA, Ctx);
  assert(Scope && "If scope is null, this should be isUnknown()");

  LLVMContext &Ctx2 = Scope->getContext();
  const Type *Int32 = Type::getInt32Ty(Ctx2);
  Value *Elts[] = {
    ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()),
    Scope, IA
  };
  return MDNode::get(Ctx2, &Elts[0], 4);
}

/// getFromDILocation - Translate the DILocation quad into a NewDebugLoc.
NewDebugLoc NewDebugLoc::getFromDILocation(MDNode *N) {
  if (N == 0 || N->getNumOperands() != 4) return NewDebugLoc();

  MDNode *Scope = dyn_cast_or_null<MDNode>(N->getOperand(2));
  if (Scope == 0) return NewDebugLoc();

  unsigned LineNo = 0, ColNo = 0;
  if (ConstantInt *Line = dyn_cast_or_null<ConstantInt>(N->getOperand(0)))
    LineNo = Line->getZExtValue();
  if (ConstantInt *Col = dyn_cast_or_null<ConstantInt>(N->getOperand(1)))
    ColNo = Col->getZExtValue();

  return get(LineNo, ColNo, Scope, dyn_cast_or_null<MDNode>(N->getOperand(3)));
}

//===----------------------------------------------------------------------===//
// LLVMContextImpl Implementation
//===----------------------------------------------------------------------===//

int LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope,
                                                 int ExistingIdx) {
  // If we already have an entry for this scope, return it.
  int &Idx = ScopeRecordIdx[Scope];
  if (Idx) return Idx;

  // If we don't have an entry, but ExistingIdx is specified, use it.
  if (ExistingIdx)
    return Idx = ExistingIdx;

  // Otherwise add a new entry.

  // Start out ScopeRecords with a minimal reasonable size to avoid
  // excessive reallocation starting out.
  if (ScopeRecords.empty())
    ScopeRecords.reserve(128);

  // Index is biased by 1 for index.
  Idx = ScopeRecords.size()+1;
  ScopeRecords.push_back(DebugRecVH(Scope, this, Idx));
  return Idx;
}

int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,
                                                    int ExistingIdx) {
  // If we already have an entry, return it.
  int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)];
  if (Idx) return Idx;

  // If we don't have an entry, but ExistingIdx is specified, use it.
  if (ExistingIdx)
    return Idx = ExistingIdx;

  // Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid
  // excessive reallocation starting out.
  if (ScopeInlinedAtRecords.empty())
    ScopeInlinedAtRecords.reserve(128);

  // Index is biased by 1 and negated.
  Idx = -ScopeInlinedAtRecords.size()-1;
  ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx),
                                                 DebugRecVH(IA, this, Idx)));
  return Idx;
}

//===----------------------------------------------------------------------===//
// DebugRecVH Implementation
//===----------------------------------------------------------------------===//

/// deleted - The MDNode this is pointing to got deleted, so this pointer needs
/// to drop to null and we need remove our entry from the DenseMap.
void DebugRecVH::deleted() {
  // If this is a  non-canonical reference, just drop the value to null, we know
  // it doesn't have a map entry.
  if (Idx == 0) {
    setValPtr(0);
    return;
  }

  MDNode *Cur = get();

  // If the index is positive, it is an entry in ScopeRecords.
  if (Idx > 0) {
    assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!");
    Ctx->ScopeRecordIdx.erase(Cur);
    // Reset this VH to null and we're done.
    setValPtr(0);
    Idx = 0;
    return;
  }

  // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
  // is the scope or the inlined-at record entry.
  assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
  std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
  assert((this == &Entry.first || this == &Entry.second) &&
         "Mapping out of date!");

  MDNode *OldScope = Entry.first.get();
  MDNode *OldInlinedAt = Entry.second.get();
  assert(OldScope != 0 && OldInlinedAt != 0 &&
         "Entry should be non-canonical if either val dropped to null");

  // Otherwise, we do have an entry in it, nuke it and we're done.
  assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
         "Mapping out of date");
  Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));

  // Reset this VH to null.
  setValPtr(0);
  Idx = 0;
}

void DebugRecVH::allUsesReplacedWith(Value *NewVa) {
  // If being replaced with a non-mdnode value (e.g. undef) handle this as if
  // the mdnode got deleted.
  MDNode *NewVal = dyn_cast<MDNode>(NewVa);
  if (NewVal == 0) return deleted();

  // If this is a non-canonical reference, just change it, we know it already
  // doesn't have a map entry.
  if (Idx == 0) {
    setValPtr(NewVa);
    return;
  }

  MDNode *OldVal = get();
  assert(OldVal != NewVa && "Node replaced with self?");

  // If the index is positive, it is an entry in ScopeRecords.
  if (Idx > 0) {
    assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!");
    Ctx->ScopeRecordIdx.erase(OldVal);
    setValPtr(NewVal);

    int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx);

    // If NewVal already has an entry, this becomes a non-canonical reference,
    // just drop Idx to 0 to signify this.
    if (NewEntry != Idx)
      Idx = 0;
    return;
  }

  // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
  // is the scope or the inlined-at record entry.
  assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
  std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
  assert((this == &Entry.first || this == &Entry.second) &&
         "Mapping out of date!");

  MDNode *OldScope = Entry.first.get();
  MDNode *OldInlinedAt = Entry.second.get();
  assert(OldScope != 0 && OldInlinedAt != 0 &&
         "Entry should be non-canonical if either val dropped to null");

  // Otherwise, we do have an entry in it, nuke it and we're done.
  assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
         "Mapping out of date");
  Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));

  // Reset this VH to the new value.
  setValPtr(NewVal);

  int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(),
                                                   Entry.second.get(), Idx);
  // If NewVal already has an entry, this becomes a non-canonical reference,
  // just drop Idx to 0 to signify this.
  if (NewIdx != Idx)
    Idx = 0;
}
<commit_msg>fix a bug in DebugRecVH::deleted/allUsesReplacedWith.  If an  entry in the Scope+InlinedAt drops to a non-canonical form, we need to reset the idx member of both VH's to 0.<commit_after>//===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/DebugLoc.h"
#include "LLVMContextImpl.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// DebugLoc Implementation
//===----------------------------------------------------------------------===//

MDNode *NewDebugLoc::getScope(const LLVMContext &Ctx) const {
  if (ScopeIdx == 0) return 0;

  if (ScopeIdx > 0) {
    // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
    // position specified.
    assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
           "Invalid ScopeIdx!");
    return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
  }

  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
}

MDNode *NewDebugLoc::getInlinedAt(const LLVMContext &Ctx) const {
  // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
  // position specified.  Zero is invalid.
  if (ScopeIdx >= 0) return 0;

  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
}

/// Return both the Scope and the InlinedAt values.
void NewDebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
                                       const LLVMContext &Ctx) const {
  if (ScopeIdx == 0) {
    Scope = IA = 0;
    return;
  }

  if (ScopeIdx > 0) {
    // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
    // position specified.
    assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
           "Invalid ScopeIdx!");
    Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
    IA = 0;
    return;
  }

  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
  IA    = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
}

NewDebugLoc NewDebugLoc::get(unsigned Line, unsigned Col,
                             MDNode *Scope, MDNode *InlinedAt) {
  NewDebugLoc Result;

  // If no scope is available, this is an unknown location.
  if (Scope == 0) return Result;

  // Saturate line and col to "unknown".
  if (Col > 255) Col = 0;
  if (Line >= (1 << 24)) Line = 0;
  Result.LineCol = Line | (Col << 24);

  LLVMContext &Ctx = Scope->getContext();

  // If there is no inlined-at location, use the ScopeRecords array.
  if (InlinedAt == 0)
    Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0);
  else
    Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope,
                                                                InlinedAt, 0);

  return Result;
}

/// getAsMDNode - This method converts the compressed DebugLoc node into a
/// DILocation compatible MDNode.
MDNode *NewDebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
  if (isUnknown()) return 0;

  MDNode *Scope, *IA;
  getScopeAndInlinedAt(Scope, IA, Ctx);
  assert(Scope && "If scope is null, this should be isUnknown()");

  LLVMContext &Ctx2 = Scope->getContext();
  const Type *Int32 = Type::getInt32Ty(Ctx2);
  Value *Elts[] = {
    ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()),
    Scope, IA
  };
  return MDNode::get(Ctx2, &Elts[0], 4);
}

/// getFromDILocation - Translate the DILocation quad into a NewDebugLoc.
NewDebugLoc NewDebugLoc::getFromDILocation(MDNode *N) {
  if (N == 0 || N->getNumOperands() != 4) return NewDebugLoc();

  MDNode *Scope = dyn_cast_or_null<MDNode>(N->getOperand(2));
  if (Scope == 0) return NewDebugLoc();

  unsigned LineNo = 0, ColNo = 0;
  if (ConstantInt *Line = dyn_cast_or_null<ConstantInt>(N->getOperand(0)))
    LineNo = Line->getZExtValue();
  if (ConstantInt *Col = dyn_cast_or_null<ConstantInt>(N->getOperand(1)))
    ColNo = Col->getZExtValue();

  return get(LineNo, ColNo, Scope, dyn_cast_or_null<MDNode>(N->getOperand(3)));
}

//===----------------------------------------------------------------------===//
// LLVMContextImpl Implementation
//===----------------------------------------------------------------------===//

int LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope,
                                                 int ExistingIdx) {
  // If we already have an entry for this scope, return it.
  int &Idx = ScopeRecordIdx[Scope];
  if (Idx) return Idx;

  // If we don't have an entry, but ExistingIdx is specified, use it.
  if (ExistingIdx)
    return Idx = ExistingIdx;

  // Otherwise add a new entry.

  // Start out ScopeRecords with a minimal reasonable size to avoid
  // excessive reallocation starting out.
  if (ScopeRecords.empty())
    ScopeRecords.reserve(128);

  // Index is biased by 1 for index.
  Idx = ScopeRecords.size()+1;
  ScopeRecords.push_back(DebugRecVH(Scope, this, Idx));
  return Idx;
}

int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,
                                                    int ExistingIdx) {
  // If we already have an entry, return it.
  int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)];
  if (Idx) return Idx;

  // If we don't have an entry, but ExistingIdx is specified, use it.
  if (ExistingIdx)
    return Idx = ExistingIdx;

  // Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid
  // excessive reallocation starting out.
  if (ScopeInlinedAtRecords.empty())
    ScopeInlinedAtRecords.reserve(128);

  // Index is biased by 1 and negated.
  Idx = -ScopeInlinedAtRecords.size()-1;
  ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx),
                                                 DebugRecVH(IA, this, Idx)));
  return Idx;
}

//===----------------------------------------------------------------------===//
// DebugRecVH Implementation
//===----------------------------------------------------------------------===//

/// deleted - The MDNode this is pointing to got deleted, so this pointer needs
/// to drop to null and we need remove our entry from the DenseMap.
void DebugRecVH::deleted() {
  // If this is a  non-canonical reference, just drop the value to null, we know
  // it doesn't have a map entry.
  if (Idx == 0) {
    setValPtr(0);
    return;
  }

  MDNode *Cur = get();

  // If the index is positive, it is an entry in ScopeRecords.
  if (Idx > 0) {
    assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!");
    Ctx->ScopeRecordIdx.erase(Cur);
    // Reset this VH to null and we're done.
    setValPtr(0);
    Idx = 0;
    return;
  }

  // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
  // is the scope or the inlined-at record entry.
  assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
  std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
  assert((this == &Entry.first || this == &Entry.second) &&
         "Mapping out of date!");

  MDNode *OldScope = Entry.first.get();
  MDNode *OldInlinedAt = Entry.second.get();
  assert(OldScope != 0 && OldInlinedAt != 0 &&
         "Entry should be non-canonical if either val dropped to null");

  // Otherwise, we do have an entry in it, nuke it and we're done.
  assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
         "Mapping out of date");
  Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));

  // Reset this VH to null.  Drop both 'Idx' values to null to indicate that
  // we're in non-canonical form now.
  setValPtr(0);
  Entry.first.Idx = Entry.second.Idx = 0;
}

void DebugRecVH::allUsesReplacedWith(Value *NewVa) {
  // If being replaced with a non-mdnode value (e.g. undef) handle this as if
  // the mdnode got deleted.
  MDNode *NewVal = dyn_cast<MDNode>(NewVa);
  if (NewVal == 0) return deleted();

  // If this is a non-canonical reference, just change it, we know it already
  // doesn't have a map entry.
  if (Idx == 0) {
    setValPtr(NewVa);
    return;
  }

  MDNode *OldVal = get();
  assert(OldVal != NewVa && "Node replaced with self?");

  // If the index is positive, it is an entry in ScopeRecords.
  if (Idx > 0) {
    assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!");
    Ctx->ScopeRecordIdx.erase(OldVal);
    setValPtr(NewVal);

    int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx);

    // If NewVal already has an entry, this becomes a non-canonical reference,
    // just drop Idx to 0 to signify this.
    if (NewEntry != Idx)
      Idx = 0;
    return;
  }

  // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
  // is the scope or the inlined-at record entry.
  assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
  std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
  assert((this == &Entry.first || this == &Entry.second) &&
         "Mapping out of date!");

  MDNode *OldScope = Entry.first.get();
  MDNode *OldInlinedAt = Entry.second.get();
  assert(OldScope != 0 && OldInlinedAt != 0 &&
         "Entry should be non-canonical if either val dropped to null");

  // Otherwise, we do have an entry in it, nuke it and we're done.
  assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
         "Mapping out of date");
  Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));

  // Reset this VH to the new value.
  setValPtr(NewVal);

  int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(),
                                                   Entry.second.get(), Idx);
  // If NewVal already has an entry, this becomes a non-canonical reference,
  // just drop Idx to 0 to signify this.
  if (NewIdx != Idx) {
    std::pair<DebugRecVH, DebugRecVH> &Entry=Ctx->ScopeInlinedAtRecords[-Idx-1];
    Entry.first.Idx = Entry.second.Idx = 0;
  }
}
<|endoftext|>


<commit_before>//===-- Verifier.cpp - Implement the Module Verifier -------------*- C++ -*-==//
//
// This file defines the function verifier interface, that can be used for some
// sanity checking of input to the system.
//
// Note that this does not provide full 'java style' security and verifications,
// instead it just tries to ensure that code is well formed.
//
//  . There are no duplicated names in a symbol table... ie there !exist a val
//    with the same name as something in the symbol table, but with a different
//    address as what is in the symbol table...
//  * Both of a binary operator's parameters are the same type
//  * Verify that the indices of mem access instructions match other operands
//  . Verify that arithmetic and other things are only performed on first class
//    types.  No adding structures or arrays.
//  . All of the constants in a switch statement are of the correct type
//  . The code is in valid SSA form
//  . It should be illegal to put a label into any other type (like a structure)
//    or to return one. [except constant arrays!]
//  * Only phi nodes can be self referential: 'add int %0, %0 ; <int>:0' is bad
//  * PHI nodes must have an entry for each predecessor, with no extras.
//  . All basic blocks should only end with terminator insts, not contain them
//  * The entry node to a function must not have predecessors
//  * All Instructions must be embeded into a basic block
//  . Verify that none of the Value getType()'s are null.
//  . Function's cannot take a void typed parameter
//  * Verify that a function's argument list agrees with it's declared type.
//  . Verify that arrays and structures have fixed elements: No unsized arrays.
//  * It is illegal to specify a name for a void value.
//  * It is illegal to have a internal function that is just a declaration
//  * It is illegal to have a ret instruction that returns a value that does not
//    agree with the function return value type.
//  * All other things that are tested by asserts spread about the code...
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/Verifier.h"
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/BasicBlock.h"
#include "llvm/DerivedTypes.h"
#include "llvm/iPHINode.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/iMemory.h"
#include "llvm/Argument.h"
#include "llvm/SymbolTable.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/InstVisitor.h"
#include "Support/STLExtras.h"
#include <algorithm>

namespace {  // Anonymous namespace for class

  struct Verifier : public FunctionPass, InstVisitor<Verifier> {
    bool Broken;

    Verifier() : Broken(false) {}

    bool doInitialization(Module *M) {
      verifySymbolTable(M->getSymbolTable());
      return false;
    }

    bool runOnFunction(Function *F) {
      visit(F);
      return false;
    }

    bool doFinalization(Module *M) {
      if (Broken) {
        cerr << "Broken module found, compilation aborted!\n";
        abort();
      }
      return false;
    }

    // Verification methods...
    void verifySymbolTable(SymbolTable *ST);
    void visitFunction(Function *F);
    void visitBasicBlock(BasicBlock *BB);
    void visitPHINode(PHINode *PN);
    void visitBinaryOperator(BinaryOperator *B);
    void visitCallInst(CallInst *CI);
    void visitGetElementPtrInst(GetElementPtrInst *GEP);
    void visitLoadInst(LoadInst *LI);
    void visitStoreInst(StoreInst *SI);
    void visitInstruction(Instruction *I);

    // CheckFailed - A check failed, so print out the condition and the message
    // that failed.  This provides a nice place to put a breakpoint if you want
    // to see why something is not correct.
    //
    inline void CheckFailed(const char *Cond, const std::string &Message,
                            const Value *V1 = 0, const Value *V2 = 0) {
      std::cerr << Message << "\n";
      if (V1) { std::cerr << V1 << "\n"; }
      if (V2) { std::cerr << V2 << "\n"; }
      Broken = true;
    }
  };
}

// Assert - We know that cond should be true, if not print an error message.
#define Assert(C, M) \
  do { if (!(C)) { CheckFailed(#C, M); return; } } while (0)
#define Assert1(C, M, V1) \
  do { if (!(C)) { CheckFailed(#C, M, V1); return; } } while (0)
#define Assert2(C, M, V1, V2) \
  do { if (!(C)) { CheckFailed(#C, M, V1, V2); return; } } while (0)

// verifySymbolTable - Verify that a function or module symbol table is ok
//
void Verifier::verifySymbolTable(SymbolTable *ST) {
  if (ST == 0) return;   // No symbol table to process

  // Loop over all of the types in the symbol table...
  for (SymbolTable::iterator TI = ST->begin(), TE = ST->end(); TI != TE; ++TI)
    for (SymbolTable::type_iterator I = TI->second.begin(),
           E = TI->second.end(); I != E; ++I) {
      Value *V = I->second;

      // Check that there are no void typed values in the symbol table.  Values
      // with a void type cannot be put into symbol tables because they cannot
      // have names!
      Assert1(V->getType() != Type::VoidTy,
              "Values with void type are not allowed to have names!\n", V);
    }
}

// visitFunction - Verify that a function is ok.
//
void Verifier::visitFunction(Function *F) {
  if (F->isExternal()) return;
  verifySymbolTable(F->getSymbolTable());

  // Check linkage of function...
  Assert1(!F->isExternal() || F->hasExternalLinkage(),
          "Function cannot be an 'internal' 'declare'ation!", F);

  // Check function arguments...
  const FunctionType *FT = F->getFunctionType();
  const Function::ArgumentListType &ArgList = F->getArgumentList();

  Assert2(!FT->isVarArg(), "Cannot define varargs functions in LLVM!", F, FT);
  Assert2(FT->getParamTypes().size() == ArgList.size(),
          "# formal arguments must match # of arguments for function type!",
          F, FT);

  // Check that the argument values match the function type for this function...
  if (FT->getParamTypes().size() == ArgList.size()) {
    for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
      Assert2(ArgList[i]->getType() == FT->getParamType(i),
              "Argument value does not match function argument type!",
              ArgList[i], FT->getParamType(i));
  }

  // Check the entry node
  BasicBlock *Entry = F->getEntryNode();
  Assert1(pred_begin(Entry) == pred_end(Entry),
          "Entry block to function must not have predecessors!", Entry);
}

// verifyBasicBlock - Verify that a basic block is well formed...
//
void Verifier::visitBasicBlock(BasicBlock *BB) {
  Assert1(BB->getTerminator(), "Basic Block does not have terminator!\n", BB);

  // Check that the terminator is ok as well...
  if (isa<ReturnInst>(BB->getTerminator())) {
    Instruction *I = BB->getTerminator();
    Function *F = I->getParent()->getParent();
    if (I->getNumOperands() == 0)
      Assert1(F->getReturnType() == Type::VoidTy,
              "Function returns no value, but ret instruction found that does!",
              I);
    else
      Assert2(F->getReturnType() == I->getOperand(0)->getType(),
              "Function return type does not match operand "
              "type of return inst!", I, F->getReturnType());
  }
}

// visitPHINode - Ensure that a PHI node is well formed.
void Verifier::visitPHINode(PHINode *PN) {
  std::vector<BasicBlock*> Preds(pred_begin(PN->getParent()),
                                 pred_end(PN->getParent()));
  // Loop over all of the incoming values, make sure that there are
  // predecessors for each one...
  //
  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
    // Make sure all of the incoming values are the right types...
    Assert2(PN->getType() == PN->getIncomingValue(i)->getType(),
            "PHI node argument type does not agree with PHI node type!",
            PN, PN->getIncomingValue(i));

    BasicBlock *BB = PN->getIncomingBlock(i);
    std::vector<BasicBlock*>::iterator PI =
      find(Preds.begin(), Preds.end(), BB);
    Assert2(PI != Preds.end(), "PHI node has entry for basic block that"
            " is not a predecessor!", PN, BB);
    Preds.erase(PI);
  }

  // There should be no entries left in the predecessor list...
  for (std::vector<BasicBlock*>::iterator I = Preds.begin(),
         E = Preds.end(); I != E; ++I)
    Assert2(0, "PHI node does not have entry for a predecessor basic block!",
            PN, *I);

  visitInstruction(PN);
}

void Verifier::visitCallInst(CallInst *CI) {
  Assert1(isa<PointerType>(CI->getOperand(0)->getType()),
          "Called function must be a pointer!", CI);
  PointerType *FPTy = cast<PointerType>(CI->getOperand(0)->getType());
  Assert1(isa<FunctionType>(FPTy->getElementType()),
          "Called function is not pointer to function type!", CI);
}

// visitBinaryOperator - Check that both arguments to the binary operator are
// of the same type!
//
void Verifier::visitBinaryOperator(BinaryOperator *B) {
  Assert2(B->getOperand(0)->getType() == B->getOperand(1)->getType(),
          "Both operands to a binary operator are not of the same type!",
          B->getOperand(0), B->getOperand(1));

  visitInstruction(B);
}

void Verifier::visitGetElementPtrInst(GetElementPtrInst *GEP) {
  const Type *ElTy =MemAccessInst::getIndexedType(GEP->getOperand(0)->getType(),
                                                  GEP->copyIndices(), true);
  Assert1(ElTy, "Invalid indices for GEP pointer type!", GEP);
  Assert2(PointerType::get(ElTy) == GEP->getType(),
          "GEP is not of right type for indices!\n", GEP, ElTy);
  visitInstruction(GEP);
}

void Verifier::visitLoadInst(LoadInst *LI) {
  const Type *ElTy = LoadInst::getIndexedType(LI->getOperand(0)->getType(),
                                              LI->copyIndices());
  Assert1(ElTy, "Invalid indices for load pointer type!", LI);
  Assert2(ElTy == LI->getType(),
          "Load is not of right type for indices!\n", LI, ElTy);
  visitInstruction(LI);
}

void Verifier::visitStoreInst(StoreInst *SI) {
  const Type *ElTy = StoreInst::getIndexedType(SI->getOperand(1)->getType(),
                                               SI->copyIndices());
  Assert1(ElTy, "Invalid indices for store pointer type!", SI);
  Assert2(ElTy == SI->getOperand(0)->getType(),
          "Stored value is not of right type for indices!\n", SI, ElTy);
  visitInstruction(SI);
}

// verifyInstruction - Verify that a non-terminator instruction is well formed.
//
void Verifier::visitInstruction(Instruction *I) {
  assert(I->getParent() && "Instruction not embedded in basic block!");

  // Check that all uses of the instruction, if they are instructions
  // themselves, actually have parent basic blocks.  If the use is not an
  // instruction, it is an error!
  //
  for (User::use_iterator UI = I->use_begin(), UE = I->use_end();
       UI != UE; ++UI) {
    Assert1(isa<Instruction>(*UI), "Use of instruction is not an instruction!",
            *UI);
    Instruction *Used = cast<Instruction>(*UI);
    Assert2(Used->getParent() != 0, "Instruction referencing instruction not"
            " embeded in a basic block!", I, Used);
  }

  if (!isa<PHINode>(I)) {   // Check that non-phi nodes are not self referential
    for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
         UI != UE; ++UI)
      Assert1(*UI != (User*)I,
              "Only PHI nodes may reference their own value!", I);
  }

  Assert1(I->getType() != Type::VoidTy || !I->hasName(),
          "Instruction has a name, but provides a void value!", I);
}

//===----------------------------------------------------------------------===//
//  Implement the public interfaces to this file...
//===----------------------------------------------------------------------===//

Pass *createVerifierPass() {
  return new Verifier();
}

bool verifyFunction(const Function *F) {
  Verifier V;
  V.visit((Function*)F);
  return V.Broken;
}

// verifyModule - Check a module for errors, printing messages on stderr.
// Return true if the module is corrupt.
//
bool verifyModule(const Module *M) {
  Verifier V;
  V.run((Module*)M);
  return V.Broken;
}
<commit_msg>The check to see if an external function was marked internal was not reachable!<commit_after>//===-- Verifier.cpp - Implement the Module Verifier -------------*- C++ -*-==//
//
// This file defines the function verifier interface, that can be used for some
// sanity checking of input to the system.
//
// Note that this does not provide full 'java style' security and verifications,
// instead it just tries to ensure that code is well formed.
//
//  . There are no duplicated names in a symbol table... ie there !exist a val
//    with the same name as something in the symbol table, but with a different
//    address as what is in the symbol table...
//  * Both of a binary operator's parameters are the same type
//  * Verify that the indices of mem access instructions match other operands
//  . Verify that arithmetic and other things are only performed on first class
//    types.  No adding structures or arrays.
//  . All of the constants in a switch statement are of the correct type
//  . The code is in valid SSA form
//  . It should be illegal to put a label into any other type (like a structure)
//    or to return one. [except constant arrays!]
//  * Only phi nodes can be self referential: 'add int %0, %0 ; <int>:0' is bad
//  * PHI nodes must have an entry for each predecessor, with no extras.
//  . All basic blocks should only end with terminator insts, not contain them
//  * The entry node to a function must not have predecessors
//  * All Instructions must be embeded into a basic block
//  . Verify that none of the Value getType()'s are null.
//  . Function's cannot take a void typed parameter
//  * Verify that a function's argument list agrees with it's declared type.
//  . Verify that arrays and structures have fixed elements: No unsized arrays.
//  * It is illegal to specify a name for a void value.
//  * It is illegal to have a internal function that is just a declaration
//  * It is illegal to have a ret instruction that returns a value that does not
//    agree with the function return value type.
//  * All other things that are tested by asserts spread about the code...
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/Verifier.h"
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/BasicBlock.h"
#include "llvm/DerivedTypes.h"
#include "llvm/iPHINode.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/iMemory.h"
#include "llvm/Argument.h"
#include "llvm/SymbolTable.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/InstVisitor.h"
#include "Support/STLExtras.h"
#include <algorithm>

namespace {  // Anonymous namespace for class

  struct Verifier : public FunctionPass, InstVisitor<Verifier> {
    bool Broken;

    Verifier() : Broken(false) {}

    bool doInitialization(Module *M) {
      verifySymbolTable(M->getSymbolTable());
      return false;
    }

    bool runOnFunction(Function *F) {
      visit(F);
      return false;
    }

    bool doFinalization(Module *M) {
      // Scan through, checking all of the external function's linkage now...
      for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
        if ((*I)->isExternal() && (*I)->hasInternalLinkage())
          CheckFailed("", "Function Declaration has Internal Linkage!", (*I));

      if (Broken) {
        cerr << "Broken module found, compilation aborted!\n";
        abort();
      }
      return false;
    }

    // Verification methods...
    void verifySymbolTable(SymbolTable *ST);
    void visitFunction(Function *F);
    void visitBasicBlock(BasicBlock *BB);
    void visitPHINode(PHINode *PN);
    void visitBinaryOperator(BinaryOperator *B);
    void visitCallInst(CallInst *CI);
    void visitGetElementPtrInst(GetElementPtrInst *GEP);
    void visitLoadInst(LoadInst *LI);
    void visitStoreInst(StoreInst *SI);
    void visitInstruction(Instruction *I);

    // CheckFailed - A check failed, so print out the condition and the message
    // that failed.  This provides a nice place to put a breakpoint if you want
    // to see why something is not correct.
    //
    inline void CheckFailed(const char *Cond, const std::string &Message,
                            const Value *V1 = 0, const Value *V2 = 0) {
      std::cerr << Message << "\n";
      if (V1) { std::cerr << V1 << "\n"; }
      if (V2) { std::cerr << V2 << "\n"; }
      Broken = true;
    }
  };
}

// Assert - We know that cond should be true, if not print an error message.
#define Assert(C, M) \
  do { if (!(C)) { CheckFailed(#C, M); return; } } while (0)
#define Assert1(C, M, V1) \
  do { if (!(C)) { CheckFailed(#C, M, V1); return; } } while (0)
#define Assert2(C, M, V1, V2) \
  do { if (!(C)) { CheckFailed(#C, M, V1, V2); return; } } while (0)

// verifySymbolTable - Verify that a function or module symbol table is ok
//
void Verifier::verifySymbolTable(SymbolTable *ST) {
  if (ST == 0) return;   // No symbol table to process

  // Loop over all of the types in the symbol table...
  for (SymbolTable::iterator TI = ST->begin(), TE = ST->end(); TI != TE; ++TI)
    for (SymbolTable::type_iterator I = TI->second.begin(),
           E = TI->second.end(); I != E; ++I) {
      Value *V = I->second;

      // Check that there are no void typed values in the symbol table.  Values
      // with a void type cannot be put into symbol tables because they cannot
      // have names!
      Assert1(V->getType() != Type::VoidTy,
              "Values with void type are not allowed to have names!\n", V);
    }
}

// visitFunction - Verify that a function is ok.
//
void Verifier::visitFunction(Function *F) {
  if (F->isExternal()) return;

  verifySymbolTable(F->getSymbolTable());

  // Check function arguments...
  const FunctionType *FT = F->getFunctionType();
  const Function::ArgumentListType &ArgList = F->getArgumentList();

  Assert2(!FT->isVarArg(), "Cannot define varargs functions in LLVM!", F, FT);
  Assert2(FT->getParamTypes().size() == ArgList.size(),
          "# formal arguments must match # of arguments for function type!",
          F, FT);

  // Check that the argument values match the function type for this function...
  if (FT->getParamTypes().size() == ArgList.size()) {
    for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
      Assert2(ArgList[i]->getType() == FT->getParamType(i),
              "Argument value does not match function argument type!",
              ArgList[i], FT->getParamType(i));
  }

  // Check the entry node
  BasicBlock *Entry = F->getEntryNode();
  Assert1(pred_begin(Entry) == pred_end(Entry),
          "Entry block to function must not have predecessors!", Entry);
}

// verifyBasicBlock - Verify that a basic block is well formed...
//
void Verifier::visitBasicBlock(BasicBlock *BB) {
  Assert1(BB->getTerminator(), "Basic Block does not have terminator!\n", BB);

  // Check that the terminator is ok as well...
  if (isa<ReturnInst>(BB->getTerminator())) {
    Instruction *I = BB->getTerminator();
    Function *F = I->getParent()->getParent();
    if (I->getNumOperands() == 0)
      Assert1(F->getReturnType() == Type::VoidTy,
              "Function returns no value, but ret instruction found that does!",
              I);
    else
      Assert2(F->getReturnType() == I->getOperand(0)->getType(),
              "Function return type does not match operand "
              "type of return inst!", I, F->getReturnType());
  }
}

// visitPHINode - Ensure that a PHI node is well formed.
void Verifier::visitPHINode(PHINode *PN) {
  std::vector<BasicBlock*> Preds(pred_begin(PN->getParent()),
                                 pred_end(PN->getParent()));
  // Loop over all of the incoming values, make sure that there are
  // predecessors for each one...
  //
  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
    // Make sure all of the incoming values are the right types...
    Assert2(PN->getType() == PN->getIncomingValue(i)->getType(),
            "PHI node argument type does not agree with PHI node type!",
            PN, PN->getIncomingValue(i));

    BasicBlock *BB = PN->getIncomingBlock(i);
    std::vector<BasicBlock*>::iterator PI =
      find(Preds.begin(), Preds.end(), BB);
    Assert2(PI != Preds.end(), "PHI node has entry for basic block that"
            " is not a predecessor!", PN, BB);
    Preds.erase(PI);
  }

  // There should be no entries left in the predecessor list...
  for (std::vector<BasicBlock*>::iterator I = Preds.begin(),
         E = Preds.end(); I != E; ++I)
    Assert2(0, "PHI node does not have entry for a predecessor basic block!",
            PN, *I);

  visitInstruction(PN);
}

void Verifier::visitCallInst(CallInst *CI) {
  Assert1(isa<PointerType>(CI->getOperand(0)->getType()),
          "Called function must be a pointer!", CI);
  PointerType *FPTy = cast<PointerType>(CI->getOperand(0)->getType());
  Assert1(isa<FunctionType>(FPTy->getElementType()),
          "Called function is not pointer to function type!", CI);
}

// visitBinaryOperator - Check that both arguments to the binary operator are
// of the same type!
//
void Verifier::visitBinaryOperator(BinaryOperator *B) {
  Assert2(B->getOperand(0)->getType() == B->getOperand(1)->getType(),
          "Both operands to a binary operator are not of the same type!",
          B->getOperand(0), B->getOperand(1));

  visitInstruction(B);
}

void Verifier::visitGetElementPtrInst(GetElementPtrInst *GEP) {
  const Type *ElTy =MemAccessInst::getIndexedType(GEP->getOperand(0)->getType(),
                                                  GEP->copyIndices(), true);
  Assert1(ElTy, "Invalid indices for GEP pointer type!", GEP);
  Assert2(PointerType::get(ElTy) == GEP->getType(),
          "GEP is not of right type for indices!\n", GEP, ElTy);
  visitInstruction(GEP);
}

void Verifier::visitLoadInst(LoadInst *LI) {
  const Type *ElTy = LoadInst::getIndexedType(LI->getOperand(0)->getType(),
                                              LI->copyIndices());
  Assert1(ElTy, "Invalid indices for load pointer type!", LI);
  Assert2(ElTy == LI->getType(),
          "Load is not of right type for indices!\n", LI, ElTy);
  visitInstruction(LI);
}

void Verifier::visitStoreInst(StoreInst *SI) {
  const Type *ElTy = StoreInst::getIndexedType(SI->getOperand(1)->getType(),
                                               SI->copyIndices());
  Assert1(ElTy, "Invalid indices for store pointer type!", SI);
  Assert2(ElTy == SI->getOperand(0)->getType(),
          "Stored value is not of right type for indices!\n", SI, ElTy);
  visitInstruction(SI);
}

// verifyInstruction - Verify that a non-terminator instruction is well formed.
//
void Verifier::visitInstruction(Instruction *I) {
  assert(I->getParent() && "Instruction not embedded in basic block!");

  // Check that all uses of the instruction, if they are instructions
  // themselves, actually have parent basic blocks.  If the use is not an
  // instruction, it is an error!
  //
  for (User::use_iterator UI = I->use_begin(), UE = I->use_end();
       UI != UE; ++UI) {
    Assert1(isa<Instruction>(*UI), "Use of instruction is not an instruction!",
            *UI);
    Instruction *Used = cast<Instruction>(*UI);
    Assert2(Used->getParent() != 0, "Instruction referencing instruction not"
            " embeded in a basic block!", I, Used);
  }

  if (!isa<PHINode>(I)) {   // Check that non-phi nodes are not self referential
    for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
         UI != UE; ++UI)
      Assert1(*UI != (User*)I,
              "Only PHI nodes may reference their own value!", I);
  }

  Assert1(I->getType() != Type::VoidTy || !I->hasName(),
          "Instruction has a name, but provides a void value!", I);
}

//===----------------------------------------------------------------------===//
//  Implement the public interfaces to this file...
//===----------------------------------------------------------------------===//

Pass *createVerifierPass() {
  return new Verifier();
}

bool verifyFunction(const Function *F) {
  Verifier V;
  V.visit((Function*)F);
  return V.Broken;
}

// verifyModule - Check a module for errors, printing messages on stderr.
// Return true if the module is corrupt.
//
bool verifyModule(const Module *M) {
  Verifier V;
  V.run((Module*)M);
  return V.Broken;
}
<|endoftext|>


<commit_before>#include <x0/SocketSpec.h>

namespace x0 {

SocketSpec::SocketSpec() :
	address(),
	port(-1),
	backlog(-1),
	valid(false)
{
}

void SocketSpec::clear()
{
	address = IPAddress();
	local.clear();

	port = -1;
	backlog = -1;
	valid = false;
}

std::string SocketSpec::str() const
{
	if (isLocal()) {
		return "unix:" + local;
	} else {
		char buf[256];
		snprintf(buf, sizeof(buf), "%s, port %d", address.str().c_str(), port);
		return buf;
	}
}

} // namespace x0
<commit_msg>[base] SocketSpec: prettify result of str()<commit_after>#include <x0/SocketSpec.h>

namespace x0 {

SocketSpec::SocketSpec() :
	address(),
	port(-1),
	backlog(-1),
	valid(false)
{
}

void SocketSpec::clear()
{
	address = IPAddress();
	local.clear();

	port = -1;
	backlog = -1;
	valid = false;
}

std::string SocketSpec::str() const
{
	if (isLocal()) {
		return "unix:" + local;
	} else {
		char buf[256];
		if (address.family() == IPAddress::V4)
			snprintf(buf, sizeof(buf), "%s:%d", address.str().c_str(), port);
		else
			snprintf(buf, sizeof(buf), "[%s]:%d", address.str().c_str(), port);
		return buf;
	}
}

} // namespace x0
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include "AveragingFilter.h"
#include "myo\myo.hpp"

#ifdef USE_SIMULATOR
#include "MyoSimIncludes.hpp"
using namespace myoSim;
#else
using namespace myo;
#endif

AveragingFilter::AveragingFilter() : avgCount(DEFAULT_AVG_COUNT) {}

AveragingFilter::AveragingFilter(unsigned int avgCount) : avgCount(avgCount) {}

AveragingFilter::~AveragingFilter() {}

void AveragingFilter::setAvgCount(unsigned int avgCount)
{
    this->avgCount = avgCount;
}

unsigned int AveragingFilter::getAvgCount() const
{
    return avgCount;
}

void AveragingFilter::process()
{
    filterDataMap input = Filter::getInput();

    float quatX  = boost::any_cast<float>(input[QUAT_DATA_X ]);
    float quatY  = boost::any_cast<float>(input[QUAT_DATA_Y ]);
    float quatZ  = boost::any_cast<float>(input[QUAT_DATA_Z ]);
    float quatW  = boost::any_cast<float>(input[QUAT_DATA_W ]);
    float accelX = boost::any_cast<float>(input[ACCEL_DATA_X]);
    float accelY = boost::any_cast<float>(input[ACCEL_DATA_Y]);
    float accelZ = boost::any_cast<float>(input[ACCEL_DATA_Z]);
    float gyroX  = boost::any_cast<float>(input[GYRO_DATA_X ]);
    float gyroY  = boost::any_cast<float>(input[GYRO_DATA_Y ]);
    float gyroZ  = boost::any_cast<float>(input[GYRO_DATA_Z ]);
    int8_t rssi  = boost::any_cast<int8_t>(input[RSSI]);

    Arm arm = boost::any_cast<Arm>(input[INPUT_ARM]);
    XDirection xDirection = boost::any_cast<XDirection>(input[INPUT_X_DIRECTION]);

    insertAvgElement(quatX, quatXDeque);
    insertAvgElement(quatY, quatYDeque);
    insertAvgElement(quatZ, quatZDeque);
    insertAvgElement(quatW, quatWDeque);
    insertAvgElement(accelX,accelXDeque);
    insertAvgElement(accelY,accelYDeque);
    insertAvgElement(accelZ,accelZDeque);
    insertAvgElement(gyroX, gyroXDeque);
    insertAvgElement(gyroY, gyroYDeque);
    insertAvgElement(gyroZ, gyroZDeque);
    insertAvgElement((float)rssi, rssiDeque);

    filterDataMap output;

    output[QUAT_DATA_X]  = calcAvg(quatXDeque);
    output[QUAT_DATA_Y]  = calcAvg(quatYDeque);
    output[QUAT_DATA_Z]  = calcAvg(quatZDeque);
    output[QUAT_DATA_W]  = calcAvg(quatWDeque);
    output[ACCEL_DATA_X] = calcAvg(accelXDeque);
    output[ACCEL_DATA_Y] = calcAvg(accelYDeque);
    output[ACCEL_DATA_Z] = calcAvg(accelZDeque);
    output[GYRO_DATA_X]  = calcAvg(gyroXDeque);
    output[GYRO_DATA_Y]  = calcAvg(gyroYDeque);
    output[GYRO_DATA_Z]  = calcAvg(gyroZDeque);
    float tempRssiAvg = calcAvg(rssiDeque);
    output[RSSI] = tempRssiAvg;
    output[INPUT_ARM] = arm;
    output[INPUT_X_DIRECTION] = xDirection;

    if (rssi != (int8_t)0)
    {
        std::ofstream file_stream;
        file_stream.open("testRssiAVG.txt", std::ios::out | std::ios::app);
        file_stream << tempRssiAvg << std::endl;
        file_stream.close();
    }

    Filter::setOutput(output);
}

void AveragingFilter::insertAvgElement(float elem, std::deque<float>& dq)
{
    dq.push_back(elem);
    while (dq.size() > avgCount) {
        // discard element so that average is only based on
        // avgCount elements.
        dq.pop_front();
    }
}

float AveragingFilter::calcAvg(std::deque<float>& dq)
{
    float sum = 0;
    float denom = dq.size();
    if (denom == 0)
    {
        return 0;
    }

    std::deque<float>::iterator it = dq.begin();
    while (it != dq.end())
    {
        sum += *it++;
    }
    return (float)sum / denom;
}
<commit_msg>add comment<commit_after>#include <fstream>
#include <iostream>
#include "AveragingFilter.h"
#include "myo\myo.hpp"

#ifdef USE_SIMULATOR
#include "MyoSimIncludes.hpp"
using namespace myoSim;
#else
using namespace myo;
#endif

AveragingFilter::AveragingFilter() : avgCount(DEFAULT_AVG_COUNT) {}

AveragingFilter::AveragingFilter(unsigned int avgCount) : avgCount(avgCount) {}

AveragingFilter::~AveragingFilter() {}

void AveragingFilter::setAvgCount(unsigned int avgCount)
{
    this->avgCount = avgCount;
}

unsigned int AveragingFilter::getAvgCount() const
{
    return avgCount;
}

void AveragingFilter::process()
{
    filterDataMap input = Filter::getInput();

    float quatX  = boost::any_cast<float>(input[QUAT_DATA_X ]);
    float quatY  = boost::any_cast<float>(input[QUAT_DATA_Y ]);
    float quatZ  = boost::any_cast<float>(input[QUAT_DATA_Z ]);
    float quatW  = boost::any_cast<float>(input[QUAT_DATA_W ]);
    float accelX = boost::any_cast<float>(input[ACCEL_DATA_X]);
    float accelY = boost::any_cast<float>(input[ACCEL_DATA_Y]);
    float accelZ = boost::any_cast<float>(input[ACCEL_DATA_Z]);
    float gyroX  = boost::any_cast<float>(input[GYRO_DATA_X ]);
    float gyroY  = boost::any_cast<float>(input[GYRO_DATA_Y ]);
    float gyroZ  = boost::any_cast<float>(input[GYRO_DATA_Z ]);
    int8_t rssi  = boost::any_cast<int8_t>(input[RSSI]);

    Arm arm = boost::any_cast<Arm>(input[INPUT_ARM]);
    XDirection xDirection = boost::any_cast<XDirection>(input[INPUT_X_DIRECTION]);

    insertAvgElement(quatX, quatXDeque);
    insertAvgElement(quatY, quatYDeque);
    insertAvgElement(quatZ, quatZDeque);
    insertAvgElement(quatW, quatWDeque);
    insertAvgElement(accelX,accelXDeque);
    insertAvgElement(accelY,accelYDeque);
    insertAvgElement(accelZ,accelZDeque);
    insertAvgElement(gyroX, gyroXDeque);
    insertAvgElement(gyroY, gyroYDeque);
    insertAvgElement(gyroZ, gyroZDeque);
    insertAvgElement((float)rssi, rssiDeque);

    filterDataMap output;

    output[QUAT_DATA_X]  = calcAvg(quatXDeque);
    output[QUAT_DATA_Y]  = calcAvg(quatYDeque);
    output[QUAT_DATA_Z]  = calcAvg(quatZDeque);
    output[QUAT_DATA_W]  = calcAvg(quatWDeque);
    output[ACCEL_DATA_X] = calcAvg(accelXDeque);
    output[ACCEL_DATA_Y] = calcAvg(accelYDeque);
    output[ACCEL_DATA_Z] = calcAvg(accelZDeque);
    output[GYRO_DATA_X]  = calcAvg(gyroXDeque);
    output[GYRO_DATA_Y]  = calcAvg(gyroYDeque);
    output[GYRO_DATA_Z]  = calcAvg(gyroZDeque);
    float tempRssiAvg = calcAvg(rssiDeque); /* This is here just to print to txt file. Remove when done */
    output[RSSI] = tempRssiAvg;
    output[INPUT_ARM] = arm;
    output[INPUT_X_DIRECTION] = xDirection;

    if (rssi != (int8_t)0)
    {
        std::ofstream file_stream;
        file_stream.open("testRssiAVG.txt", std::ios::out | std::ios::app);
        file_stream << tempRssiAvg << std::endl;
        file_stream.close();
    }

    Filter::setOutput(output);
}

void AveragingFilter::insertAvgElement(float elem, std::deque<float>& dq)
{
    dq.push_back(elem);
    while (dq.size() > avgCount) {
        // discard element so that average is only based on
        // avgCount elements.
        dq.pop_front();
    }
}

float AveragingFilter::calcAvg(std::deque<float>& dq)
{
    float sum = 0;
    float denom = dq.size();
    if (denom == 0)
    {
        return 0;
    }

    std::deque<float>::iterator it = dq.begin();
    while (it != dq.end())
    {
        sum += *it++;
    }
    return (float)sum / denom;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "folderlistmodel.h"
#include <QMailAccount>
#include <QMailFolder>
#include <QMailMessage>
#include <QMailMessageKey>
#include <QMailStore>
#include <QDateTime>
#include <QTimer>
#include <QProcess>
#include <qmailnamespace.h>
#include <libedataserver/e-account-list.h>
#include <libedataserver/e-list.h>
#include <gconf/gconf-client.h>

FolderListModel::FolderListModel(QObject *parent) :
    QAbstractListModel(parent)
{
    QHash<int, QByteArray> roles;
    roles.insert(FolderName, "folderName");
    roles.insert(FolderId, "folderId");
    roles.insert(FolderUnreadCount, "folderUnreadCount");
    roles.insert(FolderServerCount, "folderServerCount");
    setRoleNames(roles);
}

FolderListModel::~FolderListModel()
{
}

int FolderListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_folderlist.count();
}

QVariant FolderListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() > m_folderlist.count())
        return QVariant();

    CamelFolderInfoVariant  folder(m_folderlist[index.row()]);
    if (role == FolderName)
    {
        return QVariant(folder.full_name);
    }
    else if (role == FolderId)
    {
        return QVariant(folder.uri);
    }
    else if (role == FolderUnreadCount)
    {
        return QVariant (folder.unread_count);
    }
    else if (role == FolderServerCount)
    {
        return (folder.total_mail_count);
    }

    return QVariant();
}

EAccount * FolderListModel::getAccountById(EAccountList *account_list, char *id)
{
    EIterator *iter;
    EAccount *account = NULL;

    iter = e_list_get_iterator (E_LIST (account_list));
    while (e_iterator_is_valid (iter)) {
        account = (EAccount *) e_iterator_get (iter);
        if (strcmp (id, account->uid) == 0)
             return account;
        e_iterator_next (iter);
    }

    g_object_unref (iter);

    return NULL;
}

void FolderListModel::setAccountKey(QVariant id)
{
    GConfClient *client;
    EAccountList *account_list;
    QString quid;
    const char *url;

    client = gconf_client_get_default ();
    account_list = e_account_list_new (client);
    g_object_unref (client);

    quid = id.value<QString>();
    m_account = getAccountById (account_list, (char *)quid.toLocal8Bit().constData());
    url = e_account_get_string (m_account, E_ACCOUNT_SOURCE_URL);

    g_print ("fetching store: %s\n", url);
    OrgGnomeEvolutionDataserverMailSessionInterface *instance = OrgGnomeEvolutionDataserverMailSessionInterface::instance(this);
    if (instance && instance->isValid()) {
	QDBusPendingReply<QDBusObjectPath> reply = instance->getStore (QString(url));
        reply.waitForFinished();
        m_store_proxy_id = reply.value();
	g_print ("Store PATH: %s\n", (char *) m_store_proxy_id.path().toLocal8Bit().constData());
        m_store_proxy = new OrgGnomeEvolutionDataserverMailStoreInterface (QString ("org.gnome.evolution.dataserver.Mail"),
									m_store_proxy_id.path(),
									QDBusConnection::sessionBus(), this);

	if (m_store_proxy && m_store_proxy->isValid()) {
		QDBusPendingReply<CamelFolderInfoArrayVariant> reply = m_store_proxy->getFolderInfo (QString(""),
									CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED);
		reply.waitForFinished();
		m_folderlist = reply.value ();
	g_print ("Got folder list....\n");

	}
    }
}

QStringList FolderListModel::folderNames()
{
    QStringList folderNames;

    foreach (CamelFolderInfoVariant fInfo, m_folderlist)
    {
        QString displayName = QString (fInfo.full_name);

        if (fInfo.unread_count > 0)
        {
            displayName = displayName + " (" + QString::number(fInfo.unread_count) + ")";
        }

        folderNames << displayName;
	g_print("FOLDER: %s\n", (char *)displayName.toLocal8Bit().constData());
    }
    return folderNames;
}

QVariant FolderListModel::folderId(int index)
{
    if (index < 0 || index >= m_folderlist.count())
        return QVariant();

    return m_folderlist[index].uri;
}

int FolderListModel::indexFromFolderId(QVariant vFolderId)
{

    QString uri = vFolderId.toString();
    g_print ("Entering FolderListModel::indexFromFolderId: %s\n", (char *)uri.toLocal8Bit().constData());
    for (int i = 0; i < m_folderlist.size(); i ++)
    {
        if (vFolderId == 0) {
	        CamelFolderInfoVariant folder(m_folderlist[i]);
        	if (QString::compare(folder.full_name, "INBOX", Qt::CaseInsensitive) == 0)
			return i;

	} else {
        	if (uri == m_folderlist[i].uri)
            		return i;
	}
    }
    return -1;
}

QVariant FolderListModel::folderServerCount(QVariant vFolderId)
{
    QString uri = vFolderId.toString();

    for (int i = 0; i < m_folderlist.size(); i ++)
    {
        if (uri == m_folderlist[i].uri)
            return QVariant(m_folderlist[i].total_mail_count);
    }
    return QVariant(-1);
}

QVariant FolderListModel::inboxFolderId()
{
    for (int i = 0; i < m_folderlist.size(); i++)
    {
        CamelFolderInfoVariant folder(m_folderlist[i]);
        if (QString::compare(folder.full_name, "INBOX", Qt::CaseInsensitive) == 0) {
	    g_print ("Returning INBOX URI: %s\n", (char *)folder.uri.toLocal8Bit().constData());
            return QVariant(folder.uri);
	}
    }

    return QVariant();
}

QVariant FolderListModel::inboxFolderName()
{
    for (int i = 0; i < m_folderlist.size(); i++)
    {
        CamelFolderInfoVariant folder(m_folderlist[i]);

       if (QString::compare(folder.full_name, "INBOX", Qt::CaseInsensitive) == 0) {
            g_print ("Returning INBOX URI: %s\n", (char *)folder.uri.toLocal8Bit().constData());
            return QVariant(folder.folder_name);
        }
    }
    return QVariant("");
}

int FolderListModel::totalNumberOfFolders()
{
    return m_folderlist.size();
}
<commit_msg>Show the total count properly<commit_after>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "folderlistmodel.h"
#include <QMailAccount>
#include <QMailFolder>
#include <QMailMessage>
#include <QMailMessageKey>
#include <QMailStore>
#include <QDateTime>
#include <QTimer>
#include <QProcess>
#include <qmailnamespace.h>
#include <libedataserver/e-account-list.h>
#include <libedataserver/e-list.h>
#include <gconf/gconf-client.h>

FolderListModel::FolderListModel(QObject *parent) :
    QAbstractListModel(parent)
{
    QHash<int, QByteArray> roles;
    roles.insert(FolderName, "folderName");
    roles.insert(FolderId, "folderId");
    roles.insert(FolderUnreadCount, "folderUnreadCount");
    roles.insert(FolderServerCount, "folderServerCount");
    setRoleNames(roles);
}

FolderListModel::~FolderListModel()
{
}

int FolderListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_folderlist.count();
}

QVariant FolderListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() > m_folderlist.count())
        return QVariant();

    CamelFolderInfoVariant  folder(m_folderlist[index.row()]);
    if (role == FolderName)
    {
        return QVariant(folder.full_name);
    }
    else if (role == FolderId)
    {
        return QVariant(folder.uri);
    }
    else if (role == FolderUnreadCount)
    {
        return QVariant ((folder.unread_count == -1) ? 0 : folder.unread_count );
    }
    else if (role == FolderServerCount)
    {
        return QVariant ((folder.total_mail_count == -1) ? 0 : folder.total_mail_count);
    }

    return QVariant();
}

EAccount * FolderListModel::getAccountById(EAccountList *account_list, char *id)
{
    EIterator *iter;
    EAccount *account = NULL;

    iter = e_list_get_iterator (E_LIST (account_list));
    while (e_iterator_is_valid (iter)) {
        account = (EAccount *) e_iterator_get (iter);
        if (strcmp (id, account->uid) == 0)
             return account;
        e_iterator_next (iter);
    }

    g_object_unref (iter);

    return NULL;
}

void FolderListModel::setAccountKey(QVariant id)
{
    GConfClient *client;
    EAccountList *account_list;
    QString quid;
    const char *url;

    client = gconf_client_get_default ();
    account_list = e_account_list_new (client);
    g_object_unref (client);

    quid = id.value<QString>();
    m_account = getAccountById (account_list, (char *)quid.toLocal8Bit().constData());
    url = e_account_get_string (m_account, E_ACCOUNT_SOURCE_URL);

    g_print ("fetching store: %s\n", url);
    OrgGnomeEvolutionDataserverMailSessionInterface *instance = OrgGnomeEvolutionDataserverMailSessionInterface::instance(this);
    if (instance && instance->isValid()) {
	QDBusPendingReply<QDBusObjectPath> reply = instance->getStore (QString(url));
        reply.waitForFinished();
        m_store_proxy_id = reply.value();
	g_print ("Store PATH: %s\n", (char *) m_store_proxy_id.path().toLocal8Bit().constData());
        m_store_proxy = new OrgGnomeEvolutionDataserverMailStoreInterface (QString ("org.gnome.evolution.dataserver.Mail"),
									m_store_proxy_id.path(),
									QDBusConnection::sessionBus(), this);

	if (m_store_proxy && m_store_proxy->isValid()) {
		QDBusPendingReply<CamelFolderInfoArrayVariant> reply = m_store_proxy->getFolderInfo (QString(""),
									CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED);
		reply.waitForFinished();
		m_folderlist = reply.value ();
	g_print ("Got folder list....\n");

	}
    }
}

QStringList FolderListModel::folderNames()
{
    QStringList folderNames;

    foreach (CamelFolderInfoVariant fInfo, m_folderlist)
    {
        QString displayName = QString (fInfo.full_name);

        if (fInfo.unread_count > 0)
        {
            displayName = displayName + " (" + QString::number(fInfo.unread_count) + ")";
        }

        folderNames << displayName;
	g_print("FOLDER: %s\n", (char *)displayName.toLocal8Bit().constData());
    }
    return folderNames;
}

QVariant FolderListModel::folderId(int index)
{
    if (index < 0 || index >= m_folderlist.count())
        return QVariant();

    return m_folderlist[index].uri;
}

int FolderListModel::indexFromFolderId(QVariant vFolderId)
{

    QString uri = vFolderId.toString();
    g_print ("Entering FolderListModel::indexFromFolderId: %s\n", (char *)uri.toLocal8Bit().constData());
    for (int i = 0; i < m_folderlist.size(); i ++)
    {
        if (vFolderId == 0) {
	        CamelFolderInfoVariant folder(m_folderlist[i]);
        	if (QString::compare(folder.full_name, "INBOX", Qt::CaseInsensitive) == 0)
			return i;

	} else {
        	if (uri == m_folderlist[i].uri)
            		return i;
	}
    }
    return -1;
}

QVariant FolderListModel::folderServerCount(QVariant vFolderId)
{
    QString uri = vFolderId.toString();

    for (int i = 0; i < m_folderlist.size(); i ++)
    {
        if (uri == m_folderlist[i].uri)
            return QVariant(m_folderlist[i].total_mail_count);
    }
    return QVariant(-1);
}

QVariant FolderListModel::inboxFolderId()
{
    for (int i = 0; i < m_folderlist.size(); i++)
    {
        CamelFolderInfoVariant folder(m_folderlist[i]);
        if (QString::compare(folder.full_name, "INBOX", Qt::CaseInsensitive) == 0) {
	    g_print ("Returning INBOX URI: %s\n", (char *)folder.uri.toLocal8Bit().constData());
            return QVariant(folder.uri);
	}
    }

    return QVariant();
}

QVariant FolderListModel::inboxFolderName()
{
    for (int i = 0; i < m_folderlist.size(); i++)
    {
        CamelFolderInfoVariant folder(m_folderlist[i]);

       if (QString::compare(folder.full_name, "INBOX", Qt::CaseInsensitive) == 0) {
            g_print ("Returning INBOX URI: %s\n", (char *)folder.uri.toLocal8Bit().constData());
            return QVariant(folder.folder_name);
        }
    }
    return QVariant("");
}

int FolderListModel::totalNumberOfFolders()
{
    return m_folderlist.size();
}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "../include/mana/server.hpp"
#include <statman>

// #define DEBUG

using namespace mana;
using namespace std::chrono;

Server::Server(net::TCP& tcp, std::chrono::seconds timeout)
  : server_{tcp, {this, &Server::handle_request}, timeout}
{
}

Router& Server::router() noexcept {
  return router_;
}

void Server::process(Request_ptr req, Response_ptr res) {
  auto it_ptr = std::make_shared<MiddlewareStack::iterator>(middleware_.begin());
  auto next = std::make_shared<next_t>();
  auto weak_next = std::weak_ptr<next_t>(next);
  // setup Next callback
  *next = next_t::make_packed(
  [this, it_ptr, weak_next, req, res]
  {
    // derefence the pointer to the iterator
    auto& it = *it_ptr;

    // skip those who don't match
    while(it != middleware_.end() and !path_starts_with(req->uri(), it->path))
      it++;

    // while there is more to do
    if(it != middleware_.end()) {
      // dereference the function
      auto& func = it->callback;
      // advance the iterator for the next next-call
      it++;
      auto next = weak_next.lock(); // this should be safe since we're inside next
      // execute the function
      func(req, res, next);
    }
    // no more middleware, proceed with route processing
    else {
      process_route(req, res);
    }
  });
  // get the party started..
  (*next)();
}

void Server::process_route(Request_ptr req, Response_ptr res) {
  try {
    auto parsed_route = router_.match(req->method(), req->uri());
    req->set_params(parsed_route.parsed_values);
    parsed_route.job(req, res);
  }
  catch (const Router_error& err) {
    printf("<Server> Router_error: %s - Responding with 404.\n", err.what());
    res->send_code(http::Not_Found, true);
  }
}

void Server::use(const Path& path, Middleware_ptr mw_ptr) {
  mw_storage_.push_back(mw_ptr);
  mw_ptr->on_mount(path);
  use(path, mw_ptr->handler());
}

void Server::use(const Path& path, Callback callback) {
  middleware_.emplace_back(path, callback);
}

void Server::handle_request(http::Request_ptr request, http::Response_writer_ptr hrw)
{
  auto req = std::make_shared<mana::Request>(std::move(request));
  auto res = std::make_shared<mana::Response>(std::move(hrw));
  process(std::move(req), std::move(res));
}
<commit_msg>mana: Disable output when no route<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "../include/mana/server.hpp"
#include <statman>

// #define DEBUG

using namespace mana;
using namespace std::chrono;

Server::Server(net::TCP& tcp, std::chrono::seconds timeout)
  : server_{tcp, {this, &Server::handle_request}, timeout}
{
}

Router& Server::router() noexcept {
  return router_;
}

void Server::process(Request_ptr req, Response_ptr res) {
  auto it_ptr = std::make_shared<MiddlewareStack::iterator>(middleware_.begin());
  auto next = std::make_shared<next_t>();
  auto weak_next = std::weak_ptr<next_t>(next);
  // setup Next callback
  *next = next_t::make_packed(
  [this, it_ptr, weak_next, req, res]
  {
    // derefence the pointer to the iterator
    auto& it = *it_ptr;

    // skip those who don't match
    while(it != middleware_.end() and !path_starts_with(req->uri(), it->path))
      it++;

    // while there is more to do
    if(it != middleware_.end()) {
      // dereference the function
      auto& func = it->callback;
      // advance the iterator for the next next-call
      it++;
      auto next = weak_next.lock(); // this should be safe since we're inside next
      // execute the function
      func(req, res, next);
    }
    // no more middleware, proceed with route processing
    else {
      process_route(req, res);
    }
  });
  // get the party started..
  (*next)();
}

void Server::process_route(Request_ptr req, Response_ptr res) {
  try {
    auto parsed_route = router_.match(req->method(), req->uri());
    req->set_params(parsed_route.parsed_values);
    parsed_route.job(req, res);
  }
  catch (const Router_error& err) {
    res->send_code(http::Not_Found, true);
  }
}

void Server::use(const Path& path, Middleware_ptr mw_ptr) {
  mw_storage_.push_back(mw_ptr);
  mw_ptr->on_mount(path);
  use(path, mw_ptr->handler());
}

void Server::use(const Path& path, Callback callback) {
  middleware_.emplace_back(path, callback);
}

void Server::handle_request(http::Request_ptr request, http::Response_writer_ptr hrw)
{
  auto req = std::make_shared<mana::Request>(std::move(request));
  auto res = std::make_shared<mana::Response>(std::move(hrw));
  process(std::move(req), std::move(res));
}
<|endoftext|>