1*f4a2713aSLionel Sambuc //===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====//
2*f4a2713aSLionel Sambuc //
3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4*f4a2713aSLionel Sambuc //
5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7*f4a2713aSLionel Sambuc //
8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9*f4a2713aSLionel Sambuc //
10*f4a2713aSLionel Sambuc // This tablegen backend emits command lists and efficient matchers for command
11*f4a2713aSLionel Sambuc // names that are used in documentation comments.
12*f4a2713aSLionel Sambuc //
13*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14*f4a2713aSLionel Sambuc
15*f4a2713aSLionel Sambuc #include "llvm/TableGen/Record.h"
16*f4a2713aSLionel Sambuc #include "llvm/TableGen/StringMatcher.h"
17*f4a2713aSLionel Sambuc #include "llvm/TableGen/TableGenBackend.h"
18*f4a2713aSLionel Sambuc #include <vector>
19*f4a2713aSLionel Sambuc
20*f4a2713aSLionel Sambuc using namespace llvm;
21*f4a2713aSLionel Sambuc
22*f4a2713aSLionel Sambuc namespace clang {
EmitClangCommentCommandInfo(RecordKeeper & Records,raw_ostream & OS)23*f4a2713aSLionel Sambuc void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
24*f4a2713aSLionel Sambuc emitSourceFileHeader("A list of commands useable in documentation "
25*f4a2713aSLionel Sambuc "comments", OS);
26*f4a2713aSLionel Sambuc
27*f4a2713aSLionel Sambuc OS << "namespace {\n"
28*f4a2713aSLionel Sambuc "const CommandInfo Commands[] = {\n";
29*f4a2713aSLionel Sambuc std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
30*f4a2713aSLionel Sambuc for (size_t i = 0, e = Tags.size(); i != e; ++i) {
31*f4a2713aSLionel Sambuc Record &Tag = *Tags[i];
32*f4a2713aSLionel Sambuc OS << " { "
33*f4a2713aSLionel Sambuc << "\"" << Tag.getValueAsString("Name") << "\", "
34*f4a2713aSLionel Sambuc << "\"" << Tag.getValueAsString("EndCommandName") << "\", "
35*f4a2713aSLionel Sambuc << i << ", "
36*f4a2713aSLionel Sambuc << Tag.getValueAsInt("NumArgs") << ", "
37*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsInlineCommand") << ", "
38*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsBlockCommand") << ", "
39*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsBriefCommand") << ", "
40*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsReturnsCommand") << ", "
41*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsParamCommand") << ", "
42*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsTParamCommand") << ", "
43*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsThrowsCommand") << ", "
44*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsDeprecatedCommand") << ", "
45*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsHeaderfileCommand") << ", "
46*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", "
47*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
48*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
49*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsVerbatimLineCommand") << ", "
50*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsDeclarationCommand") << ", "
51*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", "
52*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", "
53*f4a2713aSLionel Sambuc << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", "
54*f4a2713aSLionel Sambuc << /* IsUnknownCommand = */ "0"
55*f4a2713aSLionel Sambuc << " }";
56*f4a2713aSLionel Sambuc if (i + 1 != e)
57*f4a2713aSLionel Sambuc OS << ",";
58*f4a2713aSLionel Sambuc OS << "\n";
59*f4a2713aSLionel Sambuc }
60*f4a2713aSLionel Sambuc OS << "};\n"
61*f4a2713aSLionel Sambuc "} // unnamed namespace\n\n";
62*f4a2713aSLionel Sambuc
63*f4a2713aSLionel Sambuc std::vector<StringMatcher::StringPair> Matches;
64*f4a2713aSLionel Sambuc for (size_t i = 0, e = Tags.size(); i != e; ++i) {
65*f4a2713aSLionel Sambuc Record &Tag = *Tags[i];
66*f4a2713aSLionel Sambuc std::string Name = Tag.getValueAsString("Name");
67*f4a2713aSLionel Sambuc std::string Return;
68*f4a2713aSLionel Sambuc raw_string_ostream(Return) << "return &Commands[" << i << "];";
69*f4a2713aSLionel Sambuc Matches.push_back(StringMatcher::StringPair(Name, Return));
70*f4a2713aSLionel Sambuc }
71*f4a2713aSLionel Sambuc
72*f4a2713aSLionel Sambuc OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
73*f4a2713aSLionel Sambuc << " StringRef Name) {\n";
74*f4a2713aSLionel Sambuc StringMatcher("Name", Matches, OS).Emit();
75*f4a2713aSLionel Sambuc OS << " return NULL;\n"
76*f4a2713aSLionel Sambuc << "}\n\n";
77*f4a2713aSLionel Sambuc }
78*f4a2713aSLionel Sambuc
MangleName(StringRef Str)79*f4a2713aSLionel Sambuc static std::string MangleName(StringRef Str) {
80*f4a2713aSLionel Sambuc std::string Mangled;
81*f4a2713aSLionel Sambuc for (unsigned i = 0, e = Str.size(); i != e; ++i) {
82*f4a2713aSLionel Sambuc switch (Str[i]) {
83*f4a2713aSLionel Sambuc default:
84*f4a2713aSLionel Sambuc Mangled += Str[i];
85*f4a2713aSLionel Sambuc break;
86*f4a2713aSLionel Sambuc case '[':
87*f4a2713aSLionel Sambuc Mangled += "lsquare";
88*f4a2713aSLionel Sambuc break;
89*f4a2713aSLionel Sambuc case ']':
90*f4a2713aSLionel Sambuc Mangled += "rsquare";
91*f4a2713aSLionel Sambuc break;
92*f4a2713aSLionel Sambuc case '{':
93*f4a2713aSLionel Sambuc Mangled += "lbrace";
94*f4a2713aSLionel Sambuc break;
95*f4a2713aSLionel Sambuc case '}':
96*f4a2713aSLionel Sambuc Mangled += "rbrace";
97*f4a2713aSLionel Sambuc break;
98*f4a2713aSLionel Sambuc case '$':
99*f4a2713aSLionel Sambuc Mangled += "dollar";
100*f4a2713aSLionel Sambuc break;
101*f4a2713aSLionel Sambuc case '/':
102*f4a2713aSLionel Sambuc Mangled += "slash";
103*f4a2713aSLionel Sambuc break;
104*f4a2713aSLionel Sambuc }
105*f4a2713aSLionel Sambuc }
106*f4a2713aSLionel Sambuc return Mangled;
107*f4a2713aSLionel Sambuc }
108*f4a2713aSLionel Sambuc
EmitClangCommentCommandList(RecordKeeper & Records,raw_ostream & OS)109*f4a2713aSLionel Sambuc void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
110*f4a2713aSLionel Sambuc emitSourceFileHeader("A list of commands useable in documentation "
111*f4a2713aSLionel Sambuc "comments", OS);
112*f4a2713aSLionel Sambuc
113*f4a2713aSLionel Sambuc OS << "#ifndef COMMENT_COMMAND\n"
114*f4a2713aSLionel Sambuc << "# define COMMENT_COMMAND(NAME)\n"
115*f4a2713aSLionel Sambuc << "#endif\n";
116*f4a2713aSLionel Sambuc
117*f4a2713aSLionel Sambuc std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
118*f4a2713aSLionel Sambuc for (size_t i = 0, e = Tags.size(); i != e; ++i) {
119*f4a2713aSLionel Sambuc Record &Tag = *Tags[i];
120*f4a2713aSLionel Sambuc std::string MangledName = MangleName(Tag.getValueAsString("Name"));
121*f4a2713aSLionel Sambuc
122*f4a2713aSLionel Sambuc OS << "COMMENT_COMMAND(" << MangledName << ")\n";
123*f4a2713aSLionel Sambuc }
124*f4a2713aSLionel Sambuc }
125*f4a2713aSLionel Sambuc } // end namespace clang
126*f4a2713aSLionel Sambuc
127