1139f7f9bSDimitry Andric //===--- ClangCommentHTMLNamedCharacterReferenceEmitter.cpp -----------------=//
2139f7f9bSDimitry Andric //
3139f7f9bSDimitry Andric // The LLVM Compiler Infrastructure
4139f7f9bSDimitry Andric //
5139f7f9bSDimitry Andric // This file is distributed under the University of Illinois Open Source
6139f7f9bSDimitry Andric // License. See LICENSE.TXT for details.
7139f7f9bSDimitry Andric //
8139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
9139f7f9bSDimitry Andric //
10*b5893f02SDimitry Andric // This tablegen backend emits an efficient function to translate HTML named
11139f7f9bSDimitry Andric // character references to UTF-8 sequences.
12139f7f9bSDimitry Andric //
13139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
14139f7f9bSDimitry Andric
15139f7f9bSDimitry Andric #include "llvm/ADT/SmallString.h"
16139f7f9bSDimitry Andric #include "llvm/Support/ConvertUTF.h"
17139f7f9bSDimitry Andric #include "llvm/TableGen/Error.h"
18139f7f9bSDimitry Andric #include "llvm/TableGen/Record.h"
19139f7f9bSDimitry Andric #include "llvm/TableGen/StringMatcher.h"
20139f7f9bSDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
21139f7f9bSDimitry Andric #include <vector>
22139f7f9bSDimitry Andric
23139f7f9bSDimitry Andric using namespace llvm;
24139f7f9bSDimitry Andric
254ba319b5SDimitry Andric /// Convert a code point to the corresponding UTF-8 sequence represented
26139f7f9bSDimitry Andric /// as a C string literal.
27139f7f9bSDimitry Andric ///
28139f7f9bSDimitry Andric /// \returns true on success.
translateCodePointToUTF8(unsigned CodePoint,SmallVectorImpl<char> & CLiteral)29139f7f9bSDimitry Andric static bool translateCodePointToUTF8(unsigned CodePoint,
30139f7f9bSDimitry Andric SmallVectorImpl<char> &CLiteral) {
31139f7f9bSDimitry Andric char Translated[UNI_MAX_UTF8_BYTES_PER_CODE_POINT];
32139f7f9bSDimitry Andric char *TranslatedPtr = Translated;
33139f7f9bSDimitry Andric if (!ConvertCodePointToUTF8(CodePoint, TranslatedPtr))
34139f7f9bSDimitry Andric return false;
35139f7f9bSDimitry Andric
36139f7f9bSDimitry Andric StringRef UTF8(Translated, TranslatedPtr - Translated);
37139f7f9bSDimitry Andric
38139f7f9bSDimitry Andric raw_svector_ostream OS(CLiteral);
39139f7f9bSDimitry Andric OS << "\"";
40139f7f9bSDimitry Andric for (size_t i = 0, e = UTF8.size(); i != e; ++i) {
41139f7f9bSDimitry Andric OS << "\\x";
42139f7f9bSDimitry Andric OS.write_hex(static_cast<unsigned char>(UTF8[i]));
43139f7f9bSDimitry Andric }
44139f7f9bSDimitry Andric OS << "\"";
45139f7f9bSDimitry Andric
46139f7f9bSDimitry Andric return true;
47139f7f9bSDimitry Andric }
48139f7f9bSDimitry Andric
49139f7f9bSDimitry Andric namespace clang {
EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper & Records,raw_ostream & OS)50139f7f9bSDimitry Andric void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records,
51139f7f9bSDimitry Andric raw_ostream &OS) {
52139f7f9bSDimitry Andric std::vector<Record *> Tags = Records.getAllDerivedDefinitions("NCR");
53139f7f9bSDimitry Andric std::vector<StringMatcher::StringPair> NameToUTF8;
54139f7f9bSDimitry Andric SmallString<32> CLiteral;
55139f7f9bSDimitry Andric for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end();
56139f7f9bSDimitry Andric I != E; ++I) {
57139f7f9bSDimitry Andric Record &Tag = **I;
58139f7f9bSDimitry Andric std::string Spelling = Tag.getValueAsString("Spelling");
59139f7f9bSDimitry Andric uint64_t CodePoint = Tag.getValueAsInt("CodePoint");
60139f7f9bSDimitry Andric CLiteral.clear();
61139f7f9bSDimitry Andric CLiteral.append("return ");
62139f7f9bSDimitry Andric if (!translateCodePointToUTF8(CodePoint, CLiteral)) {
63139f7f9bSDimitry Andric SrcMgr.PrintMessage(Tag.getLoc().front(),
64139f7f9bSDimitry Andric SourceMgr::DK_Error,
65139f7f9bSDimitry Andric Twine("invalid code point"));
66139f7f9bSDimitry Andric continue;
67139f7f9bSDimitry Andric }
68139f7f9bSDimitry Andric CLiteral.append(";");
69139f7f9bSDimitry Andric
70139f7f9bSDimitry Andric StringMatcher::StringPair Match(Spelling, CLiteral.str());
71139f7f9bSDimitry Andric NameToUTF8.push_back(Match);
72139f7f9bSDimitry Andric }
73139f7f9bSDimitry Andric
74139f7f9bSDimitry Andric emitSourceFileHeader("HTML named character reference to UTF-8 "
75139f7f9bSDimitry Andric "translation", OS);
76139f7f9bSDimitry Andric
77139f7f9bSDimitry Andric OS << "StringRef translateHTMLNamedCharacterReferenceToUTF8(\n"
78139f7f9bSDimitry Andric " StringRef Name) {\n";
79139f7f9bSDimitry Andric StringMatcher("Name", NameToUTF8, OS).Emit();
80139f7f9bSDimitry Andric OS << " return StringRef();\n"
81139f7f9bSDimitry Andric << "}\n\n";
82139f7f9bSDimitry Andric }
83139f7f9bSDimitry Andric
84139f7f9bSDimitry Andric } // end namespace clang
85139f7f9bSDimitry Andric
86