clang API Documentation
00001 //===---------- PlistSupport.h - Plist Output Utilities ---------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_CLANG_BASIC_PLISTSUPPORT_H 00011 #define LLVM_CLANG_BASIC_PLISTSUPPORT_H 00012 00013 #include "clang/Basic/FileManager.h" 00014 #include "clang/Basic/SourceManager.h" 00015 #include "clang/Lex/Lexer.h" 00016 #include "llvm/Support/raw_ostream.h" 00017 00018 namespace clang { 00019 namespace markup { 00020 typedef llvm::DenseMap<FileID, unsigned> FIDMap; 00021 00022 inline void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V, 00023 const SourceManager &SM, SourceLocation L) { 00024 FileID FID = SM.getFileID(SM.getExpansionLoc(L)); 00025 FIDMap::iterator I = FIDs.find(FID); 00026 if (I != FIDs.end()) 00027 return; 00028 FIDs[FID] = V.size(); 00029 V.push_back(FID); 00030 } 00031 00032 inline unsigned GetFID(const FIDMap &FIDs, const SourceManager &SM, 00033 SourceLocation L) { 00034 FileID FID = SM.getFileID(SM.getExpansionLoc(L)); 00035 FIDMap::const_iterator I = FIDs.find(FID); 00036 assert(I != FIDs.end()); 00037 return I->second; 00038 } 00039 00040 inline raw_ostream &Indent(raw_ostream &o, const unsigned indent) { 00041 for (unsigned i = 0; i < indent; ++i) 00042 o << ' '; 00043 return o; 00044 } 00045 00046 inline raw_ostream &EmitPlistHeader(raw_ostream &o) { 00047 static const char *PlistHeader = 00048 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 00049 "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " 00050 "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" 00051 "<plist version=\"1.0\">\n"; 00052 return o << PlistHeader; 00053 } 00054 00055 inline raw_ostream &EmitInteger(raw_ostream &o, int64_t value) { 00056 o << "<integer>"; 00057 o << value; 00058 o << "</integer>"; 00059 return o; 00060 } 00061 00062 inline raw_ostream &EmitString(raw_ostream &o, StringRef s) { 00063 o << "<string>"; 00064 for (StringRef::const_iterator I = s.begin(), E = s.end(); I != E; ++I) { 00065 char c = *I; 00066 switch (c) { 00067 default: 00068 o << c; 00069 break; 00070 case '&': 00071 o << "&"; 00072 break; 00073 case '<': 00074 o << "<"; 00075 break; 00076 case '>': 00077 o << ">"; 00078 break; 00079 case '\'': 00080 o << "'"; 00081 break; 00082 case '\"': 00083 o << """; 00084 break; 00085 } 00086 } 00087 o << "</string>"; 00088 return o; 00089 } 00090 00091 inline void EmitLocation(raw_ostream &o, const SourceManager &SM, 00092 const LangOptions &LangOpts, SourceLocation L, 00093 const FIDMap &FM, unsigned indent, 00094 bool extend = false) { 00095 FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager &>(SM)); 00096 00097 // Add in the length of the token, so that we cover multi-char tokens. 00098 unsigned offset = 00099 extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0; 00100 00101 Indent(o, indent) << "<dict>\n"; 00102 Indent(o, indent) << " <key>line</key>"; 00103 EmitInteger(o, Loc.getExpansionLineNumber()) << '\n'; 00104 Indent(o, indent) << " <key>col</key>"; 00105 EmitInteger(o, Loc.getExpansionColumnNumber() + offset) << '\n'; 00106 Indent(o, indent) << " <key>file</key>"; 00107 EmitInteger(o, GetFID(FM, SM, Loc)) << '\n'; 00108 Indent(o, indent) << "</dict>\n"; 00109 } 00110 00111 inline void EmitRange(raw_ostream &o, const SourceManager &SM, 00112 const LangOptions &LangOpts, CharSourceRange R, 00113 const FIDMap &FM, unsigned indent) { 00114 Indent(o, indent) << "<array>\n"; 00115 EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent + 1); 00116 EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent + 1, R.isTokenRange()); 00117 Indent(o, indent) << "</array>\n"; 00118 } 00119 } 00120 } 00121 00122 #endif