<commit_before>#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::tooling;
using namespace llvm;
using namespace std;

static unordered_set<string> potentialReplacements;
static unordered_map<string,string> replacements;
static bool replaceAll = false;

/////////////////////////
// COMMAND-LINE OPTIONS
/////////////////////////

static cl::OptionCategory ReplaceToolCategory("Replacer Options");
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
//static cl::extrahelp MoreHelp("\nMore help text...");

static cl::list<string> functionsToReplace(
      "f",
      cl::desc("function to replace"),
      cl::ZeroOrMore,
      cl::cat(ReplaceToolCategory));

static cl::list<string> replacementFiles(
      "r",
      cl::desc("replacement file"),
      cl::ZeroOrMore,
      cl::cat(ReplaceToolCategory));

static cl::opt<bool> dumpFunctions(
      "d",
      cl::desc("Dump the functions defined in the specified files"),
      cl::cat(ReplaceToolCategory));

static cl::opt<bool> canonicalTypes(
      "c",
      cl::desc("Print canonicalized types"),
      cl::cat(ReplaceToolCategory));

const char * const ADDITIONAL_HELP = "Replaces designated functions or member functions in C++ source";

//////////////////////
// HELPER FUNCTIONS
//////////////////////

std::string nameOfType(PrintingPolicy Policy, QualType ty)
{
  if (canonicalTypes) ty = ty.getCanonicalType();
  return ty.getAsString(Policy);
}

// Converts the AST for a function declaration into
//   a human-readable (i.e., demangled) string representation.
//
std::string nameOfDecl(PrintingPolicy Policy, FunctionDecl* f, bool showReturnTy = false)
{
  std::string funcName = f->getQualifiedNameAsString();
  std::string fullName = funcName + "(";
  ArrayRef<ParmVarDecl*> parameters = f->parameters();

  for (const auto& pvd : parameters) {
    if (&pvd != &parameters[0]) fullName += ", ";
    fullName += nameOfType(Policy, pvd->getType());
  }
  fullName += ")";

  if (CXXMethodDecl* m = dyn_cast<CXXMethodDecl>(f)) {
    if (m->isConst()) {
      fullName += " const";
                }
  }

  if (showReturnTy) {
     QualType returnTy = f->getReturnType();
//     fullName = returnTy.getCanonicalType().getAsString(Policy) + " " + fullName;
     fullName = nameOfType(Policy, returnTy) + " " + fullName;
  }

  return fullName;
}

///////////////////////////////////
// Code for Extracting Functions //
///////////////////////////////////

// ASTConsumer is an interface used to write generic actions on an AST,
// regardless of how the AST was produced.
// s̄ASTConsumer provides many different entry points

using action_t = std::function<void(const SourceManager&, const LangOptions&, Decl*)>;

class MyASTSearchConsumer : public ASTConsumer {
public:
//  MyASTSearchConsumer(Rewriter &R) : TheRewriter{R} {}
  MyASTSearchConsumer(const ASTContext& context, const action_t& action) :
      sm_{context.getSourceManager()}, lo_{context.getLangOpts()}, action_{action}
  {
     // Nothing (else) to do!
  }

  virtual void HandleInlineFunctionDefinition(FunctionDecl* d) override {
    action_(sm_, lo_, d);
  }
  // Override the method that gets called for each parsed top-level
  // declaration.
  virtual bool HandleTopLevelDecl(DeclGroupRef DR) override {

    for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
      action_(sm_, lo_, *b);
      /*
      if (FunctionDecl* f = dyn_cast<FunctionDecl>(*b)) {
        if (f->hasBody()) {
          string fullName = nameOfDecl(LangOpts, f);

          auto i = potentialReplacements.find(fullName);

          if (replaceAll || i != potentialReplacements.end()) {

            SourceRange range = f->getSourceRange();
            SourceLocation start = range.getBegin();
            SourceLocation stop = range.getEnd();

            if (start.isMacroID()) break;
            if (SM.isInSystemHeader(start)) break;
            llvm::errs() << "Search found the extracted function " << fullName << "\n";

            //llvm::errs() << "At location" <<
              //TheRewriter.getSourceMgr().getFilename(start) << "\n";

            // Clang source ranges are closed intervals, meaning
            // that 'stop' identifies the last token in the function,
            // i.e., the closing right curly brace. We could just
            // add 1 character to get the open interval needed below,
            // but let's be good and programmatically compute the
            // length of this final token.
            size_t offset = Lexer::MeasureTokenLength(stop, SM, LangOpts);

            std::string code =
              std::string(SM.getCharacterData(start),
                  SM.getCharacterData(stop)-SM.getCharacterData(start)+offset);

            replacements.insert(make_pair(fullName, code));
          }
        }
      }
      */
    }
    return true;
  }

private:
//  Rewriter& TheRewriter;
//    ASTContext& context_;
    const SourceManager& sm_;
    const LangOptions& lo_;
    action_t action_;
};

void listUserFunctions(const SourceManager& SM, const LangOptions& LangOpts, Decl* decl)
{
     if (FunctionDecl* f = dyn_cast<FunctionDecl>(decl)) {
//        if (f->isThisDeclarationADefinition()) {
//        if (f->hasBody()) {
          string fullName = nameOfDecl(LangOpts, f, true);

            SourceRange range = f->getSourceRange();
            SourceLocation start = range.getBegin();
//            SourceLocation stop = range.getEnd();

            if (start.isMacroID()) return;
            //if (SM.isInSystemHeader(start)) return;
            if (! SM.isInMainFile(start)) return;
            llvm::outs() << fullName << "\n";
//            llvm::errs() << "At location" << SM.getFilename(start) << "-"
//                         << SM.getFilename(stop) << "\n";
//        }
     }
}

class MySearchAction : public ASTFrontendAction {
public:
  MySearchAction() {}

  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 StringRef file) override
  {
    // llvm::errs() << "** Creating AST consumer for: " << file << "\n";
    // TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    return llvm::make_unique<MyASTSearchConsumer>(CI.getASTContext(), listUserFunctions); // was (TheRewriter);
  }

private:
//  Rewriter TheRewriter;
};

#if 0

///////////////////////////////
// Code for Replacing Functions
///////////////////////////////

// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
class MyASTReplaceConsumer : public ASTConsumer {
public:
  MyASTReplaceConsumer(Rewriter &R, Replacements& P) :
    TheRewriter{R}, TheReplacements{P} {}

  // Override the method that gets called for each parsed top-level
  // declaration.
  virtual bool HandleTopLevelDecl(DeclGroupRef DR) {

    const SourceManager& SM = TheRewriter.getSourceMgr();
    const LangOptions& LangOpts = TheRewriter.getLangOpts();

    //llvm::errs() << "Found a group\n";
    for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
      if (FunctionDecl* f = dyn_cast<FunctionDecl>(*b)) {
        if (f->hasBody()) {

          //llvm::errs() << "Saw function " << funcName << "\n";
          //SourceRange range = f->getSourceRange();
          //SourceLocation start = range.getBegin();
          //llvm::errs() << "At location" <<
          //TheRewriter.getSourceMgr().getFilename(start) << "\n";

          //ArrayRef<ParmVarDecl*> parameters = f->parameters();

          string fullName = nameOfDecl(LangOpts, f);
          auto i = replacements.find(fullName);
          if (i != replacements.end()) {
            SourceRange range = f->getSourceRange();
            Replacement repl{SM, CharSourceRange{range,true}, i->second};
            auto err = TheReplacements.add(repl);
            if (err) {
              cerr << "Replacement error" << endl;
              //cerr << err << endl;
              exit(-42);
            }
            // TheRewriter.ReplaceText(f->getSourceRange(), i->second);
          }
        }
      }
    }
    return true;
  }

private:
  Rewriter &TheRewriter;
  Replacements& TheReplacements;
};

// HACK
std::map< std::string, Replacements >  repl;

// For each source file provided to the tool, a new FrontendAction is created.

class MyReplaceAction : public ASTFrontendAction {
public:
  MyReplaceAction() {}

  void EndSourceFileAction() override
  {
    //SourceManager &SM = TheRewriter.getSourceMgr();

    //llvm::errs() << "** EndSourceFileAction for: "
                 //<< SM.getFileEntryForID(SM.getMainFileID())->getName() << "\n";

    // Now emit the rewritten buffer.
    //TheRewriter.getEditBuffer(SM.getMainFileID()).write(llvm::outs());
  }

  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 StringRef file) override
  {
    //llvm::errs() << "** Creating AST consumer for: " << file << "\n";

    TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    return llvm::make_unique<MyASTReplaceConsumer>(TheRewriter,
                                                   repl);
  }

private:
  Rewriter TheRewriter;
};

///////////////////////////////////////////////////////////////////////

#endif

int main(int argc, const char **argv) {
  // llvm::sys::PrintStackTraceOnErrorSignal();

  CommonOptionsParser OptionsParser(argc, argv, ReplaceToolCategory, ADDITIONAL_HELP);

  if (dumpFunctions) {
  ClangTool SearchTool(OptionsParser.getCompilations(),
                        OptionsParser.getSourcePathList());
  int searchError = SearchTool.run(newFrontendActionFactory<MySearchAction>().get());
  }
#if 0
  for (auto& s : functionsToReplace) {
    potentialReplacements.insert(s);
  }

  ClangTool SearchTool(OptionsParser.getCompilations(),
                        vector<string>(replacementFiles) );

  if (functionsToReplace.size() == 0) {
    replaceAll = true;
  }

  int searchError = SearchTool.run(newFrontendActionFactory<MySearchAction>().get());

  if (searchError) {
    llvm::errs() << "**Problem reading the file of replacements:";
    for (auto& filename : replacementFiles) {
       llvm::errs() << " " << filename;
    }
    llvm::errs() << "\n";
    exit(searchError);
  }
#endif

#if 0
  RefactoringTool ReplaceTool(OptionsParser.getCompilations(),
                        OptionsParser.getSourcePathList());
  //HACK
  repl = &ReplaceTool.getReplacements();
  return ReplaceTool.runAndSave(newFrontendActionFactory<MyReplaceAction>().get());

/*
  // At this point the rewriter's buffer should be full with the rewritten
  // file contents.
  const RewriteBuffer *RewriteBuf =
      TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID());
  llvm::outs() << std::string(RewriteBuf->begin(), RewriteBuf->end());
  */
#endif
  return 0;

}

<commit_msg>Added initial (wrong) public/private annotations<commit_after>#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::tooling;
using namespace llvm;
using namespace std;

static unordered_set<string> potentialReplacements;
static unordered_map<string,string> replacements;
static bool replaceAll = false;

/////////////////////////
// COMMAND-LINE OPTIONS
/////////////////////////

static cl::OptionCategory ReplaceToolCategory("Replacer Options");
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
//static cl::extrahelp MoreHelp("\nMore help text...");

static cl::list<string> functionsToReplace(
      "f",
      cl::desc("function to replace"),
      cl::ZeroOrMore,
      cl::cat(ReplaceToolCategory));

static cl::list<string> replacementFiles(
      "r",
      cl::desc("replacement file"),
      cl::ZeroOrMore,
      cl::cat(ReplaceToolCategory));

static cl::opt<bool> dumpFunctions(
      "d",
      cl::desc("Dump the functions defined in the specified files"),
      cl::cat(ReplaceToolCategory));

static cl::opt<bool> canonicalTypes(
      "c",
      cl::desc("Print canonicalized types"),
      cl::cat(ReplaceToolCategory));

const char * const ADDITIONAL_HELP = "Replaces designated functions or member functions in C++ source";

//////////////////////
// HELPER FUNCTIONS
//////////////////////

std::string nameOfType(PrintingPolicy Policy, QualType ty)
{
  if (canonicalTypes) ty = ty.getCanonicalType();
  return ty.getAsString(Policy);
}

// Converts the AST for a function declaration into
//   a human-readable (i.e., demangled) string representation.
//
std::string nameOfDecl(PrintingPolicy Policy, FunctionDecl* f, bool showReturnTy = false)
{
  std::string funcName = f->getQualifiedNameAsString();
  std::string fullName = funcName + "(";
  ArrayRef<ParmVarDecl*> parameters = f->parameters();

  for (const auto& pvd : parameters) {
    if (&pvd != &parameters[0]) fullName += ", ";
    fullName += nameOfType(Policy, pvd->getType());
  }
  fullName += ")";

  if (CXXMethodDecl* m = dyn_cast<CXXMethodDecl>(f)) {
    if (m->isConst()) {
      fullName += " const";
    }
  }
  /*
  string access;
  switch (f->getAccess()) {
      case AS_public: access = "public "; break;
      case AS_private: access = "private "; break;
      case AS_protected: access = "protected "; break;
      default: break;
  }
  fullName = access+ fullName;
  */

  if (showReturnTy) {
     QualType returnTy = f->getReturnType();
//     fullName = returnTy.getCanonicalType().getAsString(Policy) + " " + fullName;
     fullName = nameOfType(Policy, returnTy) + " " + fullName;
  }

  return fullName;
}

///////////////////////////////////
// Code for Extracting Functions //
///////////////////////////////////

// ASTConsumer is an interface used to write generic actions on an AST,
// regardless of how the AST was produced.
// s̄ASTConsumer provides many different entry points

using action_t = std::function<void(const SourceManager&, const LangOptions&, Decl*)>;

class MyASTSearchConsumer : public ASTConsumer {
public:
//  MyASTSearchConsumer(Rewriter &R) : TheRewriter{R} {}
  MyASTSearchConsumer(const ASTContext& context, const action_t& action) :
      sm_{context.getSourceManager()}, lo_{context.getLangOpts()}, action_{action}
  {
     // Nothing (else) to do!
  }

  virtual void HandleInlineFunctionDefinition(FunctionDecl* d) override {
    action_(sm_, lo_, d);
  }
  // Override the method that gets called for each parsed top-level
  // declaration.
  virtual bool HandleTopLevelDecl(DeclGroupRef DR) override {

    for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
      action_(sm_, lo_, *b);
      /*
      if (FunctionDecl* f = dyn_cast<FunctionDecl>(*b)) {
        if (f->hasBody()) {
          string fullName = nameOfDecl(LangOpts, f);

          auto i = potentialReplacements.find(fullName);

          if (replaceAll || i != potentialReplacements.end()) {

            SourceRange range = f->getSourceRange();
            SourceLocation start = range.getBegin();
            SourceLocation stop = range.getEnd();

            if (start.isMacroID()) break;
            if (SM.isInSystemHeader(start)) break;
            llvm::errs() << "Search found the extracted function " << fullName << "\n";

            //llvm::errs() << "At location" <<
              //TheRewriter.getSourceMgr().getFilename(start) << "\n";

            // Clang source ranges are closed intervals, meaning
            // that 'stop' identifies the last token in the function,
            // i.e., the closing right curly brace. We could just
            // add 1 character to get the open interval needed below,
            // but let's be good and programmatically compute the
            // length of this final token.
            size_t offset = Lexer::MeasureTokenLength(stop, SM, LangOpts);

            std::string code =
              std::string(SM.getCharacterData(start),
                  SM.getCharacterData(stop)-SM.getCharacterData(start)+offset);

            replacements.insert(make_pair(fullName, code));
          }
        }
      }
      */
    }
    return true;
  }

private:
//  Rewriter& TheRewriter;
//    ASTContext& context_;
    const SourceManager& sm_;
    const LangOptions& lo_;
    action_t action_;
};

void listUserFunctions(const SourceManager& SM, const LangOptions& LangOpts, Decl* decl)
{
     if (FunctionDecl* f = dyn_cast<FunctionDecl>(decl)) {
//        if (f->isThisDeclarationADefinition()) {
//        if (f->hasBody()) {
          string fullName = nameOfDecl(LangOpts, f, true);

            SourceRange range = f->getSourceRange();
            SourceLocation start = range.getBegin();
//            SourceLocation stop = range.getEnd();

            if (start.isMacroID()) return;
            //if (SM.isInSystemHeader(start)) return;
            if (! SM.isInMainFile(start)) return;
            llvm::outs() << fullName << "\n";
//            llvm::errs() << "At location" << SM.getFilename(start) << "-"
//                         << SM.getFilename(stop) << "\n";
//        }
     }
}

class MySearchAction : public ASTFrontendAction {
public:
  MySearchAction() {}

  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 StringRef file) override
  {
    // llvm::errs() << "** Creating AST consumer for: " << file << "\n";
    // TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    return llvm::make_unique<MyASTSearchConsumer>(CI.getASTContext(), listUserFunctions); // was (TheRewriter);
  }

private:
//  Rewriter TheRewriter;
};

#if 0

///////////////////////////////
// Code for Replacing Functions
///////////////////////////////

// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
class MyASTReplaceConsumer : public ASTConsumer {
public:
  MyASTReplaceConsumer(Rewriter &R, Replacements& P) :
    TheRewriter{R}, TheReplacements{P} {}

  // Override the method that gets called for each parsed top-level
  // declaration.
  virtual bool HandleTopLevelDecl(DeclGroupRef DR) {

    const SourceManager& SM = TheRewriter.getSourceMgr();
    const LangOptions& LangOpts = TheRewriter.getLangOpts();

    //llvm::errs() << "Found a group\n";
    for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
      if (FunctionDecl* f = dyn_cast<FunctionDecl>(*b)) {
        if (f->hasBody()) {

          //llvm::errs() << "Saw function " << funcName << "\n";
          //SourceRange range = f->getSourceRange();
          //SourceLocation start = range.getBegin();
          //llvm::errs() << "At location" <<
          //TheRewriter.getSourceMgr().getFilename(start) << "\n";

          //ArrayRef<ParmVarDecl*> parameters = f->parameters();

          string fullName = nameOfDecl(LangOpts, f);
          auto i = replacements.find(fullName);
          if (i != replacements.end()) {
            SourceRange range = f->getSourceRange();
            Replacement repl{SM, CharSourceRange{range,true}, i->second};
            auto err = TheReplacements.add(repl);
            if (err) {
              cerr << "Replacement error" << endl;
              //cerr << err << endl;
              exit(-42);
            }
            // TheRewriter.ReplaceText(f->getSourceRange(), i->second);
          }
        }
      }
    }
    return true;
  }

private:
  Rewriter &TheRewriter;
  Replacements& TheReplacements;
};

// HACK
std::map< std::string, Replacements >  repl;

// For each source file provided to the tool, a new FrontendAction is created.

class MyReplaceAction : public ASTFrontendAction {
public:
  MyReplaceAction() {}

  void EndSourceFileAction() override
  {
    //SourceManager &SM = TheRewriter.getSourceMgr();

    //llvm::errs() << "** EndSourceFileAction for: "
                 //<< SM.getFileEntryForID(SM.getMainFileID())->getName() << "\n";

    // Now emit the rewritten buffer.
    //TheRewriter.getEditBuffer(SM.getMainFileID()).write(llvm::outs());
  }

  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 StringRef file) override
  {
    //llvm::errs() << "** Creating AST consumer for: " << file << "\n";

    TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    return llvm::make_unique<MyASTReplaceConsumer>(TheRewriter,
                                                   repl);
  }

private:
  Rewriter TheRewriter;
};

///////////////////////////////////////////////////////////////////////

#endif

int main(int argc, const char **argv) {
  // llvm::sys::PrintStackTraceOnErrorSignal();

  CommonOptionsParser OptionsParser(argc, argv, ReplaceToolCategory, ADDITIONAL_HELP);

  if (dumpFunctions) {
  ClangTool SearchTool(OptionsParser.getCompilations(),
                        OptionsParser.getSourcePathList());
  int searchError = SearchTool.run(newFrontendActionFactory<MySearchAction>().get());
  }
#if 0
  for (auto& s : functionsToReplace) {
    potentialReplacements.insert(s);
  }

  ClangTool SearchTool(OptionsParser.getCompilations(),
                        vector<string>(replacementFiles) );

  if (functionsToReplace.size() == 0) {
    replaceAll = true;
  }

  int searchError = SearchTool.run(newFrontendActionFactory<MySearchAction>().get());

  if (searchError) {
    llvm::errs() << "**Problem reading the file of replacements:";
    for (auto& filename : replacementFiles) {
       llvm::errs() << " " << filename;
    }
    llvm::errs() << "\n";
    exit(searchError);
  }
#endif

#if 0
  RefactoringTool ReplaceTool(OptionsParser.getCompilations(),
                        OptionsParser.getSourcePathList());
  //HACK
  repl = &ReplaceTool.getReplacements();
  return ReplaceTool.runAndSave(newFrontendActionFactory<MyReplaceAction>().get());

/*
  // At this point the rewriter's buffer should be full with the rewritten
  // file contents.
  const RewriteBuffer *RewriteBuf =
      TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID());
  llvm::outs() << std::string(RewriteBuf->begin(), RewriteBuf->end());
  */
#endif
  return 0;

}

<|endoftext|>


<commit_before>// e.g.,
//    ./run -e=foo.expect foo.cpp
//    (cd testing; ../run -extract="IntList::push_front" cs70-intlist-good.cpp)

#include <algorithm>
#include <string>
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::tooling;
using namespace clang::ast_matchers;
//using namespace llvm;
//using namespace std;

//static unordered_set<std::string> potentialReplacements;
//static unordered_map<std::string,string> replacements;
//static bool replaceAll = false;

//static unordered_map<std::string,string> componentAccess;

static std::vector<std::string> expectedMembers;
static std::unordered_set<std::string> foundMembers;

static std::unordered_map<std::string, std::string> declarations;
static std::unordered_map<std::string, std::string> definitions;

/////////////////////////
// COMMAND-LINE OPTIONS
/////////////////////////

static llvm::cl::OptionCategory ReplaceToolCategory("Replacer Options");
static llvm::cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
//static llvm::cl::extrahelp MoreHelp("\nMore help text...");

/*
static llvm::cl::list<std::string> functionsToReplace(
      "f",
      llvm::cl::desc("function to replace"),
      llvm::cl::ZeroOrMore,
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::list<std::string> replacementFiles(
      "r",
      llvm::cl::desc("replacement file"),
      llvm::cl::ZeroOrMore,
      llvm::cl::cat(ReplaceToolCategory));
*/

static llvm::cl::opt<std::string> definitionToExtract(
      "extract",
      llvm::cl::desc("member to extract"),
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::opt<std::string> expectedMemberFile(
      "e",
      llvm::cl::desc("Specify expected members"),
      llvm::cl::value_desc("filename"),
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::opt<bool> dumpMembers(
      "d",
      llvm::cl::desc("Dump the functions defined in the specified files"),
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::opt<bool> canonicalTypes(
      "c",
      llvm::cl::desc("Print canonicalized types"),
      llvm::cl::cat(ReplaceToolCategory));

const char * const ADDITIONAL_HELP = "Replaces designated functions or member functions in C++ source";

//////////////////////
// HELPER FUNCTIONS
//////////////////////

std::string nameOfType(PrintingPolicy Policy, QualType ty)
{
  if (canonicalTypes) ty = ty.getCanonicalType();
  return ty.getAsString(Policy);
}

std::string nameOfAccess(AccessSpecifier access)
{
  switch (access) {
    case AS_public: return "public ";
    case AS_private: return "private ";
    case AS_protected: return "protected ";
    default: return "";
  }
}

// Converts the AST for a function declaration into
//   a human-readable (i.e., demangled) string representation.
//
std::string nameOfDecl(PrintingPolicy Policy, const NamedDecl* nd,
                       bool showReturnTy = false, bool showAccess = false)
{
  std::string fullName = nd->getQualifiedNameAsString();

  if (const FunctionDecl* f = dyn_cast<FunctionDecl>(nd)) {
    fullName +="(";
    ArrayRef<ParmVarDecl*> parameters = f->parameters();

    for (const auto& pvd : parameters) {
      if (&pvd != &parameters[0]) fullName += ", ";
      fullName += nameOfType(Policy, pvd->getType());
    }
    fullName += ")";

    if (showReturnTy) {
      QualType returnTy = f->getReturnType();
      fullName = nameOfType(Policy, returnTy) + " " + fullName;
    }

    if (const CXXMethodDecl* m = dyn_cast<CXXMethodDecl>(nd)) {
      if (m->isConst()) {
        fullName += " const";
      }

      if (m->isDeleted()) {
        fullName += " = delete";
      } else if (m->isDefaulted()) {
        fullName += " = default";
      }

      if (m->isVirtual()) {
        fullName = "virtual " + fullName;
      }
    }

    if (showAccess) {
      fullName = nameOfAccess(f->getCanonicalDecl()->getAccess()) + fullName;
    }
  } else if (const FieldDecl* f = dyn_cast<FieldDecl>(nd)) {
      fullName = nameOfType(Policy, f->getType()) + " " + fullName;
      fullName = nameOfAccess(f->getAccess()) + fullName;
  }

  return fullName;
}

///////////////////////////////////
// Code for Extracting Functions //
///////////////////////////////////

auto FunctionDeclMatcher = functionDecl().bind("functionDecl");
class ProcessFunctionDecls : public MatchFinder::MatchCallback {
public :
  virtual void run(const MatchFinder::MatchResult &Result) {
    if (const FunctionDecl* f = Result.Nodes.getNodeAs<clang::FunctionDecl>("functionDecl")) {
        const LangOptions& lo = Result.Context->getLangOpts();
        const SourceManager& sm = Result.Context->getSourceManager();

        SourceRange range = f->getSourceRange();
        SourceLocation start = range.getBegin();
        SourceLocation stop = range.getEnd();

        if (sm.isInSystemHeader(start)) return;

        if (f->isThisDeclarationADefinition()) {

            std::string fullName = nameOfDecl(lo, f, true, true);
            std::string memberDescription = "define " + fullName;
            foundMembers.insert(memberDescription);
            if (dumpMembers) llvm::outs() << memberDescription << "\n";

            if (definitionToExtract != "" && fullName.find(definitionToExtract) != std::string::npos) {

                // https://stackoverflow.com/questions/25275212/how-to-extract-comments-and-match-to-declaration-with-recursiveastvisitor-in-lib
                if (const RawComment* rc = f->getASTContext().getRawCommentForDeclNoCache(f)) {
                  start = rc->getBeginLoc();
                }

                // Clang source ranges are closed intervals, meaning
                // that 'stop' identifies the last token in the function,
                // i.e., the closing right curly brace. We could just
                // add 1 character to get the open interval needed below,
                // but let's be good and programmatically compute the
                // length of this final token.
                size_t offset = Lexer::MeasureTokenLength(stop, sm, lo);

                std::string code =
                  std::string(sm.getCharacterData(start),
                      sm.getCharacterData(stop)-sm.getCharacterData(start)+offset);
                llvm::outs() << code << "\n";
            }
            //            llvm::errs() << "At location " << SM.getFilename(start) << "-"
            //                         << SM.getFilename(stop) << "\n";
       } else {
            std::string fullName = nameOfDecl(lo, f, true, true);
            std::string memberDescription = "declare " + fullName;
            foundMembers.insert(memberDescription);
            if (dumpMembers) llvm::outs() << memberDescription << "\n";
            //            llvm::outs() << "At location " << sm.getFilename(start) << "-"
            //                         << sm_.getFilename(stop) << "\n";
       }
    }
  }
};

auto FieldDeclMatcher = fieldDecl().bind("fieldDecl");

class ProcessFieldDecls : public MatchFinder::MatchCallback {
public :
  virtual void run(const MatchFinder::MatchResult &Result) {
    if (const FieldDecl* f = Result.Nodes.getNodeAs<clang::FieldDecl>("fieldDecl")) {
            const LangOptions& lo = Result.Context->getLangOpts();
            const SourceManager& sm = Result.Context->getSourceManager();

            SourceRange range = f->getSourceRange();
            SourceLocation start = range.getBegin();
            if (sm.isInSystemHeader(start)) return;

            std::string fullName = nameOfDecl(lo, f, true, true);
            std::string memberDescription = "field " + fullName;
            foundMembers.insert(memberDescription);
            if (dumpMembers) llvm::outs() << memberDescription << "\n";
    }
  }
};

#if 0

#if 0

///////////////////////////////
// Code for Replacing Functions
///////////////////////////////

// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
class MyASTReplaceConsumer : public ASTConsumer {
public:
  MyASTReplaceConsumer(Rewriter &R, Replacements& P) :
    TheRewriter{R}, TheReplacements{P} {}

  // Override the method that gets called for each parsed top-level
  // declaration.
  virtual bool HandleTopLevelDecl(DeclGroupRef DR) {

    const SourceManager& SM = TheRewriter.getSourceMgr();
    const LangOptions& LangOpts = TheRewriter.getLangOpts();

    //llvm::errs() << "Found a group\n";
    for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
      if (FunctionDecl* f = dyn_cast<FunctionDecl>(*b)) {
        if (f->hasBody()) {

          //llvm::errs() << "Saw function " << funcName << "\n";
          //SourceRange range = f->getSourceRange();
          //SourceLocation start = range.getBegin();
          //llvm::errs() << "At location" <<
          //TheRewriter.getSourceMgr().getFilename(start) << "\n";

          //ArrayRef<ParmVarDecl*> parameters = f->parameters();

          string fullName = nameOfDecl(LangOpts, f);
          auto i = replacements.find(fullName);
          if (i != replacements.end()) {
            SourceRange range = f->getSourceRange();
            Replacement repl{SM, CharSourceRange{range,true}, i->second};
            auto err = TheReplacements.add(repl);
            if (err) {
              cerr << "Replacement error" << endl;
              //cerr << err << endl;
              exit(-42);
            }
            // TheRewriter.ReplaceText(f->getSourceRange(), i->second);
          }
        }
      }
    }
    return true;
  }

private:
  Rewriter &TheRewriter;
  Replacements& TheReplacements;
};

// HACK
std::map< std::string, Replacements >  repl;

// For each source file provided to the tool, a new FrontendAction is created.

class MyReplaceAction : public ASTFrontendAction {
public:
  MyReplaceAction() {}

  void EndSourceFileAction() override
  {
    //SourceManager &SM = TheRewriter.getSourceMgr();

    //llvm::errs() << "** EndSourceFileAction for: "
                 //<< SM.getFileEntryForID(SM.getMainFileID())->getName() << "\n";

    // Now emit the rewritten buffer.
    //TheRewriter.getEditBuffer(SM.getMainFileID()).write(llvm::outs());
  }

  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 StringRef file) override
  {
    //llvm::errs() << "** Creating AST consumer for: " << file << "\n";

    TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    return llvm::make_unique<MyASTReplaceConsumer>(TheRewriter,
                                                   repl);
  }

private:
  Rewriter TheRewriter;
};

///////////////////////////////////////////////////////////////////////

#endif

#endif

int main(int argc, const char **argv) {
  // llvm::sys::PrintStackTraceOnErrorSignal();

  CommonOptionsParser OptionsParser(argc, argv, ReplaceToolCategory, ADDITIONAL_HELP);

  bool checkExpectedMembers = expectedMemberFile != "";

  if (checkExpectedMembers) {
    std::ifstream in(expectedMemberFile);
    if (! in.good()) {
      llvm::errs() << "Can't open expectation file " << expectedMemberFile << "\n";
      exit(-1);
    }
    std::string line;
    while (std::getline(in, line))
    {
       expectedMembers.push_back(line);
    }

  }

  ClangTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());
  ProcessFunctionDecls pfnd;
  ProcessFieldDecls pfdd;

  MatchFinder Finder;
  Finder.addMatcher(FunctionDeclMatcher, &pfnd);
  Finder.addMatcher(FieldDeclMatcher, &pfdd);

  Tool.run(newFrontendActionFactory(&Finder).get());

  if (checkExpectedMembers) {
    for (const std::string& s : expectedMembers) {
      if (foundMembers.find(s) == foundMembers.end()) {
        llvm::errs() << "MISSING: " << s << "\n";
      }
    }
  }

#if 0
  for (auto& s : functionsToReplace) {
    potentialReplacements.insert(s);
  }

  ClangTool SearchTool(OptionsParser.getCompilations(),
                        vector<std::string>(replacementFiles) );

  if (functionsToReplace.size() == 0) {
    replaceAll = true;
  }

  int searchError = SearchTool.run(newFrontendActionFactory<MySearchAction>().get());

  if (searchError) {
    llvm::errs() << "**Problem reading the file of replacements:";
    for (auto& filename : replacementFiles) {
       llvm::errs() << " " << filename;
    }
    llvm::errs() << "\n";
    exit(searchError);
  }
#endif

#if 0
  RefactoringTool ReplaceTool(OptionsParser.getCompilations(),
                        OptionsParser.getSourcePathList());
  //HACK
  repl = &ReplaceTool.getReplacements();
  return ReplaceTool.runAndSave(newFrontendActionFactory<MyReplaceAction>().get());

/*
  // At this point the rewriter's buffer should be full with the rewritten
  // file contents.
  const RewriteBuffer *RewriteBuf =
      TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID());
  llvm::outs() << std::string(RewriteBuf->begin(), RewriteBuf->end());
  */
#endif
  return 0;

}

<commit_msg>More code cleanup re clang-tidy<commit_after>// e.g.,
//    ./run -e=foo.expect foo.cpp
//    (cd testing; ../run -extract="IntList::push_front" cs70-intlist-good.cpp)

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::tooling;
using namespace clang::ast_matchers;
//using namespace llvm;
//using namespace std;

//static unordered_set<std::string> potentialReplacements;
//static unordered_map<std::string,string> replacements;
//static bool replaceAll = false;

//static unordered_map<std::string,string> componentAccess;

static std::vector<std::string> expectedMembers;
static std::unordered_set<std::string> foundMembers;

static std::unordered_map<std::string, std::string> declarations;
static std::unordered_map<std::string, std::string> definitions;

/////////////////////////
// COMMAND-LINE OPTIONS
/////////////////////////

static llvm::cl::OptionCategory ReplaceToolCategory("Replacer Options");
static llvm::cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
//static llvm::cl::extrahelp MoreHelp("\nMore help text...");

/*
static llvm::cl::list<std::string> functionsToReplace(
      "f",
      llvm::cl::desc("function to replace"),
      llvm::cl::ZeroOrMore,
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::list<std::string> replacementFiles(
      "r",
      llvm::cl::desc("replacement file"),
      llvm::cl::ZeroOrMore,
      llvm::cl::cat(ReplaceToolCategory));
*/

static llvm::cl::opt<std::string> definitionToExtract(
      "extract",
      llvm::cl::desc("member to extract"),
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::opt<std::string> expectedMemberFile(
      "e",
      llvm::cl::desc("Specify expected members"),
      llvm::cl::value_desc("filename"),
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::opt<bool> dumpMembers(
      "d",
      llvm::cl::desc("Dump the functions defined in the specified files"),
      llvm::cl::cat(ReplaceToolCategory));

static llvm::cl::opt<bool> canonicalTypes(
      "c",
      llvm::cl::desc("Print canonicalized types"),
      llvm::cl::cat(ReplaceToolCategory));

const char * const ADDITIONAL_HELP = "Replaces designated functions or member functions in C++ source";

//////////////////////
// HELPER FUNCTIONS
//////////////////////

std::string nameOfType(PrintingPolicy Policy, QualType ty)
{
  if (canonicalTypes) ty = ty.getCanonicalType();
  return ty.getAsString(Policy);
}

std::string nameOfAccess(AccessSpecifier access)
{
  switch (access) {
    case AS_public: return "public ";
    case AS_private: return "private ";
    case AS_protected: return "protected ";
    default: return "";
  }
}

// Converts the AST for a function declaration into
//   a human-readable (i.e., demangled) string representation.
//
std::string nameOfDecl(PrintingPolicy Policy, const NamedDecl* nd,
                       bool showReturnTy = false, bool showAccess = false)
{
  std::string fullName = nd->getQualifiedNameAsString();

  if (const auto* f = dyn_cast<FunctionDecl>(nd)) {
    fullName +="(";
    ArrayRef<ParmVarDecl*> parameters = f->parameters();

    for (const auto& pvd : parameters) {
      if (&pvd != &parameters[0]) fullName += ", ";
      fullName += nameOfType(Policy, pvd->getType());
    }
    fullName += ")";

    if (showReturnTy) {
      QualType returnTy = f->getReturnType();
      fullName = nameOfType(Policy, returnTy) + " " + fullName;
    }

    if (const auto* m = dyn_cast<CXXMethodDecl>(nd)) {
      if (m->isConst()) {
        fullName += " const";
      }

      if (m->isDeleted()) {
        fullName += " = delete";
      } else if (m->isDefaulted()) {
        fullName += " = default";
      }

      if (m->isVirtual()) {
        fullName = "virtual " + fullName;
      }
    }

    if (showAccess) {
      fullName = nameOfAccess(f->getCanonicalDecl()->getAccess()) + fullName;
    }
  } else if (const auto* f = dyn_cast<FieldDecl>(nd)) {
      fullName = nameOfType(Policy, f->getType()) + " " + fullName;
      fullName = nameOfAccess(f->getAccess()) + fullName;
  }

  return fullName;
}

///////////////////////////////////
// Code for Extracting Functions //
///////////////////////////////////

auto FunctionDeclMatcher = functionDecl().bind("functionDecl");
class ProcessFunctionDecls : public MatchFinder::MatchCallback {
public :
  void run(const MatchFinder::MatchResult &Result) override {
    if (const FunctionDecl* f = Result.Nodes.getNodeAs<clang::FunctionDecl>("functionDecl")) {
        const LangOptions& lo = Result.Context->getLangOpts();
        const SourceManager& sm = Result.Context->getSourceManager();

        SourceRange range = f->getSourceRange();
        SourceLocation start = range.getBegin();
        SourceLocation stop = range.getEnd();

        if (sm.isInSystemHeader(start)) return;

        if (f->isThisDeclarationADefinition()) {

            std::string fullName = nameOfDecl(lo, f, true, true);
            std::string memberDescription = "define " + fullName;
            foundMembers.insert(memberDescription);
            if (dumpMembers) llvm::outs() << memberDescription << "\n";

            if (!definitionToExtract.empty() && fullName.find(definitionToExtract) != std::string::npos) {

                // https://stackoverflow.com/questions/25275212/how-to-extract-comments-and-match-to-declaration-with-recursiveastvisitor-in-lib
                if (const RawComment* rc = f->getASTContext().getRawCommentForDeclNoCache(f)) {
                  start = rc->getBeginLoc();
                }

                // Clang source ranges are closed intervals, meaning
                // that 'stop' identifies the last token in the function,
                // i.e., the closing right curly brace. We could just
                // add 1 character to get the open interval needed below,
                // but let's be good and programmatically compute the
                // length of this final token.
                size_t offset = Lexer::MeasureTokenLength(stop, sm, lo);

                std::string code =
                  std::string(sm.getCharacterData(start),
                      sm.getCharacterData(stop)-sm.getCharacterData(start)+offset);
                llvm::outs() << code << "\n";
            }
            //            llvm::errs() << "At location " << SM.getFilename(start) << "-"
            //                         << SM.getFilename(stop) << "\n";
       } else {
            std::string fullName = nameOfDecl(lo, f, true, true);
            std::string memberDescription = "declare " + fullName;
            foundMembers.insert(memberDescription);
            if (dumpMembers) llvm::outs() << memberDescription << "\n";
            //            llvm::outs() << "At location " << sm.getFilename(start) << "-"
            //                         << sm_.getFilename(stop) << "\n";
       }
    }
  }
};

auto FieldDeclMatcher = fieldDecl().bind("fieldDecl");

class ProcessFieldDecls : public MatchFinder::MatchCallback {
public :
  void run(const MatchFinder::MatchResult &Result) override {
    if (const FieldDecl* f = Result.Nodes.getNodeAs<clang::FieldDecl>("fieldDecl")) {
            const LangOptions& lo = Result.Context->getLangOpts();
            const SourceManager& sm = Result.Context->getSourceManager();

            SourceRange range = f->getSourceRange();
            SourceLocation start = range.getBegin();
            if (sm.isInSystemHeader(start)) return;

            std::string fullName = nameOfDecl(lo, f, true, true);
            std::string memberDescription = "field " + fullName;
            foundMembers.insert(memberDescription);
            if (dumpMembers) llvm::outs() << memberDescription << "\n";
    }
  }
};

#if 0

#if 0

///////////////////////////////
// Code for Replacing Functions
///////////////////////////////

// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
class MyASTReplaceConsumer : public ASTConsumer {
public:
  MyASTReplaceConsumer(Rewriter &R, Replacements& P) :
    TheRewriter{R}, TheReplacements{P} {}

  // Override the method that gets called for each parsed top-level
  // declaration.
  virtual bool HandleTopLevelDecl(DeclGroupRef DR) {

    const SourceManager& SM = TheRewriter.getSourceMgr();
    const LangOptions& LangOpts = TheRewriter.getLangOpts();

    //llvm::errs() << "Found a group\n";
    for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
      if (FunctionDecl* f = dyn_cast<FunctionDecl>(*b)) {
        if (f->hasBody()) {

          //llvm::errs() << "Saw function " << funcName << "\n";
          //SourceRange range = f->getSourceRange();
          //SourceLocation start = range.getBegin();
          //llvm::errs() << "At location" <<
          //TheRewriter.getSourceMgr().getFilename(start) << "\n";

          //ArrayRef<ParmVarDecl*> parameters = f->parameters();

          string fullName = nameOfDecl(LangOpts, f);
          auto i = replacements.find(fullName);
          if (i != replacements.end()) {
            SourceRange range = f->getSourceRange();
            Replacement repl{SM, CharSourceRange{range,true}, i->second};
            auto err = TheReplacements.add(repl);
            if (err) {
              cerr << "Replacement error" << endl;
              //cerr << err << endl;
              exit(-42);
            }
            // TheRewriter.ReplaceText(f->getSourceRange(), i->second);
          }
        }
      }
    }
    return true;
  }

private:
  Rewriter &TheRewriter;
  Replacements& TheReplacements;
};

// HACK
std::map< std::string, Replacements >  repl;

// For each source file provided to the tool, a new FrontendAction is created.

class MyReplaceAction : public ASTFrontendAction {
public:
  MyReplaceAction() {}

  void EndSourceFileAction() override
  {
    //SourceManager &SM = TheRewriter.getSourceMgr();

    //llvm::errs() << "** EndSourceFileAction for: "
                 //<< SM.getFileEntryForID(SM.getMainFileID())->getName() << "\n";

    // Now emit the rewritten buffer.
    //TheRewriter.getEditBuffer(SM.getMainFileID()).write(llvm::outs());
  }

  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                 StringRef file) override
  {
    //llvm::errs() << "** Creating AST consumer for: " << file << "\n";

    TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    return llvm::make_unique<MyASTReplaceConsumer>(TheRewriter,
                                                   repl);
  }

private:
  Rewriter TheRewriter;
};

///////////////////////////////////////////////////////////////////////

#endif

#endif

int main(int argc, const char **argv) {
  // llvm::sys::PrintStackTraceOnErrorSignal();

  CommonOptionsParser OptionsParser(argc, argv, ReplaceToolCategory, ADDITIONAL_HELP);

  bool checkExpectedMembers = expectedMemberFile != "";

  if (checkExpectedMembers) {
    std::ifstream in(expectedMemberFile);
    if (! in.good()) {
      llvm::errs() << "Can't open expectation file " << expectedMemberFile << "\n";
      exit(-1);
    }
    std::string line;
    while (std::getline(in, line))
    {
       expectedMembers.push_back(line);
    }

  }

  ClangTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());
  ProcessFunctionDecls pfnd;
  ProcessFieldDecls pfdd;

  MatchFinder Finder;
  Finder.addMatcher(FunctionDeclMatcher, &pfnd);
  Finder.addMatcher(FieldDeclMatcher, &pfdd);

  Tool.run(newFrontendActionFactory(&Finder).get());

  if (checkExpectedMembers) {
    for (const std::string& s : expectedMembers) {
      if (foundMembers.find(s) == foundMembers.end()) {
        llvm::errs() << "MISSING: " << s << "\n";
      }
    }
  }

#if 0
  for (auto& s : functionsToReplace) {
    potentialReplacements.insert(s);
  }

  ClangTool SearchTool(OptionsParser.getCompilations(),
                        vector<std::string>(replacementFiles) );

  if (functionsToReplace.size() == 0) {
    replaceAll = true;
  }

  int searchError = SearchTool.run(newFrontendActionFactory<MySearchAction>().get());

  if (searchError) {
    llvm::errs() << "**Problem reading the file of replacements:";
    for (auto& filename : replacementFiles) {
       llvm::errs() << " " << filename;
    }
    llvm::errs() << "\n";
    exit(searchError);
  }
#endif

#if 0
  RefactoringTool ReplaceTool(OptionsParser.getCompilations(),
                        OptionsParser.getSourcePathList());
  //HACK
  repl = &ReplaceTool.getReplacements();
  return ReplaceTool.runAndSave(newFrontendActionFactory<MyReplaceAction>().get());

/*
  // At this point the rewriter's buffer should be full with the rewritten
  // file contents.
  const RewriteBuffer *RewriteBuf =
      TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID());
  llvm::outs() << std::string(RewriteBuf->begin(), RewriteBuf->end());
  */
#endif
  return 0;

}

<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/3/9 17:08:58
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint &operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint &operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
constexpr ll infty{1000000000000000LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

using shop = tuple<ll, ll>;

class Solve
{
  static constexpr int C{32};
  int N, M, L;
  ll T;
  vector<shop> V;
  vector<shop> normal, zero;
  vector<ll> sum;
  vector<vector<ll>> dp;

public:
  Solve(int N, ll T, vector<shop> V) : N{N}, T{T}, V(V)
  {
    make_normal_zero();
    execute_dp();
    cout << calc_ans() << endl;
  }

private:
  static bool compare_normal(shop const &left, shop const &right)
  {
    return (get<0>(right) - 1) * get<1>(left) - (get<0>(left) - 1) * get<1>(right) <= 0;
  }

  static bool compare_zero(shop const &left, shop const &right)
  {
    return get<1>(left) <= get<1>(right);
  }

  ll f(int i, ll x)
  {
    return get<0>(V[i]) * x + get<1>(V[i]);
  }

  void make_normal_zero()
  {
    for (auto i = 0; i < N; ++i)
    {
      if (get<0>(V[i]) >= 2)
      {
        normal.push_back(V[i]);
      }
      else
      {
        zero.push_back(V[i]);
      }
    }
    M = normal.size();
    L = zero.size();
    sort(normal.begin(), normal.end(), compare_normal);
    sort(zero.begin(), zero.end(), compare_zero);
    sum = vector<ll>(L + 1, 0);
    for (auto i = 0; i < L; ++i)
    {
      sum[i + 1] = sum[i] + get<1>(zero[i]);
    }
  }

  void execute_dp()
  {
    dp = vector<vector<ll>>(M + 1, vector<ll>(C, infty));
    dp[0][0] = 0;
    for (auto i = 0; i < M; ++i)
    {
      dp[i + 1][0] = dp[i][0];
      for (auto j = 1; j < C; ++j)
      {
        dp[i + 1][j] = min(dp[i][j], f(i, dp[i][j - 1]));
      }
    }
  }

  int calc_ans()
  {
    int ans{0};
    for (auto i = 0; i < C; ++i)
    {
      ll remain{T - dp[M][i]};
      if (remain < 0)
      {
        continue;
      }
      int z{static_cast<int>(lower_bound(sum.begin(), sum.end(), remain) - sum.begin())};
      ch_max(ans, z + i);
    }
    return ans;
  }
};

int main()
{
  int N;
  ll T;
  cin >> N >> T;
  vector<shop> V(N);
  for (auto i = 0; i < N; ++i)
  {
    ll a, b;
    cin >> a >> b;
    V[i] = shop(a + 1, a + b + 1);
  }
  Solve solve(N, T, V);
}
<commit_msg>tried D2.cpp to 'D'<commit_after>#define DEBUG 1
/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/3/9 17:08:58
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint &operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint &operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
constexpr ll infty{1000000000000000LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

using shop = tuple<ll, ll>;

class Solve
{
  static constexpr int C{32};
  int N, M, L;
  ll T;
  vector<shop> V;
  vector<shop> normal, zero;
  vector<ll> sum;
  vector<vector<ll>> dp;

public:
  Solve(int N, ll T, vector<shop> V) : N{N}, T{T}, V(V)
  {
    make_normal_zero();
    execute_dp();
    cout << calc_ans() << endl;
  }

private:
  static bool compare_normal(shop const &left, shop const &right)
  {
    return (get<0>(right) - 1) * get<1>(left) - (get<0>(left) - 1) * get<1>(right) <= 0;
  }

  static bool compare_zero(shop const &left, shop const &right)
  {
    return get<1>(left) <= get<1>(right);
  }

  ll f(int i, ll x)
  {
    return get<0>(V[i]) * x + get<1>(V[i]);
  }

  void make_normal_zero()
  {
    for (auto i = 0; i < N; ++i)
    {
      if (get<0>(V[i]) >= 2)
      {
        normal.push_back(V[i]);
      }
      else
      {
        zero.push_back(V[i]);
      }
    }
    M = normal.size();
    L = zero.size();
    sort(normal.begin(), normal.end(), compare_normal);
    sort(zero.begin(), zero.end(), compare_zero);
    sum = vector<ll>(L + 1, 0);
    for (auto i = 0; i < L; ++i)
    {
      sum[i + 1] = sum[i] + get<1>(zero[i]);
    }
  }

  void execute_dp()
  {
    dp = vector<vector<ll>>(M + 1, vector<ll>(C, infty));
    dp[0][0] = 0;
    for (auto i = 0; i < M; ++i)
    {
      dp[i + 1][0] = dp[i][0];
      for (auto j = 1; j < C; ++j)
      {
        dp[i + 1][j] = min(dp[i][j], f(i, dp[i][j - 1]));
      }
    }
  }

  int calc_ans()
  {
    int ans{0};
    for (auto i = 0; i < C; ++i)
    {
#if DEBUG == 1
      cerr << "dp[" << M << "][" << i << "] = " << dp[M][i] << endl;
#endif
      ll remain{T - dp[M][i]};
      if (remain < 0)
      {
        continue;
      }
      int z{static_cast<int>(lower_bound(sum.begin(), sum.end(), remain) - sum.begin())};
      ch_max(ans, z + i);
    }
    return ans;
  }
};

int main()
{
  int N;
  ll T;
  cin >> N >> T;
  vector<shop> V(N);
  for (auto i = 0; i < N; ++i)
  {
    ll a, b;
    cin >> a >> b;
    V[i] = shop(a + 1, a + b + 1);
  }
  Solve solve(N, T, V);
}
<|endoftext|>


<commit_before>#include "uinput.h"
#include "eventlists/eventlist.h"

const char* try_to_find_uinput() {
  static const char* paths[] = {
    "/dev/uinput",
    "/dev/input/uinput",
    "/dev/misc/uinput"
  };
  const int num_paths = 3;
  int i;

  for (i = 0; i < num_paths; i++) {
    if (access(paths[i], F_OK) == 0) {
      return paths[i];
    }
  }
  return nullptr;
}

std::string uinput_devnode(int fd) {
  char buffer[128];
  buffer[0] = '\0';
  ioctl(fd, UI_GET_SYSNAME(127), &buffer);
  buffer[127] = '\0';
  return std::string("/sys/devices/virtual/input/") + std::string(buffer);
}

void uinput_destroy(int fd) {
  ioctl(fd, UI_DEV_DESTROY);
}

uinput::uinput() {
  filename = try_to_find_uinput();
  if (filename == nullptr) throw - 1;

}

int uinput::make_gamepad(const uinput_ids& ids, bool dpad_as_hat, bool analog_triggers) {
  static int abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY};
  static int key[] = { BTN_SOUTH, BTN_EAST, BTN_NORTH, BTN_WEST, BTN_SELECT, BTN_MODE, BTN_START, BTN_TL, BTN_TR, BTN_THUMBL, BTN_THUMBR, -1};
  struct uinput_user_dev uidev;
  int fd;
  int i;
  //TODO: Read from uinput for rumble events?
  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("open uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  for (i = 0; i < 4; i++) {
    ioctl(fd, UI_SET_ABSBIT, abs[i]);
    uidev.absmin[abs[i]] = -32768;
    uidev.absmax[abs[i]] = 32767;
    uidev.absflat[abs[i]] = 1024;
  }

  if (analog_triggers) {
    ioctl(fd, UI_SET_ABSBIT, ABS_Z);
    uidev.absmin[ABS_Z] = 0;
    uidev.absmax[ABS_Z] = 255;
    uidev.absflat[ABS_Z] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_RZ);
    uidev.absmin[ABS_RZ] = 0;
    uidev.absmax[ABS_RZ] = 255;
    uidev.absflat[ABS_RZ] = 0;
  }

  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = 0; key[i] >= 0; i++) {
    ioctl(fd, UI_SET_KEYBIT, key[i]);
  }

  if (dpad_as_hat) {
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0X);
    uidev.absmin[ABS_HAT0X] = -1;
    uidev.absmax[ABS_HAT0X] = 1;
    uidev.absflat[ABS_HAT0X] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0Y);
    uidev.absmin[ABS_HAT0Y] = -1;
    uidev.absmax[ABS_HAT0Y] = 1;
    uidev.absflat[ABS_HAT0Y] = 0;
  } else {
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_UP);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_DOWN);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_LEFT);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_RIGHT);
  }
  if (!analog_triggers) {
    ioctl(fd, UI_SET_KEYBIT, BTN_TL2);
    ioctl(fd, UI_SET_KEYBIT, BTN_TR2);
  }

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

int uinput::make_keyboard(const uinput_ids& ids) {
  struct uinput_user_dev uidev;
  int fd;
  int i;

  //TODO: Read from uinput for rumble events?
  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("\nopen uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  /*Just set all possible keys that come before BTN_MISC
   * This should cover all reasonable keyboard keys.*/
  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = KEY_ESC; i < BTN_MISC; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }
  for (i = KEY_OK; i < KEY_MAX; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

uinput::~uinput() {
}

bool uinput::node_owned(const std::string& path) const {
  lock.lock();
  for (auto node : virtual_nodes) {
    //Check to see if node is a prefix of this path, if so the path belongs to us.
    auto comp = std::mismatch(node.begin(),node.end(),path.begin());
    if (comp.first == node.end()) {
      lock.unlock();
      return true;
    }
  }
  lock.unlock();
  return false;
}

<commit_msg>avoid unitialized bytes<commit_after>#include "uinput.h"
#include "eventlists/eventlist.h"
#include "string.h"

const char* try_to_find_uinput() {
  static const char* paths[] = {
    "/dev/uinput",
    "/dev/input/uinput",
    "/dev/misc/uinput"
  };
  const int num_paths = 3;
  int i;

  for (i = 0; i < num_paths; i++) {
    if (access(paths[i], F_OK) == 0) {
      return paths[i];
    }
  }
  return nullptr;
}

std::string uinput_devnode(int fd) {
  char buffer[128];
  memset(buffer,0,sizeof(buffer));
  ioctl(fd, UI_GET_SYSNAME(127), &buffer);
  buffer[127] = '\0';
  return std::string("/sys/devices/virtual/input/") + std::string(buffer);
}

void uinput_destroy(int fd) {
  ioctl(fd, UI_DEV_DESTROY);
}

uinput::uinput() {
  filename = try_to_find_uinput();
  if (filename == nullptr) throw - 1;

}

int uinput::make_gamepad(const uinput_ids& ids, bool dpad_as_hat, bool analog_triggers) {
  static int abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY};
  static int key[] = { BTN_SOUTH, BTN_EAST, BTN_NORTH, BTN_WEST, BTN_SELECT, BTN_MODE, BTN_START, BTN_TL, BTN_TR, BTN_THUMBL, BTN_THUMBR, -1};
  struct uinput_user_dev uidev;
  int fd;
  int i;
  //TODO: Read from uinput for rumble events?
  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("open uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  for (i = 0; i < 4; i++) {
    ioctl(fd, UI_SET_ABSBIT, abs[i]);
    uidev.absmin[abs[i]] = -32768;
    uidev.absmax[abs[i]] = 32767;
    uidev.absflat[abs[i]] = 1024;
  }

  if (analog_triggers) {
    ioctl(fd, UI_SET_ABSBIT, ABS_Z);
    uidev.absmin[ABS_Z] = 0;
    uidev.absmax[ABS_Z] = 255;
    uidev.absflat[ABS_Z] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_RZ);
    uidev.absmin[ABS_RZ] = 0;
    uidev.absmax[ABS_RZ] = 255;
    uidev.absflat[ABS_RZ] = 0;
  }

  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = 0; key[i] >= 0; i++) {
    ioctl(fd, UI_SET_KEYBIT, key[i]);
  }

  if (dpad_as_hat) {
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0X);
    uidev.absmin[ABS_HAT0X] = -1;
    uidev.absmax[ABS_HAT0X] = 1;
    uidev.absflat[ABS_HAT0X] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0Y);
    uidev.absmin[ABS_HAT0Y] = -1;
    uidev.absmax[ABS_HAT0Y] = 1;
    uidev.absflat[ABS_HAT0Y] = 0;
  } else {
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_UP);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_DOWN);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_LEFT);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_RIGHT);
  }
  if (!analog_triggers) {
    ioctl(fd, UI_SET_KEYBIT, BTN_TL2);
    ioctl(fd, UI_SET_KEYBIT, BTN_TR2);
  }

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

int uinput::make_keyboard(const uinput_ids& ids) {
  struct uinput_user_dev uidev;
  int fd;
  int i;

  //TODO: Read from uinput for rumble events?
  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("\nopen uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  /*Just set all possible keys that come before BTN_MISC
   * This should cover all reasonable keyboard keys.*/
  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = KEY_ESC; i < BTN_MISC; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }
  for (i = KEY_OK; i < KEY_MAX; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

uinput::~uinput() {
}

bool uinput::node_owned(const std::string& path) const {
  lock.lock();
  for (auto node : virtual_nodes) {
    //Check to see if node is a prefix of this path, if so the path belongs to us.
    auto comp = std::mismatch(node.begin(),node.end(),path.begin());
    if (comp.first == node.end()) {
      lock.unlock();
      return true;
    }
  }
  lock.unlock();
  return false;
}

<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2016 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU General Public License as published by the Free  *
* Software Foundation; either version 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <SofaSimulationTree/init.h>
#include <SofaSimulationTree/TreeSimulation.h>
#include <SofaComponentBase/initComponentBase.h>
#include <SofaComponentCommon/initComponentCommon.h>
#include <SofaComponentGeneral/initComponentGeneral.h>
#include <SofaComponentAdvanced/initComponentAdvanced.h>
#include <SofaComponentMisc/initComponentMisc.h>

#include <sofa/core/ObjectFactory.h>
using sofa::core::ObjectFactory ;

// ---------------------------------------------------------------------
// ---
// ---------------------------------------------------------------------
int main(int /*argc*/, char** argv)
{
    sofa::simulation::tree::init();
    sofa::component::initComponentBase();
    sofa::component::initComponentCommon();
    sofa::component::initComponentGeneral();
    sofa::component::initComponentAdvanced();
    sofa::component::initComponentMisc();

    std::vector<ObjectFactory::ClassEntry> result;
    ObjectFactory::getAllEntries(result);

    for(ObjectFactory::ClassEntry& entry : result)
    {
        for(std::string& aliasname : entry.aliases){
            std::cout << "./renameAliases.sh " << aliasname << " " << entry.m_componentName << std::endl ;
        }
    }

    return 0;
}
<commit_msg>[findAlias] FIX compilation of findAlias.<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2016 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU General Public License as published by the Free  *
* Software Foundation; either version 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <SofaSimulationTree/init.h>
#include <SofaSimulationTree/TreeSimulation.h>
#include <SofaComponentBase/initComponentBase.h>
#include <SofaComponentCommon/initComponentCommon.h>
#include <SofaComponentGeneral/initComponentGeneral.h>
#include <SofaComponentAdvanced/initComponentAdvanced.h>
#include <SofaComponentMisc/initComponentMisc.h>

#include <sofa/core/ObjectFactory.h>
using sofa::core::ObjectFactory ;

// ---------------------------------------------------------------------
// ---
// ---------------------------------------------------------------------
int main(int /*argc*/, char** argv)
{
    sofa::simulation::tree::init();
    sofa::component::initComponentBase();
    sofa::component::initComponentCommon();
    sofa::component::initComponentGeneral();
    sofa::component::initComponentAdvanced();
    sofa::component::initComponentMisc();

    std::vector<ObjectFactory::ClassEntry::SPtr> result;
    ObjectFactory::getInstance()->getAllEntries(result);

    for(ObjectFactory::ClassEntry::SPtr& entry : result)
    {
        for(std::string& aliasname : entry->aliases){
            std::cout << "./renameAliases.sh " << aliasname << " " << entry->m_componentName << std::endl ;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>// $Id$
// Category: event
//
// See the class description in the header file.

#include <G4Timer.hh>
   // in order to avoid the odd dependency for the
   // times system function this include must be the first

#include "AliEventAction.h"
#include "AliEventActionMessenger.h"
#include "AliTrackingAction.h"
#include "AliGlobals.h"
#include "AliRun.h"

#include <G4Event.hh>
#include <G4TrajectoryContainer.hh>
#include <G4Trajectory.hh>
#include <G4VVisManager.hh>
#include <G4UImanager.hh>

AliEventAction::AliEventAction()
  : fVerboseLevel(1),
    fDrawFlag("CHARGED")
{
//
  fMessenger = new AliEventActionMessenger(this);
  fTimer = new G4Timer();
}

AliEventAction::AliEventAction(const AliEventAction& right) {
//
  AliGlobals::Exception("AliEventAction is protected from copying.");
}

AliEventAction::~AliEventAction() {
//
  delete fMessenger;
  delete fTimer;
}

// operators

AliEventAction& AliEventAction::operator=(const AliEventAction &right)
{
  // check assignement to self
  if (this == &right) return *this;

  AliGlobals::Exception("AliEventAction is protected from assigning.");

  return *this;
}

// private methods

void AliEventAction::DisplayEvent(const G4Event* event) const
{
// Draws trajectories.
// ---

  // trajectories processing
  G4TrajectoryContainer* trajectoryContainer
    = event->GetTrajectoryContainer();

  G4int nofTrajectories = 0;
  if (trajectoryContainer)
  { nofTrajectories = trajectoryContainer->entries(); }

  if (fVerboseLevel>0 && nofTrajectories>0) {
    G4cout << "    " << nofTrajectories;
    G4cout << " trajectories stored." << G4endl;
  }

  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
  if(pVVisManager && nofTrajectories>0)
  {
    G4UImanager::GetUIpointer()->ApplyCommand("/vis~/draw/current");

    for (G4int i=0; i<nofTrajectories; i++)
    {
      G4VTrajectory* vtrajectory = (*(event->GetTrajectoryContainer()))[i];
      G4Trajectory* trajectory = dynamic_cast<G4Trajectory*>(vtrajectory);
      if (!trajectory) {
        AliGlobals::Exception(
	  "AliEventAction::DisplayEvent: Unknown trajectory type.");
      }
      if ( (fDrawFlag == "ALL") ||
          ((fDrawFlag == "CHARGED") && (trajectory->GetCharge() != 0.))){
	 trajectory->DrawTrajectory(50);
	    // the argument number defines the size of the step points
	    // use 2000 to make step points well visible
      }
    }
    G4UImanager::GetUIpointer()->ApplyCommand("/vis~/show/view");
  }
}

// public methods

void AliEventAction::BeginOfEventAction(const G4Event* event)
{
// Called by G4 kernel at the beginning of event.
// ---

  G4int eventID = event->GetEventID();

  // reset the tracks counters
  AliTrackingAction::Instance()->PrepareNewEvent();

  if (fVerboseLevel>0)
    G4cout << ">>> Event " << event->GetEventID() << G4endl;

  fTimer->Start();
}

void AliEventAction::EndOfEventAction(const G4Event* event)
{
// Called by G4 kernel at the end of event.
// ---

  // finish the last primary track of the current event
  AliTrackingAction* trackingAction = AliTrackingAction::Instance();
  trackingAction->FinishPrimaryTrack();

  // verbose output
  if (fVerboseLevel>0) {
    //G4int nofPrimaryTracks = trackingAction->GetNofPrimaryTracks();
    G4int nofPrimaryTracks = gAlice->GetHeader()->GetNprimary();
    G4int nofSavedTracks = gAlice->GetNtrack();
    G4int nofAllTracks = trackingAction->GetNofTracks();

    G4cout  << "    " << nofPrimaryTracks <<
               " primary tracks processed." << G4endl;
    G4cout  << "    " << nofSavedTracks <<
               " tracks saved." << G4endl;
    G4cout  << "    " << nofAllTracks <<
               " all tracks processed." << G4endl;
  }

  // display event
  DisplayEvent(event);

  // aliroot finish event
  gAlice->FinishEvent();

  if (fVerboseLevel>0) {
    // print time
    fTimer->Stop();
    G4cout << "Time of this event: " << *fTimer << G4endl;
  }
 }
<commit_msg>two levels of verbose introduced; AliHeader.h include added<commit_after>// $Id$
// Category: event
//
// See the class description in the header file.

#include <G4Timer.hh>
   // in order to avoid the odd dependency for the
   // times system function this include must be the first

#include "AliEventAction.h"
#include "AliEventActionMessenger.h"
#include "AliTrackingAction.h"
#include "AliGlobals.h"
#include "AliRun.h"
#include "AliHeader.h"

#include <G4Event.hh>
#include <G4TrajectoryContainer.hh>
#include <G4Trajectory.hh>
#include <G4VVisManager.hh>
#include <G4UImanager.hh>

AliEventAction::AliEventAction()
  : fVerboseLevel(1),
    fDrawFlag("CHARGED")
{
//
  fMessenger = new AliEventActionMessenger(this);
  fTimer = new G4Timer();
}

AliEventAction::AliEventAction(const AliEventAction& right) {
//
  AliGlobals::Exception("AliEventAction is protected from copying.");
}

AliEventAction::~AliEventAction() {
//
  delete fMessenger;
  delete fTimer;
}

// operators

AliEventAction& AliEventAction::operator=(const AliEventAction &right)
{
  // check assignement to self
  if (this == &right) return *this;

  AliGlobals::Exception("AliEventAction is protected from assigning.");

  return *this;
}

// private methods

void AliEventAction::DisplayEvent(const G4Event* event) const
{
// Draws trajectories.
// ---

  // trajectories processing
  G4TrajectoryContainer* trajectoryContainer
    = event->GetTrajectoryContainer();

  G4int nofTrajectories = 0;
  if (trajectoryContainer)
  { nofTrajectories = trajectoryContainer->entries(); }

  if (fVerboseLevel>0 && nofTrajectories>0) {
    G4cout << "    " << nofTrajectories;
    G4cout << " trajectories stored." << G4endl;
  }

  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
  if(pVVisManager && nofTrajectories>0)
  {
    G4UImanager::GetUIpointer()->ApplyCommand("/vis~/draw/current");

    for (G4int i=0; i<nofTrajectories; i++)
    {
      G4VTrajectory* vtrajectory = (*(event->GetTrajectoryContainer()))[i];
      G4Trajectory* trajectory = dynamic_cast<G4Trajectory*>(vtrajectory);
      if (!trajectory) {
        AliGlobals::Exception(
	  "AliEventAction::DisplayEvent: Unknown trajectory type.");
      }
      if ( (fDrawFlag == "ALL") ||
          ((fDrawFlag == "CHARGED") && (trajectory->GetCharge() != 0.))){
	 trajectory->DrawTrajectory(50);
	    // the argument number defines the size of the step points
	    // use 2000 to make step points well visible
      }
    }
    G4UImanager::GetUIpointer()->ApplyCommand("/vis~/show/view");
  }
}

// public methods

void AliEventAction::BeginOfEventAction(const G4Event* event)
{
// Called by G4 kernel at the beginning of event.
// ---

  G4int eventID = event->GetEventID();

  // reset the tracks counters
  AliTrackingAction::Instance()->PrepareNewEvent();

  if (fVerboseLevel>0)
    G4cout << ">>> Event " << event->GetEventID() << G4endl;

  fTimer->Start();
}

void AliEventAction::EndOfEventAction(const G4Event* event)
{
// Called by G4 kernel at the end of event.
// ---

  // finish the last primary track of the current event
  AliTrackingAction* trackingAction = AliTrackingAction::Instance();
  trackingAction->FinishPrimaryTrack();

  // verbose output
  if (fVerboseLevel>0) {
    G4cout << G4endl;
    G4cout << ">>> End of Event " << event->GetEventID() << G4endl;
  }

  if (fVerboseLevel>1) {
    //G4int nofPrimaryTracks = trackingAction->GetNofPrimaryTracks();
    G4int nofPrimaryTracks = gAlice->GetHeader()->GetNprimary();
    G4int nofSavedTracks = gAlice->GetNtrack();
    G4int nofAllTracks = trackingAction->GetNofTracks();

    G4cout  << "    " << nofPrimaryTracks <<
               " primary tracks processed." << G4endl;
    G4cout  << "    " << nofSavedTracks <<
               " tracks saved." << G4endl;
    G4cout  << "    " << nofAllTracks <<
               " all tracks processed." << G4endl;
  }

  // display event
  DisplayEvent(event);

  // aliroot finish event
  gAlice->FinishEvent();

  if (fVerboseLevel>1) {
    // print time
    fTimer->Stop();
    G4cout << "Time of this event: " << *fTimer << G4endl;
  }
 }
<|endoftext|>