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