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
17namespace clang {
18namespace markup {
19typedef llvm::DenseMap<FileID, unsigned> FIDMap;
20
21inline 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
31inline 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
39inline raw_ostream &Indent(raw_ostream &o, const unsigned indent) {
40  for (unsigned i = 0; i < indent; ++i)
41    o << ' ';
42  return o;
43}
44
45inline 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
54inline raw_ostream &EmitInteger(raw_ostream &o, int64_t value) {
55  o << "<integer>";
56  o << value;
57  o << "</integer>";
58  return o;
59}
60
61inline 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 << "&amp;";
71      break;
72    case '<':
73      o << "&lt;";
74      break;
75    case '>':
76      o << "&gt;";
77      break;
78    case '\'':
79      o << "&apos;";
80      break;
81    case '\"':
82      o << "&quot;";
83      break;
84    }
85  }
86  o << "</string>";
87  return o;
88}
89
90inline 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
106inline 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