HTMLRewrite.cpp revision 4b0f81323b518429203051bbcd4864bbf4b000a9
1//== HTMLRewrite.cpp - Translate source code into prettified HTML --*- C++ -*-// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the HTMLRewriter clas, which is used to translate the 11// text of a source file into prettified HTML. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/Rewrite/Rewriter.h" 16#include "clang/Rewrite/HTMLRewrite.h" 17#include "clang/Basic/SourceManager.h" 18#include "llvm/Support/MemoryBuffer.h" 19#include <sstream> 20 21using namespace clang; 22 23void html::EscapeText(Rewriter& R, unsigned FileID, 24 bool EscapeSpaces, bool ReplaceTabs) { 25 26 const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); 27 const char* C = Buf->getBufferStart(); 28 const char* FileEnd = Buf->getBufferEnd(); 29 30 assert (C <= FileEnd); 31 32 for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) { 33 34 switch (*C) { 35 default: break; 36 37 case ' ': 38 if (EscapeSpaces) { 39 SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 40 R.ReplaceText(Loc, 1, " ", 6); 41 } 42 break; 43 44 case '\t': { 45 if (!ReplaceTabs) 46 break; 47 48 SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 49 50 if (EscapeSpaces) 51 R.ReplaceText(Loc, 1, " ", 6*4); 52 else 53 R.ReplaceText(Loc, 1, " ", 4); 54 55 break; 56 } 57 58 case '<': { 59 SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 60 R.ReplaceText(Loc, 1, "<", 4); 61 break; 62 } 63 64 case '>': { 65 SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 66 R.ReplaceText(Loc, 1, ">", 4); 67 break; 68 } 69 70 case '&': { 71 SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 72 R.ReplaceText(Loc, 1, "&", 5); 73 break; 74 } 75 } 76 } 77} 78 79std::string html::EscapeText(const std::string& s, bool EscapeSpaces, 80 bool ReplaceTabs) { 81 82 unsigned len = s.size(); 83 std::ostringstream os; 84 85 for (unsigned i = 0 ; i < len; ++i) { 86 87 char c = s[i]; 88 89 switch (c) { 90 default: 91 os << c; break; 92 93 case ' ': 94 if (EscapeSpaces) os << " "; 95 else os << ' '; 96 break; 97 98 case '\t': 99 if (ReplaceTabs) 100 for (unsigned i = 0; i < 4; ++i) os << " "; 101 else os << c; 102 103 break; 104 105 case '<': os << "<"; break; 106 case '>': os << ">"; break; 107 case '&': os << "&"; break; 108 } 109 } 110 111 return os.str(); 112} 113 114static void AddLineNumber(Rewriter& R, unsigned LineNo, 115 SourceLocation B, SourceLocation E) { 116 117 std::ostringstream os; 118 os << "<tr><td class=\"num\" id=\"LN" << LineNo << "\">" 119 << LineNo << "</td><td class=\"line\">"; 120 121 if (B == E) { // Handle empty lines. 122 os << " </td></tr>"; 123 R.InsertStrBefore(B, os.str()); 124 } 125 else { 126 R.InsertStrBefore(B, os.str()); 127 R.InsertCStrBefore(E, "</td></tr>"); 128 } 129} 130 131void html::AddLineNumbers(Rewriter& R, unsigned FileID) { 132 133 const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); 134 const char* FileBeg = Buf->getBufferStart(); 135 const char* FileEnd = Buf->getBufferEnd(); 136 const char* C = FileBeg; 137 138 assert (C <= FileEnd); 139 140 unsigned LineNo = 0; 141 unsigned FilePos = 0; 142 143 while (C != FileEnd) { 144 145 ++LineNo; 146 unsigned LineStartPos = FilePos; 147 unsigned LineEndPos = FileEnd - FileBeg; 148 149 assert (FilePos <= LineEndPos); 150 assert (C < FileEnd); 151 152 // Scan until the newline (or end-of-file). 153 154 while (C != FileEnd) { 155 char c = *C; 156 ++C; 157 158 if (c == '\n') { 159 LineEndPos = FilePos++; 160 break; 161 } 162 163 ++FilePos; 164 } 165 166 AddLineNumber(R, LineNo, 167 SourceLocation::getFileLoc(FileID, LineStartPos), 168 SourceLocation::getFileLoc(FileID, LineEndPos)); 169 } 170 171 // Add one big div tag that surrounds all of the code. 172 173 R.InsertCStrBefore(SourceLocation::getFileLoc(FileID, 0), 174 "<table class=\"code\">\n"); 175 176 R.InsertCStrAfter(SourceLocation::getFileLoc(FileID, FileEnd - FileBeg), 177 "</table>"); 178} 179 180void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID) { 181 182 const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); 183 const char* FileStart = Buf->getBufferStart(); 184 const char* FileEnd = Buf->getBufferEnd(); 185 186 SourceLocation StartLoc = SourceLocation::getFileLoc(FileID, 0); 187 SourceLocation EndLoc = SourceLocation::getFileLoc(FileID, FileEnd-FileStart); 188 189 // Generate header 190 191 R.InsertCStrBefore(StartLoc, 192 "<html>\n<head>\n" 193 "<style type=\"text/css\">\n" 194 " body { color:#000000; background-color:#ffffff }\n" 195 " body { font-family:Helvetica, sans-serif; font-size:10pt }\n" 196 " h1 { font-size:14pt }\n" 197 " .code { border-spacing:0px; width:100%; }\n" 198 " .code { font-family: \"Andale Mono\", monospace; font-size:10pt }\n" 199 " .code { line-height: 1.2em }\n" 200 " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n" 201 " .num { text-align:right; font-size: smaller }\n" 202 " .num { color:#444444 }\n" 203 " .line { padding-left: 1ex; border-left: 3px solid #ccc }\n" 204 " .line { white-space: pre }\n" 205 " .msg { background-color:#fff8b4; color:#000000 }\n" 206 " .msg { -webkit-box-shadow:1px 1px 7px #000 }\n" 207 " .msg { -webkit-border-radius:5px }\n" 208 " .msg { font-family:Helvetica, sans-serif; font-size: smaller }\n" 209 " .msg { font-weight: bold }\n" 210 " .msg { float:left }\n" 211 " .msg { padding:0.5em 1ex 0.5em 1ex }\n" 212 " .msg { margin-top:10px; margin-bottom:10px }\n" 213 " .mrange { background-color:#dfddf3 }\n" 214 " .mrange { border-bottom:1px solid #6F9DBE }\n" 215 " .PathIndex { font-weight: bold }\n" 216 " table.simpletable {\n" 217 " padding: 5px;\n" 218 " font-size:12pt;\n" 219 " margin:20px;\n" 220 " border-collapse: collapse; border-spacing: 0px;\n" 221 " }\n" 222 " td.rowname {\n" 223 " text-align:right; font-weight:bold; color:#444444;\n" 224 " padding-right:2ex; }\n" 225 "</style>\n</head>\n<body>"); 226 227 // Generate footer 228 229 R.InsertCStrAfter(EndLoc, "</body></html>\n"); 230} 231