Root/
Source at commit 1322 created 12 years 7 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | /******************************************************************************␊ |
2 | *␊ |
3 | * $Id: tagreader.cpp,v 1.2 2001/03/19 19:27:41 root Exp $␊ |
4 | *␊ |
5 | *␊ |
6 | * Copyright (C) 1997-2011 by Dimitri van Heesch.␊ |
7 | *␊ |
8 | * Permission to use, copy, modify, and distribute this software and its␊ |
9 | * documentation under the terms of the GNU General Public License is hereby ␊ |
10 | * granted. No representations are made about the suitability of this software ␊ |
11 | * for any purpose. It is provided "as is" without express or implied warranty.␊ |
12 | * See the GNU General Public License for more details.␊ |
13 | *␊ |
14 | * Documents produced by Doxygen are derivative works derived from the␊ |
15 | * input used in their production; they are not affected by this license.␊ |
16 | *␊ |
17 | */␊ |
18 | ␊ |
19 | #include "tagreader.h"␊ |
20 | ␊ |
21 | #include <stdio.h>␊ |
22 | #include <stdarg.h>␊ |
23 | ␊ |
24 | #include <qxml.h>␊ |
25 | #include <qstack.h>␊ |
26 | #include <qdict.h>␊ |
27 | #include <qfileinfo.h>␊ |
28 | #include <qlist.h>␊ |
29 | #include <qstring.h>␊ |
30 | #include <qstringlist.h>␊ |
31 | ␊ |
32 | #include "entry.h"␊ |
33 | #include "classdef.h"␊ |
34 | #include "doxygen.h"␊ |
35 | #include "util.h"␊ |
36 | #include "message.h"␊ |
37 | #include "defargs.h"␊ |
38 | //#include "reflist.h"␊ |
39 | ␊ |
40 | /*! Information about an linkable anchor */␊ |
41 | class TagAnchorInfo␊ |
42 | {␊ |
43 | public:␊ |
44 | TagAnchorInfo(const QString &f,const QString &l) : label(l), fileName(f) {}␊ |
45 | QString label;␊ |
46 | QString fileName;␊ |
47 | };␊ |
48 | ␊ |
49 | class TagAnchorInfoList : public QList<TagAnchorInfo>␊ |
50 | {␊ |
51 | public: ␊ |
52 | TagAnchorInfoList() : QList<TagAnchorInfo>() { setAutoDelete(TRUE); }␊ |
53 | virtual ~TagAnchorInfoList() {}␊ |
54 | };␊ |
55 | ␊ |
56 | /*! Container for member specific info that can be read from a tagfile */␊ |
57 | class TagMemberInfo␊ |
58 | {␊ |
59 | public:␊ |
60 | TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) {}␊ |
61 | QString type;␊ |
62 | QString name;␊ |
63 | QString anchorFile;␊ |
64 | QString anchor;␊ |
65 | QString arglist;␊ |
66 | QString kind;␊ |
67 | TagAnchorInfoList docAnchors;␊ |
68 | Protection prot;␊ |
69 | Specifier virt;␊ |
70 | bool isStatic; ␊ |
71 | };␊ |
72 | ␊ |
73 | /*! Container for class specific info that can be read from a tagfile */␊ |
74 | class TagClassInfo␊ |
75 | {␊ |
76 | public:␊ |
77 | enum Kind { Class, Struct, Union, Interface, Exception, Protocol, Category };␊ |
78 | TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; }␊ |
79 | ~TagClassInfo() { delete bases; delete templateArguments; }␊ |
80 | QString name;␊ |
81 | QString filename;␊ |
82 | TagAnchorInfoList docAnchors;␊ |
83 | QList<BaseInfo> *bases;␊ |
84 | QList<TagMemberInfo> members;␊ |
85 | QList<QString> *templateArguments;␊ |
86 | QStringList classList;␊ |
87 | Kind kind;␊ |
88 | bool isObjC;␊ |
89 | };␊ |
90 | ␊ |
91 | /*! Container for namespace specific info that can be read from a tagfile */␊ |
92 | class TagNamespaceInfo␊ |
93 | {␊ |
94 | public:␊ |
95 | TagNamespaceInfo() { members.setAutoDelete(TRUE); }␊ |
96 | QString name;␊ |
97 | QString filename;␊ |
98 | QStringList classList;␊ |
99 | QStringList namespaceList;␊ |
100 | TagAnchorInfoList docAnchors;␊ |
101 | QList<TagMemberInfo> members;␊ |
102 | };␊ |
103 | ␊ |
104 | /*! Container for package specific info that can be read from a tagfile */␊ |
105 | class TagPackageInfo␊ |
106 | {␊ |
107 | public:␊ |
108 | TagPackageInfo() { members.setAutoDelete(TRUE); }␊ |
109 | QString name;␊ |
110 | QString filename;␊ |
111 | TagAnchorInfoList docAnchors;␊ |
112 | QList<TagMemberInfo> members;␊ |
113 | QStringList classList;␊ |
114 | };␊ |
115 | ␊ |
116 | class TagIncludeInfo␊ |
117 | {␊ |
118 | public:␊ |
119 | QString id;␊ |
120 | QString name;␊ |
121 | QString text;␊ |
122 | bool isLocal;␊ |
123 | bool isImported;␊ |
124 | };␊ |
125 | ␊ |
126 | /*! Container for file specific info that can be read from a tagfile */␊ |
127 | class TagFileInfo␊ |
128 | {␊ |
129 | public:␊ |
130 | TagFileInfo() { members.setAutoDelete(TRUE); includes.setAutoDelete(TRUE); }␊ |
131 | QString name;␊ |
132 | QString path;␊ |
133 | QString filename;␊ |
134 | TagAnchorInfoList docAnchors;␊ |
135 | QList<TagMemberInfo> members;␊ |
136 | QStringList classList;␊ |
137 | QStringList namespaceList;␊ |
138 | QList<TagIncludeInfo> includes;␊ |
139 | };␊ |
140 | ␊ |
141 | /*! Container for group specific info that can be read from a tagfile */␊ |
142 | class TagGroupInfo␊ |
143 | {␊ |
144 | public:␊ |
145 | TagGroupInfo() { members.setAutoDelete(TRUE); }␊ |
146 | QString name;␊ |
147 | QString title;␊ |
148 | QString filename;␊ |
149 | TagAnchorInfoList docAnchors;␊ |
150 | QList<TagMemberInfo> members;␊ |
151 | QStringList subgroupList;␊ |
152 | QStringList classList;␊ |
153 | QStringList namespaceList;␊ |
154 | QStringList fileList;␊ |
155 | QStringList pageList;␊ |
156 | QStringList dirList;␊ |
157 | };␊ |
158 | ␊ |
159 | /*! Container for page specific info that can be read from a tagfile */␊ |
160 | class TagPageInfo␊ |
161 | {␊ |
162 | public:␊ |
163 | QString name;␊ |
164 | QString title;␊ |
165 | QString filename;␊ |
166 | TagAnchorInfoList docAnchors;␊ |
167 | };␊ |
168 | ␊ |
169 | /*! Container for directory specific info that can be read from a tagfile */␊ |
170 | class TagDirInfo␊ |
171 | {␊ |
172 | public:␊ |
173 | QString name;␊ |
174 | QString filename;␊ |
175 | QString path;␊ |
176 | QStringList subdirList;␊ |
177 | QStringList fileList;␊ |
178 | TagAnchorInfoList docAnchors;␊ |
179 | };␊ |
180 | ␊ |
181 | /*! Tag file parser. ␊ |
182 | * Reads an XML-structured tagfile and builds up the structure in␊ |
183 | * memory. The method buildLists() is used to transfer/translate ␊ |
184 | * the structures to the doxygen engine.␊ |
185 | */␊ |
186 | class TagFileParser : public QXmlDefaultHandler␊ |
187 | {␊ |
188 | enum State { Invalid,␊ |
189 | InClass,␊ |
190 | InFile,␊ |
191 | InNamespace,␊ |
192 | InGroup,␊ |
193 | InPage,␊ |
194 | InMember,␊ |
195 | InPackage,␊ |
196 | InDir,␊ |
197 | InTempArgList␊ |
198 | };␊ |
199 | class StartElementHandler␊ |
200 | {␊ |
201 | typedef void (TagFileParser::*Handler)(const QXmlAttributes &attrib); ␊ |
202 | public:␊ |
203 | StartElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}␊ |
204 | void operator()(const QXmlAttributes &attrib) { (m_parent->*m_handler)(attrib); }␊ |
205 | private:␊ |
206 | TagFileParser *m_parent;␊ |
207 | Handler m_handler;␊ |
208 | };␊ |
209 | ␊ |
210 | class EndElementHandler␊ |
211 | {␊ |
212 | typedef void (TagFileParser::*Handler)(); ␊ |
213 | public:␊ |
214 | EndElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}␊ |
215 | void operator()() { (m_parent->*m_handler)(); }␊ |
216 | private:␊ |
217 | TagFileParser *m_parent;␊ |
218 | Handler m_handler;␊ |
219 | };␊ |
220 | ␊ |
221 | public:␊ |
222 | TagFileParser(const char *tagName) : m_startElementHandlers(17),␊ |
223 | m_endElementHandlers(17),␊ |
224 | m_tagName(tagName)␊ |
225 | {␊ |
226 | m_startElementHandlers.setAutoDelete(TRUE);␊ |
227 | m_endElementHandlers.setAutoDelete(TRUE);␊ |
228 | }␊ |
229 | ␊ |
230 | void setDocumentLocator ( QXmlLocator * locator )␊ |
231 | {␊ |
232 | m_locator = locator;␊ |
233 | }␊ |
234 | ␊ |
235 | void setFileName( const QString &fileName )␊ |
236 | {␊ |
237 | m_inputFileName = fileName;␊ |
238 | }␊ |
239 | ␊ |
240 | void warn(const char *fmt)␊ |
241 | {␊ |
242 | ::warn(m_inputFileName,m_locator->lineNumber(),fmt);␊ |
243 | }␊ |
244 | void warn(const char *fmt,const char *s)␊ |
245 | {␊ |
246 | ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s);␊ |
247 | }␊ |
248 | ␊ |
249 | void startCompound( const QXmlAttributes& attrib )␊ |
250 | {␊ |
251 | m_curString = "";␊ |
252 | QString kind = attrib.value("kind");␊ |
253 | QString isObjC = attrib.value("objc");␊ |
254 | if (kind=="class")␊ |
255 | {␊ |
256 | m_curClass = new TagClassInfo;␊ |
257 | m_curClass->kind = TagClassInfo::Class;␊ |
258 | m_state = InClass;␊ |
259 | }␊ |
260 | else if (kind=="struct")␊ |
261 | {␊ |
262 | m_curClass = new TagClassInfo;␊ |
263 | m_curClass->kind = TagClassInfo::Struct;␊ |
264 | m_state = InClass;␊ |
265 | }␊ |
266 | else if (kind=="union")␊ |
267 | {␊ |
268 | m_curClass = new TagClassInfo;␊ |
269 | m_curClass->kind = TagClassInfo::Union;␊ |
270 | m_state = InClass;␊ |
271 | }␊ |
272 | else if (kind=="interface")␊ |
273 | {␊ |
274 | m_curClass = new TagClassInfo;␊ |
275 | m_curClass->kind = TagClassInfo::Interface;␊ |
276 | m_state = InClass;␊ |
277 | }␊ |
278 | else if (kind=="exception")␊ |
279 | {␊ |
280 | m_curClass = new TagClassInfo;␊ |
281 | m_curClass->kind = TagClassInfo::Exception;␊ |
282 | m_state = InClass;␊ |
283 | }␊ |
284 | else if (kind=="protocol")␊ |
285 | {␊ |
286 | m_curClass = new TagClassInfo;␊ |
287 | m_curClass->kind = TagClassInfo::Protocol;␊ |
288 | m_state = InClass;␊ |
289 | }␊ |
290 | else if (kind=="category")␊ |
291 | {␊ |
292 | m_curClass = new TagClassInfo;␊ |
293 | m_curClass->kind = TagClassInfo::Category;␊ |
294 | m_state = InClass;␊ |
295 | }␊ |
296 | else if (kind=="file")␊ |
297 | {␊ |
298 | m_curFile = new TagFileInfo;␊ |
299 | m_state = InFile;␊ |
300 | }␊ |
301 | else if (kind=="namespace")␊ |
302 | {␊ |
303 | m_curNamespace = new TagNamespaceInfo;␊ |
304 | m_state = InNamespace;␊ |
305 | }␊ |
306 | else if (kind=="group")␊ |
307 | {␊ |
308 | m_curGroup = new TagGroupInfo;␊ |
309 | m_state = InGroup;␊ |
310 | }␊ |
311 | else if (kind=="page")␊ |
312 | {␊ |
313 | m_curPage = new TagPageInfo;␊ |
314 | m_state = InPage;␊ |
315 | }␊ |
316 | else if (kind=="package")␊ |
317 | {␊ |
318 | m_curPackage = new TagPackageInfo;␊ |
319 | m_state = InPackage;␊ |
320 | }␊ |
321 | else if (kind=="dir")␊ |
322 | {␊ |
323 | m_curDir = new TagDirInfo;␊ |
324 | m_state = InDir;␊ |
325 | }␊ |
326 | else␊ |
327 | {␊ |
328 | warn("warning: Unknown compound attribute `%s' found!\n",kind.data());␊ |
329 | }␊ |
330 | if (isObjC=="yes" && m_curClass)␊ |
331 | {␊ |
332 | m_curClass->isObjC = TRUE; ␊ |
333 | }␊ |
334 | }␊ |
335 | ␊ |
336 | void endCompound()␊ |
337 | {␊ |
338 | switch (m_state)␊ |
339 | {␊ |
340 | case InClass: m_tagFileClasses.append(m_curClass); ␊ |
341 | m_curClass=0; break; ␊ |
342 | case InFile: m_tagFileFiles.append(m_curFile); ␊ |
343 | m_curFile=0; break; ␊ |
344 | case InNamespace: m_tagFileNamespaces.append(m_curNamespace); ␊ |
345 | m_curNamespace=0; break; ␊ |
346 | case InGroup: m_tagFileGroups.append(m_curGroup); ␊ |
347 | m_curGroup=0; break; ␊ |
348 | case InPage: m_tagFilePages.append(m_curPage); ␊ |
349 | m_curPage=0; break; ␊ |
350 | case InDir: m_tagFileDirs.append(m_curDir);␊ |
351 | m_curDir=0; break;␊ |
352 | case InPackage: m_tagFilePackages.append(m_curPackage); ␊ |
353 | m_curPackage=0; break; ␊ |
354 | default:␊ |
355 | warn("warning: tag `compound' was not expected!\n");␊ |
356 | }␊ |
357 | }␊ |
358 | ␊ |
359 | void startMember( const QXmlAttributes& attrib)␊ |
360 | {␊ |
361 | m_curMember = new TagMemberInfo;␊ |
362 | m_curMember->kind = attrib.value("kind");␊ |
363 | QString protStr = attrib.value("protection");␊ |
364 | QString virtStr = attrib.value("virtualness");␊ |
365 | QString staticStr = attrib.value("static");␊ |
366 | if (protStr=="protected")␊ |
367 | {␊ |
368 | m_curMember->prot = Protected;␊ |
369 | }␊ |
370 | else if (protStr=="private")␊ |
371 | {␊ |
372 | m_curMember->prot = Private;␊ |
373 | }␊ |
374 | if (virtStr=="virtual")␊ |
375 | {␊ |
376 | m_curMember->virt = Virtual;␊ |
377 | }␊ |
378 | else if (virtStr=="pure")␊ |
379 | {␊ |
380 | m_curMember->virt = Pure;␊ |
381 | }␊ |
382 | if (staticStr=="yes")␊ |
383 | {␊ |
384 | m_curMember->isStatic = TRUE;␊ |
385 | }␊ |
386 | m_stateStack.push(new State(m_state));␊ |
387 | m_state = InMember;␊ |
388 | }␊ |
389 | ␊ |
390 | void endMember()␊ |
391 | {␊ |
392 | m_state = *m_stateStack.top();␊ |
393 | m_stateStack.remove();␊ |
394 | switch(m_state)␊ |
395 | {␊ |
396 | case InClass: m_curClass->members.append(m_curMember); break;␊ |
397 | case InFile: m_curFile->members.append(m_curMember); break;␊ |
398 | case InNamespace: m_curNamespace->members.append(m_curMember); break;␊ |
399 | case InGroup: m_curGroup->members.append(m_curMember); break;␊ |
400 | case InPackage: m_curPackage->members.append(m_curMember); break;␊ |
401 | default: warn("warning: Unexpected tag `member' found\n"); break; ␊ |
402 | }␊ |
403 | }␊ |
404 | ␊ |
405 | void endDocAnchor()␊ |
406 | {␊ |
407 | switch(m_state)␊ |
408 | {␊ |
409 | case InClass: m_curClass->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
410 | case InFile: m_curFile->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
411 | case InNamespace: m_curNamespace->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
412 | case InGroup: m_curGroup->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
413 | case InPage: m_curPage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
414 | case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
415 | case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
416 | case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;␊ |
417 | default: warn("warning: Unexpected tag `member' found\n"); break; ␊ |
418 | }␊ |
419 | }␊ |
420 | ␊ |
421 | void endClass()␊ |
422 | {␊ |
423 | switch(m_state)␊ |
424 | {␊ |
425 | case InClass: m_curClass->classList.append(m_curString); break;␊ |
426 | case InFile: m_curFile->classList.append(m_curString); break;␊ |
427 | case InNamespace: m_curNamespace->classList.append(m_curString); break;␊ |
428 | case InGroup: m_curGroup->classList.append(m_curString); break;␊ |
429 | case InPackage: m_curPackage->classList.append(m_curString); break;␊ |
430 | default: warn("warning: Unexpected tag `class' found\n"); break; ␊ |
431 | }␊ |
432 | }␊ |
433 | ␊ |
434 | void endNamespace()␊ |
435 | {␊ |
436 | switch(m_state)␊ |
437 | {␊ |
438 | case InNamespace: m_curNamespace->classList.append(m_curString); break;␊ |
439 | case InFile: m_curFile->namespaceList.append(m_curString); break;␊ |
440 | case InGroup: m_curGroup->namespaceList.append(m_curString); break;␊ |
441 | default: warn("warning: Unexpected tag `namespace' found\n"); break; ␊ |
442 | }␊ |
443 | }␊ |
444 | ␊ |
445 | void endFile()␊ |
446 | {␊ |
447 | switch(m_state)␊ |
448 | {␊ |
449 | case InGroup: m_curGroup->fileList.append(m_curString); break;␊ |
450 | case InDir: m_curDir->fileList.append(m_curString); break;␊ |
451 | default: warn("warning: Unexpected tag `file' found\n"); break; ␊ |
452 | }␊ |
453 | }␊ |
454 | ␊ |
455 | void endPage()␊ |
456 | {␊ |
457 | switch(m_state)␊ |
458 | {␊ |
459 | case InGroup: m_curGroup->fileList.append(m_curString); break;␊ |
460 | default: warn("warning: Unexpected tag `page' found\n"); break; ␊ |
461 | }␊ |
462 | }␊ |
463 | ␊ |
464 | void endDir()␊ |
465 | {␊ |
466 | switch(m_state)␊ |
467 | {␊ |
468 | case InDir: m_curDir->subdirList.append(m_curString); break;␊ |
469 | default: warn("warning: Unexpected tag `page' found\n"); break; ␊ |
470 | }␊ |
471 | }␊ |
472 | ␊ |
473 | void startStringValue(const QXmlAttributes& )␊ |
474 | {␊ |
475 | m_curString = "";␊ |
476 | }␊ |
477 | ␊ |
478 | void startDocAnchor(const QXmlAttributes& attrib )␊ |
479 | {␊ |
480 | m_fileName = attrib.value("file");␊ |
481 | m_curString = "";␊ |
482 | }␊ |
483 | ␊ |
484 | void endType()␊ |
485 | {␊ |
486 | if (m_state==InMember)␊ |
487 | {␊ |
488 | m_curMember->type = m_curString; ␊ |
489 | }␊ |
490 | else␊ |
491 | {␊ |
492 | warn("warning: Unexpected tag `type' found\n");␊ |
493 | }␊ |
494 | }␊ |
495 | ␊ |
496 | void endName()␊ |
497 | {␊ |
498 | switch (m_state)␊ |
499 | {␊ |
500 | case InClass: m_curClass->name = m_curString; break;␊ |
501 | case InFile: m_curFile->name = m_curString; break;␊ |
502 | case InNamespace: m_curNamespace->name = m_curString; break;␊ |
503 | case InGroup: m_curGroup->name = m_curString; break;␊ |
504 | case InPage: m_curPage->name = m_curString; break;␊ |
505 | case InDir: m_curDir->name = m_curString; break;␊ |
506 | case InMember: m_curMember->name = m_curString; break;␊ |
507 | case InPackage: m_curPackage->name = m_curString; break;␊ |
508 | default: warn("warning: Unexpected tag `name' found\n"); break; ␊ |
509 | }␊ |
510 | }␊ |
511 | ␊ |
512 | void startBase(const QXmlAttributes& attrib )␊ |
513 | {␊ |
514 | m_curString="";␊ |
515 | if (m_state==InClass && m_curClass)␊ |
516 | {␊ |
517 | QString protStr = attrib.value("protection");␊ |
518 | QString virtStr = attrib.value("virtualness");␊ |
519 | Protection prot = Public;␊ |
520 | Specifier virt = Normal;␊ |
521 | if (protStr=="protected")␊ |
522 | {␊ |
523 | prot = Protected;␊ |
524 | }␊ |
525 | else if (protStr=="private")␊ |
526 | {␊ |
527 | prot = Private;␊ |
528 | }␊ |
529 | if (virtStr=="virtual")␊ |
530 | {␊ |
531 | virt = Virtual;␊ |
532 | }␊ |
533 | if (m_curClass->bases==0) ␊ |
534 | {␊ |
535 | m_curClass->bases = new QList<BaseInfo>;␊ |
536 | m_curClass->bases->setAutoDelete(TRUE);␊ |
537 | }␊ |
538 | m_curClass->bases->append(new BaseInfo(m_curString,prot,virt));␊ |
539 | }␊ |
540 | else␊ |
541 | {␊ |
542 | warn("warning: Unexpected tag `base' found\n");␊ |
543 | }␊ |
544 | }␊ |
545 | ␊ |
546 | void endBase()␊ |
547 | {␊ |
548 | if (m_state==InClass && m_curClass)␊ |
549 | {␊ |
550 | m_curClass->bases->getLast()->name = m_curString;␊ |
551 | }␊ |
552 | else␊ |
553 | {␊ |
554 | warn("warning: Unexpected tag `base' found\n");␊ |
555 | }␊ |
556 | }␊ |
557 | ␊ |
558 | void startIncludes(const QXmlAttributes& attrib )␊ |
559 | {␊ |
560 | if (m_state==InFile && m_curFile)␊ |
561 | {␊ |
562 | m_curIncludes = new TagIncludeInfo;␊ |
563 | m_curIncludes->id = attrib.value("id");␊ |
564 | m_curIncludes->name = attrib.value("name");␊ |
565 | m_curIncludes->isLocal = attrib.value("local")=="yes" ? TRUE : FALSE;␊ |
566 | m_curIncludes->isImported = attrib.value("imported")=="yes" ? TRUE : FALSE;␊ |
567 | m_curFile->includes.append(m_curIncludes);␊ |
568 | }␊ |
569 | else␊ |
570 | {␊ |
571 | warn("warning: Unexpected tag `includes' found\n");␊ |
572 | }␊ |
573 | m_curString="";␊ |
574 | }␊ |
575 | ␊ |
576 | void endIncludes()␊ |
577 | {␊ |
578 | m_curIncludes->text = m_curString;␊ |
579 | }␊ |
580 | ␊ |
581 | void endTemplateArg()␊ |
582 | {␊ |
583 | if (m_state==InClass && m_curClass)␊ |
584 | {␊ |
585 | if (m_curClass->templateArguments==0) ␊ |
586 | {␊ |
587 | m_curClass->templateArguments = new QList<QString>;␊ |
588 | m_curClass->templateArguments->setAutoDelete(TRUE);␊ |
589 | }␊ |
590 | m_curClass->templateArguments->append(new QString(m_curString));␊ |
591 | }␊ |
592 | else␊ |
593 | {␊ |
594 | warn("warning: Unexpected tag `templarg' found\n");␊ |
595 | }␊ |
596 | }␊ |
597 | ␊ |
598 | void endFilename()␊ |
599 | {␊ |
600 | switch (m_state)␊ |
601 | {␊ |
602 | case InClass: m_curClass->filename = m_curString; break;␊ |
603 | case InNamespace: m_curNamespace->filename = m_curString; break;␊ |
604 | case InFile: m_curFile->filename = m_curString; break;␊ |
605 | case InGroup: m_curGroup->filename = m_curString; break;␊ |
606 | case InPage: m_curPage->filename = m_curString; break;␊ |
607 | case InPackage: m_curPackage->filename = m_curString; break;␊ |
608 | case InDir: m_curDir->filename = m_curString; break;␊ |
609 | default: warn("warning: Unexpected tag `filename' found\n"); break; ␊ |
610 | }␊ |
611 | }␊ |
612 | ␊ |
613 | void endPath()␊ |
614 | {␊ |
615 | switch (m_state)␊ |
616 | {␊ |
617 | case InFile: m_curFile->path = m_curString; break;␊ |
618 | case InDir: m_curDir->path = m_curString; break;␊ |
619 | default: warn("warning: Unexpected tag `path' found\n"); break; ␊ |
620 | }␊ |
621 | }␊ |
622 | ␊ |
623 | void endAnchor()␊ |
624 | {␊ |
625 | if (m_state==InMember)␊ |
626 | {␊ |
627 | m_curMember->anchor = m_curString; ␊ |
628 | }␊ |
629 | else␊ |
630 | {␊ |
631 | warn("warning: Unexpected tag `anchor' found\n");␊ |
632 | }␊ |
633 | }␊ |
634 | ␊ |
635 | void endAnchorFile()␊ |
636 | {␊ |
637 | if (m_state==InMember)␊ |
638 | {␊ |
639 | m_curMember->anchorFile = m_curString; ␊ |
640 | }␊ |
641 | else␊ |
642 | {␊ |
643 | warn("warning: Unexpected tag `anchorfile' found\n");␊ |
644 | }␊ |
645 | }␊ |
646 | ␊ |
647 | void endArglist()␊ |
648 | {␊ |
649 | if (m_state==InMember)␊ |
650 | {␊ |
651 | m_curMember->arglist = m_curString; ␊ |
652 | }␊ |
653 | else␊ |
654 | {␊ |
655 | warn("warning: Unexpected tag `arglist' found\n");␊ |
656 | }␊ |
657 | }␊ |
658 | void endTitle()␊ |
659 | {␊ |
660 | switch (m_state)␊ |
661 | {␊ |
662 | case InGroup: m_curGroup->title = m_curString; break;␊ |
663 | case InPage: m_curPage->title = m_curString; break;␊ |
664 | default: warn("warning: Unexpected tag `title' found\n"); break; ␊ |
665 | }␊ |
666 | }␊ |
667 | ␊ |
668 | void endSubgroup()␊ |
669 | {␊ |
670 | if (m_state==InGroup)␊ |
671 | {␊ |
672 | m_curGroup->subgroupList.append(m_curString);␊ |
673 | }␊ |
674 | else␊ |
675 | {␊ |
676 | warn("warning: Unexpected tag `subgroup' found\n");␊ |
677 | }␊ |
678 | }␊ |
679 | ␊ |
680 | void startIgnoreElement(const QXmlAttributes& )␊ |
681 | {␊ |
682 | }␊ |
683 | ␊ |
684 | void endIgnoreElement()␊ |
685 | {␊ |
686 | }␊ |
687 | ␊ |
688 | bool startDocument()␊ |
689 | {␊ |
690 | m_state = Invalid;␊ |
691 | ␊ |
692 | m_curClass=0;␊ |
693 | m_curNamespace=0;␊ |
694 | m_curFile=0;␊ |
695 | m_curGroup=0;␊ |
696 | m_curPage=0;␊ |
697 | m_curPackage=0;␊ |
698 | m_curDir=0;␊ |
699 | ␊ |
700 | m_stateStack.setAutoDelete(TRUE);␊ |
701 | m_tagFileClasses.setAutoDelete(TRUE);␊ |
702 | m_tagFileFiles.setAutoDelete(TRUE);␊ |
703 | m_tagFileNamespaces.setAutoDelete(TRUE);␊ |
704 | m_tagFileGroups.setAutoDelete(TRUE);␊ |
705 | m_tagFilePages.setAutoDelete(TRUE);␊ |
706 | m_tagFilePackages.setAutoDelete(TRUE);␊ |
707 | m_tagFileDirs.setAutoDelete(TRUE);␊ |
708 | ␊ |
709 | m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound));␊ |
710 | m_startElementHandlers.insert("member", new StartElementHandler(this,&TagFileParser::startMember));␊ |
711 | m_startElementHandlers.insert("name", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
712 | m_startElementHandlers.insert("base", new StartElementHandler(this,&TagFileParser::startBase));␊ |
713 | m_startElementHandlers.insert("filename", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
714 | m_startElementHandlers.insert("includes", new StartElementHandler(this,&TagFileParser::startIncludes));␊ |
715 | m_startElementHandlers.insert("path", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
716 | m_startElementHandlers.insert("anchorfile", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
717 | m_startElementHandlers.insert("anchor", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
718 | m_startElementHandlers.insert("arglist", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
719 | m_startElementHandlers.insert("title", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
720 | m_startElementHandlers.insert("subgroup", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
721 | m_startElementHandlers.insert("class", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
722 | m_startElementHandlers.insert("namespace", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
723 | m_startElementHandlers.insert("file", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
724 | m_startElementHandlers.insert("dir", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
725 | m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
726 | m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startDocAnchor));␊ |
727 | m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement));␊ |
728 | m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
729 | m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue));␊ |
730 | ␊ |
731 | m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound));␊ |
732 | m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember));␊ |
733 | m_endElementHandlers.insert("name", new EndElementHandler(this,&TagFileParser::endName));␊ |
734 | m_endElementHandlers.insert("base", new EndElementHandler(this,&TagFileParser::endBase));␊ |
735 | m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename));␊ |
736 | m_endElementHandlers.insert("includes", new EndElementHandler(this,&TagFileParser::endIncludes));␊ |
737 | m_endElementHandlers.insert("path", new EndElementHandler(this,&TagFileParser::endPath));␊ |
738 | m_endElementHandlers.insert("anchorfile", new EndElementHandler(this,&TagFileParser::endAnchorFile));␊ |
739 | m_endElementHandlers.insert("anchor", new EndElementHandler(this,&TagFileParser::endAnchor));␊ |
740 | m_endElementHandlers.insert("arglist", new EndElementHandler(this,&TagFileParser::endArglist));␊ |
741 | m_endElementHandlers.insert("title", new EndElementHandler(this,&TagFileParser::endTitle));␊ |
742 | m_endElementHandlers.insert("subgroup", new EndElementHandler(this,&TagFileParser::endSubgroup));␊ |
743 | m_endElementHandlers.insert("class" , new EndElementHandler(this,&TagFileParser::endClass));␊ |
744 | m_endElementHandlers.insert("namespace", new EndElementHandler(this,&TagFileParser::endNamespace));␊ |
745 | m_endElementHandlers.insert("file", new EndElementHandler(this,&TagFileParser::endFile));␊ |
746 | m_endElementHandlers.insert("dir", new EndElementHandler(this,&TagFileParser::endDir));␊ |
747 | m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage));␊ |
748 | m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor));␊ |
749 | m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement));␊ |
750 | m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg));␊ |
751 | m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType));␊ |
752 | ␊ |
753 | return TRUE;␊ |
754 | }␊ |
755 | ␊ |
756 | bool startElement( const QString&, const QString&, ␊ |
757 | const QString&name, const QXmlAttributes& attrib )␊ |
758 | {␊ |
759 | //printf("startElement `%s'\n",name.data());␊ |
760 | StartElementHandler *handler = m_startElementHandlers[name];␊ |
761 | if (handler)␊ |
762 | {␊ |
763 | (*handler)(attrib);␊ |
764 | }␊ |
765 | else ␊ |
766 | {␊ |
767 | warn("warning: Unknown tag `%s' found!\n",name.data());␊ |
768 | }␊ |
769 | return TRUE;␊ |
770 | }␊ |
771 | ␊ |
772 | bool endElement( const QString&, const QString&, const QString& name )␊ |
773 | {␊ |
774 | //printf("endElement `%s'\n",name.data());␊ |
775 | EndElementHandler *handler = m_endElementHandlers[name];␊ |
776 | if (handler)␊ |
777 | {␊ |
778 | (*handler)();␊ |
779 | }␊ |
780 | else ␊ |
781 | {␊ |
782 | warn("warning: Unknown tag `%s' found!\n",name.data());␊ |
783 | }␊ |
784 | return TRUE;␊ |
785 | }␊ |
786 | ␊ |
787 | bool characters ( const QString & ch ) ␊ |
788 | {␊ |
789 | m_curString+=ch;␊ |
790 | return TRUE;␊ |
791 | }␊ |
792 | ␊ |
793 | void dump();␊ |
794 | void buildLists(Entry *root);␊ |
795 | void addIncludes();␊ |
796 | ␊ |
797 | private:␊ |
798 | void buildMemberList(Entry *ce,QList<TagMemberInfo> &members);␊ |
799 | void addDocAnchors(Entry *e,const TagAnchorInfoList &l);␊ |
800 | QList<TagClassInfo> m_tagFileClasses;␊ |
801 | QList<TagFileInfo> m_tagFileFiles;␊ |
802 | QList<TagNamespaceInfo> m_tagFileNamespaces;␊ |
803 | QList<TagGroupInfo> m_tagFileGroups;␊ |
804 | QList<TagPageInfo> m_tagFilePages;␊ |
805 | QList<TagPackageInfo> m_tagFilePackages;␊ |
806 | QList<TagDirInfo> m_tagFileDirs;␊ |
807 | QDict<StartElementHandler> m_startElementHandlers;␊ |
808 | QDict<EndElementHandler> m_endElementHandlers;␊ |
809 | TagClassInfo *m_curClass;␊ |
810 | TagFileInfo *m_curFile;␊ |
811 | TagNamespaceInfo *m_curNamespace;␊ |
812 | TagPackageInfo *m_curPackage;␊ |
813 | TagGroupInfo *m_curGroup;␊ |
814 | TagPageInfo *m_curPage;␊ |
815 | TagDirInfo *m_curDir;␊ |
816 | TagMemberInfo *m_curMember;␊ |
817 | TagIncludeInfo *m_curIncludes;␊ |
818 | QCString m_curString;␊ |
819 | QString m_tagName;␊ |
820 | QString m_fileName;␊ |
821 | State m_state;␊ |
822 | QStack<State> m_stateStack;␊ |
823 | QXmlLocator *m_locator;␊ |
824 | QString m_inputFileName;␊ |
825 | };␊ |
826 | ␊ |
827 | /*! Error handler for the XML tag file parser. ␊ |
828 | * Basically dumps all fatal error to stderr using err().␊ |
829 | */␊ |
830 | class TagFileErrorHandler : public QXmlErrorHandler␊ |
831 | {␊ |
832 | public:␊ |
833 | virtual ~TagFileErrorHandler() {}␊ |
834 | bool warning( const QXmlParseException & )␊ |
835 | {␊ |
836 | return FALSE;␊ |
837 | }␊ |
838 | bool error( const QXmlParseException & )␊ |
839 | {␊ |
840 | return FALSE;␊ |
841 | }␊ |
842 | bool fatalError( const QXmlParseException &exception )␊ |
843 | {␊ |
844 | err("Fatal error at line %d column %d: %s\n",␊ |
845 | exception.lineNumber(),exception.columnNumber(),␊ |
846 | exception.message().data());␊ |
847 | return FALSE;␊ |
848 | }␊ |
849 | QString errorString() { return ""; }␊ |
850 | ␊ |
851 | private:␊ |
852 | QString errorMsg;␊ |
853 | };␊ |
854 | ␊ |
855 | /*! Dumps the internal structures. For debugging only! */␊ |
856 | void TagFileParser::dump()␊ |
857 | {␊ |
858 | msg("Result:\n");␊ |
859 | QListIterator<TagClassInfo> lci(m_tagFileClasses);␊ |
860 | ␊ |
861 | //============== CLASSES␊ |
862 | TagClassInfo *cd;␊ |
863 | for (;(cd=lci.current());++lci)␊ |
864 | {␊ |
865 | msg("class `%s'\n",cd->name.data());␊ |
866 | msg(" filename `%s'\n",cd->filename.data());␊ |
867 | if (cd->bases)␊ |
868 | {␊ |
869 | QListIterator<BaseInfo> bii(*cd->bases);␊ |
870 | BaseInfo *bi;␊ |
871 | for ( bii.toFirst() ; (bi=bii.current()) ; ++bii) ␊ |
872 | {␊ |
873 | msg( " base: %s \n", bi->name.data() );␊ |
874 | }␊ |
875 | }␊ |
876 | ␊ |
877 | QListIterator<TagMemberInfo> mci(cd->members);␊ |
878 | TagMemberInfo *md;␊ |
879 | for (;(md=mci.current());++mci)␊ |
880 | {␊ |
881 | msg(" member:\n");␊ |
882 | msg(" kind: `%s'\n",md->kind.data());␊ |
883 | msg(" name: `%s'\n",md->name.data());␊ |
884 | msg(" anchor: `%s'\n",md->anchor.data());␊ |
885 | msg(" arglist: `%s'\n",md->arglist.data());␊ |
886 | }␊ |
887 | }␊ |
888 | //============== NAMESPACES␊ |
889 | QListIterator<TagNamespaceInfo> lni(m_tagFileNamespaces);␊ |
890 | TagNamespaceInfo *nd;␊ |
891 | for (;(nd=lni.current());++lni)␊ |
892 | {␊ |
893 | msg("namespace `%s'\n",nd->name.data());␊ |
894 | msg(" filename `%s'\n",nd->filename.data());␊ |
895 | QStringList::Iterator it;␊ |
896 | for ( it = nd->classList.begin(); ␊ |
897 | it != nd->classList.end(); ++it ) ␊ |
898 | {␊ |
899 | msg( " class: %s \n", (*it).latin1() );␊ |
900 | }␊ |
901 | ␊ |
902 | QListIterator<TagMemberInfo> mci(nd->members);␊ |
903 | TagMemberInfo *md;␊ |
904 | for (;(md=mci.current());++mci)␊ |
905 | {␊ |
906 | msg(" member:\n");␊ |
907 | msg(" kind: `%s'\n",md->kind.data());␊ |
908 | msg(" name: `%s'\n",md->name.data());␊ |
909 | msg(" anchor: `%s'\n",md->anchor.data());␊ |
910 | msg(" arglist: `%s'\n",md->arglist.data());␊ |
911 | }␊ |
912 | }␊ |
913 | //============== FILES␊ |
914 | QListIterator<TagFileInfo> lfi(m_tagFileFiles);␊ |
915 | TagFileInfo *fd;␊ |
916 | for (;(fd=lfi.current());++lfi)␊ |
917 | {␊ |
918 | msg("file `%s'\n",fd->name.data());␊ |
919 | msg(" filename `%s'\n",fd->filename.data());␊ |
920 | QStringList::Iterator it;␊ |
921 | for ( it = fd->namespaceList.begin(); ␊ |
922 | it != fd->namespaceList.end(); ++it ) ␊ |
923 | {␊ |
924 | msg( " namespace: %s \n", (*it).latin1() );␊ |
925 | }␊ |
926 | for ( it = fd->classList.begin(); ␊ |
927 | it != fd->classList.end(); ++it ) ␊ |
928 | {␊ |
929 | msg( " class: %s \n", (*it).latin1() );␊ |
930 | }␊ |
931 | ␊ |
932 | QListIterator<TagMemberInfo> mci(fd->members);␊ |
933 | TagMemberInfo *md;␊ |
934 | for (;(md=mci.current());++mci)␊ |
935 | {␊ |
936 | msg(" member:\n");␊ |
937 | msg(" kind: `%s'\n",md->kind.data());␊ |
938 | msg(" name: `%s'\n",md->name.data());␊ |
939 | msg(" anchor: `%s'\n",md->anchor.data());␊ |
940 | msg(" arglist: `%s'\n",md->arglist.data());␊ |
941 | }␊ |
942 | ␊ |
943 | QListIterator<TagIncludeInfo> mii(fd->includes);␊ |
944 | TagIncludeInfo *ii;␊ |
945 | for (;(ii=mii.current());++mii)␊ |
946 | {␊ |
947 | msg(" includes id: %s name: %s\n",ii->id.data(),ii->name.data());␊ |
948 | }␊ |
949 | }␊ |
950 | ␊ |
951 | //============== GROUPS␊ |
952 | QListIterator<TagGroupInfo> lgi(m_tagFileGroups);␊ |
953 | TagGroupInfo *gd;␊ |
954 | for (;(gd=lgi.current());++lgi)␊ |
955 | {␊ |
956 | msg("group `%s'\n",gd->name.data());␊ |
957 | msg(" filename `%s'\n",gd->filename.data());␊ |
958 | QStringList::Iterator it;␊ |
959 | for ( it = gd->namespaceList.begin(); ␊ |
960 | it != gd->namespaceList.end(); ++it ) ␊ |
961 | {␊ |
962 | msg( " namespace: %s \n", (*it).latin1() );␊ |
963 | }␊ |
964 | for ( it = gd->classList.begin(); ␊ |
965 | it != gd->classList.end(); ++it ) ␊ |
966 | {␊ |
967 | msg( " class: %s \n", (*it).latin1() );␊ |
968 | }␊ |
969 | for ( it = gd->fileList.begin(); ␊ |
970 | it != gd->fileList.end(); ++it ) ␊ |
971 | {␊ |
972 | msg( " file: %s \n", (*it).latin1() );␊ |
973 | }␊ |
974 | for ( it = gd->subgroupList.begin(); ␊ |
975 | it != gd->subgroupList.end(); ++it ) ␊ |
976 | {␊ |
977 | msg( " subgroup: %s \n", (*it).latin1() );␊ |
978 | }␊ |
979 | for ( it = gd->pageList.begin(); ␊ |
980 | it != gd->pageList.end(); ++it ) ␊ |
981 | {␊ |
982 | msg( " page: %s \n", (*it).latin1() );␊ |
983 | }␊ |
984 | ␊ |
985 | QListIterator<TagMemberInfo> mci(gd->members);␊ |
986 | TagMemberInfo *md;␊ |
987 | for (;(md=mci.current());++mci)␊ |
988 | {␊ |
989 | msg(" member:\n");␊ |
990 | msg(" kind: `%s'\n",md->kind.data());␊ |
991 | msg(" name: `%s'\n",md->name.data());␊ |
992 | msg(" anchor: `%s'\n",md->anchor.data());␊ |
993 | msg(" arglist: `%s'\n",md->arglist.data());␊ |
994 | }␊ |
995 | }␊ |
996 | //============== PAGES␊ |
997 | QListIterator<TagPageInfo> lpi(m_tagFilePages);␊ |
998 | TagPageInfo *pd;␊ |
999 | for (;(pd=lpi.current());++lpi)␊ |
1000 | {␊ |
1001 | msg("page `%s'\n",pd->name.data());␊ |
1002 | msg(" title `%s'\n",pd->title.data());␊ |
1003 | msg(" filename `%s'\n",pd->filename.data());␊ |
1004 | }␊ |
1005 | //============== DIRS␊ |
1006 | QListIterator<TagDirInfo> ldi(m_tagFileDirs);␊ |
1007 | TagDirInfo *dd;␊ |
1008 | for (;(dd=ldi.current());++ldi)␊ |
1009 | {␊ |
1010 | msg("dir `%s'\n",dd->name.data());␊ |
1011 | msg(" path `%s'\n",dd->path.data());␊ |
1012 | QStringList::Iterator it;␊ |
1013 | for ( it = dd->fileList.begin(); ␊ |
1014 | it != dd->fileList.end(); ++it ) ␊ |
1015 | {␊ |
1016 | msg( " file: %s \n", (*it).latin1() );␊ |
1017 | }␊ |
1018 | for ( it = dd->subdirList.begin(); ␊ |
1019 | it != dd->subdirList.end(); ++it ) ␊ |
1020 | {␊ |
1021 | msg( " subdir: %s \n", (*it).latin1() );␊ |
1022 | }␊ |
1023 | }␊ |
1024 | }␊ |
1025 | ␊ |
1026 | void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l)␊ |
1027 | {␊ |
1028 | QListIterator<TagAnchorInfo> tli(l);␊ |
1029 | TagAnchorInfo *ta;␊ |
1030 | for (tli.toFirst();(ta=tli.current());++tli)␊ |
1031 | {␊ |
1032 | if (Doxygen::sectionDict.find(ta->label)==0)␊ |
1033 | {␊ |
1034 | //printf("New sectionInfo file=%s anchor=%s\n",␊ |
1035 | // ta->fileName.data(),ta->label.data());␊ |
1036 | SectionInfo *si=new SectionInfo(ta->fileName,ta->label,ta->label,␊ |
1037 | SectionInfo::Anchor,m_tagName);␊ |
1038 | Doxygen::sectionDict.insert(ta->label,si);␊ |
1039 | e->anchors->append(si);␊ |
1040 | }␊ |
1041 | else␊ |
1042 | {␊ |
1043 | warn("Duplicate anchor %s found\n",ta->label.data());␊ |
1044 | }␊ |
1045 | }␊ |
1046 | }␊ |
1047 | ␊ |
1048 | void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members)␊ |
1049 | {␊ |
1050 | QListIterator<TagMemberInfo> mii(members);␊ |
1051 | TagMemberInfo *tmi;␊ |
1052 | for (;(tmi=mii.current());++mii)␊ |
1053 | {␊ |
1054 | Entry *me = new Entry;␊ |
1055 | me->type = tmi->type;␊ |
1056 | me->name = tmi->name;␊ |
1057 | me->args = tmi->arglist;␊ |
1058 | if (!me->args.isEmpty())␊ |
1059 | {␊ |
1060 | delete me->argList;␊ |
1061 | me->argList = new ArgumentList;␊ |
1062 | stringToArgumentList(me->args,me->argList);␊ |
1063 | }␊ |
1064 | me->protection = tmi->prot;␊ |
1065 | me->virt = tmi->virt;␊ |
1066 | me->stat = tmi->isStatic;␊ |
1067 | me->fileName = ce->fileName;␊ |
1068 | if (ce->section == Entry::GROUPDOC_SEC)␊ |
1069 | {␊ |
1070 | me->groups->append(new Grouping(ce->name,Grouping::GROUPING_INGROUP));␊ |
1071 | }␊ |
1072 | addDocAnchors(me,tmi->docAnchors);␊ |
1073 | TagInfo *ti = new TagInfo;␊ |
1074 | ti->tagName = m_tagName;␊ |
1075 | ti->anchor = tmi->anchor;␊ |
1076 | ti->fileName = tmi->anchorFile;␊ |
1077 | me->tagInfo = ti;␊ |
1078 | if (tmi->kind=="define")␊ |
1079 | {␊ |
1080 | me->type="#define";␊ |
1081 | me->section = Entry::DEFINE_SEC;␊ |
1082 | }␊ |
1083 | else if (tmi->kind=="enumvalue")␊ |
1084 | {␊ |
1085 | me->section = Entry::VARIABLE_SEC;␊ |
1086 | me->mtype = Method;␊ |
1087 | }␊ |
1088 | else if (tmi->kind=="property")␊ |
1089 | {␊ |
1090 | me->section = Entry::VARIABLE_SEC;␊ |
1091 | me->mtype = Property;␊ |
1092 | }␊ |
1093 | else if (tmi->kind=="event")␊ |
1094 | {␊ |
1095 | me->section = Entry::VARIABLE_SEC;␊ |
1096 | me->mtype = Event;␊ |
1097 | }␊ |
1098 | else if (tmi->kind=="variable")␊ |
1099 | {␊ |
1100 | me->section = Entry::VARIABLE_SEC;␊ |
1101 | me->mtype = Method;␊ |
1102 | }␊ |
1103 | else if (tmi->kind=="typedef")␊ |
1104 | {␊ |
1105 | me->section = Entry::VARIABLE_SEC; //Entry::TYPEDEF_SEC;␊ |
1106 | me->type.prepend("typedef ");␊ |
1107 | me->mtype = Method;␊ |
1108 | }␊ |
1109 | else if (tmi->kind=="enumeration")␊ |
1110 | {␊ |
1111 | me->section = Entry::ENUM_SEC;␊ |
1112 | me->mtype = Method;␊ |
1113 | }␊ |
1114 | else if (tmi->kind=="function")␊ |
1115 | {␊ |
1116 | me->section = Entry::FUNCTION_SEC;␊ |
1117 | me->mtype = Method;␊ |
1118 | }␊ |
1119 | else if (tmi->kind=="signal")␊ |
1120 | {␊ |
1121 | me->section = Entry::FUNCTION_SEC;␊ |
1122 | me->mtype = Signal;␊ |
1123 | }␊ |
1124 | else if (tmi->kind=="prototype")␊ |
1125 | {␊ |
1126 | me->section = Entry::FUNCTION_SEC;␊ |
1127 | me->mtype = Method;␊ |
1128 | }␊ |
1129 | else if (tmi->kind=="friend")␊ |
1130 | {␊ |
1131 | me->section = Entry::FUNCTION_SEC;␊ |
1132 | me->type.prepend("friend ");␊ |
1133 | me->mtype = Method;␊ |
1134 | }␊ |
1135 | else if (tmi->kind=="dcop")␊ |
1136 | {␊ |
1137 | me->section = Entry::FUNCTION_SEC;␊ |
1138 | me->mtype = DCOP;␊ |
1139 | }␊ |
1140 | else if (tmi->kind=="slot")␊ |
1141 | {␊ |
1142 | me->section = Entry::FUNCTION_SEC;␊ |
1143 | me->mtype = Slot;␊ |
1144 | }␊ |
1145 | ce->addSubEntry(me);␊ |
1146 | }␊ |
1147 | }␊ |
1148 | ␊ |
1149 | static QString stripPath(const QString &s)␊ |
1150 | {␊ |
1151 | int i=s.findRev('/');␊ |
1152 | if (i!=-1)␊ |
1153 | {␊ |
1154 | return s.right(s.length()-i-1);␊ |
1155 | }␊ |
1156 | else␊ |
1157 | {␊ |
1158 | return s;␊ |
1159 | }␊ |
1160 | }␊ |
1161 | ␊ |
1162 | /*! Injects the info gathered by the XML parser into the Entry tree.␊ |
1163 | * This tree contains the information extracted from the input in a ␊ |
1164 | * "unrelated" form.␊ |
1165 | */␊ |
1166 | void TagFileParser::buildLists(Entry *root)␊ |
1167 | {␊ |
1168 | // build class list␊ |
1169 | TagClassInfo *tci = m_tagFileClasses.first();␊ |
1170 | while (tci)␊ |
1171 | {␊ |
1172 | Entry *ce = new Entry;␊ |
1173 | ce->section = Entry::CLASS_SEC;␊ |
1174 | switch (tci->kind)␊ |
1175 | {␊ |
1176 | case TagClassInfo::Class: break;␊ |
1177 | case TagClassInfo::Struct: ce->spec = Entry::Struct; break;␊ |
1178 | case TagClassInfo::Union: ce->spec = Entry::Union; break;␊ |
1179 | case TagClassInfo::Interface: ce->spec = Entry::Interface; break;␊ |
1180 | case TagClassInfo::Exception: ce->spec = Entry::Exception; break;␊ |
1181 | case TagClassInfo::Protocol: ce->spec = Entry::Protocol; break;␊ |
1182 | case TagClassInfo::Category: ce->spec = Entry::Category; break;␊ |
1183 | }␊ |
1184 | ce->name = tci->name;␊ |
1185 | if (tci->kind==TagClassInfo::Protocol) ␊ |
1186 | {␊ |
1187 | ce->name+="-p";␊ |
1188 | }␊ |
1189 | addDocAnchors(ce,tci->docAnchors);␊ |
1190 | TagInfo *ti = new TagInfo;␊ |
1191 | ti->tagName = m_tagName;␊ |
1192 | ti->fileName = tci->filename;␊ |
1193 | ce->tagInfo = ti;␊ |
1194 | ce->lang = tci->isObjC ? SrcLangExt_ObjC : SrcLangExt_Unknown;␊ |
1195 | // transfer base class list␊ |
1196 | if (tci->bases)␊ |
1197 | {␊ |
1198 | delete ce->extends;␊ |
1199 | ce->extends = tci->bases; tci->bases = 0;␊ |
1200 | }␊ |
1201 | if (tci->templateArguments)␊ |
1202 | {␊ |
1203 | if (ce->tArgLists==0) ␊ |
1204 | {␊ |
1205 | ce->tArgLists = new QList<ArgumentList>;␊ |
1206 | ce->tArgLists->setAutoDelete(TRUE);␊ |
1207 | }␊ |
1208 | ArgumentList *al = new ArgumentList;␊ |
1209 | ce->tArgLists->append(al);␊ |
1210 | ␊ |
1211 | QListIterator<QString> sli(*tci->templateArguments);␊ |
1212 | QString *argName;␊ |
1213 | for (;(argName=sli.current());++sli)␊ |
1214 | {␊ |
1215 | Argument *a = new Argument;␊ |
1216 | a->type = "class";␊ |
1217 | a->name = *argName;␊ |
1218 | al->append(a);␊ |
1219 | }␊ |
1220 | }␊ |
1221 | ␊ |
1222 | buildMemberList(ce,tci->members);␊ |
1223 | root->addSubEntry(ce);␊ |
1224 | tci = m_tagFileClasses.next();␊ |
1225 | }␊ |
1226 | ␊ |
1227 | // build file list␊ |
1228 | TagFileInfo *tfi = m_tagFileFiles.first();␊ |
1229 | while (tfi)␊ |
1230 | {␊ |
1231 | Entry *fe = new Entry;␊ |
1232 | fe->section = guessSection(tfi->name);␊ |
1233 | fe->name = tfi->name;␊ |
1234 | addDocAnchors(fe,tfi->docAnchors);␊ |
1235 | TagInfo *ti = new TagInfo;␊ |
1236 | ti->tagName = m_tagName;␊ |
1237 | ti->fileName = tfi->filename;␊ |
1238 | fe->tagInfo = ti;␊ |
1239 | ␊ |
1240 | QString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name);␊ |
1241 | fe->fileName = fullName;␊ |
1242 | //printf("new FileDef() filename=%s\n",tfi->filename.data());␊ |
1243 | FileDef *fd = new FileDef(m_tagName+":"+tfi->path,␊ |
1244 | tfi->name,m_tagName,␊ |
1245 | tfi->filename␊ |
1246 | );␊ |
1247 | FileName *mn;␊ |
1248 | if ((mn=Doxygen::inputNameDict->find(tfi->name)))␊ |
1249 | {␊ |
1250 | mn->append(fd);␊ |
1251 | }␊ |
1252 | else␊ |
1253 | {␊ |
1254 | mn = new FileName(fullName,tfi->name);␊ |
1255 | mn->append(fd);␊ |
1256 | Doxygen::inputNameList->inSort(mn);␊ |
1257 | Doxygen::inputNameDict->insert(tfi->name,mn);␊ |
1258 | }␊ |
1259 | buildMemberList(fe,tfi->members);␊ |
1260 | root->addSubEntry(fe);␊ |
1261 | tfi = m_tagFileFiles.next();␊ |
1262 | }␊ |
1263 | ␊ |
1264 | // build namespace list␊ |
1265 | TagNamespaceInfo *tni = m_tagFileNamespaces.first();␊ |
1266 | while (tni)␊ |
1267 | {␊ |
1268 | Entry *ne = new Entry;␊ |
1269 | ne->section = Entry::NAMESPACE_SEC;␊ |
1270 | ne->name = tni->name;␊ |
1271 | addDocAnchors(ne,tni->docAnchors);␊ |
1272 | TagInfo *ti = new TagInfo;␊ |
1273 | ti->tagName = m_tagName;␊ |
1274 | ti->fileName = tni->filename;␊ |
1275 | ne->tagInfo = ti;␊ |
1276 | ␊ |
1277 | buildMemberList(ne,tni->members);␊ |
1278 | root->addSubEntry(ne);␊ |
1279 | tni = m_tagFileNamespaces.next();␊ |
1280 | }␊ |
1281 | ␊ |
1282 | // build package list␊ |
1283 | TagPackageInfo *tpgi = m_tagFilePackages.first();␊ |
1284 | while (tpgi)␊ |
1285 | {␊ |
1286 | Entry *pe = new Entry;␊ |
1287 | pe->section = Entry::PACKAGE_SEC;␊ |
1288 | pe->name = tpgi->name;␊ |
1289 | addDocAnchors(pe,tpgi->docAnchors);␊ |
1290 | TagInfo *ti = new TagInfo;␊ |
1291 | ti->tagName = m_tagName;␊ |
1292 | ti->fileName = tpgi->filename;␊ |
1293 | pe->tagInfo = ti;␊ |
1294 | ␊ |
1295 | buildMemberList(pe,tpgi->members);␊ |
1296 | root->addSubEntry(pe);␊ |
1297 | tpgi = m_tagFilePackages.next();␊ |
1298 | }␊ |
1299 | ␊ |
1300 | // build group list, but only if config file says to include it␊ |
1301 | //if (Config_getBool("EXTERNAL_GROUPS")) ␊ |
1302 | //{␊ |
1303 | TagGroupInfo *tgi = m_tagFileGroups.first();␊ |
1304 | while (tgi)␊ |
1305 | {␊ |
1306 | Entry *ge = new Entry;␊ |
1307 | ge->section = Entry::GROUPDOC_SEC;␊ |
1308 | ge->name = tgi->name;␊ |
1309 | ge->type = tgi->title;␊ |
1310 | addDocAnchors(ge,tgi->docAnchors);␊ |
1311 | TagInfo *ti = new TagInfo;␊ |
1312 | ti->tagName = m_tagName;␊ |
1313 | ti->fileName = tgi->filename;␊ |
1314 | ge->tagInfo = ti;␊ |
1315 | ␊ |
1316 | buildMemberList(ge,tgi->members);␊ |
1317 | root->addSubEntry(ge);␊ |
1318 | tgi = m_tagFileGroups.next();␊ |
1319 | }␊ |
1320 | //}␊ |
1321 | ␊ |
1322 | // build page list␊ |
1323 | TagPageInfo *tpi = m_tagFilePages.first();␊ |
1324 | while (tpi)␊ |
1325 | {␊ |
1326 | Entry *pe = new Entry;␊ |
1327 | pe->section = Entry::PAGEDOC_SEC;␊ |
1328 | pe->name = tpi->name;␊ |
1329 | pe->args = tpi->title;␊ |
1330 | addDocAnchors(pe,tpi->docAnchors);␊ |
1331 | TagInfo *ti = new TagInfo;␊ |
1332 | ti->tagName = m_tagName;␊ |
1333 | ti->fileName = tpi->filename;␊ |
1334 | pe->tagInfo = ti;␊ |
1335 | ␊ |
1336 | root->addSubEntry(pe);␊ |
1337 | tpi = m_tagFilePages.next();␊ |
1338 | }␊ |
1339 | }␊ |
1340 | ␊ |
1341 | void TagFileParser::addIncludes()␊ |
1342 | {␊ |
1343 | TagFileInfo *tfi = m_tagFileFiles.first();␊ |
1344 | while (tfi)␊ |
1345 | {␊ |
1346 | //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data());␊ |
1347 | FileName *fn = Doxygen::inputNameDict->find(tfi->name);␊ |
1348 | if (fn)␊ |
1349 | {␊ |
1350 | //printf("found\n");␊ |
1351 | FileNameIterator fni(*fn);␊ |
1352 | FileDef *fd;␊ |
1353 | for (;(fd=fni.current());++fni)␊ |
1354 | {␊ |
1355 | //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data());␊ |
1356 | if (fd->getPath()==QCString(m_tagName+":"+tfi->path))␊ |
1357 | {␊ |
1358 | //printf("found\n");␊ |
1359 | QListIterator<TagIncludeInfo> mii(tfi->includes);␊ |
1360 | TagIncludeInfo *ii;␊ |
1361 | for (;(ii=mii.current());++mii)␊ |
1362 | {␊ |
1363 | //printf("ii->name=`%s'\n",ii->name.data());␊ |
1364 | FileName *ifn = Doxygen::inputNameDict->find(ii->name);␊ |
1365 | ASSERT(ifn!=0);␊ |
1366 | if (ifn)␊ |
1367 | {␊ |
1368 | FileNameIterator ifni(*ifn);␊ |
1369 | FileDef *ifd;␊ |
1370 | for (;(ifd=ifni.current());++ifni)␊ |
1371 | {␊ |
1372 | //printf("ifd->getOutputFileBase()=%s ii->id=%s\n",␊ |
1373 | // ifd->getOutputFileBase().data(),ii->id.data());␊ |
1374 | if (ifd->getOutputFileBase()==QCString(ii->id))␊ |
1375 | {␊ |
1376 | fd->addIncludeDependency(ifd,ii->text,ii->isLocal,ii->isImported);␊ |
1377 | }␊ |
1378 | }␊ |
1379 | }␊ |
1380 | }␊ |
1381 | }␊ |
1382 | } ␊ |
1383 | }␊ |
1384 | tfi = m_tagFileFiles.next();␊ |
1385 | }␊ |
1386 | }␊ |
1387 | ␊ |
1388 | void parseTagFile(Entry *root,const char *fullName,const char *tagName)␊ |
1389 | {␊ |
1390 | QFileInfo fi(fullName);␊ |
1391 | if (!fi.exists()) return;␊ |
1392 | TagFileParser handler( tagName );␊ |
1393 | handler.setFileName(fullName);␊ |
1394 | TagFileErrorHandler errorHandler;␊ |
1395 | QFile xmlFile( fullName );␊ |
1396 | QXmlInputSource source( xmlFile );␊ |
1397 | QXmlSimpleReader reader;␊ |
1398 | reader.setContentHandler( &handler );␊ |
1399 | reader.setErrorHandler( &errorHandler );␊ |
1400 | reader.parse( source );␊ |
1401 | handler.buildLists(root);␊ |
1402 | handler.addIncludes();␊ |
1403 | //handler.dump();␊ |
1404 | }␊ |
1405 | ␊ |
1406 | ␊ |
1407 |