19#include "llvm/ADT/RewriteBuffer.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/raw_ostream.h"
33 const char *StartTag,
const char *EndTag,
36 B =
SM.getExpansionLoc(B);
37 E =
SM.getExpansionLoc(
E);
39 assert(
SM.getFileID(
E) == FID &&
"B/E not in the same file!");
41 unsigned BOffset =
SM.getFileOffset(B);
42 unsigned EOffset =
SM.getFileOffset(
E);
49 const char *BufferStart =
SM.getBufferData(FID, &
Invalid).data();
54 BufferStart, StartTag, EndTag);
60 const char *BufferStart,
61 const char *StartTag,
const char *EndTag) {
63 RB.InsertTextAfter(B, StartTag);
64 RB.InsertTextBefore(
E, EndTag);
68 bool HadOpenTag =
true;
70 unsigned LastNonWhiteSpace = B;
71 for (
unsigned i = B; i !=
E; ++i) {
72 switch (BufferStart[i]) {
78 RB.InsertTextBefore(LastNonWhiteSpace+1, EndTag);
97 RB.InsertTextAfter(i, StartTag);
102 LastNonWhiteSpace = i;
131 return std::make_shared<RelexRewriteCache>();
135 bool EscapeSpaces,
bool ReplaceTabs) {
138 const char*
C = Buf.getBufferStart();
139 const char* FileEnd = Buf.getBufferEnd();
141 assert (
C <= FileEnd);
146 for (
unsigned FilePos = 0;
C != FileEnd ; ++
C, ++FilePos) {
148 default: ++ColNo;
break;
156 RB.ReplaceText(FilePos, 1,
" ");
160 RB.ReplaceText(FilePos, 1,
"<hr>");
167 unsigned NumSpaces = 8-(ColNo&7);
169 RB.ReplaceText(FilePos, 1,
170 StringRef(
" "
171 " ", 6*NumSpaces));
173 RB.ReplaceText(FilePos, 1, StringRef(
" ", NumSpaces));
178 RB.ReplaceText(FilePos, 1,
"<");
183 RB.ReplaceText(FilePos, 1,
">");
188 RB.ReplaceText(FilePos, 1,
"&");
197 unsigned len =
s.size();
199 llvm::raw_string_ostream os(Str);
201 for (
unsigned i = 0 ; i < len; ++i) {
209 if (EscapeSpaces) os <<
" ";
216 for (
unsigned i = 0; i < 4; ++i)
219 for (
unsigned i = 0; i < 4; ++i)
227 case '<': os <<
"<";
break;
228 case '>': os <<
">";
break;
229 case '&': os <<
"&";
break;
237 unsigned B,
unsigned E) {
239 llvm::raw_svector_ostream OS(Str);
241 OS <<
"<tr class=\"codeline\" data-linenumber=\"" << LineNo <<
"\">"
242 <<
"<td class=\"num\" id=\"LN" << LineNo <<
"\">" << LineNo
243 <<
"</td><td class=\"line\">";
247 RB.InsertTextBefore(B, OS.str());
249 RB.InsertTextBefore(B, OS.str());
250 RB.InsertTextBefore(
E,
"</td></tr>");
257 const char* FileBeg = Buf.getBufferStart();
258 const char* FileEnd = Buf.getBufferEnd();
259 const char*
C = FileBeg;
262 assert (
C <= FileEnd);
265 unsigned FilePos = 0;
267 while (
C != FileEnd) {
270 unsigned LineStartPos = FilePos;
271 unsigned LineEndPos = FileEnd - FileBeg;
273 assert (FilePos <= LineEndPos);
274 assert (
C < FileEnd);
278 while (
C != FileEnd) {
283 LineEndPos = FilePos++;
295 llvm::raw_string_ostream os(
s);
296 os <<
"<table class=\"code\" data-fileid=\"" << FID.
getHashValue() <<
"\">\n";
297 RB.InsertTextBefore(0, os.str());
298 RB.InsertTextAfter(FileEnd - FileBeg,
"</table>");
305 const char* FileStart = Buf.getBufferStart();
306 const char* FileEnd = Buf.getBufferEnd();
312 llvm::raw_string_ostream os(
s);
313 os <<
"<!doctype html>\n"
320<style type="text/css">
321body { color:#000000; background-color:#ffffff }
322body { font-family:Helvetica, sans-serif; font-size:10pt }
324.FileName { margin-top: 5px; margin-bottom: 5px; display: inline; }
325.FileNav { margin-left: 5px; margin-right: 5px; display: inline; }
326.FileNav a { text-decoration:none; font-size: larger; }
327.divider { margin-top: 30px; margin-bottom: 30px; height: 15px; }
328.divider { background-color: gray; }
329.code { border-collapse:collapse; width:100%; }
330.code { font-family: "Monospace", monospace; font-size:10pt }
331.code { line-height: 1.2em }
332.comment { color: green; font-style: oblique }
333.keyword { color: blue }
334.string_literal { color: red }
335.directive { color: darkmagenta }
337/* Macros and variables could have pop-up notes hidden by default.
338 - Macro pop-up: expansion of the macro
339 - Variable pop-up: value (table) of the variable */
340.macro_popup, .variable_popup { display: none; }
342/* Pop-up appears on mouse-hover event. */
343.macro:hover .macro_popup, .variable:hover .variable_popup {
346 -webkit-border-radius:5px;
347 -webkit-box-shadow:1px 1px 7px #000;
349 box-shadow:1px 1px 7px #000;
357 border: 2px solid red;
358 background-color:#FFF0F0;
363 border: 2px solid blue;
364 background-color:#F0F0FF;
366 font-family: Helvetica, sans-serif;
370/* Pop-up notes needs a relative position as a base where they pops up. */
372 background-color: PaleGoldenRod;
375.macro { color: DarkMagenta; }
383 border: 1px solid #b0b0b0;
385 box-shadow: 1px 1px 7px black;
386 background-color: #c0c0c0;
390.num { width:2.5em; padding-right:2ex; background-color:#eeeeee }
391.num { text-align:right; font-size:8pt }
392.num { color:#444444 }
393.line { padding-left: 1ex; border-left: 3px solid #ccc }
394.line { white-space: pre }
395.msg { -webkit-box-shadow:1px 1px 7px #000 }
396.msg { box-shadow:1px 1px 7px #000 }
397.msg { -webkit-border-radius:5px }
398.msg { border-radius:5px }
399.msg { font-family:Helvetica, sans-serif; font-size:8pt }
401.msg { position:relative }
402.msg { padding:0.25em 1ex 0.25em 1ex }
403.msg { margin-top:10px; margin-bottom:10px }
404.msg { font-weight:bold }
405.msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap }
406.msgT { padding:0x; spacing:0x }
407.msgEvent { background-color:#fff8b4; color:#000000 }
408.msgControl { background-color:#bbbbbb; color:#000000 }
409.msgNote { background-color:#ddeeff; color:#000000 }
410.mrange { background-color:#dfddf3 }
411.mrange { border-bottom:1px solid #6F9DBE }
412.PathIndex { font-weight: bold; padding:0px 5px; margin-right:5px; }
413.PathIndex { -webkit-border-radius:8px }
414.PathIndex { border-radius:8px }
415.PathIndexEvent { background-color:#bfba87 }
416.PathIndexControl { background-color:#8c8c8c }
417.PathIndexPopUp { background-color: #879abc; }
418.PathNav a { text-decoration:none; font-size: larger }
419.CodeInsertionHint { font-weight: bold; background-color: #10dd10 }
420.CodeRemovalHint { background-color:#de1010 }
421.CodeRemovalHint { border-bottom:1px solid #6F9DBE }
422.msg.selected{ background-color:orange !important; }
428 border-collapse: collapse; border-spacing: 0px;
439input.spoilerhider + label {
441 text-decoration: underline;
447input.spoilerhider ~ .spoiler {
453input.spoilerhider:checked + label + .spoiler{
474 llvm::function_ref<
void(RewriteBuffer &,
unsigned,
unsigned,
const char *,
475 const char *,
const char *)>
476 HighlightRangeCallback) {
480 llvm::MemoryBufferRef FromFile =
SM.getBufferOrFake(FID);
481 const char *BufferStart = FromFile.getBuffer().data();
494 while (Tok.
isNot(tok::eof)) {
501 case tok::identifier:
502 llvm_unreachable(
"tok::identifier in raw lexing mode!");
503 case tok::raw_identifier: {
509 if (Tok.
isNot(tok::identifier))
510 HighlightRangeCallback(RB, TokOffs, TokOffs + TokLen, BufferStart,
511 "<span class='keyword'>",
"</span>");
515 HighlightRangeCallback(RB, TokOffs, TokOffs + TokLen, BufferStart,
516 "<span class='comment'>",
"</span>");
518 case tok::utf8_string_literal:
524 case tok::wide_string_literal:
525 case tok::utf16_string_literal:
526 case tok::utf32_string_literal:
531 case tok::string_literal:
533 HighlightRangeCallback(RB, TokOffs, TokOffs + TokLen, BufferStart,
534 "<span class='string_literal'>",
"</span>");
543 unsigned TokEnd = TokOffs+TokLen;
551 HighlightRangeCallback(RB, TokOffs, TokEnd, BufferStart,
552 "<span class='directive'>",
"</span>");
566 llvm::MemoryBufferRef FromFile =
SM.getBufferOrFake(FID);
567 const char *BufferStart = FromFile.getBuffer().data();
570 auto CacheIt =
Cache->SyntaxHighlights.find(FID);
571 if (CacheIt !=
Cache->SyntaxHighlights.end()) {
581 auto HighlightRangeCallback = [&](RewriteBuffer &RB,
unsigned B,
unsigned E,
582 const char *BufferStart,
583 const char *StartTag,
const char *EndTag) {
587 Cache->SyntaxHighlights[FID].push_back({B,
E, StartTag, EndTag});
596 const char *,
const char *,
bool)>
597 HighlightRangeCallback) {
601 std::vector<Token> TokenStream;
603 llvm::MemoryBufferRef FromFile =
SM.getBufferOrFake(FID);
610 L.LexFromRawLexer(Tok);
620 if (Tok.
is(tok::hashhash))
626 if (Tok.
is(tok::raw_identifier))
629 TokenStream.push_back(Tok);
631 if (Tok.
is(tok::eof))
break;
657 TmpPP.EnterTokenStream(TokenStream,
false,
false);
664 while (Tok.
isNot(tok::eof)) {
682 assert(
SM.getFileID(LLoc.
getEnd()) == FID &&
683 "Start and end of expansion must be in the same ultimate file!");
686 unsigned LineLen = Expansion.size();
696 while (!Tok.
is(tok::eof) &&
704 LineLen -= Expansion.size();
709 ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok))
714 LineLen += Expansion.size();
716 PrevPrevTok = PrevTok;
723 Expansion =
"<span class='macro_popup'>" + Expansion +
"</span></span>";
726 "<span class='macro'>", Expansion.c_str(),
742 auto CacheIt =
Cache->MacroHighlights.find(FID);
743 if (CacheIt !=
Cache->MacroHighlights.end()) {
755 const char *EndTag,
bool isTokenRange) {
759 Cache->MacroHighlights[FID].push_back(
760 {B,
E, StartTag, EndTag, isTokenRange});
static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo, unsigned B, unsigned E)
static void HighlightMacrosImpl(Rewriter &R, FileID FID, const Preprocessor &PP, llvm::function_ref< void(Rewriter &, SourceLocation, SourceLocation, const char *, const char *, bool)> HighlightRangeCallback)
static void SyntaxHighlightImpl(Rewriter &R, FileID FID, const Preprocessor &PP, llvm::function_ref< void(RewriteBuffer &, unsigned, unsigned, const char *, const char *, const char *)> HighlightRangeCallback)
SyntaxHighlight - Relex the specified FileID and annotate the HTML with information about keywords,...
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
Represents a character-granular source range.
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
SourceLocation getEnd() const
SourceLocation getBegin() const
Concrete class used by the front-end to report problems and issues.
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
const IntrusiveRefCntPtr< DiagnosticIDs > & getDiagnosticIDs() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
unsigned getHashValue() const
A diagnostic client that ignores all diagnostics.
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode.
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
Given a tok::raw_identifier token, look up the identifier information for the token and install it in...
void setDiagnostics(DiagnosticsEngine &D)
void Lex(Token &Result)
Lex the next token for this preprocessor.
SourceManager & getSourceManager() const
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
const LangOptions & getLangOpts() const
void setPragmasEnabled(bool Enabled)
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments)
Control whether the preprocessor retains comments in output.
bool getPragmasEnabled() const
DiagnosticsEngine & getDiagnostics() const
Rewriter - This is the main interface to the rewrite buffers.
bool InsertTextBefore(SourceLocation Loc, StringRef Str)
InsertText - Insert the specified string at the specified location in the original buffer.
SourceManager & getSourceMgr() const
const LangOptions & getLangOpts() const
bool InsertTextAfter(SourceLocation Loc, StringRef Str)
InsertTextAfter - Insert the specified string at the specified location in the original buffer.
llvm::RewriteBuffer & getEditBuffer(FileID FID)
getEditBuffer - This is like getRewriteBufferFor, but always returns a buffer, and allows you to writ...
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
TokenConcatenation class, which answers the question of "Is it safe to emit two tokens without a whit...
Token - This structure provides full information about a lexed token.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
void setKind(tok::TokenKind K)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
bool isNot(tok::TokenKind K) const
void AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID, StringRef title)
void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, const char *StartTag, const char *EndTag, bool IsTokenRange=true)
HighlightRange - Highlight a range in the source code with the specified start/end tags.
RelexRewriteCacheRef instantiateRelexRewriteCache()
If you need to rewrite the same file multiple times, you can instantiate a RelexRewriteCache and refe...
void AddLineNumbers(Rewriter &R, FileID FID)
void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP, RelexRewriteCacheRef Cache=nullptr)
SyntaxHighlight - Relex the specified FileID and annotate the HTML with information about keywords,...
void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP, RelexRewriteCacheRef Cache=nullptr)
HighlightMacros - This uses the macro table state from the end of the file, to reexpand macros and in...
void EscapeText(Rewriter &R, FileID FID, bool EscapeSpaces=false, bool ReplaceTabs=false)
EscapeText - HTMLize a specified file so that special characters are are translated so that they are ...
std::shared_ptr< RelexRewriteCache > RelexRewriteCacheRef
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
std::vector< RawHighlight > RawHighlightList
DenseMap< FileID, RawHighlightList > SyntaxHighlights
std::vector< Highlight > HighlightList
DenseMap< FileID, HighlightList > MacroHighlights