blob: 9bd18109bbb4d50475eb7a0fc56919691f5894b1 [file] [log] [blame]
Ted Kremenek6a340832008-03-18 21:19:49 +00001//== 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, bool EscapeSpaces) {
24
25 const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID);
26 const char* C = Buf->getBufferStart();
27 const char* FileEnd = Buf->getBufferEnd();
28
29 assert (C <= FileEnd);
30
31 for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) {
32
33 SourceLocation Loc = SourceLocation::getFileLoc(FileID, FilePos);
34
35 switch (*C) {
36 default: break;
37
38 case ' ':
39 if (EscapeSpaces) R.ReplaceText(Loc, 1, "&#32;", 5);
40 break;
41
42 case '<': R.ReplaceText(Loc, 1, "&lt;", 4); break;
43 case '>': R.ReplaceText(Loc, 1, "&gt;", 4); break;
44 case '&': R.ReplaceText(Loc, 1, "&amp;", 5); break;
45 }
46 }
47}
48
Ted Kremenekb485cd12008-03-18 23:08:51 +000049static void AddLineNumber(Rewriter& R, unsigned LineNo,
50 SourceLocation B, SourceLocation E) {
Ted Kremenekf8309972008-03-19 01:30:02 +000051
Ted Kremenekd6c13602008-03-19 05:07:26 +000052 // Surround the line text with a div tag.
Ted Kremenekb485cd12008-03-18 23:08:51 +000053
Ted Kremenekd6c13602008-03-19 05:07:26 +000054 if (B == E) // Handle empty lines.
55 R.InsertCStrBefore(B, "<div class=\"lines\"> </div>");
56 else {
57 R.InsertCStrBefore(E, "</div>");
58 R.InsertCStrBefore(B, "<div class=\"lines\">");
59 }
Ted Kremenekf8309972008-03-19 01:30:02 +000060
Ted Kremenekd6c13602008-03-19 05:07:26 +000061 // Insert a div tag for the line number.
62
Ted Kremenekb485cd12008-03-18 23:08:51 +000063 std::ostringstream os;
Ted Kremenekd6c13602008-03-19 05:07:26 +000064 os << "<div class=\"nums\">" << LineNo << "</div>";
65
66 R.InsertStrBefore(B, os.str());
67
68 // Now surround the whole line with another div tag.
69
70 R.InsertCStrBefore(B, "<div class=\"codeline\">");
71 R.InsertCStrAfter(E, "</div>");
Ted Kremenekb485cd12008-03-18 23:08:51 +000072}
73
74void html::AddLineNumbers(Rewriter& R, unsigned FileID) {
75
76 const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID);
77 const char* FileBeg = Buf->getBufferStart();
78 const char* FileEnd = Buf->getBufferEnd();
79 const char* C = FileBeg;
80
81 assert (C <= FileEnd);
82
83 unsigned LineNo = 0;
84 unsigned FilePos = 0;
85
86 while (C != FileEnd) {
87
88 ++LineNo;
89 unsigned LineStartPos = FilePos;
90 unsigned LineEndPos = FileEnd - FileBeg;
91
92 assert (FilePos <= LineEndPos);
93 assert (C < FileEnd);
94
95 // Scan until the newline (or end-of-file).
96
97 for ( ; C != FileEnd ; ++C, ++FilePos)
98 if (*C == '\n') {
99 LineEndPos = FilePos;
100 break;
101 }
102
103 AddLineNumber(R, LineNo,
104 SourceLocation::getFileLoc(FileID, LineStartPos),
105 SourceLocation::getFileLoc(FileID, LineEndPos));
106
107 if (C != FileEnd) {
108 ++C;
109 ++FilePos;
110 }
Ted Kremenekd6c13602008-03-19 05:07:26 +0000111 }
112
113 // Add one big div tag that surrounds all of the code.
114
115 R.InsertCStrBefore(SourceLocation::getFileLoc(FileID, 0),
116 "<div id=\"codeblock\">");
117
118 R.InsertCStrAfter(SourceLocation::getFileLoc(FileID, FileEnd - FileBeg),
119 "</div>");
Ted Kremenekb485cd12008-03-18 23:08:51 +0000120}