|
1 /****************************************************************************** |
|
2 * |
|
3 * |
|
4 * |
|
5 * Copyright (C) 1997-2008 by Dimitri van Heesch. |
|
6 * |
|
7 * Permission to use, copy, modify, and distribute this software and its |
|
8 * documentation under the terms of the GNU General Public License is hereby |
|
9 * granted. No representations are made about the suitability of this software |
|
10 * for any purpose. It is provided "as is" without express or implied warranty. |
|
11 * See the GNU General Public License for more details. |
|
12 * |
|
13 * Documents produced by Doxygen are derivative works derived from the |
|
14 * input used in their production; they are not affected by this license. |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <stdlib.h> |
|
19 #include <qfile.h> |
|
20 #include "entry.h" |
|
21 #include "marshal.h" |
|
22 #include "util.h" |
|
23 #include "section.h" |
|
24 #include "doxygen.h" |
|
25 |
|
26 //------------------------------------------------------------------ |
|
27 |
|
28 #define HEADER ('D'<<24)+('O'<<16)+('X'<<8)+'!' |
|
29 |
|
30 //------------------------------------------------------------------ |
|
31 |
|
32 /*! the argument list is documented if one of its |
|
33 * arguments is documented |
|
34 */ |
|
35 bool ArgumentList::hasDocumentation() const |
|
36 { |
|
37 bool hasDocs=FALSE; |
|
38 ArgumentListIterator ali(*this); |
|
39 Argument *a; |
|
40 for (ali.toFirst();!hasDocs && (a=ali.current());++ali) |
|
41 { |
|
42 hasDocs = hasDocs || a->hasDocumentation(); |
|
43 } |
|
44 return hasDocs; |
|
45 } |
|
46 |
|
47 //------------------------------------------------------------------ |
|
48 |
|
49 int Entry::num=0; |
|
50 |
|
51 Entry::Entry() |
|
52 { |
|
53 //printf("Entry::Entry(%p)\n",this); |
|
54 num++; |
|
55 m_parent=0; |
|
56 section = EMPTY_SEC; |
|
57 m_sublist = new QList<Entry>; |
|
58 m_sublist->setAutoDelete(TRUE); |
|
59 extends = new QList<BaseInfo>; |
|
60 extends->setAutoDelete(TRUE); |
|
61 groups = new QList<Grouping>; |
|
62 groups->setAutoDelete(TRUE); |
|
63 anchors = new QList<SectionInfo>; // Doxygen::sectionDict takes ownership of the items! |
|
64 argList = new ArgumentList; |
|
65 argList->setAutoDelete(TRUE); |
|
66 //printf("Entry::Entry() tArgList=0\n"); |
|
67 tArgLists = 0; |
|
68 typeConstr = 0; |
|
69 mGrpId = -1; |
|
70 tagInfo = 0; |
|
71 sli = 0; |
|
72 relatesType = Simple; |
|
73 hidden = FALSE; |
|
74 groupDocType = GROUPDOC_NORMAL; |
|
75 reset(); |
|
76 } |
|
77 |
|
78 Entry::Entry(const Entry &e) |
|
79 { |
|
80 //printf("Entry::Entry(%p):copy\n",this); |
|
81 num++; |
|
82 section = e.section; |
|
83 type = e.type; |
|
84 name = e.name; |
|
85 tagInfo = e.tagInfo; |
|
86 protection = e.protection; |
|
87 mtype = e.mtype; |
|
88 spec = e.spec; |
|
89 initLines = e.initLines; |
|
90 stat = e.stat; |
|
91 explicitExternal = e.explicitExternal; |
|
92 proto = e.proto; |
|
93 subGrouping = e.subGrouping; |
|
94 callGraph = e.callGraph; |
|
95 callerGraph = e.callerGraph; |
|
96 virt = e.virt; |
|
97 args = e.args; |
|
98 bitfields = e.bitfields; |
|
99 argList = new ArgumentList; |
|
100 argList->setAutoDelete(TRUE); |
|
101 tArgLists = 0; |
|
102 program = e.program; |
|
103 initializer = e.initializer; |
|
104 includeFile = e.includeFile; |
|
105 includeName = e.includeName; |
|
106 doc = e.doc; |
|
107 docLine = e.docLine; |
|
108 docFile = e.docFile; |
|
109 brief = e.brief; |
|
110 briefLine = e.briefLine; |
|
111 briefFile = e.briefFile; |
|
112 inbodyDocs = e.inbodyDocs; |
|
113 inbodyLine = e.inbodyLine; |
|
114 inbodyFile = e.inbodyFile; |
|
115 relates = e.relates; |
|
116 relatesType = e.relatesType; |
|
117 read = e.read; |
|
118 write = e.write; |
|
119 inside = e.inside; |
|
120 exception = e.exception; |
|
121 typeConstr = new ArgumentList; |
|
122 typeConstr->setAutoDelete(TRUE); |
|
123 bodyLine = e.bodyLine; |
|
124 endBodyLine = e.endBodyLine; |
|
125 mGrpId = e.mGrpId; |
|
126 extends = new QList<BaseInfo>; |
|
127 extends->setAutoDelete(TRUE); |
|
128 groups = new QList<Grouping>; |
|
129 groups->setAutoDelete(TRUE); |
|
130 anchors = new QList<SectionInfo>; |
|
131 fileName = e.fileName; |
|
132 startLine = e.startLine; |
|
133 if (e.sli) |
|
134 { |
|
135 sli = new QList<ListItemInfo>; |
|
136 sli->setAutoDelete(TRUE); |
|
137 QListIterator<ListItemInfo> slii(*e.sli); |
|
138 ListItemInfo *ili; |
|
139 for (slii.toFirst();(ili=slii.current());++slii) |
|
140 { |
|
141 sli->append(new ListItemInfo(*ili)); |
|
142 } |
|
143 } |
|
144 else |
|
145 { |
|
146 sli=0; |
|
147 } |
|
148 objc = e.objc; |
|
149 hidden = e.hidden; |
|
150 artificial = e.artificial; |
|
151 groupDocType = e.groupDocType; |
|
152 |
|
153 m_parent = e.m_parent; |
|
154 m_sublist = new QList<Entry>; |
|
155 m_sublist->setAutoDelete(TRUE); |
|
156 |
|
157 // deep copy of the child entry list |
|
158 QListIterator<Entry> eli(*e.m_sublist); |
|
159 Entry *cur; |
|
160 for (;(cur=eli.current());++eli) |
|
161 { |
|
162 m_sublist->append(new Entry(*cur)); |
|
163 } |
|
164 |
|
165 // deep copy base class list |
|
166 QListIterator<BaseInfo> bli(*e.extends); |
|
167 BaseInfo *bi; |
|
168 for (;(bi=bli.current());++bli) |
|
169 { |
|
170 extends->append(new BaseInfo(*bi)); |
|
171 } |
|
172 |
|
173 // deep copy group list |
|
174 QListIterator<Grouping> gli(*e.groups); |
|
175 Grouping *g; |
|
176 for (;(g=gli.current());++gli) |
|
177 { |
|
178 groups->append(new Grouping(*g)); |
|
179 } |
|
180 |
|
181 QListIterator<SectionInfo> sli2(*e.anchors); |
|
182 SectionInfo *s; |
|
183 for (;(s=sli2.current());++sli2) |
|
184 { |
|
185 anchors->append(new SectionInfo(*s)); |
|
186 } |
|
187 |
|
188 // deep copy argument list |
|
189 QListIterator<Argument> ali(*e.argList); |
|
190 Argument *a; |
|
191 for (;(a=ali.current());++ali) |
|
192 { |
|
193 argList->append(new Argument(*a)); |
|
194 } |
|
195 argList->constSpecifier = e.argList->constSpecifier; |
|
196 argList->volatileSpecifier = e.argList->volatileSpecifier; |
|
197 argList->pureSpecifier = e.argList->pureSpecifier; |
|
198 |
|
199 // deep copy type contraint list |
|
200 if (e.typeConstr) |
|
201 { |
|
202 QListIterator<Argument> tcli(*e.typeConstr); |
|
203 for (;(a=tcli.current());++tcli) |
|
204 { |
|
205 typeConstr->append(new Argument(*a)); |
|
206 } |
|
207 } |
|
208 |
|
209 // deep copy template argument lists |
|
210 if (e.tArgLists) |
|
211 { |
|
212 tArgLists = copyArgumentLists(e.tArgLists); |
|
213 } |
|
214 |
|
215 } |
|
216 |
|
217 Entry::~Entry() |
|
218 { |
|
219 //printf("Entry::~Entry(%p) num=%d\n",this,num); |
|
220 //printf("Deleting entry %d name %s type %x children %d\n", |
|
221 // num,name.data(),section,sublist->count()); |
|
222 |
|
223 delete m_sublist; // each element is now own by a EntryNav so we do no longer own |
|
224 // our children. |
|
225 delete extends; |
|
226 delete groups; |
|
227 delete anchors; |
|
228 delete argList; |
|
229 delete tArgLists; |
|
230 delete tagInfo; |
|
231 delete typeConstr; |
|
232 delete sli; |
|
233 num--; |
|
234 } |
|
235 |
|
236 void Entry::addSubEntry(Entry *current) |
|
237 { |
|
238 //printf("Entry %d with name %s type 0x%x added to %s type 0x%x\n", |
|
239 // current->num,current->name.data(),current->section, |
|
240 // name.data(),section); |
|
241 //printf("Entry::addSubEntry(%s:%p) to %s\n",current->name.data(), |
|
242 // current,name.data()); |
|
243 current->m_parent=this; |
|
244 m_sublist->append(current); |
|
245 } |
|
246 |
|
247 void Entry::reset() |
|
248 { |
|
249 //printf("Entry::reset()\n"); |
|
250 name.resize(0); |
|
251 type.resize(0); |
|
252 args.resize(0); |
|
253 bitfields.resize(0); |
|
254 exception.resize(0); |
|
255 program.resize(0); |
|
256 includeFile.resize(0); |
|
257 includeName.resize(0); |
|
258 doc.resize(0); |
|
259 docFile.resize(0); |
|
260 docLine=-1; |
|
261 relates.resize(0); |
|
262 relatesType=Simple; |
|
263 brief.resize(0); |
|
264 briefFile.resize(0); |
|
265 briefLine=-1; |
|
266 inbodyDocs.resize(0); |
|
267 inbodyFile.resize(0); |
|
268 inbodyLine=-1; |
|
269 inside.resize(0); |
|
270 fileName.resize(0); |
|
271 initializer.resize(0); |
|
272 initLines = -1; |
|
273 startLine = 1; |
|
274 bodyLine = -1; |
|
275 endBodyLine = -1; |
|
276 mGrpId = -1; |
|
277 callGraph = FALSE; |
|
278 callerGraph = FALSE; |
|
279 section = EMPTY_SEC; |
|
280 mtype = Method; |
|
281 virt = Normal; |
|
282 stat = FALSE; |
|
283 proto = FALSE; |
|
284 explicitExternal = FALSE; |
|
285 spec = 0; |
|
286 objc = FALSE; |
|
287 hidden = FALSE; |
|
288 artificial = FALSE; |
|
289 subGrouping = TRUE; |
|
290 protection = Public; |
|
291 groupDocType = GROUPDOC_NORMAL; |
|
292 m_sublist->clear(); |
|
293 extends->clear(); |
|
294 groups->clear(); |
|
295 anchors->clear(); |
|
296 argList->clear(); |
|
297 if (tagInfo) { delete tagInfo; tagInfo=0; } |
|
298 if (tArgLists) { delete tArgLists; tArgLists=0; } |
|
299 if (sli) { delete sli; sli=0; } |
|
300 if (typeConstr) { delete typeConstr; typeConstr=0; } |
|
301 //if (mtArgList) { delete mtArgList; mtArgList=0; } |
|
302 } |
|
303 |
|
304 |
|
305 int Entry::getSize() |
|
306 { |
|
307 return sizeof(Entry); |
|
308 } |
|
309 |
|
310 void Entry::createSubtreeIndex(EntryNav *nav,FileStorage *storage,FileDef *fd) |
|
311 { |
|
312 EntryNav *childNav = new EntryNav(nav,this); |
|
313 nav->addChild(childNav); |
|
314 childNav->setFileDef(fd); |
|
315 childNav->saveEntry(this,storage); |
|
316 if (m_sublist) |
|
317 { |
|
318 //printf("saveEntry: %d children\n",node->sublist->count()); |
|
319 QListIterator<Entry> eli(*m_sublist); |
|
320 Entry *childNode; |
|
321 for (eli.toFirst();(childNode=eli.current());++eli) |
|
322 { |
|
323 childNode->createSubtreeIndex(childNav,storage,fd); |
|
324 } |
|
325 //m_sublist->setAutoDelete(FALSE); |
|
326 m_sublist->clear(); |
|
327 } |
|
328 } |
|
329 |
|
330 void Entry::createNavigationIndex(EntryNav *rootNav,FileStorage *storage,FileDef *fd) |
|
331 { |
|
332 //printf("createNavigationIndex(%p) sublist=%p\n",this,m_sublist); |
|
333 if (m_sublist) |
|
334 { |
|
335 //printf("saveEntries: %d children\n",root->sublist->count()); |
|
336 // store all child entries of root, but keep the navigation info (=index) |
|
337 QListIterator<Entry> eli(*m_sublist); |
|
338 Entry *e; |
|
339 for (eli.toFirst();(e=eli.current());++eli) |
|
340 { |
|
341 createSubtreeIndex(rootNav,storage,fd); |
|
342 } |
|
343 // remove all entries from root |
|
344 //m_sublist->setAutoDelete(FALSE); |
|
345 m_sublist->clear(); |
|
346 } |
|
347 } |
|
348 |
|
349 void Entry::addSpecialListItem(const char *listName,int itemId) |
|
350 { |
|
351 if (sli==0) |
|
352 { |
|
353 sli = new QList<ListItemInfo>; |
|
354 sli->setAutoDelete(TRUE); |
|
355 } |
|
356 ListItemInfo *ili=new ListItemInfo; |
|
357 ili->type = listName; |
|
358 ili->itemId = itemId; |
|
359 sli->append(ili); |
|
360 } |
|
361 |
|
362 //------------------------------------------------------------------ |
|
363 |
|
364 |
|
365 EntryNav::EntryNav(EntryNav *parent, Entry *e) |
|
366 : m_parent(parent), m_subList(0), m_section(e->section), m_type(e->type), |
|
367 m_name(e->name), m_fileDef(0), m_info(0), m_offset(-1), |
|
368 m_noLoad(FALSE) |
|
369 { |
|
370 if (e->tagInfo) |
|
371 { |
|
372 m_tagInfo = new TagInfo; |
|
373 m_tagInfo->tagName = e->tagInfo->tagName; |
|
374 m_tagInfo->fileName = e->tagInfo->fileName; |
|
375 m_tagInfo->anchor = e->tagInfo->anchor; |
|
376 if (e->tagInfo) |
|
377 { |
|
378 //printf("tagInfo %p: tagName=%s fileName=%s anchor=%s\n", |
|
379 // e->tagInfo, |
|
380 // e->tagInfo->tagName.data(), |
|
381 // e->tagInfo->fileName.data(), |
|
382 // e->tagInfo->anchor.data()); |
|
383 } |
|
384 } |
|
385 else |
|
386 { |
|
387 m_tagInfo = 0; |
|
388 } |
|
389 } |
|
390 |
|
391 EntryNav::~EntryNav() |
|
392 { |
|
393 delete m_subList; |
|
394 delete m_info; |
|
395 delete m_tagInfo; |
|
396 } |
|
397 |
|
398 void EntryNav::addChild(EntryNav *e) |
|
399 { |
|
400 if (m_subList==0) |
|
401 { |
|
402 m_subList = new QList<EntryNav>; |
|
403 m_subList->setAutoDelete(TRUE); |
|
404 } |
|
405 m_subList->append(e); |
|
406 } |
|
407 |
|
408 bool EntryNav::loadEntry(FileStorage *storage) |
|
409 { |
|
410 if (m_noLoad) |
|
411 { |
|
412 return TRUE; |
|
413 } |
|
414 if (m_offset==-1) |
|
415 { |
|
416 //printf("offset not set!\n"); |
|
417 return FALSE; |
|
418 } |
|
419 //delete m_info; |
|
420 //printf("EntryNav::loadEntry: new entry %p: %s\n",m_info,m_name.data()); |
|
421 //m_info->tagInfo = m_tagInfo; |
|
422 //if (m_parent) |
|
423 //{ |
|
424 // m_info->parent = m_parent->m_info; |
|
425 //} |
|
426 //m_info->parent = 0; |
|
427 //printf("load entry: seek to %llx\n",m_offset); |
|
428 if (!storage->seek(m_offset)) |
|
429 { |
|
430 //printf("seek failed!\n"); |
|
431 return FALSE; |
|
432 } |
|
433 if (m_info) delete m_info; |
|
434 m_info = unmarshalEntry(storage); |
|
435 m_info->name = m_name; |
|
436 m_info->type = m_type; |
|
437 m_info->section = m_section; |
|
438 return TRUE; |
|
439 } |
|
440 |
|
441 bool EntryNav::saveEntry(Entry *e,FileStorage *storage) |
|
442 { |
|
443 m_offset = storage->pos(); |
|
444 //printf("EntryNav::saveEntry offset=%llx\n",m_offset); |
|
445 marshalEntry(storage,e); |
|
446 return TRUE; |
|
447 } |
|
448 |
|
449 void EntryNav::releaseEntry() |
|
450 { |
|
451 if (!m_noLoad) |
|
452 { |
|
453 //printf("EntryNav::releaseEntry %p\n",m_info); |
|
454 delete m_info; |
|
455 m_info=0; |
|
456 } |
|
457 } |
|
458 |
|
459 void EntryNav::setEntry(Entry *e) |
|
460 { |
|
461 delete m_info; |
|
462 m_info = e; |
|
463 //printf("EntryNav::setEntry %p\n",e); |
|
464 m_noLoad=TRUE; |
|
465 } |
|
466 |