1249259Sdim//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This tablegen backend emits an index of definitions in ctags(1) format. 11249259Sdim// A helper script, utils/TableGen/tdtags, provides an easier-to-use 12249259Sdim// interface; run 'tdtags -H' for documentation. 13249259Sdim// 14249259Sdim//===----------------------------------------------------------------------===// 15249259Sdim 16249259Sdim#define DEBUG_TYPE "ctags-emitter" 17249259Sdim 18249259Sdim#include "llvm/Support/SourceMgr.h" 19249259Sdim#include "llvm/Support/MemoryBuffer.h" 20249259Sdim#include "llvm/TableGen/Error.h" 21249259Sdim#include "llvm/TableGen/Record.h" 22249259Sdim#include "llvm/TableGen/TableGenBackend.h" 23249259Sdim#include <algorithm> 24249259Sdim#include <string> 25249259Sdim#include <vector> 26249259Sdimusing namespace llvm; 27249259Sdim 28249259Sdimnamespace llvm { extern SourceMgr SrcMgr; } 29249259Sdim 30249259Sdimnamespace { 31249259Sdim 32249259Sdimclass Tag { 33249259Sdimprivate: 34249259Sdim const std::string *Id; 35249259Sdim SMLoc Loc; 36249259Sdimpublic: 37249259Sdim Tag(const std::string &Name, const SMLoc Location) 38249259Sdim : Id(&Name), Loc(Location) {} 39249259Sdim int operator<(const Tag &B) const { return *Id < *B.Id; } 40249259Sdim void emit(raw_ostream &OS) const { 41249259Sdim int BufferID = SrcMgr.FindBufferContainingLoc(Loc); 42249259Sdim MemoryBuffer *CurMB = SrcMgr.getBufferInfo(BufferID).Buffer; 43249259Sdim const char *BufferName = CurMB->getBufferIdentifier(); 44249259Sdim std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc); 45249259Sdim OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n"; 46249259Sdim } 47249259Sdim}; 48249259Sdim 49249259Sdimclass CTagsEmitter { 50249259Sdimprivate: 51249259Sdim RecordKeeper &Records; 52249259Sdimpublic: 53249259Sdim CTagsEmitter(RecordKeeper &R) : Records(R) {} 54249259Sdim 55249259Sdim void run(raw_ostream &OS); 56249259Sdim 57249259Sdimprivate: 58249259Sdim static SMLoc locate(const Record *R); 59249259Sdim}; 60249259Sdim 61249259Sdim} // End anonymous namespace. 62249259Sdim 63249259SdimSMLoc CTagsEmitter::locate(const Record *R) { 64249259Sdim ArrayRef<SMLoc> Locs = R->getLoc(); 65249259Sdim if (Locs.empty()) { 66249259Sdim SMLoc NullLoc; 67249259Sdim return NullLoc; 68249259Sdim } 69249259Sdim return Locs.front(); 70249259Sdim} 71249259Sdim 72249259Sdimvoid CTagsEmitter::run(raw_ostream &OS) { 73249259Sdim const std::map<std::string, Record *> &Classes = Records.getClasses(); 74249259Sdim const std::map<std::string, Record *> &Defs = Records.getDefs(); 75249259Sdim std::vector<Tag> Tags; 76249259Sdim // Collect tags. 77249259Sdim Tags.reserve(Classes.size() + Defs.size()); 78249259Sdim for (std::map<std::string, Record *>::const_iterator I = Classes.begin(), 79249259Sdim E = Classes.end(); 80249259Sdim I != E; ++I) 81249259Sdim Tags.push_back(Tag(I->first, locate(I->second))); 82249259Sdim for (std::map<std::string, Record *>::const_iterator I = Defs.begin(), 83249259Sdim E = Defs.end(); 84249259Sdim I != E; ++I) 85249259Sdim Tags.push_back(Tag(I->first, locate(I->second))); 86249259Sdim // Emit tags. 87249259Sdim std::sort(Tags.begin(), Tags.end()); 88249259Sdim OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; 89249259Sdim OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n"; 90249259Sdim for (std::vector<Tag>::const_iterator I = Tags.begin(), E = Tags.end(); 91249259Sdim I != E; ++I) 92249259Sdim I->emit(OS); 93249259Sdim} 94249259Sdim 95249259Sdimnamespace llvm { 96249259Sdim 97249259Sdimvoid EmitCTags(RecordKeeper &RK, raw_ostream &OS) { CTagsEmitter(RK).run(OS); } 98249259Sdim 99249259Sdim} // End llvm namespace. 100