Example #1
0
void html::EscapeText(Rewriter &R, FileID FID,
                      bool EscapeSpaces, bool ReplaceTabs) {

  const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
  const char* C = Buf->getBufferStart();
  const char* FileEnd = Buf->getBufferEnd();

  assert (C <= FileEnd);

  RewriteBuffer &RB = R.getEditBuffer(FID);

  unsigned ColNo = 0;
  for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) {
    switch (*C) {
    default: ++ColNo; break;
    case '\n':
    case '\r':
      ColNo = 0;
      break;

    case ' ':
      if (EscapeSpaces)
        RB.ReplaceText(FilePos, 1, "&nbsp;");
      ++ColNo;
      break;
    case '\f':
      RB.ReplaceText(FilePos, 1, "<hr>");
      ColNo = 0;
      break;

    case '\t': {
      if (!ReplaceTabs)
        break;
      unsigned NumSpaces = 8-(ColNo&7);
      if (EscapeSpaces)
        RB.ReplaceText(FilePos, 1,
                       StringRef("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
                                       "&nbsp;&nbsp;&nbsp;", 6*NumSpaces));
      else
        RB.ReplaceText(FilePos, 1, StringRef("        ", NumSpaces));
      ColNo += NumSpaces;
      break;
    }
    case '<':
      RB.ReplaceText(FilePos, 1, "&lt;");
      ++ColNo;
      break;

    case '>':
      RB.ReplaceText(FilePos, 1, "&gt;");
      ++ColNo;
      break;

    case '&':
      RB.ReplaceText(FilePos, 1, "&amp;");
      ++ColNo;
      break;
    }
  }
}
Example #2
0
bool formatAndApplyAllReplacements(
    const std::map<std::string, Replacements> &FileToReplaces, Rewriter &Rewrite,
    StringRef Style) {
  SourceManager &SM = Rewrite.getSourceMgr();
  FileManager &Files = SM.getFileManager();

  bool Result = true;
  for (const auto &FileAndReplaces : groupReplacementsByFile(FileToReplaces)) {
    const std::string &FilePath = FileAndReplaces.first;
    auto &CurReplaces = FileAndReplaces.second;

    const FileEntry *Entry = Files.getFile(FilePath);
    FileID ID = SM.getOrCreateFileID(Entry, SrcMgr::C_User);
    StringRef Code = SM.getBufferData(ID);

    format::FormatStyle CurStyle = format::getStyle(Style, FilePath, "LLVM");
    auto NewReplacements =
        format::formatReplacements(Code, CurReplaces, CurStyle);
    if (!NewReplacements) {
      llvm::errs() << llvm::toString(NewReplacements.takeError()) << "\n";
      return false;
    }
    Result = applyAllReplacements(*NewReplacements, Rewrite) && Result;
  }
  return Result;
}
Example #3
0
/// HighlightRange - Highlight a range in the source code with the specified
/// start/end tags.  B/E must be in the same file.  This ensures that
/// start/end tags are placed at the start/end of each line if the range is
/// multiline.
void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
                          const char *StartTag, const char *EndTag) {
  SourceManager &SM = R.getSourceMgr();
  B = SM.getInstantiationLoc(B);
  E = SM.getInstantiationLoc(E);
  FileID FID = SM.getFileID(B);
  assert(SM.getFileID(E) == FID && "B/E not in the same file!");

  unsigned BOffset = SM.getFileOffset(B);
  unsigned EOffset = SM.getFileOffset(E);
  
  // Include the whole end token in the range.
  EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
  
  HighlightRange(R.getEditBuffer(FID), BOffset, EOffset,
                 SM.getBufferData(FID).first, StartTag, EndTag);
}
Example #4
0
bool saveRewrittenFiles(Rewriter &Rewrite) {
  for (Rewriter::buffer_iterator I = Rewrite.buffer_begin(),
                                 E = Rewrite.buffer_end();
       I != E; ++I) {
    // FIXME: This code is copied from the FixItRewriter.cpp - I think it should
    // go into directly into Rewriter (there we also have the Diagnostics to
    // handle the error cases better).
    const FileEntry *Entry =
        Rewrite.getSourceMgr().getFileEntryForID(I->first);
    std::string ErrorInfo;
    llvm::raw_fd_ostream FileStream(
        Entry->getName(), ErrorInfo, llvm::sys::fs::F_Binary);
    llvm::raw_fd_ostream BackupStream(
	    (std::string(Entry->getName()) + ".orig").c_str(), ErrorInfo, llvm::sys::fs::F_Binary);
    if (!ErrorInfo.empty())
      return false;
    BackupStream << Rewrite.getSourceMgr().getBufferData(I->first);
    BackupStream.flush();
    I->second.write(FileStream);
    FileStream.flush();
  }
  return true;
}
Example #5
0
int main(int argc, const char **argv) {
    // parse the command-line args passed to your code
    static cl::OptionCategory MyToolCategory("My tool options");
    CommonOptionsParser op(argc, argv, MyToolCategory);        
    // create a new Clang Tool instance (a LibTooling environment)
    ClangTool Tool(op.getCompilations(), op.getSourcePathList());

    // run the Clang Tool, creating a new FrontendAction (explained below)
    int result = Tool.run(newFrontendActionFactory<ExampleFrontendAction>().get());

    errs() << "\nFound " << numFunctions << " functions.\n\n";
    // print out the rewritten source code ("rewriter" is a global var.)
    rewriter.getEditBuffer(rewriter.getSourceMgr().getMainFileID()).write(errs());
    return result;
}
Example #6
0
void SynthesizeRemovalConsumer::HandleTranslationUnit(ASTContext &C)
{
  if (compilerInstance->getDiagnostics().hasErrorOccurred()) {
    return;
  }
  
  astContext = &C;
  auto TUD = C.getTranslationUnitDecl();  
  removeSynthesizeDirectives(TUD);
  processDeclContext(TUD);

  if (removeSet.empty()) {
    // nothing is removed
    llvm::errs() << "nothing to remove.\n";
    return;
  }

  SourceManager &SM = rewriter.getSourceMgr();
  FileID FID = SM.getMainFileID();
  const FileEntry* F = SM.getFileEntryForID(FID);
  
  // backup the source
  std::string backupFilename = std::string(F->getName()) + ".bak";
  std::string errInfo;
  llvm::raw_fd_ostream backupStream(backupFilename.c_str(), errInfo,
    llvm::sys::fs::F_Binary);
  if (!errInfo.empty()) {
    llvm::errs() << "Cannot write backup file: " << backupFilename <<
      ", error info: " << errInfo << "\n";
    return;
  }
  backupStream << SM.getBufferData(FID);
  backupStream.flush();

  // write the output
  llvm::raw_fd_ostream outStream(F->getName(), errInfo,
    llvm::sys::fs::F_Binary);
  if (!errInfo.empty()) {
    llvm::errs() << "Cannot write output file: " << F->getName() <<
      ", error info: " << errInfo << "\n";
    return;
  }
    
  const RewriteBuffer *RB = rewriter.getRewriteBufferFor(FID);
  RB->write(outStream);
  outStream.flush();
}
Example #7
0
void html::AddLineNumbers(Rewriter& R, FileID FID) {

  const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
  const char* FileBeg = Buf->getBufferStart();
  const char* FileEnd = Buf->getBufferEnd();
  const char* C = FileBeg;
  RewriteBuffer &RB = R.getEditBuffer(FID);
  
  assert (C <= FileEnd);
  
  unsigned LineNo = 0;
  unsigned FilePos = 0;
  
  while (C != FileEnd) {    
    
    ++LineNo;
    unsigned LineStartPos = FilePos;
    unsigned LineEndPos = FileEnd - FileBeg;
    
    assert (FilePos <= LineEndPos);
    assert (C < FileEnd);
    
    // Scan until the newline (or end-of-file).
    
    while (C != FileEnd) {
      char c = *C;
      ++C;
      
      if (c == '\n') {
        LineEndPos = FilePos++;
        break;
      }
      
      ++FilePos;
    }
    
    AddLineNumber(RB, LineNo, LineStartPos, LineEndPos);
  }
  
  // Add one big table tag that surrounds all of the code.
  RB.InsertTextBefore(0, "<table class=\"code\">\n",
                      strlen("<table class=\"code\">\n"));
  
  RB.InsertTextAfter(FileEnd - FileBeg, "</table>", strlen("</table>"));
}
Example #8
0
/// \brief Convenience function to get rewritten content for \c Filename from
/// \c Rewrites.
///
/// \pre Replacements[i].getFilePath() == Replacements[i+1].getFilePath().
/// \post Replacements.empty() -> Result.empty()
///
/// \param[in] Replacements Replacements to apply
/// \param[in] Rewrites Rewriter to use to apply replacements.
/// \param[out] Result Contents of the file after applying replacements if
/// replacements were provided.
///
/// \returns \li true if all replacements were applied successfully.
///          \li false if at least one replacement failed to apply.
static bool
getRewrittenData(const std::vector<tooling::Replacement> &Replacements,
                 Rewriter &Rewrites, std::string &Result) {
  if (Replacements.empty()) return true;

  if (!tooling::applyAllReplacements(Replacements, Rewrites))
    return false;

  SourceManager &SM = Rewrites.getSourceMgr();
  FileManager &Files = SM.getFileManager();

  StringRef FileName = Replacements.begin()->getFilePath();
  const clang::FileEntry *Entry = Files.getFile(FileName);
  assert(Entry && "Expected an existing file");
  FileID ID = SM.translateFile(Entry);
  assert(!ID.isInvalid() && "Expected a valid FileID");
  const RewriteBuffer *Buffer = Rewrites.getRewriteBufferFor(ID);
  Result = std::string(Buffer->begin(), Buffer->end());

  return true;
}
Example #9
0
int main(int argc, const char **argv) {

    for(int i = 3; i+1< argc; i+=2){
        functionsMap[argv[i]]=argv[i+1];
    }

    CommonOptionsParser op(argc, argv, MyToolCategory);

    ClangTool Tool(op.getCompilations(), op.getSourcePathList());

    int result = Tool.run(newFrontendActionFactory<InserterFrontendAction>().get());

    std::vector<string> paths = op.getSourcePathList();
    StringRef path = (paths[0]).insert(paths[0].find('.'),"Secured");
    std::error_code EC;
    llvm::raw_fd_ostream fd(path, EC, sys::fs::F_RW);

    rewriter.getEditBuffer(rewriter.getSourceMgr().getMainFileID()).write(fd);

    return result;

}
Example #10
0
bool Replacement::apply(Rewriter &Rewrite) const {
  SourceManager &SM = Rewrite.getSourceMgr();
  const FileEntry *Entry = SM.getFileManager().getFile(FilePath);
  if (Entry == NULL)
    return false;
  FileID ID;
  // FIXME: Use SM.translateFile directly.
  SourceLocation Location = SM.translateFileLineCol(Entry, 1, 1);
  ID = Location.isValid() ?
    SM.getFileID(Location) :
    SM.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
  // FIXME: We cannot check whether Offset + Length is in the file, as
  // the remapping API is not public in the RewriteBuffer.
  const SourceLocation Start =
    SM.getLocForStartOfFile(ID).
    getLocWithOffset(Offset);
  // ReplaceText returns false on success.
  // ReplaceText only fails if the source location is not a file location, in
  // which case we already returned false earlier.
  bool RewriteSucceeded = !Rewrite.ReplaceText(Start, Length, ReplacementText);
  assert(RewriteSucceeded);
  return RewriteSucceeded;
}
Example #11
0
void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
                                     SourceRange Range,
                                     const char *HighlightStart,
                                     const char *HighlightEnd) {
  SourceManager &SM = R.getSourceMgr();
  const LangOptions &LangOpts = R.getLangOpts();

  SourceLocation InstantiationStart = SM.getExpansionLoc(Range.getBegin());
  unsigned StartLineNo = SM.getExpansionLineNumber(InstantiationStart);

  SourceLocation InstantiationEnd = SM.getExpansionLoc(Range.getEnd());
  unsigned EndLineNo = SM.getExpansionLineNumber(InstantiationEnd);

  if (EndLineNo < StartLineNo)
    return;

  if (SM.getFileID(InstantiationStart) != BugFileID ||
      SM.getFileID(InstantiationEnd) != BugFileID)
    return;

  // Compute the column number of the end.
  unsigned EndColNo = SM.getExpansionColumnNumber(InstantiationEnd);
  unsigned OldEndColNo = EndColNo;

  if (EndColNo) {
    // Add in the length of the token, so that we cover multi-char tokens.
    EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM, LangOpts)-1;
  }

  // Highlight the range.  Make the span tag the outermost tag for the
  // selected range.

  SourceLocation E =
    InstantiationEnd.getLocWithOffset(EndColNo - OldEndColNo);

  html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
}
Example #12
0
void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
                                  const PathDiagnosticPiece& P,
                                  unsigned num, unsigned max) {

  // For now, just draw a box above the line in question, and emit the
  // warning.
  FullSourceLoc Pos = P.getLocation().asLocation();

  if (!Pos.isValid())
    return;

  SourceManager &SM = R.getSourceMgr();
  assert(&Pos.getManager() == &SM && "SourceManagers are different!");
  std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedExpansionLoc(Pos);

  if (LPosInfo.first != BugFileID)
    return;

  const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
  const char* FileStart = Buf->getBufferStart();

  // Compute the column number.  Rewind from the current position to the start
  // of the line.
  unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second);
  const char *TokInstantiationPtr =Pos.getExpansionLoc().getCharacterData();
  const char *LineStart = TokInstantiationPtr-ColNo;

  // Compute LineEnd.
  const char *LineEnd = TokInstantiationPtr;
  const char* FileEnd = Buf->getBufferEnd();
  while (*LineEnd != '\n' && LineEnd != FileEnd)
    ++LineEnd;

  // Compute the margin offset by counting tabs and non-tabs.
  unsigned PosNo = 0;
  for (const char* c = LineStart; c != TokInstantiationPtr; ++c)
    PosNo += *c == '\t' ? 8 : 1;

  // Create the html for the message.

  const char *Kind = 0;
  switch (P.getKind()) {
  case PathDiagnosticPiece::Call:
      llvm_unreachable("Calls should already be handled");
  case PathDiagnosticPiece::Event:  Kind = "Event"; break;
  case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
    // Setting Kind to "Control" is intentional.
  case PathDiagnosticPiece::Macro: Kind = "Control"; break;
  }

  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);

  os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";

  if (num == max)
    os << "EndPath";
  else
    os << "Path" << num;

  os << "\" class=\"msg";
  if (Kind)
    os << " msg" << Kind;
  os << "\" style=\"margin-left:" << PosNo << "ex";

  // Output a maximum size.
  if (!isa<PathDiagnosticMacroPiece>(P)) {
    // Get the string and determining its maximum substring.
    const std::string& Msg = P.getString();
    unsigned max_token = 0;
    unsigned cnt = 0;
    unsigned len = Msg.size();

    for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
      switch (*I) {
      default:
        ++cnt;
        continue;
      case ' ':
      case '\t':
      case '\n':
        if (cnt > max_token) max_token = cnt;
        cnt = 0;
      }

    if (cnt > max_token)
      max_token = cnt;

    // Determine the approximate size of the message bubble in em.
    unsigned em;
    const unsigned max_line = 120;

    if (max_token >= max_line)
      em = max_token / 2;
    else {
      unsigned characters = max_line;
      unsigned lines = len / max_line;

      if (lines > 0) {
        for (; characters > max_token; --characters)
          if (len / characters > lines) {
            ++characters;
            break;
          }
      }

      em = characters / 2;
    }

    if (em < max_line/2)
      os << "; max-width:" << em << "em";
  }
  else
    os << "; max-width:100em";

  os << "\">";

  if (max > 1) {
    os << "<table class=\"msgT\"><tr><td valign=\"top\">";
    os << "<div class=\"PathIndex";
    if (Kind) os << " PathIndex" << Kind;
    os << "\">" << num << "</div>";

    if (num > 1) {
      os << "</td><td><div class=\"PathNav\"><a href=\"#Path"
         << (num - 1)
         << "\" title=\"Previous event ("
         << (num - 1)
         << ")\">&#x2190;</a></div></td>";
    }

    os << "</td><td>";
  }

  if (const PathDiagnosticMacroPiece *MP =
        dyn_cast<PathDiagnosticMacroPiece>(&P)) {

    os << "Within the expansion of the macro '";

    // Get the name of the macro by relexing it.
    {
      FullSourceLoc L = MP->getLocation().asLocation().getExpansionLoc();
      assert(L.isFileID());
      StringRef BufferInfo = L.getBufferData();
      std::pair<FileID, unsigned> LocInfo = L.getDecomposedLoc();
      const char* MacroName = LocInfo.second + BufferInfo.data();
      Lexer rawLexer(SM.getLocForStartOfFile(LocInfo.first), PP.getLangOpts(),
                     BufferInfo.begin(), MacroName, BufferInfo.end());

      Token TheTok;
      rawLexer.LexFromRawLexer(TheTok);
      for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
        os << MacroName[i];
    }

    os << "':\n";

    if (max > 1) {
      os << "</td>";
      if (num < max) {
        os << "<td><div class=\"PathNav\"><a href=\"#";
        if (num == max - 1)
          os << "EndPath";
        else
          os << "Path" << (num + 1);
        os << "\" title=\"Next event ("
        << (num + 1)
        << ")\">&#x2192;</a></div></td>";
      }

      os << "</tr></table>";
    }

    // Within a macro piece.  Write out each event.
    ProcessMacroPiece(os, *MP, 0);
  }
  else {
    os << html::EscapeText(P.getString());

    if (max > 1) {
      os << "</td>";
      if (num < max) {
        os << "<td><div class=\"PathNav\"><a href=\"#";
        if (num == max - 1)
          os << "EndPath";
        else
          os << "Path" << (num + 1);
        os << "\" title=\"Next event ("
           << (num + 1)
           << ")\">&#x2192;</a></div></td>";
      }
      
      os << "</tr></table>";
    }
  }

  os << "</div></td></tr>";

  // Insert the new html.
  unsigned DisplayPos = LineEnd - FileStart;
  SourceLocation Loc =
    SM.getLocForStartOfFile(LPosInfo.first).getLocWithOffset(DisplayPos);

  R.InsertTextBefore(Loc, os.str());

  // Now highlight the ranges.
  ArrayRef<SourceRange> Ranges = P.getRanges();
  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
                                       E = Ranges.end(); I != E; ++I) {
    HighlightRange(R, LPosInfo.first, *I);
  }
}
Example #13
0
void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
                                             const char *title) {

  const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
  const char* FileStart = Buf->getBufferStart();
  const char* FileEnd = Buf->getBufferEnd();

  SourceLocation StartLoc = R.getSourceMgr().getLocForStartOfFile(FID);
  SourceLocation EndLoc = StartLoc.getLocWithOffset(FileEnd-FileStart);

  std::string s;
  llvm::raw_string_ostream os(s);
  os << "<!doctype html>\n" // Use HTML 5 doctype
        "<html>\n<head>\n";

  if (title)
    os << "<title>" << html::EscapeText(title) << "</title>\n";

  os << "<style type=\"text/css\">\n"
      " body { color:#000000; background-color:#ffffff }\n"
      " body { font-family:Helvetica, sans-serif; font-size:10pt }\n"
      " h1 { font-size:14pt }\n"
      " .code { border-collapse:collapse; width:100%; }\n"
      " .code { font-family: \"Monospace\", monospace; font-size:10pt }\n"
      " .code { line-height: 1.2em }\n"
      " .comment { color: green; font-style: oblique }\n"
      " .keyword { color: blue }\n"
      " .string_literal { color: red }\n"
      " .directive { color: darkmagenta }\n"
      // Macro expansions.
      " .expansion { display: none; }\n"
      " .macro:hover .expansion { display: block; border: 2px solid #FF0000; "
          "padding: 2px; background-color:#FFF0F0; font-weight: normal; "
          "  -webkit-border-radius:5px;  -webkit-box-shadow:1px 1px 7px #000; "
          "  border-radius:5px;  box-shadow:1px 1px 7px #000; "
          "position: absolute; top: -1em; left:10em; z-index: 1 } \n"
      " .macro { color: darkmagenta; background-color:LemonChiffon;"
             // Macros are position: relative to provide base for expansions.
             " position: relative }\n"
      " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n"
      " .num { text-align:right; font-size:8pt }\n"
      " .num { color:#444444 }\n"
      " .line { padding-left: 1ex; border-left: 3px solid #ccc }\n"
      " .line { white-space: pre }\n"
      " .msg { -webkit-box-shadow:1px 1px 7px #000 }\n"
      " .msg { box-shadow:1px 1px 7px #000 }\n"
      " .msg { -webkit-border-radius:5px }\n"
      " .msg { border-radius:5px }\n"
      " .msg { font-family:Helvetica, sans-serif; font-size:8pt }\n"
      " .msg { float:left }\n"
      " .msg { padding:0.25em 1ex 0.25em 1ex }\n"
      " .msg { margin-top:10px; margin-bottom:10px }\n"
      " .msg { font-weight:bold }\n"
      " .msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap }\n"
      " .msgT { padding:0x; spacing:0x }\n"
      " .msgEvent { background-color:#fff8b4; color:#000000 }\n"
      " .msgControl { background-color:#bbbbbb; color:#000000 }\n"
      " .mrange { background-color:#dfddf3 }\n"
      " .mrange { border-bottom:1px solid #6F9DBE }\n"
      " .PathIndex { font-weight: bold; padding:0px 5px; "
        "margin-right:5px; }\n"
      " .PathIndex { -webkit-border-radius:8px }\n"
      " .PathIndex { border-radius:8px }\n"
      " .PathIndexEvent { background-color:#bfba87 }\n"
      " .PathIndexControl { background-color:#8c8c8c }\n"
      " .PathNav a { text-decoration:none; font-size: larger }\n"
      " .CodeInsertionHint { font-weight: bold; background-color: #10dd10 }\n"
      " .CodeRemovalHint { background-color:#de1010 }\n"
      " .CodeRemovalHint { border-bottom:1px solid #6F9DBE }\n"
      " table.simpletable {\n"
      "   padding: 5px;\n"
      "   font-size:12pt;\n"
      "   margin:20px;\n"
      "   border-collapse: collapse; border-spacing: 0px;\n"
      " }\n"
      " td.rowname {\n"
      "   text-align:right; font-weight:bold; color:#444444;\n"
      "   padding-right:2ex; }\n"
      "</style>\n</head>\n<body>";

  // Generate header
  R.InsertTextBefore(StartLoc, os.str());
  // Generate footer

  R.InsertTextAfter(EndLoc, "</body></html>\n");
}