1 //===---------- PlistSupport.h - Plist Output Utilities ---------*- C++ -*-===// 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 #ifndef LLVM_CLANG_BASIC_PLISTSUPPORT_H 11 #define LLVM_CLANG_BASIC_PLISTSUPPORT_H 12 13 #include "clang/Basic/FileManager.h" 14 #include "clang/Basic/SourceManager.h" 15 #include "llvm/Support/raw_ostream.h" 16 17 namespace clang { 18 namespace markup { 19 typedef llvm::DenseMap<FileID, unsigned> FIDMap; 20 21 inline void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V, 22 const SourceManager &SM, SourceLocation L) { 23 FileID FID = SM.getFileID(SM.getExpansionLoc(L)); 24 FIDMap::iterator I = FIDs.find(FID); 25 if (I != FIDs.end()) 26 return; 27 FIDs[FID] = V.size(); 28 V.push_back(FID); 29 } 30 31 inline unsigned GetFID(const FIDMap &FIDs, const SourceManager &SM, 32 SourceLocation L) { 33 FileID FID = SM.getFileID(SM.getExpansionLoc(L)); 34 FIDMap::const_iterator I = FIDs.find(FID); 35 assert(I != FIDs.end()); 36 return I->second; 37 } 38 39 inline raw_ostream &Indent(raw_ostream &o, const unsigned indent) { 40 for (unsigned i = 0; i < indent; ++i) 41 o << ' '; 42 return o; 43 } 44 45 inline raw_ostream &EmitPlistHeader(raw_ostream &o) { 46 static const char *PlistHeader = 47 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 48 "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " 49 "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" 50 "<plist version=\"1.0\">\n"; 51 return o << PlistHeader; 52 } 53 54 inline raw_ostream &EmitInteger(raw_ostream &o, int64_t value) { 55 o << "<integer>"; 56 o << value; 57 o << "</integer>"; 58 return o; 59 } 60 61 inline raw_ostream &EmitString(raw_ostream &o, StringRef s) { 62 o << "<string>"; 63 for (StringRef::const_iterator I = s.begin(), E = s.end(); I != E; ++I) { 64 char c = *I; 65 switch (c) { 66 default: 67 o << c; 68 break; 69 case '&': 70 o << "&"; 71 break; 72 case '<': 73 o << "<"; 74 break; 75 case '>': 76 o << ">"; 77 break; 78 case '\'': 79 o << "'"; 80 break; 81 case '\"': 82 o << """; 83 break; 84 } 85 } 86 o << "</string>"; 87 return o; 88 } 89 90 inline void EmitLocation(raw_ostream &o, const SourceManager &SM, 91 SourceLocation L, const FIDMap &FM, unsigned indent) { 92 if (L.isInvalid()) return; 93 94 FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager &>(SM)); 95 96 Indent(o, indent) << "<dict>\n"; 97 Indent(o, indent) << " <key>line</key>"; 98 EmitInteger(o, Loc.getExpansionLineNumber()) << '\n'; 99 Indent(o, indent) << " <key>col</key>"; 100 EmitInteger(o, Loc.getExpansionColumnNumber()) << '\n'; 101 Indent(o, indent) << " <key>file</key>"; 102 EmitInteger(o, GetFID(FM, SM, Loc)) << '\n'; 103 Indent(o, indent) << "</dict>\n"; 104 } 105 106 inline void EmitRange(raw_ostream &o, const SourceManager &SM, 107 CharSourceRange R, const FIDMap &FM, unsigned indent) { 108 if (R.isInvalid()) return; 109 110 assert(R.isCharRange() && "cannot handle a token range"); 111 Indent(o, indent) << "<array>\n"; 112 EmitLocation(o, SM, R.getBegin(), FM, indent + 1); 113 EmitLocation(o, SM, R.getEnd(), FM, indent + 1); 114 Indent(o, indent) << "</array>\n"; 115 } 116 } 117 } 118 119 #endif 120