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// 10249423Sdim// 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" 17249423Sdim#include "llvm/TableGen/TableGenBackend.h" 18243791Sdim#include <vector> 19243791Sdim 20243791Sdimusing namespace llvm; 21243791Sdim 22243791Sdimnamespace clang { 23243791Sdimvoid EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) { 24249423Sdim emitSourceFileHeader("A list of commands useable in documentation " 25249423Sdim "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") << ", " 44249423Sdim << Tag.getValueAsBit("IsHeaderfileCommand") << ", " 45243791Sdim << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", " 46243791Sdim << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " 47243791Sdim << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " 48243791Sdim << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " 49243791Sdim << Tag.getValueAsBit("IsDeclarationCommand") << ", " 50249423Sdim << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", " 51249423Sdim << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", " 52249423Sdim << 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} 77249423Sdim 78249423Sdimstatic std::string MangleName(StringRef Str) { 79249423Sdim std::string Mangled; 80249423Sdim for (unsigned i = 0, e = Str.size(); i != e; ++i) { 81249423Sdim switch (Str[i]) { 82249423Sdim default: 83249423Sdim Mangled += Str[i]; 84249423Sdim break; 85249423Sdim case '[': 86249423Sdim Mangled += "lsquare"; 87249423Sdim break; 88249423Sdim case ']': 89249423Sdim Mangled += "rsquare"; 90249423Sdim break; 91249423Sdim case '{': 92249423Sdim Mangled += "lbrace"; 93249423Sdim break; 94249423Sdim case '}': 95249423Sdim Mangled += "rbrace"; 96249423Sdim break; 97249423Sdim case '$': 98249423Sdim Mangled += "dollar"; 99249423Sdim break; 100251662Sdim case '/': 101251662Sdim Mangled += "slash"; 102251662Sdim break; 103249423Sdim } 104249423Sdim } 105249423Sdim return Mangled; 106249423Sdim} 107249423Sdim 108249423Sdimvoid EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) { 109249423Sdim emitSourceFileHeader("A list of commands useable in documentation " 110249423Sdim "comments", OS); 111249423Sdim 112249423Sdim OS << "#ifndef COMMENT_COMMAND\n" 113249423Sdim << "# define COMMENT_COMMAND(NAME)\n" 114249423Sdim << "#endif\n"; 115249423Sdim 116249423Sdim std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); 117249423Sdim for (size_t i = 0, e = Tags.size(); i != e; ++i) { 118249423Sdim Record &Tag = *Tags[i]; 119249423Sdim std::string MangledName = MangleName(Tag.getValueAsString("Name")); 120249423Sdim 121249423Sdim OS << "COMMENT_COMMAND(" << MangledName << ")\n"; 122249423Sdim } 123249423Sdim} 124243791Sdim} // end namespace clang 125243791Sdim 126