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