summaryrefslogtreecommitdiff
path: root/src/definition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/definition.cpp')
-rw-r--r--src/definition.cpp1938
1 files changed, 1938 insertions, 0 deletions
diff --git a/src/definition.cpp b/src/definition.cpp
new file mode 100644
index 0000000..649fdc7
--- /dev/null
+++ b/src/definition.cpp
@@ -0,0 +1,1938 @@
+/******************************************************************************
+ *
+ * $Id: index.cpp,v 1.30 1999/03/06 22:15:39 root Exp $
+ *
+ * Copyright (C) 1997-2012 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#include "qtbc.h"
+#include <ctype.h>
+#include <qregexp.h>
+#include "md5.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "config.h"
+#include "definition.h"
+#include "doxygen.h"
+#include "language.h"
+#include "message.h"
+#include "outputlist.h"
+#include "code.h"
+#include "util.h"
+#include "groupdef.h"
+#include "pagedef.h"
+#include "section.h"
+#include "htags.h"
+#include "parserintf.h"
+#include "marshal.h"
+#include "debug.h"
+#include "vhdldocgen.h"
+
+#define START_MARKER 0x4445465B // DEF[
+#define END_MARKER 0x4445465D // DEF]
+
+//-----------------------------------------------------------------------------------------
+
+
+/** Private data associated with a Symbol Definition object. */
+class DefinitionImpl
+{
+ public:
+ DefinitionImpl();
+ ~DefinitionImpl();
+ void init(const char *df, const char *n);
+
+ SectionDict *sectionDict; // dictionary of all sections, not accessible
+
+ MemberSDict *sourceRefByDict;
+ MemberSDict *sourceRefsDict;
+ QList<ListItemInfo> *xrefListItems;
+ GroupList *partOfGroups;
+
+ DocInfo *details; // not exported
+ DocInfo *inbodyDocs; // not exported
+ BriefInfo *brief; // not exported
+ BodyInfo *body; // not exported
+ QCString docSignatures;
+
+ QCString localName; // local (unqualified) name of the definition
+ // in the future m_name should become m_localName
+ QCString qualifiedName;
+ QCString ref; // reference to external documentation
+
+ bool hidden;
+ bool isArtificial;
+
+ Definition *outerScope; // not owner
+
+ // where the item was found
+ QCString defFileName;
+ QCString defFileExt;
+
+ SrcLangExt lang;
+};
+
+DefinitionImpl::DefinitionImpl()
+ : sectionDict(0), sourceRefByDict(0), sourceRefsDict(0),
+ xrefListItems(0), partOfGroups(0),
+ details(0), inbodyDocs(0), brief(0), body(0),
+ outerScope(0)
+{
+}
+
+DefinitionImpl::~DefinitionImpl()
+{
+ delete sectionDict;
+ delete sourceRefByDict;
+ delete sourceRefsDict;
+ delete partOfGroups;
+ delete xrefListItems;
+ delete brief;
+ delete details;
+ delete body;
+ delete inbodyDocs;
+}
+
+void DefinitionImpl::init(const char *df, const char *n)
+{
+ defFileName = df;
+ int lastDot = defFileName.findRev('.');
+ if (lastDot!=-1)
+ {
+ defFileExt = defFileName.mid(lastDot);
+ }
+ QCString name = n;
+ if (name!="<globalScope>")
+ {
+ //extractNamespaceName(m_name,m_localName,ns);
+ localName=stripScope(n);
+ }
+ else
+ {
+ localName=n;
+ }
+ //printf("m_localName=%s\n",m_localName.data());
+
+ brief = 0;
+ details = 0;
+ body = 0;
+ inbodyDocs = 0;
+ sourceRefByDict = 0;
+ sourceRefsDict = 0;
+ sectionDict = 0,
+ outerScope = Doxygen::globalScope;
+ partOfGroups = 0;
+ xrefListItems = 0;
+ hidden = FALSE;
+ isArtificial = FALSE;
+ lang = SrcLangExt_Unknown;
+}
+
+//-----------------------------------------------------------------------------------------
+
+static bool matchExcludedSymbols(const char *name)
+{
+ static QStrList &exclSyms = Config_getList("EXCLUDE_SYMBOLS");
+ if (exclSyms.count()==0) return FALSE; // nothing specified
+ const char *pat = exclSyms.first();
+ QCString symName = name;
+ while (pat)
+ {
+ QCString pattern = pat;
+ bool forceStart=FALSE;
+ bool forceEnd=FALSE;
+ if (pattern.at(0)=='^')
+ pattern=pattern.mid(1),forceStart=TRUE;
+ if (pattern.at(pattern.length()-1)=='$')
+ pattern=pattern.left(pattern.length()-1),forceEnd=TRUE;
+ if (pattern.find('*')!=-1) // wildcard mode
+ {
+ QRegExp re(substitute(pattern,"*",".*"),TRUE);
+ int i,pl;
+ i = re.match(symName,0,&pl);
+ //printf(" %d = re.match(%s) pattern=%s\n",i,symName.data(),pattern.data());
+ if (i!=-1) // wildcard match
+ {
+ int sl=symName.length();
+ // check if it is a whole word match
+ if ((i==0 || pattern.at(0)=='*' || (!isId(symName.at(i-1)) && !forceStart)) &&
+ (i+pl==sl || pattern.at(i+pl)=='*' || (!isId(symName.at(i+pl)) && !forceEnd))
+ )
+ {
+ //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i);
+ return TRUE;
+ }
+ }
+ }
+ else if (!pattern.isEmpty()) // match words
+ {
+ int i = symName.find(pattern);
+ if (i!=-1) // we have a match!
+ {
+ int pl=pattern.length();
+ int sl=symName.length();
+ // check if it is a whole word match
+ if ((i==0 || (!isId(symName.at(i-1)) && !forceStart)) &&
+ (i+pl==sl || (!isId(symName.at(i+pl)) && !forceEnd))
+ )
+ {
+ //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i);
+ return TRUE;
+ }
+ }
+ }
+ pat = exclSyms.next();
+ }
+ //printf("--> name=%s: no match\n",name);
+ return FALSE;
+}
+
+void Definition::addToMap(const char *name,Definition *d)
+{
+ bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
+ QCString symbolName = name;
+ int index=computeQualifiedIndex(symbolName);
+ if (!vhdlOpt && index!=-1) symbolName=symbolName.mid(index+2);
+ if (!symbolName.isEmpty())
+ {
+ //printf("******* adding symbol `%s' (%p)\n",symbolName.data(),d);
+ DefinitionIntf *di=Doxygen::symbolMap->find(symbolName);
+ //printf(" addToMap(%p): looking for symbol %s: %p\n",d,symbolName.data(),di);
+ if (di==0) // new Symbol
+ {
+ //printf(" new symbol!\n");
+ Doxygen::symbolMap->insert(symbolName,d);
+ }
+ else // existing symbol
+ {
+ //printf(" existing symbol: ");
+ if (di->definitionType()==DefinitionIntf::TypeSymbolList) // already multiple symbols
+ {
+ //printf("adding to exiting list\n");
+ DefinitionList *dl = (DefinitionList*)di;
+ dl->append(d);
+ }
+ else // going from one to two symbols
+ {
+ Doxygen::symbolMap->take(symbolName);
+ DefinitionList *dl = new DefinitionList;
+ //printf("replacing symbol by list %p with elements %p and %p\n",dl,di,d);
+ dl->append((Definition*)di);
+ dl->append(d);
+ Doxygen::symbolMap->insert(symbolName,dl);
+ }
+ }
+
+ // auto resize if needed
+ static int sizeIndex=9;
+ if (Doxygen::symbolMap->size()>SDict_primes[sizeIndex])
+ {
+ Doxygen::symbolMap->resize(SDict_primes[++sizeIndex]);
+ }
+
+ d->_setSymbolName(symbolName);
+ }
+}
+
+void Definition::removeFromMap(Definition *d)
+{
+ QCString symbolName = d->m_symbolName;
+ if (!symbolName.isEmpty())
+ {
+ //printf("******* removing symbol `%s' (%p)\n",symbolName.data(),d);
+ DefinitionIntf *di=Doxygen::symbolMap->find(symbolName);
+ if (di)
+ {
+ if (di!=d) // symbolName not unique
+ {
+ //printf(" removing from list: %p!\n",di);
+ DefinitionList *dl = (DefinitionList*)di;
+ bool b = dl->removeRef(d);
+ ASSERT(b==TRUE);
+ if (dl->isEmpty())
+ {
+ Doxygen::symbolMap->take(symbolName);
+ }
+ }
+ else // symbolName unique
+ {
+ //printf(" removing symbol %p\n",di);
+ Doxygen::symbolMap->take(symbolName);
+ }
+ }
+ }
+}
+
+Definition::Definition(const char *df,int dl,
+ const char *name,const char *b,
+ const char *d,bool isSymbol)
+{
+ m_name = name;
+ m_defLine = dl;
+ m_impl = new DefinitionImpl;
+ m_impl->init(df,name);
+ m_isSymbol = isSymbol;
+ if (isSymbol) addToMap(name,this);
+ _setBriefDescription(b,df,dl);
+ _setDocumentation(d,df,dl,TRUE,FALSE);
+ if (matchExcludedSymbols(name))
+ {
+ m_impl->hidden = TRUE;
+ }
+}
+
+Definition::Definition(const Definition &d) : DefinitionIntf(), LockableObj()
+{
+ m_name = d.m_name;
+ m_defLine = d.m_defLine;
+ m_impl = new DefinitionImpl;
+ *m_impl = *d.m_impl;
+ m_impl->sectionDict = 0;
+ m_impl->sourceRefByDict = 0;
+ m_impl->sourceRefsDict = 0;
+ m_impl->partOfGroups = 0;
+ m_impl->xrefListItems = 0;
+ m_impl->brief = 0;
+ m_impl->details = 0;
+ m_impl->body = 0;
+ m_impl->inbodyDocs = 0;
+ if (d.m_impl->sectionDict)
+ {
+ m_impl->sectionDict = new SectionDict(17);
+ SDict<SectionInfo>::Iterator it(*d.m_impl->sectionDict);
+ SectionInfo *si;
+ for (it.toFirst();(si=it.current());++it)
+ {
+ m_impl->sectionDict->append(si->label,si);
+ }
+ }
+ if (d.m_impl->sourceRefByDict)
+ {
+ m_impl->sourceRefByDict = new MemberSDict;
+ MemberSDict::IteratorDict it(*d.m_impl->sourceRefByDict);
+ MemberDef *md;
+ for (it.toFirst();(md=it.current());++it)
+ {
+ m_impl->sourceRefByDict->append(it.currentKey(),md);
+ }
+ }
+ if (d.m_impl->sourceRefsDict)
+ {
+ m_impl->sourceRefsDict = new MemberSDict;
+ MemberSDict::IteratorDict it(*d.m_impl->sourceRefsDict);
+ MemberDef *md;
+ for (it.toFirst();(md=it.current());++it)
+ {
+ m_impl->sourceRefsDict->append(it.currentKey(),md);
+ }
+ }
+ if (d.m_impl->partOfGroups)
+ {
+ GroupListIterator it(*d.m_impl->partOfGroups);
+ GroupDef *gd;
+ for (it.toFirst();(gd=it.current());++it)
+ {
+ makePartOfGroup(gd);
+ }
+ }
+ if (d.m_impl->xrefListItems)
+ {
+ setRefItems(d.m_impl->xrefListItems);
+ }
+ if (d.m_impl->brief)
+ {
+ m_impl->brief = new BriefInfo(*d.m_impl->brief);
+ }
+ if (d.m_impl->details)
+ {
+ m_impl->details = new DocInfo(*d.m_impl->details);
+ }
+ if (d.m_impl->body)
+ {
+ m_impl->body = new BodyInfo(*d.m_impl->body);
+ }
+ if (d.m_impl->inbodyDocs)
+ {
+ m_impl->details = new DocInfo(*d.m_impl->inbodyDocs);
+ }
+
+ m_isSymbol = d.m_isSymbol;
+ if (m_isSymbol) addToMap(m_name,this);
+}
+
+Definition::~Definition()
+{
+ if (m_isSymbol)
+ {
+ removeFromMap(this);
+ }
+ if (m_impl)
+ {
+ delete m_impl;
+ m_impl=0;
+ }
+}
+
+void Definition::setName(const char *name)
+{
+ if (name==0) return;
+ m_name = name;
+}
+
+void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList)
+{
+ if (!anchorList) return;
+ makeResident();
+ //printf("%s: addSectionsToDefinition(%d)\n",name().data(),anchorList->count());
+ SectionInfo *si=anchorList->first();
+ while (si)
+ {
+ //printf("Add section `%s' to definition `%s'\n",
+ // si->label.data(),name().data());
+ SectionInfo *gsi=Doxygen::sectionDict.find(si->label);
+ //printf("===== label=%s gsi=%p\n",si->label.data(),gsi);
+ if (gsi==0)
+ {
+ gsi = new SectionInfo(*si);
+ Doxygen::sectionDict.append(si->label,gsi);
+ }
+ if (m_impl->sectionDict==0)
+ {
+ m_impl->sectionDict = new SectionDict(17);
+ }
+ if (m_impl->sectionDict->find(gsi->label)==0)
+ {
+ m_impl->sectionDict->append(gsi->label,gsi);
+ gsi->definition = this;
+ }
+ si=anchorList->next();
+ }
+}
+
+bool Definition::hasSections() const
+{
+ makeResident();
+ //printf("Definition::hasSections(%s) #sections=%d\n",name().data(),
+ // m_impl->sectionDict ? m_impl->sectionDict->count() : 0);
+ if (m_impl->sectionDict==0) return FALSE;
+ SDict<SectionInfo>::Iterator li(*m_impl->sectionDict);
+ SectionInfo *si;
+ for (li.toFirst();(si=li.current());++li)
+ {
+ if (si->type==SectionInfo::Section ||
+ si->type==SectionInfo::Subsection ||
+ si->type==SectionInfo::Subsubsection ||
+ si->type==SectionInfo::Paragraph)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void Definition::addSectionsToIndex()
+{
+ makeResident();
+ if (m_impl->sectionDict==0) return;
+ //printf("Definition::addSectionsToIndex()\n");
+ SDict<SectionInfo>::Iterator li(*m_impl->sectionDict);
+ SectionInfo *si;
+ int level=1;
+ for (li.toFirst();(si=li.current());++li)
+ {
+ if (si->type==SectionInfo::Section ||
+ si->type==SectionInfo::Subsection ||
+ si->type==SectionInfo::Subsubsection ||
+ si->type==SectionInfo::Paragraph)
+ {
+ //printf(" level=%d title=%s\n",level,si->title.data());
+ int nextLevel = (int)si->type;
+ int i;
+ if (nextLevel>level)
+ {
+ for (i=level;i<nextLevel;i++)
+ {
+ Doxygen::indexList.incContentsDepth();
+ }
+ }
+ else if (nextLevel<level)
+ {
+ for (i=nextLevel;i<level;i++)
+ {
+ Doxygen::indexList.decContentsDepth();
+ }
+ }
+ QCString title = si->title;
+ if (title.isEmpty()) title = si->label;
+ Doxygen::indexList.addContentsItem(TRUE,title,
+ getReference(),
+ getOutputFileBase(),
+ si->label,
+ FALSE,
+ TRUE);
+ level = nextLevel;
+ }
+ }
+ while (level>1)
+ {
+ Doxygen::indexList.decContentsDepth();
+ level--;
+ }
+}
+
+void Definition::writeDocAnchorsToTagFile()
+{
+ makeResident();
+ if (!Config_getString("GENERATE_TAGFILE").isEmpty() && m_impl->sectionDict)
+ {
+ //printf("%s: writeDocAnchorsToTagFile(%d)\n",name().data(),m_sectionDict->count());
+ SDict<SectionInfo>::Iterator sdi(*m_impl->sectionDict);
+ SectionInfo *si;
+ for (;(si=sdi.current());++sdi)
+ {
+ if (!si->generated)
+ {
+ //printf("write an entry!\n");
+ if (definitionType()==TypeMember) Doxygen::tagFile << " ";
+ Doxygen::tagFile << " <docanchor file=\""
+ << si->fileName << "\">" << si->label
+ << "</docanchor>" << endl;
+ }
+ }
+ }
+}
+
+bool Definition::_docsAlreadyAdded(const QCString &doc)
+{
+ uchar md5_sig[16];
+ QCString sigStr(33);
+ // to avoid mismatches due to differences in indenting, we first remove
+ // double whitespaces...
+ QCString docStr = doc.simplifyWhiteSpace();
+ MD5Buffer((const unsigned char *)docStr.data(),docStr.length(),md5_sig);
+ MD5SigToString(md5_sig,sigStr.data(),33);
+ if (m_impl->docSignatures.find(sigStr)==-1) // new docs, add signature to prevent re-adding it
+ {
+ m_impl->docSignatures+=":"+sigStr;
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void Definition::_setDocumentation(const char *d,const char *docFile,int docLine,
+ bool stripWhiteSpace,bool atTop)
+{
+ //printf("%s::setDocumentation(%s,%s,%d,%d)\n",name().data(),d,docFile,docLine,stripWhiteSpace);
+ if (d==0) return;
+ QCString doc = d;
+ if (stripWhiteSpace)
+ {
+ doc = stripLeadingAndTrailingEmptyLines(doc,docLine);
+ }
+ else // don't strip whitespace
+ {
+ doc=d;
+ }
+ if (!_docsAlreadyAdded(doc))
+ {
+ //printf("setting docs for %s: `%s'\n",name().data(),m_doc.data());
+ if (m_impl->details==0)
+ {
+ m_impl->details = new DocInfo;
+ }
+ if (m_impl->details->doc.isEmpty()) // fresh detailed description
+ {
+ m_impl->details->doc = doc;
+ }
+ else if (atTop) // another detailed description, append it to the start
+ {
+ m_impl->details->doc = doc+"\n\n"+m_impl->details->doc;
+ }
+ else // another detailed description, append it to the end
+ {
+ m_impl->details->doc += "\n\n"+doc;
+ }
+ if (docLine!=-1) // store location if valid
+ {
+ m_impl->details->file = docFile;
+ m_impl->details->line = docLine;
+ }
+ else
+ {
+ m_impl->details->file = docFile;
+ m_impl->details->line = 1;
+ }
+ }
+}
+
+void Definition::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace)
+{
+ if (d==0) return;
+ makeResident();
+ _setDocumentation(d,docFile,docLine,stripWhiteSpace,FALSE);
+}
+
+#define uni_isupper(c) (QChar(c).category()==QChar::Letter_Uppercase)
+
+// do a UTF-8 aware search for the last real character and return TRUE
+// if that is a multibyte one.
+static bool lastCharIsMultibyte(const QCString &s)
+{
+ int l = s.length();
+ int p = 0;
+ int pp = -1;
+ while ((p=nextUtf8CharPosition(s,l,p))<l) pp=p;
+ if (pp==-1 || ((uchar)s[pp])<0x80) return FALSE;
+ return TRUE;
+}
+
+void Definition::_setBriefDescription(const char *b,const char *briefFile,int briefLine)
+{
+ static QCString outputLanguage = Config_getEnum("OUTPUT_LANGUAGE");
+ static bool needsDot = outputLanguage!="Japanese" &&
+ outputLanguage!="Chinese" &&
+ outputLanguage!="Korean";
+ QCString brief = b;
+ brief = brief.stripWhiteSpace();
+ if (brief.isEmpty()) return;
+ int bl = brief.length();
+ if (bl>0 && needsDot) // add punctuation if needed
+ {
+ int c = brief.at(bl-1);
+ switch(c)
+ {
+ case '.': case '!': case '?': case '>': case ':': case ')': break;
+ default:
+ if (uni_isupper(brief.at(0)) && !lastCharIsMultibyte(brief)) brief+='.';
+ break;
+ }
+ }
+
+ if (m_impl->brief && !m_impl->brief->doc.isEmpty())
+ {
+ //printf("adding to details\n");
+ _setDocumentation(brief,briefFile,briefLine,FALSE,TRUE);
+ }
+ else if (!_docsAlreadyAdded(brief))
+ {
+ //fprintf(stderr,"Definition::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine);
+ if (m_impl->brief==0)
+ {
+ m_impl->brief = new BriefInfo;
+ }
+ m_impl->brief->doc=brief;
+ if (briefLine!=-1)
+ {
+ m_impl->brief->file = briefFile;
+ m_impl->brief->line = briefLine;
+ }
+ else
+ {
+ m_impl->brief->file = briefFile;
+ m_impl->brief->line = 1;
+ }
+ }
+}
+
+void Definition::setBriefDescription(const char *b,const char *briefFile,int briefLine)
+{
+ if (b==0) return;
+ makeResident();
+ _setBriefDescription(b,briefFile,briefLine);
+}
+
+void Definition::_setInbodyDocumentation(const char *doc,const char *inbodyFile,int inbodyLine)
+{
+ if (m_impl->inbodyDocs==0)
+ {
+ m_impl->inbodyDocs = new DocInfo;
+ }
+ if (m_impl->inbodyDocs->doc.isEmpty()) // fresh inbody docs
+ {
+ m_impl->inbodyDocs->doc = doc;
+ m_impl->inbodyDocs->file = inbodyFile;
+ m_impl->inbodyDocs->line = inbodyLine;
+ }
+ else // another inbody documentation fragment, append this to the end
+ {
+ m_impl->inbodyDocs->doc += QCString("\n\n")+doc;
+ }
+}
+
+void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine)
+{
+ if (d==0) return;
+ makeResident();
+ _setInbodyDocumentation(d,inbodyFile,inbodyLine);
+}
+
+/*! Reads a fragment of code from file \a fileName starting at
+ * line \a startLine and ending at line \a endLine (inclusive). The fragment is
+ * stored in \a result. If FALSE is returned the code fragment could not be
+ * found.
+ *
+ * The file is scanned for a opening bracket ('{') from \a startLine onward
+ * The line actually containing the bracket is returned via startLine.
+ * The file is scanned for a closing bracket ('}') from \a endLine backward.
+ * The line actually containing the bracket is returned via endLine.
+ * Note that for VHDL code the bracket search is not done.
+ */
+static bool readCodeFragment(const char *fileName,
+ int &startLine,int &endLine,QCString &result)
+{
+ static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES");
+ static int tabSize = Config_getInt("TAB_SIZE");
+ //printf("readCodeFragment(%s,%d,%d)\n",fileName,startLine,endLine);
+ if (fileName==0 || fileName[0]==0) return FALSE; // not a valid file name
+ QCString filter = getFileFilter(fileName,TRUE);
+ FILE *f=0;
+ bool usePipe = !filter.isEmpty() && filterSourceFiles;
+ SrcLangExt lang = getLanguageFromFileName(fileName);
+ if (!usePipe) // no filter given or wanted
+ {
+ f = portable_fopen(fileName,"r");
+ }
+ else // use filter
+ {
+ QCString cmd=filter+" \""+fileName+"\"";
+ Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data());
+ f = portable_popen(cmd,"r");
+ }
+ bool found = lang==SrcLangExt_VHDL ||
+ lang==SrcLangExt_Tcl ||
+ lang==SrcLangExt_Python ||
+ lang==SrcLangExt_Fortran;
+ // for VHDL, TCL, Python, and Fortran no bracket search is possible
+ if (f)
+ {
+ int c=0;
+ int col=0;
+ int lineNr=1;
+ // skip until the startLine has reached
+ while (lineNr<startLine && !feof(f))
+ {
+ while ((c=fgetc(f))!='\n' && c!=EOF) /* skip */;
+ lineNr++;
+ }
+ if (!feof(f))
+ {
+ // skip until the opening bracket or lonely : is found
+ char cn=0;
+ while (lineNr<=endLine && !feof(f) && !found)
+ {
+ int pc=0;
+ while ((c=fgetc(f))!='{' && c!=':' && c!=EOF)
+ {
+ //printf("parsing char `%c'\n",c);
+ if (c=='\n')
+ {
+ lineNr++,col=0;
+ }
+ else if (c=='\t')
+ {
+ col+=tabSize - (col%tabSize);
+ }
+ else if (pc=='/' && c=='/') // skip single line comment
+ {
+ while ((c=fgetc(f))!='\n' && c!=EOF) pc=c;
+ if (c=='\n') lineNr++,col=0;
+ }
+ else if (pc=='/' && c=='*') // skip C style comment
+ {
+ while (((c=fgetc(f))!='/' || pc!='*') && c!=EOF)
+ {
+ if (c=='\n') lineNr++,col=0;
+ pc=c;
+ }
+ }
+ else
+ {
+ col++;
+ }
+ pc = c;
+ }
+ if (c==':')
+ {
+ cn=fgetc(f);
+ if (cn!=':') found=TRUE;
+ }
+ else if (c=='{') // } so vi matching brackets has no problem
+ {
+ found=TRUE;
+ }
+ }
+ //printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr);
+ if (found)
+ {
+ // For code with more than one line,
+ // fill the line with spaces until we are at the right column
+ // so that the opening brace lines up with the closing brace
+ if (endLine!=startLine)
+ {
+ QCString spaces;
+ spaces.fill(' ',col);
+ result+=spaces;
+ }
+ // copy until end of line
+ result+=c;
+ if (c==':')
+ {
+ result+=cn;
+ if (cn=='\n') lineNr++;
+ }
+ startLine=lineNr;
+ const int maxLineLength=4096;
+ char lineStr[maxLineLength];
+ do
+ {
+ //printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine);
+ int size_read;
+ do
+ {
+ // read up to maxLineLength-1 bytes, the last byte being zero
+ char *p = fgets(lineStr, maxLineLength,f);
+ //printf(" read %s",p);
+ if (p)
+ {
+ size_read=qstrlen(p);
+ }
+ else // nothing read
+ {
+ size_read=-1;
+ lineStr[0]='\0';
+ }
+ result+=lineStr;
+ } while (size_read == (maxLineLength-1));
+
+ lineNr++;
+ } while (lineNr<=endLine && !feof(f));
+
+ // strip stuff after closing bracket
+ int newLineIndex = result.findRev('\n');
+ int braceIndex = result.findRev('}');
+ if (braceIndex > newLineIndex)
+ {
+ result.truncate(braceIndex+1);
+ }
+ endLine=lineNr-1;
+ }
+ }
+ if (usePipe)
+ {
+ portable_pclose(f);
+ Debug::print(Debug::FilterOutput, 0, "Filter output\n");
+ Debug::print(Debug::FilterOutput,0,"-------------\n%s\n-------------\n",result.data());
+ }
+ else
+ {
+ fclose(f);
+ }
+ }
+ result = transcodeCharacterStringToUTF8(result);
+ return found;
+}
+
+/*! Write a reference to the source code defining this definition */
+void Definition::writeSourceDef(OutputList &ol,const char *)
+{
+ static bool sourceBrowser = Config_getBool("SOURCE_BROWSER");
+ static bool latexSourceCode = Config_getBool("LATEX_SOURCE_CODE");
+ makeResident();
+ ol.pushGeneratorState();
+ //printf("Definition::writeSourceRef %d %p\n",bodyLine,bodyDef);
+ if (sourceBrowser &&
+ m_impl->body && m_impl->body->startLine!=-1 && m_impl->body->fileDef)
+ {
+ QCString refText = theTranslator->trDefinedAtLineInSourceFile();
+ int lineMarkerPos = refText.find("@0");
+ int fileMarkerPos = refText.find("@1");
+ if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this.
+ {
+ QCString lineStr,anchorStr;
+ lineStr.sprintf("%d",m_impl->body->startLine);
+ anchorStr.sprintf(Htags::useHtags ? "L%d" : "l%05d",m_impl->body->startLine);
+ ol.startParagraph();
+ if (lineMarkerPos<fileMarkerPos) // line marker before file marker
+ {
+ // write text left from linePos marker
+ ol.parseText(refText.left(lineMarkerPos));
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::RTF);
+ ol.disable(OutputGenerator::Man);
+ if (!latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ // write line link (HTML, LaTeX optionally)
+ ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(),
+ anchorStr,lineStr);
+ ol.enableAll();
+ ol.disable(OutputGenerator::Html);
+ if (latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ // write normal text (Man/RTF, Latex optionally)
+ ol.docify(lineStr);
+ ol.popGeneratorState();
+
+ // write text between markers
+ ol.parseText(refText.mid(lineMarkerPos+2,
+ fileMarkerPos-lineMarkerPos-2));
+
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::RTF);
+ ol.disable(OutputGenerator::Man);
+ if (!latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ // write line link (HTML, LaTeX optionally)
+ ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(),
+ 0,m_impl->body->fileDef->name());
+ ol.enableAll();
+ ol.disable(OutputGenerator::Html);
+ if (latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ // write normal text (Man/RTF, Latex optionally)
+ ol.docify(m_impl->body->fileDef->name());
+ ol.popGeneratorState();
+
+ // write text right from file marker
+ ol.parseText(refText.right(
+ refText.length()-fileMarkerPos-2));
+ }
+ else // file marker before line marker
+ {
+ // write text left from file marker
+ ol.parseText(refText.left(fileMarkerPos));
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::RTF);
+ ol.disable(OutputGenerator::Man);
+ if (!latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ // write file link (HTML only)
+ ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(),
+ 0,m_impl->body->fileDef->name());
+ ol.enableAll();
+ ol.disable(OutputGenerator::Html);
+ if (latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ // write normal text (Latex/Man only)
+ ol.docify(m_impl->body->fileDef->name());
+ ol.popGeneratorState();
+
+ // write text between markers
+ ol.parseText(refText.mid(fileMarkerPos+2,
+ lineMarkerPos-fileMarkerPos-2));
+
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::RTF);
+ ol.disable(OutputGenerator::Man);
+ if (!latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ ol.disableAllBut(OutputGenerator::Html);
+ // write line link (HTML only)
+ ol.writeObjectLink(0,m_impl->body->fileDef->getSourceFileBase(),
+ anchorStr,lineStr);
+ ol.enableAll();
+ ol.disable(OutputGenerator::Html);
+ if (latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ // write normal text (Latex/Man only)
+ ol.docify(lineStr);
+ ol.popGeneratorState();
+
+ // write text right from linePos marker
+ ol.parseText(refText.right(
+ refText.length()-lineMarkerPos-2));
+ }
+ ol.endParagraph();
+ }
+ else
+ {
+ err("error: translation error: invalid markers in trDefinedInSourceFile()\n");
+ }
+ }
+ ol.popGeneratorState();
+}
+
+void Definition::setBodySegment(int bls,int ble)
+{
+ //printf("setBodySegment(%d,%d) for %s\n",bls,ble,name().data());
+ makeResident();
+ if (m_impl->body==0) m_impl->body = new BodyInfo;
+ m_impl->body->startLine=bls;
+ m_impl->body->endLine=ble;
+}
+
+void Definition::setBodyDef(FileDef *fd)
+{
+ makeResident();
+ if (m_impl->body==0) m_impl->body = new BodyInfo;
+ m_impl->body->fileDef=fd;
+}
+
+/*! Write code of this definition into the documentation */
+void Definition::writeInlineCode(OutputList &ol,const char *scopeName)
+{
+ makeResident();
+ ol.pushGeneratorState();
+ //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(),
+ // m_startBodyLine,m_endBodyLine,m_bodyDef);
+ if (Config_getBool("INLINE_SOURCES") &&
+ m_impl->body && m_impl->body->startLine!=-1 &&
+ m_impl->body->endLine>=m_impl->body->startLine && m_impl->body->fileDef)
+ {
+ QCString codeFragment;
+ int actualStart=m_impl->body->startLine,actualEnd=m_impl->body->endLine;
+ if (readCodeFragment(m_impl->body->fileDef->absFilePath(),
+ actualStart,actualEnd,codeFragment)
+ )
+ {
+ //printf("Adding code fragement '%s' ext='%s'\n",
+ // codeFragment.data(),m_impl->defFileExt.data());
+ ParserInterface *pIntf = Doxygen::parserManager->getParser(m_impl->defFileExt);
+ pIntf->resetCodeParserState();
+ //printf("Read:\n`%s'\n\n",codeFragment.data());
+ MemberDef *thisMd = 0;
+ if (definitionType()==TypeMember) thisMd = (MemberDef *)this;
+
+ // vhdl parser can' t start at an arbitrary point in the source code
+ if(this->getLanguage()==SrcLangExt_VHDL)
+ {
+ if (thisMd) VhdlDocGen::writeCodeFragment(ol,actualStart,codeFragment,thisMd);
+ return;
+ }
+
+ ol.startCodeFragment();
+ pIntf->parseCode(ol, // codeOutIntf
+ scopeName, // scope
+ codeFragment, // input
+ FALSE, // isExample
+ 0, // exampleName
+ m_impl->body->fileDef, // fileDef
+ actualStart, // startLine
+ actualEnd, // endLine
+ TRUE, // inlineFragment
+ thisMd, // memberDef
+ FALSE // show line numbers
+ );
+ ol.endCodeFragment();
+ }
+ }
+ ol.popGeneratorState();
+}
+
+/*! Write a reference to the source code fragments in which this
+ * definition is used.
+ */
+void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName,
+ const QCString &text,MemberSDict *members,bool /*funcOnly*/)
+{
+ LockingPtr<Definition> lock(this,this); // since this can be a memberDef
+ // accessing other memberDefs prevent
+ // it from being flushed to disk
+ static bool latexSourceCode = Config_getBool("LATEX_SOURCE_CODE");
+ static bool sourceBrowser = Config_getBool("SOURCE_BROWSER");
+ static bool refLinkSource = Config_getBool("REFERENCES_LINK_SOURCE");
+ ol.pushGeneratorState();
+ if (members)
+ {
+ members->sort();
+
+ ol.startParagraph();
+ ol.parseText(text);
+ ol.docify(" ");
+
+ QCString ldefLine=theTranslator->trWriteList(members->count());
+
+ QRegExp marker("@[0-9]+");
+ int index=0,newIndex,matchLen;
+ // now replace all markers in inheritLine with links to the classes
+ while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1)
+ {
+ bool ok;
+ ol.parseText(ldefLine.mid(index,newIndex-index));
+ uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
+ MemberDef *md=members->at(entryIndex);
+ if (ok && md)
+ {
+ QCString scope=md->getScopeString();
+ QCString name=md->name();
+ //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName);
+ if (!scope.isEmpty() && scope!=scopeName)
+ {
+ name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang));
+ }
+ if (!md->isObjCMethod() &&
+ (md->isFunction() || md->isSlot() ||
+ md->isPrototype() || md->isSignal()
+ )
+ )
+ {
+ name+="()";
+ }
+ //Definition *d = md->getOutputFileBase();
+ //if (d==Doxygen::globalScope) d=md->getBodyDef();
+ if (sourceBrowser &&
+ !(md->isLinkable() && !refLinkSource) &&
+ md->getStartBodyLine()!=-1 &&
+ md->getBodyDef()
+ )
+ {
+ //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope);
+ // for HTML write a real link
+ ol.pushGeneratorState();
+ //ol.disableAllBut(OutputGenerator::Html);
+
+ ol.disable(OutputGenerator::RTF);
+ ol.disable(OutputGenerator::Man);
+ if (!latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ QCString lineStr,anchorStr;
+ anchorStr.sprintf("l%05d",md->getStartBodyLine());
+ //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data());
+ ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name);
+ ol.popGeneratorState();
+
+ // for the other output formats just mention the name
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ if (latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ ol.docify(name);
+ ol.popGeneratorState();
+ }
+ else if (md->isLinkable() /*&& d && d->isLinkable()*/)
+ {
+ // for HTML write a real link
+ ol.pushGeneratorState();
+ //ol.disableAllBut(OutputGenerator::Html);
+ ol.disable(OutputGenerator::RTF);
+ ol.disable(OutputGenerator::Man);
+ if (!latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+
+ ol.writeObjectLink(md->getReference(),
+ md->getOutputFileBase(),
+ md->anchor(),name);
+ ol.popGeneratorState();
+
+ // for the other output formats just mention the name
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ if (latexSourceCode)
+ {
+ ol.disable(OutputGenerator::Latex);
+ }
+ ol.docify(name);
+ ol.popGeneratorState();
+ }
+ else
+ {
+ ol.docify(name);
+ }
+ }
+ index=newIndex+matchLen;
+ }
+ ol.parseText(ldefLine.right(ldefLine.length()-index));
+ ol.writeString(".");
+ ol.endParagraph();
+ }
+ ol.popGeneratorState();
+}
+
+void Definition::writeSourceReffedBy(OutputList &ol,const char *scopeName)
+{
+ makeResident();
+ if (Config_getBool("REFERENCED_BY_RELATION"))
+ {
+ _writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),m_impl->sourceRefByDict,FALSE);
+ }
+}
+
+void Definition::writeSourceRefs(OutputList &ol,const char *scopeName)
+{
+ makeResident();
+ if (Config_getBool("REFERENCES_RELATION"))
+ {
+ _writeSourceRefList(ol,scopeName,theTranslator->trReferences(),m_impl->sourceRefsDict,TRUE);
+ }
+}
+
+bool Definition::hasDocumentation() const
+{
+ static bool extractAll = Config_getBool("EXTRACT_ALL");
+ //static bool sourceBrowser = Config_getBool("SOURCE_BROWSER");
+ makeResident();
+ bool hasDocs =
+ (m_impl->details && !m_impl->details->doc.isEmpty()) || // has detailed docs
+ (m_impl->brief && !m_impl->brief->doc.isEmpty()) || // has brief description
+ (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty()) || // has inbody docs
+ extractAll //|| // extract everything
+ // (sourceBrowser && m_impl->body &&
+ // m_impl->body->startLine!=-1 && m_impl->body->fileDef)
+ ; // link to definition
+ return hasDocs;
+}
+
+bool Definition::hasUserDocumentation() const
+{
+ makeResident();
+ bool hasDocs =
+ (m_impl->details && !m_impl->details->doc.isEmpty()) ||
+ (m_impl->brief && !m_impl->brief->doc.isEmpty()) ||
+ (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty());
+ return hasDocs;
+}
+
+void Definition::addSourceReferencedBy(MemberDef *md)
+{
+ if (md)
+ {
+ makeResident();
+ QCString name = md->name();
+ QCString scope = md->getScopeString();
+
+ if (!scope.isEmpty())
+ {
+ name.prepend(scope+"::");
+ }
+
+ if (m_impl->sourceRefByDict==0)
+ {
+ m_impl->sourceRefByDict = new MemberSDict;
+ }
+ if (m_impl->sourceRefByDict->find(name)==0)
+ {
+ m_impl->sourceRefByDict->append(name,md);
+ }
+ }
+}
+
+void Definition::addSourceReferences(MemberDef *md)
+{
+ if (md)
+ {
+ QCString name = md->name();
+ QCString scope = md->getScopeString();
+ makeResident();
+
+ if (!scope.isEmpty())
+ {
+ name.prepend(scope+"::");
+ }
+
+ if (m_impl->sourceRefsDict==0)
+ {
+ m_impl->sourceRefsDict = new MemberSDict;
+ }
+ if (m_impl->sourceRefsDict->find(name)==0)
+ {
+ m_impl->sourceRefsDict->append(name,md);
+ }
+ }
+}
+
+Definition *Definition::findInnerCompound(const char *)
+{
+ return 0;
+}
+
+void Definition::addInnerCompound(Definition *)
+{
+ err("error: Definition::addInnerCompound() called\n");
+}
+
+QCString Definition::qualifiedName() const
+{
+ //static int count=0;
+ //count++;
+ makeResident();
+ if (!m_impl->qualifiedName.isEmpty())
+ {
+ //count--;
+ return m_impl->qualifiedName;
+ }
+
+ //printf("start %s::qualifiedName() localName=%s\n",name().data(),m_impl->localName.data());
+ if (m_impl->outerScope==0)
+ {
+ if (m_impl->localName=="<globalScope>")
+ {
+ //count--;
+ return "";
+ }
+ else
+ {
+ //count--;
+ return m_impl->localName;
+ }
+ }
+
+ if (m_impl->outerScope->name()=="<globalScope>")
+ {
+ m_impl->qualifiedName = m_impl->localName;
+ }
+ else
+ {
+ m_impl->qualifiedName = m_impl->outerScope->qualifiedName()+
+ getLanguageSpecificSeparator(getLanguage())+
+ m_impl->localName;
+ }
+ //printf("end %s::qualifiedName()=%s\n",name().data(),m_impl->qualifiedName.data());
+ //count--;
+ return m_impl->qualifiedName;
+};
+
+void Definition::setOuterScope(Definition *d)
+{
+ makeResident();
+ //printf("%s::setOuterScope(%s)\n",name().data(),d?d->name().data():"<none>");
+ if (m_impl->outerScope!=d)
+ {
+ m_impl->qualifiedName.resize(0); // flush cached scope name
+ m_impl->outerScope = d;
+ }
+ m_impl->hidden = m_impl->hidden || d->isHidden();
+}
+
+QCString Definition::localName() const
+{
+ makeResident();
+ return m_impl->localName;
+}
+
+void Definition::makePartOfGroup(GroupDef *gd)
+{
+ makeResident();
+ if (m_impl->partOfGroups==0) m_impl->partOfGroups = new GroupList;
+ m_impl->partOfGroups->append(gd);
+}
+
+void Definition::setRefItems(const QList<ListItemInfo> *sli)
+{
+ //printf("%s::setRefItems()\n",name().data());
+ if (sli)
+ {
+ makeResident();
+ // deep copy the list
+ if (m_impl->xrefListItems==0)
+ {
+ m_impl->xrefListItems=new QList<ListItemInfo>;
+ m_impl->xrefListItems->setAutoDelete(TRUE);
+ }
+ QListIterator<ListItemInfo> slii(*sli);
+ ListItemInfo *lii;
+ for (slii.toFirst();(lii=slii.current());++slii)
+ {
+ m_impl->xrefListItems->append(new ListItemInfo(*lii));
+ }
+ }
+}
+
+void Definition::mergeRefItems(Definition *d)
+{
+ //printf("%s::mergeRefItems()\n",name().data());
+ LockingPtr< QList<ListItemInfo> > xrefList = d->xrefListItems();
+ if (xrefList!=0)
+ {
+ makeResident();
+ // deep copy the list
+ if (m_impl->xrefListItems==0)
+ {
+ m_impl->xrefListItems=new QList<ListItemInfo>;
+ m_impl->xrefListItems->setAutoDelete(TRUE);
+ }
+ QListIterator<ListItemInfo> slii(*xrefList);
+ ListItemInfo *lii;
+ for (slii.toFirst();(lii=slii.current());++slii)
+ {
+ if (_getXRefListId(lii->type)==-1)
+ {
+ m_impl->xrefListItems->append(new ListItemInfo(*lii));
+ }
+ }
+ }
+}
+
+int Definition::_getXRefListId(const char *listName) const
+{
+ makeResident();
+ if (m_impl->xrefListItems)
+ {
+ QListIterator<ListItemInfo> slii(*m_impl->xrefListItems);
+ ListItemInfo *lii;
+ for (slii.toFirst();(lii=slii.current());++slii)
+ {
+ if (strcmp(lii->type,listName)==0)
+ {
+ return lii->itemId;
+ }
+ }
+ }
+ return -1;
+}
+
+LockingPtr< QList<ListItemInfo> > Definition::xrefListItems() const
+{
+ makeResident();
+ return LockingPtr< QList<ListItemInfo> >(this,m_impl->xrefListItems);
+}
+
+
+QCString Definition::convertNameToFile(const char *name,bool allowDots) const
+{
+ makeResident();
+ if (!m_impl->ref.isEmpty())
+ {
+ return name;
+ }
+ else
+ {
+ return ::convertNameToFile(name,allowDots);
+ }
+}
+
+QCString Definition::pathFragment() const
+{
+ makeResident();
+ QCString result;
+ if (m_impl->outerScope && m_impl->outerScope!=Doxygen::globalScope)
+ {
+ result = m_impl->outerScope->pathFragment();
+ }
+ if (isLinkable())
+ {
+ if (!result.isEmpty()) result+="/";
+ if (definitionType()==Definition::TypeGroup && ((const GroupDef*)this)->groupTitle())
+ {
+ result+=((const GroupDef*)this)->groupTitle();
+ }
+ else if (definitionType()==Definition::TypePage && !((const PageDef*)this)->title().isEmpty())
+ {
+ result+=((const PageDef*)this)->title();
+ }
+ else
+ {
+ result+=m_impl->localName;
+ }
+ }
+ else
+ {
+ result+=m_impl->localName;
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+
+// TODO: move to htmlgen
+/*! Returns the string used in the footer for $navpath when
+ * GENERATE_TREEVIEW is enabled
+ */
+QCString Definition::navigationPathAsString() const
+{
+ makeResident();
+ QCString result;
+ Definition *outerScope = getOuterScope();
+ QCString locName = localName();
+ if (outerScope && outerScope!=Doxygen::globalScope)
+ {
+ result+=outerScope->navigationPathAsString();
+ }
+ else if (definitionType()==Definition::TypeFile && ((const FileDef*)this)->getDirDef())
+ {
+ result+=((const FileDef*)this)->getDirDef()->navigationPathAsString();
+ }
+ result+="<li class=\"navelem\">";
+ if (isLinkable())
+ {
+ if (definitionType()==Definition::TypeGroup && ((const GroupDef*)this)->groupTitle())
+ {
+ result+="<a class=\"el\" href=\"$relpath$"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
+ ((const GroupDef*)this)->groupTitle()+"</a>";
+ }
+ else if (definitionType()==Definition::TypePage && !((const PageDef*)this)->title().isEmpty())
+ {
+ result+="<a class=\"el\" href=\"$relpath$"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
+ ((const PageDef*)this)->title()+"</a>";
+ }
+ else if (definitionType()==Definition::TypeClass)
+ {
+ QCString name = locName;
+ if (name.right(2)=="-p" /*|| name.right(2)=="-g"*/)
+ {
+ name = name.left(name.length()-2);
+ }
+ result+="<a class=\"el\" href=\"$relpath$"+getOutputFileBase()+Doxygen::htmlFileExtension;
+ if (!anchor().isEmpty()) result+="#"+anchor();
+ result+="\">"+name+"</a>";
+ }
+ else
+ {
+ result+="<a class=\"el\" href=\"$relpath$"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
+ locName+"</a>";
+ }
+ }
+ else
+ {
+ result+="<b>"+locName+"</b>";
+ }
+ result+="</li>";
+ return result;
+}
+
+// TODO: move to htmlgen
+void Definition::writeNavigationPath(OutputList &ol) const
+{
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+
+ QCString navPath;
+ navPath += "<div id=\"nav-path\" class=\"navpath\">\n"
+ " <ul>\n";
+ navPath += navigationPathAsString();
+ navPath += " </ul>\n"
+ "</div>\n";
+ ol.writeNavigationPath(navPath);
+
+ ol.popGeneratorState();
+}
+
+// TODO: move to htmlgen
+void Definition::writeToc(OutputList &ol)
+{
+ makeResident();
+ SectionDict *sectionDict = m_impl->sectionDict;
+ if (sectionDict==0) return;
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.writeString("<div class=\"toc\">");
+ ol.writeString("<h3>");
+ ol.writeString(theTranslator->trRTFTableOfContents());
+ ol.writeString("</h3>\n");
+ ol.writeString("<ul>");
+ SDict<SectionInfo>::Iterator li(*sectionDict);
+ SectionInfo *si;
+ int level=1;
+ char cs[2];
+ cs[1]='\0';
+ bool inLi[5]={ FALSE, FALSE, FALSE, FALSE };
+ for (li.toFirst();(si=li.current());++li)
+ {
+ if (si->type==SectionInfo::Section ||
+ si->type==SectionInfo::Subsection ||
+ si->type==SectionInfo::Subsubsection ||
+ si->type==SectionInfo::Paragraph)
+ {
+ //printf(" level=%d title=%s\n",level,si->title.data());
+ int nextLevel = (int)si->type;
+ if (nextLevel>level)
+ {
+ ol.writeString("<ul>");
+ }
+ else if (nextLevel<level)
+ {
+ if (inLi[level]) ol.writeString("</li>\n");
+ inLi[level]=FALSE;
+ ol.writeString("</ul>\n");
+ }
+ cs[0]='0'+nextLevel;
+ if (inLi[nextLevel]) ol.writeString("</li>\n");
+ ol.writeString("<li class=\"level"+QCString(cs)+"\"><a href=\"#"+si->label+"\">"+si->title+"</a>");
+ inLi[nextLevel]=TRUE;
+ level = nextLevel;
+ }
+ }
+ while (level>1)
+ {
+ if (inLi[level]) ol.writeString("</li>\n");
+ inLi[level]=FALSE;
+ ol.writeString("</ul>\n");
+ level--;
+ }
+ if (inLi[level]) ol.writeString("</li>\n");
+ inLi[level]=FALSE;
+ ol.writeString("</ul>\n");
+ ol.writeString("</div>\n");
+ ol.popGeneratorState();
+}
+
+//----------------------------------------------------------------------------------------
+
+
+QCString Definition::symbolName() const
+{
+ return m_symbolName;
+}
+
+//----------------------
+
+QCString Definition::documentation() const
+{
+ makeResident();
+ return m_impl->details ? m_impl->details->doc : QCString("");
+}
+
+int Definition::docLine() const
+{
+ makeResident();
+ return m_impl->details ? m_impl->details->line : 1;
+}
+
+QCString Definition::docFile() const
+{
+ makeResident();
+ return m_impl->details ? m_impl->details->file : QCString("<"+m_name+">");
+}
+
+//----------------------------------------------------------------------------
+// strips w from s iff s starts with w
+static bool stripWord(QCString &s,QCString w)
+{
+ bool success=FALSE;
+ if (s.left(w.length())==w)
+ {
+ success=TRUE;
+ s=s.right(s.length()-w.length());
+ }
+ return success;
+}
+
+//----------------------------------------------------------------------------
+// some quasi intelligent brief description abbreviator :^)
+QCString abbreviate(const char *s,const char *name)
+{
+ QCString scopelessName=name;
+ int i=scopelessName.findRev("::");
+ if (i!=-1) scopelessName=scopelessName.mid(i+2);
+ QCString result=s;
+ result=result.stripWhiteSpace();
+ // strip trailing .
+ if (!result.isEmpty() && result.at(result.length()-1)=='.')
+ result=result.left(result.length()-1);
+
+ // strip any predefined prefix
+ QStrList &briefDescAbbrev = Config_getList("ABBREVIATE_BRIEF");
+ const char *p = briefDescAbbrev.first();
+ while (p)
+ {
+ QCString s = p;
+ s.replace(QRegExp("\\$name"), scopelessName); // replace $name with entity name
+ s += " ";
+ stripWord(result,s);
+ p = briefDescAbbrev.next();
+ }
+
+ // capitalize first word
+ if (!result.isEmpty())
+ {
+ int c=result[0];
+ if (c>='a' && c<='z') c+='A'-'a';
+ result[0]=c;
+ }
+ return result;
+}
+
+
+//----------------------
+
+QCString Definition::briefDescription(bool abbr) const
+{
+ makeResident();
+ return m_impl->brief ?
+ (abbr ? abbreviate(m_impl->brief->doc,displayName()) : m_impl->brief->doc) :
+ QCString("");
+}
+
+QCString Definition::briefDescriptionAsTooltip() const
+{
+ makeResident();
+ LockingPtr<Definition> lock(this,this); // since this can be a memberDef
+ // accessing other memberDefs prevent
+ // it from being flushed to disk
+ if (m_impl->brief)
+ {
+ if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty())
+ {
+ static bool reentering=FALSE;
+ if (!reentering)
+ {
+ MemberDef *md = definitionType()==TypeMember ? (MemberDef*)this : 0;
+ const Definition *scope = definitionType()==TypeMember ? getOuterScope() : this;
+ reentering=TRUE; // prevent requests for tooltips while parsing a tooltip
+ m_impl->brief->tooltip = parseCommentAsText(
+ scope,md,
+ m_impl->brief->doc,
+ m_impl->brief->file,
+ m_impl->brief->line);
+ reentering=FALSE;
+ }
+ }
+ return m_impl->brief->tooltip;
+ }
+ return QCString("");
+}
+
+int Definition::briefLine() const
+{
+ makeResident();
+ return m_impl->brief ? m_impl->brief->line : 1;
+}
+
+QCString Definition::briefFile() const
+{
+ makeResident();
+ return m_impl->brief ? m_impl->brief->file : QCString("<"+m_name+">");
+}
+
+//----------------------
+
+QCString Definition::inbodyDocumentation() const
+{
+ makeResident();
+ return m_impl->inbodyDocs ? m_impl->inbodyDocs->doc : QCString("");
+}
+
+int Definition::inbodyLine() const
+{
+ makeResident();
+ return m_impl->inbodyDocs ? m_impl->inbodyDocs->line : 1;
+}
+
+QCString Definition::inbodyFile() const
+{
+ makeResident();
+ return m_impl->inbodyDocs ? m_impl->inbodyDocs->file : QCString("<"+m_name+">");
+}
+
+
+//----------------------
+
+QCString Definition::getDefFileName() const
+{
+ makeResident();
+ return m_impl->defFileName;
+}
+
+QCString Definition::getDefFileExtension() const
+{
+ makeResident();
+ return m_impl->defFileExt;
+}
+
+bool Definition::isHidden() const
+{
+ makeResident();
+ return m_impl->hidden;
+}
+
+bool Definition::isVisibleInProject() const
+{
+ return isLinkableInProject() && !m_impl->hidden;
+}
+
+bool Definition::isVisible() const
+{
+ return isLinkable() && !m_impl->hidden;
+}
+
+bool Definition::isArtificial() const
+{
+ return m_impl->isArtificial;
+}
+
+QCString Definition::getReference() const
+{
+ makeResident();
+ return m_impl->ref;
+}
+
+bool Definition::isReference() const
+{
+ makeResident();
+ return !m_impl->ref.isEmpty();
+}
+
+int Definition::getStartBodyLine() const
+{
+ makeResident();
+ return m_impl->body ? m_impl->body->startLine : -1;
+}
+
+int Definition::getEndBodyLine() const
+{
+ makeResident();
+ return m_impl->body ? m_impl->body->endLine : -1;
+}
+
+FileDef *Definition::getBodyDef()
+{
+ makeResident();
+ return m_impl->body ? m_impl->body->fileDef : 0;
+}
+
+LockingPtr<GroupList> Definition::partOfGroups() const
+{
+ makeResident();
+ return LockingPtr<GroupList>(this,m_impl->partOfGroups);
+}
+
+Definition *Definition::getOuterScope() const
+{
+ makeResident();
+ return m_impl->outerScope;
+}
+
+LockingPtr<MemberSDict> Definition::getReferencesMembers() const
+{
+ makeResident();
+ return LockingPtr<MemberSDict>(this,m_impl->sourceRefsDict);
+}
+
+LockingPtr<MemberSDict> Definition::getReferencedByMembers() const
+{
+ makeResident();
+ return LockingPtr<MemberSDict>(this,m_impl->sourceRefByDict);
+}
+
+void Definition::setReference(const char *r)
+{
+ makeResident();
+ m_impl->ref=r;
+}
+
+SrcLangExt Definition::getLanguage() const
+{
+ makeResident();
+ return m_impl->lang;
+}
+
+void Definition::setHidden(bool b)
+{
+ makeResident();
+ m_impl->hidden = m_impl->hidden || b;
+}
+
+void Definition::setArtificial(bool b)
+{
+ makeResident();
+ m_impl->isArtificial = b;
+}
+
+void Definition::setLocalName(const QCString name)
+{
+ makeResident();
+ m_impl->localName=name;
+}
+
+void Definition::setLanguage(SrcLangExt lang)
+{
+ makeResident();
+ m_impl->lang=lang;
+}
+
+void Definition::makeResident() const
+{
+}
+
+//---------------
+
+void Definition::_setSymbolName(const QCString &name)
+{
+ m_symbolName=name;
+}
+
+void Definition::flushToDisk() const
+{
+ //printf("%p: Definition::flushToDisk()\n",this);
+ Definition *that = (Definition *)this;
+ //printf("Definition::flushToDisk(): pos=%d\n",(int)m_storagePos);
+ marshalUInt(Doxygen::symbolStorage,START_MARKER);
+ marshalSectionDict (Doxygen::symbolStorage,m_impl->sectionDict);
+ marshalMemberSDict (Doxygen::symbolStorage,m_impl->sourceRefByDict);
+ marshalMemberSDict (Doxygen::symbolStorage,m_impl->sourceRefsDict);
+ marshalItemInfoList (Doxygen::symbolStorage,m_impl->xrefListItems);
+ marshalGroupList (Doxygen::symbolStorage,m_impl->partOfGroups);
+ marshalDocInfo (Doxygen::symbolStorage,m_impl->details);
+ marshalDocInfo (Doxygen::symbolStorage,m_impl->inbodyDocs);
+ marshalBriefInfo (Doxygen::symbolStorage,m_impl->brief);
+ marshalBodyInfo (Doxygen::symbolStorage,m_impl->body);
+ marshalQCString (Doxygen::symbolStorage,m_impl->docSignatures);
+ marshalQCString (Doxygen::symbolStorage,m_impl->localName);
+ marshalQCString (Doxygen::symbolStorage,m_impl->qualifiedName);
+ marshalQCString (Doxygen::symbolStorage,m_impl->ref);
+ marshalBool (Doxygen::symbolStorage,m_impl->hidden);
+ marshalBool (Doxygen::symbolStorage,m_impl->isArtificial);
+ marshalObjPointer (Doxygen::symbolStorage,m_impl->outerScope);
+ marshalQCString (Doxygen::symbolStorage,m_impl->defFileName);
+ marshalQCString (Doxygen::symbolStorage,m_impl->defFileExt);
+ marshalInt (Doxygen::symbolStorage,(int)m_impl->lang);
+ marshalUInt(Doxygen::symbolStorage,END_MARKER);
+ delete that->m_impl;
+ that->m_impl = 0;
+}
+
+void Definition::loadFromDisk() const
+{
+ //printf("%p: Definition::loadFromDisk()\n",this);
+ Definition *that = (Definition *)this;
+ assert(m_impl==0);
+ that->m_impl = new DefinitionImpl;
+ uint marker = unmarshalUInt(Doxygen::symbolStorage);
+ assert(marker==START_MARKER);
+ m_impl->sectionDict = unmarshalSectionDict (Doxygen::symbolStorage);
+ m_impl->sourceRefByDict = unmarshalMemberSDict (Doxygen::symbolStorage);
+ m_impl->sourceRefsDict = unmarshalMemberSDict (Doxygen::symbolStorage);
+ m_impl->xrefListItems = unmarshalItemInfoList (Doxygen::symbolStorage);
+ m_impl->partOfGroups = unmarshalGroupList (Doxygen::symbolStorage);
+ m_impl->details = unmarshalDocInfo (Doxygen::symbolStorage);
+ m_impl->inbodyDocs = unmarshalDocInfo (Doxygen::symbolStorage);
+ m_impl->brief = unmarshalBriefInfo (Doxygen::symbolStorage);
+ m_impl->body = unmarshalBodyInfo (Doxygen::symbolStorage);
+ m_impl->docSignatures = unmarshalQCString (Doxygen::symbolStorage);
+ m_impl->localName = unmarshalQCString (Doxygen::symbolStorage);
+ m_impl->qualifiedName = unmarshalQCString (Doxygen::symbolStorage);
+ m_impl->ref = unmarshalQCString (Doxygen::symbolStorage);
+ m_impl->hidden = unmarshalBool (Doxygen::symbolStorage);
+ m_impl->isArtificial = unmarshalBool (Doxygen::symbolStorage);
+ m_impl->outerScope = (Definition *)unmarshalObjPointer (Doxygen::symbolStorage);
+ m_impl->defFileName = unmarshalQCString (Doxygen::symbolStorage);
+ m_impl->defFileExt = unmarshalQCString (Doxygen::symbolStorage);
+ m_impl->lang = (SrcLangExt)unmarshalInt(Doxygen::symbolStorage);
+ marker = unmarshalUInt(Doxygen::symbolStorage);
+ assert(marker==END_MARKER);
+}
+