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") << ", " 43263509Sdim << Tag.getValueAsBit("IsThrowsCommand") << ", " 44243791Sdim << Tag.getValueAsBit("IsDeprecatedCommand") << ", " 45252723Sdim << Tag.getValueAsBit("IsHeaderfileCommand") << ", " 46243791Sdim << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", " 47243791Sdim << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " 48243791Sdim << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " 49243791Sdim << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " 50243791Sdim << Tag.getValueAsBit("IsDeclarationCommand") << ", " 51252723Sdim << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", " 52252723Sdim << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", " 53252723Sdim << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", " 54243791Sdim << /* IsUnknownCommand = */ "0" 55243791Sdim << " }"; 56243791Sdim if (i + 1 != e) 57243791Sdim OS << ","; 58243791Sdim OS << "\n"; 59243791Sdim } 60243791Sdim OS << "};\n" 61243791Sdim "} // unnamed namespace\n\n"; 62243791Sdim 63243791Sdim std::vector<StringMatcher::StringPair> Matches; 64243791Sdim for (size_t i = 0, e = Tags.size(); i != e; ++i) { 65243791Sdim Record &Tag = *Tags[i]; 66243791Sdim std::string Name = Tag.getValueAsString("Name"); 67243791Sdim std::string Return; 68243791Sdim raw_string_ostream(Return) << "return &Commands[" << i << "];"; 69243791Sdim Matches.push_back(StringMatcher::StringPair(Name, Return)); 70243791Sdim } 71243791Sdim 72243791Sdim OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n" 73243791Sdim << " StringRef Name) {\n"; 74243791Sdim StringMatcher("Name", Matches, OS).Emit(); 75243791Sdim OS << " return NULL;\n" 76243791Sdim << "}\n\n"; 77243791Sdim} 78252723Sdim 79252723Sdimstatic std::string MangleName(StringRef Str) { 80252723Sdim std::string Mangled; 81252723Sdim for (unsigned i = 0, e = Str.size(); i != e; ++i) { 82252723Sdim switch (Str[i]) { 83252723Sdim default: 84252723Sdim Mangled += Str[i]; 85252723Sdim break; 86252723Sdim case '[': 87252723Sdim Mangled += "lsquare"; 88252723Sdim break; 89252723Sdim case ']': 90252723Sdim Mangled += "rsquare"; 91252723Sdim break; 92252723Sdim case '{': 93252723Sdim Mangled += "lbrace"; 94252723Sdim break; 95252723Sdim case '}': 96252723Sdim Mangled += "rbrace"; 97252723Sdim break; 98252723Sdim case '$': 99252723Sdim Mangled += "dollar"; 100252723Sdim break; 101252723Sdim case '/': 102252723Sdim Mangled += "slash"; 103252723Sdim break; 104252723Sdim } 105252723Sdim } 106252723Sdim return Mangled; 107252723Sdim} 108252723Sdim 109252723Sdimvoid EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) { 110252723Sdim emitSourceFileHeader("A list of commands useable in documentation " 111252723Sdim "comments", OS); 112252723Sdim 113252723Sdim OS << "#ifndef COMMENT_COMMAND\n" 114252723Sdim << "# define COMMENT_COMMAND(NAME)\n" 115252723Sdim << "#endif\n"; 116252723Sdim 117252723Sdim std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); 118252723Sdim for (size_t i = 0, e = Tags.size(); i != e; ++i) { 119252723Sdim Record &Tag = *Tags[i]; 120252723Sdim std::string MangledName = MangleName(Tag.getValueAsString("Name")); 121252723Sdim 122252723Sdim OS << "COMMENT_COMMAND(" << MangledName << ")\n"; 123252723Sdim } 124252723Sdim} 125243791Sdim} // end namespace clang 126243791Sdim 127