Orb/Doxygen/src/definition.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     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("&nbsp;");
       
  1254       ol.writeString("&raquo;");
       
  1255       ol.writeString("&nbsp;");
       
  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