|
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 "qtbc.h" |
|
19 #include <ctype.h> |
|
20 #include <qregexp.h> |
|
21 #include <md5.h> |
|
22 #include <stdio.h> |
|
23 #include <stdlib.h> |
|
24 #include <assert.h> |
|
25 #include "config.h" |
|
26 #include "definition.h" |
|
27 #include "doxygen.h" |
|
28 #include "language.h" |
|
29 #include "message.h" |
|
30 #include "outputlist.h" |
|
31 #include "code.h" |
|
32 #include "util.h" |
|
33 #include "groupdef.h" |
|
34 #include "pagedef.h" |
|
35 #include "section.h" |
|
36 #include "htags.h" |
|
37 #include "parserintf.h" |
|
38 #include "marshal.h" |
|
39 #include "debug.h" |
|
40 |
|
41 #define START_MARKER 0x4445465B // DEF[ |
|
42 #define END_MARKER 0x4445465D // DEF] |
|
43 |
|
44 //----------------------------------------------------------------------------------------- |
|
45 |
|
46 class DefinitionImpl |
|
47 { |
|
48 public: |
|
49 DefinitionImpl(); |
|
50 ~DefinitionImpl(); |
|
51 void init(const char *df,int dl, |
|
52 const char *n); |
|
53 |
|
54 SectionDict *sectionDict; // dictionary of all sections, not accessible |
|
55 |
|
56 MemberSDict *sourceRefByDict; |
|
57 MemberSDict *sourceRefsDict; |
|
58 QList<ListItemInfo> *xrefListItems; |
|
59 GroupList *partOfGroups; |
|
60 |
|
61 DocInfo *details; // not exported |
|
62 DocInfo *inbodyDocs; // not exported |
|
63 BriefInfo *brief; // not exported |
|
64 BodyInfo *body; // not exported |
|
65 QCString docSignatures; |
|
66 |
|
67 QCString localName; // local (unqualified) name of the definition |
|
68 // in the future m_name should become m_localName |
|
69 QCString qualifiedName; |
|
70 QCString ref; // reference to external documentation |
|
71 |
|
72 bool hidden; |
|
73 bool isArtificial; |
|
74 |
|
75 Definition *outerScope; // not owner |
|
76 |
|
77 // where the item was found |
|
78 QCString defFileName; |
|
79 int defLine; |
|
80 QCString defFileExt; |
|
81 }; |
|
82 |
|
83 DefinitionImpl::DefinitionImpl() |
|
84 : sectionDict(0), sourceRefByDict(0), sourceRefsDict(0), |
|
85 xrefListItems(0), partOfGroups(0), |
|
86 details(0), inbodyDocs(0), brief(0), body(0), |
|
87 outerScope(0) |
|
88 { |
|
89 } |
|
90 |
|
91 DefinitionImpl::~DefinitionImpl() |
|
92 { |
|
93 delete sectionDict; |
|
94 delete sourceRefByDict; |
|
95 delete sourceRefsDict; |
|
96 delete partOfGroups; |
|
97 delete xrefListItems; |
|
98 delete brief; |
|
99 delete details; |
|
100 delete body; |
|
101 delete inbodyDocs; |
|
102 } |
|
103 |
|
104 void DefinitionImpl::init(const char *df,int dl, |
|
105 const char *n) |
|
106 { |
|
107 defFileName = df; |
|
108 int lastDot = defFileName.findRev('.'); |
|
109 if (lastDot!=-1) |
|
110 { |
|
111 defFileExt = defFileName.mid(lastDot); |
|
112 } |
|
113 defLine = dl; |
|
114 QCString name = n; |
|
115 if (name!="<globalScope>") |
|
116 { |
|
117 //extractNamespaceName(m_name,m_localName,ns); |
|
118 localName=stripScope(n); |
|
119 } |
|
120 else |
|
121 { |
|
122 localName=n; |
|
123 } |
|
124 //printf("m_localName=%s\n",m_localName.data()); |
|
125 |
|
126 brief = 0; |
|
127 details = 0; |
|
128 body = 0; |
|
129 inbodyDocs = 0; |
|
130 sourceRefByDict = 0; |
|
131 sourceRefsDict = 0; |
|
132 sectionDict = 0, |
|
133 outerScope = Doxygen::globalScope; |
|
134 partOfGroups = 0; |
|
135 xrefListItems = 0; |
|
136 hidden = FALSE; |
|
137 isArtificial = FALSE; |
|
138 } |
|
139 |
|
140 //----------------------------------------------------------------------------------------- |
|
141 |
|
142 static bool matchExcludedSymbols(const char *name) |
|
143 { |
|
144 static QStrList &exclSyms = Config_getList("EXCLUDE_SYMBOLS"); |
|
145 if (exclSyms.count()==0) return FALSE; // nothing specified |
|
146 const char *pat = exclSyms.first(); |
|
147 QCString symName = name; |
|
148 while (pat) |
|
149 { |
|
150 QCString pattern = pat; |
|
151 bool forceStart=FALSE; |
|
152 bool forceEnd=FALSE; |
|
153 if (pattern.at(0)=='^') |
|
154 pattern=pattern.mid(1),forceStart=TRUE; |
|
155 if (pattern.at(pattern.length()-1)=='$') |
|
156 pattern=pattern.left(pattern.length()-1),forceEnd=TRUE; |
|
157 if (pattern.find('*')!=-1) // wildcard mode |
|
158 { |
|
159 QRegExp re(substitute(pattern,"*",".*"),TRUE); |
|
160 int i,pl; |
|
161 i = re.match(symName,0,&pl); |
|
162 //printf(" %d = re.match(%s) pattern=%s\n",i,symName.data(),pattern.data()); |
|
163 if (i!=-1) // wildcard match |
|
164 { |
|
165 int sl=symName.length(); |
|
166 // check if it is a whole word match |
|
167 if ((i==0 || pattern.at(0)=='*' || (!isId(symName.at(i-1)) && !forceStart)) && |
|
168 (i+pl==sl || pattern.at(i+pl)=='*' || (!isId(symName.at(i+pl)) && !forceEnd)) |
|
169 ) |
|
170 { |
|
171 //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); |
|
172 return TRUE; |
|
173 } |
|
174 } |
|
175 } |
|
176 else if (!pattern.isEmpty()) // match words |
|
177 { |
|
178 int i = symName.find(pattern); |
|
179 if (i!=-1) // we have a match! |
|
180 { |
|
181 int pl=pattern.length(); |
|
182 int sl=symName.length(); |
|
183 // check if it is a whole word match |
|
184 if ((i==0 || (!isId(symName.at(i-1)) && !forceStart)) && |
|
185 (i+pl==sl || (!isId(symName.at(i+pl)) && !forceEnd)) |
|
186 ) |
|
187 { |
|
188 //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); |
|
189 return TRUE; |
|
190 } |
|
191 } |
|
192 } |
|
193 pat = exclSyms.next(); |
|
194 } |
|
195 //printf("--> name=%s: no match\n",name); |
|
196 return FALSE; |
|
197 } |
|
198 |
|
199 void Definition::addToMap(const char *name,Definition *d) |
|
200 { |
|
201 bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); |
|
202 QCString symbolName = name; |
|
203 int index=computeQualifiedIndex(symbolName); |
|
204 if (!vhdlOpt && index!=-1) symbolName=symbolName.mid(index+2); |
|
205 if (!symbolName.isEmpty()) |
|
206 { |
|
207 //printf("******* adding symbol `%s' (%p)\n",symbolName.data(),d); |
|
208 DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); |
|
209 //printf(" addToMap(%p): looking for symbol %s: %p\n",d,symbolName.data(),di); |
|
210 if (di==0) // new Symbol |
|
211 { |
|
212 //printf(" new symbol!\n"); |
|
213 Doxygen::symbolMap->insert(symbolName,d); |
|
214 } |
|
215 else // existing symbol |
|
216 { |
|
217 //printf(" existing symbol: "); |
|
218 if (di->definitionType()==DefinitionIntf::TypeSymbolList) // already multiple symbols |
|
219 { |
|
220 //printf("adding to exiting list\n"); |
|
221 DefinitionList *dl = (DefinitionList*)di; |
|
222 dl->append(d); |
|
223 } |
|
224 else // going from one to two symbols |
|
225 { |
|
226 Doxygen::symbolMap->take(symbolName); |
|
227 DefinitionList *dl = new DefinitionList; |
|
228 //printf("replacing symbol by list %p with elements %p and %p\n",dl,di,d); |
|
229 dl->append((Definition*)di); |
|
230 dl->append(d); |
|
231 Doxygen::symbolMap->insert(symbolName,dl); |
|
232 } |
|
233 } |
|
234 |
|
235 // auto resize if needed |
|
236 static int sizeIndex=9; |
|
237 if (Doxygen::symbolMap->size()>SDict_primes[sizeIndex]) |
|
238 { |
|
239 Doxygen::symbolMap->resize(SDict_primes[++sizeIndex]); |
|
240 } |
|
241 |
|
242 d->_setSymbolName(symbolName); |
|
243 } |
|
244 } |
|
245 |
|
246 void Definition::removeFromMap(Definition *d) |
|
247 { |
|
248 QCString symbolName = d->symbolName(); |
|
249 int index=computeQualifiedIndex(symbolName); |
|
250 if (index!=-1) symbolName=symbolName.mid(index+2); |
|
251 if (!symbolName.isEmpty()) |
|
252 { |
|
253 //printf("******* removing symbol `%s' (%p)\n",symbolName.data(),d); |
|
254 DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); |
|
255 if (di) |
|
256 { |
|
257 ASSERT(di!=0); |
|
258 if (di!=d) // symbolName not unique |
|
259 { |
|
260 //printf(" removing from list: %p!\n",di); |
|
261 DefinitionList *dl = (DefinitionList*)di; |
|
262 bool b = dl->removeRef(d); |
|
263 ASSERT(b==TRUE); |
|
264 if (dl->isEmpty()) |
|
265 { |
|
266 Doxygen::symbolMap->take(symbolName); |
|
267 } |
|
268 } |
|
269 else // symbolName unique |
|
270 { |
|
271 //printf(" removing symbol %p\n",di); |
|
272 Doxygen::symbolMap->take(symbolName); |
|
273 } |
|
274 } |
|
275 } |
|
276 } |
|
277 |
|
278 Definition::Definition(const char *df,int dl, |
|
279 const char *name,const char *b, |
|
280 const char *d,bool isSymbol) |
|
281 { |
|
282 m_name = name; |
|
283 m_impl = new DefinitionImpl; |
|
284 m_impl->init(df,dl,name); |
|
285 m_isSymbol = isSymbol; |
|
286 if (isSymbol) addToMap(name,this); |
|
287 _setBriefDescription(b,df,dl); |
|
288 _setDocumentation(d,df,dl,TRUE,FALSE); |
|
289 if (matchExcludedSymbols(name)) |
|
290 { |
|
291 m_impl->hidden = TRUE; |
|
292 } |
|
293 } |
|
294 |
|
295 Definition::~Definition() |
|
296 { |
|
297 if (m_isSymbol) |
|
298 { |
|
299 removeFromMap(this); |
|
300 } |
|
301 if (m_impl) |
|
302 { |
|
303 delete m_impl; |
|
304 m_impl=0; |
|
305 } |
|
306 } |
|
307 |
|
308 void Definition::setName(const char *name) |
|
309 { |
|
310 if (name==0) return; |
|
311 m_name = name; |
|
312 } |
|
313 |
|
314 void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList) |
|
315 { |
|
316 if (!anchorList) return; |
|
317 makeResident(); |
|
318 //printf("%s: addSectionsToDefinition(%d)\n",name().data(),anchorList->count()); |
|
319 SectionInfo *si=anchorList->first(); |
|
320 while (si) |
|
321 { |
|
322 //printf("Add section `%s' to definition `%s'\n", |
|
323 // si->label.data(),name().data()); |
|
324 SectionInfo *gsi=Doxygen::sectionDict.find(si->label); |
|
325 if (gsi==0) |
|
326 { |
|
327 gsi = new SectionInfo(*si); |
|
328 Doxygen::sectionDict.insert(si->label,gsi); |
|
329 } |
|
330 if (m_impl->sectionDict==0) |
|
331 { |
|
332 m_impl->sectionDict = new SectionDict(17); |
|
333 } |
|
334 if (m_impl->sectionDict->find(gsi->label)==0) |
|
335 { |
|
336 m_impl->sectionDict->insert(gsi->label,gsi); |
|
337 gsi->definition = this; |
|
338 } |
|
339 si=anchorList->next(); |
|
340 } |
|
341 } |
|
342 |
|
343 void Definition::writeDocAnchorsToTagFile() |
|
344 { |
|
345 makeResident(); |
|
346 if (!Config_getString("GENERATE_TAGFILE").isEmpty() && m_impl->sectionDict) |
|
347 { |
|
348 //printf("%s: writeDocAnchorsToTagFile(%d)\n",name().data(),m_sectionDict->count()); |
|
349 QDictIterator<SectionInfo> sdi(*m_impl->sectionDict); |
|
350 SectionInfo *si; |
|
351 for (;(si=sdi.current());++sdi) |
|
352 { |
|
353 if (!si->generated) |
|
354 { |
|
355 //printf("write an entry!\n"); |
|
356 if (definitionType()==TypeMember) Doxygen::tagFile << " "; |
|
357 Doxygen::tagFile << " <docanchor file=\"" |
|
358 << si->fileName << "\">" << si->label |
|
359 << "</docanchor>" << endl; |
|
360 } |
|
361 } |
|
362 } |
|
363 } |
|
364 |
|
365 bool Definition::_docsAlreadyAdded(const QCString &doc) |
|
366 { |
|
367 uchar md5_sig[16]; |
|
368 QCString sigStr(33); |
|
369 // to avoid mismatches due to differences in indenting, we first remove |
|
370 // double whitespaces... |
|
371 QCString docStr = doc.simplifyWhiteSpace(); |
|
372 MD5Buffer((const unsigned char *)docStr.data(),docStr.length(),md5_sig); |
|
373 MD5SigToString(md5_sig,sigStr.data(),33); |
|
374 if (m_impl->docSignatures.find(sigStr)==-1) // new docs, add signature to prevent re-adding it |
|
375 { |
|
376 m_impl->docSignatures+=":"+sigStr; |
|
377 return FALSE; |
|
378 } |
|
379 else |
|
380 { |
|
381 return TRUE; |
|
382 } |
|
383 } |
|
384 |
|
385 void Definition::_setDocumentation(const char *d,const char *docFile,int docLine, |
|
386 bool stripWhiteSpace,bool atTop) |
|
387 { |
|
388 if (d==0) return; |
|
389 //printf("Definition::setDocumentation(%s,%s,%d,%d)\n",d,docFile,docLine,stripWhiteSpace); |
|
390 QCString doc = d; |
|
391 if (stripWhiteSpace) |
|
392 { |
|
393 doc = stripLeadingAndTrailingEmptyLines(doc); |
|
394 } |
|
395 else // don't strip whitespace |
|
396 { |
|
397 doc=d; |
|
398 } |
|
399 if (!_docsAlreadyAdded(doc)) |
|
400 { |
|
401 //printf("setting docs for %s: `%s'\n",name().data(),m_doc.data()); |
|
402 if (m_impl->details==0) |
|
403 { |
|
404 m_impl->details = new DocInfo; |
|
405 } |
|
406 if (m_impl->details->doc.isEmpty()) // fresh detailed description |
|
407 { |
|
408 m_impl->details->doc = doc; |
|
409 } |
|
410 else if (atTop) // another detailed description, append it to the start |
|
411 { |
|
412 m_impl->details->doc = doc+"\n\n"+m_impl->details->doc; |
|
413 } |
|
414 else // another detailed description, append it to the end |
|
415 { |
|
416 m_impl->details->doc += "\n\n"+doc; |
|
417 } |
|
418 if (docLine!=-1) // store location if valid |
|
419 { |
|
420 m_impl->details->file = docFile; |
|
421 m_impl->details->line = docLine; |
|
422 } |
|
423 else |
|
424 { |
|
425 m_impl->details->file = docFile; |
|
426 m_impl->details->line = 1; |
|
427 } |
|
428 } |
|
429 } |
|
430 |
|
431 void Definition::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace) |
|
432 { |
|
433 if (d==0) return; |
|
434 makeResident(); |
|
435 _setDocumentation(d,docFile,docLine,stripWhiteSpace,FALSE); |
|
436 } |
|
437 |
|
438 #define uni_isupper(c) (QChar(c).category()==QChar::Letter_Uppercase) |
|
439 |
|
440 void Definition::_setBriefDescription(const char *b,const char *briefFile,int briefLine) |
|
441 { |
|
442 static QCString outputLanguage = Config_getEnum("OUTPUT_LANGUAGE"); |
|
443 static bool needsDot = outputLanguage!="Japanese" && |
|
444 outputLanguage!="Chinese" && |
|
445 outputLanguage!="Korean"; |
|
446 QCString brief = b; |
|
447 brief = brief.stripWhiteSpace(); |
|
448 if (brief.isEmpty()) return; |
|
449 int bl = brief.length(); |
|
450 if (bl>0 && needsDot) // add punctuation if needed |
|
451 { |
|
452 switch(brief.at(bl-1)) |
|
453 { |
|
454 case '.': case '!': case '?': break; |
|
455 default: |
|
456 if (uni_isupper(brief.at(0))) brief+='.'; |
|
457 break; |
|
458 } |
|
459 } |
|
460 |
|
461 if (m_impl->brief && !m_impl->brief->doc.isEmpty()) |
|
462 { |
|
463 //printf("adding to details\n"); |
|
464 _setDocumentation(brief,briefFile,briefLine,FALSE,TRUE); |
|
465 } |
|
466 else if (!_docsAlreadyAdded(brief)) |
|
467 { |
|
468 //fprintf(stderr,"Definition::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine); |
|
469 if (m_impl->brief==0) |
|
470 { |
|
471 m_impl->brief = new BriefInfo; |
|
472 } |
|
473 m_impl->brief->doc=brief; |
|
474 if (briefLine!=-1) |
|
475 { |
|
476 m_impl->brief->file = briefFile; |
|
477 m_impl->brief->line = briefLine; |
|
478 } |
|
479 } |
|
480 } |
|
481 |
|
482 void Definition::setBriefDescription(const char *b,const char *briefFile,int briefLine) |
|
483 { |
|
484 if (b==0) return; |
|
485 makeResident(); |
|
486 _setBriefDescription(b,briefFile,briefLine); |
|
487 } |
|
488 |
|
489 void Definition::_setInbodyDocumentation(const char *doc,const char *inbodyFile,int inbodyLine) |
|
490 { |
|
491 if (m_impl->inbodyDocs==0) |
|
492 { |
|
493 m_impl->inbodyDocs = new DocInfo; |
|
494 } |
|
495 if (m_impl->inbodyDocs->doc.isEmpty()) // fresh inbody docs |
|
496 { |
|
497 m_impl->inbodyDocs->doc = doc; |
|
498 m_impl->inbodyDocs->file = inbodyFile; |
|
499 m_impl->inbodyDocs->line = inbodyLine; |
|
500 } |
|
501 else // another inbody documentation fragment, append this to the end |
|
502 { |
|
503 m_impl->inbodyDocs->doc += QCString("\n\n")+doc; |
|
504 } |
|
505 } |
|
506 |
|
507 void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine) |
|
508 { |
|
509 if (d==0) return; |
|
510 makeResident(); |
|
511 _setInbodyDocumentation(d,inbodyFile,inbodyLine); |
|
512 } |
|
513 |
|
514 /*! Reads a fragment of code from file \a fileName starting at |
|
515 * line \a startLine and ending at line \a endLine (inclusive). The fragment is |
|
516 * stored in \a result. If FALSE is returned the code fragment could not be |
|
517 * found. |
|
518 * |
|
519 * The file is scanned for a opening bracket ('{') from \a startLine onward |
|
520 * The line actually containing the bracket is returned via startLine. |
|
521 * The file is scanned for a closing bracket ('}') from \a endLine backward. |
|
522 * The line actually containing the bracket is returned via endLine. |
|
523 * Note that for VHDL code the bracket search is not done. |
|
524 */ |
|
525 static bool readCodeFragment(const char *fileName, |
|
526 int &startLine,int &endLine,QCString &result) |
|
527 { |
|
528 static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); |
|
529 static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); |
|
530 //printf("readCodeFragment(%s,%d,%d)\n",fileName,startLine,endLine); |
|
531 if (fileName==0 || fileName[0]==0) return FALSE; // not a valid file name |
|
532 QCString filter = getFileFilter(fileName); |
|
533 FILE *f=0; |
|
534 bool usePipe = !filter.isEmpty() && filterSourceFiles; |
|
535 if (!usePipe) // no filter given or wanted |
|
536 { |
|
537 f = fopen(fileName,"r"); |
|
538 } |
|
539 else // use filter |
|
540 { |
|
541 QCString cmd=filter+" \""+fileName+"\""; |
|
542 Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data()); |
|
543 f = portable_popen(cmd,"r"); |
|
544 } |
|
545 bool found=vhdlOpt; // for VHDL no bracket search is possible |
|
546 if (f) |
|
547 { |
|
548 int c=0; |
|
549 int col=0; |
|
550 int lineNr=1; |
|
551 // skip until the startLine has reached |
|
552 while (lineNr<startLine && !feof(f)) |
|
553 { |
|
554 while ((c=fgetc(f))!='\n' && c!=EOF) /* skip */; |
|
555 lineNr++; |
|
556 } |
|
557 if (!feof(f)) |
|
558 { |
|
559 // skip until the opening bracket or lonely : is found |
|
560 char cn=0; |
|
561 while (lineNr<=endLine && !feof(f) && !found) |
|
562 { |
|
563 while ((c=fgetc(f))!='{' && c!=':' && c!=EOF) |
|
564 { |
|
565 //printf("parsing char `%c'\n",c); |
|
566 if (c=='\n') |
|
567 { |
|
568 lineNr++,col=0; |
|
569 } |
|
570 else if (c=='\t') |
|
571 { |
|
572 col+=Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE")); |
|
573 } |
|
574 else |
|
575 { |
|
576 col++; |
|
577 } |
|
578 } |
|
579 if (c==':') |
|
580 { |
|
581 cn=fgetc(f); |
|
582 if (cn!=':') found=TRUE; |
|
583 } |
|
584 else if (c=='{') |
|
585 { |
|
586 found=TRUE; |
|
587 } |
|
588 } |
|
589 //printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr); |
|
590 if (found) |
|
591 { |
|
592 // For code with more than one line, |
|
593 // fill the line with spaces until we are at the right column |
|
594 // so that the opening brace lines up with the closing brace |
|
595 if (endLine!=startLine) |
|
596 { |
|
597 QCString spaces; |
|
598 spaces.fill(' ',col); |
|
599 result+=spaces; |
|
600 } |
|
601 // copy until end of line |
|
602 result+=c; |
|
603 if (c==':') |
|
604 { |
|
605 result+=cn; |
|
606 if (cn=='\n') lineNr++; |
|
607 } |
|
608 startLine=lineNr; |
|
609 const int maxLineLength=4096; |
|
610 char lineStr[maxLineLength]; |
|
611 do |
|
612 { |
|
613 //printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine); |
|
614 int size_read; |
|
615 do |
|
616 { |
|
617 // read up to maxLineLength-1 bytes, the last byte being zero |
|
618 char *p = fgets(lineStr, maxLineLength,f); |
|
619 //printf(" read %s",p); |
|
620 if (p) |
|
621 { |
|
622 size_read=qstrlen(p); |
|
623 } |
|
624 else // nothing read |
|
625 { |
|
626 size_read=-1; |
|
627 lineStr[0]='\0'; |
|
628 } |
|
629 result+=lineStr; |
|
630 } while (size_read == (maxLineLength-1)); |
|
631 |
|
632 lineNr++; |
|
633 } while (lineNr<=endLine && !feof(f)); |
|
634 |
|
635 // strip stuff after closing bracket |
|
636 int newLineIndex = result.findRev('\n'); |
|
637 int braceIndex = result.findRev('}'); |
|
638 if (braceIndex > newLineIndex) |
|
639 { |
|
640 result.truncate(braceIndex+1); |
|
641 } |
|
642 endLine=lineNr-1; |
|
643 } |
|
644 } |
|
645 if (usePipe) |
|
646 { |
|
647 portable_pclose(f); |
|
648 } |
|
649 else |
|
650 { |
|
651 fclose(f); |
|
652 } |
|
653 } |
|
654 result = transcodeCharacterStringToUTF8(result); |
|
655 return found; |
|
656 } |
|
657 |
|
658 /*! Write a reference to the source code defining this definition */ |
|
659 void Definition::writeSourceDef(OutputList &ol,const char *) |
|
660 { |
|
661 static bool sourceBrowser = Config_getBool("SOURCE_BROWSER"); |
|
662 static bool latexSourceCode = Config_getBool("LATEX_SOURCE_CODE"); |
|
663 makeResident(); |
|
664 ol.pushGeneratorState(); |
|
665 //printf("Definition::writeSourceRef %d %p\n",bodyLine,bodyDef); |
|
666 if (sourceBrowser && |
|
667 m_impl->body && m_impl->body->startLine!=-1 && m_impl->body->fileDef) |
|
668 { |
|
669 QCString refText = theTranslator->trDefinedAtLineInSourceFile(); |
|
670 int lineMarkerPos = refText.find("@0"); |
|
671 int fileMarkerPos = refText.find("@1"); |
|
672 if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this. |
|
673 { |
|
674 QCString lineStr,anchorStr; |
|
675 lineStr.sprintf("%d",m_impl->body->startLine); |
|
676 anchorStr.sprintf(Htags::useHtags ? "L%d" : "l%05d",m_impl->body->startLine); |
|
677 ol.startParagraph(); |
|
678 if (lineMarkerPos<fileMarkerPos) // line marker before file marker |
|
679 { |
|
680 // write text left from linePos marker |
|
681 ol.parseText(refText.left(lineMarkerPos)); |
|
682 ol.pushGeneratorState(); |
|
683 ol.disable(OutputGenerator::RTF); |
|
684 ol.disable(OutputGenerator::Man); |
|
685 if (!latexSourceCode) |
|
686 { |
|
687 ol.disable(OutputGenerator::Latex); |
|
688 } |
|
689 // write line link (HTML, LaTeX optionally) |
|
690 ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(), |
|
691 anchorStr,lineStr); |
|
692 ol.enableAll(); |
|
693 ol.disable(OutputGenerator::Html); |
|
694 if (latexSourceCode) |
|
695 { |
|
696 ol.disable(OutputGenerator::Latex); |
|
697 } |
|
698 // write normal text (Man/RTF, Latex optionally) |
|
699 ol.docify(lineStr); |
|
700 ol.popGeneratorState(); |
|
701 |
|
702 // write text between markers |
|
703 ol.parseText(refText.mid(lineMarkerPos+2, |
|
704 fileMarkerPos-lineMarkerPos-2)); |
|
705 |
|
706 ol.pushGeneratorState(); |
|
707 ol.disable(OutputGenerator::RTF); |
|
708 ol.disable(OutputGenerator::Man); |
|
709 if (!latexSourceCode) |
|
710 { |
|
711 ol.disable(OutputGenerator::Latex); |
|
712 } |
|
713 // write line link (HTML, LaTeX optionally) |
|
714 ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(), |
|
715 0,m_impl->body->fileDef->name()); |
|
716 ol.enableAll(); |
|
717 ol.disable(OutputGenerator::Html); |
|
718 if (latexSourceCode) |
|
719 { |
|
720 ol.disable(OutputGenerator::Latex); |
|
721 } |
|
722 // write normal text (Man/RTF, Latex optionally) |
|
723 ol.docify(m_impl->body->fileDef->name()); |
|
724 ol.popGeneratorState(); |
|
725 |
|
726 // write text right from file marker |
|
727 ol.parseText(refText.right( |
|
728 refText.length()-fileMarkerPos-2)); |
|
729 } |
|
730 else // file marker before line marker |
|
731 { |
|
732 // write text left from file marker |
|
733 ol.parseText(refText.left(fileMarkerPos)); |
|
734 ol.pushGeneratorState(); |
|
735 ol.disable(OutputGenerator::RTF); |
|
736 ol.disable(OutputGenerator::Man); |
|
737 if (!latexSourceCode) |
|
738 { |
|
739 ol.disable(OutputGenerator::Latex); |
|
740 } |
|
741 // write file link (HTML only) |
|
742 ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(), |
|
743 0,m_impl->body->fileDef->name()); |
|
744 ol.enableAll(); |
|
745 ol.disable(OutputGenerator::Html); |
|
746 if (latexSourceCode) |
|
747 { |
|
748 ol.disable(OutputGenerator::Latex); |
|
749 } |
|
750 // write normal text (Latex/Man only) |
|
751 ol.docify(m_impl->body->fileDef->name()); |
|
752 ol.popGeneratorState(); |
|
753 |
|
754 // write text between markers |
|
755 ol.parseText(refText.mid(fileMarkerPos+2, |
|
756 lineMarkerPos-fileMarkerPos-2)); |
|
757 |
|
758 ol.pushGeneratorState(); |
|
759 ol.disable(OutputGenerator::RTF); |
|
760 ol.disable(OutputGenerator::Man); |
|
761 if (!latexSourceCode) |
|
762 { |
|
763 ol.disable(OutputGenerator::Latex); |
|
764 } |
|
765 ol.disableAllBut(OutputGenerator::Html); |
|
766 // write line link (HTML only) |
|
767 ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(), |
|
768 anchorStr,lineStr); |
|
769 ol.enableAll(); |
|
770 ol.disable(OutputGenerator::Html); |
|
771 if (latexSourceCode) |
|
772 { |
|
773 ol.disable(OutputGenerator::Latex); |
|
774 } |
|
775 // write normal text (Latex/Man only) |
|
776 ol.docify(lineStr); |
|
777 ol.popGeneratorState(); |
|
778 |
|
779 // write text right from linePos marker |
|
780 ol.parseText(refText.right( |
|
781 refText.length()-lineMarkerPos-2)); |
|
782 } |
|
783 ol.endParagraph(); |
|
784 } |
|
785 else |
|
786 { |
|
787 err("Error: translation error: invalid markers in trDefinedInSourceFile()\n"); |
|
788 } |
|
789 } |
|
790 ol.popGeneratorState(); |
|
791 } |
|
792 |
|
793 void Definition::setBodySegment(int bls,int ble) |
|
794 { |
|
795 makeResident(); |
|
796 //printf("setBodySegment(%d,%d) for %s\n",bls,ble,name().data()); |
|
797 if (m_impl->body==0) m_impl->body = new BodyInfo; |
|
798 m_impl->body->startLine=bls; |
|
799 m_impl->body->endLine=ble; |
|
800 } |
|
801 |
|
802 void Definition::setBodyDef(FileDef *fd) |
|
803 { |
|
804 makeResident(); |
|
805 if (m_impl->body==0) m_impl->body = new BodyInfo; |
|
806 m_impl->body->fileDef=fd; |
|
807 } |
|
808 |
|
809 /*! Write code of this definition into the documentation */ |
|
810 void Definition::writeInlineCode(OutputList &ol,const char *scopeName) |
|
811 { |
|
812 makeResident(); |
|
813 ol.pushGeneratorState(); |
|
814 //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(), |
|
815 // m_startBodyLine,m_endBodyLine,m_bodyDef); |
|
816 if (Config_getBool("INLINE_SOURCES") && |
|
817 m_impl->body && m_impl->body->startLine!=-1 && |
|
818 m_impl->body->endLine>=m_impl->body->startLine && m_impl->body->fileDef) |
|
819 { |
|
820 QCString codeFragment; |
|
821 int actualStart=m_impl->body->startLine,actualEnd=m_impl->body->endLine; |
|
822 if (readCodeFragment(m_impl->body->fileDef->absFilePath(), |
|
823 actualStart,actualEnd,codeFragment) |
|
824 ) |
|
825 { |
|
826 //printf("Adding code fragement '%s' ext='%s'\n", |
|
827 // codeFragment.data(),m_impl->defFileExt.data()); |
|
828 ParserInterface *pIntf = Doxygen::parserManager->getParser(m_impl->defFileExt); |
|
829 pIntf->resetCodeParserState(); |
|
830 //printf("Read:\n`%s'\n\n",codeFragment.data()); |
|
831 MemberDef *thisMd = 0; |
|
832 if (definitionType()==TypeMember) thisMd = (MemberDef *)this; |
|
833 ol.startParagraph(); |
|
834 ol.startCodeFragment(); |
|
835 pIntf->parseCode(ol, // codeOutIntf |
|
836 scopeName, // scope |
|
837 codeFragment, // input |
|
838 FALSE, // isExample |
|
839 0, // exampleName |
|
840 m_impl->body->fileDef, // fileDef |
|
841 actualStart, // startLine |
|
842 actualEnd, // endLine |
|
843 TRUE, // inlineFragment |
|
844 thisMd // memberDef |
|
845 ); |
|
846 ol.endCodeFragment(); |
|
847 ol.endParagraph(); |
|
848 } |
|
849 } |
|
850 ol.popGeneratorState(); |
|
851 } |
|
852 |
|
853 /*! Write a reference to the source code fragments in which this |
|
854 * definition is used. |
|
855 */ |
|
856 void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, |
|
857 const QCString &text,MemberSDict *members,bool /*funcOnly*/) |
|
858 { |
|
859 static bool latexSourceCode = Config_getBool("LATEX_SOURCE_CODE"); |
|
860 ol.pushGeneratorState(); |
|
861 if (/*Config_getBool("SOURCE_BROWSER") &&*/ members) |
|
862 { |
|
863 ol.startParagraph(); |
|
864 ol.parseText(text); |
|
865 ol.docify(" "); |
|
866 |
|
867 QCString ldefLine=theTranslator->trWriteList(members->count()); |
|
868 |
|
869 QRegExp marker("@[0-9]+"); |
|
870 int index=0,newIndex,matchLen; |
|
871 // now replace all markers in inheritLine with links to the classes |
|
872 while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1) |
|
873 { |
|
874 bool ok; |
|
875 ol.parseText(ldefLine.mid(index,newIndex-index)); |
|
876 uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); |
|
877 MemberDef *md=members->at(entryIndex); |
|
878 if (ok && md) |
|
879 { |
|
880 QCString scope=md->getScopeString(); |
|
881 QCString name=md->name(); |
|
882 //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName); |
|
883 if (!scope.isEmpty() && scope!=scopeName) |
|
884 { |
|
885 if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) |
|
886 { |
|
887 name.prepend(scope+"."); |
|
888 } |
|
889 else |
|
890 { |
|
891 name.prepend(scope+"::"); |
|
892 } |
|
893 } |
|
894 if (!md->isObjCMethod() && |
|
895 (md->isFunction() || md->isSlot() || |
|
896 md->isPrototype() || md->isSignal() |
|
897 ) |
|
898 ) name+="()"; |
|
899 //Definition *d = md->getOutputFileBase(); |
|
900 //if (d==Doxygen::globalScope) d=md->getBodyDef(); |
|
901 if (!(md->isLinkable() && !Config_getBool("REFERENCES_LINK_SOURCE")) && md->getStartBodyLine()!=-1 && md->getBodyDef()) |
|
902 { |
|
903 //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); |
|
904 // for HTML write a real link |
|
905 ol.pushGeneratorState(); |
|
906 //ol.disableAllBut(OutputGenerator::Html); |
|
907 |
|
908 ol.disable(OutputGenerator::RTF); |
|
909 ol.disable(OutputGenerator::Man); |
|
910 if (!latexSourceCode) |
|
911 { |
|
912 ol.disable(OutputGenerator::Latex); |
|
913 } |
|
914 QCString lineStr,anchorStr; |
|
915 anchorStr.sprintf("l%05d",md->getStartBodyLine()); |
|
916 //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data()); |
|
917 ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name); |
|
918 ol.popGeneratorState(); |
|
919 |
|
920 // for the other output formats just mention the name |
|
921 ol.pushGeneratorState(); |
|
922 ol.disable(OutputGenerator::Html); |
|
923 if (latexSourceCode) |
|
924 { |
|
925 ol.disable(OutputGenerator::Latex); |
|
926 } |
|
927 ol.docify(name); |
|
928 ol.popGeneratorState(); |
|
929 } |
|
930 else if (md->isLinkable() /*&& d && d->isLinkable()*/) |
|
931 { |
|
932 // for HTML write a real link |
|
933 ol.pushGeneratorState(); |
|
934 //ol.disableAllBut(OutputGenerator::Html); |
|
935 ol.disable(OutputGenerator::RTF); |
|
936 ol.disable(OutputGenerator::Man); |
|
937 if (!latexSourceCode) |
|
938 { |
|
939 ol.disable(OutputGenerator::Latex); |
|
940 } |
|
941 |
|
942 ol.writeObjectLink(md->getReference(), |
|
943 md->getOutputFileBase(), |
|
944 md->anchor(),name); |
|
945 ol.popGeneratorState(); |
|
946 |
|
947 // for the other output formats just mention the name |
|
948 ol.pushGeneratorState(); |
|
949 ol.disable(OutputGenerator::Html); |
|
950 if (latexSourceCode) |
|
951 { |
|
952 ol.disable(OutputGenerator::Latex); |
|
953 } |
|
954 ol.docify(name); |
|
955 ol.popGeneratorState(); |
|
956 } |
|
957 else |
|
958 { |
|
959 ol.docify(name); |
|
960 } |
|
961 } |
|
962 index=newIndex+matchLen; |
|
963 } |
|
964 ol.parseText(ldefLine.right(ldefLine.length()-index)); |
|
965 ol.writeString("."); |
|
966 ol.endParagraph(); |
|
967 } |
|
968 ol.popGeneratorState(); |
|
969 } |
|
970 |
|
971 void Definition::writeSourceReffedBy(OutputList &ol,const char *scopeName) |
|
972 { |
|
973 makeResident(); |
|
974 if (Config_getBool("REFERENCED_BY_RELATION")) |
|
975 { |
|
976 _writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),m_impl->sourceRefByDict,FALSE); |
|
977 } |
|
978 } |
|
979 |
|
980 void Definition::writeSourceRefs(OutputList &ol,const char *scopeName) |
|
981 { |
|
982 makeResident(); |
|
983 if (Config_getBool("REFERENCES_RELATION")) |
|
984 { |
|
985 _writeSourceRefList(ol,scopeName,theTranslator->trReferences(),m_impl->sourceRefsDict,TRUE); |
|
986 } |
|
987 } |
|
988 |
|
989 bool Definition::hasDocumentation() const |
|
990 { |
|
991 static bool extractAll = Config_getBool("EXTRACT_ALL"); |
|
992 //static bool sourceBrowser = Config_getBool("SOURCE_BROWSER"); |
|
993 makeResident(); |
|
994 bool hasDocs = |
|
995 (m_impl->details && !m_impl->details->doc.isEmpty()) || // has detailed docs |
|
996 (m_impl->brief && !m_impl->brief->doc.isEmpty()) || // has brief description |
|
997 (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty()) || // has inbody docs |
|
998 extractAll //|| // extract everything |
|
999 // (sourceBrowser && m_impl->body && |
|
1000 // m_impl->body->startLine!=-1 && m_impl->body->fileDef) |
|
1001 ; // link to definition |
|
1002 return hasDocs; |
|
1003 } |
|
1004 |
|
1005 bool Definition::hasUserDocumentation() const |
|
1006 { |
|
1007 makeResident(); |
|
1008 bool hasDocs = |
|
1009 (m_impl->details && !m_impl->details->doc.isEmpty()) || |
|
1010 (m_impl->brief && !m_impl->brief->doc.isEmpty()) || |
|
1011 (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty()); |
|
1012 return hasDocs; |
|
1013 } |
|
1014 |
|
1015 void Definition::addSourceReferencedBy(MemberDef *md) |
|
1016 { |
|
1017 if (md) |
|
1018 { |
|
1019 makeResident(); |
|
1020 QCString name = md->name(); |
|
1021 QCString scope = md->getScopeString(); |
|
1022 |
|
1023 if (!scope.isEmpty()) |
|
1024 { |
|
1025 name.prepend(scope+"::"); |
|
1026 } |
|
1027 |
|
1028 if (m_impl->sourceRefByDict==0) |
|
1029 { |
|
1030 m_impl->sourceRefByDict = new MemberSDict; |
|
1031 } |
|
1032 if (m_impl->sourceRefByDict->find(name)==0) |
|
1033 { |
|
1034 m_impl->sourceRefByDict->inSort(name,md); |
|
1035 } |
|
1036 } |
|
1037 } |
|
1038 |
|
1039 void Definition::addSourceReferences(MemberDef *md) |
|
1040 { |
|
1041 if (md) |
|
1042 { |
|
1043 QCString name = md->name(); |
|
1044 QCString scope = md->getScopeString(); |
|
1045 makeResident(); |
|
1046 |
|
1047 if (!scope.isEmpty()) |
|
1048 { |
|
1049 name.prepend(scope+"::"); |
|
1050 } |
|
1051 |
|
1052 if (m_impl->sourceRefsDict==0) |
|
1053 { |
|
1054 m_impl->sourceRefsDict = new MemberSDict; |
|
1055 } |
|
1056 if (m_impl->sourceRefsDict->find(name)==0) |
|
1057 { |
|
1058 m_impl->sourceRefsDict->inSort(name,md); |
|
1059 } |
|
1060 } |
|
1061 } |
|
1062 |
|
1063 Definition *Definition::findInnerCompound(const char *) |
|
1064 { |
|
1065 return 0; |
|
1066 } |
|
1067 |
|
1068 void Definition::addInnerCompound(Definition *) |
|
1069 { |
|
1070 err("Error: Definition::addInnerCompound() called\n"); |
|
1071 } |
|
1072 |
|
1073 QCString Definition::qualifiedName() const |
|
1074 { |
|
1075 static int count=0; |
|
1076 count++; |
|
1077 makeResident(); |
|
1078 if (!m_impl->qualifiedName.isEmpty()) |
|
1079 { |
|
1080 count--; |
|
1081 return m_impl->qualifiedName; |
|
1082 } |
|
1083 #if 0 |
|
1084 if (count>20) |
|
1085 { |
|
1086 printf("Definition::qualifiedName() Infinite recursion detected! Type=%d\n",definitionType()); |
|
1087 printf("Trace:\n"); |
|
1088 Definition *d = (Definition *)this; |
|
1089 for (int i=0;d && i<20;i++) |
|
1090 { |
|
1091 printf(" %s\n",d->name().data()); |
|
1092 d = d->getOuterScope(); |
|
1093 } |
|
1094 } |
|
1095 #endif |
|
1096 |
|
1097 //printf("start %s::qualifiedName() localName=%s\n",name().data(),m_impl->localName.data()); |
|
1098 if (m_impl->outerScope==0) |
|
1099 { |
|
1100 if (m_impl->localName=="<globalScope>") |
|
1101 { |
|
1102 count--; |
|
1103 return ""; |
|
1104 } |
|
1105 else |
|
1106 { |
|
1107 count--; |
|
1108 return m_impl->localName; |
|
1109 } |
|
1110 } |
|
1111 |
|
1112 if (m_impl->outerScope->name()=="<globalScope>") |
|
1113 { |
|
1114 m_impl->qualifiedName = m_impl->localName; |
|
1115 } |
|
1116 else |
|
1117 { |
|
1118 m_impl->qualifiedName = m_impl->outerScope->qualifiedName()+"::"+m_impl->localName; |
|
1119 } |
|
1120 //printf("end %s::qualifiedName()=%s\n",name().data(),m_impl->qualifiedName.data()); |
|
1121 count--; |
|
1122 return m_impl->qualifiedName; |
|
1123 }; |
|
1124 |
|
1125 void Definition::setOuterScope(Definition *d) |
|
1126 { |
|
1127 makeResident(); |
|
1128 if (m_impl->outerScope!=d) |
|
1129 { |
|
1130 m_impl->qualifiedName.resize(0); // flush cached scope name |
|
1131 m_impl->outerScope = d; |
|
1132 } |
|
1133 m_impl->hidden = m_impl->hidden || d->isHidden(); |
|
1134 } |
|
1135 |
|
1136 QCString Definition::localName() const |
|
1137 { |
|
1138 makeResident(); |
|
1139 return m_impl->localName; |
|
1140 } |
|
1141 |
|
1142 void Definition::makePartOfGroup(GroupDef *gd) |
|
1143 { |
|
1144 makeResident(); |
|
1145 if (m_impl->partOfGroups==0) m_impl->partOfGroups = new GroupList; |
|
1146 m_impl->partOfGroups->append(gd); |
|
1147 } |
|
1148 |
|
1149 void Definition::setRefItems(const QList<ListItemInfo> *sli) |
|
1150 { |
|
1151 if (sli) |
|
1152 { |
|
1153 makeResident(); |
|
1154 // deep copy the list |
|
1155 if (m_impl->xrefListItems==0) |
|
1156 { |
|
1157 m_impl->xrefListItems=new QList<ListItemInfo>; |
|
1158 m_impl->xrefListItems->setAutoDelete(TRUE); |
|
1159 } |
|
1160 QListIterator<ListItemInfo> slii(*sli); |
|
1161 ListItemInfo *lii; |
|
1162 for (slii.toFirst();(lii=slii.current());++slii) |
|
1163 { |
|
1164 m_impl->xrefListItems->append(new ListItemInfo(*lii)); |
|
1165 } |
|
1166 } |
|
1167 } |
|
1168 |
|
1169 void Definition::mergeRefItems(Definition *d) |
|
1170 { |
|
1171 LockingPtr< QList<ListItemInfo> > xrefList = d->xrefListItems(); |
|
1172 if (xrefList!=0) |
|
1173 { |
|
1174 makeResident(); |
|
1175 // deep copy the list |
|
1176 if (m_impl->xrefListItems==0) |
|
1177 { |
|
1178 m_impl->xrefListItems=new QList<ListItemInfo>; |
|
1179 m_impl->xrefListItems->setAutoDelete(TRUE); |
|
1180 } |
|
1181 QListIterator<ListItemInfo> slii(*xrefList); |
|
1182 ListItemInfo *lii; |
|
1183 for (slii.toFirst();(lii=slii.current());++slii) |
|
1184 { |
|
1185 if (_getXRefListId(lii->type)==-1) |
|
1186 { |
|
1187 m_impl->xrefListItems->append(new ListItemInfo(*lii)); |
|
1188 } |
|
1189 } |
|
1190 } |
|
1191 } |
|
1192 |
|
1193 int Definition::_getXRefListId(const char *listName) const |
|
1194 { |
|
1195 makeResident(); |
|
1196 if (m_impl->xrefListItems) |
|
1197 { |
|
1198 QListIterator<ListItemInfo> slii(*m_impl->xrefListItems); |
|
1199 ListItemInfo *lii; |
|
1200 for (slii.toFirst();(lii=slii.current());++slii) |
|
1201 { |
|
1202 if (strcmp(lii->type,listName)==0) |
|
1203 { |
|
1204 return lii->itemId; |
|
1205 } |
|
1206 } |
|
1207 } |
|
1208 return -1; |
|
1209 } |
|
1210 |
|
1211 LockingPtr< QList<ListItemInfo> > Definition::xrefListItems() const |
|
1212 { |
|
1213 makeResident(); |
|
1214 return LockingPtr< QList<ListItemInfo> >(this,m_impl->xrefListItems); |
|
1215 } |
|
1216 |
|
1217 |
|
1218 QCString Definition::convertNameToFile(const char *name,bool allowDots) const |
|
1219 { |
|
1220 makeResident(); |
|
1221 if (!m_impl->ref.isEmpty()) |
|
1222 { |
|
1223 return name; |
|
1224 } |
|
1225 else |
|
1226 { |
|
1227 return ::convertNameToFile(name,allowDots); |
|
1228 } |
|
1229 } |
|
1230 |
|
1231 void Definition::writePathFragment(OutputList &ol) const |
|
1232 { |
|
1233 makeResident(); |
|
1234 if (m_impl->outerScope && m_impl->outerScope!=Doxygen::globalScope) |
|
1235 { |
|
1236 m_impl->outerScope->writePathFragment(ol); |
|
1237 if (m_impl->outerScope->definitionType()==Definition::TypeClass || |
|
1238 m_impl->outerScope->definitionType()==Definition::TypeNamespace) |
|
1239 { |
|
1240 if (Config_getBool("OPTIMIZE_OUTPUT_JAVA") || |
|
1241 Config_getBool("OPTIMIZE_OUTPUT_VHDL") |
|
1242 ) |
|
1243 { |
|
1244 ol.writeString("."); |
|
1245 } |
|
1246 else |
|
1247 { |
|
1248 ol.writeString("::"); |
|
1249 } |
|
1250 } |
|
1251 else |
|
1252 { |
|
1253 ol.writeString(" "); |
|
1254 ol.writeString("»"); |
|
1255 ol.writeString(" "); |
|
1256 } |
|
1257 } |
|
1258 if (isLinkable()) |
|
1259 { |
|
1260 if (definitionType()==Definition::TypeGroup && ((const GroupDef*)this)->groupTitle()) |
|
1261 { |
|
1262 ol.writeObjectLink(getReference(),getOutputFileBase(),0,((const GroupDef*)this)->groupTitle()); |
|
1263 } |
|
1264 else if (definitionType()==Definition::TypePage && !((const PageDef*)this)->title().isEmpty()) |
|
1265 { |
|
1266 ol.writeObjectLink(getReference(),getOutputFileBase(),0,((const PageDef*)this)->title()); |
|
1267 } |
|
1268 else |
|
1269 { |
|
1270 ol.writeObjectLink(getReference(),getOutputFileBase(),0,m_impl->localName); |
|
1271 } |
|
1272 } |
|
1273 else |
|
1274 { |
|
1275 ol.startBold(); |
|
1276 ol.docify(m_impl->localName); |
|
1277 ol.endBold(); |
|
1278 } |
|
1279 } |
|
1280 |
|
1281 void Definition::writeNavigationPath(OutputList &ol) const |
|
1282 { |
|
1283 ol.pushGeneratorState(); |
|
1284 ol.disableAllBut(OutputGenerator::Html); |
|
1285 |
|
1286 ol.writeString(" <div class=\"navpath\">"); |
|
1287 writePathFragment(ol); |
|
1288 ol.writeString("\n </div>\n"); |
|
1289 |
|
1290 ol.popGeneratorState(); |
|
1291 } |
|
1292 |
|
1293 QCString Definition::symbolName() const |
|
1294 { |
|
1295 return m_symbolName; |
|
1296 } |
|
1297 |
|
1298 //---------------------- |
|
1299 |
|
1300 QCString Definition::documentation() const |
|
1301 { |
|
1302 makeResident(); |
|
1303 return m_impl->details ? m_impl->details->doc : QCString(""); |
|
1304 } |
|
1305 |
|
1306 int Definition::docLine() const |
|
1307 { |
|
1308 makeResident(); |
|
1309 return m_impl->details ? m_impl->details->line : 1; |
|
1310 } |
|
1311 |
|
1312 QCString Definition::docFile() const |
|
1313 { |
|
1314 makeResident(); |
|
1315 return m_impl->details ? m_impl->details->file : QCString("<"+m_name+">"); |
|
1316 } |
|
1317 |
|
1318 //---------------------- |
|
1319 |
|
1320 QCString Definition::briefDescription() const |
|
1321 { |
|
1322 makeResident(); |
|
1323 return m_impl->brief ? m_impl->brief->doc : QCString(""); |
|
1324 } |
|
1325 |
|
1326 QCString Definition::briefDescriptionAsTooltip() const |
|
1327 { |
|
1328 makeResident(); |
|
1329 if (m_impl->brief) |
|
1330 { |
|
1331 if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) |
|
1332 { |
|
1333 static bool reentering=FALSE; |
|
1334 if (!reentering) |
|
1335 { |
|
1336 MemberDef *md = definitionType()==TypeMember ? (MemberDef*)this : 0; |
|
1337 const Definition *scope = definitionType()==TypeMember ? getOuterScope() : this; |
|
1338 reentering=TRUE; // prevent requests for tooltips while parsing a tooltip |
|
1339 m_impl->brief->tooltip = parseCommentAsText( |
|
1340 scope,md, |
|
1341 m_impl->brief->doc, |
|
1342 m_impl->brief->file, |
|
1343 m_impl->brief->line); |
|
1344 reentering=FALSE; |
|
1345 } |
|
1346 } |
|
1347 return m_impl->brief->tooltip; |
|
1348 } |
|
1349 return QCString(""); |
|
1350 } |
|
1351 |
|
1352 int Definition::briefLine() const |
|
1353 { |
|
1354 makeResident(); |
|
1355 return m_impl->brief ? m_impl->brief->line : 1; |
|
1356 } |
|
1357 |
|
1358 QCString Definition::briefFile() const |
|
1359 { |
|
1360 makeResident(); |
|
1361 return m_impl->brief ? m_impl->brief->file : QCString("<"+m_name+">"); |
|
1362 } |
|
1363 |
|
1364 //---------------------- |
|
1365 |
|
1366 QCString Definition::inbodyDocumentation() const |
|
1367 { |
|
1368 makeResident(); |
|
1369 return m_impl->inbodyDocs ? m_impl->inbodyDocs->doc : QCString(""); |
|
1370 } |
|
1371 |
|
1372 int Definition::inbodyLine() const |
|
1373 { |
|
1374 makeResident(); |
|
1375 return m_impl->inbodyDocs ? m_impl->inbodyDocs->line : 1; |
|
1376 } |
|
1377 |
|
1378 QCString Definition::inbodyFile() const |
|
1379 { |
|
1380 makeResident(); |
|
1381 return m_impl->inbodyDocs ? m_impl->inbodyDocs->file : QCString("<"+m_name+">"); |
|
1382 } |
|
1383 |
|
1384 |
|
1385 //---------------------- |
|
1386 |
|
1387 QCString Definition::getDefFileName() const |
|
1388 { |
|
1389 makeResident(); |
|
1390 return m_impl->defFileName; |
|
1391 } |
|
1392 |
|
1393 QCString Definition::getDefFileExtension() const |
|
1394 { |
|
1395 makeResident(); |
|
1396 return m_impl->defFileExt; |
|
1397 } |
|
1398 |
|
1399 int Definition::getDefLine() const |
|
1400 { |
|
1401 makeResident(); |
|
1402 return m_impl->defLine; |
|
1403 } |
|
1404 |
|
1405 bool Definition::isHidden() const |
|
1406 { |
|
1407 makeResident(); |
|
1408 return m_impl->hidden; |
|
1409 } |
|
1410 |
|
1411 bool Definition::isVisibleInProject() const |
|
1412 { |
|
1413 return isLinkableInProject() && !m_impl->hidden; |
|
1414 } |
|
1415 |
|
1416 bool Definition::isVisible() const |
|
1417 { |
|
1418 return isLinkable() && !m_impl->hidden; |
|
1419 } |
|
1420 |
|
1421 bool Definition::isArtificial() const |
|
1422 { |
|
1423 return m_impl->isArtificial; |
|
1424 } |
|
1425 |
|
1426 QCString Definition::getReference() const |
|
1427 { |
|
1428 makeResident(); |
|
1429 return m_impl->ref; |
|
1430 } |
|
1431 |
|
1432 bool Definition::isReference() const |
|
1433 { |
|
1434 makeResident(); |
|
1435 return !m_impl->ref.isEmpty(); |
|
1436 } |
|
1437 |
|
1438 int Definition::getStartBodyLine() const |
|
1439 { |
|
1440 makeResident(); |
|
1441 return m_impl->body ? m_impl->body->startLine : -1; |
|
1442 } |
|
1443 |
|
1444 int Definition::getEndBodyLine() const |
|
1445 { |
|
1446 makeResident(); |
|
1447 return m_impl->body ? m_impl->body->endLine : -1; |
|
1448 } |
|
1449 |
|
1450 FileDef *Definition::getBodyDef() |
|
1451 { |
|
1452 makeResident(); |
|
1453 return m_impl->body ? m_impl->body->fileDef : 0; |
|
1454 } |
|
1455 |
|
1456 LockingPtr<GroupList> Definition::partOfGroups() const |
|
1457 { |
|
1458 makeResident(); |
|
1459 return LockingPtr<GroupList>(this,m_impl->partOfGroups); |
|
1460 } |
|
1461 |
|
1462 Definition *Definition::getOuterScope() const |
|
1463 { |
|
1464 makeResident(); |
|
1465 return m_impl->outerScope; |
|
1466 } |
|
1467 |
|
1468 LockingPtr<MemberSDict> Definition::getReferencesMembers() const |
|
1469 { |
|
1470 makeResident(); |
|
1471 return LockingPtr<MemberSDict>(this,m_impl->sourceRefsDict); |
|
1472 } |
|
1473 |
|
1474 LockingPtr<MemberSDict> Definition::getReferencedByMembers() const |
|
1475 { |
|
1476 makeResident(); |
|
1477 return LockingPtr<MemberSDict>(this,m_impl->sourceRefByDict); |
|
1478 } |
|
1479 |
|
1480 void Definition::setReference(const char *r) |
|
1481 { |
|
1482 makeResident(); |
|
1483 m_impl->ref=r; |
|
1484 } |
|
1485 |
|
1486 void Definition::_setSymbolName(const QCString &name) |
|
1487 { |
|
1488 m_symbolName=name; |
|
1489 } |
|
1490 |
|
1491 void Definition::setHidden(bool b) |
|
1492 { |
|
1493 makeResident(); |
|
1494 m_impl->hidden = m_impl->hidden || b; |
|
1495 } |
|
1496 |
|
1497 void Definition::setArtificial(bool b) |
|
1498 { |
|
1499 makeResident(); |
|
1500 m_impl->isArtificial = b; |
|
1501 } |
|
1502 |
|
1503 void Definition::setLocalName(const QCString name) |
|
1504 { |
|
1505 makeResident(); |
|
1506 m_impl->localName=name; |
|
1507 } |
|
1508 |
|
1509 void Definition::makeResident() const |
|
1510 { |
|
1511 } |
|
1512 |
|
1513 |
|
1514 void Definition::flushToDisk() const |
|
1515 { |
|
1516 //printf("%p: Definition::flushToDisk()\n",this); |
|
1517 Definition *that = (Definition *)this; |
|
1518 //printf("Definition::flushToDisk(): pos=%d\n",(int)m_storagePos); |
|
1519 marshalUInt(Doxygen::symbolStorage,START_MARKER); |
|
1520 marshalSectionDict (Doxygen::symbolStorage,m_impl->sectionDict); |
|
1521 marshalMemberSDict (Doxygen::symbolStorage,m_impl->sourceRefByDict); |
|
1522 marshalMemberSDict (Doxygen::symbolStorage,m_impl->sourceRefsDict); |
|
1523 marshalItemInfoList (Doxygen::symbolStorage,m_impl->xrefListItems); |
|
1524 marshalGroupList (Doxygen::symbolStorage,m_impl->partOfGroups); |
|
1525 marshalDocInfo (Doxygen::symbolStorage,m_impl->details); |
|
1526 marshalDocInfo (Doxygen::symbolStorage,m_impl->inbodyDocs); |
|
1527 marshalBriefInfo (Doxygen::symbolStorage,m_impl->brief); |
|
1528 marshalBodyInfo (Doxygen::symbolStorage,m_impl->body); |
|
1529 marshalQCString (Doxygen::symbolStorage,m_impl->docSignatures); |
|
1530 marshalQCString (Doxygen::symbolStorage,m_impl->localName); |
|
1531 marshalQCString (Doxygen::symbolStorage,m_impl->qualifiedName); |
|
1532 marshalQCString (Doxygen::symbolStorage,m_impl->ref); |
|
1533 marshalBool (Doxygen::symbolStorage,m_impl->hidden); |
|
1534 marshalBool (Doxygen::symbolStorage,m_impl->isArtificial); |
|
1535 marshalObjPointer (Doxygen::symbolStorage,m_impl->outerScope); |
|
1536 marshalQCString (Doxygen::symbolStorage,m_impl->defFileName); |
|
1537 marshalInt (Doxygen::symbolStorage,m_impl->defLine); |
|
1538 marshalQCString (Doxygen::symbolStorage,m_impl->defFileExt); |
|
1539 marshalUInt(Doxygen::symbolStorage,END_MARKER); |
|
1540 delete that->m_impl; |
|
1541 that->m_impl = 0; |
|
1542 } |
|
1543 |
|
1544 void Definition::loadFromDisk() const |
|
1545 { |
|
1546 //printf("%p: Definition::loadFromDisk()\n",this); |
|
1547 Definition *that = (Definition *)this; |
|
1548 assert(m_impl==0); |
|
1549 that->m_impl = new DefinitionImpl; |
|
1550 uint marker = unmarshalUInt(Doxygen::symbolStorage); |
|
1551 assert(marker==START_MARKER); |
|
1552 m_impl->sectionDict = unmarshalSectionDict (Doxygen::symbolStorage); |
|
1553 m_impl->sourceRefByDict = unmarshalMemberSDict (Doxygen::symbolStorage); |
|
1554 m_impl->sourceRefsDict = unmarshalMemberSDict (Doxygen::symbolStorage); |
|
1555 m_impl->xrefListItems = unmarshalItemInfoList (Doxygen::symbolStorage); |
|
1556 m_impl->partOfGroups = unmarshalGroupList (Doxygen::symbolStorage); |
|
1557 m_impl->details = unmarshalDocInfo (Doxygen::symbolStorage); |
|
1558 m_impl->inbodyDocs = unmarshalDocInfo (Doxygen::symbolStorage); |
|
1559 m_impl->brief = unmarshalBriefInfo (Doxygen::symbolStorage); |
|
1560 m_impl->body = unmarshalBodyInfo (Doxygen::symbolStorage); |
|
1561 m_impl->docSignatures = unmarshalQCString (Doxygen::symbolStorage); |
|
1562 m_impl->localName = unmarshalQCString (Doxygen::symbolStorage); |
|
1563 m_impl->qualifiedName = unmarshalQCString (Doxygen::symbolStorage); |
|
1564 m_impl->ref = unmarshalQCString (Doxygen::symbolStorage); |
|
1565 m_impl->hidden = unmarshalBool (Doxygen::symbolStorage); |
|
1566 m_impl->isArtificial = unmarshalBool (Doxygen::symbolStorage); |
|
1567 m_impl->outerScope = (Definition *)unmarshalObjPointer (Doxygen::symbolStorage); |
|
1568 m_impl->defFileName = unmarshalQCString (Doxygen::symbolStorage); |
|
1569 m_impl->defLine = unmarshalInt (Doxygen::symbolStorage); |
|
1570 m_impl->defFileExt = unmarshalQCString (Doxygen::symbolStorage); |
|
1571 marker = unmarshalUInt(Doxygen::symbolStorage); |
|
1572 assert(marker==END_MARKER); |
|
1573 } |
|
1574 |