Fix for UBSan build
[platform/upstream/doxygen.git] / src / memberdef.cpp
1 /******************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2012 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 <stdio.h>
19 #include <qglobal.h>
20 #include <qregexp.h>
21 #include <assert.h>
22 #include "md5.h"
23 #include "memberdef.h"
24 #include "membername.h"
25 #include "doxygen.h"
26 #include "util.h"
27 #include "code.h"
28 #include "message.h"
29 #include "htmlhelp.h"
30 #include "language.h"
31 #include "outputlist.h"
32 #include "example.h"
33 #include "membergroup.h"
34 #include "groupdef.h"
35 #include "defargs.h"
36 #include "docparser.h"
37 #include "dot.h"
38 #include "searchindex.h"
39 #include "parserintf.h"
40 #include "marshal.h"
41 #include "objcache.h"
42 #include "vhdlscanner.h"
43 #include "vhdldocgen.h"
44 #include "arguments.h"
45
46 #define START_MARKER 0x4D454D5B // MEM[
47 #define END_MARKER   0x4D454D5D // MEM]
48
49 #if defined(_OS_WIN32_)
50 #define snprintf _snprintf
51 #endif
52
53 // Put this macro at the start of any method of MemberDef that can directly
54 // or indirectly access other MemberDefs. It prevents that the content 
55 // pointed to by m_impl gets flushed to disk in the middle of the method call!
56 #define KEEP_RESIDENT_DURING_CALL makeResident();LockingPtr<MemberDef> lock(this,this)
57
58 //-----------------------------------------------------------------------------
59
60 int MemberDef::s_indentLevel = 0;
61
62 //-----------------------------------------------------------------------------
63
64 static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t)
65 {
66   QCString result;
67   QCString clRealName=n;
68   int p=0,i;
69   if ((i=clRealName.find('<'))!=-1)
70   {
71     clRealName=clRealName.left(i); // strip template specialization
72   }
73   if ((i=clRealName.findRev("::"))!=-1)
74   {
75     clRealName=clRealName.right(clRealName.length()-i-2);
76   }
77   while ((i=s.find(clRealName,p))!=-1)
78   {
79     result+=s.mid(p,i-p);
80     uint j=clRealName.length()+i;
81     if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j))))
82     { // add template names
83       //printf("Adding %s+%s\n",clRealName.data(),t.data());
84       result+=clRealName+t; 
85     }
86     else 
87     { // template names already present
88       //printf("Adding %s\n",clRealName.data());
89       result+=clRealName;
90     }
91     p=i+clRealName.length();
92   }
93   result+=s.right(s.length()-p);
94   //printf("addTemplateNames(%s,%s,%s)=%s\n",s.data(),n.data(),t.data(),result.data());
95   return result;
96 }
97
98 static bool writeDefArgumentList(OutputList &ol,ClassDef *cd,
99                                  const QCString & /*scopeName*/,MemberDef *md)
100 {
101   LockingPtr<ArgumentList> defArgList=(md->isDocsForDefinition()) ? 
102                              md->argumentList() : md->declArgumentList();
103   //printf("writeDefArgumentList `%s' isDocsForDefinition()=%d\n",md->name().data(),md->isDocsForDefinition());
104   if (defArgList==0 || md->isProperty()) 
105   {
106     return FALSE; // member has no function like argument list
107   }
108   if (!md->isDefine()) ol.docify(" ");
109
110   // simple argument list for tcl
111   if (md->getLanguage()==SrcLangExt_Tcl)
112   {
113     Argument *a=defArgList->first();
114     ol.startParameterName(FALSE);
115     while (a) 
116     {
117       if (a->defval.isEmpty())
118       {
119         ol.docify(a->name+" ");
120       }
121       else
122       {
123         ol.docify("?"+a->name+"? ");
124       }
125       a=defArgList->next();
126     }
127     ol.endParameterName(FALSE,FALSE,FALSE);
128     ol.endMemberDocName();
129     return TRUE;
130   }
131
132   //printf("writeDefArgList(%d)\n",defArgList->count());
133   ol.pushGeneratorState();
134   //ol.disableAllBut(OutputGenerator::Html);
135   bool htmlOn  = ol.isEnabled(OutputGenerator::Html);
136   bool latexOn = ol.isEnabled(OutputGenerator::Latex);
137   {
138     // html and latex
139     if (htmlOn)  ol.enable(OutputGenerator::Html);
140     if (latexOn) ol.enable(OutputGenerator::Latex);
141
142     ol.endMemberDocName();
143     ol.startParameterList(!md->isObjCMethod()); 
144   }
145   ol.enableAll();
146   ol.disable(OutputGenerator::Html);
147   ol.disable(OutputGenerator::Latex);
148   {
149     // other formats
150     if (!md->isObjCMethod()) ol.docify("("); // start argument list
151     ol.endMemberDocName();
152   }
153   ol.popGeneratorState();
154   //printf("===> name=%s isDefine=%d\n",md->name().data(),md->isDefine());
155
156   Argument *a=defArgList->first();
157   QCString cName;
158   if (cd)
159   {
160     cName=cd->name();
161     int il=cName.find('<');
162     int ir=cName.findRev('>');
163     if (il!=-1 && ir!=-1 && ir>il)
164     {
165       cName=cName.mid(il,ir-il+1);
166       //printf("1. cName=%s\n",cName.data());
167     }
168     else if (cd->templateArguments())
169     {
170       cName=tempArgListToString(cd->templateArguments()); 
171       //printf("2. cName=%s\n",cName.data());
172     }
173     else // no template specifier
174     {
175       cName.resize(0);
176     }
177   }
178   //printf("~~~ %s cName=%s\n",md->name().data(),cName.data());
179
180   bool first=TRUE;
181   bool paramTypeStarted=FALSE;
182   bool isDefine = md->isDefine();
183   while (a)
184   {
185     if (isDefine || first) 
186     {
187       ol.startParameterType(first,0);
188       paramTypeStarted=TRUE;
189       if (isDefine)
190       {
191         ol.endParameterType();
192         ol.startParameterName(TRUE);
193       }
194     }
195     QRegExp re(")("),res("(.*\\*");
196     int vp=a->type.find(re);
197     int wp=a->type.find(res);
198
199     // use the following to put the function pointer type before the name
200     bool hasFuncPtrType=FALSE; 
201
202     if (!a->attrib.isEmpty() && !md->isObjCMethod()) // argument has an IDL attribute
203     {
204       ol.docify(a->attrib+" ");
205     }
206     if (hasFuncPtrType) // argument type is a function pointer
207     {
208       //printf("a->type=`%s' a->name=`%s'\n",a->type.data(),a->name.data());
209       QCString n=a->type.left(vp);
210       if (hasFuncPtrType) n=a->type.left(wp);
211       if (md->isObjCMethod()) { n.prepend("("); n.append(")"); }
212       if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName);
213       linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,n);
214     }
215     else // non-function pointer type
216     {
217       QCString n=a->type;
218       if (md->isObjCMethod()) { n.prepend("("); n.append(")"); }
219       if (a->type!="...")
220       {
221         if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName);
222         linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,n);
223       }
224     }
225     if (!isDefine)
226     {
227       if (paramTypeStarted) 
228       {
229         ol.endParameterType();
230         paramTypeStarted=FALSE;
231       }
232       ol.startParameterName(defArgList->count()<2);
233     }
234     if (hasFuncPtrType)
235     {
236       ol.docify(a->type.mid(wp,vp-wp)); 
237     }
238     if (!a->name.isEmpty() || (a->name.isEmpty() && a->type=="...")) // argument has a name
239     { 
240       //if (!hasFuncPtrType)
241       //{
242       //  ol.docify(" ");
243       //}
244       ol.disable(OutputGenerator::Man);
245       ol.disable(OutputGenerator::Latex);
246       ol.startEmphasis();
247       ol.enable(OutputGenerator::Man);
248       if (latexOn) ol.enable(OutputGenerator::Latex);
249       if (a->name.isEmpty()) ol.docify(a->type); else ol.docify(a->name);
250       ol.disable(OutputGenerator::Man);
251       ol.disable(OutputGenerator::Latex);
252       ol.endEmphasis();
253       ol.enable(OutputGenerator::Man);
254       if (latexOn) ol.enable(OutputGenerator::Latex);
255     }
256     if (!a->array.isEmpty())
257     {
258       ol.docify(a->array);
259     }
260     if (hasFuncPtrType) // write the part of the argument type 
261                         // that comes after the name
262     {
263       linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),
264                   md,a->type.right(a->type.length()-vp));
265     }
266     if (!a->defval.isEmpty()) // write the default value
267     {
268       QCString n=a->defval;
269       if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName);
270       ol.docify(" = ");
271
272       ol.startTypewriter();
273       linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,n,FALSE,TRUE,TRUE); 
274       ol.endTypewriter();
275
276     }
277     a=defArgList->next();
278     if (a) 
279     {
280       if (!md->isObjCMethod()) ol.docify(", "); // there are more arguments
281       if (!isDefine) 
282       {
283         QCString key;
284         if (md->isObjCMethod() && a->attrib.length()>=2)
285         {
286           //printf("Found parameter keyword %s\n",a->attrib.data());
287           // strip [ and ]
288           key=a->attrib.mid(1,a->attrib.length()-2);
289           if (key!=",") key+=":"; // for normal keywords add colon
290         }
291         ol.endParameterName(FALSE,FALSE,!md->isObjCMethod());
292         if (paramTypeStarted) 
293         {
294           ol.endParameterType();
295         }
296         ol.startParameterType(FALSE,key);
297         paramTypeStarted=TRUE;
298       }
299       else // isDefine
300       {
301         ol.endParameterName(FALSE,FALSE,TRUE);
302       }
303     }
304     first=FALSE;
305   }
306   ol.pushGeneratorState();
307   ol.disable(OutputGenerator::Html);
308   ol.disable(OutputGenerator::Latex);
309   if (!md->isObjCMethod()) ol.docify(")"); // end argument list
310   ol.enableAll();
311   if (htmlOn) ol.enable(OutputGenerator::Html);
312   if (latexOn) ol.enable(OutputGenerator::Latex);
313   if (first) ol.startParameterName(defArgList->count()<2);
314   ol.endParameterName(TRUE,defArgList->count()<2,!md->isObjCMethod());
315   ol.popGeneratorState();
316   if (md->extraTypeChars())
317   {
318     ol.docify(md->extraTypeChars());
319   }
320   if (defArgList->constSpecifier)
321   {
322     ol.docify(" const");
323   }
324   if (defArgList->volatileSpecifier)
325   {
326     ol.docify(" volatile");
327   }
328   if (!defArgList->trailingReturnType.isEmpty())
329   {
330     linkifyText(TextGeneratorOLImpl(ol), // out
331                 cd,                      // scope
332                 md->getBodyDef(),        // fileScope
333                 md,                      // self
334                 defArgList->trailingReturnType, // text
335                 FALSE                    // autoBreak
336                ); 
337
338   }
339   return TRUE;
340 }
341
342 static void writeTemplatePrefix(OutputList &ol,ArgumentList *al)
343 {
344   ol.docify("template<");
345   Argument *a=al->first();
346   while (a)
347   {
348     ol.docify(a->type);
349     ol.docify(" ");
350     ol.docify(a->name);
351     if (a->defval.length()!=0)
352     {
353       ol.docify(" = ");
354       ol.docify(a->defval);
355     } 
356     a=al->next();
357     if (a) ol.docify(", ");
358   }
359   ol.docify("> ");
360 }
361
362 QCString extractDirection(QCString &docs)
363 {
364   QRegExp re("\\[[^\\]]+\\]"); // [...]
365   int l=0;
366   if (re.match(docs,0,&l)==0)
367   {
368     int  inPos  = docs.find("in", 1,FALSE);
369     int outPos  = docs.find("out",1,FALSE);
370     bool input  =  inPos!=-1 &&  inPos<l;
371     bool output = outPos!=-1 && outPos<l;
372     if (input || output) // in,out attributes
373     {
374       docs = docs.mid(l); // strip attributes
375       if (input && output) return "[in,out]";
376       else if (input)      return "[in]";
377       else if (output)     return "[out]";
378     }
379   }
380   return QCString();
381 }
382
383 //-----------------------------------------------------------------------------
384 //-----------------------------------------------------------------------------
385 //-----------------------------------------------------------------------------
386
387 class MemberDefImpl
388 {
389   public:
390     MemberDefImpl();
391    ~MemberDefImpl();
392     void init(Definition *def,const char *t,const char *a,const char *e,
393               Protection p,Specifier v,bool s,Relationship r,
394               MemberDef::MemberType mt,const ArgumentList *tal,
395               const ArgumentList *al
396              );
397
398     ClassDef     *classDef;   // member of or related to 
399     FileDef      *fileDef;    // member of file definition 
400     NamespaceDef *nspace;     // the namespace this member is in.
401
402     MemberDef  *enumScope;    // the enclosing scope, if this is an enum field
403     MemberDef  *annEnumType;  // the anonymous enum that is the type of this member
404     MemberList *enumFields;   // enumeration fields
405
406     MemberDef  *redefines;    // the members that this member redefines 
407     MemberList *redefinedBy;  // the list of members that redefine this one
408
409     MemberDef  *memDef;       // member definition for this declaration
410     MemberDef  *memDec;       // member declaration for this definition
411     ClassDef   *relatedAlso;  // points to class marked by relatedAlso
412
413     ExampleSDict *exampleSDict; // a dictionary of all examples for quick access
414
415     QCString type;            // return actual type
416     QCString accessorType;    // return type that tell how to get to this member
417     ClassDef *accessorClass;  // class that this member accesses (for anonymous types)
418     QCString args;            // function arguments/variable array specifiers
419     QCString def;             // member definition in code (fully qualified name)
420     QCString anc;             // HTML anchor name
421     Specifier virt;           // normal/virtual/pure virtual
422     Protection prot;          // protection type [Public/Protected/Private]
423     QCString decl;            // member declaration in class
424
425     QCString bitfields;       // struct member bitfields
426     QCString read;            // property read accessor
427     QCString write;           // property write accessor
428     QCString exception;       // exceptions that can be thrown
429     QCString initializer;     // initializer
430     QCString extraTypeChars;  // extra type info found after the argument list
431     QCString enumBaseType;    // base type of the enum (C++11)
432     int initLines;            // number of lines in the initializer
433
434     int  memSpec;             // The specifiers present for this member
435     MemberDef::MemberType mtype;         // returns the kind of member
436     int maxInitLines;         // when the initializer will be displayed 
437     int userInitLines;        // result of explicit \hideinitializer or \showinitializer
438     MemberDef  *annMemb;
439
440     ArgumentList *defArgList;    // argument list of this member definition
441     ArgumentList *declArgList;   // argument list of this member declaration
442
443     ArgumentList *tArgList;      // template argument list of function template
444     ArgumentList *typeConstraints; // type constraints for template parameters
445     MemberDef *templateMaster;
446     QList<ArgumentList> *defTmpArgLists; // lists of template argument lists 
447                                          // (for template functions in nested template classes)
448
449     ClassDef *cachedAnonymousType; // if the member has an anonymous compound
450                                    // as its type then this is computed by
451                                    // getClassDefOfAnonymousType() and 
452                                    // cached here. 
453     SDict<MemberList> *classSectionSDict; // not accessible
454
455     MemberDef *groupAlias;    // Member containing the definition
456     int grpId;                // group id
457     MemberGroup *memberGroup; // group's member definition
458     GroupDef *group;          // group in which this member is in
459     Grouping::GroupPri_t grouppri; // priority of this definition
460     QCString groupFileName;   // file where this grouping was defined
461     int groupStartLine;       // line  "      "      "     "     "
462     MemberDef *groupMember;
463
464     bool isTypedefValCached;
465     ClassDef *cachedTypedefValue;
466     QCString cachedTypedefTemplSpec;
467     QCString cachedResolvedType;
468     
469     // inbody documentation
470     //int inbodyLine;
471     //QCString inbodyFile;
472     //QCString inbodyDocs;
473
474     // documentation inheritance
475     MemberDef *docProvider;
476
477     // to store the output file base from tag files
478     QCString explicitOutputFileBase;
479
480     // objective-c
481     bool implOnly; // function found in implementation but not 
482                      // in the interface
483     bool hasDocumentedParams;
484     bool hasDocumentedReturnType;
485     bool isDMember;
486     Relationship related;     // relationship of this to the class
487     bool stat;                // is it a static function?
488     bool proto;               // is it a prototype;
489     bool docEnumValues;       // is an enum with documented enum values.
490     bool annScope;            // member is part of an annoymous scope
491     bool annUsed;             
492     bool hasCallGraph;
493     bool hasCallerGraph;
494     bool explExt;             // member was explicitly declared external
495     bool tspec;               // member is a template specialization
496     bool groupHasDocs;        // true if the entry that caused the grouping was documented
497     bool docsForDefinition;   // TRUE => documentation block is put before
498                               //         definition.
499                               // FALSE => block is put before declaration.
500     ClassDef *category;
501     MemberDef *categoryRelation;
502 };
503
504 MemberDefImpl::MemberDefImpl() :
505     enumFields(0),
506     redefinedBy(0),
507     exampleSDict(0),
508     defArgList(0),
509     declArgList(0),
510     tArgList(0),
511     typeConstraints(0),
512     defTmpArgLists(0),
513     classSectionSDict(0),
514     category(0),
515     categoryRelation(0)
516 {
517 }
518
519 MemberDefImpl::~MemberDefImpl()
520 {
521   delete redefinedBy;
522   delete exampleSDict;
523   delete enumFields;
524   delete defArgList;
525   delete tArgList;
526   delete typeConstraints;
527   delete defTmpArgLists;
528   delete classSectionSDict;
529   delete declArgList;
530 }
531
532 void MemberDefImpl::init(Definition *def,
533                      const char *t,const char *a,const char *e,
534                      Protection p,Specifier v,bool s,Relationship r,
535                      MemberDef::MemberType mt,const ArgumentList *tal,
536                      const ArgumentList *al
537                     )
538 {
539   classDef=0;
540   fileDef=0;
541   redefines=0;
542   relatedAlso=0;
543   redefinedBy=0;
544   accessorClass=0;
545   nspace=0;
546   memDef=0;
547   memDec=0;
548   group=0;
549   grpId=-1;
550   exampleSDict=0;
551   enumFields=0;
552   enumScope=0;
553   defTmpArgLists=0;
554   hasCallGraph = FALSE;
555   hasCallerGraph = FALSE;
556   initLines=0;
557   type=t;
558   if (mt==MemberDef::Typedef) type.stripPrefix("typedef ");
559   //  type.stripPrefix("struct ");
560   //  type.stripPrefix("class " );
561   //  type.stripPrefix("union " );
562   type=removeRedundantWhiteSpace(type);
563   args=a;
564   args=removeRedundantWhiteSpace(args);
565   if (type.isEmpty()) decl=def->name()+args; else decl=type+" "+def->name()+args;
566
567   memberGroup=0;
568   virt=v;
569   prot=p;
570   related=r;
571   stat=s;
572   mtype=mt;
573   exception=e;
574   proto=FALSE;
575   annScope=FALSE;
576   memSpec=0;
577   annMemb=0;
578   annUsed=FALSE;
579   annEnumType=0;
580   groupAlias=0;
581   explExt=FALSE;
582   tspec=FALSE;
583   cachedAnonymousType=0;
584   maxInitLines=Config_getInt("MAX_INITIALIZER_LINES");
585   userInitLines=-1;
586   docEnumValues=FALSE;
587   // copy function template arguments (if any)
588   if (tal)
589   {
590     tArgList = tal->deepCopy();
591   }
592   else
593   {
594     tArgList=0;
595   }
596   //printf("new member al=%p\n",al);
597   // copy function definition arguments (if any)
598   if (al)
599   {
600     defArgList = al->deepCopy();
601   }
602   else
603   {
604     defArgList=0;
605   }
606   // convert function declaration arguments (if any)
607   if (!args.isEmpty())
608   {
609     declArgList = new ArgumentList;
610     stringToArgumentList(args,declArgList,&extraTypeChars);
611     //printf("setDeclArgList %s to %s const=%d\n",args.data(),
612     //    argListToString(declArgList).data(),declArgList->constSpecifier);
613   }
614   else
615   {
616     declArgList = 0;
617   }
618   templateMaster = 0;
619   classSectionSDict = 0;
620   docsForDefinition = TRUE;
621   isTypedefValCached = FALSE;
622   cachedTypedefValue = 0;
623   //inbodyLine = -1;
624   implOnly=FALSE;
625   groupMember = 0;
626   hasDocumentedParams = FALSE;
627   hasDocumentedReturnType = FALSE;
628   docProvider = 0;
629   isDMember = def->getDefFileName().right(2).lower()==".d";
630 }
631
632
633 //-----------------------------------------------------------------------------
634 //-----------------------------------------------------------------------------
635 //-----------------------------------------------------------------------------
636
637 /*! Creates a new member definition.
638  *
639  * \param df File containing the definition of this member.
640  * \param dl Line at which the member definition was found.
641  * \param t  A string representing the type of the member.
642  * \param na A string representing the name of the member.
643  * \param a  A string representing the arguments of the member.
644  * \param e  A string representing the throw clause of the members.
645  * \param p  The protection context of the member, possible values are:
646  *           \c Public, \c Protected, \c Private.
647  * \param v  The degree of `virtualness' of the member, possible values are:
648  *           \c Normal, \c Virtual, \c Pure.
649  * \param s  A boolean that is true iff the member is static.
650  * \param r  The relationship between the class and the member.
651  * \param mt The kind of member. See #MemberDef::MemberType for a list of 
652  *           all types.
653  * \param tal The template arguments of this member.
654  * \param al  The arguments of this member. This is a structured form of 
655  *            the string past as argument \a a.
656  */
657
658 MemberDef::MemberDef(const char *df,int dl,
659                      const char *t,const char *na,const char *a,const char *e,
660                      Protection p,Specifier v,bool s,Relationship r,MemberType mt,
661                      const ArgumentList *tal,const ArgumentList *al
662                     ) : Definition(df,dl,removeRedundantWhiteSpace(na))
663 {
664   //printf("MemberDef::MemberDef(%s)\n",na);
665   m_storagePos=-1;
666   m_cacheHandle=-1;
667   m_impl = new MemberDefImpl;
668   m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al);
669   m_flushPending = FALSE;
670   m_isLinkableCached    = 0;
671   m_isConstructorCached = 0;
672   m_isDestructorCached  = 0;
673 }
674
675 MemberDef::MemberDef(const MemberDef &md) : Definition(md)
676 {
677   m_storagePos=-1;
678   m_cacheHandle=-1;
679   m_impl = new MemberDefImpl;
680   m_flushPending = FALSE;
681   m_isLinkableCached    = 0;
682   m_isConstructorCached = 0;
683   m_isDestructorCached  = 0;
684 }
685
686 MemberDef *MemberDef::deepCopy() const
687 {
688   makeResident();
689   //MemberDef *result = new MemberDef(getDefFileName(),getDefLine(),name());
690   MemberDef *result = new MemberDef(*this);
691   // first copy everything by reference
692   *result->m_impl = *m_impl;
693   // clear pointers owned by object
694   result->m_impl->redefinedBy= 0;
695   result->m_impl->exampleSDict=0;
696   result->m_impl->enumFields=0;
697   result->m_impl->defArgList=0;
698   result->m_impl->tArgList=0;
699   result->m_impl->typeConstraints=0;
700   result->m_impl->defTmpArgLists=0;
701   result->m_impl->classSectionSDict=0;
702   result->m_impl->declArgList=0;
703   // replace pointers owned by the object by deep copies 
704   if (m_impl->redefinedBy)
705   {
706     MemberListIterator mli(*m_impl->redefinedBy);
707     MemberDef *md;
708     for (mli.toFirst();(md=mli.current());++mli)
709     {
710       result->insertReimplementedBy(md);
711     }
712   }
713   if (m_impl->exampleSDict)
714   {
715     ExampleSDict::Iterator it(*m_impl->exampleSDict);
716     Example *e;
717     for (it.toFirst();(e=it.current());++it)
718     {
719       result->addExample(e->anchor,e->name,e->file);
720     }
721   }
722   if (m_impl->enumFields)
723   {
724     MemberListIterator mli(*m_impl->redefinedBy);
725     MemberDef *md;
726     for (mli.toFirst();(md=mli.current());++mli)
727     {
728       result->insertEnumField(md);
729     }
730   }
731   if (m_impl->defArgList)
732   {
733     result->m_impl->defArgList = m_impl->defArgList->deepCopy();
734   }
735   if (m_impl->tArgList)
736   {
737     result->m_impl->tArgList = m_impl->tArgList->deepCopy();
738   }
739   if (m_impl->typeConstraints)
740   {
741     result->m_impl->typeConstraints = m_impl->typeConstraints->deepCopy();
742   }
743   result->setDefinitionTemplateParameterLists(m_impl->defTmpArgLists);
744   if (m_impl->classSectionSDict)
745   {
746     result->m_impl->classSectionSDict = new SDict<MemberList>(7);
747     SDict<MemberList>::IteratorDict it(*m_impl->classSectionSDict);
748     MemberList *ml;
749     for (it.toFirst();(ml=it.current());++it)
750     {
751       result->m_impl->classSectionSDict->append(it.currentKey(),ml);
752     }
753   }
754   if (m_impl->declArgList)
755   {
756     result->m_impl->declArgList = m_impl->declArgList->deepCopy();
757   }
758   return result;
759 }
760
761 void MemberDef::moveTo(Definition *scope)
762 {
763    setOuterScope(scope);
764    if (scope->definitionType()==Definition::TypeClass)
765    {
766      m_impl->classDef = (ClassDef*)scope;
767    }
768    else if (scope->definitionType()==Definition::TypeFile)
769    {
770      m_impl->fileDef = (FileDef*)scope;
771    }
772    else if (scope->definitionType()==Definition::TypeNamespace)
773    {
774      m_impl->nspace = (NamespaceDef*)scope;
775    }
776    m_isLinkableCached = 0; 
777    m_isConstructorCached = 0; 
778 }
779
780
781 /*! Destroys the member definition. */
782 MemberDef::~MemberDef()
783 {
784   delete m_impl;
785   //printf("%p: ~MemberDef()\n",this);
786   m_impl=0;
787   if (m_cacheHandle!=-1)
788   {
789     Doxygen::symbolCache->del(m_cacheHandle);
790     m_cacheHandle=-1;
791   }
792 }
793
794 void MemberDef::setReimplements(MemberDef *md)   
795
796   makeResident();
797
798   m_impl->redefines = md;
799 }
800
801 void MemberDef::insertReimplementedBy(MemberDef *md)
802 {
803   makeResident();
804   if (m_impl->templateMaster)
805   {
806     m_impl->templateMaster->insertReimplementedBy(md);
807   }
808   if (m_impl->redefinedBy==0) m_impl->redefinedBy = new MemberList(MemberList::redefinedBy);
809   if (m_impl->redefinedBy->findRef(md)==-1) 
810   {
811     m_impl->redefinedBy->inSort(md);
812   }
813 }
814
815 MemberDef *MemberDef::reimplements() const      
816
817   makeResident();
818   return m_impl->redefines; 
819 }
820
821 LockingPtr<MemberList> MemberDef::reimplementedBy() const   
822
823   makeResident();
824   return LockingPtr<MemberList>(this,m_impl->redefinedBy); 
825 }
826
827 bool MemberDef::isReimplementedBy(ClassDef *cd) const
828 {
829   makeResident();
830   if (cd && m_impl->redefinedBy)
831   {
832     MemberListIterator mi(*m_impl->redefinedBy);
833     MemberDef *md;
834     for (mi.toFirst();(md=mi.current());++mi)
835     {
836       ClassDef *mcd = md->getClassDef();
837       if (mcd)
838       {
839         if (cd==mcd || cd->isBaseClass(mcd,TRUE))
840         {
841           return TRUE;
842         }
843       }
844     }
845   }
846   return FALSE;
847 }
848
849 void MemberDef::insertEnumField(MemberDef *md)
850 {
851   makeResident();
852   if (m_impl->enumFields==0) m_impl->enumFields=new MemberList(MemberList::enumFields);
853   m_impl->enumFields->append(md);
854 }
855
856 bool MemberDef::addExample(const char *anchor,const char *nameStr,
857                            const char *file)
858 {
859   makeResident();
860   //printf("%s::addExample(%s,%s,%s)\n",name().data(),anchor,nameStr,file);
861   if (m_impl->exampleSDict==0) m_impl->exampleSDict = new ExampleSDict;
862   if (m_impl->exampleSDict->find(nameStr)==0) 
863   {
864     //printf("Add reference to example %s to member %s\n",nameStr,name.data());
865     Example *e=new Example;
866     e->anchor=anchor;
867     e->name=nameStr;
868     e->file=file;
869     m_impl->exampleSDict->inSort(nameStr,e);
870     return TRUE;
871   }
872   return FALSE; 
873 }
874
875 bool MemberDef::hasExamples()
876 {
877   makeResident();
878   if (m_impl->exampleSDict==0) 
879     return FALSE;
880   else
881     return m_impl->exampleSDict->count()>0;
882 }
883
884 QCString MemberDef::getOutputFileBase() const
885 {
886   makeResident();
887   static bool separateMemberPages = Config_getBool("SEPARATE_MEMBER_PAGES");
888   QCString baseName;
889   //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n",
890   //    name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef,
891   //    m_impl->nspace,m_impl->fileDef);
892   if (!m_impl->explicitOutputFileBase.isEmpty())
893   {
894     return m_impl->explicitOutputFileBase;
895   }
896   else if (m_impl->templateMaster)
897   {
898     return m_impl->templateMaster->getOutputFileBase();
899   }
900   else if (m_impl->group)
901   {
902     baseName=m_impl->group->getOutputFileBase();
903   }
904   else if (m_impl->classDef)
905   {
906     baseName=m_impl->classDef->getOutputFileBase();
907   }
908   else if (m_impl->nspace)
909   {
910     baseName=m_impl->nspace->getOutputFileBase();
911   }
912   else if (m_impl->fileDef)
913   {
914     baseName=m_impl->fileDef->getOutputFileBase();
915   }
916   
917   if (baseName.isEmpty())
918   {
919     warn(getDefFileName(),getDefLine(),
920        "warning: Internal inconsistency: member %s does not belong to any"
921        " container!",qPrint(name())
922       );
923     return "dummy";
924   }
925   else if (separateMemberPages)
926   {
927     if (getEnumScope()) // enum value, which is part of enum's documentation
928     {
929       baseName+="_"+getEnumScope()->anchor();
930     }
931     else
932     {
933       baseName+="_"+anchor();
934     }
935   }
936   return baseName;
937 }
938
939 QCString MemberDef::getReference() const
940 {
941   makeResident();
942   QCString ref = Definition::getReference();
943   if (!ref.isEmpty())
944   {
945     return ref;
946   }
947   if (m_impl->templateMaster)
948   {
949     return m_impl->templateMaster->getReference();
950   }
951   else if (m_impl->group)
952   {
953     return m_impl->group->getReference();
954   }
955   else if (m_impl->classDef)
956   {
957     return m_impl->classDef->getReference();
958   }
959   else if (m_impl->nspace)
960   {
961     return m_impl->nspace->getReference();
962   }
963   else if (m_impl->fileDef)
964   {
965     return m_impl->fileDef->getReference();
966   }
967   return "";
968 }
969
970 QCString MemberDef::anchor() const
971 {
972   KEEP_RESIDENT_DURING_CALL;
973   QCString result=m_impl->anc;
974   if (m_impl->groupAlias)     return m_impl->groupAlias->anchor();
975   if (m_impl->templateMaster) return m_impl->templateMaster->anchor();
976   if (m_impl->enumScope && m_impl->enumScope!=this) // avoid recursion for C#'s public enum E { E, F }
977   {
978     result.prepend(m_impl->enumScope->anchor());
979   }
980   if (m_impl->group) 
981   {
982     if (m_impl->groupMember)
983     {
984       result=m_impl->groupMember->anchor();
985     }
986     else if (getReference().isEmpty())
987     {
988       result.prepend("g");
989     }
990   }
991   return result;
992 }
993
994 void MemberDef::_computeLinkableInProject()
995 {
996   KEEP_RESIDENT_DURING_CALL;
997   static bool extractStatic  = Config_getBool("EXTRACT_STATIC");
998   m_isLinkableCached = 2; // linkable
999   //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data());
1000   if (isHidden()) 
1001   {
1002     //printf("is hidden\n");
1003     m_isLinkableCached = 1;
1004     return;
1005   }
1006   if (m_impl->templateMaster)
1007   {
1008     //printf("has template master\n");
1009     m_isLinkableCached = m_impl->templateMaster->isLinkableInProject() ? 2 : 1;
1010     return;
1011   }
1012   if (name().isEmpty() || name().at(0)=='@') 
1013   {
1014     //printf("name invalid\n");
1015     m_isLinkableCached = 1; // not a valid or a dummy name
1016     return;
1017   }
1018   if (!hasDocumentation() && !isReference()) 
1019   {
1020     //printf("no docs or reference\n");
1021     m_isLinkableCached = 1; // no documentation
1022     return;
1023   }
1024   if (m_impl->group && !m_impl->group->isLinkableInProject()) 
1025   {
1026     //printf("group but group not linkable!\n");
1027     m_isLinkableCached = 1; // group but group not linkable
1028     return;
1029   }
1030   if (!m_impl->group && m_impl->classDef && !m_impl->classDef->isLinkableInProject()) 
1031   {
1032     //printf("in a class but class not linkable!\n");
1033     m_isLinkableCached = 1; // in class but class not linkable
1034     return;
1035   }
1036   if (!m_impl->group && m_impl->nspace && !m_impl->related && !m_impl->nspace->isLinkableInProject()) 
1037   {
1038     //printf("in a namespace but namespace not linkable!\n");
1039     m_isLinkableCached = 1; // in namespace but namespace not linkable
1040     return;
1041   }
1042   if (!m_impl->group && !m_impl->nspace && 
1043       !m_impl->related && !m_impl->classDef && 
1044       m_impl->fileDef && !m_impl->fileDef->isLinkableInProject()) 
1045   {
1046     //printf("in a file but file not linkable!\n");
1047     m_isLinkableCached = 1; // in file (and not in namespace) but file not linkable
1048     return;
1049   }
1050   if (!protectionLevelVisible(m_impl->prot) && m_impl->mtype!=Friend) 
1051   {
1052     //printf("private and invisible!\n");
1053     m_isLinkableCached = 1; // hidden due to protection
1054     return;
1055   }
1056   if (m_impl->stat && m_impl->classDef==0 && !extractStatic) 
1057   {
1058     //printf("static and invisible!\n");
1059     m_isLinkableCached = 1; // hidden due to staticness
1060     return;
1061   }
1062   //printf("linkable!\n");
1063   return; // linkable!
1064 }
1065
1066 void MemberDef::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace)
1067 {
1068   makeResident();
1069   Definition::setDocumentation(d,docFile,docLine,stripWhiteSpace);
1070   m_isLinkableCached = 0;
1071 }
1072
1073 void MemberDef::setBriefDescription(const char *b,const char *briefFile,int briefLine)
1074 {
1075   makeResident();
1076   Definition::setBriefDescription(b,briefFile,briefLine);
1077   m_isLinkableCached = 0;
1078 }
1079
1080 void MemberDef::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine)
1081 {
1082   makeResident();
1083   Definition::setInbodyDocumentation(d,inbodyFile,inbodyLine);
1084   m_isLinkableCached = 0;
1085 }
1086
1087 void MemberDef::setHidden(bool b)
1088 {
1089   makeResident();
1090   Definition::setHidden(b);
1091   m_isLinkableCached = 0;
1092 }
1093
1094 bool MemberDef::isLinkableInProject() const
1095 {
1096   if (m_isLinkableCached==0)
1097   {
1098     MemberDef *that = (MemberDef*)this;
1099     that->_computeLinkableInProject();
1100   }
1101   ASSERT(m_isLinkableCached>0);
1102   return m_isLinkableCached==2;
1103 }
1104
1105 bool MemberDef::isLinkable() const
1106 {
1107   makeResident();
1108   if (m_impl->templateMaster)
1109   {
1110     return m_impl->templateMaster->isLinkable();
1111   }
1112   else
1113   {
1114     return isLinkableInProject() || isReference();
1115   }
1116 }
1117
1118
1119 void MemberDef::setDefinitionTemplateParameterLists(QList<ArgumentList> *lists)
1120 {
1121   if (lists)
1122   {
1123     makeResident();
1124     if (m_impl->defTmpArgLists) delete m_impl->defTmpArgLists;
1125     m_impl->defTmpArgLists = copyArgumentLists(lists);
1126   }
1127 }
1128
1129 void MemberDef::writeLink(OutputList &ol,ClassDef *,NamespaceDef *,
1130                       FileDef *fd,GroupDef *gd,bool onlyText)
1131 {
1132   KEEP_RESIDENT_DURING_CALL;
1133   SrcLangExt lang = getLanguage();
1134   static bool hideScopeNames     = Config_getBool("HIDE_SCOPE_NAMES");
1135   QCString sep = getLanguageSpecificSeparator(lang,TRUE);
1136   QCString n = name();
1137   if (!hideScopeNames)
1138   {
1139     if (m_impl->classDef && gd && !isRelated()) 
1140     {
1141       n.prepend(m_impl->classDef->displayName()+sep);
1142     }
1143     else if (m_impl->nspace && (gd || fd)) 
1144     {
1145       n.prepend(m_impl->nspace->displayName()+sep);
1146     }
1147   }
1148
1149   if (isObjCMethod())
1150   {
1151     if (isStatic()) ol.docify("+ "); else ol.docify("- ");
1152   }
1153   if (!onlyText && isLinkable()) // write link
1154   {
1155     if (m_impl->mtype==EnumValue && getGroupDef()==0 &&          // enum value is not grouped
1156         getEnumScope() && getEnumScope()->getGroupDef()) // but its container is
1157     {
1158       GroupDef *enumValGroup = getEnumScope()->getGroupDef();
1159       ol.writeObjectLink(enumValGroup->getReference(),
1160                          enumValGroup->getOutputFileBase(),
1161                          anchor(),n);
1162     }
1163     else
1164     {
1165       ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),n);
1166     }
1167   }
1168   else // write only text
1169   {
1170     ol.startBold();
1171     ol.docify(n);
1172     ol.endBold();
1173   }
1174 }
1175
1176 /*! If this member has an anonymous class/struct/union as its type, then
1177  *  this method will return the ClassDef that describes this return type.
1178  */
1179 ClassDef *MemberDef::getClassDefOfAnonymousType() 
1180 {
1181   // split KEEP_RESIDENT_DURING_CALL for performance
1182   makeResident();
1183   if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType;
1184   LockingPtr<MemberDef> lock(this,this); // since this memberDef can access 
1185                                          // other memberDefs prevent it from 
1186                                          // being flushed to disk halfway
1187
1188   QCString cname;
1189   if (getClassDef()!=0) 
1190   {
1191     cname=getClassDef()->name().copy();
1192   }
1193   else if (getNamespaceDef()!=0)
1194   {
1195     cname=getNamespaceDef()->name().copy();
1196   }
1197   QCString ltype(m_impl->type);
1198   // strip `static' keyword from ltype
1199   //if (ltype.left(7)=="static ") ltype=ltype.right(ltype.length()-7);
1200   // strip `friend' keyword from ltype
1201   ltype.stripPrefix("friend ");
1202   static QRegExp r("@[0-9]+");
1203   int l,i=r.match(ltype,0,&l);
1204   //printf("ltype=`%s' i=%d\n",ltype.data(),i);
1205   // search for the last anonymous scope in the member type
1206   ClassDef *annoClassDef=0;
1207   if (i!=-1) // found anonymous scope in type
1208   {
1209     int il=i-1,ir=i+l;
1210     // extract anonymous scope
1211     while (il>=0 && (isId(ltype.at(il)) || ltype.at(il)==':' || ltype.at(il)=='@')) il--;
1212     if (il>0) il++; else if (il<0) il=0;
1213     while (ir<(int)ltype.length() && (isId(ltype.at(ir)) || ltype.at(ir)==':' || ltype.at(ir)=='@')) ir++;
1214
1215     QCString annName = ltype.mid(il,ir-il);
1216
1217     // if inside a class or namespace try to prepend the scope name
1218     if (!cname.isEmpty() && annName.left(cname.length()+2)!=cname+"::") 
1219     {
1220       QCString ts=stripAnonymousNamespaceScope(cname+"::"+annName);
1221       annoClassDef=getClass(ts);
1222     }
1223     // if not found yet, try without scope name
1224     if (annoClassDef==0)
1225     {
1226       QCString ts=stripAnonymousNamespaceScope(annName);
1227       annoClassDef=getClass(ts);
1228     }
1229   }
1230   m_impl->cachedAnonymousType = annoClassDef;
1231   return annoClassDef;
1232 }
1233     
1234 /*! This methods returns TRUE iff the brief section (also known as
1235  *  declaration section) is visible in the documentation.
1236  */
1237 bool MemberDef::isBriefSectionVisible() const
1238 {
1239   static bool extractStatic       = Config_getBool("EXTRACT_STATIC");
1240   static bool hideUndocMembers    = Config_getBool("HIDE_UNDOC_MEMBERS");
1241   static bool briefMemberDesc     = Config_getBool("BRIEF_MEMBER_DESC");
1242   static bool repeatBrief         = Config_getBool("REPEAT_BRIEF");
1243   static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS");
1244
1245   //printf("Member %s grpId=%d docs=%s file=%s args=%s\n",
1246   //    name().data(),
1247   //    0,"", //grpId,grpId==-1?"<none>":Doxygen::memberDocDict[grpId]->data(),
1248   //    "", //getFileDef()->name().data(),
1249   //    argsString());
1250
1251   KEEP_RESIDENT_DURING_CALL;
1252
1253   MemberGroupInfo *info = Doxygen::memGrpInfoDict[m_impl->grpId];
1254   //printf("name=%s m_impl->grpId=%d info=%p\n",name().data(),m_impl->grpId,info);
1255   //QCString *pMemGrp = Doxygen::memberDocDict[grpId];
1256   bool hasDocs = hasDocumentation() || 
1257                   // part of a documented member group
1258                  (m_impl->grpId!=-1 && info && !(info->doc.isEmpty() && info->header.isEmpty()));
1259
1260   // only include static members with file/namespace scope if 
1261   // explicitly enabled in the config file
1262   bool visibleIfStatic = !(getClassDef()==0 && 
1263                            isStatic() && 
1264                            !extractStatic
1265                           );
1266
1267   // only include members is the are documented or 
1268   // HIDE_UNDOC_MEMBERS is NO in the config file
1269   bool visibleIfDocumented = (!hideUndocMembers || 
1270                               hasDocs || 
1271                               isDocumentedFriendClass()
1272                              );
1273
1274   // hide members with no detailed description and brief descriptions 
1275   // explicitly disabled.
1276   bool visibleIfEnabled = !(hideUndocMembers && 
1277                             documentation().isEmpty() &&
1278                             !briefMemberDesc && 
1279                             !repeatBrief
1280                            );
1281
1282   // Hide friend (class|struct|union) declarations if HIDE_FRIEND_COMPOUNDS is true
1283   bool visibleIfFriendCompound = !(hideFriendCompounds &&
1284                                    isFriend() &&
1285                                    (m_impl->type=="friend class" || 
1286                                     m_impl->type=="friend struct" ||
1287                                     m_impl->type=="friend union"
1288                                    )
1289                                   );
1290   
1291   // only include members that are non-private unless EXTRACT_PRIVATE is
1292   // set to YES or the member is part of a group
1293   bool visibleIfPrivate = (protectionLevelVisible(protection()) || 
1294                            m_impl->mtype==Friend
1295                           );
1296   
1297   // hide member if it overrides a member in a superclass and has no
1298   // documentation of its own
1299   //bool visibleIfDocVirtual = !reimplements() || 
1300   //                           !Config_getBool("INHERIT_DOCS") ||  
1301   //                           hasDocs;
1302
1303   // true if this member is a constructor or destructor
1304   bool cOrDTor = isConstructor() || isDestructor();
1305
1306   // hide default constructors or destructors (no args) without
1307   // documentation
1308   bool visibleIfNotDefaultCDTor = !(cOrDTor &&
1309                                    m_impl->defArgList &&
1310                                    (m_impl->defArgList->isEmpty() ||
1311                                     m_impl->defArgList->first()->type == "void"
1312                                    ) &&
1313                                    !hasDocs
1314                                   );
1315
1316
1317   //printf("visibleIfStatic=%d visibleIfDocumented=%d visibleIfEnabled=%d "
1318   //       "visibleIfPrivate=%d visibltIfNotDefaultCDTor=%d "
1319   //       "visibleIfFriendCompound=%d !annScope=%d\n",
1320   //       visibleIfStatic,visibleIfDocumented,
1321   //       visibleIfEnabled,visibleIfPrivate,visibleIfNotDefaultCDTor,
1322   //       visibleIfFriendCompound,!m_impl->annScope);
1323   
1324   bool visible = visibleIfStatic     && visibleIfDocumented      && 
1325                  visibleIfEnabled    && visibleIfPrivate         &&
1326                  /*visibleIfDocVirtual &&*/ visibleIfNotDefaultCDTor && 
1327                  visibleIfFriendCompound && 
1328                  !m_impl->annScope && !isHidden();
1329   //printf("MemberDef::isBriefSectionVisible() %d\n",visible);
1330   return visible;
1331 }
1332
1333
1334 void MemberDef::writeDeclaration(OutputList &ol,
1335                ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
1336                bool inGroup,ClassDef *inheritedFrom,const char *inheritId
1337                )
1338 {
1339   //printf("%s MemberDef::writeDeclaration() inGroup=%d\n",name().data(),inGroup);
1340
1341   // hide enum value, since they appear already as part of the enum, unless they
1342   // are explicitly grouped.
1343   KEEP_RESIDENT_DURING_CALL;
1344   if (!inGroup && m_impl->mtype==EnumValue) return;
1345
1346   // hide members whose brief section should not be visible
1347   //if (!isBriefSectionVisible()) return;
1348
1349   Definition *d=0;
1350   ASSERT (cd!=0 || nd!=0 || fd!=0 || gd!=0); // member should belong to something
1351   if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
1352
1353   // write tag file information of this member
1354   if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !isReference())
1355   {
1356     Doxygen::tagFile << "    <member kind=\"";
1357     switch (m_impl->mtype)
1358     {
1359       case Define:      Doxygen::tagFile << "define";      break;
1360       case EnumValue:   Doxygen::tagFile << "enumvalue";   break;
1361       case Property:    Doxygen::tagFile << "property";    break;
1362       case Event:       Doxygen::tagFile << "event";       break;
1363       case Variable:    Doxygen::tagFile << "variable";    break;
1364       case Typedef:     Doxygen::tagFile << "typedef";     break;
1365       case Enumeration: Doxygen::tagFile << "enumeration"; break;
1366       case Function:    Doxygen::tagFile << "function";    break;
1367       case Signal:      Doxygen::tagFile << "signal";      break;
1368       //case Prototype:   Doxygen::tagFile << "prototype";   break;
1369       case Friend:      Doxygen::tagFile << "friend";      break;
1370       case DCOP:        Doxygen::tagFile << "dcop";        break;
1371       case Slot:        Doxygen::tagFile << "slot";        break;
1372     }
1373     if (m_impl->prot!=Public)
1374     {
1375       Doxygen::tagFile << "\" protection=\"";
1376       if (m_impl->prot==Protected)    Doxygen::tagFile << "protected";
1377       else if (m_impl->prot==Package) Doxygen::tagFile << "package";
1378       else /* Private */              Doxygen::tagFile << "private"; 
1379     }
1380     if (m_impl->virt!=Normal)
1381     {
1382       Doxygen::tagFile << "\" virtualness=\"";
1383       if (m_impl->virt==Virtual) Doxygen::tagFile << "virtual";
1384       else /* Pure */            Doxygen::tagFile << "pure"; 
1385     }
1386     if (isStatic())
1387     {
1388       Doxygen::tagFile << "\" static=\"yes";
1389     }
1390     Doxygen::tagFile << "\">" << endl;
1391     Doxygen::tagFile << "      <type>" << convertToXML(typeString()) << "</type>" << endl;
1392     Doxygen::tagFile << "      <name>" << convertToXML(name()) << "</name>" << endl;
1393     Doxygen::tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;
1394     Doxygen::tagFile << "      <anchor>" << convertToXML(anchor()) << "</anchor>" << endl;
1395     Doxygen::tagFile << "      <arglist>" << convertToXML(argsString()) << "</arglist>" << endl;
1396     writeDocAnchorsToTagFile();
1397     Doxygen::tagFile << "    </member>" << endl;
1398   }
1399
1400   // write search index info
1401   if (Doxygen::searchIndex && isLinkableInProject())
1402   {
1403     Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
1404     Doxygen::searchIndex->addWord(localName(),TRUE);
1405     Doxygen::searchIndex->addWord(qualifiedName(),FALSE);
1406   }
1407
1408   QCString cname  = d->name();
1409   QCString cdname = d->displayName();
1410   QCString cfname = getOutputFileBase();
1411   //QCString osname = cname;
1412   // in case of class members that are put in a group the name of the outerscope
1413   // differs from the cname.
1414   //if (getOuterScope()) osname=getOuterScope()->name();
1415
1416   //HtmlHelp *htmlHelp=0;
1417   //bool hasHtmlHelp = Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_HTMLHELP");
1418   //if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance();
1419
1420   // search for the last anonymous scope in the member type
1421   ClassDef *annoClassDef=getClassDefOfAnonymousType();
1422
1423   ol.startMemberDeclaration();
1424
1425   // start a new member declaration
1426   bool isAnonymous = annoClassDef || m_impl->annMemb || m_impl->annEnumType;
1427   ///printf("startMemberItem for %s\n",name().data());
1428   ol.startMemberItem(anchor(), 
1429                      isAnonymous ? 1 : m_impl->tArgList ? 3 : 0,
1430                      inheritId
1431                     );
1432
1433   // If there is no detailed description we need to write the anchor here.
1434   bool detailsVisible = isDetailedSectionLinkable();
1435   if (!detailsVisible && !m_impl->annMemb)
1436   {
1437     QCString doxyName=name().copy();
1438     if (!cname.isEmpty()) 
1439     {
1440       doxyName.prepend(cdname+getLanguageSpecificSeparator(getLanguage()));
1441     }
1442     QCString doxyArgs=argsString();
1443     ol.startDoxyAnchor(cfname,cname,anchor(),doxyName,doxyArgs);
1444
1445     ol.pushGeneratorState();
1446     ol.disable(OutputGenerator::Man);
1447     ol.disable(OutputGenerator::Latex);
1448     ol.docify("\n");
1449     ol.popGeneratorState();
1450   }
1451
1452   if (annoClassDef || m_impl->annMemb)
1453   {
1454     int j;
1455     for (j=0;j<s_indentLevel;j++) 
1456     {
1457       ol.writeNonBreakableSpace(3);
1458     }
1459   }
1460
1461   // *** write template lists
1462   if (m_impl->tArgList && getLanguage()==SrcLangExt_Cpp)
1463   {
1464     if (!isAnonymous) ol.startMemberTemplateParams();
1465     writeTemplatePrefix(ol,m_impl->tArgList);
1466     if (!isAnonymous) ol.endMemberTemplateParams(anchor(),inheritId);
1467   }
1468
1469   // *** write type
1470   QCString ltype(m_impl->type);
1471   if (m_impl->mtype==Typedef) ltype.prepend("typedef ");
1472   if (isAlias())
1473   {
1474     ltype="using";
1475   }
1476   // strip `friend' keyword from ltype
1477   ltype.stripPrefix("friend ");
1478   static QRegExp r("@[0-9]+");
1479
1480   bool endAnonScopeNeeded=FALSE;
1481   int l,i=r.match(ltype,0,&l);
1482   if (i!=-1) // member has an anonymous type
1483   {
1484     //printf("annoClassDef=%p annMemb=%p scopeName=`%s' anonymous=`%s'\n",
1485     //    annoClassDef,annMemb,cname.data(),ltype.mid(i,l).data());
1486
1487     if (annoClassDef) // type is an anonymous compound
1488     {
1489       int ir=i+l;
1490       //printf("<<<<<<<<<<<<<<\n");
1491       ol.startAnonTypeScope(s_indentLevel++);
1492       annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,inheritedFrom,inheritId);
1493       //printf(">>>>>>>>>>>>>> startMemberItem(2)\n");
1494       ol.startMemberItem(anchor(),2,inheritId);
1495       int j;
1496       for (j=0;j< s_indentLevel-1;j++) 
1497       {
1498         ol.writeNonBreakableSpace(3);
1499       }
1500       QCString varName=ltype.right(ltype.length()-ir).stripWhiteSpace();
1501       //printf(">>>>>> indDepth=%d ltype=`%s' varName=`%s'\n",indDepth,ltype.data(),varName.data());
1502       ol.docify("}");
1503       if (varName.isEmpty() && (name().isEmpty() || name().at(0)=='@')) 
1504       {
1505         ol.docify(";"); 
1506       }
1507       endAnonScopeNeeded=TRUE;
1508     }
1509     else
1510     {
1511       if (getAnonymousEnumType()) // type is an anonymous enum
1512       {
1513         linkifyText(TextGeneratorOLImpl(ol), // out
1514                     d,                       // scope
1515                     getBodyDef(),            // fileScope
1516                     this,                    // self
1517                     ltype.left(i),           // text
1518                     TRUE                     // autoBreak
1519                    ); 
1520         getAnonymousEnumType()->writeEnumDeclaration(ol,cd,nd,fd,gd);
1521         //ol+=*getAnonymousEnumType()->enumDecl();
1522         linkifyText(TextGeneratorOLImpl(ol),d,m_impl->fileDef,this,ltype.right(ltype.length()-i-l),TRUE); 
1523       }
1524       else
1525       {
1526         ltype = ltype.left(i) + " { ... } " + removeAnonymousScopes(ltype.right(ltype.length()-i-l));
1527         linkifyText(TextGeneratorOLImpl(ol), // out
1528                     d,                       // scope
1529                     getBodyDef(),            // fileScope
1530                     this,                    // self
1531                     ltype,                   // text
1532                     TRUE                     // autoBreak
1533                    ); 
1534       }
1535     }
1536   }
1537   else if (ltype=="@") // rename type from enum values
1538   {
1539     ltype="";
1540   }
1541   else
1542   {
1543     if (isObjCMethod())
1544     {
1545       ltype.prepend("(");
1546       ltype.append(")");
1547     }
1548     linkifyText(TextGeneratorOLImpl(ol), // out
1549                 d,                       // scope
1550                 getBodyDef(),            // fileScope
1551                 this,                    // self
1552                 ltype,                   // text
1553                 TRUE                     // autoBreak
1554                );
1555   }
1556   bool htmlOn = ol.isEnabled(OutputGenerator::Html);
1557   if (htmlOn && /*Config_getBool("HTML_ALIGN_MEMBERS") &&*/ !ltype.isEmpty())
1558   {
1559     ol.disable(OutputGenerator::Html);
1560   }
1561   if (!ltype.isEmpty()) ol.docify(" ");
1562   if (htmlOn) 
1563   {
1564     ol.enable(OutputGenerator::Html);
1565   }
1566
1567   if (m_impl->annMemb) 
1568   {
1569     ol.pushGeneratorState();
1570     ol.disableAllBut(OutputGenerator::Html);
1571     ol.writeNonBreakableSpace(3);
1572     ol.popGeneratorState();
1573   }
1574   else
1575   {
1576     ol.insertMemberAlign(m_impl->tArgList!=0);
1577   }
1578
1579   // *** write name
1580   if (!name().isEmpty() && name().at(0)!='@') // hide anonymous stuff 
1581   {
1582     //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable());
1583     if (!(name().isEmpty() || name().at(0)=='@') && // name valid
1584         (hasDocumentation() || isReference()) && // has docs
1585         !(m_impl->prot==Private && !Config_getBool("EXTRACT_PRIVATE") && m_impl->mtype!=Friend) && // hidden due to protection
1586         !(isStatic() && m_impl->classDef==0 && !Config_getBool("EXTRACT_STATIC")) // hidden due to static-ness
1587        )
1588     {
1589       if (m_impl->annMemb)
1590       {
1591         //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor());
1592         m_impl->annMemb->writeLink(ol,
1593             m_impl->annMemb->getClassDef(),
1594             m_impl->annMemb->getNamespaceDef(),
1595             m_impl->annMemb->getFileDef(),
1596             m_impl->annMemb->getGroupDef()
1597                           );
1598         m_impl->annMemb->setAnonymousUsed();
1599         setAnonymousUsed();
1600       }
1601       else
1602       {
1603         //printf("writeLink %s->%d\n",name.data(),hasDocumentation());
1604         ClassDef *rcd = cd;
1605         if (isReference() && m_impl->classDef) rcd = m_impl->classDef; 
1606         writeLink(ol,rcd,nd,fd,gd);
1607       }
1608     }
1609     else if (isDocumentedFriendClass())
1610       // if the member is an undocumented friend declaration for some class, 
1611       // then maybe we can link to the class
1612     {
1613       writeLink(ol,getClass(name()),0,0,0);
1614     }
1615     else
1616       // there is a brief member description and brief member 
1617       // descriptions are enabled or there is no detailed description.
1618     {
1619       if (m_impl->annMemb)  
1620       {
1621         m_impl->annMemb->setAnonymousUsed();
1622         setAnonymousUsed();
1623       }
1624       ClassDef *rcd = cd;
1625       if (isReference() && m_impl->classDef) rcd = m_impl->classDef; 
1626       writeLink(ol,rcd,nd,fd,gd,TRUE);
1627     }
1628   }
1629
1630   // add to index
1631   if (isEnumerate() && name().at(0)=='@')
1632   {
1633     // don't add to index
1634   }
1635   else // index member
1636   {
1637     //static bool separateMemPages = Config_getBool("SEPARATE_MEMBER_PAGES");
1638     //QCString cfname = getOutputFileBase();
1639     //QCString cfiname = d->getOutputFileBase();
1640     //Doxygen::indexList.addIndexItem(
1641     //    cname,                                 // level1
1642     //    name(),                                // level2
1643     //    separateMemPages ? cfname : cfiname,   // contRef
1644     //    cfname,                                // memRef
1645     //    anchor(),                              // anchor
1646     //    this);                                 // memberdef
1647     Doxygen::indexList.addIndexItem(d,this);
1648   }
1649
1650   // *** write arguments
1651   if (argsString() && !isObjCMethod()) 
1652   {
1653     if (!isDefine()) ol.writeString(" ");
1654     linkifyText(TextGeneratorOLImpl(ol), // out
1655                 d,                       // scope
1656                 getBodyDef(),            // fileScope
1657                 this,                    // self
1658                 argsString(),            // text
1659                 m_impl->annMemb,         // autoBreak
1660                 TRUE,                    // external
1661                 FALSE,                   // keepSpaces
1662                 s_indentLevel
1663                );
1664   }
1665   // *** write exceptions
1666   if (excpString())
1667   {
1668     ol.writeString(" ");
1669     ol.docify(excpString());
1670   }
1671
1672   // *** write bitfields
1673   if (!m_impl->bitfields.isEmpty()) // add bitfields
1674   {
1675     linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->bitfields.simplifyWhiteSpace());
1676   }
1677   else if (hasOneLineInitializer()
1678       //!init.isEmpty() && initLines==0 && // one line initializer
1679       //((maxInitLines>0 && userInitLines==-1) || userInitLines>0) // enabled by default or explicitly
1680           ) // add initializer
1681   {
1682     if (!isDefine()) 
1683     {
1684       //ol.writeString(" = "); 
1685       ol.writeString(" "); 
1686       linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer.simplifyWhiteSpace());
1687     }
1688     else 
1689     {
1690       ol.writeNonBreakableSpace(3);
1691       linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer);
1692     }
1693   }
1694   else if (isAlias()) // using template alias
1695   {
1696     ol.writeString(" = "); 
1697     linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->type);
1698   }
1699
1700
1701   if ((isObjCMethod() || isObjCProperty()) && isImplementation())
1702   {
1703     ol.startTypewriter();
1704     ol.docify(" [implementation]");
1705     ol.endTypewriter();
1706   }
1707
1708   if (isProperty() && (isSettable() || isGettable()))
1709   {
1710       ol.writeLatexSpacing();
1711       ol.startTypewriter();
1712       ol.docify(" [");
1713       QStrList sl;
1714       if (isGettable())  sl.append("get");
1715       if (isSettable())  sl.append("set");
1716       const char *s=sl.first();
1717       while (s)
1718       {
1719          ol.docify(s);
1720          s=sl.next();
1721          if (s) ol.docify(", ");
1722       }
1723       ol.docify("]");
1724       ol.endTypewriter();
1725   }
1726
1727   if (isEvent() && (isAddable() || isRemovable() || isRaisable()))
1728   {
1729       ol.writeLatexSpacing();
1730       ol.startTypewriter();
1731       ol.docify(" [");
1732       QStrList sl;
1733       if (isAddable())   sl.append("add");
1734       if (isRemovable()) sl.append("remove");
1735       if (isRaisable())  sl.append("raise");
1736       const char *s=sl.first();
1737       while (s)
1738       {
1739          ol.docify(s);
1740          s=sl.next();
1741          if (s) ol.docify(", ");
1742       }
1743       ol.docify("]");
1744       ol.endTypewriter();
1745   }
1746
1747   if (!detailsVisible && !m_impl->annMemb)
1748   {
1749     ol.endDoxyAnchor(cfname,anchor());
1750   }
1751
1752   //printf("endMember %s annoClassDef=%p annEnumType=%p\n",
1753   //    name().data(),annoClassDef,annEnumType);
1754   ol.endMemberItem();
1755   if (endAnonScopeNeeded) 
1756   {
1757     ol.endAnonTypeScope(--s_indentLevel);
1758   }
1759
1760   // write brief description
1761   if (!briefDescription().isEmpty() && 
1762       Config_getBool("BRIEF_MEMBER_DESC") 
1763       /* && !annMemb */
1764      )
1765   {
1766     ol.startMemberDescription(anchor(),inheritId);
1767     ol.parseDoc(briefFile(),briefLine(),
1768                 getOuterScope()?getOuterScope():d,this,briefDescription(),
1769                 TRUE,FALSE,0,TRUE,FALSE);
1770     if (detailsVisible) 
1771     {
1772       ol.pushGeneratorState();
1773       ol.disableAllBut(OutputGenerator::Html);
1774       //ol.endEmphasis();
1775       ol.docify(" ");
1776       if (m_impl->group!=0 && gd==0) // forward link to the group
1777       {
1778         ol.startTextLink(getOutputFileBase(),anchor());
1779       }
1780       else // local link
1781       {
1782         ol.startTextLink(0,anchor());
1783       }
1784       ol.endTextLink();
1785       //ol.startEmphasis();
1786       ol.popGeneratorState();
1787     }
1788     // for RTF we need to add an extra empty paragraph
1789     ol.pushGeneratorState();
1790     ol.disableAllBut(OutputGenerator::RTF);
1791       ol.startParagraph();
1792       ol.endParagraph();
1793     ol.popGeneratorState();
1794     ol.endMemberDescription();
1795   }
1796
1797   ol.endMemberDeclaration(anchor(),inheritId);
1798
1799   warnIfUndocumented();
1800 }
1801
1802 bool MemberDef::isDetailedSectionLinkable() const          
1803
1804   static bool extractAll        = Config_getBool("EXTRACT_ALL");
1805   static bool alwaysDetailedSec = Config_getBool("ALWAYS_DETAILED_SEC");
1806   static bool repeatBrief       = Config_getBool("REPEAT_BRIEF");
1807   static bool briefMemberDesc   = Config_getBool("BRIEF_MEMBER_DESC");
1808   static bool hideUndocMembers  = Config_getBool("HIDE_UNDOC_MEMBERS");
1809   static bool extractStatic     = Config_getBool("EXTRACT_STATIC");
1810
1811   KEEP_RESIDENT_DURING_CALL;
1812
1813   // the member has details documentation for any of the following reasons
1814   bool docFilter = 
1815          // treat everything as documented
1816          extractAll ||          
1817          // has detailed docs
1818          !documentation().isEmpty() ||             
1819          // has inbody docs
1820          !inbodyDocumentation().isEmpty() ||
1821          // is an enum with values that are documented
1822          (m_impl->mtype==Enumeration && m_impl->docEnumValues) ||  
1823          // is documented enum value
1824          (m_impl->mtype==EnumValue && !briefDescription().isEmpty()) || 
1825          // has brief description that is part of the detailed description
1826          (!briefDescription().isEmpty() &&           // has brief docs
1827           (alwaysDetailedSec &&                      // they are visible in
1828            (repeatBrief ||                           // detailed section or
1829             !briefMemberDesc                         // they are explicitly not
1830            )                                         // shown in brief section
1831           )                                       
1832          ) ||
1833          // has a multi-line initialization block
1834          //(initLines>0 && initLines<maxInitLines) || 
1835          (hasMultiLineInitializer() && !hideUndocMembers) ||
1836          // has one or more documented arguments
1837          (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation()) ||
1838          // has user comments
1839          Doxygen::userComments
1840          ; 
1841          
1842   // this is not a global static or global statics should be extracted
1843   bool staticFilter = getClassDef()!=0 || !isStatic() || extractStatic; 
1844          
1845   // only include members that are non-private unless EXTRACT_PRIVATE is
1846   // set to YES or the member is part of a   group
1847   bool privateFilter = protectionLevelVisible(protection()) || m_impl->mtype==Friend;
1848
1849   // member is part of an anonymous scope that is the type of
1850   // another member in the list.
1851   //
1852   //bool inAnonymousScope = !briefDescription().isEmpty() && annUsed;
1853
1854   // hide friend (class|struct|union) member if HIDE_FRIEND_COMPOUNDS
1855   // is true
1856   bool friendCompoundFilter = !(Config_getBool("HIDE_FRIEND_COMPOUNDS") &&
1857                                 isFriend() &&
1858                                 (m_impl->type=="friend class" || 
1859                                  m_impl->type=="friend struct" ||
1860                                  m_impl->type=="friend union"
1861                                 )
1862                                );
1863  
1864   
1865   bool result = ((docFilter && staticFilter && privateFilter && friendCompoundFilter && !isHidden()));
1866   //printf("%s::isDetailedSectionLinkable: %d\n",name().data(),result);
1867   return result;
1868 }
1869
1870 bool MemberDef::isDetailedSectionVisible(bool inGroup,bool inFile) const          
1871
1872   static bool separateMemPages = Config_getBool("SEPARATE_MEMBER_PAGES");
1873   static bool inlineSimpleStructs = Config_getBool("INLINE_SIMPLE_STRUCTS");
1874   static bool hideUndocMembers = Config_getBool("HIDE_UNDOC_MEMBERS");
1875   bool groupFilter = getGroupDef()==0 || inGroup || separateMemPages; 
1876   bool fileFilter  = getNamespaceDef()==0 || !inFile;
1877   bool simpleFilter = !hideUndocMembers && inlineSimpleStructs && 
1878                       getClassDef()!=0 && getClassDef()->isSimple();
1879
1880   bool visible = isDetailedSectionLinkable() && groupFilter && fileFilter && 
1881                  !isReference();
1882   bool result = visible || simpleFilter;
1883   //printf("%s::isDetailedSectionVisble: %d groupFilter=%d fileFilter=%d\n",
1884   //    name().data(),result,groupFilter,fileFilter);
1885   return result;
1886 }
1887
1888 void MemberDef::_getLabels(QStrList &sl,Definition *container) const
1889 {
1890   static bool inlineInfo = Config_getBool("INLINE_INFO");
1891
1892   Specifier lvirt=virtualness();
1893   if ((!isObjCMethod() || isOptional() || isRequired()) &&
1894       (protection()!=Public || lvirt!=Normal ||
1895        isFriend() || isRelated() || 
1896        (isInline() && inlineInfo) ||
1897        isSignal() || isSlot() ||
1898        isStatic() || 
1899        (m_impl->classDef && m_impl->classDef!=container && container->definitionType()==TypeClass) ||
1900        (m_impl->memSpec & ~Entry::Inline)!=0 
1901       )
1902      )
1903   {
1904     // write the member specifier list
1905     //ol.writeLatexSpacing();
1906     //ol.startTypewriter();
1907     //ol.docify(" [");
1908     SrcLangExt lang = getLanguage();
1909     bool optVhdl = lang==SrcLangExt_VHDL;
1910     if (optVhdl)
1911     {
1912       sl.append(VhdlDocGen::trTypeString(getMemberSpecifiers()));
1913     }
1914     else
1915     {
1916       if (isFriend()) sl.append("friend");
1917       else if (isRelated()) sl.append("related");
1918       else
1919       {
1920         if      (Config_getBool("INLINE_INFO") && isInline()) sl.append("inline");
1921         if      (isExplicit())            sl.append("explicit");
1922         if      (isMutable())             sl.append("mutable");
1923         if      (isStatic())              sl.append("static");
1924         if      (isGettable())            sl.append("get");
1925         if      (isSettable())            sl.append("set");
1926         if      (isAddable())             sl.append("add");
1927         if      (isRemovable())           sl.append("remove");
1928         if      (isRaisable())            sl.append("raise");
1929         if      (isReadable())            sl.append("read");
1930         if      (isWritable())            sl.append("write");
1931         if      (isFinal())               sl.append("final");
1932         if      (isAbstract())            sl.append("abstract");
1933         if      (isOverride())            sl.append("override");
1934         if      (isInitonly())            sl.append("initonly");
1935         if      (isSealed())              sl.append("sealed");
1936         if      (isNew())                 sl.append("new");
1937         if      (isOptional())            sl.append("optional");
1938         if      (isRequired())            sl.append("required");
1939
1940         if      (isNonAtomic())           sl.append("nonatomic");
1941         else if (isObjCProperty())        sl.append("atomic");
1942
1943         // mutual exclusive Objective 2.0 property attributes
1944         if      (isAssign())              sl.append("assign");
1945         else if (isCopy())                sl.append("copy");
1946         else if (isRetain())              sl.append("retain");
1947         else if (isWeak())                sl.append("weak");
1948         else if (isStrong())              sl.append("strong");
1949         else if (isUnretained())          sl.append("unsafe_unretained");
1950
1951         if (!isObjCMethod())
1952         {
1953           if      (protection()==Protected) sl.append("protected");
1954           else if (protection()==Private)   sl.append("private");
1955           else if (protection()==Package)   sl.append("package");
1956
1957           if      (lvirt==Virtual)          sl.append("virtual");
1958           else if (lvirt==Pure)             sl.append("pure virtual");
1959           if      (isSignal())              sl.append("signal");
1960           if      (isSlot())                sl.append("slot");
1961           if      (isDefault())             sl.append("default");
1962           if      (isDelete())              sl.append("delete");
1963           if      (isNoExcept())            sl.append("noexcept");
1964         }
1965         if (isObjCProperty() && isImplementation())
1966         {
1967           sl.append("implementation");
1968         }
1969       }
1970       if (m_impl->classDef && 
1971           container->definitionType()==TypeClass && 
1972           m_impl->classDef!=container &&
1973           !isRelated()
1974          ) 
1975       {
1976         sl.append("inherited");
1977       }
1978     }
1979   }
1980   else if (isObjCMethod() && isImplementation())
1981   {
1982     sl.append("implementation");
1983   }
1984 }
1985
1986 void MemberDef::_writeCallGraph(OutputList &ol)
1987 {
1988   // write call graph
1989   if ((m_impl->hasCallGraph || Config_getBool("CALL_GRAPH")) 
1990       && (isFunction() || isSlot() || isSignal()) && Config_getBool("HAVE_DOT")
1991      )
1992   {
1993     DotCallGraph callGraph(this,FALSE);
1994     if (callGraph.isTooBig())
1995     {
1996        err("warning: Call graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",qPrint(qualifiedName()));
1997     }
1998     else if (!callGraph.isTrivial())
1999     {
2000       msg("Generating call graph for function %s\n",qPrint(qualifiedName()));
2001       ol.disable(OutputGenerator::Man);
2002       ol.startParagraph();
2003       ol.startCallGraph();
2004       ol.parseText(theTranslator->trCallGraph());
2005       ol.endCallGraph(callGraph);
2006       ol.endParagraph(); 
2007       ol.enableAll();
2008     }
2009   }
2010 }
2011
2012 void MemberDef::_writeCallerGraph(OutputList &ol)
2013 {
2014   if ((m_impl->hasCallerGraph || Config_getBool("CALLER_GRAPH")) 
2015       && (isFunction() || isSlot() || isSignal()) && Config_getBool("HAVE_DOT")
2016      )
2017   {
2018     DotCallGraph callerGraph(this, TRUE);
2019     if (callerGraph.isTooBig())
2020     {
2021        err("warning: Caller graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",qPrint(qualifiedName()));
2022     }
2023     else if (!callerGraph.isTrivial() && !callerGraph.isTooBig())
2024     {
2025       msg("Generating caller graph for function %s\n",qPrint(qualifiedName()));
2026       ol.disable(OutputGenerator::Man);
2027       ol.startParagraph();
2028       ol.startCallGraph();
2029       ol.parseText(theTranslator->trCallerGraph());
2030       ol.endCallGraph(callerGraph);
2031       ol.endParagraph();
2032       ol.enableAll();
2033     }
2034   }
2035 }
2036
2037 void MemberDef::_writeReimplements(OutputList &ol)
2038 {
2039   MemberDef *bmd=reimplements();
2040   ClassDef *bcd=0;
2041   if (bmd && (bcd=bmd->getClassDef()))
2042   {
2043     // write class that contains a member that is reimplemented by this one
2044     if (bcd->isLinkable())
2045     {
2046       ol.startParagraph();
2047       QCString reimplFromLine; 
2048       if (bmd->virtualness()!=Pure && bcd->compoundType()!=ClassDef::Interface)
2049       {
2050         reimplFromLine = theTranslator->trReimplementedFromList(1);
2051       }
2052       else
2053       {
2054         reimplFromLine = theTranslator->trImplementedFromList(1);
2055       }
2056       int markerPos = reimplFromLine.find("@0");
2057       if (markerPos!=-1) // should always pass this.
2058       {
2059         ol.parseText(reimplFromLine.left(markerPos)); //text left from marker
2060         if (bmd->isLinkable()) // replace marker with link
2061         {
2062           //Definition *bd=bmd->group;
2063           //if (bd==0) bd=bcd;
2064           ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
2065               bmd->anchor(),bcd->displayName());
2066
2067           //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2068           //    bmd->anchor(),bcd->name());
2069           if ( bmd->isLinkableInProject() ) 
2070           {
2071             writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
2072           }
2073         }
2074         else
2075         {
2076           ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2077               0,bcd->displayName());
2078           if (bcd->isLinkableInProject()/* && !Config_getBool("PDF_HYPERLINKS")*/ )
2079           {
2080             writePageRef(ol,bcd->getOutputFileBase(),bcd->anchor());
2081           }
2082         }
2083         ol.parseText(reimplFromLine.right(
2084               reimplFromLine.length()-markerPos-2)); // text right from marker
2085
2086       }
2087       else
2088       {
2089         err("error: translation error: no marker in trReimplementsFromList()\n");
2090       }
2091       ol.endParagraph();
2092     }
2093   }
2094 }
2095
2096 void MemberDef::_writeReimplementedBy(OutputList &ol)
2097 {
2098   LockingPtr<MemberList> bml=reimplementedBy();
2099   if (bml!=0)
2100   {
2101     MemberListIterator mli(*bml);
2102     MemberDef *bmd=0;
2103     uint count=0;
2104     ClassDef *bcd=0;
2105     for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->getClassDef());++mli)
2106     {
2107       // count the members that directly inherit from md and for
2108       // which the member and class are visible in the docs.
2109       if ( bmd->isLinkable() && bcd->isLinkable() ) 
2110       {
2111         count++;
2112       }
2113     }
2114     if (count>0)
2115     {
2116       mli.toFirst();
2117       // write the list of classes that overwrite this member
2118       ol.startParagraph();
2119
2120       QCString reimplInLine;
2121       if (m_impl->virt==Pure || (m_impl->classDef && m_impl->classDef->compoundType()==ClassDef::Interface))
2122       {
2123         reimplInLine = theTranslator->trImplementedInList(count);
2124       }
2125       else
2126       {
2127         reimplInLine = theTranslator->trReimplementedInList(count);
2128       }
2129       static QRegExp marker("@[0-9]+");
2130       int index=0,newIndex,matchLen;
2131       // now replace all markers in reimplInLine with links to the classes
2132       while ((newIndex=marker.match(reimplInLine,index,&matchLen))!=-1)
2133       {
2134         ol.parseText(reimplInLine.mid(index,newIndex-index));
2135         bool ok;
2136         uint entryIndex = reimplInLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
2137         //bmd=bml->at(entryIndex);
2138
2139         count=0;
2140         // find the entryIndex-th documented entry in the inheritance list.
2141         for (mli.toLast();(bmd=mli.current()) && (bcd=bmd->getClassDef());--mli)
2142         {
2143           if ( bmd->isLinkable() && bcd->isLinkable()) 
2144           {
2145             if (count==entryIndex) break;
2146             count++;
2147           }
2148         }
2149
2150         if (ok && bcd && bmd) // write link for marker
2151         {
2152           //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2153           //    bmd->anchor(),bcd->name());
2154           ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
2155               bmd->anchor(),bcd->displayName());
2156
2157           if (bmd->isLinkableInProject() ) 
2158           {
2159             writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
2160           }
2161         }
2162         ++mli;
2163         index=newIndex+matchLen;
2164       } 
2165       ol.parseText(reimplInLine.right(reimplInLine.length()-index));
2166       ol.endParagraph();
2167     }
2168   }
2169 }
2170
2171 void MemberDef::_writeCategoryRelation(OutputList &ol)
2172 {
2173   if (m_impl->classDef) // this should be a member of a class/category
2174   {
2175     //printf("%s: category %s relation %s class=%s categoryOf=%s\n",
2176     //    name().data(),
2177     //    m_impl->category ? m_impl->category->name().data() : "<none>",
2178     //    m_impl->categoryRelation ? m_impl->categoryRelation->name().data() : "<none>",
2179     //    m_impl->classDef->name().data(),
2180     //    m_impl->classDef->categoryOf() ? m_impl->classDef->categoryOf()->name().data() : "<none>"
2181     //    );
2182     QCString text;
2183     QCString ref;
2184     QCString file;
2185     QCString anc;
2186     QCString name;
2187     int i=-1;
2188     if (m_impl->categoryRelation && m_impl->categoryRelation->isLinkable())
2189     {
2190       if (m_impl->category)
2191       {
2192         // this member is in a normal class and implements method categoryRelation from category 
2193         // so link to method 'categoryRelation' with 'provided by category 'category' text.
2194         text = theTranslator->trProvidedByCategory();
2195         name = m_impl->category->displayName();
2196       }
2197       else if (m_impl->classDef->categoryOf())
2198       {
2199         // this member is part of a category so link to the corresponding class member of the class we extend
2200         // so link to method 'categoryRelation' with 'extends class 'classDef->categoryOf()'
2201         text = theTranslator->trExtendsClass();
2202         name = m_impl->classDef->categoryOf()->displayName();
2203       }
2204       i=text.find("@1");
2205       if (i!=-1)
2206       {
2207         MemberDef *md = m_impl->categoryRelation;
2208         ref  = md->getReference();
2209         file = md->getOutputFileBase();
2210         anc  = md->anchor();
2211       }
2212     }
2213     if (i!=-1 && !name.isEmpty())
2214     {
2215       ol.startParagraph();
2216       ol.parseText(text.left(i));
2217       ol.writeObjectLink(ref,file,anc,name);
2218       ol.parseText(text.mid(i+2));
2219       ol.endParagraph();
2220     }
2221   }
2222 }
2223
2224 void MemberDef::_writeExamples(OutputList &ol)
2225 {
2226   // write the list of examples that use this member
2227   if (hasExamples())
2228   {
2229     ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": ");
2230     ol.startDescForItem();
2231     writeExample(ol,m_impl->exampleSDict);
2232     ol.endDescForItem();
2233     ol.endSimpleSect();
2234   }
2235 }
2236
2237 void MemberDef::_writeTypeConstraints(OutputList &ol)
2238 {
2239   if (m_impl->typeConstraints)
2240   {
2241     writeTypeConstraints(ol,this,m_impl->typeConstraints);
2242   }
2243 }
2244
2245 void MemberDef::_writeEnumValues(OutputList &ol,Definition *container,
2246                                  const QCString &cfname,const QCString &ciname,
2247                                  const QCString &cname)
2248 {
2249   // For enum, we also write the documented enum values
2250   if (isEnumerate())
2251   {
2252     bool first=TRUE;
2253     LockingPtr<MemberList> fmdl=enumFieldList();
2254     //printf("** %s: enum values=%d\n",name().data(),fmdl!=0 ? fmdl->count() : 0);
2255     if (fmdl!=0)
2256     {
2257       MemberDef *fmd=fmdl->first();
2258       while (fmd)
2259       {
2260         //printf("Enum %p: isLinkable()=%d\n",fmd,fmd->isLinkable());
2261         if (fmd->isLinkable())
2262         {
2263           if (first)
2264           {
2265             ol.startSimpleSect(BaseOutputDocInterface::EnumValues,0,0,theTranslator->trEnumerationValues()+": ");
2266             ol.startDescForItem();
2267             ol.startDescTable();
2268           }
2269
2270           ol.addIndexItem(fmd->name(),ciname);
2271           ol.addIndexItem(ciname,fmd->name());
2272
2273           //Doxygen::indexList.addIndexItem(
2274           //                       ciname,                                // level1
2275           //                       fmd->name(),                           // level2
2276           //                       separateMemPages ? cfname : cfiname,   // contRef
2277           //                       cfname,                                // memRef
2278           //                       fmd->anchor(),                         // anchor
2279           //                       fmd);                                  // memberdef
2280           Doxygen::indexList.addIndexItem(container,fmd);
2281
2282           //ol.writeListItem();
2283           ol.startDescTableTitle(); // this enables emphasis!
2284           ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString());
2285           first=FALSE;
2286           //ol.startEmphasis();
2287           ol.docify(fmd->name());
2288           //ol.endEmphasis();
2289           ol.disableAllBut(OutputGenerator::Man);
2290           ol.writeString(" ");
2291           ol.enableAll();
2292           ol.endDoxyAnchor(cfname,fmd->anchor());
2293           ol.endDescTableTitle();
2294           //ol.newParagraph();
2295           ol.startDescTableData();
2296
2297           if (!fmd->briefDescription().isEmpty())
2298           { 
2299             ol.parseDoc(fmd->briefFile(),fmd->briefLine(),getOuterScope()?getOuterScope():container,fmd,fmd->briefDescription(),TRUE,FALSE);
2300           }
2301           // FIXME:PARA
2302           //if (!fmd->briefDescription().isEmpty() && 
2303           //    !fmd->documentation().isEmpty())
2304           //{
2305           //  ol.newParagraph();
2306           //}
2307           if (!fmd->documentation().isEmpty())
2308           { 
2309             ol.parseDoc(fmd->docFile(),fmd->docLine(),getOuterScope()?getOuterScope():container,fmd,fmd->documentation()+"\n",TRUE,FALSE);
2310           }
2311           ol.endDescTableData();
2312         }
2313         fmd=fmdl->next();
2314       }
2315     }
2316     if (!first) 
2317     { 
2318       //ol.endItemList(); 
2319       ol.endDescTable();
2320       ol.endDescForItem();
2321       ol.endSimpleSect();
2322       ol.writeChar('\n'); 
2323     }
2324   }
2325 }
2326
2327
2328 /*! Writes the "detailed documentation" section of this member to
2329  *  all active output formats.
2330  */
2331 void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
2332                                    const char *scName,
2333                                    Definition *container,
2334                                    bool inGroup,
2335                                    bool showEnumValues,
2336                                    bool showInline
2337                                   )
2338 {
2339   // if this member is in a group find the real scope name.
2340   bool hasParameterList = FALSE;
2341   bool inFile = container->definitionType()==Definition::TypeFile;
2342   bool hasDocs = isDetailedSectionVisible(inGroup,inFile);
2343
2344   //printf("MemberDef::writeDocumentation(): name=`%s' hasDocs=`%d' containerType=%d inGroup=%d\n",
2345   //    name().data(),hasDocs,container->definitionType(),inGroup);
2346
2347   if ( !hasDocs ) return;
2348   if (isEnumValue() && !showEnumValues) return;
2349
2350   KEEP_RESIDENT_DURING_CALL;
2351
2352   SrcLangExt lang = getLanguage();
2353   //printf("member=%s lang=%d\n",name().data(),lang);
2354   bool optVhdl = lang==SrcLangExt_VHDL;
2355   QCString sep = getLanguageSpecificSeparator(lang,TRUE);
2356
2357   QCString scopeName = scName;
2358   QCString memAnchor = anchor();
2359   QCString ciname = container->name();
2360   if (container->definitionType()==TypeGroup)
2361   {
2362     if (getClassDef())          scopeName=getClassDef()->displayName();
2363     else if (getNamespaceDef()) scopeName=getNamespaceDef()->displayName();
2364     else if (getFileDef())      scopeName=getFileDef()->displayName();
2365     ciname = ((GroupDef *)container)->groupTitle();
2366   }
2367   else if (container->definitionType()==TypeFile && getNamespaceDef())
2368   { // member is in a namespace, but is written as part of the file documentation
2369     // as well, so we need to make sure its label is unique.
2370     memAnchor.prepend("file_");
2371   }
2372
2373   QCString cname   = container->name();
2374   QCString cfname  = getOutputFileBase();
2375   QCString cfiname = container->getOutputFileBase();
2376
2377   // get member name
2378   QCString doxyName=name();
2379   // prepend scope if there is any. TODO: make this optional for C only docs
2380   if (!scopeName.isEmpty())
2381   {
2382     doxyName.prepend(scopeName+sep);
2383   }
2384   QCString doxyArgs=argsString();
2385
2386   QCString ldef = definition();
2387   QCString title = name();
2388   //printf("member `%s' def=`%s'\n",name().data(),ldef.data());
2389   if (isEnumerate()) 
2390   {
2391     if (title.at(0)=='@')
2392     {
2393       ldef = title = "anonymous enum";
2394     }
2395     else
2396     {
2397       ldef.prepend("enum ");
2398     }
2399   }
2400   else if (isEnumValue())
2401   {
2402     if (ldef.at(0)=='@')
2403     {
2404       ldef=ldef.mid(2);
2405     }
2406   }
2407   int i=0,l;
2408   static QRegExp r("@[0-9]+");
2409
2410   //----------------------------------------
2411
2412   ol.pushGeneratorState();
2413
2414   bool htmlEndLabelTable=FALSE;
2415   QStrList sl;
2416   _getLabels(sl,container);
2417
2418   if ((isVariable() || isTypedef()) && (i=r.match(ldef,0,&l))!=-1)
2419   {
2420     // find enum type and insert it in the definition
2421     QListIterator<MemberDef> vmli(*ml);
2422     MemberDef *vmd;
2423     bool found=FALSE;
2424     for ( ; (vmd=vmli.current()) && !found ; ++vmli)
2425     {
2426       if (vmd->isEnumerate() && ldef.mid(i,l)==vmd->name())
2427       {
2428         ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
2429         ol.startMemberDoc(ciname,name(),memAnchor,name(),showInline);
2430         linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),this,ldef.left(i));
2431         vmd->writeEnumDeclaration(ol,getClassDef(),getNamespaceDef(),getFileDef(),getGroupDef());
2432         linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),this,ldef.right(ldef.length()-i-l));
2433
2434         found=TRUE;
2435       }
2436     }
2437     if (!found) // anonymous compound
2438     {
2439       //printf("Anonymous compound `%s'\n",cname.data());
2440       ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
2441       ol.startMemberDoc(ciname,name(),memAnchor,name(),showInline);
2442       // search for the last anonymous compound name in the definition
2443       int si=ldef.find(' '),pi,ei=i+l;
2444       if (si==-1) si=0;
2445       while ((pi=r.match(ldef,i+l,&l))!=-1) 
2446       {
2447         i=pi;
2448         ei=i+l;
2449       }
2450       // first si characters of ldef contain compound type name
2451       ol.startMemberDocName(isObjCMethod());
2452       ol.docify(ldef.left(si));
2453       ol.docify(" { ... } ");
2454       // last ei characters of ldef contain pointer/reference specifiers
2455       int ni=ldef.find("::",si);
2456       if (ni>=ei) ei=ni+2;
2457       linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),this,ldef.right(ldef.length()-ei));
2458     }
2459   }
2460   else // not an enum value or anonymous compound
2461   {
2462     ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
2463     ol.startMemberDoc(ciname,name(),memAnchor,title,showInline);
2464
2465     ClassDef *cd=getClassDef();
2466     if (!Config_getBool("HIDE_SCOPE_NAMES"))
2467     {
2468       bool first=TRUE;
2469       SrcLangExt lang = getLanguage();
2470       if (m_impl->defTmpArgLists && lang==SrcLangExt_Cpp) 
2471         // definition has explicit template parameter declarations
2472       {
2473         QListIterator<ArgumentList> ali(*m_impl->defTmpArgLists);
2474         ArgumentList *tal;
2475         for (ali.toFirst();(tal=ali.current());++ali)
2476         {
2477           if (tal->count()>0)
2478           {
2479             if (!first) ol.docify(" ");
2480             ol.startMemberDocPrefixItem();
2481             writeTemplatePrefix(ol,tal);
2482             ol.endMemberDocPrefixItem();
2483           }
2484         }
2485       }
2486       else // definition gets it template parameters from its class
2487         // (since no definition was found)
2488       {
2489         if (cd && lang==SrcLangExt_Cpp && !isTemplateSpecialization())
2490         {
2491           QList<ArgumentList> tempParamLists;
2492           cd->getTemplateParameterLists(tempParamLists);
2493           //printf("#tempParamLists=%d\n",tempParamLists.count());
2494           QListIterator<ArgumentList> ali(tempParamLists);
2495           ArgumentList *tal;
2496           for (ali.toFirst();(tal=ali.current());++ali)
2497           {
2498             if (tal->count()>0)
2499             {
2500               if (!first) ol.docify(" ");
2501               ol.startMemberDocPrefixItem();
2502               writeTemplatePrefix(ol,tal);
2503               ol.endMemberDocPrefixItem();
2504             }
2505           }
2506         }
2507         if (m_impl->tArgList && lang==SrcLangExt_Cpp) // function template prefix
2508         {
2509           ol.startMemberDocPrefixItem();
2510           writeTemplatePrefix(ol,m_impl->tArgList);
2511           ol.endMemberDocPrefixItem();
2512         }
2513       }
2514     }
2515
2516     if (sl.count()>0)
2517     {
2518       ol.pushGeneratorState();
2519       ol.disableAll();
2520       ol.enable(OutputGenerator::Html);
2521       ol.writeString("<table class=\"mlabels\">\n");
2522       ol.writeString("  <tr>\n");
2523       ol.writeString("  <td class=\"mlabels-left\">\n");
2524       ol.popGeneratorState();
2525       htmlEndLabelTable=TRUE;
2526     }
2527
2528     ol.startMemberDocName(isObjCMethod());
2529     if (cd && cd->isObjectiveC())
2530     {
2531       // strip scope name
2532       int ep = ldef.find("::");
2533       if (ep!=-1) 
2534       {
2535         int sp=ldef.findRev(' ',ep);
2536         if (sp!=-1)
2537         {
2538           ldef=ldef.left(sp+1)+ldef.mid(ep+2);
2539         }
2540       }
2541       // strip keywords
2542       int dp = ldef.find(':');
2543       if (dp!=-1)
2544       {
2545         ldef=ldef.left(dp+1);
2546       }
2547       int l=ldef.length();
2548       //printf("start >%s<\n",ldef.data());
2549       int i=l-1;
2550       while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--;
2551       while (i>=0 && isspace((uchar)ldef.at(i))) i--;
2552       if (i>0)
2553       {
2554         // insert braches around the type
2555         QCString tmp("("+ldef.left(i+1)+")"+ldef.mid(i+1));
2556         ldef=tmp;
2557       }
2558       //printf("end   >%s< i=%d\n",ldef.data(),i);
2559       if (isStatic()) ldef.prepend("+ "); else ldef.prepend("- ");
2560     }
2561
2562     if (optVhdl)
2563     {
2564       VhdlDocGen::writeVHDLTypeDocumentation(this,container,ol);
2565     }
2566     else
2567     {
2568       linkifyText(TextGeneratorOLImpl(ol),
2569                   container,
2570                   getBodyDef(),
2571                   this,
2572                   substitute(ldef,"::",sep)
2573                  );
2574       hasParameterList=writeDefArgumentList(ol,cd,scopeName,this);
2575     }
2576
2577     if (hasOneLineInitializer()) // add initializer
2578     {
2579       if (!isDefine()) 
2580       {
2581         //ol.docify(" = "); 
2582         ol.docify(" "); 
2583         QCString init = m_impl->initializer.simplifyWhiteSpace();
2584         linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),this,init);
2585       }
2586       else 
2587       {
2588         ol.writeNonBreakableSpace(3);
2589         linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),this,m_impl->initializer);
2590       }
2591     }
2592     if (excpString()) // add exception list
2593     {
2594       ol.docify(" ");
2595       linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),this,excpString());
2596     }
2597   }
2598
2599   ol.pushGeneratorState();
2600   ol.disable(OutputGenerator::Html);
2601   if (sl.count()>0)
2602   {
2603     ol.startLabels();
2604     const char *s=sl.first();
2605     while (s)
2606     {
2607       const char *ns = sl.next();
2608       ol.writeLabel(s,ns==0);
2609       s=ns;
2610     }
2611     ol.endLabels();
2612   }
2613   ol.popGeneratorState();
2614
2615   if (hasParameterList) 
2616   {
2617     ol.endParameterList();
2618     ol.endMemberDoc(TRUE);
2619   }
2620   else
2621   {
2622     ol.endMemberDocName();
2623     ol.endMemberDoc(FALSE);
2624   }
2625
2626   // for HTML write the labels here
2627   ol.pushGeneratorState();
2628   ol.disableAll();
2629   ol.enable(OutputGenerator::Html);
2630   if (htmlEndLabelTable)
2631   {
2632     ol.writeString("  </td>\n");
2633     ol.writeString("  <td class=\"mlabels-right\">\n");
2634     ol.startLabels();
2635     const char *s=sl.first();
2636     while (s)
2637     {
2638       const char *ns = sl.next();
2639       ol.writeLabel(s,ns==0);
2640       s=ns;
2641     }
2642     ol.endLabels();
2643     ol.writeString("  </td>\n");
2644     ol.writeString("  </tr>\n");
2645     ol.writeString("</table>\n");
2646   }
2647   ol.writeString("</div>");
2648   ol.popGeneratorState();
2649
2650
2651   ol.endDoxyAnchor(cfname,memAnchor);
2652   ol.startIndent();
2653
2654   /* write multi-line initializer (if any) */
2655   if (hasMultiLineInitializer()
2656       //initLines>0 && ((initLines<maxInitLines && userInitLines==-1) // implicitly enabled
2657       //                || initLines<userInitLines // explicitly enabled
2658       //               )
2659      )
2660   {
2661     //printf("md=%s initLines=%d init=`%s'\n",name().data(),initLines,init.data());
2662     ol.startBold();
2663     if (m_impl->mtype==Define)
2664       ol.parseText(theTranslator->trDefineValue());
2665     else
2666       ol.parseText(theTranslator->trInitialValue());
2667     ol.endBold();
2668     ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
2669     pIntf->resetCodeParserState();
2670     ol.startCodeFragment();
2671     pIntf->parseCode(ol,scopeName,m_impl->initializer,FALSE,0,getFileDef(),
2672                      -1,-1,TRUE,this,FALSE,this);
2673     ol.endCodeFragment();
2674   }
2675
2676   QCString brief           = briefDescription();
2677   QCString detailed        = documentation();
2678   LockingPtr<ArgumentList> docArgList = LockingPtr<ArgumentList>(this,m_impl->defArgList);
2679   if (m_impl->templateMaster)
2680   {
2681     brief      = m_impl->templateMaster->briefDescription();
2682     detailed   = m_impl->templateMaster->documentation();
2683     docArgList = m_impl->templateMaster->argumentList();
2684   }
2685
2686   /* write brief description */
2687   if (!brief.isEmpty() && 
2688       (Config_getBool("REPEAT_BRIEF") || 
2689        !Config_getBool("BRIEF_MEMBER_DESC")
2690       ) 
2691      )  
2692   { 
2693     ol.startParagraph();
2694     ol.parseDoc(briefFile(),briefLine(),
2695                 getOuterScope()?getOuterScope():container,this,
2696                 brief,FALSE,FALSE,0,TRUE,FALSE);
2697     ol.endParagraph();
2698   }
2699
2700   /* write detailed description */
2701   if (!detailed.isEmpty() || 
2702       !inbodyDocumentation().isEmpty())
2703   { 
2704     // write vhdl inline code with or without option INLINE_SOURCE
2705     if (optVhdl && VhdlDocGen::isMisc(this)) 
2706     {
2707       VhdlDocGen::writeSource(this,ol,cname);
2708       return;
2709     }
2710     else
2711     {
2712       ol.parseDoc(docFile(),docLine(),getOuterScope()?getOuterScope():container,this,detailed+"\n",TRUE,FALSE);
2713     }
2714    
2715     if (!inbodyDocumentation().isEmpty())
2716     {
2717       ol.parseDoc(inbodyFile(),inbodyLine(),
2718                   getOuterScope()?getOuterScope():container,this,
2719                   inbodyDocumentation()+"\n",TRUE,FALSE);
2720     }
2721   }
2722   else if (!brief.isEmpty() && (Config_getBool("REPEAT_BRIEF") ||
2723         !Config_getBool("BRIEF_MEMBER_DESC")))
2724   {
2725     if (!inbodyDocumentation().isEmpty())
2726     {
2727       ol.parseDoc(inbodyFile(),inbodyLine(),getOuterScope()?getOuterScope():container,this,inbodyDocumentation()+"\n",TRUE,FALSE);
2728     }
2729   }
2730
2731
2732   //printf("***** defArgList=%p name=%s docs=%s hasDocs=%d\n",
2733   //     defArgList, 
2734   //     defArgList?defArgList->hasDocumentation():-1);
2735   if (docArgList!=0 && docArgList->hasDocumentation())
2736   {
2737     QCString paramDocs;
2738     ArgumentListIterator ali(*docArgList);
2739     Argument *a;
2740     // convert the parameter documentation into a list of @param commands
2741     for (ali.toFirst();(a=ali.current());++ali)
2742     {
2743       if (a->hasDocumentation())
2744       {
2745         QCString direction = extractDirection(a->docs);
2746         paramDocs+="@param"+direction+" "+a->name+" "+a->docs;
2747       }
2748     }
2749     // feed the result to the documentation parser
2750     ol.parseDoc(
2751         docFile(),docLine(),
2752         getOuterScope()?getOuterScope():container,
2753         this,         // memberDef
2754         paramDocs,    // docStr
2755         TRUE,         // indexWords
2756         FALSE         // isExample
2757         );
2758
2759   }
2760
2761   _writeEnumValues(ol,container,cfname,ciname,cname);
2762   _writeReimplements(ol);
2763   _writeReimplementedBy(ol);
2764   _writeCategoryRelation(ol);
2765   _writeExamples(ol);
2766   _writeTypeConstraints(ol);
2767   writeSourceDef(ol,cname);
2768   writeSourceRefs(ol,cname);
2769   writeSourceReffedBy(ol,cname);
2770   writeInlineCode(ol,cname);
2771   _writeCallGraph(ol);
2772   _writeCallerGraph(ol);
2773
2774   if (Doxygen::userComments)
2775   {
2776     ol.pushGeneratorState();
2777     ol.disableAllBut(OutputGenerator::Html);
2778     QCString cmd = "<? $root=$_SERVER['DOCUMENT_ROOT']; "
2779                    "passthru(\"$root/doxynotes --lookup "+
2780                    getOutputFileBase()+":"+anchor()+"\") ?>";
2781     ol.writeString(cmd);
2782     ol.popGeneratorState();
2783   }
2784
2785   ol.endIndent();
2786
2787   // enable LaTeX again
2788   //if (Config_getBool("EXTRACT_ALL") && !hasDocs) ol.enable(OutputGenerator::Latex); 
2789   ol.popGeneratorState();
2790
2791   //------------------------------------------------
2792
2793   if (!Config_getBool("EXTRACT_ALL") &&
2794       Config_getBool("WARN_IF_UNDOCUMENTED") &&
2795       Config_getBool("WARN_NO_PARAMDOC") &&
2796       !Doxygen::suppressDocWarnings)
2797   {
2798     if (!hasDocumentedParams())
2799     {
2800       warn_doc_error(docFile(),docLine(),
2801           "warning: parameters of member %s are not (all) documented",
2802           qPrint(qualifiedName()));
2803     }
2804     if (!hasDocumentedReturnType() && isFunction() && hasDocumentation())
2805     {
2806       warn_doc_error(docFile(),docLine(),
2807           "warning: return type of member %s is not documented",
2808           qPrint(qualifiedName()));
2809     }
2810   }
2811 }
2812
2813 // strip scope and field name from the type
2814 // example: "struct N::S.v.c" will become "struct v"
2815 static QCString simplifyTypeForTable(const QCString &s)
2816 {
2817   QCString ts=removeAnonymousScopes(s);
2818   if (ts.right(2)=="::") ts = ts.left(ts.length()-2);
2819   static QRegExp re("[A-Z_a-z0-9]+::");
2820   int i,l;
2821   while ((i=re.match(ts,0,&l))!=-1)
2822   {
2823     ts=ts.left(i)+ts.mid(i+l);
2824   }
2825   i=ts.findRev('.');
2826   if (i!=-1) ts = ts.left(i);
2827   i=ts.findRev('.');
2828   if (i!=-1) ts = ts.right(ts.length()-i-1);
2829   //printf("simplifyTypeForTable(%s)->%s\n",s.data(),ts.data());
2830   return ts;
2831 }
2832
2833 #if 0
2834 /** Returns the type definition corresponding to a member's return type. 
2835  *  @param[in]  scope The scope in which to search for the class definition.
2836  *  @param[in]  type  The string representing the member's return type.
2837  *  @param[in]  lang  The programming language in which the class is defined.
2838  *  @param[out] start The string position where the class definition name was found.
2839  *  @param[out] length The length of the class definition's name.
2840  */
2841 static Definition *getClassFromType(Definition *scope,const QCString &type,SrcLangExt lang,int &start,int &length)
2842 {
2843   int pos=0;
2844   int i;
2845   QCString name;
2846   QCString templSpec;
2847   while ((i=extractClassNameFromType(type,pos,name,templSpec,lang))!=-1)
2848   {
2849     ClassDef *cd=0;
2850     MemberDef *md=0;
2851     int l = name.length()+templSpec.length();
2852     if (!templSpec.isEmpty())
2853     {
2854       cd = getResolvedClass(scope,0,name+templSpec,&md);
2855     }
2856     cd = getResolvedClass(scope,0,name);
2857     if (cd) 
2858     {
2859       start=i;
2860       length=l;
2861       printf("getClassFromType: type=%s name=%s start=%d length=%d\n",type.data(),name.data(),start,length);
2862       return cd;
2863     }
2864     else if (md)
2865     {
2866       start=i;
2867       length=l;
2868       printf("getClassFromType: type=%s name=%s start=%d length=%d\n",type.data(),name.data(),start,length);
2869       return md;
2870     }
2871     pos=i+l;
2872   }
2873   return 0;
2874 }
2875 #endif
2876
2877 void MemberDef::writeMemberDocSimple(OutputList &ol, Definition *container)
2878 {
2879   KEEP_RESIDENT_DURING_CALL;
2880
2881   Definition *scope  = getOuterScope();
2882   QCString doxyName  = name();
2883   QCString doxyArgs  = argsString();
2884   QCString memAnchor = anchor();
2885   QCString cfname    = getOutputFileBase();
2886   QCString cname;
2887   if (scope) cname   = scope->name();
2888   if (doxyName.at(0)=='@')
2889   {
2890     doxyName="__unnamed__";
2891   }
2892
2893   ClassDef *cd = m_impl->accessorClass;
2894   //printf("===> %s::anonymous: %s\n",name().data(),cd?cd->name().data():"<none>");
2895
2896   ol.startInlineMemberType();
2897   ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
2898
2899   QCString type = m_impl->accessorType;
2900   if (type.isEmpty())
2901   {
2902     type = m_impl->type;
2903   }
2904   QCString ts = simplifyTypeForTable(type);
2905
2906   if (cd) // cd points to an anonymous struct pointed to by this member
2907           // so we add a link to it from the type column.
2908   {
2909     int i=0;
2910     const char *prefixes[] = { "struct ","union ","class ", 0 };
2911     const char **p = prefixes;
2912     while (*p)
2913     {
2914       int l=strlen(*p);
2915       if (ts.left(l)==*p)
2916       {
2917         ol.writeString(*p);
2918         i=l;
2919       }
2920       p++;
2921     }
2922     ol.writeObjectLink(cd->getReference(),
2923                        cd->getOutputFileBase(),
2924                        cd->anchor(),ts.mid(i));
2925   }
2926   else // use standard auto linking
2927   {
2928     linkifyText(TextGeneratorOLImpl(ol), // out
2929                 scope,                   // scope
2930                 getBodyDef(),            // fileScope
2931                 this,                    // self
2932                 ts,                      // text
2933                 TRUE                     // autoBreak
2934                ); 
2935   }
2936   ol.endDoxyAnchor(cfname,memAnchor);
2937   ol.endInlineMemberType();
2938
2939   ol.startInlineMemberName();
2940   ol.docify(doxyName);
2941   if (!m_impl->bitfields.isEmpty()) // add bitfields
2942   {
2943     linkifyText(TextGeneratorOLImpl(ol),getOuterScope(),getBodyDef(),this,m_impl->bitfields.simplifyWhiteSpace());
2944   }
2945   ol.endInlineMemberName();
2946
2947   ol.startInlineMemberDoc();
2948
2949   QCString brief           = briefDescription();
2950   QCString detailed        = documentation();
2951
2952   /* write brief description */
2953   if (!brief.isEmpty() && 
2954       (Config_getBool("REPEAT_BRIEF") || 
2955        !Config_getBool("BRIEF_MEMBER_DESC")
2956       ) 
2957      )  
2958   { 
2959     ol.parseDoc(briefFile(),briefLine(),
2960                 getOuterScope()?getOuterScope():container,this,
2961                 brief,FALSE,FALSE,0,TRUE,FALSE);
2962   }
2963
2964   /* write detailed description */
2965   if (!detailed.isEmpty())
2966   { 
2967     ol.parseDoc(docFile(),docLine(),
2968                 getOuterScope()?getOuterScope():container,this,
2969                 detailed+"\n",FALSE,FALSE,0,TRUE,FALSE);
2970    
2971   }
2972
2973   ol.endInlineMemberDoc();
2974 }
2975
2976 QCString MemberDef::memberTypeName() const
2977 {
2978   makeResident();
2979   switch (m_impl->mtype)
2980   {
2981     case Define:      return "macro definition";
2982     case Function:    return "function";
2983     case Variable:    return "variable";
2984     case Typedef:     return "typedef";
2985     case Enumeration: return "enumeration"; 
2986     case EnumValue:   return "enumvalue";
2987     case Signal:      return "signal";
2988     case Slot:        return "slot";
2989     case Friend:      return "friend";
2990     case DCOP:        return "dcop";
2991     case Property:    return "property";
2992     case Event:       return "event";
2993     default:          return "unknown";
2994   }
2995 }
2996
2997 void MemberDef::warnIfUndocumented()
2998 {
2999   makeResident();
3000   if (m_impl->memberGroup) return;
3001   ClassDef     *cd = getClassDef();
3002   NamespaceDef *nd = getNamespaceDef();
3003   FileDef      *fd = getFileDef();
3004   GroupDef     *gd = getGroupDef();
3005   Definition *d=0;
3006   const char *t=0;
3007   if (cd) 
3008     t="class", d=cd; 
3009   else if (nd) 
3010     t="namespace", d=nd; 
3011   else if (gd)
3012     t="group", d=gd;
3013   else
3014     t="file", d=fd;
3015   static bool extractAll = Config_getBool("EXTRACT_ALL");
3016
3017   //printf("warnIfUndoc: d->isLinkable()=%d isLinkable()=%d "
3018   //       "isDocumentedFriendClass()=%d name()=%s prot=%d\n",
3019   //       d->isLinkable(),isLinkable(),isDocumentedFriendClass(),
3020   //       name().data(),prot);
3021   if ((!hasUserDocumentation() && !extractAll) &&
3022       !isFriendClass() && 
3023       name().find('@')==-1 && d && d->name().find('@')==-1 &&
3024       protectionLevelVisible(m_impl->prot) &&
3025       !isReference()
3026      )
3027   {
3028     warn_undoc(getDefFileName(),getDefLine(),"warning: Member %s%s (%s) of %s %s is not documented.",
3029          qPrint(name()),qPrint(argsString()),qPrint(memberTypeName()),t,qPrint(d->name()));
3030   }
3031 }
3032
3033
3034
3035 bool MemberDef::isFriendClass() const
3036 {
3037   makeResident();
3038   return (isFriend() && 
3039          (m_impl->type=="friend class" || m_impl->type=="friend struct" || 
3040           m_impl->type=="friend union"));
3041 }
3042
3043 bool MemberDef::isDocumentedFriendClass() const
3044 {
3045   makeResident();
3046   ClassDef *fcd=0;
3047   QCString baseName=name();
3048   int i=baseName.find('<');
3049   if (i!=-1) baseName=baseName.left(i);
3050   return (isFriendClass() &&
3051          (fcd=getClass(baseName)) && fcd->isLinkable()); 
3052 }
3053
3054 bool MemberDef::hasDocumentation() const
3055
3056   makeResident();
3057   return Definition::hasDocumentation() || 
3058          (m_impl->mtype==Enumeration && m_impl->docEnumValues) ||  // has enum values
3059          (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation()); // has doc arguments
3060 }
3061
3062 #if 0
3063 bool MemberDef::hasUserDocumentation() const
3064 {
3065   bool hasDocs = Definition::hasUserDocumentation();
3066   return hasDocs;
3067 }
3068 #endif
3069
3070
3071 void MemberDef::setMemberGroup(MemberGroup *grp)
3072 {
3073   makeResident();
3074   m_impl->memberGroup = grp;
3075 }
3076
3077 bool MemberDef::visibleMemberGroup(bool hideNoHeader) 
3078
3079   makeResident();
3080   return m_impl->memberGroup!=0 && 
3081           (!hideNoHeader || m_impl->memberGroup->header()!="[NOHEADER]"); 
3082 }
3083
3084 QCString MemberDef::getScopeString() const
3085 {
3086   makeResident();
3087   QCString result;
3088   if (getClassDef()) result=getClassDef()->displayName();
3089   else if (getNamespaceDef()) result=getNamespaceDef()->displayName();
3090   return result;
3091 }
3092
3093 #if 0
3094 static QCString escapeAnchor(const QCString &anchor)
3095 {
3096   QCString result;
3097   int l = anchor.length(),i;
3098   for (i=0;i<l;i++)
3099   {
3100     char c = anchor.at(i);
3101     if ((c>='a' && c<='z') || (c>='A' && c<='Z'))
3102     {
3103       result+=c;
3104     }
3105     else
3106     {
3107       static char hexStr[]="0123456789ABCDEF";
3108       char escChar[]={ '_', 0, 0, 0 };
3109       escChar[1]=hexStr[c>>4];
3110       escChar[2]=hexStr[c&0xf];
3111       result+=escChar;
3112     }
3113   }
3114   return result;
3115 }
3116 #endif
3117
3118 void MemberDef::setAnchor(const char *a)
3119 {
3120   makeResident();
3121   //anc=a;
3122   (void)a;
3123   QCString memAnchor = name();
3124   if (!m_impl->args.isEmpty()) memAnchor+=m_impl->args;
3125
3126   memAnchor.prepend(definition()); // actually the method name is now included
3127             // twice, which is silly, but we keep it this way for backward
3128             // compatibility.
3129
3130   // include number of template arguments as well, 
3131   // to distinguish between two template
3132   // specializations that only differ in the template parameters.
3133   if (m_impl->tArgList) 
3134   {
3135     char buf[20];
3136     snprintf(buf,20,"%d:",m_impl->tArgList->count());
3137     buf[19]='\0';
3138     memAnchor.prepend(buf);
3139   }
3140   
3141   // convert to md5 hash
3142   uchar md5_sig[16];
3143   QCString sigStr(33);
3144   MD5Buffer((const unsigned char *)memAnchor.data(),memAnchor.length(),md5_sig);
3145   //printf("memAnchor=%s\n",memAnchor.data());
3146   MD5SigToString(md5_sig,sigStr.data(),33);
3147   m_impl->anc = "a"+sigStr;
3148 }
3149
3150 void MemberDef::setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri,
3151                             const QCString &fileName,int startLine,
3152                             bool hasDocs,MemberDef *member)
3153 {
3154   //printf("%s MemberDef::setGroupDef(%s)\n",name().data(),gd->name().data());
3155   makeResident();
3156   m_impl->group=gd;
3157   m_impl->grouppri=pri;
3158   m_impl->groupFileName=fileName;
3159   m_impl->groupStartLine=startLine;
3160   m_impl->groupHasDocs=hasDocs;
3161   m_impl->groupMember=member;
3162   m_isLinkableCached = 0; 
3163 }
3164
3165 void MemberDef::setEnumScope(MemberDef *md) 
3166
3167   makeResident();
3168   m_impl->enumScope=md; 
3169   if (md->getGroupDef())
3170   {
3171     m_impl->group=md->getGroupDef();
3172     m_impl->grouppri=md->getGroupPri();
3173     m_impl->groupFileName=md->getGroupFileName();
3174     m_impl->groupStartLine=md->getGroupStartLine();
3175     m_impl->groupHasDocs=md->getGroupHasDocs();
3176     m_isLinkableCached = 0; 
3177   }
3178 }
3179
3180 void MemberDef::setMemberClass(ClassDef *cd)     
3181
3182   makeResident();
3183   m_impl->classDef=cd; 
3184   m_isLinkableCached = 0; 
3185   m_isConstructorCached = 0; 
3186   setOuterScope(cd); 
3187 }
3188
3189 void MemberDef::setNamespace(NamespaceDef *nd) 
3190
3191   makeResident();
3192   m_impl->nspace=nd; 
3193   setOuterScope(nd); 
3194 }
3195
3196 MemberDef *MemberDef::createTemplateInstanceMember(
3197         ArgumentList *formalArgs,ArgumentList *actualArgs)
3198 {
3199   KEEP_RESIDENT_DURING_CALL;
3200   //printf("  Member %s %s %s\n",typeString(),name().data(),argsString());
3201   ArgumentList *actualArgList = 0;
3202   if (m_impl->defArgList)
3203   {
3204     actualArgList = m_impl->defArgList->deepCopy();
3205
3206     // replace formal arguments with actuals
3207     ArgumentListIterator ali(*actualArgList);
3208     Argument *arg;
3209     for (;(arg=ali.current());++ali)
3210     {
3211       arg->type = substituteTemplateArgumentsInString(arg->type,formalArgs,actualArgs);
3212     }
3213     actualArgList->trailingReturnType = 
3214        substituteTemplateArgumentsInString(actualArgList->trailingReturnType,formalArgs,actualArgs);
3215   }
3216
3217   QCString methodName=name();
3218   if (methodName.left(9)=="operator ") // conversion operator
3219   {
3220     methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs);
3221   }
3222
3223   MemberDef *imd = new MemberDef(
3224                        getDefFileName(),getDefLine(),
3225                        substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs), 
3226                        methodName, 
3227                        substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs), 
3228                        m_impl->exception, m_impl->prot,
3229                        m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, 0, 0
3230                    );
3231   imd->setArgumentList(actualArgList);
3232   imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs));
3233   imd->setBodyDef(getBodyDef());
3234   imd->setBodySegment(getStartBodyLine(),getEndBodyLine());
3235   //imd->setBodyMember(this);
3236
3237   // TODO: init other member variables (if needed).
3238   // TODO: reimplemented info
3239   return imd; 
3240 }
3241
3242 bool MemberDef::hasOneLineInitializer() const
3243 {
3244   makeResident();
3245   //printf("%s: init=%s, initLines=%d maxInitLines=%d userInitLines=%d\n",
3246   //    name().data(),m_impl->initializer.data(),m_impl->initLines,
3247   //    m_impl->maxInitLines,m_impl->userInitLines);
3248   return !m_impl->initializer.isEmpty() && m_impl->initLines==0 && // one line initializer
3249          ((m_impl->maxInitLines>0 && m_impl->userInitLines==-1) || m_impl->userInitLines>0); // enabled by default or explicitly
3250 }
3251
3252 bool MemberDef::hasMultiLineInitializer() const
3253 {
3254   makeResident();
3255   //printf("initLines=%d userInitLines=%d maxInitLines=%d\n",
3256   //    initLines,userInitLines,maxInitLines);
3257   return m_impl->initLines>0 && 
3258          ((m_impl->initLines<m_impl->maxInitLines && m_impl->userInitLines==-1) // implicitly enabled
3259           || m_impl->initLines<m_impl->userInitLines // explicitly enabled
3260          );
3261 }
3262
3263 void MemberDef::setInitializer(const char *initializer)    
3264
3265   makeResident();
3266   m_impl->initializer=initializer; 
3267   int l=m_impl->initializer.length();
3268   int p=l-1;
3269   while (p>=0 && isspace((uchar)m_impl->initializer.at(p))) p--;
3270   m_impl->initializer=m_impl->initializer.left(p+1);
3271   m_impl->initLines=m_impl->initializer.contains('\n');
3272   //printf("%s::setInitializer(%s)\n",name().data(),m_impl->initializer.data());
3273 }
3274
3275 void MemberDef::addListReference(Definition *)
3276 {
3277   KEEP_RESIDENT_DURING_CALL;
3278   static bool optimizeOutputForC = Config_getBool("OPTIMIZE_OUTPUT_FOR_C");
3279   //static bool hideScopeNames     = Config_getBool("HIDE_SCOPE_NAMES");
3280   //static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
3281   //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");  
3282   SrcLangExt lang = getLanguage();
3283   visited=TRUE;
3284   if (!isLinkableInProject()) return;
3285   QCString memLabel;
3286   if (optimizeOutputForC) 
3287   {
3288     memLabel=theTranslator->trGlobal(TRUE,TRUE);
3289   }
3290   else if (lang==SrcLangExt_Fortran)
3291   {
3292     memLabel=theTranslator->trSubprogram(TRUE,TRUE);
3293   }
3294   else
3295   {
3296     memLabel=theTranslator->trMember(TRUE,TRUE);
3297   }
3298   QCString memName = name();
3299   Definition *pd=getOuterScope();
3300   QCString pdName = pd->definitionType()==Definition::TypeClass ? 
3301                     ((ClassDef*)pd)->displayName() : pd->name();
3302   QCString sep = getLanguageSpecificSeparator(lang,TRUE);
3303   QCString memArgs;
3304   if (!isRelated() 
3305       /* && commented out as a result of bug 597016
3306       (
3307        (!hideScopeNames &&                    // there is a scope
3308         pd && pd!=Doxygen::globalScope)       // and we can show it
3309        ||
3310        (pd=getClassDef())                     // it's a class so we
3311                                               // show the scope anyway
3312       )
3313       */
3314      )
3315   {
3316     if (isObjCMethod())
3317     {
3318       memName = "[" + pd->name() + " " + name() + "]";
3319     }
3320     else 
3321     {
3322       if (pd!=Doxygen::globalScope) memName.prepend(pdName+sep);
3323       memArgs = argsString();
3324     }
3325   }
3326   LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems();
3327   if (xrefItems!=0)
3328   {
3329     addRefItem(xrefItems.pointer(),
3330         qualifiedName()+argsString(), // argsString is needed for overloaded functions (see bug 609624)
3331         memLabel,
3332         getOutputFileBase()+"#"+anchor(),memName,memArgs);
3333   }
3334 }
3335
3336 MemberList *MemberDef::getSectionList(Definition *d) const 
3337
3338   makeResident();
3339   char key[20];
3340   sprintf(key,"%p",d);
3341   return (d!=0 && m_impl->classSectionSDict) ? m_impl->classSectionSDict->find(key) : 0;
3342 }
3343
3344 void MemberDef::setSectionList(Definition *d, MemberList *sl)   
3345
3346   makeResident();
3347   //printf("MemberDef::setSectionList(%p,%p) name=%s\n",d,sl,name().data());
3348   char key[20];
3349   sprintf(key,"%p",d);
3350   if (m_impl->classSectionSDict==0) 
3351   {
3352     m_impl->classSectionSDict = new SDict<MemberList>(7);
3353   }
3354   m_impl->classSectionSDict->append(key,sl);
3355 }
3356
3357 Specifier MemberDef::virtualness(int count) const
3358 {
3359   KEEP_RESIDENT_DURING_CALL;
3360   if (count>25) 
3361   {
3362      warn(getDefFileName(),getDefLine(),
3363        "warning: Internal inconsistency: recursion detected in overload relation for member %s!"
3364        ,qPrint(name())
3365       );
3366      return Normal;
3367   }
3368   makeResident();
3369   Specifier v = m_impl->virt;
3370   MemberDef *rmd = reimplements();
3371   while (rmd && v==Normal)
3372   {
3373     v = rmd->virtualness(count+1)==Normal ? Normal : Virtual;
3374     rmd = rmd->reimplements();
3375   }
3376   return v;
3377 }
3378
3379 void MemberDef::_computeIsConstructor()
3380 {
3381   KEEP_RESIDENT_DURING_CALL;
3382   m_isConstructorCached=1; // FALSE
3383   if (m_impl->classDef) 
3384   {
3385     if (m_impl->isDMember) // for D
3386     {
3387       m_isConstructorCached = name()=="this" ? 2 : 1;
3388       return;
3389     }
3390     else if (getLanguage()==SrcLangExt_PHP) // for PHP
3391     { 
3392       m_isConstructorCached = name()=="__construct" ? 2 : 1;
3393       return;
3394     }
3395     else if (name()=="__init__" && 
3396              getLanguage()==SrcLangExt_Python) // for Python
3397     {
3398       m_isConstructorCached = 2; // TRUE
3399       return;
3400     }
3401     else if (getLanguage()==SrcLangExt_Tcl) // for Tcl
3402     {
3403       m_isConstructorCached = name()=="constructor" ? 2 : 1;
3404       return;
3405     }
3406     else // for other languages
3407     {
3408       QCString locName = m_impl->classDef->localName();
3409       int i=locName.find('<');
3410       if (i==-1) // not a template class
3411       {
3412         m_isConstructorCached = name()==locName ? 2 : 1;
3413       }
3414       else
3415       {
3416         m_isConstructorCached = name()==locName.left(i) ? 2 : 1;
3417       }
3418       return;
3419     }
3420   }
3421 }
3422
3423 bool MemberDef::isConstructor() const            
3424
3425   if (m_isConstructorCached==0)
3426   {
3427     MemberDef *that = (MemberDef*)this;
3428     that->_computeIsConstructor();
3429   }
3430   ASSERT(m_isConstructorCached>0);
3431   return m_isConstructorCached==2;
3432
3433 }
3434
3435 void MemberDef::_computeIsDestructor()
3436 {
3437   KEEP_RESIDENT_DURING_CALL;
3438   bool isDestructor;
3439   if (m_impl->isDMember) // for D
3440   {
3441     isDestructor = name()=="~this";
3442   }
3443   else if (getLanguage()==SrcLangExt_PHP) // for PHP
3444   {                
3445     isDestructor = name()=="__destruct";
3446   }
3447   else if (getLanguage()==SrcLangExt_Tcl) // for Tcl
3448   { 
3449     isDestructor = name()=="destructor";
3450   }
3451   else if (name()=="__del__" && 
3452            getLanguage()==SrcLangExt_Python) // for Python
3453   {
3454     isDestructor=TRUE;
3455   }
3456   else // other languages
3457   {
3458     isDestructor =
3459            (name().find('~')!=-1 || name().find('!')!=-1)  // The ! is for C++/CLI
3460            && name().find("operator")==-1; 
3461   }
3462   m_isDestructorCached = isDestructor ? 2 : 1;
3463 }
3464
3465 bool MemberDef::isDestructor() const
3466
3467   if (m_isDestructorCached==0)
3468   {
3469     MemberDef *that=(MemberDef*)this;
3470     that->_computeIsDestructor();
3471   }
3472   ASSERT(m_isDestructorCached>0);
3473   return m_isDestructorCached==2;
3474 }
3475
3476 void MemberDef::writeEnumDeclaration(OutputList &typeDecl,
3477      ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd)
3478 {
3479   KEEP_RESIDENT_DURING_CALL;
3480
3481   int enumMemCount=0;
3482
3483   MemberList *fmdl=m_impl->enumFields;
3484   uint numVisibleEnumValues=0;
3485   if (fmdl)
3486   {
3487     MemberDef *fmd=fmdl->first();
3488     while (fmd)
3489     {
3490       if (fmd->isBriefSectionVisible()) numVisibleEnumValues++;
3491       fmd=fmdl->next();
3492     }
3493   }
3494   if (numVisibleEnumValues==0 && !isBriefSectionVisible()) 
3495   {
3496     return;
3497   }
3498
3499   QCString n = name();
3500   int i=n.findRev("::");
3501   if (i!=-1) n=n.right(n.length()-i-2); // strip scope (TODO: is this needed?)
3502   if (n[0]!='@') // not an anonymous enum
3503   {
3504     if (isLinkableInProject() || hasDocumentedEnumValues())
3505     {
3506       if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !isReference())
3507       {
3508         Doxygen::tagFile << "    <member kind=\"enumeration\">" << endl;
3509         Doxygen::tagFile << "      <name>" << convertToXML(name()) << "</name>" << endl; 
3510         Doxygen::tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;
3511         Doxygen::tagFile << "      <anchor>" << convertToXML(anchor()) << "</anchor>" << endl; 
3512         Doxygen::tagFile << "      <arglist>" << convertToXML(argsString()) << "</arglist>" << endl; 
3513         Doxygen::tagFile << "    </member>" << endl;
3514       }
3515       writeLink(typeDecl,cd,nd,fd,gd);
3516     }
3517     else
3518     {
3519       typeDecl.startBold();
3520       typeDecl.docify(n);
3521       typeDecl.endBold();
3522     }
3523     typeDecl.writeChar(' ');
3524     if (!m_impl->enumBaseType.isEmpty())
3525     {
3526       typeDecl.writeChar(':');
3527       typeDecl.writeChar(' ');
3528       typeDecl.docify(m_impl->enumBaseType);
3529       typeDecl.writeChar(' ');
3530     }
3531   }
3532
3533   uint enumValuesPerLine = (uint)Config_getInt("ENUM_VALUES_PER_LINE");
3534   if (numVisibleEnumValues>0 && enumValuesPerLine>0)
3535   {
3536     typeDecl.docify("{ ");
3537     if (fmdl)
3538     {
3539       MemberDef *fmd=fmdl->first();
3540       bool fmdVisible = fmd->isBriefSectionVisible();
3541       while (fmd)
3542       {
3543         if (fmdVisible)
3544         {
3545           /* in html we start a new line after a number of items */
3546           if (numVisibleEnumValues>enumValuesPerLine
3547               && (enumMemCount%enumValuesPerLine)==0
3548              )
3549           {
3550             typeDecl.pushGeneratorState();
3551             typeDecl.disableAllBut(OutputGenerator::Html);
3552             typeDecl.enable(OutputGenerator::Latex);
3553             typeDecl.lineBreak(); 
3554             typeDecl.disable(OutputGenerator::Latex);
3555             typeDecl.writeString("&#160;&#160;");
3556             typeDecl.popGeneratorState();
3557           }
3558
3559           if (fmd->hasDocumentation()) // enum value has docs
3560           {
3561             if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !fmd->isReference())
3562             {
3563               Doxygen::tagFile << "    <member kind=\"enumvalue\">" << endl;
3564               Doxygen::tagFile << "      <name>" << convertToXML(fmd->name()) << "</name>" << endl; 
3565               Doxygen::tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;              
3566               Doxygen::tagFile << "      <anchor>" << convertToXML(fmd->anchor()) << "</anchor>" << endl; 
3567               Doxygen::tagFile << "      <arglist>" << convertToXML(fmd->argsString()) << "</arglist>" << endl; 
3568               Doxygen::tagFile << "    </member>" << endl;
3569             }
3570             fmd->writeLink(typeDecl,cd,nd,fd,gd);
3571           }
3572           else // no docs for this enum value
3573           {
3574             typeDecl.startBold();
3575             typeDecl.docify(fmd->name());
3576             typeDecl.endBold();
3577           }
3578           if (fmd->hasOneLineInitializer()) // enum value has initializer
3579           {
3580             //typeDecl.writeString(" = ");
3581             typeDecl.writeString(" ");
3582             typeDecl.parseText(fmd->initializer());
3583           }
3584         }
3585
3586         bool prevVisible = fmdVisible;
3587         fmd=fmdl->next();
3588         if (fmd && (fmdVisible=fmd->isBriefSectionVisible())) 
3589         {
3590           typeDecl.writeString(", ");
3591         }
3592         if (prevVisible)
3593         {
3594           typeDecl.disable(OutputGenerator::Man);
3595           typeDecl.writeString("\n"); // to prevent too long lines in LaTeX
3596           typeDecl.enable(OutputGenerator::Man);
3597           enumMemCount++;
3598         }
3599       }
3600       if (numVisibleEnumValues>enumValuesPerLine)
3601       {
3602         typeDecl.pushGeneratorState();
3603         typeDecl.disableAllBut(OutputGenerator::Html);
3604         typeDecl.lineBreak(); 
3605         typeDecl.popGeneratorState();
3606       }
3607     }
3608     typeDecl.docify(" }");
3609   }
3610 }
3611
3612 void MemberDef::setArgumentList(ArgumentList *al) 
3613
3614   makeResident();
3615   if (m_impl->defArgList) delete m_impl->defArgList;
3616   m_impl->defArgList = al;
3617 }
3618
3619 void MemberDef::setDeclArgumentList(ArgumentList *al)
3620 {
3621   makeResident();
3622   if (m_impl->declArgList) delete m_impl->declArgList;
3623   m_impl->declArgList = al;
3624 }
3625
3626 void MemberDef::setTypeConstraints(ArgumentList *al)
3627 {
3628   if (al==0) return;
3629   makeResident();
3630   if (m_impl->typeConstraints) delete m_impl->typeConstraints;
3631   m_impl->typeConstraints = new ArgumentList;
3632   m_impl->typeConstraints->setAutoDelete(TRUE);
3633   ArgumentListIterator ali(*al);
3634   Argument *a;
3635   for (;(a=ali.current());++ali)
3636   {
3637     m_impl->typeConstraints->append(new Argument(*a));
3638   }
3639 }
3640
3641 void MemberDef::setType(const char *t)
3642 {
3643   makeResident();
3644   m_impl->type = t;
3645 }
3646
3647 void MemberDef::setAccessorType(ClassDef *cd,const char *t)
3648 {
3649   makeResident();
3650   m_impl->accessorClass = cd;
3651   m_impl->accessorType = t;
3652 }
3653
3654 void MemberDef::findSectionsInDocumentation()
3655 {
3656   makeResident();
3657   docFindSections(documentation(),this,0,docFile());  
3658 }
3659
3660 void MemberDef::enableCallGraph(bool e) 
3661
3662   makeResident();
3663   m_impl->hasCallGraph=e; 
3664   if (e) Doxygen::parseSourcesNeeded = TRUE;
3665 }
3666
3667 void MemberDef::enableCallerGraph(bool e) 
3668
3669   makeResident();
3670   m_impl->hasCallerGraph=e; 
3671   if (e) Doxygen::parseSourcesNeeded = TRUE;
3672 }
3673
3674 #if 0
3675 bool MemberDef::protectionVisible() const
3676 {
3677   makeResident();
3678   return m_impl->prot==Public || 
3679          (m_impl->prot==Private   && Config_getBool("EXTRACT_PRIVATE"))   ||
3680          (m_impl->prot==Protected && Config_getBool("EXTRACT_PROTECTED")) ||
3681          (m_impl->prot==Package   && Config_getBool("EXTRACT_PACKAGE"));
3682 }
3683 #endif
3684
3685 #if 0
3686 void MemberDef::setInbodyDocumentation(const char *docs,
3687                   const char *docFile,int docLine)
3688 {
3689   makeResident();
3690   m_impl->inbodyDocs = docs;
3691   m_impl->inbodyDocs = m_impl->inbodyDocs.stripWhiteSpace();
3692   m_impl->inbodyLine = docLine;
3693   m_impl->inbodyFile = docFile;
3694 }
3695 #endif
3696
3697 bool MemberDef::isObjCMethod() const
3698 {
3699   makeResident();
3700   if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isFunction()) return TRUE;
3701   return FALSE; 
3702 }
3703
3704 bool MemberDef::isObjCProperty() const
3705 {
3706   makeResident();
3707   if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isProperty()) return TRUE;
3708   return FALSE; 
3709 }
3710
3711 QCString MemberDef::qualifiedName() const
3712 {
3713   makeResident();
3714   if (isObjCMethod())
3715   {
3716     QCString qm;
3717     if (isStatic()) qm="+"; else qm="-";
3718     qm+="[";
3719     qm+=m_impl->classDef->name()+" ";
3720     qm+=name();
3721     qm+="]";
3722     return qm;
3723   }
3724   else
3725   {
3726     return Definition::qualifiedName();
3727   }  
3728 }
3729
3730 void MemberDef::setTagInfo(TagInfo *ti)
3731 {
3732   if (ti)
3733   {
3734     makeResident();
3735     //printf("%s: Setting tag name=%s anchor=%s\n",name().data(),ti->tagName.data(),ti->anchor.data());
3736     m_impl->anc=ti->anchor;
3737     setReference(ti->tagName);
3738     m_impl->explicitOutputFileBase = stripExtension(ti->fileName);
3739   }
3740 }
3741
3742 QCString MemberDef::objCMethodName(bool localLink,bool showStatic) const
3743 {
3744   makeResident();
3745   QCString qm;
3746   if (showStatic)
3747   {
3748     if (isStatic()) qm="+ "; else qm="- ";
3749   }
3750   qm+=name();
3751   if (!localLink) // link to method of same class
3752   {
3753     qm+=" (";
3754     qm+=m_impl->classDef->name();
3755     qm+=")";
3756   }
3757   return qm;
3758 }
3759
3760 const char *MemberDef::declaration() const
3761
3762   makeResident();
3763   return m_impl->decl; 
3764 }
3765
3766 const char *MemberDef::definition() const
3767
3768   makeResident();
3769   return m_impl->def;
3770 }
3771
3772 const char *MemberDef::extraTypeChars() const
3773 {
3774   makeResident();
3775   return m_impl->extraTypeChars;
3776 }
3777
3778 const char *MemberDef::typeString() const
3779
3780   makeResident();
3781   return m_impl->type; 
3782 }
3783
3784 const char *MemberDef::argsString() const
3785
3786   makeResident();
3787   return m_impl->args; 
3788 }
3789
3790 const char *MemberDef::excpString() const
3791
3792   makeResident();
3793   return m_impl->exception; 
3794 }
3795
3796 const char *MemberDef::bitfieldString() const
3797
3798   makeResident();
3799   return m_impl->bitfields; 
3800 }
3801
3802 const QCString &MemberDef::initializer() const
3803
3804   makeResident();
3805   return m_impl->initializer; 
3806 }
3807
3808 int MemberDef::initializerLines() const
3809
3810   makeResident();
3811   return m_impl->initLines; 
3812 }
3813
3814 int  MemberDef::getMemberSpecifiers() const
3815
3816   makeResident();
3817   return m_impl->memSpec; 
3818 }
3819
3820 ClassDef *MemberDef::getClassDef() const
3821
3822   makeResident();
3823   return m_impl->classDef; 
3824 }
3825
3826 FileDef  *MemberDef::getFileDef() const
3827
3828   makeResident();
3829   return m_impl->fileDef; 
3830 }
3831
3832 NamespaceDef* MemberDef::getNamespaceDef() const
3833
3834   makeResident();
3835   return m_impl->nspace; 
3836 }
3837
3838 const char *MemberDef::getReadAccessor() const
3839
3840   makeResident();
3841   return m_impl->read; 
3842 }
3843
3844 const char *MemberDef::getWriteAccessor() const
3845
3846   makeResident();
3847   return m_impl->write; 
3848 }
3849
3850 GroupDef *MemberDef::getGroupDef() const
3851
3852   makeResident();
3853   return m_impl->group; 
3854 }
3855
3856 Grouping::GroupPri_t MemberDef::getGroupPri() const
3857
3858   makeResident();
3859   return m_impl->grouppri; 
3860 }
3861
3862 const char *MemberDef::getGroupFileName() const
3863
3864   makeResident();
3865   return m_impl->groupFileName; 
3866 }
3867
3868 int MemberDef::getGroupStartLine() const
3869
3870   makeResident();
3871   return m_impl->groupStartLine; 
3872 }
3873
3874 bool MemberDef::getGroupHasDocs() const
3875
3876   makeResident();
3877   return m_impl->groupHasDocs; 
3878 }
3879
3880 Protection MemberDef::protection() const
3881
3882   makeResident();
3883   return m_impl->prot; 
3884 }
3885
3886 MemberDef::MemberType MemberDef::memberType() const
3887
3888   makeResident();
3889   return m_impl->mtype; 
3890 }
3891
3892 bool MemberDef::isSignal() const
3893
3894   makeResident();
3895   return m_impl->mtype==Signal;      
3896 }
3897
3898 bool MemberDef::isSlot() const
3899
3900   makeResident();
3901   return m_impl->mtype==Slot;        
3902 }
3903
3904 bool MemberDef::isVariable() const
3905
3906   makeResident();
3907   return m_impl->mtype==Variable;    
3908 }
3909
3910 bool MemberDef::isEnumerate() const
3911
3912   makeResident();
3913   return m_impl->mtype==Enumeration; 
3914 }
3915
3916 bool MemberDef::isEnumValue() const
3917
3918   makeResident();
3919   return m_impl->mtype==EnumValue;   
3920 }
3921
3922 bool MemberDef::isTypedef() const
3923
3924   makeResident();
3925   return m_impl->mtype==Typedef;     
3926 }
3927
3928 bool MemberDef::isFunction() const
3929
3930   makeResident();
3931   return m_impl->mtype==Function;    
3932 }
3933
3934 bool MemberDef::isFunctionPtr() const
3935 {
3936   makeResident();
3937   return m_impl->mtype==Variable && QCString(argsString()).find(")(")!=-1;
3938 }
3939
3940 bool MemberDef::isDefine() const
3941
3942   makeResident();
3943   return m_impl->mtype==Define;      
3944 }
3945
3946 bool MemberDef::isFriend() const
3947
3948   makeResident();
3949   return m_impl->mtype==Friend;      
3950 }
3951
3952 bool MemberDef::isDCOP() const
3953
3954   makeResident();
3955   return m_impl->mtype==DCOP;        
3956 }
3957
3958 bool MemberDef::isProperty() const
3959
3960   makeResident();
3961   return m_impl->mtype==Property;    
3962 }
3963
3964 bool MemberDef::isEvent() const
3965
3966   makeResident();
3967   return m_impl->mtype==Event;       
3968 }
3969
3970 bool MemberDef::isRelated() const
3971
3972   makeResident();
3973   return m_impl->related == Related;
3974 }
3975
3976 bool MemberDef::isForeign() const
3977
3978   makeResident();
3979   return m_impl->related == Foreign; 
3980 }
3981
3982 bool MemberDef::isStatic() const
3983
3984   makeResident();
3985   return m_impl->stat; 
3986 }
3987
3988 bool MemberDef::isInline() const
3989
3990   makeResident();
3991   return (m_impl->memSpec&Entry::Inline)!=0; 
3992 }
3993
3994 bool MemberDef::isExplicit() const
3995
3996   makeResident();
3997   return (m_impl->memSpec&Entry::Explicit)!=0; 
3998 }
3999
4000 bool MemberDef::isMutable() const
4001
4002   makeResident();
4003   return (m_impl->memSpec&Entry::Mutable)!=0; 
4004 }
4005
4006 bool MemberDef::isGettable() const
4007
4008   makeResident();
4009   return (m_impl->memSpec&Entry::Gettable)!=0; 
4010 }
4011
4012 bool MemberDef::isSettable() const
4013
4014   makeResident();
4015   return (m_impl->memSpec&Entry::Settable)!=0; 
4016 }
4017
4018 bool MemberDef::isAddable() const
4019
4020   makeResident();
4021   return (m_impl->memSpec&Entry::Addable)!=0; 
4022 }
4023
4024 bool MemberDef::isRemovable() const
4025
4026   makeResident();
4027   return (m_impl->memSpec&Entry::Removable)!=0; 
4028 }
4029
4030 bool MemberDef::isRaisable() const
4031
4032   makeResident();
4033   return (m_impl->memSpec&Entry::Raisable)!=0; 
4034 }
4035
4036 bool MemberDef::isReadable() const
4037
4038   makeResident();
4039   return (m_impl->memSpec&Entry::Readable)!=0; 
4040 }
4041
4042 bool MemberDef::isWritable() const
4043
4044   makeResident();
4045   return (m_impl->memSpec&Entry::Writable)!=0; 
4046 }
4047
4048 bool MemberDef::isFinal() const
4049
4050   makeResident();
4051   return (m_impl->memSpec&Entry::Final)!=0; 
4052 }
4053
4054 bool MemberDef::isNew() const
4055
4056   makeResident();
4057   return (m_impl->memSpec&Entry::New)!=0; 
4058 }
4059
4060 bool MemberDef::isSealed() const
4061
4062   makeResident();
4063   return (m_impl->memSpec&Entry::Sealed)!=0; 
4064 }
4065
4066 bool MemberDef::isOverride() const
4067
4068   makeResident();
4069   return (m_impl->memSpec&Entry::Override)!=0; 
4070 }
4071
4072 bool MemberDef::isInitonly() const
4073
4074   makeResident();
4075   return (m_impl->memSpec&Entry::Initonly)!=0; 
4076 }
4077
4078 bool MemberDef::isAbstract() const
4079
4080   makeResident();
4081   return (m_impl->memSpec&Entry::Abstract)!=0; 
4082 }
4083
4084 bool MemberDef::isOptional() const
4085
4086   makeResident();
4087   return (m_impl->memSpec&Entry::Optional)!=0; 
4088 }
4089
4090 bool MemberDef::isRequired() const
4091
4092   makeResident();
4093   return (m_impl->memSpec&Entry::Required)!=0; 
4094 }
4095
4096 bool MemberDef::isNonAtomic() const
4097
4098   makeResident();
4099   return (m_impl->memSpec&Entry::NonAtomic)!=0; 
4100 }
4101
4102 bool MemberDef::isCopy() const
4103
4104   makeResident();
4105   return (m_impl->memSpec&Entry::Copy)!=0; 
4106 }
4107
4108 bool MemberDef::isAssign() const
4109
4110   makeResident();
4111   return (m_impl->memSpec&Entry::Assign)!=0; 
4112 }
4113
4114 bool MemberDef::isRetain() const
4115
4116   makeResident();
4117   return (m_impl->memSpec&Entry::Retain)!=0; 
4118 }
4119
4120 bool MemberDef::isWeak() const
4121 {
4122   makeResident();
4123   return (m_impl->memSpec&Entry::Weak)!=0; 
4124 }
4125
4126 bool MemberDef::isStrong() const
4127 {
4128   makeResident();
4129   return (m_impl->memSpec&Entry::Strong)!=0; 
4130 }
4131
4132 bool MemberDef::isUnretained() const
4133 {
4134   makeResident();
4135   return (m_impl->memSpec&Entry::Unretained)!=0; 
4136 }
4137
4138 bool MemberDef::isAlias() const
4139 {
4140   makeResident();
4141   return (m_impl->memSpec&Entry::Alias)!=0;
4142 }
4143
4144 bool MemberDef::isDefault() const
4145 {
4146   makeResident();
4147   return (m_impl->memSpec&Entry::Default)!=0;
4148 }
4149
4150 bool MemberDef::isDelete() const
4151 {
4152   makeResident();
4153   return (m_impl->memSpec&Entry::Delete)!=0;
4154 }
4155
4156 bool MemberDef::isNoExcept() const
4157 {
4158   makeResident();
4159   return (m_impl->memSpec&Entry::NoExcept)!=0;
4160 }
4161
4162
4163
4164 bool MemberDef::isImplementation() const
4165
4166   makeResident();
4167   return m_impl->implOnly; 
4168 }
4169
4170 bool MemberDef::isExternal() const
4171
4172   makeResident();
4173   return m_impl->explExt; 
4174 }
4175
4176 bool MemberDef::isTemplateSpecialization() const
4177
4178   makeResident();
4179   return m_impl->tspec; 
4180 }
4181
4182 bool MemberDef::hasDocumentedParams() const
4183
4184   makeResident();
4185   return m_impl->hasDocumentedParams; 
4186 }
4187
4188 bool MemberDef::hasDocumentedReturnType() const
4189
4190   makeResident();
4191   return m_impl->hasDocumentedReturnType; 
4192 }
4193
4194 ClassDef *MemberDef::relatedAlso() const
4195
4196   makeResident();
4197   return m_impl->relatedAlso; 
4198 }
4199
4200 bool MemberDef::hasDocumentedEnumValues() const
4201
4202   makeResident();
4203   return m_impl->docEnumValues; 
4204 }
4205
4206 MemberDef *MemberDef::getAnonymousEnumType() const
4207
4208   makeResident();
4209   return m_impl->annEnumType; 
4210 }
4211
4212 bool MemberDef::isDocsForDefinition() const
4213
4214   makeResident();
4215   return m_impl->docsForDefinition; 
4216 }
4217
4218 MemberDef *MemberDef::getEnumScope() const
4219
4220   makeResident();
4221   return m_impl->enumScope; 
4222 }
4223
4224 LockingPtr<MemberList> MemberDef::enumFieldList() const
4225
4226   makeResident();
4227   return LockingPtr<MemberList>(this,m_impl->enumFields); 
4228 }
4229
4230 LockingPtr<ExampleSDict> MemberDef::getExamples() const
4231
4232   makeResident();
4233   return LockingPtr<ExampleSDict>(this,m_impl->exampleSDict); 
4234 }
4235
4236 bool MemberDef::isPrototype() const
4237
4238   makeResident();
4239   return m_impl->proto; 
4240 }
4241
4242 LockingPtr<ArgumentList> MemberDef::argumentList() const
4243
4244   makeResident();
4245   return LockingPtr<ArgumentList>(this,m_impl->defArgList); 
4246 }
4247
4248 LockingPtr<ArgumentList> MemberDef::declArgumentList() const
4249
4250   makeResident();
4251   return LockingPtr<ArgumentList>(this,m_impl->declArgList); 
4252 }
4253
4254 LockingPtr<ArgumentList> MemberDef::templateArguments() const
4255
4256   makeResident();
4257   return LockingPtr<ArgumentList>(this,m_impl->tArgList); 
4258 }
4259
4260 LockingPtr< QList<ArgumentList> > MemberDef::definitionTemplateParameterLists() const
4261
4262   makeResident();
4263   return LockingPtr< QList<ArgumentList> >(this,m_impl->defTmpArgLists); 
4264 }
4265
4266 int MemberDef::getMemberGroupId() const
4267
4268   makeResident();
4269   return m_impl->grpId; 
4270 }
4271
4272 MemberGroup *MemberDef::getMemberGroup() const
4273
4274   makeResident();
4275   return m_impl->memberGroup; 
4276 }
4277
4278 bool MemberDef::fromAnonymousScope() const
4279
4280   makeResident();
4281   return m_impl->annScope; 
4282 }
4283
4284 bool MemberDef::anonymousDeclShown() const
4285
4286   makeResident();
4287   return m_impl->annUsed; 
4288 }
4289
4290 void MemberDef::setAnonymousUsed() 
4291 {
4292   makeResident();
4293   m_impl->annUsed = TRUE;
4294 }
4295
4296 bool MemberDef::hasCallGraph() const
4297
4298   makeResident();
4299   return m_impl->hasCallGraph; 
4300 }
4301
4302 bool MemberDef::hasCallerGraph() const
4303
4304   makeResident();
4305   return m_impl->hasCallerGraph; 
4306 }
4307
4308 MemberDef *MemberDef::templateMaster() const
4309
4310   makeResident();
4311   return m_impl->templateMaster; 
4312 }
4313
4314 bool MemberDef::isTypedefValCached() const
4315
4316   makeResident();
4317   return m_impl->isTypedefValCached; 
4318 }
4319
4320 ClassDef *MemberDef::getCachedTypedefVal() const
4321
4322   makeResident();
4323   return m_impl->cachedTypedefValue; 
4324 }
4325
4326 QCString MemberDef::getCachedTypedefTemplSpec() const
4327
4328   makeResident();
4329   return m_impl->cachedTypedefTemplSpec; 
4330 }
4331
4332 QCString MemberDef::getCachedResolvedTypedef() const
4333
4334   makeResident();
4335   //printf("MemberDef::getCachedResolvedTypedef()=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl);
4336   return m_impl->cachedResolvedType; 
4337 }
4338
4339 MemberDef *MemberDef::memberDefinition() const
4340
4341   makeResident();
4342   return m_impl->memDef; 
4343 }
4344
4345 MemberDef *MemberDef::memberDeclaration() const
4346
4347   makeResident();
4348   return m_impl->memDec; 
4349 }
4350
4351 MemberDef *MemberDef::inheritsDocsFrom() const
4352
4353   makeResident();
4354   return m_impl->docProvider; 
4355 }
4356
4357 MemberDef *MemberDef::getGroupAlias() const
4358
4359   makeResident();
4360   return m_impl->groupAlias; 
4361 }
4362
4363 void MemberDef::setMemberType(MemberType t)
4364
4365   makeResident();
4366   m_impl->mtype=t; 
4367   m_isLinkableCached = 0;
4368 }
4369
4370 void MemberDef::setDefinition(const char *d)
4371
4372   makeResident();
4373   m_impl->def=d; 
4374 }
4375
4376 void MemberDef::setFileDef(FileDef *fd)
4377
4378   makeResident();
4379   m_impl->fileDef=fd; 
4380   m_isLinkableCached = 0;
4381   m_isConstructorCached = 0;
4382   m_isDestructorCached = 0;
4383 }
4384
4385 void MemberDef::setProtection(Protection p)
4386
4387   makeResident();
4388   m_impl->prot=p; 
4389   m_isLinkableCached = 0;
4390 }
4391
4392 void MemberDef::setMemberSpecifiers(int s)
4393
4394   makeResident();
4395   m_impl->memSpec=s; 
4396 }
4397
4398 void MemberDef::mergeMemberSpecifiers(int s)
4399
4400   makeResident();
4401   m_impl->memSpec|=s; 
4402 }
4403
4404 void MemberDef::setBitfields(const char *s)
4405
4406   makeResident();
4407   m_impl->bitfields = s; 
4408 }
4409
4410 void MemberDef::setMaxInitLines(int lines)
4411
4412   if (lines!=-1)
4413   {
4414     makeResident();
4415     m_impl->userInitLines=lines; 
4416   }
4417 }
4418
4419 void MemberDef::setExplicitExternal(bool b)
4420
4421   makeResident();
4422   m_impl->explExt=b; 
4423 }
4424
4425 void MemberDef::setReadAccessor(const char *r)
4426
4427   makeResident();
4428   m_impl->read=r; 
4429 }
4430
4431 void MemberDef::setWriteAccessor(const char *w)
4432
4433   makeResident();
4434   m_impl->write=w; 
4435 }
4436
4437 void MemberDef::setTemplateSpecialization(bool b)
4438
4439   makeResident();
4440   m_impl->tspec=b; 
4441 }
4442
4443 void MemberDef::makeRelated()
4444
4445   makeResident();
4446   m_impl->related = Related; 
4447   m_isLinkableCached = 0;
4448 }
4449
4450 void MemberDef::makeForeign()
4451
4452   makeResident();
4453   m_impl->related = Foreign; 
4454   m_isLinkableCached = 0;
4455 }
4456
4457 void MemberDef::setHasDocumentedParams(bool b)
4458
4459   makeResident();
4460   m_impl->hasDocumentedParams = b; 
4461 }
4462
4463 void MemberDef::setHasDocumentedReturnType(bool b)
4464
4465   makeResident();
4466   m_impl->hasDocumentedReturnType = b; 
4467 }
4468
4469 void MemberDef::setInheritsDocsFrom(MemberDef *md)
4470
4471   makeResident();
4472   m_impl->docProvider = md; 
4473 }
4474
4475 void MemberDef::setArgsString(const char *as)
4476
4477   makeResident();
4478   m_impl->args = as; 
4479 }
4480
4481 void MemberDef::setRelatedAlso(ClassDef *cd)
4482
4483   makeResident();
4484   m_impl->relatedAlso=cd; 
4485 }
4486
4487 void MemberDef::setEnumClassScope(ClassDef *cd)
4488
4489   makeResident();
4490   m_impl->classDef = cd; 
4491   m_isLinkableCached = 0; 
4492   m_isConstructorCached = 0; 
4493 }
4494
4495 void MemberDef::setDocumentedEnumValues(bool value)
4496
4497   makeResident();
4498   m_impl->docEnumValues=value; 
4499 }
4500
4501 void MemberDef::setAnonymousEnumType(MemberDef *md)
4502
4503   makeResident();
4504   m_impl->annEnumType = md; 
4505 }
4506
4507 void MemberDef::setPrototype(bool p)
4508
4509   makeResident();
4510   m_impl->proto=p; 
4511 }
4512
4513 void MemberDef::setMemberGroupId(int id)
4514
4515   makeResident();
4516   m_impl->grpId=id; 
4517 }
4518
4519 void MemberDef::makeImplementationDetail()
4520
4521   makeResident();
4522   m_impl->implOnly=TRUE; 
4523 }
4524
4525 void MemberDef::setFromAnonymousScope(bool b)
4526
4527   makeResident();
4528   m_impl->annScope=b; 
4529 }
4530
4531 void MemberDef::setFromAnonymousMember(MemberDef *m)
4532
4533   makeResident();
4534   m_impl->annMemb=m; 
4535 }
4536
4537 void MemberDef::setTemplateMaster(MemberDef *mt)
4538
4539   makeResident();
4540   m_impl->templateMaster=mt; 
4541   m_isLinkableCached = 0; 
4542 }
4543
4544 void MemberDef::setDocsForDefinition(bool b)
4545
4546   makeResident();
4547   m_impl->docsForDefinition = b; 
4548 }
4549
4550 void MemberDef::setGroupAlias(MemberDef *md)
4551
4552   makeResident();
4553   m_impl->groupAlias = md; 
4554 }
4555
4556 void MemberDef::invalidateTypedefValCache()
4557
4558   makeResident();
4559   m_impl->isTypedefValCached=FALSE; 
4560 }
4561
4562 void MemberDef::setMemberDefinition(MemberDef *md)
4563
4564   makeResident();
4565   m_impl->memDef=md; 
4566 }
4567
4568 void MemberDef::setMemberDeclaration(MemberDef *md)
4569
4570   makeResident();
4571   m_impl->memDec=md; 
4572 }
4573
4574 ClassDef *MemberDef::category() const
4575 {
4576   makeResident();
4577   return m_impl->category;
4578 }
4579
4580 void MemberDef::setCategory(ClassDef *def)
4581 {
4582   makeResident();
4583   m_impl->category = def;
4584 }
4585
4586 MemberDef *MemberDef::categoryRelation() const
4587 {
4588   makeResident();
4589   return m_impl->categoryRelation;
4590 }
4591
4592 void MemberDef::setCategoryRelation(MemberDef *md)
4593 {
4594   makeResident();
4595   m_impl->categoryRelation = md;
4596 }
4597
4598 void MemberDef::setEnumBaseType(const QCString &type)
4599 {
4600   makeResident();
4601   m_impl->enumBaseType = type;
4602 }
4603
4604 QCString MemberDef::enumBaseType() const
4605 {
4606   makeResident();
4607   return m_impl->enumBaseType;
4608 }
4609
4610
4611 void MemberDef::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType)
4612 {
4613   makeResident();
4614   m_impl->isTypedefValCached=TRUE; 
4615   m_impl->cachedTypedefValue=val; 
4616   m_impl->cachedTypedefTemplSpec=templSpec; 
4617   m_impl->cachedResolvedType=resolvedType;
4618   //printf("MemberDef::cacheTypedefVal=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl);
4619 }
4620
4621 void MemberDef::copyArgumentNames(MemberDef *bmd)
4622 {
4623   makeResident();
4624   {
4625     LockingPtr<ArgumentList> arguments = bmd->argumentList();
4626     if (m_impl->defArgList && arguments!=0)
4627     {
4628       ArgumentListIterator aliDst(*m_impl->defArgList);
4629       ArgumentListIterator aliSrc(*arguments);
4630       Argument *argDst, *argSrc;
4631       for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
4632       {
4633         argDst->name = argSrc->name;
4634       }
4635     }
4636   }
4637   {
4638     LockingPtr<ArgumentList> arguments = bmd->declArgumentList();
4639     if (m_impl->declArgList && arguments!=0)
4640     {
4641       ArgumentListIterator aliDst(*m_impl->declArgList);
4642       ArgumentListIterator aliSrc(*arguments);
4643       Argument *argDst, *argSrc;
4644       for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
4645       {
4646         argDst->name = argSrc->name;
4647       }
4648     }
4649   }
4650 }
4651
4652 static void invalidateCachedTypesInArgumentList(ArgumentList *al)
4653 {
4654   if (al)
4655   {
4656     ArgumentListIterator ali(*al);
4657     Argument *a;
4658     for (ali.toFirst();(a=ali.current());++ali)
4659     {
4660       a->canType.resize(0);
4661     }
4662   }
4663 }
4664
4665 void MemberDef::invalidateCachedArgumentTypes()
4666 {
4667   makeResident();
4668   invalidateCachedTypesInArgumentList(m_impl->defArgList);
4669   invalidateCachedTypesInArgumentList(m_impl->declArgList);
4670 }
4671
4672
4673 //-----------------------------------------------------------------
4674
4675 void MemberDef::flushToDisk() const
4676 {
4677   if (isLocked()) return;
4678   MemberDef *that = (MemberDef*)this;
4679   that->m_storagePos = Doxygen::symbolStorage->alloc();
4680   //printf("%p: MemberDef::flushToDisk() m_impl=%p\n",this,m_impl);
4681   // write the definition base class member variables to disk
4682   Definition::flushToDisk();
4683
4684   //printf("%p:   flushing specific part\n",this);
4685
4686   // write the memberdef member variables to disk
4687   marshalUInt(Doxygen::symbolStorage,START_MARKER);
4688   marshalObjPointer   (Doxygen::symbolStorage,m_impl->classDef);
4689   marshalObjPointer   (Doxygen::symbolStorage,m_impl->fileDef);
4690   marshalObjPointer   (Doxygen::symbolStorage,m_impl->nspace);
4691   marshalObjPointer   (Doxygen::symbolStorage,m_impl->enumScope);
4692   marshalObjPointer   (Doxygen::symbolStorage,m_impl->annEnumType);
4693   marshalMemberList   (Doxygen::symbolStorage,m_impl->enumFields);
4694   marshalObjPointer   (Doxygen::symbolStorage,m_impl->redefines);
4695   marshalMemberList   (Doxygen::symbolStorage,m_impl->redefinedBy);
4696   marshalObjPointer   (Doxygen::symbolStorage,m_impl->memDef);
4697   marshalObjPointer   (Doxygen::symbolStorage,m_impl->memDec);
4698   marshalObjPointer   (Doxygen::symbolStorage,m_impl->relatedAlso);
4699   marshalExampleSDict (Doxygen::symbolStorage,m_impl->exampleSDict);
4700   marshalQCString     (Doxygen::symbolStorage,m_impl->type);
4701   marshalQCString     (Doxygen::symbolStorage,m_impl->enumBaseType);
4702   marshalQCString     (Doxygen::symbolStorage,m_impl->accessorType);
4703   marshalObjPointer   (Doxygen::symbolStorage,m_impl->accessorClass);
4704   marshalQCString     (Doxygen::symbolStorage,m_impl->args);
4705   marshalQCString     (Doxygen::symbolStorage,m_impl->def);
4706   marshalQCString     (Doxygen::symbolStorage,m_impl->anc);
4707   marshalInt          (Doxygen::symbolStorage,(int)m_impl->virt);
4708   marshalInt          (Doxygen::symbolStorage,(int)m_impl->prot);
4709   marshalQCString     (Doxygen::symbolStorage,m_impl->decl);
4710   marshalQCString     (Doxygen::symbolStorage,m_impl->bitfields);
4711   marshalQCString     (Doxygen::symbolStorage,m_impl->read);
4712   marshalQCString     (Doxygen::symbolStorage,m_impl->write);
4713   marshalQCString     (Doxygen::symbolStorage,m_impl->exception);
4714   marshalQCString     (Doxygen::symbolStorage,m_impl->initializer);
4715   marshalQCString     (Doxygen::symbolStorage,m_impl->extraTypeChars);
4716   marshalInt          (Doxygen::symbolStorage,m_impl->initLines);
4717   marshalInt          (Doxygen::symbolStorage,m_impl->memSpec);
4718   marshalInt          (Doxygen::symbolStorage,(int)m_impl->mtype);
4719   marshalInt          (Doxygen::symbolStorage,m_impl->maxInitLines);
4720   marshalInt          (Doxygen::symbolStorage,m_impl->userInitLines);
4721   marshalObjPointer   (Doxygen::symbolStorage,m_impl->annMemb);
4722   marshalArgumentList (Doxygen::symbolStorage,m_impl->defArgList);
4723   marshalArgumentList (Doxygen::symbolStorage,m_impl->declArgList);
4724   marshalArgumentList (Doxygen::symbolStorage,m_impl->tArgList);
4725   marshalArgumentList (Doxygen::symbolStorage,m_impl->typeConstraints);
4726   marshalObjPointer   (Doxygen::symbolStorage,m_impl->templateMaster);
4727   marshalArgumentLists(Doxygen::symbolStorage,m_impl->defTmpArgLists);
4728   marshalObjPointer   (Doxygen::symbolStorage,m_impl->cachedAnonymousType);
4729   marshalMemberLists  (Doxygen::symbolStorage,m_impl->classSectionSDict);
4730   marshalObjPointer   (Doxygen::symbolStorage,m_impl->groupAlias);
4731   marshalInt          (Doxygen::symbolStorage,m_impl->grpId);
4732   marshalObjPointer   (Doxygen::symbolStorage,m_impl->memberGroup);
4733   marshalObjPointer   (Doxygen::symbolStorage,m_impl->group);
4734   marshalInt          (Doxygen::symbolStorage,(int)m_impl->grouppri);
4735   marshalQCString     (Doxygen::symbolStorage,m_impl->groupFileName);
4736   marshalInt          (Doxygen::symbolStorage,m_impl->groupStartLine);
4737   marshalObjPointer   (Doxygen::symbolStorage,m_impl->groupMember);
4738   marshalBool         (Doxygen::symbolStorage,m_impl->isTypedefValCached);
4739   marshalObjPointer   (Doxygen::symbolStorage,m_impl->cachedTypedefValue);
4740   marshalQCString     (Doxygen::symbolStorage,m_impl->cachedTypedefTemplSpec);
4741   marshalQCString     (Doxygen::symbolStorage,m_impl->cachedResolvedType);
4742   marshalObjPointer   (Doxygen::symbolStorage,m_impl->docProvider);
4743   marshalQCString     (Doxygen::symbolStorage,m_impl->explicitOutputFileBase);
4744   marshalBool         (Doxygen::symbolStorage,m_impl->implOnly); 
4745   marshalBool         (Doxygen::symbolStorage,m_impl->hasDocumentedParams);
4746   marshalBool         (Doxygen::symbolStorage,m_impl->hasDocumentedReturnType);
4747   marshalBool         (Doxygen::symbolStorage,m_impl->isDMember);
4748   marshalInt          (Doxygen::symbolStorage,(int)m_impl->related);
4749   marshalBool         (Doxygen::symbolStorage,m_impl->stat);
4750   marshalBool         (Doxygen::symbolStorage,m_impl->proto);
4751   marshalBool         (Doxygen::symbolStorage,m_impl->docEnumValues);
4752   marshalBool         (Doxygen::symbolStorage,m_impl->annScope);
4753   marshalBool         (Doxygen::symbolStorage,m_impl->annUsed);
4754   marshalBool         (Doxygen::symbolStorage,m_impl->hasCallGraph);
4755   marshalBool         (Doxygen::symbolStorage,m_impl->hasCallerGraph);
4756   marshalBool         (Doxygen::symbolStorage,m_impl->explExt);
4757   marshalBool         (Doxygen::symbolStorage,m_impl->tspec);
4758   marshalBool         (Doxygen::symbolStorage,m_impl->groupHasDocs);
4759   marshalBool         (Doxygen::symbolStorage,m_impl->docsForDefinition);
4760   marshalObjPointer   (Doxygen::symbolStorage,m_impl->category);
4761   marshalObjPointer   (Doxygen::symbolStorage,m_impl->categoryRelation);
4762   marshalUInt(Doxygen::symbolStorage,END_MARKER);
4763
4764   // function doesn't modify the object conceptually but compiler doesn't know this.
4765   delete that->m_impl;
4766   that->m_impl=0;
4767   that->m_flushPending=FALSE;
4768 }
4769
4770 void MemberDef::loadFromDisk() const
4771 {
4772   MemberDef *that = (MemberDef *)this;
4773   if (isLocked()) 
4774   {
4775     //printf("%p: loadFromDisk() locked: so still in memory\n",this);
4776     assert(m_impl!=0);
4777     return;
4778   }
4779   assert(m_impl==0);
4780
4781   Doxygen::symbolStorage->seek(m_storagePos);
4782   Definition::loadFromDisk();
4783
4784   //printf("%p:   loading specific part\n",this);
4785
4786   that->m_impl = new MemberDefImpl;
4787   //printf("%p: MemberDef::loadFromDisk(): m_impl=%p\n",this,m_impl);
4788
4789   uint marker = unmarshalUInt(Doxygen::symbolStorage);
4790   assert(marker==START_MARKER);
4791   m_impl->classDef                = (ClassDef*)unmarshalObjPointer     (Doxygen::symbolStorage);
4792   m_impl->fileDef                 = (FileDef*)unmarshalObjPointer      (Doxygen::symbolStorage);
4793   m_impl->nspace                  = (NamespaceDef*)unmarshalObjPointer (Doxygen::symbolStorage);
4794   m_impl->enumScope               = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
4795   m_impl->annEnumType             = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
4796   m_impl->enumFields              = unmarshalMemberList                (Doxygen::symbolStorage);
4797   m_impl->redefines               = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
4798   m_impl->redefinedBy             = unmarshalMemberList                (Doxygen::symbolStorage);
4799   m_impl->memDef                  = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
4800   m_impl->memDec                  = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
4801   m_impl->relatedAlso             = (ClassDef*)unmarshalObjPointer     (Doxygen::symbolStorage);
4802   m_impl->exampleSDict            = unmarshalExampleSDict (Doxygen::symbolStorage);
4803   m_impl->type                    = unmarshalQCString     (Doxygen::symbolStorage);
4804   m_impl->enumBaseType            = unmarshalQCString     (Doxygen::symbolStorage);
4805   m_impl->accessorType            = unmarshalQCString     (Doxygen::symbolStorage);
4806   m_impl->accessorClass           = (ClassDef*)unmarshalObjPointer     (Doxygen::symbolStorage);
4807   m_impl->args                    = unmarshalQCString     (Doxygen::symbolStorage);
4808   m_impl->def                     = unmarshalQCString     (Doxygen::symbolStorage);
4809   m_impl->anc                     = unmarshalQCString     (Doxygen::symbolStorage);
4810   m_impl->virt                    = (Specifier)unmarshalInt (Doxygen::symbolStorage);
4811   m_impl->prot                    = (Protection)unmarshalInt(Doxygen::symbolStorage);
4812   m_impl->decl                    = unmarshalQCString     (Doxygen::symbolStorage);
4813   m_impl->bitfields               = unmarshalQCString     (Doxygen::symbolStorage);
4814   m_impl->read                    = unmarshalQCString     (Doxygen::symbolStorage);
4815   m_impl->write                   = unmarshalQCString     (Doxygen::symbolStorage);
4816   m_impl->exception               = unmarshalQCString     (Doxygen::symbolStorage);
4817   m_impl->initializer             = unmarshalQCString     (Doxygen::symbolStorage);
4818   m_impl->extraTypeChars          = unmarshalQCString     (Doxygen::symbolStorage);
4819   m_impl->initLines               = unmarshalInt          (Doxygen::symbolStorage);
4820   m_impl->memSpec                 = unmarshalInt          (Doxygen::symbolStorage);
4821   m_impl->mtype                   = (MemberDef::MemberType)unmarshalInt          (Doxygen::symbolStorage);
4822   m_impl->maxInitLines            = unmarshalInt          (Doxygen::symbolStorage);
4823   m_impl->userInitLines           = unmarshalInt          (Doxygen::symbolStorage);
4824   m_impl->annMemb                 = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4825   m_impl->defArgList              = unmarshalArgumentList (Doxygen::symbolStorage);
4826   m_impl->declArgList             = unmarshalArgumentList (Doxygen::symbolStorage);
4827   m_impl->tArgList                = unmarshalArgumentList (Doxygen::symbolStorage);
4828   m_impl->typeConstraints         = unmarshalArgumentList (Doxygen::symbolStorage);
4829   m_impl->templateMaster          = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4830   m_impl->defTmpArgLists          = unmarshalArgumentLists(Doxygen::symbolStorage);
4831   m_impl->cachedAnonymousType     = (ClassDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4832   m_impl->classSectionSDict       = unmarshalMemberLists  (Doxygen::symbolStorage);
4833   m_impl->groupAlias              = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4834   m_impl->grpId                   = unmarshalInt          (Doxygen::symbolStorage);
4835   m_impl->memberGroup             = (MemberGroup*)unmarshalObjPointer   (Doxygen::symbolStorage);
4836   m_impl->group                   = (GroupDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4837   m_impl->grouppri                = (Grouping::GroupPri_t)unmarshalInt          (Doxygen::symbolStorage);
4838   m_impl->groupFileName           = unmarshalQCString     (Doxygen::symbolStorage);
4839   m_impl->groupStartLine          = unmarshalInt          (Doxygen::symbolStorage);
4840   m_impl->groupMember             = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4841   m_impl->isTypedefValCached      = unmarshalBool         (Doxygen::symbolStorage);
4842   m_impl->cachedTypedefValue      = (ClassDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4843   m_impl->cachedTypedefTemplSpec  = unmarshalQCString     (Doxygen::symbolStorage);
4844   m_impl->cachedResolvedType      = unmarshalQCString     (Doxygen::symbolStorage);
4845   m_impl->docProvider             = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4846   m_impl->explicitOutputFileBase  = unmarshalQCString     (Doxygen::symbolStorage);
4847   m_impl->implOnly                = unmarshalBool         (Doxygen::symbolStorage); 
4848   m_impl->hasDocumentedParams     = unmarshalBool         (Doxygen::symbolStorage);
4849   m_impl->hasDocumentedReturnType = unmarshalBool         (Doxygen::symbolStorage);
4850   m_impl->isDMember               = unmarshalBool         (Doxygen::symbolStorage);
4851   m_impl->related                 = (Relationship)unmarshalInt(Doxygen::symbolStorage);
4852   m_impl->stat                    = unmarshalBool         (Doxygen::symbolStorage);
4853   m_impl->proto                   = unmarshalBool         (Doxygen::symbolStorage);
4854   m_impl->docEnumValues           = unmarshalBool         (Doxygen::symbolStorage);
4855   m_impl->annScope                = unmarshalBool         (Doxygen::symbolStorage);
4856   m_impl->annUsed                 = unmarshalBool         (Doxygen::symbolStorage);
4857   m_impl->hasCallGraph            = unmarshalBool         (Doxygen::symbolStorage);
4858   m_impl->hasCallerGraph          = unmarshalBool         (Doxygen::symbolStorage);
4859   m_impl->explExt                 = unmarshalBool         (Doxygen::symbolStorage);
4860   m_impl->tspec                   = unmarshalBool         (Doxygen::symbolStorage);
4861   m_impl->groupHasDocs            = unmarshalBool         (Doxygen::symbolStorage);
4862   m_impl->docsForDefinition       = unmarshalBool         (Doxygen::symbolStorage);
4863   m_impl->category                = (ClassDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
4864   m_impl->categoryRelation        = (MemberDef*)unmarshalObjPointer  (Doxygen::symbolStorage);
4865   marker = unmarshalUInt(Doxygen::symbolStorage);
4866   assert(marker==END_MARKER);
4867
4868   //printf("%p: MemberDef::loadFromDisk(): sorting\n",this);
4869 }
4870
4871 void MemberDef::makeResident() const
4872
4873   if (Doxygen::symbolCache==0) return;
4874   if (m_cacheHandle==-1) // not yet in cache
4875   { 
4876     MemberDef *victim = 0;
4877     MemberDef *that = (MemberDef*)this; // fake method constness
4878     that->m_cacheHandle = Doxygen::symbolCache->add(that,(void **)&victim);
4879     //printf("adding %s to cache, handle=%d\n",m_impl->name.data(),that->m_cacheHandle);
4880     if (victim)  // cache was full, victim was the least recently used item and has to go
4881     {
4882       //printf("%p: makeResident(): cache full %p::saveToDisk(): m_impl=%p\n",this,victim,victim->m_impl);
4883       victim->m_cacheHandle=-1; // invalidate cache handle
4884       victim->saveToDisk();     // store the item on disk
4885     }
4886     else // cache not yet full
4887     {
4888       //printf("Adding %s to cache, handle=%d\n",m_impl->name.data(),m_cacheHandle);
4889     }
4890     if (m_storagePos!=-1) // already been written to disk
4891     {
4892       if (isLocked()) // locked in memory
4893       {
4894         assert(m_impl!=0);
4895         that->m_flushPending=FALSE; // no need to flush anymore
4896       }
4897       else // not locked in memory
4898       {
4899         assert(m_impl==0);
4900         loadFromDisk();
4901       }
4902     }
4903   }
4904   else // already cached, make this object the most recently used.
4905   {
4906     assert(m_impl!=0);
4907     //printf("Touching symbol %s\n",m_impl->name.data());
4908     Doxygen::symbolCache->use(m_cacheHandle);
4909   }
4910 }
4911
4912 void MemberDef::saveToDisk() const
4913 {
4914   assert(m_impl!=0);
4915   MemberDef *that = (MemberDef *)this;
4916   //printf("%p: saveToDisk(): m_impl=%p\n",this,m_impl);
4917   if (isLocked()) // cannot flush the item as it is locked
4918   {
4919     that->m_flushPending=TRUE; // flush when unlocked
4920   }
4921   else // ready to flush the item to disk
4922   {
4923     //printf("Adding %s to cache, handle=%d by replacing %s\n",
4924     //    m_impl->name.data(),m_cacheHandle,victim->m_impl->name.data());
4925     if (m_storagePos!=-1) 
4926       // if victim was stored on disk already and is not locked
4927     {
4928       // free the storage space occupied by the old store item
4929       Doxygen::symbolStorage->release(m_storagePos); // free up space for others
4930     }
4931     // write a the new (possibly modified) instance to disk
4932     flushToDisk();
4933     // end to write sequence (unless nothing was written due to the lock)
4934     Doxygen::symbolStorage->end();
4935   }
4936 }
4937
4938 void MemberDef::lock() const
4939 {
4940 }
4941
4942 void MemberDef::unlock() const
4943 {
4944   if (m_flushPending && !isLocked())
4945   {
4946     //printf("%p: flush after unlock\n",this);
4947     // write a the new (possibly modified) instance to disk
4948     flushToDisk();
4949     // end to write sequence (unless nothing was written due to the lock)
4950     Doxygen::symbolStorage->end();
4951   }
4952 }
4953
4954 QCString MemberDef::displayName(bool) const 
4955
4956   return Definition::name(); 
4957 }
4958
4959 //----------------
4960
4961 static void transferArgumentDocumentation(ArgumentList *decAl,ArgumentList *defAl)
4962 {
4963   if (decAl && defAl)
4964   {
4965     ArgumentListIterator decAli(*decAl);
4966     ArgumentListIterator defAli(*defAl);
4967     Argument *decA,*defA;
4968     for (decAli.toFirst(),defAli.toFirst();
4969         (decA=decAli.current()) && (defA=defAli.current());
4970         ++decAli,++defAli)
4971     {
4972       //printf("Argument decA->name=%s (doc=%s) defA->name=%s (doc=%s)\n",
4973       //    decA->name.data(),decA->docs.data(),
4974       //    defA->name.data(),defA->docs.data()
4975       //      );
4976       if (decA->docs.isEmpty() && !defA->docs.isEmpty())
4977       {
4978         decA->docs = defA->docs.copy();
4979       }
4980       else if (defA->docs.isEmpty() && !decA->docs.isEmpty())
4981       {
4982         defA->docs = decA->docs.copy();
4983       }
4984     }
4985   }
4986 }
4987
4988 void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef)
4989 {
4990   //printf("mdec=%s isPrototype()=%d\n",mdec->name().data(),mdec->isPrototype());
4991   if (
4992       (mdef->isFunction() && !mdef->isStatic() && !mdef->isPrototype()) ||
4993       (mdef->isVariable() && !mdef->isExternal() && !mdef->isStatic())
4994      )
4995   {
4996     //printf("mdef=(%p,%s) mdec=(%p,%s)\n",
4997     //    mdef, mdef ? mdef->name().data() : "",
4998     //    mdec, mdec ? mdec->name().data() : "");
4999
5000     LockingPtr<ArgumentList> mdefAl = mdef->argumentList();
5001     LockingPtr<ArgumentList> mdecAl = mdec->argumentList();
5002     if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl.pointer(),
5003           mdec->getOuterScope(),mdec->getFileDef(),mdecAl.pointer(),
5004           TRUE
5005           )
5006        ) /* match found */
5007     {
5008       //printf("Found member %s: definition in %s (doc=`%s') and declaration in %s (doc=`%s')\n",
5009       //    mn->memberName(),
5010       //    mdef->getFileDef()->name().data(),mdef->documentation().data(),
5011       //    mdec->getFileDef()->name().data(),mdec->documentation().data()
5012       //    );
5013
5014       // first merge argument documentation
5015       transferArgumentDocumentation(mdecAl.pointer(),mdefAl.pointer());
5016
5017       /* copy documentation between function definition and declaration */
5018       if (!mdec->briefDescription().isEmpty())
5019       {
5020         mdef->setBriefDescription(mdec->briefDescription(),mdec->briefFile(),mdec->briefLine());
5021       }
5022       else if (!mdef->briefDescription().isEmpty())
5023       {
5024         mdec->setBriefDescription(mdef->briefDescription(),mdef->briefFile(),mdef->briefLine());
5025       }
5026       if (!mdef->documentation().isEmpty())
5027       {
5028         //printf("transfering docs mdef->mdec (%s->%s)\n",mdef->argsString(),mdec->argsString());
5029         mdec->setDocumentation(mdef->documentation(),mdef->docFile(),mdef->docLine());
5030         mdec->setDocsForDefinition(mdef->isDocsForDefinition());
5031         if (mdefAl!=0)
5032         {
5033           ArgumentList *mdefAlComb = new ArgumentList;
5034           stringToArgumentList(mdef->argsString(),mdefAlComb);
5035           transferArgumentDocumentation(mdefAl.pointer(),mdefAlComb);
5036           mdec->setArgumentList(mdefAlComb);
5037         }
5038       }
5039       else if (!mdec->documentation().isEmpty())
5040       {
5041         //printf("transfering docs mdec->mdef (%s->%s)\n",mdec->argsString(),mdef->argsString());
5042         mdef->setDocumentation(mdec->documentation(),mdec->docFile(),mdec->docLine());
5043         mdef->setDocsForDefinition(mdec->isDocsForDefinition());
5044         if (mdecAl!=0)
5045         {
5046           ArgumentList *mdecAlComb = new ArgumentList;
5047           stringToArgumentList(mdec->argsString(),mdecAlComb);
5048           transferArgumentDocumentation(mdecAl.pointer(),mdecAlComb);
5049           mdef->setDeclArgumentList(mdecAlComb);
5050         }
5051       }
5052       if (!mdef->inbodyDocumentation().isEmpty())
5053       {
5054         mdec->setInbodyDocumentation(mdef->inbodyDocumentation(),mdef->inbodyFile(),mdef->inbodyLine());
5055       }
5056       else if (!mdec->inbodyDocumentation().isEmpty())
5057       {
5058         mdef->setInbodyDocumentation(mdec->inbodyDocumentation(),mdec->inbodyFile(),mdec->inbodyLine());
5059       }
5060       if (mdec->getStartBodyLine()!=-1 && mdef->getStartBodyLine()==-1)
5061       {
5062         //printf("body mdec->mdef %d-%d\n",mdec->getStartBodyLine(),mdef->getEndBodyLine());
5063         mdef->setBodySegment(mdec->getStartBodyLine(),mdec->getEndBodyLine());
5064         mdef->setBodyDef(mdec->getBodyDef());
5065         //mdef->setBodyMember(mdec);
5066       }
5067       else if (mdef->getStartBodyLine()!=-1 && mdec->getStartBodyLine()==-1)
5068       {
5069         //printf("body mdef->mdec %d-%d\n",mdef->getStartBodyLine(),mdec->getEndBodyLine());
5070         mdec->setBodySegment(mdef->getStartBodyLine(),mdef->getEndBodyLine());
5071         mdec->setBodyDef(mdef->getBodyDef());
5072         //mdec->setBodyMember(mdef);
5073       }
5074       mdec->mergeMemberSpecifiers(mdef->getMemberSpecifiers());
5075       mdef->mergeMemberSpecifiers(mdec->getMemberSpecifiers());
5076
5077
5078       // copy group info.
5079       if (mdec->getGroupDef()==0 && mdef->getGroupDef()!=0)
5080       {
5081         mdec->setGroupDef(mdef->getGroupDef(),
5082             mdef->getGroupPri(),
5083             mdef->docFile(),
5084             mdef->docLine(),
5085             mdef->hasDocumentation(),
5086             mdef
5087             );
5088       }
5089       else if (mdef->getGroupDef()==0 && mdec->getGroupDef()!=0)
5090       {
5091         mdef->setGroupDef(mdec->getGroupDef(),
5092             mdec->getGroupPri(),
5093             mdec->docFile(),
5094             mdec->docLine(),
5095             mdec->hasDocumentation(),
5096             mdec
5097             );
5098       }
5099
5100
5101       mdec->mergeRefItems(mdef);
5102       mdef->mergeRefItems(mdec);
5103
5104       mdef->setMemberDeclaration(mdec);
5105       mdec->setMemberDefinition(mdef);
5106
5107       mdef->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
5108       mdef->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
5109       mdec->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
5110       mdec->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
5111     }
5112   }
5113 }
5114