ClangCommentCommandInfoEmitter.cpp revision 252723
1243791Sdim//===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====// 2243791Sdim// 3243791Sdim// The LLVM Compiler Infrastructure 4243791Sdim// 5243791Sdim// This file is distributed under the University of Illinois Open Source 6243791Sdim// License. See LICENSE.TXT for details. 7243791Sdim// 8243791Sdim//===----------------------------------------------------------------------===// 9243791Sdim// 10252723Sdim// This tablegen backend emits command lists and efficient matchers for command 11243791Sdim// names that are used in documentation comments. 12243791Sdim// 13243791Sdim//===----------------------------------------------------------------------===// 14243791Sdim 15243791Sdim#include "llvm/TableGen/Record.h" 16243791Sdim#include "llvm/TableGen/StringMatcher.h" 17252723Sdim#include "llvm/TableGen/TableGenBackend.h" 18243791Sdim#include <vector> 19243791Sdim 20243791Sdimusing namespace llvm; 21243791Sdim 22243791Sdimnamespace clang { 23243791Sdimvoid EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) { 24252723Sdim emitSourceFileHeader("A list of commands useable in documentation " 25252723Sdim "comments", OS); 26243791Sdim 27243791Sdim OS << "namespace {\n" 28243791Sdim "const CommandInfo Commands[] = {\n"; 29243791Sdim std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); 30243791Sdim for (size_t i = 0, e = Tags.size(); i != e; ++i) { 31243791Sdim Record &Tag = *Tags[i]; 32243791Sdim OS << " { " 33243791Sdim << "\"" << Tag.getValueAsString("Name") << "\", " 34243791Sdim << "\"" << Tag.getValueAsString("EndCommandName") << "\", " 35243791Sdim << i << ", " 36243791Sdim << Tag.getValueAsInt("NumArgs") << ", " 37243791Sdim << Tag.getValueAsBit("IsInlineCommand") << ", " 38243791Sdim << Tag.getValueAsBit("IsBlockCommand") << ", " 39243791Sdim << Tag.getValueAsBit("IsBriefCommand") << ", " 40243791Sdim << Tag.getValueAsBit("IsReturnsCommand") << ", " 41243791Sdim << Tag.getValueAsBit("IsParamCommand") << ", " 42243791Sdim << Tag.getValueAsBit("IsTParamCommand") << ", " 43243791Sdim << Tag.getValueAsBit("IsDeprecatedCommand") << ", " 44252723Sdim << Tag.getValueAsBit("IsHeaderfileCommand") << ", " 45243791Sdim << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", " 46243791Sdim << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " 47243791Sdim << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " 48243791Sdim << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " 49243791Sdim << Tag.getValueAsBit("IsDeclarationCommand") << ", " 50252723Sdim << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", " 51252723Sdim << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", " 52252723Sdim << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", " 53243791Sdim << /* IsUnknownCommand = */ "0" 54243791Sdim << " }"; 55243791Sdim if (i + 1 != e) 56243791Sdim OS << ","; 57243791Sdim OS << "\n"; 58243791Sdim } 59243791Sdim OS << "};\n" 60243791Sdim "} // unnamed namespace\n\n"; 61243791Sdim 62243791Sdim std::vector<StringMatcher::StringPair> Matches; 63243791Sdim for (size_t i = 0, e = Tags.size(); i != e; ++i) { 64243791Sdim Record &Tag = *Tags[i]; 65243791Sdim std::string Name = Tag.getValueAsString("Name"); 66243791Sdim std::string Return; 67243791Sdim raw_string_ostream(Return) << "return &Commands[" << i << "];"; 68243791Sdim Matches.push_back(StringMatcher::StringPair(Name, Return)); 69243791Sdim } 70243791Sdim 71243791Sdim OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n" 72243791Sdim << " StringRef Name) {\n"; 73243791Sdim StringMatcher("Name", Matches, OS).Emit(); 74243791Sdim OS << " return NULL;\n" 75243791Sdim << "}\n\n"; 76243791Sdim} 77252723Sdim 78252723Sdimstatic std::string MangleName(StringRef Str) { 79252723Sdim std::string Mangled; 80252723Sdim for (unsigned i = 0, e = Str.size(); i != e; ++i) { 81252723Sdim switch (Str[i]) { 82252723Sdim default: 83252723Sdim Mangled += Str[i]; 84252723Sdim break; 85252723Sdim case '[': 86252723Sdim Mangled += "lsquare"; 87252723Sdim break; 88252723Sdim case ']': 89252723Sdim Mangled += "rsquare"; 90252723Sdim break; 91252723Sdim case '{': 92252723Sdim Mangled += "lbrace"; 93252723Sdim break; 94252723Sdim case '}': 95252723Sdim Mangled += "rbrace"; 96252723Sdim break; 97252723Sdim case '$': 98252723Sdim Mangled += "dollar"; 99252723Sdim break; 100252723Sdim case '/': 101252723Sdim Mangled += "slash"; 102252723Sdim break; 103252723Sdim } 104252723Sdim } 105252723Sdim return Mangled; 106252723Sdim} 107252723Sdim 108252723Sdimvoid EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) { 109252723Sdim emitSourceFileHeader("A list of commands useable in documentation " 110252723Sdim "comments", OS); 111252723Sdim 112252723Sdim OS << "#ifndef COMMENT_COMMAND\n" 113252723Sdim << "# define COMMENT_COMMAND(NAME)\n" 114252723Sdim << "#endif\n"; 115252723Sdim 116252723Sdim std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); 117252723Sdim for (size_t i = 0, e = Tags.size(); i != e; ++i) { 118252723Sdim Record &Tag = *Tags[i]; 119252723Sdim std::string MangledName = MangleName(Tag.getValueAsString("Name")); 120252723Sdim 121252723Sdim OS << "COMMENT_COMMAND(" << MangledName << ")\n"; 122252723Sdim } 123252723Sdim} 124243791Sdim} // end namespace clang 125243791Sdim 126