HTMLRewrite.cpp revision fa5be3617294f0e3c341f0ecb6b2076478b1b5ac
16a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek//== HTMLRewrite.cpp - Translate source code into prettified HTML --*- C++ -*-// 26a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// 36a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// The LLVM Compiler Infrastructure 46a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// 56a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// This file is distributed under the University of Illinois Open Source 66a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// License. See LICENSE.TXT for details. 76a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// 86a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek//===----------------------------------------------------------------------===// 96a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// 106a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// This file defines the HTMLRewriter clas, which is used to translate the 116a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// text of a source file into prettified HTML. 126a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek// 136a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek//===----------------------------------------------------------------------===// 146a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 156a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "clang/Rewrite/Rewriter.h" 166a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "clang/Rewrite/HTMLRewrite.h" 176a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "clang/Basic/SourceManager.h" 186a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "llvm/Support/MemoryBuffer.h" 196a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include <sstream> 206a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 216a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenekusing namespace clang; 226a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 23fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenekvoid html::EscapeText(Rewriter& R, unsigned FileID, 24fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek bool EscapeSpaces, bool ReplaceTabs) { 256a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 266a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); 276a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek const char* C = Buf->getBufferStart(); 286a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek const char* FileEnd = Buf->getBufferEnd(); 296a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 306a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek assert (C <= FileEnd); 316a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 326a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) { 3349cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek 346a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek switch (*C) { 356a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek default: break; 366a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 376a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek case ' ': 3849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek if (EscapeSpaces) { 3949cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 4049cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek R.ReplaceText(Loc, 1, " ", 6); 4149cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 426a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek break; 436a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 4449cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek case '\t': { 45fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek if (!ReplaceTabs) 46fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek break; 47fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek 4849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 494ce32cb52b19102216f3120b81b4de5227b8d5f0Ted Kremenek 504ce32cb52b19102216f3120b81b4de5227b8d5f0Ted Kremenek if (EscapeSpaces) 514ce32cb52b19102216f3120b81b4de5227b8d5f0Ted Kremenek R.ReplaceText(Loc, 1, " ", 6*4); 524ce32cb52b19102216f3120b81b4de5227b8d5f0Ted Kremenek else 534ce32cb52b19102216f3120b81b4de5227b8d5f0Ted Kremenek R.ReplaceText(Loc, 1, " ", 4); 544ce32cb52b19102216f3120b81b4de5227b8d5f0Ted Kremenek 5549cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek break; 5649cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 5749cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek 5849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek case '<': { 5949cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 6049cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek R.ReplaceText(Loc, 1, "<", 4); 6149cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek break; 6249cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 6349cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek 6449cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek case '>': { 6549cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 6649cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek R.ReplaceText(Loc, 1, ">", 4); 6749cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek break; 6849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 6949cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek 7049cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek case '&': { 7149cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos); 7249cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek R.ReplaceText(Loc, 1, "&", 5); 7349cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek break; 7449cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 756a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek } 766a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek } 776a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek} 786a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 79fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenekstd::string html::EscapeText(const std::string& s, bool EscapeSpaces, 80fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek bool ReplaceTabs) { 81053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 82053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek unsigned len = s.size(); 83053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek std::ostringstream os; 84053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 85053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek for (unsigned i = 0 ; i < len; ++i) { 86053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 87053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek char c = s[i]; 88053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 89053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek switch (c) { 90053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek default: 91053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek os << c; break; 92053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 93053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek case ' ': 948fb001684fb7740d6bed973f927bc33bc7473ff7Ted Kremenek if (EscapeSpaces) os << " "; 95487f827a7f8e9b2c89aec0d35b6154cb17116444Ted Kremenek else os << ' '; 96053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek break; 97053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 98fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek case '\t': 99fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek if (ReplaceTabs) 100fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek for (unsigned i = 0; i < 4; ++i) os << " "; 101fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek else os << c; 102fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek 103fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek break; 104fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek 105053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek case '<': os << "<"; break; 106053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek case '>': os << ">"; break; 107053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek case '&': os << "&"; break; 108053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek } 109053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek } 110053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 111053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek return os.str(); 112053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek} 113053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 114b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenekstatic void AddLineNumber(Rewriter& R, unsigned LineNo, 115b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek SourceLocation B, SourceLocation E) { 116f830997de6ca8aa9526a9f4bb44593c19040ca85Ted Kremenek 117b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek std::ostringstream os; 118356708cb339d3f727ff85f9fb251e4f8d4e5bd1cTed Kremenek os << "<tr><td class=\"num\" id=\"LN" << LineNo << "\">" 119356708cb339d3f727ff85f9fb251e4f8d4e5bd1cTed Kremenek << LineNo << "</td><td class=\"line\">"; 12013e479b2b74771738a5e5c5dc1c270416924b126Ted Kremenek 12149cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek if (B == E) { // Handle empty lines. 12249cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek os << " </td></tr>"; 12349cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek R.InsertStrBefore(B, os.str()); 12449cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 12549cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek else { 12649cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek R.InsertStrBefore(B, os.str()); 12749cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek R.InsertCStrBefore(E, "</td></tr>"); 12849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 129b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek} 130b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 131b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenekvoid html::AddLineNumbers(Rewriter& R, unsigned FileID) { 132b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 133b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); 134b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek const char* FileBeg = Buf->getBufferStart(); 135b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek const char* FileEnd = Buf->getBufferEnd(); 136b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek const char* C = FileBeg; 137b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 138b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek assert (C <= FileEnd); 139b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 140b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek unsigned LineNo = 0; 141b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek unsigned FilePos = 0; 142b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 143b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek while (C != FileEnd) { 144b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 145b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek ++LineNo; 146b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek unsigned LineStartPos = FilePos; 147b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek unsigned LineEndPos = FileEnd - FileBeg; 148b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 149b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek assert (FilePos <= LineEndPos); 150b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek assert (C < FileEnd); 151b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 152b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek // Scan until the newline (or end-of-file). 153b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 15449cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek while (C != FileEnd) { 15549cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek char c = *C; 15649cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek ++C; 15749cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek 15849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek if (c == '\n') { 15949cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek LineEndPos = FilePos++; 160b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek break; 161b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek } 16249cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek 16349cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek ++FilePos; 16449cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek } 165b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 166b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek AddLineNumber(R, LineNo, 167b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek SourceLocation::getFileLoc(FileID, LineStartPos), 16849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek SourceLocation::getFileLoc(FileID, LineEndPos)); 169d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek } 170d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek 171d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek // Add one big div tag that surrounds all of the code. 172d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek 173d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek R.InsertCStrBefore(SourceLocation::getFileLoc(FileID, 0), 174e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek "<table class=\"code\">\n"); 175d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek 176d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek R.InsertCStrAfter(SourceLocation::getFileLoc(FileID, FileEnd - FileBeg), 177e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek "</table>"); 178b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek} 179ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 180ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenekvoid html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID) { 181ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 182ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); 183ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek const char* FileStart = Buf->getBufferStart(); 184ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek const char* FileEnd = Buf->getBufferEnd(); 185ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 186ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek SourceLocation StartLoc = SourceLocation::getFileLoc(FileID, 0); 187ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek SourceLocation EndLoc = SourceLocation::getFileLoc(FileID, FileEnd-FileStart); 188ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 189ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek // Generate header 190ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 191ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek { 192ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek std::ostringstream os; 193ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 194ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek os << "<html>\n<head>\n" 195eeacc5203ae1defadbe647b3b22b0432e23f4393Ted Kremenek << "<style type=\"text/css\">\n" 196eeacc5203ae1defadbe647b3b22b0432e23f4393Ted Kremenek << " body { color:#000000; background-color:#ffffff }\n" 197487f827a7f8e9b2c89aec0d35b6154cb17116444Ted Kremenek << " body { font-family:Helvetica, sans-serif; font-size:10pt }\n" 198487f827a7f8e9b2c89aec0d35b6154cb17116444Ted Kremenek << " h1 { font-size:12pt }\n" 199e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .code { border-spacing:0px; width:100%; }\n" 2006ccb91abc37700e646139f49c448ccdbf14eb575Chris Lattner << " .code { font-family: \"Andale Mono\", monospace; font-size:10pt }\n" 201e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .code { line-height: 1.2em }\n" 202e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n" 203e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .num { text-align:right; font-size: smaller }\n" 2040f1b67bc25058b71eacc0d9ef85075fff23e7b31Ted Kremenek << " .num { color:#444444 }\n" 205e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .line { padding-left: 1ex; border-left: 3px solid #ccc }\n" 206e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .line { white-space: pre }\n" 2077e54eede4079085f35b91cc9a4f5c38a1c4f9890Ted Kremenek << " .msg { background-color:#fff8b4; color:#000000 }\n" 2089d4e659fce4e0cc7cb36fce9fedb42a3e4c38496Ted Kremenek << " .msg { -webkit-box-shadow:1px 1px 7px #000 }\n" 2099d4e659fce4e0cc7cb36fce9fedb42a3e4c38496Ted Kremenek << " .msg { -webkit-border-radius:5px }\n" 210e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .msg { font-family:Helvetica, sans-serif; font-size: smaller }\n" 211db87ca09df48d3cc6ac868debd68c72c878a0daaTed Kremenek << " .msg { font-weight: bold }\n" 212e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << " .msg { float:left }\n" 213eeacc5203ae1defadbe647b3b22b0432e23f4393Ted Kremenek << " .msg { padding:0.5em 1ex 0.5em 1ex }\n" 214eeacc5203ae1defadbe647b3b22b0432e23f4393Ted Kremenek << " .msg { margin-top:10px; margin-bottom:10px }\n" 215f23621f1fc448cab7d896cd80e3abf35cb97af1fTed Kremenek << " .mrange { background-color:#dfddf3 }\n" 2169e628a02f43a93d30d5be7680ce5c3bbccf6ce79Ted Kremenek << " .mrange { border-bottom:1px solid #6F9DBE }\n" 217718ceb13e078ff99d3338e643c7ea6cf797b0e8bTed Kremenek << " .PathIndex { font-weight: bold }\n" 218e8e019ede11579bce271bee0b2b0b543bd9833a5Ted Kremenek << "</style>\n</head>\n<body>"; 219ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 220ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek R.InsertStrBefore(StartLoc, os.str()); 221ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek } 222ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 223ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek // Generate footer 224ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 225ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek { 226ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek std::ostringstream os; 227ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 228ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek os << "</body></html>\n"; 229ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek R.InsertStrAfter(EndLoc, os.str()); 230ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek } 231ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek} 232ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 233ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 234