Advertisement
Guest User

rewritersample.cpp

a guest
Jul 10th, 2013
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.12 KB | None | 0 0
  1. //-------------------------------------------------------------------------
  2. //
  3. // rewritersample.cpp: Source-to-source transformation sample with Clang,
  4. // using Rewriter - the code rewriting interface.
  5. //
  6. // This code is in the public domain
  7. //
  8. #include <cstdio>
  9. #include <string>
  10. #include <sstream>
  11. #include <iostream>
  12. #include <fstream>
  13.  
  14. #include "clang/AST/ASTConsumer.h"
  15. #include "clang/AST/RecursiveASTVisitor.h"
  16. #include "clang/Basic/Diagnostic.h"
  17. #include "clang/Basic/FileManager.h"
  18. #include "clang/Basic/SourceManager.h"
  19. #include "clang/Basic/TargetOptions.h"
  20. #include "clang/Basic/TargetInfo.h"
  21. #include "clang/Frontend/CompilerInstance.h"
  22. #include "clang/Lex/Preprocessor.h"
  23. #include "clang/Parse/ParseAST.h"
  24. #include "clang/Rewrite/Core/Rewriter.h"
  25. #include "clang/Rewrite/Frontend/Rewriters.h"
  26. #include "llvm/Support/Host.h"
  27. #include "llvm/Support/raw_ostream.h"
  28.  
  29. using namespace clang;
  30. using namespace std;
  31.  
  32. CompilerInstance* pTheCompInst_g;
  33. std::set<int> unexecutedlines_g;
  34.  
  35. void printheader (stringstream& mystr) {
  36. return;
  37.  
  38. mystr << "\
  39. <html>\
  40. <head>\
  41. \
  42. <script language=\"javascript\"> \
  43.     function toggle(xyz) {\
  44.         var displayText = \"displayText\"+xyz;\
  45.         var toggleText = \"toggleText\"+xyz;\
  46. \
  47.     var ele = document.getElementById(toggleText);\
  48.     var text = document.getElementById(displayText);\
  49.     if(ele.style.display == \"block\") {\
  50.             ele.style.display = \"none\";\
  51.         text.innerHTML = \"show\";\
  52.     }\
  53.     else {\
  54.         ele.style.display = \"block\";\
  55.         text.innerHTML = \"hide\";\
  56.     }\
  57. } \
  58. </script>\
  59. </head>\
  60. \
  61. <body>\
  62.     \
  63. <pre>\
  64. ";
  65.     return;
  66.  
  67. }
  68.  
  69. // By implementing RecursiveASTVisitor, we can specify which AST nodes
  70. // we're interested in by overriding relevant methods.
  71. class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
  72. {
  73. public:
  74.     MyASTVisitor(Rewriter &R)
  75.         : TheRewriter(R)
  76.     {}
  77.  
  78.     void printbefore(stringstream& str,int id) {
  79.     return;
  80.  
  81.         str << "<a id=\"displayText"<<id<<"\" href=\"javascript:toggle("<<id<<");\">show</a> <== click Here\n"
  82.             << "<div id=\"toggleText"<<id<<"\" style=\"display: none\">\n";
  83.  
  84.          return;
  85.     }
  86.     void printafter (stringstream& str) {
  87.     return;
  88.         str << "</div>\n";
  89.  
  90.         return;
  91.     }
  92.  
  93.     bool VisitStmt(Stmt *s) {
  94.         // Only care about If statements.
  95.         static int divid = 0;
  96.         if (isa<IfStmt>(s)) {
  97.             IfStmt *IfStatement = cast<IfStmt>(s);
  98.             Stmt *Then = IfStatement->getThen();
  99.  
  100.             PresumedLoc PLoc = pTheCompInst_g->getSourceManager().getPresumedLoc(IfStatement->getLocStart(), 1);//DiagOpts->ShowPresumedLoc);
  101.             cout << "Line number is " << PLoc.getLine() << endl;
  102.             cout << "Line number is " << pTheCompInst_g->getSourceManager().getSpellingLineNumber(IfStatement->getLocStart(), 0) << endl;
  103.             cout << "Line number is " << pTheCompInst_g->getSourceManager().getExpansionLineNumber(IfStatement->getLocStart(), 0) << endl;
  104.             cout << "Line number is " << pTheCompInst_g->getSourceManager().getPresumedLineNumber(IfStatement->getLocStart(), 0) << endl;
  105.             cout << "-----------------\n";
  106.  
  107.  
  108.  
  109.  
  110.             stringstream str_before;
  111.             //printbefore(str_before, divid);
  112.             divid++;
  113.             TheRewriter.InsertText(Then->getLocStart(), str_before.str(), true,true);  
  114.  
  115.             SourceLocation END = Then->getLocEnd();
  116.             int offset = Lexer::MeasureTokenLength(END,
  117.                                            pTheCompInst_g->getSourceManager(),
  118.                                            pTheCompInst_g->getLangOpts()) + 1;
  119.  
  120.             SourceLocation END1 = END.getLocWithOffset(offset);
  121.  
  122.             stringstream str_after;
  123.             //printafter(str_after);
  124.             TheRewriter.InsertText(END1,
  125.                                    str_after.str(),
  126.                                    true, true);
  127.  
  128.  
  129.             Stmt *Else = IfStatement->getElse();
  130.             if (Else) {
  131.                 SourceLocation END = Else->getLocEnd();
  132.                 int offset = Lexer::MeasureTokenLength(END,
  133.                                            pTheCompInst_g->getSourceManager(),
  134.                                            pTheCompInst_g->getLangOpts()) + 1;
  135.  
  136.                 SourceLocation END1 = END.getLocWithOffset(offset);
  137.  
  138.                 TheRewriter.InsertText(Else->getLocStart(),
  139.                                        "// the 'else' part\n",
  140.                                        true, true);
  141.             }
  142.         }
  143.  
  144.         return true;
  145.     }
  146.  
  147.     bool VisitFunctionDecl(FunctionDecl *f) {
  148.         // Only function definitions (with bodies), not declarations.
  149.         if (f->hasBody()) {
  150.             Stmt *FuncBody = f->getBody();
  151.  
  152.             // Type name as string
  153.             QualType QT = f->getResultType();
  154.             string TypeStr = QT.getAsString();
  155.  
  156.             // Function name
  157.             DeclarationName DeclName = f->getNameInfo().getName();
  158.             string FuncName = DeclName.getAsString();
  159.  
  160.             // Add comment before
  161.             stringstream SSBefore;
  162.             SSBefore << "// Begin function " << FuncName << " returning "
  163.                      << TypeStr << "\n";
  164.             SourceLocation ST = f->getSourceRange().getBegin();
  165.             TheRewriter.InsertText(ST, SSBefore.str(), true, true);
  166.  
  167.             // And after
  168.             stringstream SSAfter;
  169.             SSAfter << "\n// End function " << FuncName << "\n";
  170.             ST = FuncBody->getLocEnd().getLocWithOffset(1);
  171.             TheRewriter.InsertText(ST, SSAfter.str(), true, true);
  172.         }
  173.  
  174.         return true;
  175.     }
  176.  
  177. private:
  178.     void AddBraces(Stmt *s);
  179.  
  180.     Rewriter &TheRewriter;
  181. };
  182.  
  183.  
  184. // Implementation of the ASTConsumer interface for reading an AST produced
  185. // by the Clang parser.
  186. class MyASTConsumer : public ASTConsumer
  187. {
  188. public:
  189.     MyASTConsumer(Rewriter &R)
  190.         : Visitor(R)
  191.     {}
  192.  
  193.     // Override the method that gets called for each parsed top-level
  194.     // declaration.
  195.     virtual bool HandleTopLevelDecl(DeclGroupRef DR) {
  196.         for (DeclGroupRef::iterator b = DR.begin(), e = DR.end();
  197.              b != e; ++b)
  198.             // Traverse the declaration using our AST visitor.
  199.             Visitor.TraverseDecl(*b);
  200.         return true;
  201.     }
  202.  
  203. private:
  204.     MyASTVisitor Visitor;
  205. };
  206.  
  207.  
  208. int main(int argc, char *argv[])
  209. {
  210.     if (argc != 2) {
  211.         llvm::errs() << "Usage: rewritersample <filename>\n";
  212.         //llvm::errs() << "Usage: rewritersample <filename> <gcov-file>\n";
  213.         return 1;
  214.     }
  215.  
  216.     // CompilerInstance will hold the instance of the Clang compiler for us,
  217.     // managing the various objects needed to run the compiler.
  218.     CompilerInstance TheCompInst;
  219.     pTheCompInst_g = &TheCompInst;
  220.  
  221.     /*
  222.     LangOptions& Opts = TheCompInst.getLangOpts();
  223.     TheCompInst.getInvocation().setLangDefaults (Opts, IK_CXX);
  224.     */
  225.  
  226.     //TheCompInst.createDiagnostics(0, 0);
  227.     TheCompInst.createDiagnostics(NULL, false);
  228.  
  229.     // Initialize target info with the default triple for our platform.
  230.     TargetOptions TO;
  231.     TO.Triple = llvm::sys::getDefaultTargetTriple();
  232.     TargetInfo *TI = TargetInfo::CreateTargetInfo(
  233.         TheCompInst.getDiagnostics(), &TO);
  234.     TheCompInst.setTarget(TI);
  235.  
  236.     TheCompInst.createFileManager();
  237.     FileManager &FileMgr = TheCompInst.getFileManager();
  238.     TheCompInst.createSourceManager(FileMgr);
  239.     SourceManager &SourceMgr = TheCompInst.getSourceManager();
  240.     TheCompInst.createPreprocessor();
  241.     TheCompInst.createASTContext();
  242.  
  243.     // A Rewriter helps us manage the code rewriting task.
  244.     Rewriter TheRewriter;
  245.     TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts());
  246.  
  247. #if 0
  248.     //Parse the gcov file.
  249.     std::ifstream infile (argv[2]);
  250.     string line;
  251.     int linenum = 0;
  252.     while (std::getline(infile,line)) {
  253.         //cout << line << endl;
  254.         linenum++;
  255.         const char* str = line.c_str();
  256.         if (!strncmp (str,"    #####:", strlen ("    #####:"))) {
  257.             unexecutedlines_g.insert (linenum);
  258.         }
  259.     }
  260. #endif
  261.  
  262.     // Set the main file handled by the source manager to the input file.
  263.     const FileEntry *FileIn = FileMgr.getFile(argv[1]);
  264.     SourceMgr.createMainFileID(FileIn);
  265.     TheCompInst.getDiagnosticClient().BeginSourceFile(
  266.         TheCompInst.getLangOpts(),
  267.         &TheCompInst.getPreprocessor());
  268.  
  269.     // Create an AST consumer instance which is going to get called by
  270.     // ParseAST.
  271.     MyASTConsumer TheConsumer(TheRewriter);
  272.  
  273.     // Parse the file to AST, registering our consumer as the AST consumer.
  274.     ParseAST(TheCompInst.getPreprocessor(), &TheConsumer,
  275.              TheCompInst.getASTContext());
  276.  
  277.  
  278.     stringstream str;
  279.     printheader (str);
  280.     cout << str.str() <<endl;
  281.  
  282.     // At this point the rewriter's buffer should be full with the rewritten
  283.     // file contents.
  284.     const RewriteBuffer *RewriteBuf =
  285.         TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID());
  286.     llvm::outs() << string(RewriteBuf->begin(), RewriteBuf->end());
  287.  
  288.     llvm::outs() << string("</pre></body></html>\n");
  289.     exit (-1);
  290.     return 0;
  291. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement