//== HTMLRewrite.cpp - Translate source code into prettified HTML --*- C++ -*-// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the HTMLRewriter clas, which is used to translate the // text of a source file into prettified HTML. // //===----------------------------------------------------------------------===// #include "clang/Rewrite/Rewriter.h" #include "clang/Rewrite/HTMLRewrite.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/MemoryBuffer.h" #include using namespace clang; void html::EscapeText(Rewriter& R, unsigned FileID, bool EscapeSpaces, bool ReplaceTabs) { const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); const char* C = Buf->getBufferStart(); const char* FileEnd = Buf->getBufferEnd(); assert (C <= FileEnd); RewriteBuffer &RB = R.getEditBuffer(FileID); for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) { switch (*C) { default: break; case ' ': if (EscapeSpaces) RB.ReplaceText(FilePos, 1, " ", 6); break; case '\t': if (!ReplaceTabs) break; if (EscapeSpaces) RB.ReplaceText(FilePos, 1, "    ", 6*4); else RB.ReplaceText(FilePos, 1, " ", 4); break; case '<': RB.ReplaceText(FilePos, 1, "<", 4); break; case '>': RB.ReplaceText(FilePos, 1, ">", 4); break; case '&': RB.ReplaceText(FilePos, 1, "&", 5); break; } } } std::string html::EscapeText(const std::string& s, bool EscapeSpaces, bool ReplaceTabs) { unsigned len = s.size(); std::ostringstream os; for (unsigned i = 0 ; i < len; ++i) { char c = s[i]; switch (c) { default: os << c; break; case ' ': if (EscapeSpaces) os << " "; else os << ' '; break; case '\t': if (ReplaceTabs) for (unsigned i = 0; i < 4; ++i) os << " "; else os << c; break; case '<': os << "<"; break; case '>': os << ">"; break; case '&': os << "&"; break; } } return os.str(); } static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo, unsigned B, unsigned E) { llvm::SmallString<100> Str; Str += ""; Str.append_uint(LineNo); Str += ""; if (B == E) { // Handle empty lines. Str += " "; RB.InsertTextBefore(B, &Str[0], Str.size()); } else { RB.InsertTextBefore(B, &Str[0], Str.size()); RB.InsertTextBefore(E, "", strlen("")); } } void html::AddLineNumbers(Rewriter& R, unsigned FileID) { const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); const char* FileBeg = Buf->getBufferStart(); const char* FileEnd = Buf->getBufferEnd(); const char* C = FileBeg; RewriteBuffer &RB = R.getEditBuffer(FileID); 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, "\n", strlen("
\n")); RB.InsertTextAfter(FileEnd - FileBeg, "
", strlen("")); } void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID) { const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); const char* FileStart = Buf->getBufferStart(); const char* FileEnd = Buf->getBufferEnd(); SourceLocation StartLoc = SourceLocation::getFileLoc(FileID, 0); SourceLocation EndLoc = SourceLocation::getFileLoc(FileID, FileEnd-FileStart); // Generate header R.InsertCStrBefore(StartLoc, "\n\n" "\n\n"); // Generate footer R.InsertCStrAfter(EndLoc, "\n"); }