1 //===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This tablegen backend emits an index of definitions in ctags(1) format. 11 // A helper script, utils/TableGen/tdtags, provides an easier-to-use 12 // interface; run 'tdtags -H' for documentation. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/Support/SourceMgr.h" 17 #include "llvm/Support/MemoryBuffer.h" 18 #include "llvm/TableGen/Error.h" 19 #include "llvm/TableGen/Record.h" 20 #include <algorithm> 21 #include <string> 22 #include <vector> 23 using namespace llvm; 24 25 #define DEBUG_TYPE "ctags-emitter" 26 27 namespace { 28 29 class Tag { 30 private: 31 const std::string *Id; 32 SMLoc Loc; 33 public: 34 Tag(const std::string &Name, const SMLoc Location) 35 : Id(&Name), Loc(Location) {} 36 int operator<(const Tag &B) const { return *Id < *B.Id; } 37 void emit(raw_ostream &OS) const { 38 const MemoryBuffer *CurMB = 39 SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc)); 40 const char *BufferName = CurMB->getBufferIdentifier(); 41 std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc); 42 OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n"; 43 } 44 }; 45 46 class CTagsEmitter { 47 private: 48 RecordKeeper &Records; 49 public: 50 CTagsEmitter(RecordKeeper &R) : Records(R) {} 51 52 void run(raw_ostream &OS); 53 54 private: 55 static SMLoc locate(const Record *R); 56 }; 57 58 } // End anonymous namespace. 59 60 SMLoc CTagsEmitter::locate(const Record *R) { 61 ArrayRef<SMLoc> Locs = R->getLoc(); 62 return !Locs.empty() ? Locs.front() : SMLoc(); 63 } 64 65 void CTagsEmitter::run(raw_ostream &OS) { 66 const auto &Classes = Records.getClasses(); 67 const auto &Defs = Records.getDefs(); 68 std::vector<Tag> Tags; 69 // Collect tags. 70 Tags.reserve(Classes.size() + Defs.size()); 71 for (const auto &C : Classes) 72 Tags.push_back(Tag(C.first, locate(C.second.get()))); 73 for (const auto &D : Defs) 74 Tags.push_back(Tag(D.first, locate(D.second.get()))); 75 // Emit tags. 76 std::sort(Tags.begin(), Tags.end()); 77 OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; 78 OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n"; 79 for (const Tag &T : Tags) 80 T.emit(OS); 81 } 82 83 namespace llvm { 84 85 void EmitCTags(RecordKeeper &RK, raw_ostream &OS) { CTagsEmitter(RK).run(OS); } 86 87 } // End llvm namespace. 88