 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
81.6% |
71 / 87 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
95.4% |
83 / 87 |
| |
|
Line Coverage: |
89.9% |
152 / 169 |
| |
 |
|
 |
1 : //===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
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 : // This file implements the XML document class, which provides the means to
11 : // dump out the AST in a XML form that exposes type details and other fields.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "clang/Frontend/DocumentXML.h"
16 : #include "clang/AST/Decl.h"
17 : #include "clang/AST/ASTContext.h"
18 : #include "clang/Basic/SourceManager.h"
19 : #include "llvm/ADT/StringExtras.h"
20 :
21 : namespace clang {
22 :
23 : //---------------------------------------------------------
24 1: DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
25 : Out(out),
26 : Ctx(0),
27 1: HasCurrentNodeSubNodes(false) {
28 1: NodeStack.push(rootName);
29 1: Out << "<?xml version=\"1.0\"?>\n<" << rootName;
30 1: }
31 :
32 : //---------------------------------------------------------
33 497: DocumentXML& DocumentXML::addSubNode(const std::string& name) {
237: branch 0 taken
260: branch 1 taken
34 497: if (!HasCurrentNodeSubNodes)
35 237: Out << ">\n";
36 497: NodeStack.push(name);
37 497: HasCurrentNodeSubNodes = false;
38 497: Indent();
39 497: Out << "<" << NodeStack.top();
40 497: return *this;
41 : }
42 :
43 : //---------------------------------------------------------
44 733: void DocumentXML::Indent() {
8042: branch 1 taken
733: branch 2 taken
45 8775: for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
46 8042: Out << ' ';
47 733: }
48 :
49 : //---------------------------------------------------------
50 497: DocumentXML& DocumentXML::toParent() {
497: branch 1 taken
0: branch 2 not taken
51 497: assert(NodeStack.size() > 1 && "too much backtracking");
52 :
236: branch 0 taken
261: branch 1 taken
53 497: if (HasCurrentNodeSubNodes) {
54 236: Indent();
55 236: Out << "</" << NodeStack.top() << ">\n";
56 : } else
57 261: Out << "/>\n";
58 497: NodeStack.pop();
59 497: HasCurrentNodeSubNodes = true;
60 497: return *this;
61 : }
62 :
63 : //---------------------------------------------------------
64 : namespace {
65 :
66 : enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
67 :
68 227: unsigned getNewId(tIdType idType) {
69 : static unsigned int idCounts[ID_LAST] = { 0 };
70 227: return ++idCounts[idType];
71 : }
72 :
73 : //---------------------------------------------------------
74 1186: inline std::string getPrefixedId(unsigned uId, tIdType idType) {
75 : static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
76 : char buffer[20];
77 1186: char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
78 1186: *--BufPtr = idPrefix[idType];
79 1186: return BufPtr;
80 : }
81 :
82 : //---------------------------------------------------------
83 : template<class T, class V>
84 1184: bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) {
85 1184: typename T::iterator i = idMap.find(value);
86 1184: bool toAdd = i == idMap.end();
47: branch 0 taken
316: branch 1 taken
3: branch 2 taken
377: branch 3 taken
377: branch 4 taken
377: branch 5 taken
1: branch 6 taken
2: branch 7 taken
26: branch 8 taken
186: branch 9 taken
96: branch 10 taken
57: branch 11 taken
54: branch 12 taken
19: branch 13 taken
87 1184: if (toAdd)
88 227: idMap.insert(typename T::value_type(value, getNewId(idType)));
89 1184: return toAdd;
90 : }
91 :
92 : } // anon NS
93 :
94 :
95 : //---------------------------------------------------------
96 : std::string DocumentXML::escapeString(const char* pStr,
97 4: std::string::size_type len) {
98 4: std::string value;
99 4: value.reserve(len + 1);
100 : char buffer[16];
160: branch 0 taken
4: branch 1 taken
101 164: for (unsigned i = 0; i < len; ++i) {
158: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
1: branch 7 taken
1: branch 8 taken
0: branch 9 not taken
0: branch 10 not taken
102 160: switch (char C = pStr[i]) {
103 : default:
158: branch 1 taken
0: branch 2 not taken
104 158: if (isprint(C))
105 158: value += C;
106 : else {
107 0: sprintf(buffer, "\\%03o", C);
108 0: value += buffer;
109 : }
110 158: break;
111 :
112 0: case '\n': value += "\\n"; break;
113 0: case '\t': value += "\\t"; break;
114 0: case '\a': value += "\\a"; break;
115 0: case '\b': value += "\\b"; break;
116 0: case '\r': value += "\\r"; break;
117 :
118 0: case '&': value += "&"; break;
119 1: case '<': value += "<"; break;
120 1: case '>': value += ">"; break;
121 0: case '"': value += """; break;
122 0: case '\'': value += "'"; break;
123 :
124 : }
125 : }
126 : return value;
127 : }
128 :
129 : //---------------------------------------------------------
130 1: void DocumentXML::finalize() {
1: branch 1 taken
0: branch 2 not taken
131 1: assert(NodeStack.size() == 1 && "not completely backtracked");
132 :
133 1: addSubNode("ReferenceSection");
134 1: addSubNode("Types");
135 :
47: branch 4 taken
1: branch 5 taken
136 48: for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
137 : i != e; ++i) {
2: branch 2 taken
45: branch 3 taken
138 47: if (i->first.hasLocalQualifiers()) {
139 2: writeTypeToXML(i->first);
140 2: addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
141 2: toParent();
142 : }
143 : }
144 :
54: branch 4 taken
1: branch 5 taken
145 56: for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(),
146 1: e = BasicTypes.end(); i != e; ++i) {
147 54: writeTypeToXML(i->first);
148 54: addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
149 54: toParent();
150 : }
151 :
152 :
153 1: toParent().addSubNode("Contexts");
154 :
26: branch 4 taken
1: branch 5 taken
155 28: for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(),
156 1: e = Contexts.end(); i != e; ++i) {
157 26: addSubNode(i->first->getDeclKindName());
158 26: addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
25: branch 2 taken
1: branch 3 taken
159 26: if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first))
160 25: addAttribute("name", ND->getNameAsString());
8: branch 2 taken
18: branch 3 taken
161 26: if (const TagDecl *TD = dyn_cast<TagDecl>(i->first))
162 8: addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL));
17: branch 2 taken
1: branch 3 taken
163 18: else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first))
164 17: addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAs<FunctionType>()], ID_NORMAL));
165 :
25: branch 2 taken
1: branch 3 taken
166 26: if (const DeclContext* parent = i->first->getParent())
167 25: addAttribute("context", parent);
168 26: toParent();
169 : }
170 :
171 1: toParent().addSubNode("Files");
172 :
3: branch 3 taken
1: branch 4 taken
173 5: for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(),
174 1: e = SourceFiles.end(); i != e; ++i) {
175 3: addSubNode("File");
176 3: addAttribute("id", getPrefixedId(i->second, ID_FILE));
177 3: addAttribute("name", escapeString(i->first.c_str(), i->first.size()));
178 3: toParent();
179 : }
180 :
181 1: toParent().toParent();
182 :
183 : // write the root closing node (which has always subnodes)
184 1: Out << "</" << NodeStack.top() << ">\n";
185 1: }
186 :
187 : //---------------------------------------------------------
188 : void DocumentXML::addAttribute(const char* pAttributeName,
189 327: const QualType& pType) {
190 327: addTypeRecursively(pType);
191 327: addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
192 327: }
193 :
194 : //---------------------------------------------------------
195 : void DocumentXML::addPtrAttribute(const char* pAttributeName,
196 26: const Type* pType) {
197 26: addTypeRecursively(pType);
198 26: addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
199 26: }
200 :
201 : //---------------------------------------------------------
202 363: void DocumentXML::addTypeRecursively(const QualType& pType)
203 : {
47: branch 1 taken
316: branch 2 taken
204 363: if (addToMap(Types, pType))
205 : {
206 47: addTypeRecursively(pType.getTypePtr());
207 : // beautifier: a non-qualified type shall be transparent
45: branch 1 taken
2: branch 2 taken
208 47: if (!pType.hasLocalQualifiers())
209 : {
210 45: Types[pType] = BasicTypes[pType.getTypePtr()];
211 : }
212 : }
213 363: }
214 :
215 : //---------------------------------------------------------
216 73: void DocumentXML::addTypeRecursively(const Type* pType)
217 : {
54: branch 1 taken
19: branch 2 taken
218 73: if (addToMap(BasicTypes, pType))
219 : {
220 54: addParentTypes(pType);
221 : /*
222 : // FIXME: doesn't work in the immediate streaming approach
223 : if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
224 : {
225 : addSubNode("VariableArraySizeExpression");
226 : PrintStmt(VAT->getSizeExpr());
227 : toParent();
228 : }
229 : */
230 : }
231 73: }
232 :
233 : //---------------------------------------------------------
234 157: void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
235 : {
236 157: addContextsRecursively(DC);
237 157: addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
238 157: }
239 :
240 : //---------------------------------------------------------
241 183: void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
242 : {
30: branch 1 taken
153: branch 2 taken
243 183: if (const DeclContext* DC = dyn_cast<DeclContext>(D))
244 : {
245 30: addContextsRecursively(DC);
246 30: addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
247 : }
248 : else
249 : {
250 153: addToMap(Decls, D);
251 153: addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
252 : }
253 183: }
254 :
255 : //---------------------------------------------------------
256 0: void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
257 : {
0: branch 0 not taken
0: branch 1 not taken
258 0: addPtrAttribute(pName, static_cast<const DeclContext*>(D));
259 0: }
260 :
261 : //---------------------------------------------------------
262 213: void DocumentXML::addContextsRecursively(const DeclContext *DC)
263 : {
212: branch 0 taken
1: branch 1 taken
26: branch 3 taken
186: branch 4 taken
26: branch 5 taken
187: branch 6 taken
264 213: if (DC != 0 && addToMap(Contexts, DC))
265 : {
266 26: addContextsRecursively(DC->getParent());
267 : }
268 213: }
269 :
270 : //---------------------------------------------------------
271 380: void DocumentXML::addSourceFileAttribute(const std::string& fileName)
272 : {
273 380: addToMap(SourceFiles, fileName, ID_FILE);
274 380: addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
275 380: }
276 :
277 :
278 : //---------------------------------------------------------
279 3: void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
280 : {
281 3: addToMap(Labels, L, ID_LABEL);
282 3: addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
283 3: }
284 :
285 :
286 : //---------------------------------------------------------
287 385: PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
288 : {
289 385: SourceManager& SM = Ctx->getSourceManager();
290 385: SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
291 385: PresumedLoc PLoc;
380: branch 1 taken
5: branch 2 taken
292 385: if (!SpellingLoc.isInvalid())
293 : {
294 380: PLoc = SM.getPresumedLoc(SpellingLoc);
295 380: addSourceFileAttribute(PLoc.getFilename());
296 380: addAttribute("line", PLoc.getLine());
297 380: addAttribute("col", PLoc.getColumn());
298 : }
299 : // else there is no error in some cases (eg. CXXThisExpr)
300 : return PLoc;
301 : }
302 :
303 : //---------------------------------------------------------
304 263: void DocumentXML::addLocationRange(const SourceRange& R)
305 : {
306 263: PresumedLoc PStartLoc = addLocation(R.getBegin());
148: branch 3 taken
115: branch 4 taken
307 263: if (R.getBegin() != R.getEnd())
308 : {
309 148: SourceManager& SM = Ctx->getSourceManager();
310 148: SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd());
147: branch 1 taken
1: branch 2 taken
311 148: if (!SpellingLoc.isInvalid())
312 : {
313 147: PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc);
147: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
147: branch 7 taken
0: branch 8 not taken
147: branch 9 taken
314 147: if (PStartLoc.isInvalid() ||
315 : strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) {
316 0: addToMap(SourceFiles, PLoc.getFilename(), ID_FILE);
317 0: addAttribute("endfile", PLoc.getFilename());
318 0: addAttribute("endline", PLoc.getLine());
319 0: addAttribute("endcol", PLoc.getColumn());
28: branch 2 taken
119: branch 3 taken
320 147: } else if (PLoc.getLine() != PStartLoc.getLine()) {
321 28: addAttribute("endline", PLoc.getLine());
322 28: addAttribute("endcol", PLoc.getColumn());
323 : } else {
324 119: addAttribute("endcol", PLoc.getColumn());
325 : }
326 : }
327 : }
328 263: }
329 :
330 : //---------------------------------------------------------
331 96: void DocumentXML::PrintDecl(Decl *D)
332 : {
333 96: writeDeclToXML(D);
334 96: }
335 :
336 : //---------------------------------------------------------
337 : } // NS clang
338 :
Generated: 2010-02-10 01:31 by zcov