00001 /****************************************************************************** 00002 * 00003 * 00004 * 00005 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00006 * 00007 * Permission to use, copy, modify, and distribute this software and its 00008 * documentation under the terms of the GNU General Public License is hereby 00009 * granted. No representations are made about the suitability of this software 00010 * for any purpose. It is provided "as is" without express or implied warranty. 00011 * See the GNU General Public License for more details. 00012 * 00013 * Documents produced by Doxygen are derivative works derived from the 00014 * input used in their production; they are not affected by this license. 00015 * 00016 */ 00017 00018 #include <stdio.h> 00019 #include <qregexp.h> 00020 #include <assert.h> 00021 #include <md5.h> 00022 #include "memberdef.h" 00023 #include "membername.h" 00024 #include "doxygen.h" 00025 #include "util.h" 00026 #include "code.h" 00027 #include "message.h" 00028 #include "htmlhelp.h" 00029 #include "language.h" 00030 #include "outputlist.h" 00031 #include "example.h" 00032 #include "membergroup.h" 00033 #include "groupdef.h" 00034 #include "defargs.h" 00035 #include "docparser.h" 00036 #include "dot.h" 00037 #include "searchindex.h" 00038 #include "parserintf.h" 00039 #include "marshal.h" 00040 #include "objcache.h" 00041 #include "vhdlscanner.h" 00042 #include "vhdldocgen.h" 00043 00044 #define START_MARKER 0x4D454D5B // MEM[ 00045 #define END_MARKER 0x4D454D5D // MEM] 00046 00047 //----------------------------------------------------------------------------- 00048 00049 int MemberDef::s_indentLevel = 0; 00050 00051 //----------------------------------------------------------------------------- 00052 00053 static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t) 00054 { 00055 QCString result; 00056 QCString clRealName=n; 00057 int p=0,i; 00058 if ((i=clRealName.find('<'))!=-1) 00059 { 00060 clRealName=clRealName.left(i); // strip template specialization 00061 } 00062 if ((i=clRealName.findRev("::"))!=-1) 00063 { 00064 clRealName=clRealName.right(clRealName.length()-i-2); 00065 } 00066 while ((i=s.find(clRealName,p))!=-1) 00067 { 00068 result+=s.mid(p,i-p); 00069 uint j=clRealName.length()+i; 00070 if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j)))) 00071 { // add template names 00072 //printf("Adding %s+%s\n",clRealName.data(),t.data()); 00073 result+=clRealName+t; 00074 } 00075 else 00076 { // template names already present 00077 //printf("Adding %s\n",clRealName.data()); 00078 result+=clRealName; 00079 } 00080 p=i+clRealName.length(); 00081 } 00082 result+=s.right(s.length()-p); 00083 //printf("addTemplateNames(%s,%s,%s)=%s\n",s.data(),n.data(),t.data(),result.data()); 00084 return result; 00085 } 00086 00087 static bool writeDefArgumentList(OutputList &ol,ClassDef *cd, 00088 const QCString & /*scopeName*/,MemberDef *md) 00089 { 00090 LockingPtr<ArgumentList> defArgList=(md->isDocsForDefinition()) ? 00091 md->argumentList() : md->declArgumentList(); 00092 //printf("writeDefArgumentList `%s' isDocsForDefinition()=%d\n",md->name().data(),md->isDocsForDefinition()); 00093 if (defArgList==0 || md->isProperty()) 00094 { 00095 return FALSE; // member has no function like argument list 00096 } 00097 if (!md->isDefine()) ol.docify(" "); 00098 00099 //printf("writeDefArgList(%d)\n",defArgList->count()); 00100 ol.pushGeneratorState(); 00101 ol.disableAllBut(OutputGenerator::Html); 00102 { 00103 // html 00104 ol.endMemberDocName(); 00105 ol.startParameterList(!md->isObjCMethod()); 00106 } 00107 ol.enableAll(); 00108 ol.disable(OutputGenerator::Html); 00109 { 00110 // other formats 00111 if (!md->isObjCMethod()) ol.docify("("); // start argument list 00112 ol.endMemberDocName(); 00113 } 00114 ol.popGeneratorState(); 00115 //printf("===> name=%s isDefine=%d\n",md->name().data(),md->isDefine()); 00116 00117 Argument *a=defArgList->first(); 00118 QCString cName; 00119 if (cd) 00120 { 00121 cName=cd->name(); 00122 int il=cName.find('<'); 00123 int ir=cName.findRev('>'); 00124 if (il!=-1 && ir!=-1 && ir>il) 00125 { 00126 cName=cName.mid(il,ir-il+1); 00127 //printf("1. cName=%s\n",cName.data()); 00128 } 00129 else if (cd->templateArguments()) 00130 { 00131 cName=tempArgListToString(cd->templateArguments()); 00132 //printf("2. cName=%s\n",cName.data()); 00133 } 00134 else // no template specifier 00135 { 00136 cName.resize(0); 00137 } 00138 } 00139 //printf("~~~ %s cName=%s\n",md->name().data(),cName.data()); 00140 00141 //if (!md->isDefine()) ol.startParameter(TRUE); else ol.docify(" "); 00142 bool first=TRUE; 00143 while (a) 00144 { 00145 if (md->isDefine() || first) ol.startParameterType(first,md->isObjCMethod()?"dummy":0); 00146 QRegExp re(")("),res("(.*\\*"); 00147 int vp=a->type.find(re); 00148 int wp=a->type.find(res); 00149 00150 // use the following to put the function pointer type before the name 00151 bool hasFuncPtrType=FALSE; 00152 00153 // or use the following to put the function pointer as it appears in 00154 // the prototype. 00155 //bool hasFuncPtrType=vp!=-1 && wp!=-1 && wp<vp; 00156 00157 if (!a->attrib.isEmpty() && !md->isObjCMethod()) // argument has an IDL attribute 00158 { 00159 ol.docify(a->attrib+" "); 00160 } 00161 if (hasFuncPtrType) // argument type is a function pointer 00162 { 00163 //printf("a->type=`%s' a->name=`%s'\n",a->type.data(),a->name.data()); 00164 QCString n=a->type.left(vp); 00165 if (hasFuncPtrType) n=a->type.left(wp); 00166 if (md->isObjCMethod()) { n.prepend("("); n.append(")"); } 00167 if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName); 00168 linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md->name(),n); 00169 } 00170 else // non-function pointer type 00171 { 00172 QCString n=a->type; 00173 if (md->isObjCMethod()) { n.prepend("("); n.append(")"); } 00174 if (a->type!="...") 00175 { 00176 if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName); 00177 linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md->name(),n); 00178 } 00179 } 00180 if (!md->isDefine()) 00181 { 00182 ol.endParameterType(); 00183 ol.startParameterName(defArgList->count()<2); 00184 } 00185 if (hasFuncPtrType) 00186 { 00187 ol.docify(a->type.mid(wp,vp-wp)); 00188 } 00189 if (!a->name.isEmpty() || (a->name.isEmpty() && a->type=="...")) // argument has a name 00190 { 00191 if (!hasFuncPtrType) 00192 { 00193 ol.docify(" "); 00194 } 00195 ol.disable(OutputGenerator::Man); 00196 ol.startEmphasis(); 00197 ol.enable(OutputGenerator::Man); 00198 if (a->name.isEmpty()) ol.docify(a->type); else ol.docify(a->name); 00199 ol.disable(OutputGenerator::Man); 00200 ol.endEmphasis(); 00201 ol.enable(OutputGenerator::Man); 00202 } 00203 if (!a->array.isEmpty()) 00204 { 00205 ol.docify(a->array); 00206 } 00207 if (hasFuncPtrType) // write the part of the argument type 00208 // that comes after the name 00209 { 00210 linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(), 00211 md->name(),a->type.right(a->type.length()-vp)); 00212 } 00213 if (!a->defval.isEmpty()) // write the default value 00214 { 00215 QCString n=a->defval; 00216 if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName); 00217 ol.docify(" = "); 00218 00219 ol.startTypewriter(); 00220 linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md->name(),n,FALSE,TRUE,TRUE); 00221 ol.endTypewriter(); 00222 00223 } 00224 a=defArgList->next(); 00225 if (a) 00226 { 00227 if (!md->isObjCMethod()) ol.docify(", "); // there are more arguments 00228 if (!md->isDefine()) 00229 { 00230 QCString key; 00231 if (md->isObjCMethod() && a->attrib.length()>=2) 00232 { 00233 //printf("Found parameter keyword %s\n",a->attrib.data()); 00234 // strip [ and ] 00235 key=a->attrib.mid(1,a->attrib.length()-2); 00236 if (key!=",") key+=":"; // for normal keywords add colon 00237 } 00238 ol.endParameterName(FALSE,FALSE,!md->isObjCMethod()); 00239 ol.startParameterType(FALSE,key); 00240 } 00241 } 00242 first=FALSE; 00243 } 00244 ol.pushGeneratorState(); 00245 bool htmlOn = ol.isEnabled(OutputGenerator::Html); 00246 ol.disable(OutputGenerator::Html); 00247 //if (!first) ol.writeString(" "); 00248 if (!md->isObjCMethod()) ol.docify(")"); // end argument list 00249 ol.enableAll(); 00250 ol.disableAllBut(OutputGenerator::Html); 00251 if (!htmlOn) ol.disable(OutputGenerator::Html); 00252 if (!md->isDefine()) 00253 { 00254 if (first) ol.startParameterName(defArgList->count()<2); 00255 ol.endParameterName(TRUE,defArgList->count()<2,!md->isObjCMethod()); 00256 } 00257 else 00258 { 00259 ol.endParameterType(); 00260 ol.startParameterName(TRUE); 00261 ol.endParameterName(TRUE,TRUE,!md->isObjCMethod()); 00262 } 00263 ol.popGeneratorState(); 00264 if (md->extraTypeChars()) 00265 { 00266 ol.docify(md->extraTypeChars()); 00267 } 00268 if (defArgList->constSpecifier) 00269 { 00270 ol.docify(" const"); 00271 } 00272 if (defArgList->volatileSpecifier) 00273 { 00274 ol.docify(" volatile"); 00275 } 00276 return TRUE; 00277 } 00278 00279 static void writeTemplatePrefix(OutputList &ol,ArgumentList *al) 00280 { 00281 ol.docify("template<"); 00282 Argument *a=al->first(); 00283 while (a) 00284 { 00285 ol.docify(a->type); 00286 ol.docify(" "); 00287 ol.docify(a->name); 00288 if (a->defval.length()!=0) 00289 { 00290 ol.docify(" = "); 00291 ol.docify(a->defval); 00292 } 00293 a=al->next(); 00294 if (a) ol.docify(", "); 00295 } 00296 ol.docify("> "); 00297 } 00298 00299 //----------------------------------------------------------------------------- 00300 //----------------------------------------------------------------------------- 00301 //----------------------------------------------------------------------------- 00302 00303 class MemberDefImpl 00304 { 00305 public: 00306 MemberDefImpl(); 00307 ~MemberDefImpl(); 00308 void init(Definition *def,const char *t,const char *a,const char *e, 00309 Protection p,Specifier v,bool s,bool r,MemberDef::MemberType mt, 00310 const ArgumentList *tal,const ArgumentList *al 00311 ); 00312 00313 ClassDef *classDef; // member of or related to 00314 FileDef *fileDef; // member of file definition 00315 NamespaceDef *nspace; // the namespace this member is in. 00316 00317 MemberDef *enumScope; // the enclosing scope, if this is an enum field 00318 MemberDef *annEnumType; // the annonymous enum that is the type of this member 00319 MemberList *enumFields; // enumeration fields 00320 00321 MemberDef *redefines; // the members that this member redefines 00322 MemberList *redefinedBy; // the list of members that redefine this one 00323 00324 MemberDef *memDef; // member definition for this declaration 00325 MemberDef *memDec; // member declaration for this definition 00326 ClassDef *relatedAlso; // points to class marked by relatedAlso 00327 00328 ExampleSDict *exampleSDict; // a dictionary of all examples for quick access 00329 00330 QCString type; // return type 00331 QCString args; // function arguments/variable array specifiers 00332 QCString def; // member definition in code (fully qualified name) 00333 QCString anc; // HTML anchor name 00334 Specifier virt; // normal/virtual/pure virtual 00335 Protection prot; // protection type [Public/Protected/Private] 00336 QCString decl; // member declaration in class 00337 00338 QCString bitfields; // struct member bitfields 00339 QCString read; // property read accessor 00340 QCString write; // property write accessor 00341 QCString exception; // exceptions that can be thrown 00342 QCString initializer; // initializer 00343 QCString extraTypeChars; // extra type info found after the argument list 00344 int initLines; // number of lines in the initializer 00345 00346 int memSpec; // The specifiers present for this member 00347 MemberDef::MemberType mtype; // returns the kind of member 00348 int maxInitLines; // when the initializer will be displayed 00349 int userInitLines; // result of explicit \hideinitializer or \showinitializer 00350 MemberDef *annMemb; 00351 00352 ArgumentList *defArgList; // argument list of this member definition 00353 ArgumentList *declArgList; // argument list of this member declaration 00354 00355 ArgumentList *tArgList; // template argument list of function template 00356 ArgumentList *typeConstraints; // type constraints for template parameters 00357 MemberDef *templateMaster; 00358 QList<ArgumentList> *defTmpArgLists; // lists of template argument lists 00359 // (for template functions in nested template classes) 00360 00361 ClassDef *cachedAnonymousType; // if the member has an anonymous compound 00362 // as its type then this is computed by 00363 // getClassDefOfAnonymousType() and 00364 // cached here. 00365 SDict<MemberList> *classSectionSDict; // not accessible 00366 00367 MemberDef *groupAlias; // Member containing the definition 00368 int grpId; // group id 00369 MemberGroup *memberGroup; // group's member definition 00370 GroupDef *group; // group in which this member is in 00371 Grouping::GroupPri_t grouppri; // priority of this definition 00372 QCString groupFileName; // file where this grouping was defined 00373 int groupStartLine; // line " " " " " 00374 MemberDef *groupMember; 00375 00376 bool isTypedefValCached; 00377 ClassDef *cachedTypedefValue; 00378 QCString cachedTypedefTemplSpec; 00379 QCString cachedResolvedType; 00380 00381 // inbody documentation 00382 int inbodyLine; 00383 QCString inbodyFile; 00384 QCString inbodyDocs; 00385 00386 // documentation inheritance 00387 MemberDef *docProvider; 00388 00389 // to store the output file base from tag files 00390 QCString explicitOutputFileBase; 00391 00392 // objective-c 00393 bool implOnly; // function found in implementation but not 00394 // in the interface 00395 bool hasDocumentedParams; 00396 bool hasDocumentedReturnType; 00397 bool isDMember; 00398 bool related; // is this a member that is only related to a class 00399 bool stat; // is it a static function? 00400 bool proto; // is it a prototype; 00401 bool docEnumValues; // is an enum with documented enum values. 00402 bool annScope; // member is part of an annoymous scope 00403 bool annUsed; 00404 bool hasCallGraph; 00405 bool hasCallerGraph; 00406 bool explExt; // member was explicitly declared external 00407 bool tspec; // member is a template specialization 00408 bool groupHasDocs; // true if the entry that caused the grouping was documented 00409 bool docsForDefinition; // TRUE => documentation block is put before 00410 // definition. 00411 // FALSE => block is put before declaration. 00412 }; 00413 00414 MemberDefImpl::MemberDefImpl() : 00415 enumFields(0), 00416 redefinedBy(0), 00417 exampleSDict(0), 00418 defArgList(0), 00419 declArgList(0), 00420 tArgList(0), 00421 typeConstraints(0), 00422 defTmpArgLists(0), 00423 classSectionSDict(0) 00424 { 00425 } 00426 00427 MemberDefImpl::~MemberDefImpl() 00428 { 00429 delete redefinedBy; 00430 delete exampleSDict; 00431 delete enumFields; 00432 delete defArgList; 00433 delete tArgList; 00434 delete typeConstraints; 00435 delete defTmpArgLists; 00436 delete classSectionSDict; 00437 delete declArgList; 00438 } 00439 00440 void MemberDefImpl::init(Definition *def, 00441 const char *t,const char *a,const char *e, 00442 Protection p,Specifier v,bool s,bool r,MemberDef::MemberType mt, 00443 const ArgumentList *tal,const ArgumentList *al 00444 ) 00445 { 00446 classDef=0; 00447 fileDef=0; 00448 redefines=0; 00449 relatedAlso=0; 00450 redefinedBy=0; 00451 nspace=0; 00452 memDef=0; 00453 memDec=0; 00454 group=0; 00455 grpId=-1; 00456 exampleSDict=0; 00457 enumFields=0; 00458 enumScope=0; 00459 defTmpArgLists=0; 00460 hasCallGraph = FALSE; 00461 hasCallerGraph = FALSE; 00462 initLines=0; 00463 type=t; 00464 if (mt==MemberDef::Typedef) type.stripPrefix("typedef "); 00465 // type.stripPrefix("struct "); 00466 // type.stripPrefix("class " ); 00467 // type.stripPrefix("union " ); 00468 type=removeRedundantWhiteSpace(type); 00469 args=a; 00470 args=removeRedundantWhiteSpace(args); 00471 if (type.isEmpty()) decl=def->name()+args; else decl=type+" "+def->name()+args; 00472 00473 memberGroup=0; 00474 virt=v; 00475 prot=p; 00476 related=r; 00477 stat=s; 00478 mtype=mt; 00479 exception=e; 00480 proto=FALSE; 00481 annScope=FALSE; 00482 memSpec=0; 00483 annMemb=0; 00484 annUsed=FALSE; 00485 annEnumType=0; 00486 groupAlias=0; 00487 explExt=FALSE; 00488 tspec=FALSE; 00489 cachedAnonymousType=0; 00490 maxInitLines=Config_getInt("MAX_INITIALIZER_LINES"); 00491 userInitLines=-1; 00492 docEnumValues=FALSE; 00493 // copy function template arguments (if any) 00494 if (tal) 00495 { 00496 tArgList = new ArgumentList; 00497 tArgList->setAutoDelete(TRUE); 00498 ArgumentListIterator ali(*tal); 00499 Argument *a; 00500 for (;(a=ali.current());++ali) 00501 { 00502 tArgList->append(new Argument(*a)); 00503 } 00504 } 00505 else 00506 { 00507 tArgList=0; 00508 } 00509 //printf("new member al=%p\n",al); 00510 // copy function definition arguments (if any) 00511 if (al) 00512 { 00513 defArgList = new ArgumentList; 00514 defArgList->setAutoDelete(TRUE); 00515 ArgumentListIterator ali(*al); 00516 Argument *a; 00517 for (;(a=ali.current());++ali) 00518 { 00519 //printf("copy argument %s (doc=%s)\n",a->name.data(),a->docs.data()); 00520 defArgList->append(new Argument(*a)); 00521 } 00522 defArgList->constSpecifier = al->constSpecifier; 00523 defArgList->volatileSpecifier = al->volatileSpecifier; 00524 defArgList->pureSpecifier = al->pureSpecifier; 00525 //printf("defArgList(%p)->constSpecifier=%d\n",defArgList,defArgList->constSpecifier); 00526 } 00527 else 00528 { 00529 defArgList=0; 00530 } 00531 // convert function declaration arguments (if any) 00532 if (!args.isEmpty()) 00533 { 00534 declArgList = new ArgumentList; 00535 stringToArgumentList(args,declArgList,&extraTypeChars); 00536 //printf("setDeclArgList %s to %p const=%d\n",args.data(), 00537 // declArgList,declArgList->constSpecifier); 00538 } 00539 else 00540 { 00541 declArgList = 0; 00542 } 00543 templateMaster = 0; 00544 classSectionSDict = 0; 00545 docsForDefinition = TRUE; 00546 isTypedefValCached = FALSE; 00547 cachedTypedefValue = 0; 00548 inbodyLine = -1; 00549 implOnly=FALSE; 00550 groupMember = 0; 00551 hasDocumentedParams = FALSE; 00552 hasDocumentedReturnType = FALSE; 00553 docProvider = 0; 00554 isDMember = def->getDefFileName().right(2).lower()==".d"; 00555 } 00556 00557 00558 //----------------------------------------------------------------------------- 00559 //----------------------------------------------------------------------------- 00560 //----------------------------------------------------------------------------- 00561 00583 MemberDef::MemberDef(const char *df,int dl, 00584 const char *t,const char *na,const char *a,const char *e, 00585 Protection p,Specifier v,bool s,bool r,MemberType mt, 00586 const ArgumentList *tal,const ArgumentList *al 00587 ) : Definition(df,dl,removeRedundantWhiteSpace(na)) 00588 { 00589 m_storagePos=-1; 00590 m_cacheHandle=-1; 00591 m_impl = new MemberDefImpl; 00592 m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al); 00593 m_flushPending = FALSE; 00594 } 00595 00597 MemberDef::~MemberDef() 00598 { 00599 delete m_impl; 00600 if (m_cacheHandle!=-1) 00601 { 00602 Doxygen::symbolCache->del(m_cacheHandle); 00603 m_cacheHandle=-1; 00604 } 00605 } 00606 00607 void MemberDef::setReimplements(MemberDef *md) 00608 { 00609 makeResident(); 00610 //if (redefines==0) redefines = new MemberList; 00611 //if (redefines->find(md)==-1) redefines->inSort(md); 00612 00613 m_impl->redefines = md; 00614 } 00615 00616 void MemberDef::insertReimplementedBy(MemberDef *md) 00617 { 00618 makeResident(); 00619 if (m_impl->templateMaster) 00620 { 00621 m_impl->templateMaster->insertReimplementedBy(md); 00622 } 00623 if (m_impl->redefinedBy==0) m_impl->redefinedBy = new MemberList(MemberList::redefinedBy); 00624 if (m_impl->redefinedBy->findRef(md)==-1) 00625 { 00626 m_impl->redefinedBy->inSort(md); 00627 } 00628 } 00629 00630 MemberDef *MemberDef::reimplements() const 00631 { 00632 makeResident(); 00633 return m_impl->redefines; 00634 } 00635 00636 LockingPtr<MemberList> MemberDef::reimplementedBy() const 00637 { 00638 makeResident(); 00639 return LockingPtr<MemberList>(this,m_impl->redefinedBy); 00640 } 00641 00642 void MemberDef::insertEnumField(MemberDef *md) 00643 { 00644 makeResident(); 00645 if (m_impl->enumFields==0) m_impl->enumFields=new MemberList(MemberList::enumFields); 00646 m_impl->enumFields->append(md); 00647 } 00648 00649 bool MemberDef::addExample(const char *anchor,const char *nameStr, 00650 const char *file) 00651 { 00652 makeResident(); 00653 //printf("%s::addExample(%s,%s,%s)\n",name().data(),anchor,nameStr,file); 00654 if (m_impl->exampleSDict==0) m_impl->exampleSDict = new ExampleSDict; 00655 if (m_impl->exampleSDict->find(nameStr)==0) 00656 { 00657 //printf("Add reference to example %s to member %s\n",nameStr,name.data()); 00658 Example *e=new Example; 00659 e->anchor=anchor; 00660 e->name=nameStr; 00661 e->file=file; 00662 m_impl->exampleSDict->inSort(nameStr,e); 00663 return TRUE; 00664 } 00665 return FALSE; 00666 } 00667 00668 bool MemberDef::hasExamples() 00669 { 00670 makeResident(); 00671 if (m_impl->exampleSDict==0) 00672 return FALSE; 00673 else 00674 return m_impl->exampleSDict->count()>0; 00675 } 00676 00677 QCString MemberDef::getOutputFileBase() const 00678 { 00679 makeResident(); 00680 static bool separateMemberPages = Config_getBool("SEPARATE_MEMBER_PAGES"); 00681 QCString baseName; 00682 //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n", 00683 // name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef, 00684 // m_impl->nspace,m_impl->fileDef); 00685 if (!m_impl->explicitOutputFileBase.isEmpty()) 00686 { 00687 return m_impl->explicitOutputFileBase; 00688 } 00689 else if (m_impl->templateMaster) 00690 { 00691 return m_impl->templateMaster->getOutputFileBase(); 00692 } 00693 else if (m_impl->group) 00694 { 00695 baseName=m_impl->group->getOutputFileBase(); 00696 } 00697 else if (m_impl->classDef) 00698 { 00699 baseName=m_impl->classDef->getOutputFileBase(); 00700 } 00701 else if (m_impl->nspace) 00702 { 00703 baseName=m_impl->nspace->getOutputFileBase(); 00704 } 00705 else if (m_impl->fileDef) 00706 { 00707 baseName=m_impl->fileDef->getOutputFileBase(); 00708 } 00709 00710 if (baseName.isEmpty()) 00711 { 00712 warn(getDefFileName(),getDefLine(), 00713 "Warning: Internal inconsistency: member %s does not belong to any" 00714 " container!",name().data() 00715 ); 00716 return "dummy"; 00717 } 00718 else if (separateMemberPages) 00719 { 00720 if (getEnumScope()) // enum value, which is part of enum's documentation 00721 { 00722 baseName+="_"+getEnumScope()->anchor(); 00723 } 00724 else 00725 { 00726 baseName+="_"+anchor(); 00727 } 00728 } 00729 return baseName; 00730 } 00731 00732 QCString MemberDef::getReference() const 00733 { 00734 makeResident(); 00735 QCString ref = Definition::getReference(); 00736 if (!ref.isEmpty()) 00737 { 00738 return ref; 00739 } 00740 if (m_impl->templateMaster) 00741 { 00742 return m_impl->templateMaster->getReference(); 00743 } 00744 else if (m_impl->group) 00745 { 00746 return m_impl->group->getReference(); 00747 } 00748 else if (m_impl->classDef) 00749 { 00750 return m_impl->classDef->getReference(); 00751 } 00752 else if (m_impl->nspace) 00753 { 00754 return m_impl->nspace->getReference(); 00755 } 00756 else if (m_impl->fileDef) 00757 { 00758 return m_impl->fileDef->getReference(); 00759 } 00760 return ""; 00761 } 00762 00763 QCString MemberDef::anchor() const 00764 { 00765 makeResident(); 00766 QCString result=m_impl->anc; 00767 if (m_impl->groupAlias) return m_impl->groupAlias->anchor(); 00768 if (m_impl->templateMaster) return m_impl->templateMaster->anchor(); 00769 if (m_impl->enumScope) result.prepend(m_impl->enumScope->anchor()); 00770 if (m_impl->group) 00771 { 00772 if (m_impl->groupMember) 00773 { 00774 result=m_impl->groupMember->anchor(); 00775 } 00776 else if (getReference().isEmpty()) 00777 { 00778 result.prepend("g"); 00779 } 00780 } 00781 return result; 00782 } 00783 00784 bool MemberDef::isLinkableInProject() const 00785 { 00786 static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); 00787 static bool extractStatic = Config_getBool("EXTRACT_STATIC"); 00788 makeResident(); 00789 00790 //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data()); 00791 if (isHidden()) 00792 { 00793 //printf("is hidden\n"); 00794 return FALSE; 00795 } 00796 if (m_impl->templateMaster) 00797 { 00798 //printf("has template master\n"); 00799 return m_impl->templateMaster->isLinkableInProject(); 00800 } 00801 if (name().isEmpty() || name().at(0)=='@') 00802 { 00803 //printf("name invalid\n"); 00804 return FALSE; // not a valid or a dummy name 00805 } 00806 if (!hasDocumentation() && !isReference()) 00807 { 00808 //printf("no docs or reference\n"); 00809 return FALSE; // no documentation 00810 } 00811 if (m_impl->group && !m_impl->group->isLinkableInProject()) 00812 { 00813 //printf("group but group not linkable!\n"); 00814 return FALSE; // group but group not linkable 00815 } 00816 if (!m_impl->group && m_impl->classDef && !m_impl->classDef->isLinkableInProject()) 00817 { 00818 //printf("in a class but class not linkable!\n"); 00819 return FALSE; // in class but class not linkable 00820 } 00821 if (!m_impl->group && m_impl->nspace && !m_impl->related && !m_impl->nspace->isLinkableInProject()) 00822 { 00823 //printf("in a namespace but namespace not linkable!\n"); 00824 return FALSE; // in namespace but namespace not linkable 00825 } 00826 if (!m_impl->group && !m_impl->nspace && !m_impl->related && !m_impl->classDef && m_impl->fileDef && !m_impl->fileDef->isLinkableInProject()) 00827 { 00828 //printf("in a file but file not linkable!\n"); 00829 return FALSE; // in file (and not in namespace) but file not linkable 00830 } 00831 if (m_impl->prot==Private && !extractPrivate && m_impl->mtype!=Friend) 00832 { 00833 //printf("private and invisible!\n"); 00834 return FALSE; // hidden due to protection 00835 } 00836 if (isStatic() && m_impl->classDef==0 && !extractStatic) 00837 { 00838 //printf("static and invisible!\n"); 00839 return FALSE; // hidden due to staticness 00840 } 00841 //printf("linkable!\n"); 00842 return TRUE; // linkable! 00843 } 00844 00845 bool MemberDef::isLinkable() const 00846 { 00847 makeResident(); 00848 if (m_impl->templateMaster) 00849 { 00850 return m_impl->templateMaster->isLinkable(); 00851 } 00852 else 00853 { 00854 return isLinkableInProject() || isReference(); 00855 } 00856 } 00857 00858 00859 void MemberDef::setDefinitionTemplateParameterLists(QList<ArgumentList> *lists) 00860 { 00861 if (lists) 00862 { 00863 makeResident(); 00864 if (m_impl->defTmpArgLists) delete m_impl->defTmpArgLists; 00865 m_impl->defTmpArgLists = copyArgumentLists(lists); 00866 } 00867 } 00868 00869 void MemberDef::writeLink(OutputList &ol,ClassDef *,NamespaceDef *, 00870 FileDef *fd,GroupDef *gd,bool onlyText) 00871 { 00872 static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); 00873 static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES"); 00874 makeResident(); 00875 LockingPtr<MemberDef> lock(this,this); 00876 QCString sep = optimizeOutputJava ? "." : "::"; 00877 QCString n = name(); 00878 if (!hideScopeNames && m_impl->classDef && gd) n.prepend(m_impl->classDef->name()+sep); 00879 else if (!hideScopeNames && m_impl->nspace && (gd || fd)) n.prepend(m_impl->nspace->name()+sep); 00880 if (isObjCMethod()) 00881 { 00882 if (isStatic()) ol.docify("+ "); else ol.docify("- "); 00883 } 00884 if (!onlyText) // write link 00885 { 00886 if (m_impl->mtype==EnumValue && getGroupDef()==0 && // enum value is not grouped 00887 getEnumScope() && getEnumScope()->getGroupDef()) // but its container is 00888 { 00889 GroupDef *enumValGroup = getEnumScope()->getGroupDef(); 00890 ol.writeObjectLink(enumValGroup->getReference(), 00891 enumValGroup->getOutputFileBase(), 00892 anchor(),n); 00893 } 00894 else 00895 { 00896 ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),n); 00897 } 00898 } 00899 else // write only text 00900 { 00901 ol.startBold(); 00902 ol.docify(n); 00903 ol.endBold(); 00904 } 00905 } 00906 00910 ClassDef *MemberDef::getClassDefOfAnonymousType() 00911 { 00912 makeResident(); 00913 if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType; 00914 LockingPtr<MemberDef> lock(this,this); 00915 00916 QCString cname; 00917 if (getClassDef()!=0) 00918 { 00919 cname=getClassDef()->name().copy(); 00920 } 00921 else if (getNamespaceDef()!=0) 00922 { 00923 cname=getNamespaceDef()->name().copy(); 00924 } 00925 QCString ltype(m_impl->type); 00926 // strip `static' keyword from ltype 00927 //if (ltype.left(7)=="static ") ltype=ltype.right(ltype.length()-7); 00928 // strip `friend' keyword from ltype 00929 ltype.stripPrefix("friend "); 00930 static QRegExp r("@[0-9]+"); 00931 int l,i=r.match(ltype,0,&l); 00932 //printf("ltype=`%s' i=%d\n",ltype.data(),i); 00933 // search for the last anonymous scope in the member type 00934 ClassDef *annoClassDef=0; 00935 if (i!=-1) // found anonymous scope in type 00936 { 00937 int il=i-1,ir=i+l; 00938 // extract anonymous scope 00939 while (il>=0 && (isId(ltype.at(il)) || ltype.at(il)==':' || ltype.at(il)=='@')) il--; 00940 if (il>0) il++; else if (il<0) il=0; 00941 while (ir<(int)ltype.length() && (isId(ltype.at(ir)) || ltype.at(ir)==':' || ltype.at(ir)=='@')) ir++; 00942 00943 QCString annName = ltype.mid(il,ir-il); 00944 00945 // if inside a class or namespace try to prepend the scope name 00946 if (!cname.isEmpty() && annName.left(cname.length()+2)!=cname+"::") 00947 { 00948 QCString ts=stripAnonymousNamespaceScope(cname+"::"+annName); 00949 //printf("Member::writeDeclaration: Trying %s\n",ts.data()); 00950 annoClassDef=getClass(ts); 00951 } 00952 // if not found yet, try without scope name 00953 if (annoClassDef==0) 00954 { 00955 QCString ts=stripAnonymousNamespaceScope(annName); 00956 //printf("Member::writeDeclaration: Trying %s\n",ts.data()); 00957 annoClassDef=getClass(ts); 00958 } 00959 } 00960 m_impl->cachedAnonymousType = annoClassDef; 00961 return annoClassDef; 00962 } 00963 00967 bool MemberDef::isBriefSectionVisible() const 00968 { 00969 static bool extractStatic = Config_getBool("EXTRACT_STATIC"); 00970 static bool hideUndocMembers = Config_getBool("HIDE_UNDOC_MEMBERS"); 00971 static bool briefMemberDesc = Config_getBool("BRIEF_MEMBER_DESC"); 00972 static bool repeatBrief = Config_getBool("REPEAT_BRIEF"); 00973 static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS"); 00974 static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); 00975 00976 //printf("Member %s grpId=%d docs=%s file=%s args=%s\n", 00977 // name().data(), 00978 // 0,"", //grpId,grpId==-1?"<none>":Doxygen::memberDocDict[grpId]->data(), 00979 // "", //getFileDef()->name().data(), 00980 // argsString()); 00981 00982 makeResident(); 00983 LockingPtr<MemberDef> lock(this,this); 00984 MemberGroupInfo *info = Doxygen::memGrpInfoDict[m_impl->grpId]; 00985 //printf("name=%s m_impl->grpId=%d info=%p\n",name().data(),m_impl->grpId,info); 00986 //QCString *pMemGrp = Doxygen::memberDocDict[grpId]; 00987 bool hasDocs = hasDocumentation() || 00988 // part of a documented member group 00989 (m_impl->grpId!=-1 && info && !(info->doc.isEmpty() && info->header.isEmpty())); 00990 00991 // only include static members with file/namespace scope if 00992 // explicitly enabled in the config file 00993 bool visibleIfStatic = !(getClassDef()==0 && 00994 isStatic() && 00995 !extractStatic 00996 ); 00997 00998 // only include members is the are documented or 00999 // HIDE_UNDOC_MEMBERS is NO in the config file 01000 bool visibleIfDocumented = (!hideUndocMembers || 01001 hasDocs || 01002 isDocumentedFriendClass() 01003 ); 01004 01005 // hide members with no detailed description and brief descriptions 01006 // explicitly disabled. 01007 bool visibleIfEnabled = !(hideUndocMembers && 01008 documentation().isEmpty() && 01009 !briefMemberDesc && 01010 !repeatBrief 01011 ); 01012 01013 // Hide friend (class|struct|union) declarations if HIDE_FRIEND_COMPOUNDS is true 01014 bool visibleIfFriendCompound = !(hideFriendCompounds && 01015 isFriend() && 01016 (m_impl->type=="friend class" || 01017 m_impl->type=="friend struct" || 01018 m_impl->type=="friend union" 01019 ) 01020 ); 01021 01022 // only include members that are non-private unless EXTRACT_PRIVATE is 01023 // set to YES or the member is part of a group 01024 bool visibleIfPrivate = (protection()!=Private || 01025 extractPrivate || 01026 m_impl->mtype==Friend 01027 ); 01028 01029 // hide member if it overrides a member in a superclass and has no 01030 // documentation of its own 01031 //bool visibleIfDocVirtual = !reimplements() || 01032 // !Config_getBool("INHERIT_DOCS") || 01033 // hasDocs; 01034 01035 // true if this member is a constructor or destructor 01036 bool cOrDTor = isConstructor() || isDestructor(); 01037 01038 // hide default constructors or destructors (no args) without 01039 // documentation 01040 bool visibleIfNotDefaultCDTor = !(cOrDTor && 01041 m_impl->defArgList && 01042 (m_impl->defArgList->isEmpty() || 01043 m_impl->defArgList->first()->type == "void" 01044 ) && 01045 !hasDocs 01046 ); 01047 01048 //printf("visibleIfStatic=%d visibleIfDocumented=%d visibleIfEnabled=%d " 01049 // "visibleIfPrivate=%d visibltIfNotDefaultCDTor=%d " 01050 // "visibleIfFriendCompound=%d\n",visibleIfStatic,visibleIfDocumented, 01051 // visibleIfEnabled,visibleIfPrivate,visibleIfNotDefaultCDTor, 01052 // visibleIfFriendCompound); 01053 01054 bool visible = visibleIfStatic && visibleIfDocumented && 01055 visibleIfEnabled && visibleIfPrivate && 01056 /*visibleIfDocVirtual &&*/ visibleIfNotDefaultCDTor && 01057 visibleIfFriendCompound && 01058 !m_impl->annScope; 01059 //printf("MemberDef::isBriefSectionVisible() %d\n",visible); 01060 return visible; 01061 } 01062 01063 01064 void MemberDef::writeDeclaration(OutputList &ol, 01065 ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, 01066 bool inGroup 01067 ) 01068 { 01069 //printf("%s MemberDef::writeDeclaration() inGroup=%d\n",name().data(),inGroup); 01070 01071 // hide enum value, since they appear already as part of the enum, unless they 01072 // are explicitly grouped. 01073 makeResident(); 01074 if (!inGroup && m_impl->mtype==EnumValue) return; 01075 LockingPtr<MemberDef> lock(this,this); 01076 01077 // hide members whose brief section should not be visible 01078 //if (!isBriefSectionVisible()) return; 01079 01080 Definition *d=0; 01081 ASSERT (cd!=0 || nd!=0 || fd!=0 || gd!=0); // member should belong to something 01082 if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd; 01083 01084 // write tag file information of this member 01085 if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !isReference()) 01086 { 01087 Doxygen::tagFile << " <member kind=\""; 01088 switch (m_impl->mtype) 01089 { 01090 case Define: Doxygen::tagFile << "define"; break; 01091 case EnumValue: Doxygen::tagFile << "enumvalue"; break; 01092 case Property: Doxygen::tagFile << "property"; break; 01093 case Event: Doxygen::tagFile << "event"; break; 01094 case Variable: Doxygen::tagFile << "variable"; break; 01095 case Typedef: Doxygen::tagFile << "typedef"; break; 01096 case Enumeration: Doxygen::tagFile << "enumeration"; break; 01097 case Function: Doxygen::tagFile << "function"; break; 01098 case Signal: Doxygen::tagFile << "signal"; break; 01099 case Prototype: Doxygen::tagFile << "prototype"; break; 01100 case Friend: Doxygen::tagFile << "friend"; break; 01101 case DCOP: Doxygen::tagFile << "dcop"; break; 01102 case Slot: Doxygen::tagFile << "slot"; break; 01103 } 01104 if (m_impl->prot!=Public) 01105 { 01106 Doxygen::tagFile << "\" protection=\""; 01107 if (m_impl->prot==Protected) Doxygen::tagFile << "protected"; 01108 else if (m_impl->prot==Package) Doxygen::tagFile << "package"; 01109 else /* Private */ Doxygen::tagFile << "private"; 01110 } 01111 if (m_impl->virt!=Normal) 01112 { 01113 Doxygen::tagFile << "\" virtualness=\""; 01114 if (m_impl->virt==Virtual) Doxygen::tagFile << "virtual"; 01115 else /* Pure */ Doxygen::tagFile << "pure"; 01116 } 01117 if (isStatic()) 01118 { 01119 Doxygen::tagFile << "\" static=\"yes"; 01120 } 01121 Doxygen::tagFile << "\">" << endl; 01122 Doxygen::tagFile << " <type>" << convertToXML(typeString()) << "</type>" << endl; 01123 Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; 01124 Doxygen::tagFile << " <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl; 01125 Doxygen::tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>" << endl; 01126 Doxygen::tagFile << " <arglist>" << convertToXML(argsString()) << "</arglist>" << endl; 01127 writeDocAnchorsToTagFile(); 01128 Doxygen::tagFile << " </member>" << endl; 01129 } 01130 01131 // write search index info 01132 if (Config_getBool("SEARCHENGINE") && !isReference()) 01133 { 01134 Doxygen::searchIndex->setCurrentDoc(qualifiedName(),getOutputFileBase(),anchor()); 01135 Doxygen::searchIndex->addWord(localName(),TRUE); 01136 Doxygen::searchIndex->addWord(qualifiedName(),FALSE); 01137 } 01138 01139 QCString cname = d->name(); 01140 QCString cfname = getOutputFileBase(); 01141 //QCString osname = cname; 01142 // in case of class members that are put in a group the name of the outerscope 01143 // differs from the cname. 01144 //if (getOuterScope()) osname=getOuterScope()->name(); 01145 01146 //HtmlHelp *htmlHelp=0; 01147 //bool hasHtmlHelp = Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_HTMLHELP"); 01148 //if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance(); 01149 01150 // search for the last anonymous scope in the member type 01151 ClassDef *annoClassDef=getClassDefOfAnonymousType(); 01152 01153 // start a new member declaration 01154 bool isAnonymous = annoClassDef || m_impl->annMemb || m_impl->annEnumType; 01156 ol.startMemberItem( isAnonymous ? 1 : m_impl->tArgList ? 3 : 0); 01157 01158 // If there is no detailed description we need to write the anchor here. 01159 bool detailsVisible = isDetailedSectionLinkable(); 01160 if (!detailsVisible && !m_impl->annMemb) 01161 { 01162 QCString doxyName=name().copy(); 01163 if (!cname.isEmpty()) doxyName.prepend(cname+"::"); 01164 QCString doxyArgs=argsString(); 01165 ol.startDoxyAnchor(cfname,cname,anchor(),doxyName,doxyArgs); 01166 01167 ol.pushGeneratorState(); 01168 ol.disable(OutputGenerator::Man); 01169 ol.disable(OutputGenerator::Latex); 01170 ol.docify("\n"); 01171 ol.popGeneratorState(); 01172 } 01173 01174 if (annoClassDef || m_impl->annMemb) 01175 { 01176 int j; 01177 for (j=0;j<s_indentLevel;j++) 01178 { 01179 ol.writeNonBreakableSpace(3); 01180 } 01181 } 01182 01183 // *** write template lists 01184 if (m_impl->tArgList) 01185 { 01186 if (!isAnonymous) ol.startMemberTemplateParams(); 01187 writeTemplatePrefix(ol,m_impl->tArgList); 01188 if (!isAnonymous) ol.endMemberTemplateParams(); 01189 } 01190 01191 // *** write type 01192 QCString ltype(m_impl->type); 01193 if (m_impl->mtype==Typedef) ltype.prepend("typedef "); 01194 // strip `friend' keyword from ltype 01195 ltype.stripPrefix("friend "); 01196 static QRegExp r("@[0-9]+"); 01197 01198 bool endAnonScopeNeeded=FALSE; 01199 int l,i=r.match(ltype,0,&l); 01200 if (i!=-1) // member has an anonymous type 01201 { 01202 //printf("annoClassDef=%p annMemb=%p scopeName=`%s' anonymous=`%s'\n", 01203 // annoClassDef,annMemb,cname.data(),ltype.mid(i,l).data()); 01204 01205 if (annoClassDef) // type is an anonymous compound 01206 { 01207 int ir=i+l; 01208 //printf("<<<<<<<<<<<<<<\n"); 01209 ol.startAnonTypeScope(s_indentLevel++); 01210 annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup); 01211 //printf(">>>>>>>>>>>>>> startMemberItem(2)\n"); 01212 ol.startMemberItem(2); 01213 int j; 01214 for (j=0;j< s_indentLevel-1;j++) 01215 { 01216 ol.writeNonBreakableSpace(3); 01217 } 01218 QCString varName=ltype.right(ltype.length()-ir).stripWhiteSpace(); 01219 //printf(">>>>>> indDepth=%d ltype=`%s' varName=`%s'\n",indDepth,ltype.data(),varName.data()); 01220 ol.docify("}"); 01221 if (varName.isEmpty() && (name().isEmpty() || name().at(0)=='@')) 01222 { 01223 ol.docify(";"); 01224 } 01225 endAnonScopeNeeded=TRUE; 01226 } 01227 else 01228 { 01229 if (getAnonymousEnumType()) // type is an anonymous enum 01230 { 01231 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),ltype.left(i),TRUE); 01232 getAnonymousEnumType()->writeEnumDeclaration(ol,cd,nd,fd,gd); 01233 //ol+=*getAnonymousEnumType()->enumDecl(); 01234 linkifyText(TextGeneratorOLImpl(ol),d,m_impl->fileDef,name(),ltype.right(ltype.length()-i-l),TRUE); 01235 } 01236 else 01237 { 01238 ltype = ltype.left(i) + " { ... } " + removeAnonymousScopes(ltype.right(ltype.length()-i-l)); 01239 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),ltype,TRUE); 01240 } 01241 } 01242 } 01243 else if (ltype=="@") // rename type from enum values 01244 { 01245 ltype=""; 01246 } 01247 else 01248 { 01249 if (isObjCMethod()) 01250 { 01251 ltype.prepend("("); 01252 ltype.append(")"); 01253 } 01254 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),ltype,TRUE); 01255 } 01256 bool htmlOn = ol.isEnabled(OutputGenerator::Html); 01257 if (htmlOn && Config_getBool("HTML_ALIGN_MEMBERS") && !ltype.isEmpty()) 01258 { 01259 ol.disable(OutputGenerator::Html); 01260 } 01261 if (!ltype.isEmpty()) ol.docify(" "); 01262 if (htmlOn) 01263 { 01264 ol.enable(OutputGenerator::Html); 01265 } 01266 01267 if (m_impl->annMemb) 01268 { 01269 ol.pushGeneratorState(); 01270 ol.disableAllBut(OutputGenerator::Html); 01271 ol.writeNonBreakableSpace(3); 01272 ol.popGeneratorState(); 01273 } 01274 else 01275 { 01276 ol.insertMemberAlign(m_impl->tArgList!=0); 01277 } 01278 01279 // *** write name 01280 if (!name().isEmpty() && name().at(0)!='@') // hide annonymous stuff 01281 { 01282 //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable()); 01283 if (!(name().isEmpty() || name().at(0)=='@') && // name valid 01284 (hasDocumentation() || isReference()) && // has docs 01285 !(m_impl->prot==Private && !Config_getBool("EXTRACT_PRIVATE") && m_impl->mtype!=Friend) && // hidden due to protection 01286 !(isStatic() && m_impl->classDef==0 && !Config_getBool("EXTRACT_STATIC")) // hidden due to static-ness 01287 ) 01288 { 01289 if (m_impl->annMemb) 01290 { 01291 //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor()); 01292 m_impl->annMemb->writeLink(ol, 01293 m_impl->annMemb->getClassDef(), 01294 m_impl->annMemb->getNamespaceDef(), 01295 m_impl->annMemb->getFileDef(), 01296 m_impl->annMemb->getGroupDef() 01297 ); 01298 m_impl->annMemb->setAnonymousUsed(); 01299 setAnonymousUsed(); 01300 } 01301 else 01302 { 01303 //printf("writeLink %s->%d\n",name.data(),hasDocumentation()); 01304 ClassDef *rcd = cd; 01305 if (isReference() && m_impl->classDef) rcd = m_impl->classDef; 01306 writeLink(ol,rcd,nd,fd,gd); 01307 } 01308 } 01309 else if (isDocumentedFriendClass()) 01310 // if the member is an undocumented friend declaration for some class, 01311 // then maybe we can link to the class 01312 { 01313 writeLink(ol,getClass(name()),0,0,0); 01314 } 01315 else 01316 // there is a brief member description and brief member 01317 // descriptions are enabled or there is no detailed description. 01318 { 01319 if (m_impl->annMemb) 01320 { 01321 m_impl->annMemb->setAnonymousUsed(); 01322 setAnonymousUsed(); 01323 } 01324 ClassDef *rcd = cd; 01325 if (isReference() && m_impl->classDef) rcd = m_impl->classDef; 01326 writeLink(ol,rcd,nd,fd,gd,TRUE); 01327 } 01328 } 01329 01330 // add to index 01331 if (isEnumerate() && name().at(0)=='@') 01332 { 01333 // don't add to index 01334 } 01335 else // index member 01336 { 01337 static bool separateMemPages = Config_getBool("SEPARATE_MEMBER_PAGES"); 01338 QCString cfname = getOutputFileBase(); 01339 QCString cfiname = d->getOutputFileBase(); 01340 Doxygen::indexList.addIndexItem( 01341 cname, // level1 01342 name(), // level2 01343 separateMemPages ? cfname : cfiname, // contRef 01344 cfname, // memRef 01345 anchor(), // anchor 01346 this); // memberdef 01347 } 01348 01349 // *** write arguments 01350 if (argsString() && !isObjCMethod()) 01351 { 01352 if (!isDefine()) ol.writeString(" "); 01353 //ol.docify(argsString()); 01354 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),argsString()); 01355 } 01356 01357 // *** write exceptions 01358 if (excpString()) 01359 { 01360 ol.writeString(" "); 01361 ol.docify(excpString()); 01362 } 01363 01364 // *** write bitfields 01365 if (!m_impl->bitfields.isEmpty()) // add bitfields 01366 { 01367 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),m_impl->bitfields.simplifyWhiteSpace()); 01368 } 01369 else if (hasOneLineInitializer() 01371 //((maxInitLines>0 && userInitLines==-1) || userInitLines>0) // enabled by default or explicitly 01372 ) // add initializer 01373 { 01374 if (!isDefine()) 01375 { 01376 ol.writeString(" = "); 01377 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),m_impl->initializer.simplifyWhiteSpace()); 01378 } 01379 else 01380 { 01381 ol.writeNonBreakableSpace(3); 01382 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),m_impl->initializer); 01383 } 01384 } 01385 01386 if (isObjCMethod() && isImplementation()) 01387 { 01388 ol.startTypewriter(); 01389 ol.docify(" [implementation]"); 01390 ol.endTypewriter(); 01391 } 01392 01393 if (isProperty() && (isSettable() || isGettable())) 01394 { 01395 ol.writeLatexSpacing(); 01396 ol.startTypewriter(); 01397 ol.docify(" ["); 01398 QStrList sl; 01399 if (isGettable()) sl.append("get"); 01400 if (isSettable()) sl.append("set"); 01401 const char *s=sl.first(); 01402 while (s) 01403 { 01404 ol.docify(s); 01405 s=sl.next(); 01406 if (s) ol.docify(", "); 01407 } 01408 ol.docify("]"); 01409 ol.endTypewriter(); 01410 } 01411 01412 if (isEvent() && (isAddable() || isRemovable() || isRaisable())) 01413 { 01414 ol.writeLatexSpacing(); 01415 ol.startTypewriter(); 01416 ol.docify(" ["); 01417 QStrList sl; 01418 if (isAddable()) sl.append("add"); 01419 if (isRemovable()) sl.append("remove"); 01420 if (isRaisable()) sl.append("raise"); 01421 const char *s=sl.first(); 01422 while (s) 01423 { 01424 ol.docify(s); 01425 s=sl.next(); 01426 if (s) ol.docify(", "); 01427 } 01428 ol.docify("]"); 01429 ol.endTypewriter(); 01430 } 01431 01432 if (!detailsVisible && !m_impl->annMemb) 01433 { 01434 ol.endDoxyAnchor(cfname,anchor()); 01435 } 01436 01437 //printf("endMember %s annoClassDef=%p annEnumType=%p\n", 01438 // name().data(),annoClassDef,annEnumType); 01439 ol.endMemberItem(); 01440 if (endAnonScopeNeeded) 01441 { 01442 ol.endAnonTypeScope(--s_indentLevel); 01443 } 01444 01445 // write brief description 01446 if (!briefDescription().isEmpty() && 01447 Config_getBool("BRIEF_MEMBER_DESC") 01448 /* && !annMemb */ 01449 ) 01450 { 01451 ol.startMemberDescription(); 01452 ol.parseDoc(briefFile(),briefLine(),getOuterScope()?getOuterScope():d,this,briefDescription(),TRUE,FALSE); 01453 if (detailsVisible) 01454 { 01455 ol.pushGeneratorState(); 01456 ol.disableAllBut(OutputGenerator::Html); 01457 //ol.endEmphasis(); 01458 ol.docify(" "); 01459 if (m_impl->group!=0 && gd==0) // forward link to the group 01460 { 01461 ol.startTextLink(getOutputFileBase(),anchor()); 01462 } 01463 else // local link 01464 { 01465 ol.startTextLink(0,anchor()); 01466 } 01467 ol.endTextLink(); 01468 //ol.startEmphasis(); 01469 ol.popGeneratorState(); 01470 } 01471 //ol.newParagraph(); 01472 ol.endMemberDescription(); 01473 } 01474 warnIfUndocumented(); 01475 } 01476 01477 bool MemberDef::isDetailedSectionLinkable() const 01478 { 01479 static bool extractAll = Config_getBool("EXTRACT_ALL"); 01480 static bool alwaysDetailedSec = Config_getBool("ALWAYS_DETAILED_SEC"); 01481 static bool repeatBrief = Config_getBool("REPEAT_BRIEF"); 01482 static bool briefMemberDesc = Config_getBool("BRIEF_MEMBER_DESC"); 01483 static bool hideUndocMembers = Config_getBool("HIDE_UNDOC_MEMBERS"); 01484 static bool extractStatic = Config_getBool("EXTRACT_STATIC"); 01485 static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); 01486 01487 makeResident(); 01488 // the member has details documentation for any of the following reasons 01489 bool docFilter = 01490 // treat everything as documented 01491 extractAll || 01492 // has detailed docs 01493 !documentation().isEmpty() || 01494 // has inbody docs 01495 !inbodyDocumentation().isEmpty() || 01496 // is an enum with values that are documented 01497 (m_impl->mtype==Enumeration && m_impl->docEnumValues) || 01498 // is documented enum value 01499 (m_impl->mtype==EnumValue && !briefDescription().isEmpty()) || 01500 // has brief description that is part of the detailed description 01501 (!briefDescription().isEmpty() && // has brief docs 01502 (alwaysDetailedSec && // they or visible in 01503 repeatBrief || // detailed section or 01504 !briefMemberDesc // they are explicitly not 01505 ) // shown in brief section 01506 ) || 01507 // has a multi-line initialization block 01508 //(initLines>0 && initLines<maxInitLines) || 01509 (hasMultiLineInitializer() && !hideUndocMembers) || 01510 // has one or more documented arguments 01511 (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation()) || 01512 // has user comments 01513 Doxygen::userComments 01514 ; 01515 01516 // this is not a global static or global statics should be extracted 01517 bool staticFilter = getClassDef()!=0 || !isStatic() || extractStatic; 01518 01519 // only include members that are non-private unless EXTRACT_PRIVATE is 01520 // set to YES or the member is part of a group 01521 bool privateFilter = (protection()!=Private || extractPrivate || 01522 m_impl->mtype==Friend 01523 ); 01524 01525 // member is part of an anonymous scope that is the type of 01526 // another member in the list. 01527 // 01528 //bool inAnonymousScope = !briefDescription().isEmpty() && annUsed; 01529 01530 // hide friend (class|struct|union) member if HIDE_FRIEND_COMPOUNDS 01531 // is true 01532 bool friendCompoundFilter = !(Config_getBool("HIDE_FRIEND_COMPOUNDS") && 01533 isFriend() && 01534 (m_impl->type=="friend class" || 01535 m_impl->type=="friend struct" || 01536 m_impl->type=="friend union" 01537 ) 01538 ); 01539 01540 return ((docFilter && staticFilter && privateFilter && friendCompoundFilter) /*|| inAnonymousScope*/); 01541 } 01542 01543 bool MemberDef::isDetailedSectionVisible(bool inGroup,bool inFile) const 01544 { 01545 bool groupFilter = getGroupDef()==0 || inGroup; 01546 bool fileFilter = getNamespaceDef()==0 || !inFile; 01547 01548 bool visible = isDetailedSectionLinkable() && groupFilter && fileFilter && 01549 !isReference(); 01550 //printf("MemberDef::isDetailedSectionVisible() %d\n",visible); 01551 return visible; 01552 } 01553 01557 void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, 01558 const char *scName, 01559 Definition *container, 01560 bool inGroup, 01561 bool showEnumValues 01562 ) 01563 { 01564 // if this member is in a group find the real scope name. 01565 bool hasParameterList = FALSE; 01566 bool inFile = container->definitionType()==Definition::TypeFile; 01567 bool hasDocs = isDetailedSectionVisible(inGroup,inFile); 01568 static bool separateMemPages = Config_getBool("SEPARATE_MEMBER_PAGES"); 01569 static bool optVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); 01570 //printf("MemberDef::writeDocumentation(): name=`%s' hasDocs=`%d' containerType=%d inGroup=%d\n", 01571 // name().data(),hasDocs,container->definitionType(),inGroup); 01572 if ( !hasDocs ) return; 01573 if (isEnumValue() && !showEnumValues) return; 01574 01575 makeResident(); 01576 LockingPtr<MemberDef> lock(this,this); 01577 01578 QCString scopeName = scName; 01579 QCString memAnchor = anchor(); 01580 QCString ciname = container->name(); 01581 if (container->definitionType()==TypeGroup) 01582 { 01583 if (getClassDef()) scopeName=getClassDef()->name(); 01584 else if (getNamespaceDef()) scopeName=getNamespaceDef()->name(); 01585 else if (getFileDef()) scopeName=getFileDef()->name(); 01586 ciname = ((GroupDef *)container)->groupTitle(); 01587 } 01588 else if (container->definitionType()==TypeFile && getNamespaceDef()) 01589 { // member is in a namespace, but is written as part of the file documentation 01590 // as well, so we need to make sure its label is unique. 01591 memAnchor.prepend("file_"); 01592 } 01593 01594 QCString cname = container->name(); 01595 QCString cfname = getOutputFileBase(); 01596 QCString cfiname = container->getOutputFileBase(); 01597 01598 // the next part is moved to declaration 01599 //if (isEnumerate() && name().at(0)=='@') 01600 //{ 01601 // // don't add to index 01602 //} 01603 //else 01604 //{ 01605 // Doxygen::indexList.addIndexItem( 01606 // ciname, // level1 01607 // name(), // level2 01608 // separateMemPages ? cfname : cfiname, // contRef 01609 // cfname, // memRef 01610 // memAnchor, // anchor 01611 // this); // memberdef 01612 //} 01613 01614 // get member name 01615 QCString doxyName=name(); 01616 // prepend scope if there is any. TODO: make this optional for C only docs 01617 if (scopeName) doxyName.prepend((QCString)scopeName+"::"); 01618 QCString doxyArgs=argsString(); 01619 01620 QCString ldef = definition(); 01621 //printf("member `%s' def=`%s'\n",name().data(),ldef.data()); 01622 if (isEnumerate()) 01623 { 01624 if (name().at(0)=='@') 01625 { 01626 ldef = "anonymous enum"; 01627 } 01628 else 01629 { 01630 ldef.prepend("enum "); 01631 } 01632 } 01633 else if (isEnumValue()) 01634 { 01635 if (ldef.at(0)=='@') 01636 { 01637 ldef=ldef.mid(2); 01638 } 01639 } 01640 int i=0,l; 01641 static QRegExp r("@[0-9]+"); 01642 01643 //---------------------------------------- 01644 01645 ol.pushGeneratorState(); 01646 01647 01648 if ((isVariable() || isTypedef()) && (i=r.match(ldef,0,&l))!=-1) 01649 { 01650 // find enum type and insert it in the definition 01651 MemberListIterator vmli(*ml); 01652 MemberDef *vmd; 01653 bool found=FALSE; 01654 for ( ; (vmd=vmli.current()) && !found ; ++vmli) 01655 { 01656 if (vmd->isEnumerate() && ldef.mid(i,l)==vmd->name()) 01657 { 01658 ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); 01659 ol.startMemberDoc(cname,name(),memAnchor,name()); 01660 linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.left(i)); 01661 vmd->writeEnumDeclaration(ol,getClassDef(),getNamespaceDef(),getFileDef(),getGroupDef()); 01662 linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.right(ldef.length()-i-l)); 01663 01664 found=TRUE; 01665 } 01666 } 01667 if (!found) // anonymous compound 01668 { 01669 //printf("Anonymous compound `%s'\n",cname.data()); 01670 ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); 01671 ol.startMemberDoc(cname,name(),memAnchor,name()); 01672 // strip anonymous compound names from definition 01673 int si=ldef.find(' '),pi,ei=i+l; 01674 if (si==-1) si=0; 01675 while ((pi=r.match(ldef,i+l,&l))!=-1) ei=i=pi+l; 01676 // first si characters of ldef contain compound type name 01677 ol.startMemberDocName(isObjCMethod()); 01678 ol.docify(ldef.left(si)); 01679 ol.docify(" { ... } "); 01680 // last ei characters of ldef contain pointer/reference specifiers 01681 int ni=ldef.find("::",si); 01682 if (ni>=ei) ei=ni+2; 01683 linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.right(ldef.length()-ei)); 01684 } 01685 } 01686 else // not an enum value 01687 { 01688 ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); 01689 ol.startMemberDoc(cname,name(),memAnchor,name()); 01690 01691 ClassDef *cd=getClassDef(); 01692 if (!Config_getBool("HIDE_SCOPE_NAMES")) 01693 { 01694 bool first=TRUE; 01695 if (m_impl->defTmpArgLists) 01696 // definition has explicit template parameter declarations 01697 { 01698 QListIterator<ArgumentList> ali(*m_impl->defTmpArgLists); 01699 ArgumentList *tal; 01700 for (ali.toFirst();(tal=ali.current());++ali) 01701 { 01702 if (tal->count()>0) 01703 { 01704 if (!first) ol.docify(" "); 01705 ol.startMemberDocPrefixItem(); 01706 writeTemplatePrefix(ol,tal); 01707 ol.endMemberDocPrefixItem(); 01708 } 01709 } 01710 } 01711 else // definition gets it template parameters from its class 01712 // (since no definition was found) 01713 { 01714 if (cd && !isTemplateSpecialization()) 01715 { 01716 QList<ArgumentList> tempParamLists; 01717 cd->getTemplateParameterLists(tempParamLists); 01718 //printf("#tempParamLists=%d\n",tempParamLists.count()); 01719 QListIterator<ArgumentList> ali(tempParamLists); 01720 ArgumentList *tal; 01721 for (ali.toFirst();(tal=ali.current());++ali) 01722 { 01723 if (tal->count()>0) 01724 { 01725 if (!first) ol.docify(" "); 01726 ol.startMemberDocPrefixItem(); 01727 writeTemplatePrefix(ol,tal); 01728 ol.endMemberDocPrefixItem(); 01729 } 01730 } 01731 } 01732 if (m_impl->tArgList) // function template prefix 01733 { 01734 ol.startMemberDocPrefixItem(); 01735 writeTemplatePrefix(ol,m_impl->tArgList); 01736 ol.endMemberDocPrefixItem(); 01737 } 01738 } 01739 } 01740 01741 ol.startMemberDocName(isObjCMethod()); 01742 if (cd && cd->isObjectiveC()) 01743 { 01744 // strip scope name 01745 int ep = ldef.find("::"); 01746 if (ep!=-1) 01747 { 01748 int sp=ldef.findRev(' ',ep); 01749 if (sp!=-1) 01750 { 01751 ldef=ldef.left(sp+1)+ldef.mid(ep+2); 01752 } 01753 } 01754 // strip keywords 01755 int dp = ldef.find(':'); 01756 if (dp!=-1) 01757 { 01758 ldef=ldef.left(dp+1); 01759 } 01760 int l=ldef.length(); 01761 //printf("start >%s<\n",ldef.data()); 01762 int i=l-1; 01763 while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--; 01764 while (i>=0 && isspace((uchar)ldef.at(i))) i--; 01765 if (i>0) 01766 { 01767 // insert braches around the type 01768 QCString tmp("("+ldef.left(i+1)+")"+ldef.mid(i+1)); 01769 ldef=tmp; 01770 } 01771 //printf("end >%s< i=%d\n",ldef.data(),i); 01772 if (isStatic()) ldef.prepend("+ "); else ldef.prepend("- "); 01773 } 01774 01775 if (optVhdl) 01776 { 01777 VhdlDocGen::writeVHDLTypeDocumentation(this,container,ol); 01778 } 01779 else 01780 { 01781 linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef); 01782 hasParameterList=writeDefArgumentList(ol,cd,scopeName,this); 01783 } 01784 01785 if (hasOneLineInitializer()) // add initializer 01786 { 01787 if (!isDefine()) 01788 { 01789 ol.docify(" = "); 01790 linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),m_impl->initializer.simplifyWhiteSpace()); 01791 } 01792 else 01793 { 01794 ol.writeNonBreakableSpace(3); 01795 linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),m_impl->initializer); 01796 } 01797 } 01798 if (excpString()) // add exception list 01799 { 01800 ol.docify(" "); 01801 linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),excpString()); 01802 } 01803 } 01804 01805 Specifier lvirt=virtualness(); 01806 01807 if (!isObjCMethod() && 01808 (protection()!=Public || lvirt!=Normal || 01809 isFriend() || isRelated() || 01810 (isInline() && Config_getBool("INLINE_INFO")) || 01811 isSignal() || isSlot() || 01812 isStatic() || (m_impl->classDef && m_impl->classDef!=container) || 01813 (m_impl->memSpec & ~Entry::Inline)!=0 01814 ) 01815 ) 01816 { 01817 // write the member specifier list 01818 ol.writeLatexSpacing(); 01819 ol.startTypewriter(); 01820 ol.docify(" ["); 01821 QStrList sl; 01822 if (optVhdl) 01823 { 01824 sl.append(VhdlDocGen::trTypeString(getMemberSpecifiers())); 01825 } 01826 else 01827 { 01828 if (isFriend()) sl.append("friend"); 01829 else if (isRelated()) sl.append("related"); 01830 else 01831 { 01832 if (Config_getBool("INLINE_INFO") && isInline()) sl.append("inline"); 01833 if (isExplicit()) sl.append("explicit"); 01834 if (isMutable()) sl.append("mutable"); 01835 if (isStatic()) sl.append("static"); 01836 if (isGettable()) sl.append("get"); 01837 if (isSettable()) sl.append("set"); 01838 if (isAddable()) sl.append("add"); 01839 if (isRemovable()) sl.append("remove"); 01840 if (isRaisable()) sl.append("raise"); 01841 if (isReadable()) sl.append("read"); 01842 if (isWritable()) sl.append("write"); 01843 if (isFinal()) sl.append("final"); 01844 if (isAbstract()) sl.append("abstract"); 01845 if (isOverride()) sl.append("override"); 01846 if (isInitonly()) sl.append("initonly"); 01847 if (isSealed()) sl.append("sealed"); 01848 if (isNew()) sl.append("new"); 01849 if (isOptional()) sl.append("optional"); 01850 if (isRequired()) sl.append("required"); 01851 if (isAssign()) sl.append("assign"); 01852 else if (isCopy()) sl.append("copy"); 01853 else if (isRetain()) sl.append("retain"); 01854 if (protection()==Protected) sl.append("protected"); 01855 else if (protection()==Private) sl.append("private"); 01856 else if (protection()==Package) sl.append("package"); 01857 if (lvirt==Virtual) sl.append("virtual"); 01858 else if (lvirt==Pure) sl.append("pure virtual"); 01859 if (isSignal()) sl.append("signal"); 01860 if (isSlot()) sl.append("slot"); 01861 } 01862 if (m_impl->classDef && m_impl->classDef!=container) sl.append("inherited"); 01863 } 01864 const char *s=sl.first(); 01865 while (s) 01866 { 01867 ol.docify(s); 01868 s=sl.next(); 01869 if (s) ol.docify(", "); 01870 } 01871 ol.docify("]"); 01872 ol.endTypewriter(); 01873 } 01874 else if (isObjCMethod() && isImplementation()) 01875 { 01876 ol.writeLatexSpacing(); 01877 ol.startTypewriter(); 01878 ol.docify(" [implementation]"); 01879 ol.endTypewriter(); 01880 } 01881 if (hasParameterList) 01882 { 01883 ol.endParameterList(); 01884 ol.endMemberDoc(TRUE); 01885 } 01886 else 01887 { 01888 ol.endMemberDocName(); 01889 ol.endMemberDoc(FALSE); 01890 } 01891 ol.endDoxyAnchor(cfname,memAnchor); 01892 ol.startIndent(); 01893 01894 ol.pushGeneratorState(); 01895 ol.disable(OutputGenerator::RTF); 01896 ol.newParagraph(); 01897 ol.popGeneratorState(); 01898 01899 /* write multi-line initializer (if any) */ 01900 if (hasMultiLineInitializer() 01901 //initLines>0 && ((initLines<maxInitLines && userInitLines==-1) // implicitly enabled 01902 // || initLines<userInitLines // explicitly enabled 01903 // ) 01904 ) 01905 { 01906 //printf("md=%s initLines=%d init=`%s'\n",name().data(),initLines,init.data()); 01907 ol.startBold(); 01908 if (m_impl->mtype==Define) 01909 ol.parseText(theTranslator->trDefineValue()); 01910 else 01911 ol.parseText(theTranslator->trInitialValue()); 01912 ol.endBold(); 01913 ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); 01914 pIntf->resetCodeParserState(); 01915 ol.startCodeFragment(); 01916 pIntf->parseCode(ol,scopeName,m_impl->initializer,FALSE,0); 01917 ol.endCodeFragment(); 01918 } 01919 01920 QCString brief = briefDescription(); 01921 QCString detailed = documentation(); 01922 LockingPtr<ArgumentList> docArgList = LockingPtr<ArgumentList>(this,m_impl->defArgList); 01923 if (m_impl->templateMaster) 01924 { 01925 brief = m_impl->templateMaster->briefDescription(); 01926 detailed = m_impl->templateMaster->documentation(); 01927 docArgList = m_impl->templateMaster->argumentList(); 01928 } 01929 01930 /* write brief description */ 01931 if (!brief.isEmpty() && 01932 (Config_getBool("REPEAT_BRIEF") || 01933 !Config_getBool("BRIEF_MEMBER_DESC") 01934 ) 01935 ) 01936 { 01937 ol.parseDoc(briefFile(),briefLine(),getOuterScope()?getOuterScope():container,this,brief,FALSE,FALSE); 01938 ol.newParagraph(); 01939 } 01940 01941 /* write detailed description */ 01942 if (!detailed.isEmpty() || !m_impl->inbodyDocs.isEmpty()) 01943 { 01944 ol.parseDoc(docFile(),docLine(),getOuterScope()?getOuterScope():container,this,detailed+"\n",TRUE,FALSE); 01945 if (!m_impl->inbodyDocs.isEmpty()) 01946 { 01947 ol.newParagraph(); 01948 ol.parseDoc(inbodyFile(),inbodyLine(),getOuterScope()?getOuterScope():container,this,m_impl->inbodyDocs+"\n",TRUE,FALSE); 01949 } 01950 } 01951 else if (!brief.isEmpty() && (Config_getBool("REPEAT_BRIEF") || 01952 !Config_getBool("BRIEF_MEMBER_DESC"))) 01953 { 01954 if (!m_impl->inbodyDocs.isEmpty()) 01955 { 01956 ol.newParagraph(); 01957 ol.parseDoc(inbodyFile(),inbodyLine(),getOuterScope()?getOuterScope():container,this,m_impl->inbodyDocs+"\n",TRUE,FALSE); 01958 } 01959 } 01960 01961 01962 //printf("***** defArgList=%p name=%s docs=%s hasDocs=%d\n", 01963 // defArgList, 01964 // defArgList?defArgList->hasDocumentation():-1); 01965 if (docArgList!=0 && docArgList->hasDocumentation()) 01966 { 01967 //printf("***** argumentList is documented\n"); 01968 ol.startParamList(BaseOutputDocInterface::Param,theTranslator->trParameters()+": "); 01969 ol.writeDescItem(); 01970 ol.startDescTable(); 01971 ArgumentListIterator ali(*docArgList); 01972 Argument *a; 01973 for (ali.toFirst();(a=ali.current());++ali) 01974 { 01975 if (a->hasDocumentation()) 01976 { 01977 ol.startDescTableTitle(); 01978 ol.docify(a->name); 01979 ol.endDescTableTitle(); 01980 ol.startDescTableData(); 01981 ol.parseDoc(docFile(),docLine(), 01982 getOuterScope()?getOuterScope():container, 01983 this, // memberDef 01984 a->docs+"\n", // docStr 01985 TRUE, // indexWords 01986 FALSE // isExample 01987 ); 01988 ol.endDescTableData(); 01989 } 01990 } 01991 ol.endDescTable(); 01992 ol.endParamList(); 01993 } 01994 01995 // For enum, we also write the documented enum values 01996 if (isEnumerate()) 01997 { 01998 bool first=TRUE; 01999 LockingPtr<MemberList> fmdl=enumFieldList(); 02000 if (fmdl!=0) 02001 { 02002 MemberDef *fmd=fmdl->first(); 02003 while (fmd) 02004 { 02005 if (fmd->isLinkable()) 02006 { 02007 if (first) 02008 { 02009 //ol.newParagraph(); 02010 ol.startSimpleSect(BaseOutputDocInterface::EnumValues,0,0,theTranslator->trEnumerationValues()+": "); 02011 ol.writeDescItem(); 02012 ol.startDescTable(); 02013 } 02014 02015 ol.addIndexItem(fmd->name(),cname); 02016 ol.addIndexItem(cname,fmd->name()); 02017 02018 //if (hasHtmlHelp) 02019 //{ 02020 // htmlHelp->addIndexItem(ciname, // level1 02021 // fmd->name(), // level2 02022 // separateMemPages ? cfname : cfiname, // contRef 02023 // cfname, // memRef 02024 // fmd->anchor()); // anchor 02025 //} 02026 Doxygen::indexList.addIndexItem( 02027 ciname, // level1 02028 fmd->name(), // level2 02029 separateMemPages ? cfname : cfiname, // contRef 02030 cfname, // memRef 02031 fmd->anchor(), // anchor 02032 fmd); // memberdef 02033 //ol.writeListItem(); 02034 ol.startDescTableTitle(); // this enables emphasis! 02035 ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString()); 02036 first=FALSE; 02037 //ol.startEmphasis(); 02038 ol.docify(fmd->name()); 02039 //ol.endEmphasis(); 02040 ol.disableAllBut(OutputGenerator::Man); 02041 ol.writeString(" "); 02042 ol.enableAll(); 02043 ol.endDoxyAnchor(cfname,fmd->anchor()); 02044 ol.endDescTableTitle(); 02045 //ol.newParagraph(); 02046 ol.startDescTableData(); 02047 02048 if (!fmd->briefDescription().isEmpty()) 02049 { 02050 ol.parseDoc(fmd->briefFile(),fmd->briefLine(),getOuterScope()?getOuterScope():container,fmd,fmd->briefDescription(),TRUE,FALSE); 02051 //ol.newParagraph(); 02052 } 02053 if (!fmd->briefDescription().isEmpty() && 02054 !fmd->documentation().isEmpty()) 02055 { 02056 ol.newParagraph(); 02057 } 02058 if (!fmd->documentation().isEmpty()) 02059 { 02060 ol.parseDoc(fmd->docFile(),fmd->docLine(),getOuterScope()?getOuterScope():container,fmd,fmd->documentation()+"\n",TRUE,FALSE); 02061 } 02062 ol.endDescTableData(); 02063 } 02064 fmd=fmdl->next(); 02065 } 02066 } 02067 if (!first) 02068 { 02069 //ol.endItemList(); 02070 ol.endDescTable(); 02071 ol.endSimpleSect(); 02072 ol.writeChar('\n'); 02073 } 02074 } 02075 02076 MemberDef *bmd=reimplements(); 02077 ClassDef *bcd=0; 02078 if (bmd && (bcd=bmd->getClassDef())) 02079 { 02080 // write class that contains a member that is reimplemented by this one 02081 if (bcd->isLinkable()) 02082 { 02083 ol.startParagraph(); 02084 QCString reimplFromLine; 02085 if (bmd->virtualness()!=Pure && bcd->compoundType()!=ClassDef::Interface) 02086 { 02087 reimplFromLine = theTranslator->trReimplementedFromList(1); 02088 } 02089 else 02090 { 02091 reimplFromLine = theTranslator->trImplementedFromList(1); 02092 } 02093 int markerPos = reimplFromLine.find("@0"); 02094 if (markerPos!=-1) // should always pass this. 02095 { 02096 ol.parseText(reimplFromLine.left(markerPos)); //text left from marker 02097 if (bmd->isLinkable()) // replace marker with link 02098 { 02099 //Definition *bd=bmd->group; 02100 //if (bd==0) bd=bcd; 02101 ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(), 02102 bmd->anchor(),bcd->displayName()); 02103 02104 //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), 02105 // bmd->anchor(),bcd->name()); 02106 if ( bmd->isLinkableInProject() ) 02107 { 02108 writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor()); 02109 } 02110 } 02111 else 02112 { 02113 ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), 02114 0,bcd->displayName()); 02115 if (bcd->isLinkableInProject()/* && !Config_getBool("PDF_HYPERLINKS")*/ ) 02116 { 02117 writePageRef(ol,bcd->getOutputFileBase(),0); 02118 } 02119 } 02120 ol.parseText(reimplFromLine.right( 02121 reimplFromLine.length()-markerPos-2)); // text right from marker 02122 02123 } 02124 else 02125 { 02126 err("Error: translation error: no marker in trReimplementsFromList()\n"); 02127 } 02128 ol.endParagraph(); 02129 } 02130 02131 //ol.writeString("."); 02132 } 02133 02134 LockingPtr<MemberList> bml=reimplementedBy(); 02135 if (bml!=0) 02136 { 02137 MemberListIterator mli(*bml); 02138 MemberDef *bmd=0; 02139 uint count=0; 02140 ClassDef *bcd=0; 02141 for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->getClassDef());++mli) 02142 { 02143 // count the members that directly inherit from md and for 02144 // which the member and class are visible in the docs. 02145 if ( bmd->isLinkable() && bcd->isLinkable() ) 02146 { 02147 count++; 02148 } 02149 } 02150 if (count>0) 02151 { 02152 mli.toFirst(); 02153 // write the list of classes that overwrite this member 02154 ol.startParagraph(); 02155 02156 QCString reimplInLine; 02157 if (m_impl->virt==Pure || (m_impl->classDef && m_impl->classDef->compoundType()==ClassDef::Interface)) 02158 { 02159 reimplInLine = theTranslator->trImplementedInList(count); 02160 } 02161 else 02162 { 02163 reimplInLine = theTranslator->trReimplementedInList(count); 02164 } 02165 static QRegExp marker("@[0-9]+"); 02166 int index=0,newIndex,matchLen; 02167 // now replace all markers in reimplInLine with links to the classes 02168 while ((newIndex=marker.match(reimplInLine,index,&matchLen))!=-1) 02169 { 02170 ol.parseText(reimplInLine.mid(index,newIndex-index)); 02171 bool ok; 02172 uint entryIndex = reimplInLine.mid(newIndex+1,matchLen-1).toUInt(&ok); 02173 //bmd=bml->at(entryIndex); 02174 02175 count=0; 02176 // find the entryIndex-th documented entry in the inheritance list. 02177 for (mli.toLast();(bmd=mli.current()) && (bcd=bmd->getClassDef());--mli) 02178 { 02179 if ( bmd->isLinkable() && bcd->isLinkable()) 02180 { 02181 if (count==entryIndex) break; 02182 count++; 02183 } 02184 } 02185 02186 if (ok && bcd && bmd) // write link for marker 02187 { 02188 //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), 02189 // bmd->anchor(),bcd->name()); 02190 ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(), 02191 bmd->anchor(),bcd->displayName()); 02192 02193 if (bmd->isLinkableInProject() ) 02194 { 02195 writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor()); 02196 } 02197 } 02198 ++mli; 02199 index=newIndex+matchLen; 02200 } 02201 ol.parseText(reimplInLine.right(reimplInLine.length()-index)); 02202 ol.endParagraph(); 02203 } 02204 } 02205 02206 // write the list of examples that use this member 02207 if (hasExamples()) 02208 { 02209 ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": "); 02210 ol.writeDescItem(); 02211 writeExample(ol,m_impl->exampleSDict); 02212 //ol.endDescItem(); 02213 ol.endSimpleSect(); 02214 } 02215 02216 if (m_impl->typeConstraints) 02217 { 02218 writeTypeConstraints(ol,this,m_impl->typeConstraints); 02219 } 02220 02221 // write reference to the source 02222 writeSourceDef(ol,cname); 02223 writeSourceRefs(ol,cname); 02224 writeSourceReffedBy(ol,cname); 02225 writeInlineCode(ol,cname); 02226 02227 // write call graph 02228 if ((m_impl->hasCallGraph || Config_getBool("CALL_GRAPH")) 02229 && isFunction() && Config_getBool("HAVE_DOT") 02230 ) 02231 { 02232 DotCallGraph callGraph(this,FALSE); 02233 if (!callGraph.isTrivial() && !callGraph.isTooBig()) 02234 { 02235 msg("Generating call graph for function %s\n",qualifiedName().data()); 02236 ol.disable(OutputGenerator::Man); 02237 ol.newParagraph(); 02238 ol.startCallGraph(); 02239 ol.parseText(theTranslator->trCallGraph()); 02240 ol.endCallGraph(callGraph); 02241 ol.enableAll(); 02242 } 02243 } 02244 if ((m_impl->hasCallerGraph || Config_getBool("CALLER_GRAPH")) 02245 && isFunction() && Config_getBool("HAVE_DOT") 02246 ) 02247 { 02248 DotCallGraph callerGraph(this, TRUE); 02249 if (!callerGraph.isTrivial() && !callerGraph.isTooBig()) 02250 { 02251 msg("Generating caller graph for function %s\n",qualifiedName().data()); 02252 ol.disable(OutputGenerator::Man); 02253 ol.newParagraph(); 02254 ol.startCallGraph(); 02255 ol.parseText(theTranslator->trCallerGraph()); 02256 ol.endCallGraph(callerGraph); 02257 ol.enableAll(); 02258 } 02259 } 02260 02261 if (Doxygen::userComments) 02262 { 02263 ol.pushGeneratorState(); 02264 ol.disableAllBut(OutputGenerator::Html); 02265 QCString cmd = "<? $root=$_SERVER['DOCUMENT_ROOT']; " 02266 "passthru(\"$root/doxynotes --lookup "+ 02267 getOutputFileBase()+":"+anchor()+"\") ?>"; 02268 ol.writeString(cmd); 02269 ol.popGeneratorState(); 02270 } 02271 02272 ol.endIndent(); 02273 02274 // enable LaTeX again 02275 //if (Config_getBool("EXTRACT_ALL") && !hasDocs) ol.enable(OutputGenerator::Latex); 02276 ol.popGeneratorState(); 02277 02278 //------------------------------------------------ 02279 02280 if (!Config_getBool("EXTRACT_ALL") && 02281 Config_getBool("WARN_IF_UNDOCUMENTED") && 02282 Config_getBool("WARN_NO_PARAMDOC") && 02283 !Doxygen::suppressDocWarnings) 02284 { 02285 if (!hasDocumentedParams()) 02286 { 02287 warn_doc_error(docFile(),docLine(), 02288 "Warning: parameters of member %s are not (all) documented", 02289 qualifiedName().data()); 02290 } 02291 if (!hasDocumentedReturnType()) 02292 { 02293 warn_doc_error(docFile(),docLine(), 02294 "Warning: return type of member %s is not documented", 02295 qualifiedName().data()); 02296 } 02297 } 02298 02299 } 02300 02301 QCString MemberDef::memberTypeName() const 02302 { 02303 makeResident(); 02304 switch (m_impl->mtype) 02305 { 02306 case Define: return "define"; 02307 case Function: return "function"; 02308 case Variable: return "variable"; 02309 case Typedef: return "typedef"; 02310 case Enumeration: return "enumeration"; 02311 case EnumValue: return "enumvalue"; 02312 case Prototype: return "prototype"; 02313 case Signal: return "signal"; 02314 case Slot: return "slot"; 02315 case Friend: return "friend"; 02316 case DCOP: return "dcop"; 02317 case Property: return "property"; 02318 case Event: return "event"; 02319 default: return "unknown"; 02320 } 02321 } 02322 02323 void MemberDef::warnIfUndocumented() 02324 { 02325 makeResident(); 02326 if (m_impl->memberGroup) return; 02327 ClassDef *cd = getClassDef(); 02328 NamespaceDef *nd = getNamespaceDef(); 02329 FileDef *fd = getFileDef(); 02330 GroupDef *gd = getGroupDef(); 02331 Definition *d=0; 02332 const char *t=0; 02333 if (cd) 02334 t="class", d=cd; 02335 else if (nd) 02336 t="namespace", d=nd; 02337 else if (gd) 02338 t="group", d=gd; 02339 else 02340 t="file", d=fd; 02341 static bool extractAll = Config_getBool("EXTRACT_ALL"); 02342 02343 //printf("warnIfUndoc: d->isLinkable()=%d isLinkable()=%d " 02344 // "isDocumentedFriendClass()=%d name()=%s prot=%d\n", 02345 // d->isLinkable(),isLinkable(),isDocumentedFriendClass(), 02346 // name().data(),prot); 02347 if ((!hasUserDocumentation() && !extractAll) && 02348 !isFriendClass() && 02349 name().find('@')==-1 && d->name().find('@')==-1 && 02350 (m_impl->prot!=Private || Config_getBool("EXTRACT_PRIVATE")) 02351 ) 02352 { 02353 warn_undoc(getDefFileName(),getDefLine(),"Warning: Member %s%s (%s) of %s %s is not documented.", 02354 name().data(),argsString()?argsString():"",memberTypeName().data(),t,d->name().data()); 02355 } 02356 } 02357 02358 02359 02360 bool MemberDef::isFriendClass() const 02361 { 02362 makeResident(); 02363 return (isFriend() && 02364 (m_impl->type=="friend class" || m_impl->type=="friend struct" || 02365 m_impl->type=="friend union")); 02366 } 02367 02368 bool MemberDef::isDocumentedFriendClass() const 02369 { 02370 makeResident(); 02371 ClassDef *fcd=0; 02372 QCString baseName=name(); 02373 int i=baseName.find('<'); 02374 if (i!=-1) baseName=baseName.left(i); 02375 return (isFriendClass() && 02376 (fcd=getClass(baseName)) && fcd->isLinkable()); 02377 } 02378 02379 bool MemberDef::hasDocumentation() const 02380 { 02381 makeResident(); 02382 return Definition::hasDocumentation() || 02383 !m_impl->inbodyDocs.isEmpty() || 02384 (m_impl->mtype==Enumeration && m_impl->docEnumValues) || // has enum values 02385 (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation()); // has doc arguments 02386 } 02387 02388 bool MemberDef::hasUserDocumentation() const 02389 { 02390 bool hasDocs = Definition::hasUserDocumentation() || 02391 (m_impl->inbodyDocs && !m_impl->inbodyDocs.isEmpty()); 02392 return hasDocs; 02393 } 02394 02395 02396 void MemberDef::setMemberGroup(MemberGroup *grp) 02397 { 02398 makeResident(); 02399 m_impl->memberGroup = grp; 02400 } 02401 02402 bool MemberDef::visibleMemberGroup(bool hideNoHeader) 02403 { 02404 makeResident(); 02405 return m_impl->memberGroup!=0 && 02406 (!hideNoHeader || m_impl->memberGroup->header()!="[NOHEADER]"); 02407 } 02408 02409 QCString MemberDef::getScopeString() const 02410 { 02411 makeResident(); 02412 QCString result; 02413 if (getClassDef()) result=getClassDef()->displayName(); 02414 else if (getNamespaceDef()) result=getNamespaceDef()->displayName(); 02415 return result; 02416 } 02417 02418 #if 0 02419 static QCString escapeAnchor(const QCString &anchor) 02420 { 02421 QCString result; 02422 int l = anchor.length(),i; 02423 for (i=0;i<l;i++) 02424 { 02425 char c = anchor.at(i); 02426 if ((c>='a' && c<='z') || (c>='A' && c<='Z')) 02427 { 02428 result+=c; 02429 } 02430 else 02431 { 02432 static char hexStr[]="0123456789ABCDEF"; 02433 char escChar[]={ '_', 0, 0, 0 }; 02434 escChar[1]=hexStr[c>>4]; 02435 escChar[2]=hexStr[c&0xf]; 02436 result+=escChar; 02437 } 02438 } 02439 return result; 02440 } 02441 #endif 02442 02443 void MemberDef::setAnchor(const char *a) 02444 { 02445 makeResident(); 02446 //anc=a; 02447 a=a; 02448 QCString memAnchor = name(); 02449 if (!m_impl->args.isEmpty()) memAnchor+=m_impl->args; 02450 02451 // include definition as well, to distinguish between two template 02452 // specializations that only differ in the template parameters. 02453 memAnchor.prepend(definition()); 02454 02455 // convert to md5 hash 02456 uchar md5_sig[16]; 02457 QCString sigStr(33); 02458 MD5Buffer((const unsigned char *)memAnchor.data(),memAnchor.length(),md5_sig); 02459 MD5SigToString(md5_sig,sigStr.data(),33); 02460 m_impl->anc = sigStr; 02461 } 02462 02463 void MemberDef::setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, 02464 const QCString &fileName,int startLine, 02465 bool hasDocs,MemberDef *member) 02466 { 02467 //printf("%s MemberDef::setGroupDef(%s)\n",name().data(),gd->name().data()); 02468 makeResident(); 02469 m_impl->group=gd; 02470 m_impl->grouppri=pri; 02471 m_impl->groupFileName=fileName; 02472 m_impl->groupStartLine=startLine; 02473 m_impl->groupHasDocs=hasDocs; 02474 m_impl->groupMember=member; 02475 } 02476 02477 void MemberDef::setEnumScope(MemberDef *md) 02478 { 02479 makeResident(); 02480 m_impl->enumScope=md; 02481 if (md->getGroupDef()) 02482 { 02483 m_impl->group=md->getGroupDef(); 02484 m_impl->grouppri=md->getGroupPri(); 02485 m_impl->groupFileName=md->getGroupFileName(); 02486 m_impl->groupStartLine=md->getGroupStartLine(); 02487 m_impl->groupHasDocs=md->getGroupHasDocs(); 02488 } 02489 } 02490 02491 void MemberDef::setMemberClass(ClassDef *cd) 02492 { 02493 makeResident(); 02494 m_impl->classDef=cd; 02495 setOuterScope(cd); 02496 } 02497 02498 void MemberDef::setNamespace(NamespaceDef *nd) 02499 { 02500 makeResident(); 02501 m_impl->nspace=nd; 02502 setOuterScope(nd); 02503 } 02504 02505 MemberDef *MemberDef::createTemplateInstanceMember( 02506 ArgumentList *formalArgs,ArgumentList *actualArgs) 02507 { 02508 makeResident(); 02509 LockingPtr<MemberDef> lock(this,this); 02510 //printf(" Member %s %s %s\n",typeString(),name().data(),argsString()); 02511 ArgumentList *actualArgList = 0; 02512 if (m_impl->defArgList) 02513 { 02514 actualArgList = new ArgumentList; 02515 ArgumentListIterator ali(*m_impl->defArgList); 02516 Argument *arg; 02517 for (;(arg=ali.current());++ali) 02518 { 02519 Argument *actArg = new Argument(*arg); 02520 actArg->type = substituteTemplateArgumentsInString(actArg->type,formalArgs,actualArgs); 02521 actualArgList->append(actArg); 02522 } 02523 actualArgList->constSpecifier = m_impl->defArgList->constSpecifier; 02524 actualArgList->volatileSpecifier = m_impl->defArgList->volatileSpecifier; 02525 actualArgList->pureSpecifier = m_impl->defArgList->pureSpecifier; 02526 } 02527 02528 QCString methodName=name(); 02529 if (methodName.left(9)=="operator ") // conversion operator 02530 { 02531 methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs); 02532 } 02533 02534 MemberDef *imd = new MemberDef( 02535 getDefFileName(),getDefLine(), 02536 substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs), 02537 methodName, 02538 substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs), 02539 m_impl->exception, m_impl->prot, 02540 m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, 0, 0 02541 ); 02542 imd->setArgumentList(actualArgList); 02543 imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs)); 02544 imd->setBodyDef(getBodyDef()); 02545 imd->setBodySegment(getStartBodyLine(),getEndBodyLine()); 02546 //imd->setBodyMember(this); 02547 02548 // TODO: init other member variables (if needed). 02549 // TODO: reimplemented info 02550 return imd; 02551 } 02552 02553 bool MemberDef::hasOneLineInitializer() const 02554 { 02555 makeResident(); 02556 //printf("%s: init=%s, initLines=%d maxInitLines=%d userInitLines=%d\n", 02557 // name().data(),m_impl->initializer.data(),m_impl->initLines, 02558 // m_impl->maxInitLines,m_impl->userInitLines); 02559 return !m_impl->initializer.isEmpty() && m_impl->initLines==0 && // one line initializer 02560 ((m_impl->maxInitLines>0 && m_impl->userInitLines==-1) || m_impl->userInitLines>0); // enabled by default or explicitly 02561 } 02562 02563 bool MemberDef::hasMultiLineInitializer() const 02564 { 02565 makeResident(); 02566 //printf("initLines=%d userInitLines=%d maxInitLines=%d\n", 02567 // initLines,userInitLines,maxInitLines); 02568 return m_impl->initLines>0 && 02569 ((m_impl->initLines<m_impl->maxInitLines && m_impl->userInitLines==-1) // implicitly enabled 02570 || m_impl->initLines<m_impl->userInitLines // explicitly enabled 02571 ); 02572 } 02573 02574 void MemberDef::setInitializer(const char *initializer) 02575 { 02576 makeResident(); 02577 m_impl->initializer=initializer; 02578 int p=m_impl->initializer.length()-1; 02579 while (p>=0 && isspace((uchar)m_impl->initializer.at(p))) p--; 02580 m_impl->initializer=m_impl->initializer.left(p+1); 02581 m_impl->initLines=m_impl->initializer.contains('\n'); 02582 } 02583 02584 void MemberDef::addListReference(Definition *) 02585 { 02586 makeResident(); 02587 static bool optimizeOutputForC = Config_getBool("OPTIMIZE_OUTPUT_FOR_C"); 02588 static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES"); 02589 static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); 02590 static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); 02591 visited=TRUE; 02592 if (!isLinkableInProject()) return; 02593 QCString memLabel; 02594 if (optimizeOutputForC) 02595 { 02596 memLabel=theTranslator->trGlobal(TRUE,TRUE); 02597 } 02598 else if (fortranOpt) 02599 { 02600 memLabel=theTranslator->trSubprogram(TRUE,TRUE); 02601 } 02602 else 02603 { 02604 memLabel=theTranslator->trMember(TRUE,TRUE); 02605 } 02606 QCString memName = name(); 02607 Definition *pd=getOuterScope(); 02608 QCString memArgs; 02609 if (!isRelated() && 02610 ( 02611 (!hideScopeNames && // there is a scope 02612 pd && pd!=Doxygen::globalScope) // and we can show it 02613 || 02614 (pd=getClassDef()) // it's a class so we 02615 // show the scope anyway 02616 ) 02617 ) 02618 { 02619 if (isObjCMethod()) 02620 { 02621 memName = "[" + pd->name() + " " + name() + "]"; 02622 } 02623 else if (optimizeOutputJava) 02624 { 02625 memName.prepend(pd->name()+"."); 02626 memArgs = argsString(); 02627 } 02628 else 02629 { 02630 memName.prepend(pd->name()+"::"); 02631 memArgs = argsString(); 02632 } 02633 } 02634 LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems(); 02635 if (xrefItems!=0) 02636 { 02637 addRefItem(xrefItems.pointer(),memLabel, 02638 getOutputFileBase()+"#"+anchor(),memName,memArgs); 02639 } 02640 } 02641 02642 MemberList *MemberDef::getSectionList(Definition *d) const 02643 { 02644 makeResident(); 02645 char key[20]; 02646 sprintf(key,"%p",d); 02647 return (d!=0 && m_impl->classSectionSDict) ? m_impl->classSectionSDict->find(key) : 0; 02648 } 02649 02650 void MemberDef::setSectionList(Definition *d, MemberList *sl) 02651 { 02652 makeResident(); 02653 //printf("MemberDef::setSectionList(%p,%p) name=%s\n",d,sl,name().data()); 02654 char key[20]; 02655 sprintf(key,"%p",d); 02656 if (m_impl->classSectionSDict==0) 02657 { 02658 m_impl->classSectionSDict = new SDict<MemberList>(7); 02659 } 02660 m_impl->classSectionSDict->append(key,sl); 02661 } 02662 02663 Specifier MemberDef::virtualness(int count) const 02664 { 02665 if (count>25) 02666 { 02667 warn(getDefFileName(),getDefLine(), 02668 "Warning: Internal inconsistency: recursion detected in overload relation for member %s!" 02669 ,name().data() 02670 ); 02671 return Normal; 02672 } 02673 makeResident(); 02674 Specifier v = m_impl->virt; 02675 MemberDef *rmd = reimplements(); 02676 while (rmd && v==Normal) 02677 { 02678 v = rmd->virtualness(count+1)==Normal ? Normal : Virtual; 02679 rmd = rmd->reimplements(); 02680 } 02681 return v; 02682 } 02683 02684 bool MemberDef::isConstructor() const 02685 { 02686 makeResident(); 02687 if (m_impl->classDef) 02688 { 02689 if (m_impl->isDMember) // for D 02690 { 02691 return name()=="this"; 02692 } 02693 else if (m_impl->fileDef && 02694 getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_PHP) 02695 { // for PHP 02696 return name()=="__construct"; 02697 } 02698 else // for other languages 02699 { 02700 QCString locName = m_impl->classDef->localName(); 02701 int i=locName.find('<'); 02702 if (i==-1) // not a template class 02703 { 02704 return name()==locName; 02705 } 02706 else 02707 { 02708 return name()==locName.left(i); 02709 } 02710 } 02711 } 02712 else 02713 return FALSE; 02714 } 02715 02716 bool MemberDef::isDestructor() const 02717 { 02718 makeResident(); 02719 if (m_impl->isDMember) // for D 02720 { 02721 return name()=="~this"; 02722 } 02723 else if (m_impl->fileDef && 02724 getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_PHP) 02725 { // for PHP 02726 return name()=="__destruct"; 02727 } 02728 else // other languages 02729 { 02730 return (name().find('~')!=-1 || name().find('!')!=-1) // The ! is for C++/CLI 02731 && name().find("operator")==-1; 02732 } 02733 } 02734 02735 void MemberDef::writeEnumDeclaration(OutputList &typeDecl, 02736 ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd) 02737 { 02738 makeResident(); 02739 LockingPtr<MemberDef> lock(this,this); 02740 int enumMemCount=0; 02741 02742 QList<MemberDef> *fmdl=m_impl->enumFields; 02743 uint numVisibleEnumValues=0; 02744 if (fmdl) 02745 { 02746 MemberDef *fmd=fmdl->first(); 02747 while (fmd) 02748 { 02749 if (fmd->isBriefSectionVisible()) numVisibleEnumValues++; 02750 fmd=fmdl->next(); 02751 } 02752 } 02753 if (numVisibleEnumValues==0 && !isBriefSectionVisible()) 02754 { 02755 return; 02756 } 02757 02758 QCString n = name(); 02759 int i=n.findRev("::"); 02760 if (i!=-1) n=n.right(n.length()-i-2); // strip scope (TODO: is this needed?) 02761 if (n[0]!='@') // not an anonymous enum 02762 { 02763 if (isLinkableInProject() || hasDocumentedEnumValues()) 02764 { 02765 if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !isReference()) 02766 { 02767 Doxygen::tagFile << " <member kind=\"enumeration\">" << endl; 02768 Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; 02769 Doxygen::tagFile << " <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl; 02770 Doxygen::tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>" << endl; 02771 Doxygen::tagFile << " <arglist>" << convertToXML(argsString()) << "</arglist>" << endl; 02772 Doxygen::tagFile << " </member>" << endl; 02773 } 02774 writeLink(typeDecl,cd,nd,fd,gd); 02775 } 02776 else 02777 { 02778 typeDecl.startBold(); 02779 typeDecl.docify(n); 02780 typeDecl.endBold(); 02781 } 02782 typeDecl.writeChar(' '); 02783 } 02784 02785 if (numVisibleEnumValues>0) 02786 { 02787 uint enumValuesPerLine = (uint)Config_getInt("ENUM_VALUES_PER_LINE"); 02788 if (enumValuesPerLine==0) enumValuesPerLine=1; 02789 typeDecl.docify("{ "); 02790 if (fmdl) 02791 { 02792 MemberDef *fmd=fmdl->first(); 02793 bool fmdVisible = fmd->isBriefSectionVisible(); 02794 while (fmd) 02795 { 02796 if (fmdVisible) 02797 { 02798 /* in html we start a new line after a number of items */ 02799 if (numVisibleEnumValues>enumValuesPerLine 02800 && (enumMemCount%enumValuesPerLine)==0 02801 ) 02802 { 02803 typeDecl.pushGeneratorState(); 02804 typeDecl.disableAllBut(OutputGenerator::Html); 02805 typeDecl.enable(OutputGenerator::Latex); 02806 typeDecl.lineBreak(); 02807 typeDecl.disable(OutputGenerator::Latex); 02808 typeDecl.writeString(" "); 02809 typeDecl.popGeneratorState(); 02810 } 02811 02812 if (fmd->hasDocumentation()) // enum value has docs 02813 { 02814 if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !fmd->isReference()) 02815 { 02816 Doxygen::tagFile << " <member kind=\"enumvalue\">" << endl; 02817 Doxygen::tagFile << " <name>" << convertToXML(fmd->name()) << "</name>" << endl; 02818 Doxygen::tagFile << " <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl; 02819 Doxygen::tagFile << " <anchor>" << convertToXML(fmd->anchor()) << "</anchor>" << endl; 02820 Doxygen::tagFile << " <arglist>" << convertToXML(fmd->argsString()) << "</arglist>" << endl; 02821 Doxygen::tagFile << " </member>" << endl; 02822 } 02823 fmd->writeLink(typeDecl,cd,nd,fd,gd); 02824 } 02825 else // no docs for this enum value 02826 { 02827 typeDecl.startBold(); 02828 typeDecl.docify(fmd->name()); 02829 typeDecl.endBold(); 02830 } 02831 if (fmd->hasOneLineInitializer()) // enum value has initializer 02832 { 02833 typeDecl.writeString(" = "); 02834 typeDecl.parseText(fmd->initializer()); 02835 } 02836 } 02837 02838 bool prevVisible = fmdVisible; 02839 fmd=fmdl->next(); 02840 if (fmd && (fmdVisible=fmd->isBriefSectionVisible())) 02841 { 02842 typeDecl.writeString(", "); 02843 } 02844 if (prevVisible) 02845 { 02846 typeDecl.disable(OutputGenerator::Man); 02847 typeDecl.writeString("\n"); // to prevent too long lines in LaTeX 02848 typeDecl.enable(OutputGenerator::Man); 02849 enumMemCount++; 02850 } 02851 } 02852 if (numVisibleEnumValues>enumValuesPerLine) 02853 { 02854 typeDecl.pushGeneratorState(); 02855 typeDecl.disableAllBut(OutputGenerator::Html); 02856 typeDecl.lineBreak(); 02857 typeDecl.popGeneratorState(); 02858 } 02859 } 02860 typeDecl.docify(" }"); 02861 } 02862 } 02863 02864 void MemberDef::setArgumentList(ArgumentList *al) 02865 { 02866 makeResident(); 02867 if (m_impl->defArgList) delete m_impl->defArgList; 02868 m_impl->defArgList = al; 02869 } 02870 02871 void MemberDef::setDeclArgumentList(ArgumentList *al) 02872 { 02873 makeResident(); 02874 if (m_impl->declArgList) delete m_impl->declArgList; 02875 m_impl->declArgList = al; 02876 } 02877 02878 void MemberDef::setTypeConstraints(ArgumentList *al) 02879 { 02880 if (al==0) return; 02881 makeResident(); 02882 if (m_impl->typeConstraints) delete m_impl->typeConstraints; 02883 m_impl->typeConstraints = new ArgumentList; 02884 m_impl->typeConstraints->setAutoDelete(TRUE); 02885 ArgumentListIterator ali(*al); 02886 Argument *a; 02887 for (;(a=ali.current());++ali) 02888 { 02889 m_impl->typeConstraints->append(new Argument(*a)); 02890 } 02891 } 02892 02893 void MemberDef::findSectionsInDocumentation() 02894 { 02895 makeResident(); 02896 docFindSections(documentation(),this,0,docFile()); 02897 } 02898 02899 void MemberDef::enableCallGraph(bool e) 02900 { 02901 makeResident(); 02902 m_impl->hasCallGraph=e; 02903 if (e) Doxygen::parseSourcesNeeded = TRUE; 02904 } 02905 02906 void MemberDef::enableCallerGraph(bool e) 02907 { 02908 makeResident(); 02909 m_impl->hasCallerGraph=e; 02910 if (e) Doxygen::parseSourcesNeeded = TRUE; 02911 } 02912 02913 bool MemberDef::protectionVisible() const 02914 { 02915 makeResident(); 02916 return m_impl->prot==Public || 02917 (m_impl->prot==Private && Config_getBool("EXTRACT_PRIVATE")) || 02918 (m_impl->prot==Protected && Config_getBool("EXTRACT_PROTECTED")) || 02919 (m_impl->prot==Package && Config_getBool("EXTRACT_PACKAGE")); 02920 } 02921 02922 void MemberDef::setInbodyDocumentation(const char *docs, 02923 const char *docFile,int docLine) 02924 { 02925 makeResident(); 02926 m_impl->inbodyDocs = docs; 02927 m_impl->inbodyDocs = m_impl->inbodyDocs.stripWhiteSpace(); 02928 m_impl->inbodyLine = docLine; 02929 m_impl->inbodyFile = docFile; 02930 } 02931 02932 bool MemberDef::isObjCMethod() const 02933 { 02934 makeResident(); 02935 if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isFunction()) return TRUE; 02936 return FALSE; 02937 } 02938 02939 QCString MemberDef::qualifiedName() const 02940 { 02941 makeResident(); 02942 if (isObjCMethod()) 02943 { 02944 QCString qm; 02945 if (isStatic()) qm="+"; else qm="-"; 02946 qm+="["; 02947 qm+=m_impl->classDef->name()+" "; 02948 qm+=name(); 02949 qm+="]"; 02950 return qm; 02951 } 02952 else 02953 { 02954 return Definition::qualifiedName(); 02955 } 02956 } 02957 02958 void MemberDef::setTagInfo(TagInfo *ti) 02959 { 02960 if (ti) 02961 { 02962 makeResident(); 02963 //printf("%s: Setting tag name=%s anchor=%s\n",name().data(),ti->tagName.data(),ti->anchor.data()); 02964 m_impl->anc=ti->anchor; 02965 setReference(ti->tagName); 02966 m_impl->explicitOutputFileBase = stripExtension(ti->fileName); 02967 } 02968 } 02969 02970 QCString MemberDef::objCMethodName(bool localLink,bool showStatic) const 02971 { 02972 makeResident(); 02973 QCString qm; 02974 if (showStatic) 02975 { 02976 if (isStatic()) qm="+ "; else qm="- "; 02977 } 02978 qm+=name(); 02979 if (!localLink) // link to method of same class 02980 { 02981 qm+=" ("; 02982 qm+=m_impl->classDef->name(); 02983 qm+=")"; 02984 } 02985 return qm; 02986 } 02987 02988 const char *MemberDef::declaration() const 02989 { 02990 makeResident(); 02991 return m_impl->decl; 02992 } 02993 02994 const char *MemberDef::definition() const 02995 { 02996 makeResident(); 02997 return m_impl->def; 02998 } 02999 03000 const char *MemberDef::extraTypeChars() const 03001 { 03002 makeResident(); 03003 return m_impl->extraTypeChars; 03004 } 03005 03006 const char *MemberDef::typeString() const 03007 { 03008 makeResident(); 03009 return m_impl->type; 03010 } 03011 03012 const char *MemberDef::argsString() const 03013 { 03014 makeResident(); 03015 return m_impl->args; 03016 } 03017 03018 const char *MemberDef::excpString() const 03019 { 03020 makeResident(); 03021 return m_impl->exception; 03022 } 03023 03024 const char *MemberDef::bitfieldString() const 03025 { 03026 makeResident(); 03027 return m_impl->bitfields; 03028 } 03029 03030 const QCString &MemberDef::initializer() const 03031 { 03032 makeResident(); 03033 return m_impl->initializer; 03034 } 03035 03036 int MemberDef::initializerLines() const 03037 { 03038 makeResident(); 03039 return m_impl->initLines; 03040 } 03041 03042 int MemberDef::getMemberSpecifiers() const 03043 { 03044 makeResident(); 03045 return m_impl->memSpec; 03046 } 03047 03048 ClassDef *MemberDef::getClassDef() const 03049 { 03050 makeResident(); 03051 return m_impl->classDef; 03052 } 03053 03054 FileDef *MemberDef::getFileDef() const 03055 { 03056 makeResident(); 03057 return m_impl->fileDef; 03058 } 03059 03060 NamespaceDef* MemberDef::getNamespaceDef() const 03061 { 03062 makeResident(); 03063 return m_impl->nspace; 03064 } 03065 03066 const char *MemberDef::getReadAccessor() const 03067 { 03068 makeResident(); 03069 return m_impl->read; 03070 } 03071 03072 const char *MemberDef::getWriteAccessor() const 03073 { 03074 makeResident(); 03075 return m_impl->write; 03076 } 03077 03078 GroupDef *MemberDef::getGroupDef() const 03079 { 03080 makeResident(); 03081 return m_impl->group; 03082 } 03083 03084 Grouping::GroupPri_t MemberDef::getGroupPri() const 03085 { 03086 makeResident(); 03087 return m_impl->grouppri; 03088 } 03089 03090 const char *MemberDef::getGroupFileName() const 03091 { 03092 makeResident(); 03093 return m_impl->groupFileName; 03094 } 03095 03096 int MemberDef::getGroupStartLine() const 03097 { 03098 makeResident(); 03099 return m_impl->groupStartLine; 03100 } 03101 03102 bool MemberDef::getGroupHasDocs() const 03103 { 03104 makeResident(); 03105 return m_impl->groupHasDocs; 03106 } 03107 03108 Protection MemberDef::protection() const 03109 { 03110 makeResident(); 03111 return m_impl->prot; 03112 } 03113 03114 MemberDef::MemberType MemberDef::memberType() const 03115 { 03116 makeResident(); 03117 return m_impl->mtype; 03118 } 03119 03120 bool MemberDef::isSignal() const 03121 { 03122 makeResident(); 03123 return m_impl->mtype==Signal; 03124 } 03125 03126 bool MemberDef::isSlot() const 03127 { 03128 makeResident(); 03129 return m_impl->mtype==Slot; 03130 } 03131 03132 bool MemberDef::isVariable() const 03133 { 03134 makeResident(); 03135 return m_impl->mtype==Variable; 03136 } 03137 03138 bool MemberDef::isEnumerate() const 03139 { 03140 makeResident(); 03141 return m_impl->mtype==Enumeration; 03142 } 03143 03144 bool MemberDef::isEnumValue() const 03145 { 03146 makeResident(); 03147 return m_impl->mtype==EnumValue; 03148 } 03149 03150 bool MemberDef::isTypedef() const 03151 { 03152 makeResident(); 03153 return m_impl->mtype==Typedef; 03154 } 03155 03156 bool MemberDef::isFunction() const 03157 { 03158 makeResident(); 03159 return m_impl->mtype==Function; 03160 } 03161 03162 bool MemberDef::isDefine() const 03163 { 03164 makeResident(); 03165 return m_impl->mtype==Define; 03166 } 03167 03168 bool MemberDef::isFriend() const 03169 { 03170 makeResident(); 03171 return m_impl->mtype==Friend; 03172 } 03173 03174 bool MemberDef::isDCOP() const 03175 { 03176 makeResident(); 03177 return m_impl->mtype==DCOP; 03178 } 03179 03180 bool MemberDef::isProperty() const 03181 { 03182 makeResident(); 03183 return m_impl->mtype==Property; 03184 } 03185 03186 bool MemberDef::isEvent() const 03187 { 03188 makeResident(); 03189 return m_impl->mtype==Event; 03190 } 03191 03192 bool MemberDef::isRelated() const 03193 { 03194 makeResident(); 03195 return m_impl->related; 03196 } 03197 03198 bool MemberDef::isStatic() const 03199 { 03200 makeResident(); 03201 return m_impl->stat; 03202 } 03203 03204 bool MemberDef::isInline() const 03205 { 03206 makeResident(); 03207 return (m_impl->memSpec&Entry::Inline)!=0; 03208 } 03209 03210 bool MemberDef::isExplicit() const 03211 { 03212 makeResident(); 03213 return (m_impl->memSpec&Entry::Explicit)!=0; 03214 } 03215 03216 bool MemberDef::isMutable() const 03217 { 03218 makeResident(); 03219 return (m_impl->memSpec&Entry::Mutable)!=0; 03220 } 03221 03222 bool MemberDef::isGettable() const 03223 { 03224 makeResident(); 03225 return (m_impl->memSpec&Entry::Gettable)!=0; 03226 } 03227 03228 bool MemberDef::isSettable() const 03229 { 03230 makeResident(); 03231 return (m_impl->memSpec&Entry::Settable)!=0; 03232 } 03233 03234 bool MemberDef::isAddable() const 03235 { 03236 makeResident(); 03237 return (m_impl->memSpec&Entry::Addable)!=0; 03238 } 03239 03240 bool MemberDef::isRemovable() const 03241 { 03242 makeResident(); 03243 return (m_impl->memSpec&Entry::Removable)!=0; 03244 } 03245 03246 bool MemberDef::isRaisable() const 03247 { 03248 makeResident(); 03249 return (m_impl->memSpec&Entry::Raisable)!=0; 03250 } 03251 03252 bool MemberDef::isReadable() const 03253 { 03254 makeResident(); 03255 return (m_impl->memSpec&Entry::Readable)!=0; 03256 } 03257 03258 bool MemberDef::isWritable() const 03259 { 03260 makeResident(); 03261 return (m_impl->memSpec&Entry::Writable)!=0; 03262 } 03263 03264 bool MemberDef::isFinal() const 03265 { 03266 makeResident(); 03267 return (m_impl->memSpec&Entry::Final)!=0; 03268 } 03269 03270 bool MemberDef::isNew() const 03271 { 03272 makeResident(); 03273 return (m_impl->memSpec&Entry::New)!=0; 03274 } 03275 03276 bool MemberDef::isSealed() const 03277 { 03278 makeResident(); 03279 return (m_impl->memSpec&Entry::Sealed)!=0; 03280 } 03281 03282 bool MemberDef::isOverride() const 03283 { 03284 makeResident(); 03285 return (m_impl->memSpec&Entry::Override)!=0; 03286 } 03287 03288 bool MemberDef::isInitonly() const 03289 { 03290 makeResident(); 03291 return (m_impl->memSpec&Entry::Initonly)!=0; 03292 } 03293 03294 bool MemberDef::isAbstract() const 03295 { 03296 makeResident(); 03297 return (m_impl->memSpec&Entry::Abstract)!=0; 03298 } 03299 03300 bool MemberDef::isOptional() const 03301 { 03302 makeResident(); 03303 return (m_impl->memSpec&Entry::Optional)!=0; 03304 } 03305 03306 bool MemberDef::isRequired() const 03307 { 03308 makeResident(); 03309 return (m_impl->memSpec&Entry::Required)!=0; 03310 } 03311 03312 bool MemberDef::isNonAtomic() const 03313 { 03314 makeResident(); 03315 return (m_impl->memSpec&Entry::NonAtomic)!=0; 03316 } 03317 03318 bool MemberDef::isCopy() const 03319 { 03320 makeResident(); 03321 return (m_impl->memSpec&Entry::Copy)!=0; 03322 } 03323 03324 bool MemberDef::isAssign() const 03325 { 03326 makeResident(); 03327 return (m_impl->memSpec&Entry::Assign)!=0; 03328 } 03329 03330 bool MemberDef::isRetain() const 03331 { 03332 makeResident(); 03333 return (m_impl->memSpec&Entry::Retain)!=0; 03334 } 03335 03336 03337 bool MemberDef::isImplementation() const 03338 { 03339 makeResident(); 03340 return m_impl->implOnly; 03341 } 03342 03343 bool MemberDef::isExternal() const 03344 { 03345 makeResident(); 03346 return m_impl->explExt; 03347 } 03348 03349 bool MemberDef::isTemplateSpecialization() const 03350 { 03351 makeResident(); 03352 return m_impl->tspec; 03353 } 03354 03355 bool MemberDef::hasDocumentedParams() const 03356 { 03357 makeResident(); 03358 return m_impl->hasDocumentedParams; 03359 } 03360 03361 bool MemberDef::hasDocumentedReturnType() const 03362 { 03363 makeResident(); 03364 return m_impl->hasDocumentedReturnType; 03365 } 03366 03367 int MemberDef::inbodyLine() const 03368 { 03369 makeResident(); 03370 return m_impl->inbodyLine; 03371 } 03372 03373 QCString MemberDef::inbodyFile() const 03374 { 03375 makeResident(); 03376 return m_impl->inbodyFile; 03377 } 03378 03379 const QCString &MemberDef::inbodyDocumentation() const 03380 { 03381 makeResident(); 03382 return m_impl->inbodyDocs; 03383 } 03384 03385 ClassDef *MemberDef::relatedAlso() const 03386 { 03387 makeResident(); 03388 return m_impl->relatedAlso; 03389 } 03390 03391 bool MemberDef::hasDocumentedEnumValues() const 03392 { 03393 makeResident(); 03394 return m_impl->docEnumValues; 03395 } 03396 03397 MemberDef *MemberDef::getAnonymousEnumType() const 03398 { 03399 makeResident(); 03400 return m_impl->annEnumType; 03401 } 03402 03403 bool MemberDef::isDocsForDefinition() const 03404 { 03405 makeResident(); 03406 return m_impl->docsForDefinition; 03407 } 03408 03409 MemberDef *MemberDef::getEnumScope() const 03410 { 03411 makeResident(); 03412 return m_impl->enumScope; 03413 } 03414 03415 LockingPtr<MemberList> MemberDef::enumFieldList() const 03416 { 03417 makeResident(); 03418 return LockingPtr<MemberList>(this,m_impl->enumFields); 03419 } 03420 03421 LockingPtr<ExampleSDict> MemberDef::getExamples() const 03422 { 03423 makeResident(); 03424 return LockingPtr<ExampleSDict>(this,m_impl->exampleSDict); 03425 } 03426 03427 bool MemberDef::isPrototype() const 03428 { 03429 makeResident(); 03430 return m_impl->proto; 03431 } 03432 03433 LockingPtr<ArgumentList> MemberDef::argumentList() const 03434 { 03435 makeResident(); 03436 return LockingPtr<ArgumentList>(this,m_impl->defArgList); 03437 } 03438 03439 LockingPtr<ArgumentList> MemberDef::declArgumentList() const 03440 { 03441 makeResident(); 03442 return LockingPtr<ArgumentList>(this,m_impl->declArgList); 03443 } 03444 03445 LockingPtr<ArgumentList> MemberDef::templateArguments() const 03446 { 03447 makeResident(); 03448 return LockingPtr<ArgumentList>(this,m_impl->tArgList); 03449 } 03450 03451 LockingPtr< QList<ArgumentList> > MemberDef::definitionTemplateParameterLists() const 03452 { 03453 makeResident(); 03454 return LockingPtr< QList<ArgumentList> >(this,m_impl->defTmpArgLists); 03455 } 03456 03457 int MemberDef::getMemberGroupId() const 03458 { 03459 makeResident(); 03460 return m_impl->grpId; 03461 } 03462 03463 MemberGroup *MemberDef::getMemberGroup() const 03464 { 03465 makeResident(); 03466 return m_impl->memberGroup; 03467 } 03468 03469 bool MemberDef::fromAnonymousScope() const 03470 { 03471 makeResident(); 03472 return m_impl->annScope; 03473 } 03474 03475 bool MemberDef::anonymousDeclShown() const 03476 { 03477 makeResident(); 03478 return m_impl->annUsed; 03479 } 03480 03481 void MemberDef::setAnonymousUsed() 03482 { 03483 makeResident(); 03484 m_impl->annUsed = TRUE; 03485 } 03486 03487 bool MemberDef::hasCallGraph() const 03488 { 03489 makeResident(); 03490 return m_impl->hasCallGraph; 03491 } 03492 03493 bool MemberDef::hasCallerGraph() const 03494 { 03495 makeResident(); 03496 return m_impl->hasCallerGraph; 03497 } 03498 03499 MemberDef *MemberDef::templateMaster() const 03500 { 03501 makeResident(); 03502 return m_impl->templateMaster; 03503 } 03504 03505 bool MemberDef::isTypedefValCached() const 03506 { 03507 makeResident(); 03508 return m_impl->isTypedefValCached; 03509 } 03510 03511 ClassDef *MemberDef::getCachedTypedefVal() const 03512 { 03513 makeResident(); 03514 return m_impl->cachedTypedefValue; 03515 } 03516 03517 QCString MemberDef::getCachedTypedefTemplSpec() const 03518 { 03519 makeResident(); 03520 return m_impl->cachedTypedefTemplSpec; 03521 } 03522 03523 QCString MemberDef::getCachedResolvedTypedef() const 03524 { 03525 makeResident(); 03526 //printf("MemberDef::getCachedResolvedTypedef()=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl); 03527 return m_impl->cachedResolvedType; 03528 } 03529 03530 MemberDef *MemberDef::memberDefinition() const 03531 { 03532 makeResident(); 03533 return m_impl->memDef; 03534 } 03535 03536 MemberDef *MemberDef::memberDeclaration() const 03537 { 03538 makeResident(); 03539 return m_impl->memDec; 03540 } 03541 03542 MemberDef *MemberDef::inheritsDocsFrom() const 03543 { 03544 makeResident(); 03545 return m_impl->docProvider; 03546 } 03547 03548 MemberDef *MemberDef::getGroupAlias() const 03549 { 03550 makeResident(); 03551 return m_impl->groupAlias; 03552 } 03553 03554 void MemberDef::setMemberType(MemberType t) 03555 { 03556 makeResident(); 03557 m_impl->mtype=t; 03558 } 03559 03560 void MemberDef::setDefinition(const char *d) 03561 { 03562 makeResident(); 03563 m_impl->def=d; 03564 } 03565 03566 void MemberDef::setFileDef(FileDef *fd) 03567 { 03568 makeResident(); 03569 m_impl->fileDef=fd; 03570 } 03571 03572 void MemberDef::setProtection(Protection p) 03573 { 03574 makeResident(); 03575 m_impl->prot=p; 03576 } 03577 03578 void MemberDef::setMemberSpecifiers(int s) 03579 { 03580 makeResident(); 03581 m_impl->memSpec=s; 03582 } 03583 03584 void MemberDef::mergeMemberSpecifiers(int s) 03585 { 03586 makeResident(); 03587 m_impl->memSpec|=s; 03588 } 03589 03590 void MemberDef::setBitfields(const char *s) 03591 { 03592 makeResident(); 03593 m_impl->bitfields = s; 03594 } 03595 03596 void MemberDef::setMaxInitLines(int lines) 03597 { 03598 if (lines!=-1) 03599 { 03600 makeResident(); 03601 m_impl->userInitLines=lines; 03602 } 03603 } 03604 03605 void MemberDef::setExplicitExternal(bool b) 03606 { 03607 makeResident(); 03608 m_impl->explExt=b; 03609 } 03610 03611 void MemberDef::setReadAccessor(const char *r) 03612 { 03613 makeResident(); 03614 m_impl->read=r; 03615 } 03616 03617 void MemberDef::setWriteAccessor(const char *w) 03618 { 03619 makeResident(); 03620 m_impl->write=w; 03621 } 03622 03623 void MemberDef::setTemplateSpecialization(bool b) 03624 { 03625 makeResident(); 03626 m_impl->tspec=b; 03627 } 03628 03629 void MemberDef::makeRelated() 03630 { 03631 makeResident(); 03632 m_impl->related=TRUE; 03633 } 03634 03635 void MemberDef::setHasDocumentedParams(bool b) 03636 { 03637 makeResident(); 03638 m_impl->hasDocumentedParams = b; 03639 } 03640 03641 void MemberDef::setHasDocumentedReturnType(bool b) 03642 { 03643 makeResident(); 03644 m_impl->hasDocumentedReturnType = b; 03645 } 03646 03647 void MemberDef::setInheritsDocsFrom(MemberDef *md) 03648 { 03649 makeResident(); 03650 m_impl->docProvider = md; 03651 } 03652 03653 void MemberDef::setArgsString(const char *as) 03654 { 03655 makeResident(); 03656 m_impl->args = as; 03657 } 03658 03659 void MemberDef::setRelatedAlso(ClassDef *cd) 03660 { 03661 makeResident(); 03662 m_impl->relatedAlso=cd; 03663 } 03664 03665 void MemberDef::setEnumClassScope(ClassDef *cd) 03666 { 03667 makeResident(); 03668 m_impl->classDef = cd; 03669 } 03670 03671 void MemberDef::setDocumentedEnumValues(bool value) 03672 { 03673 makeResident(); 03674 m_impl->docEnumValues=value; 03675 } 03676 03677 void MemberDef::setAnonymousEnumType(MemberDef *md) 03678 { 03679 makeResident(); 03680 m_impl->annEnumType = md; 03681 } 03682 03683 void MemberDef::setPrototype(bool p) 03684 { 03685 makeResident(); 03686 m_impl->proto=p; 03687 } 03688 03689 void MemberDef::setMemberGroupId(int id) 03690 { 03691 makeResident(); 03692 m_impl->grpId=id; 03693 } 03694 03695 void MemberDef::makeImplementationDetail() 03696 { 03697 makeResident(); 03698 m_impl->implOnly=TRUE; 03699 } 03700 03701 void MemberDef::setFromAnonymousScope(bool b) 03702 { 03703 makeResident(); 03704 m_impl->annScope=b; 03705 } 03706 03707 void MemberDef::setFromAnonymousMember(MemberDef *m) 03708 { 03709 makeResident(); 03710 m_impl->annMemb=m; 03711 } 03712 03713 void MemberDef::setTemplateMaster(MemberDef *mt) 03714 { 03715 makeResident(); 03716 m_impl->templateMaster=mt; 03717 } 03718 03719 void MemberDef::setDocsForDefinition(bool b) 03720 { 03721 makeResident(); 03722 m_impl->docsForDefinition = b; 03723 } 03724 03725 void MemberDef::setGroupAlias(MemberDef *md) 03726 { 03727 makeResident(); 03728 m_impl->groupAlias = md; 03729 } 03730 03731 void MemberDef::invalidateTypedefValCache() 03732 { 03733 makeResident(); 03734 m_impl->isTypedefValCached=FALSE; 03735 } 03736 03737 void MemberDef::setMemberDefinition(MemberDef *md) 03738 { 03739 makeResident(); 03740 m_impl->memDef=md; 03741 } 03742 03743 void MemberDef::setMemberDeclaration(MemberDef *md) 03744 { 03745 makeResident(); 03746 m_impl->memDec=md; 03747 } 03748 03749 void MemberDef::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType) 03750 { 03751 makeResident(); 03752 m_impl->isTypedefValCached=TRUE; 03753 m_impl->cachedTypedefValue=val; 03754 m_impl->cachedTypedefTemplSpec=templSpec; 03755 m_impl->cachedResolvedType=resolvedType; 03756 //printf("MemberDef::cacheTypedefVal=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl); 03757 } 03758 03759 void MemberDef::flushToDisk() const 03760 { 03761 if (isLocked()) return; 03762 MemberDef *that = (MemberDef*)this; 03763 that->m_storagePos = Doxygen::symbolStorage->alloc(); 03764 //printf("%p: MemberDef::flushToDisk()\n",this); 03765 // write the definition base class member variables to disk 03766 Definition::flushToDisk(); 03767 03768 //printf("%p: flushing specific part\n",this); 03769 03770 // write the memberdef member variables to disk 03771 marshalUInt(Doxygen::symbolStorage,START_MARKER); 03772 marshalObjPointer (Doxygen::symbolStorage,m_impl->classDef); 03773 marshalObjPointer (Doxygen::symbolStorage,m_impl->fileDef); 03774 marshalObjPointer (Doxygen::symbolStorage,m_impl->nspace); 03775 marshalObjPointer (Doxygen::symbolStorage,m_impl->enumScope); 03776 marshalObjPointer (Doxygen::symbolStorage,m_impl->annEnumType); 03777 marshalMemberList (Doxygen::symbolStorage,m_impl->enumFields); 03778 marshalObjPointer (Doxygen::symbolStorage,m_impl->redefines); 03779 marshalMemberList (Doxygen::symbolStorage,m_impl->redefinedBy); 03780 marshalObjPointer (Doxygen::symbolStorage,m_impl->memDef); 03781 marshalObjPointer (Doxygen::symbolStorage,m_impl->memDec); 03782 marshalObjPointer (Doxygen::symbolStorage,m_impl->relatedAlso); 03783 marshalExampleSDict (Doxygen::symbolStorage,m_impl->exampleSDict); 03784 marshalQCString (Doxygen::symbolStorage,m_impl->type); 03785 marshalQCString (Doxygen::symbolStorage,m_impl->args); 03786 marshalQCString (Doxygen::symbolStorage,m_impl->def); 03787 marshalQCString (Doxygen::symbolStorage,m_impl->anc); 03788 marshalInt (Doxygen::symbolStorage,(int)m_impl->virt); 03789 marshalInt (Doxygen::symbolStorage,(int)m_impl->prot); 03790 marshalQCString (Doxygen::symbolStorage,m_impl->decl); 03791 marshalQCString (Doxygen::symbolStorage,m_impl->bitfields); 03792 marshalQCString (Doxygen::symbolStorage,m_impl->read); 03793 marshalQCString (Doxygen::symbolStorage,m_impl->write); 03794 marshalQCString (Doxygen::symbolStorage,m_impl->exception); 03795 marshalQCString (Doxygen::symbolStorage,m_impl->initializer); 03796 marshalQCString (Doxygen::symbolStorage,m_impl->extraTypeChars); 03797 marshalInt (Doxygen::symbolStorage,m_impl->initLines); 03798 marshalInt (Doxygen::symbolStorage,m_impl->memSpec); 03799 marshalInt (Doxygen::symbolStorage,(int)m_impl->mtype); 03800 marshalInt (Doxygen::symbolStorage,m_impl->maxInitLines); 03801 marshalInt (Doxygen::symbolStorage,m_impl->userInitLines); 03802 marshalObjPointer (Doxygen::symbolStorage,m_impl->annMemb); 03803 marshalArgumentList (Doxygen::symbolStorage,m_impl->defArgList); 03804 marshalArgumentList (Doxygen::symbolStorage,m_impl->declArgList); 03805 marshalArgumentList (Doxygen::symbolStorage,m_impl->tArgList); 03806 marshalArgumentList (Doxygen::symbolStorage,m_impl->typeConstraints); 03807 marshalObjPointer (Doxygen::symbolStorage,m_impl->templateMaster); 03808 marshalArgumentLists(Doxygen::symbolStorage,m_impl->defTmpArgLists); 03809 marshalObjPointer (Doxygen::symbolStorage,m_impl->cachedAnonymousType); 03810 marshalMemberLists (Doxygen::symbolStorage,m_impl->classSectionSDict); 03811 marshalObjPointer (Doxygen::symbolStorage,m_impl->groupAlias); 03812 marshalInt (Doxygen::symbolStorage,m_impl->grpId); 03813 marshalObjPointer (Doxygen::symbolStorage,m_impl->memberGroup); 03814 marshalObjPointer (Doxygen::symbolStorage,m_impl->group); 03815 marshalInt (Doxygen::symbolStorage,(int)m_impl->grouppri); 03816 marshalQCString (Doxygen::symbolStorage,m_impl->groupFileName); 03817 marshalInt (Doxygen::symbolStorage,m_impl->groupStartLine); 03818 marshalObjPointer (Doxygen::symbolStorage,m_impl->groupMember); 03819 marshalBool (Doxygen::symbolStorage,m_impl->isTypedefValCached); 03820 marshalObjPointer (Doxygen::symbolStorage,m_impl->cachedTypedefValue); 03821 marshalQCString (Doxygen::symbolStorage,m_impl->cachedTypedefTemplSpec); 03822 marshalQCString (Doxygen::symbolStorage,m_impl->cachedResolvedType); 03823 marshalInt (Doxygen::symbolStorage,m_impl->inbodyLine); 03824 marshalQCString (Doxygen::symbolStorage,m_impl->inbodyFile); 03825 marshalQCString (Doxygen::symbolStorage,m_impl->inbodyDocs); 03826 marshalObjPointer (Doxygen::symbolStorage,m_impl->docProvider); 03827 marshalQCString (Doxygen::symbolStorage,m_impl->explicitOutputFileBase); 03828 marshalBool (Doxygen::symbolStorage,m_impl->implOnly); 03829 marshalBool (Doxygen::symbolStorage,m_impl->hasDocumentedParams); 03830 marshalBool (Doxygen::symbolStorage,m_impl->hasDocumentedReturnType); 03831 marshalBool (Doxygen::symbolStorage,m_impl->isDMember); 03832 marshalBool (Doxygen::symbolStorage,m_impl->related); 03833 marshalBool (Doxygen::symbolStorage,m_impl->stat); 03834 marshalBool (Doxygen::symbolStorage,m_impl->proto); 03835 marshalBool (Doxygen::symbolStorage,m_impl->docEnumValues); 03836 marshalBool (Doxygen::symbolStorage,m_impl->annScope); 03837 marshalBool (Doxygen::symbolStorage,m_impl->annUsed); 03838 marshalBool (Doxygen::symbolStorage,m_impl->hasCallGraph); 03839 marshalBool (Doxygen::symbolStorage,m_impl->hasCallerGraph); 03840 marshalBool (Doxygen::symbolStorage,m_impl->explExt); 03841 marshalBool (Doxygen::symbolStorage,m_impl->tspec); 03842 marshalBool (Doxygen::symbolStorage,m_impl->groupHasDocs); 03843 marshalBool (Doxygen::symbolStorage,m_impl->docsForDefinition); 03844 marshalUInt(Doxygen::symbolStorage,END_MARKER); 03845 03846 // function doesn't modify the object conceptually but compiler doesn't know this. 03847 delete that->m_impl; 03848 that->m_impl=0; 03849 that->m_flushPending=FALSE; 03850 } 03851 03852 void MemberDef::loadFromDisk() const 03853 { 03854 //printf("%p: MemberDef::loadFromDisk()\n",this); 03855 MemberDef *that = (MemberDef *)this; 03856 if (isLocked()) 03857 { 03858 assert(m_impl!=0); 03859 return; 03860 } 03861 assert(m_impl==0); 03862 03863 Doxygen::symbolStorage->seek(m_storagePos); 03864 Definition::loadFromDisk(); 03865 03866 //printf("%p: loading specific part\n",this); 03867 03868 that->m_impl = new MemberDefImpl; 03869 03870 uint marker = unmarshalUInt(Doxygen::symbolStorage); 03871 assert(marker==START_MARKER); 03872 m_impl->classDef = (ClassDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03873 m_impl->fileDef = (FileDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03874 m_impl->nspace = (NamespaceDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03875 m_impl->enumScope = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03876 m_impl->annEnumType = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03877 m_impl->enumFields = unmarshalMemberList (Doxygen::symbolStorage); 03878 m_impl->redefines = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03879 m_impl->redefinedBy = unmarshalMemberList (Doxygen::symbolStorage); 03880 m_impl->memDef = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03881 m_impl->memDec = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03882 m_impl->relatedAlso = (ClassDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03883 m_impl->exampleSDict = unmarshalExampleSDict (Doxygen::symbolStorage); 03884 m_impl->type = unmarshalQCString (Doxygen::symbolStorage); 03885 m_impl->args = unmarshalQCString (Doxygen::symbolStorage); 03886 m_impl->def = unmarshalQCString (Doxygen::symbolStorage); 03887 m_impl->anc = unmarshalQCString (Doxygen::symbolStorage); 03888 m_impl->virt = (Specifier)unmarshalInt (Doxygen::symbolStorage); 03889 m_impl->prot = (Protection)unmarshalInt(Doxygen::symbolStorage); 03890 m_impl->decl = unmarshalQCString (Doxygen::symbolStorage); 03891 m_impl->bitfields = unmarshalQCString (Doxygen::symbolStorage); 03892 m_impl->read = unmarshalQCString (Doxygen::symbolStorage); 03893 m_impl->write = unmarshalQCString (Doxygen::symbolStorage); 03894 m_impl->exception = unmarshalQCString (Doxygen::symbolStorage); 03895 m_impl->initializer = unmarshalQCString (Doxygen::symbolStorage); 03896 m_impl->extraTypeChars = unmarshalQCString (Doxygen::symbolStorage); 03897 m_impl->initLines = unmarshalInt (Doxygen::symbolStorage); 03898 m_impl->memSpec = unmarshalInt (Doxygen::symbolStorage); 03899 m_impl->mtype = (MemberDef::MemberType)unmarshalInt (Doxygen::symbolStorage); 03900 m_impl->maxInitLines = unmarshalInt (Doxygen::symbolStorage); 03901 m_impl->userInitLines = unmarshalInt (Doxygen::symbolStorage); 03902 m_impl->annMemb = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03903 m_impl->defArgList = unmarshalArgumentList (Doxygen::symbolStorage); 03904 m_impl->declArgList = unmarshalArgumentList (Doxygen::symbolStorage); 03905 m_impl->tArgList = unmarshalArgumentList (Doxygen::symbolStorage); 03906 m_impl->typeConstraints = unmarshalArgumentList (Doxygen::symbolStorage); 03907 m_impl->templateMaster = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03908 m_impl->defTmpArgLists = unmarshalArgumentLists(Doxygen::symbolStorage); 03909 m_impl->cachedAnonymousType = (ClassDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03910 m_impl->classSectionSDict = unmarshalMemberLists (Doxygen::symbolStorage); 03911 m_impl->groupAlias = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03912 m_impl->grpId = unmarshalInt (Doxygen::symbolStorage); 03913 m_impl->memberGroup = (MemberGroup*)unmarshalObjPointer (Doxygen::symbolStorage); 03914 m_impl->group = (GroupDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03915 m_impl->grouppri = (Grouping::GroupPri_t)unmarshalInt (Doxygen::symbolStorage); 03916 m_impl->groupFileName = unmarshalQCString (Doxygen::symbolStorage); 03917 m_impl->groupStartLine = unmarshalInt (Doxygen::symbolStorage); 03918 m_impl->groupMember = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03919 m_impl->isTypedefValCached = unmarshalBool (Doxygen::symbolStorage); 03920 m_impl->cachedTypedefValue = (ClassDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03921 m_impl->cachedTypedefTemplSpec = unmarshalQCString (Doxygen::symbolStorage); 03922 m_impl->cachedResolvedType = unmarshalQCString (Doxygen::symbolStorage); 03923 m_impl->inbodyLine = unmarshalInt (Doxygen::symbolStorage); 03924 m_impl->inbodyFile = unmarshalQCString (Doxygen::symbolStorage); 03925 m_impl->inbodyDocs = unmarshalQCString (Doxygen::symbolStorage); 03926 m_impl->docProvider = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); 03927 m_impl->explicitOutputFileBase = unmarshalQCString (Doxygen::symbolStorage); 03928 m_impl->implOnly = unmarshalBool (Doxygen::symbolStorage); 03929 m_impl->hasDocumentedParams = unmarshalBool (Doxygen::symbolStorage); 03930 m_impl->hasDocumentedReturnType = unmarshalBool (Doxygen::symbolStorage); 03931 m_impl->isDMember = unmarshalBool (Doxygen::symbolStorage); 03932 m_impl->related = unmarshalBool (Doxygen::symbolStorage); 03933 m_impl->stat = unmarshalBool (Doxygen::symbolStorage); 03934 m_impl->proto = unmarshalBool (Doxygen::symbolStorage); 03935 m_impl->docEnumValues = unmarshalBool (Doxygen::symbolStorage); 03936 m_impl->annScope = unmarshalBool (Doxygen::symbolStorage); 03937 m_impl->annUsed = unmarshalBool (Doxygen::symbolStorage); 03938 m_impl->hasCallGraph = unmarshalBool (Doxygen::symbolStorage); 03939 m_impl->hasCallerGraph = unmarshalBool (Doxygen::symbolStorage); 03940 m_impl->explExt = unmarshalBool (Doxygen::symbolStorage); 03941 m_impl->tspec = unmarshalBool (Doxygen::symbolStorage); 03942 m_impl->groupHasDocs = unmarshalBool (Doxygen::symbolStorage); 03943 m_impl->docsForDefinition = unmarshalBool (Doxygen::symbolStorage); 03944 marker = unmarshalUInt(Doxygen::symbolStorage); 03945 assert(marker==END_MARKER); 03946 } 03947 03948 void MemberDef::makeResident() const 03949 { 03950 if (m_cacheHandle==-1) // not yet in cache 03951 { 03952 MemberDef *victim = 0; 03953 MemberDef *that = (MemberDef*)this; // fake method constness 03954 that->m_cacheHandle = Doxygen::symbolCache->add(that,(void **)&victim); 03955 //printf("adding %s to cache, handle=%d\n",m_impl->name.data(),that->m_cacheHandle); 03956 if (victim) // cache was full, victim was the least recently used item and has to go 03957 { 03958 victim->m_cacheHandle=-1; // invalidate cache handle 03959 victim->saveToDisk(); // store the item on disk 03960 } 03961 else // cache not yet full 03962 { 03963 //printf("Adding %s to cache, handle=%d\n",m_impl->name.data(),m_cacheHandle); 03964 } 03965 if (m_storagePos!=-1) // already been written to disk 03966 { 03967 if (isLocked()) // locked in memory 03968 { 03969 assert(m_impl!=0); 03970 that->m_flushPending=FALSE; // no need to flush anymore 03971 } 03972 else // not locked in memory 03973 { 03974 assert(m_impl==0); 03975 loadFromDisk(); 03976 } 03977 } 03978 } 03979 else // already cached, make this object the most recently used. 03980 { 03981 assert(m_impl!=0); 03982 //printf("Touching symbol %s\n",m_impl->name.data()); 03983 Doxygen::symbolCache->use(m_cacheHandle); 03984 } 03985 } 03986 03987 void MemberDef::saveToDisk() const 03988 { 03989 assert(m_impl!=0); 03990 MemberDef *that = (MemberDef *)this; 03991 if (isLocked()) // cannot flush the item as it is locked 03992 { 03993 that->m_flushPending=TRUE; // flush when unlocked 03994 } 03995 else // ready to flush the item to disk 03996 { 03997 //printf("Adding %s to cache, handle=%d by replacing %s\n", 03998 // m_impl->name.data(),m_cacheHandle,victim->m_impl->name.data()); 03999 if (m_storagePos!=-1) 04000 // if victim was stored on disk already and is not locked 04001 { 04002 // free the storage space occupied by the old store item 04003 Doxygen::symbolStorage->release(m_storagePos); // free up space for others 04004 } 04005 // write a the new (possibly modified) instance to disk 04006 flushToDisk(); 04007 // end to write sequence (unless nothing was written due to the lock) 04008 Doxygen::symbolStorage->end(); 04009 } 04010 } 04011 04012 void MemberDef::lock() const 04013 { 04014 } 04015 04016 void MemberDef::unlock() const 04017 { 04018 if (m_flushPending && !isLocked()) 04019 { 04020 // write a the new (possibly modified) instance to disk 04021 flushToDisk(); 04022 // end to write sequence (unless nothing was written due to the lock) 04023 Doxygen::symbolStorage->end(); 04024 } 04025 } 04026 04027 void MemberDef::copyArgumentNames(MemberDef *bmd) 04028 { 04029 makeResident(); 04030 { 04031 LockingPtr<ArgumentList> arguments = bmd->argumentList(); 04032 if (m_impl->defArgList && arguments!=0) 04033 { 04034 ArgumentListIterator aliDst(*m_impl->defArgList); 04035 ArgumentListIterator aliSrc(*arguments); 04036 Argument *argDst, *argSrc; 04037 for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc) 04038 { 04039 argDst->name = argSrc->name; 04040 } 04041 } 04042 } 04043 { 04044 LockingPtr<ArgumentList> arguments = bmd->declArgumentList(); 04045 if (m_impl->declArgList && arguments!=0) 04046 { 04047 ArgumentListIterator aliDst(*m_impl->declArgList); 04048 ArgumentListIterator aliSrc(*arguments); 04049 Argument *argDst, *argSrc; 04050 for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc) 04051 { 04052 argDst->name = argSrc->name; 04053 } 04054 } 04055 } 04056 } 04057 04058