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