diff options
Diffstat (limited to 'src/doxygen.cpp')
-rw-r--r-- | src/doxygen.cpp | 755 |
1 files changed, 585 insertions, 170 deletions
diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 9c0a97b..8f09abb 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -16,7 +16,7 @@ */ #include "qtbc.h" -#include <qfileinf.h> +#include <qfileinfo.h> #include <qfile.h> #include <qdir.h> #include <qdict.h> @@ -50,7 +50,7 @@ #include "htmlhelp.h" #include "defargs.h" -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__BORLANDC__) #define popen _popen #endif @@ -81,6 +81,7 @@ FileNameDict inputNameDict(1009); // dictionary of sections StringDict excludeNameDict(1009); // dictionary of sections FileNameDict includeNameDict(1009); // dictionary of include names FileNameDict exampleNameDict(1009); // dictionary of examples +FileNameDict imageNameDict(257); // dictionary of images FileDict includeDict(1009); // dictionary of include files DefineDict defineDict(10007); // dictionary of all defines StringDict typedefDict(1009); // dictionary of all typedefs @@ -114,6 +115,7 @@ void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl, bool over_load); const char idMask[] = "[A-Za-z_][A-Za-z_0-9]*"; +QCString spaces; //---------------------------------------------------------------------- // Returns the standard string that is generated when the \overload @@ -149,7 +151,7 @@ void buildGroupList(Entry *root) gd->setBriefDescription(root->brief); gd->setDocumentation(root->doc); gd->addSectionsToDefinition(root->anchors); - groupList.inSort(gd); + groupList.append(gd); groupDict.insert(root->name,gd); } } @@ -232,11 +234,12 @@ void buildFileList(Entry *root) } else { + const char *fn = root->fileName.data(); warn("Warning: the name `%s' supplied as " "the second argument in the \\file statement in file " "%s at line %d ", root->name.data(), - root->fileName.data(), + fn ? fn : "???", root->startLine); if (ambig) // name is ambigious { @@ -409,28 +412,46 @@ void buildClassList(Entry *root) //printf("existing ClassDef tempArgList=%p specScope=%s\n",root->tArgList,root->scopeSpec.data()); cd->setTemplateArguments(root->tArgList); } - if (root->doc.length()>0 || root->brief.length()>0) // block contains docs + if (!root->doc.isEmpty() || !root->brief.isEmpty() || + (root->bodyLine!=-1 && Config::sourceBrowseFlag) + ) + // block contains something that ends up in the docs { - if (cd->documentation()) // class already documented + if (!root->doc.isEmpty() && !cd->documentation().isEmpty()) { - warn("Warning: class %s already documented\n" - " skipping documentation in file %s at line %d\n", + warn("Warning: class %s already has a detailed description\n" + " skipping the one in file %s at line %d\n", fullName.data(),root->fileName.data(),root->startLine); } - else // class not documented, use docs in block + else if (!root->doc.isEmpty()) { cd->setDocumentation(root->doc); + } + if (!root->brief.isEmpty() && !cd->briefDescription().isEmpty()) + { + warn("Warning: class %s already has a brief description\n" + " skipping the one in file %s at line %d\n", + fullName.data(),root->fileName.data(),root->startLine); + } + else if (!root->brief.isEmpty()) + { cd->setBriefDescription(root->brief); - cd->addSectionsToDefinition(root->anchors); - cd->setName(fullName); // change name to match docs } + if (root->bodyLine!=-1 && cd->getBodyLine()==-1) + { + cd->setBodyLine(root->bodyLine); + cd->setBodyDef(findFileDef(&inputNameDict,root->fileName,ambig)); + } + cd->addSectionsToDefinition(root->anchors); + cd->setName(fullName); // change name to match docs } - if (cd->includeFile()==0) + if (cd->includeFile()==0 && + (!root->doc.isEmpty() || !root->brief.isEmpty()) + ) { - addIncludeFile(cd, - findFileDef(&inputNameDict,root->fileName,ambig), - root - ); + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + cd->setFileDef(fd); + addIncludeFile(cd,fd,root); } addNamespace(root,cd); } @@ -456,6 +477,10 @@ void buildClassList(Entry *root) cd->setTemplateArguments(root->tArgList); cd->setProtection(root->protection); cd->addSectionsToDefinition(root->anchors); + // file definition containing the class cd + FileDef *ifd=findFileDef(&inputNameDict,root->fileName,ambig); + cd->setBodyLine(root->bodyLine); + cd->setBodyDef(ifd); QListIterator<QCString> sli(*root->groups); QCString *s; @@ -471,10 +496,10 @@ void buildClassList(Entry *root) bool found=addNamespace(root,cd); - // file definition containing the class cd - FileDef *ifd=findFileDef(&inputNameDict,root->fileName,ambig); - addIncludeFile(cd,ifd,root); + cd->setFileDef(ifd); + if (!root->doc.isEmpty() || !root->brief.isEmpty()) + addIncludeFile(cd,ifd,root); // if the class is not in a namespace then we insert // it in the file definition @@ -594,6 +619,78 @@ void buildNamespaceList(Entry *root) } } +void findUsingDirectives(Entry *root) +{ + if (root->section==Entry::USINGDIR_SEC) + { + //printf("Found using directive %s at line %d of %s\n", + // root->name.data(),root->startLine,root->fileName.data()); + bool ambig; + if (!root->name.isEmpty()) + { + NamespaceDef *usingNd = 0; + NamespaceDef *nd = 0; + FileDef *fd = findFileDef(&inputNameDict,root->fileName,ambig); + QCString nsName; + + // see if the using statement was found inside a namespace or inside + // the global file scope. + if (root->parent->section == Entry::NAMESPACE_SEC) + { + nsName=root->parent->name.copy(); + if (!nsName.isEmpty()) + { + nd = namespaceDict[nsName]; + } + } + + // find the scope in which the `using' namespace is defined by prepending + // the possible scopes in which the using statement was found, starting + // with the most inner scope and going to the most outer scope (i.e. + // file scope). + int scopeOffset = nsName.length(); + do + { + QCString scope=scopeOffset>0 ? + nsName.left(scopeOffset)+"::" : QCString(); + //printf("Trying with scope=`%s'\n",scope.data()); + usingNd = namespaceDict[scope+root->name]; + if (scopeOffset==0) + { + scopeOffset=-1; + } + else if ((scopeOffset=nsName.findRev("::",scopeOffset-1))==-1) + { + scopeOffset=0; + } + } while (scopeOffset>=0 && usingNd==0); + + //printf("%s -> %p\n",root->name.data(),usingNd); + + // add the namespace the correct scope + if (usingNd) + { + if (nd) + { + //printf("Inside namespace %s\n",nd->name().data()); + nd->addUsingDirective(usingNd); + } + else if (fd) + { + //printf("Inside file %s\n",fd->name().data()); + fd->addUsingDirective(usingNd); + } + } + } + } + EntryListIterator eli(*root->sublist); + Entry *e; + for (;(e=eli.current());++eli) + { + findUsingDirectives(e); + } +} + //---------------------------------------------------------------------- static MemberDef *addVariableToClass(Entry *root,ClassDef *cd, @@ -665,6 +762,9 @@ static MemberDef *addVariableToClass(Entry *root,ClassDef *cd, md->setFromAnnonymousScope(fromAnnScope); md->setFromAnnonymousMember(fromAnnMemb); md->setIndentDepth(indentDepth); + md->setBodyLine(root->bodyLine); + bool ambig; + md->setBodyDef(findFileDef(&inputNameDict,root->fileName,ambig)); // add the member to the global list if (mn) @@ -715,6 +815,10 @@ static MemberDef *addVariableToFile(Entry *root,MemberDef::MemberType mtype, md->setFromAnnonymousScope(fromAnnScope); md->setFromAnnonymousMember(fromAnnMemb); md->setIndentDepth(indentDepth); + md->setBodyLine(root->bodyLine); + bool ambig; + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + md->setBodyDef(fd); // see if the function is inside a namespace NamespaceDef *nd = 0; @@ -730,11 +834,7 @@ static MemberDef *addVariableToFile(Entry *root,MemberDef::MemberType mtype, else { // find file definition - FileDef *fd=0; - bool ambig; - if (root->fileName.length()>0 && - (fd=findFileDef(&inputNameDict,root->fileName,ambig)) - ) + if (fd) { fd->insertMember(md); md->setFileDef(fd); @@ -810,10 +910,11 @@ void buildVarList(Entry *root) { Debug::print(Debug::Variables,0, "VARIABLE_SEC: \n" - " type=`%s' name=`%s' args=`%s'\n", + " type=`%s' name=`%s' args=`%s' bodyLine=`%d'\n", root->type.data(), root->name.data(), - root->args.data() + root->args.data(), + root->bodyLine ); //printf("root->parent->name=%s\n",root->parent->name.data()); @@ -978,13 +1079,15 @@ void buildMemberList(Entry *root) { Debug::print(Debug::Functions,0, "FUNCTION_SEC:\n" - " `%s' `%s'::`%s' `%s' relates=`%s' file=`%s' #targs=%d #mtargs=%d mGrpId=%d\n", + " `%s' `%s'::`%s' `%s' relates=`%s' file=`%s' line=`%d' bodyLine=`%d' #targs=%d #mtargs=%d mGrpId=%d\n", root->type.data(), root->parent->name.data(), root->name.data(), root->args.data(), root->relates.data(), root->fileName.data(), + root->startLine, + root->bodyLine, root->tArgList ? (int)root->tArgList->count() : -1, root->mtArgList ? (int)root->mtArgList->count() : -1, root->mGrpId @@ -1053,9 +1156,12 @@ void buildMemberList(Entry *root) md->setDefLine(root->startLine); md->setDocumentation(root->doc); md->setBriefDescription(root->brief); - md->setBody(root->body); + //md->setBody(root->body); + md->setBodyLine(root->bodyLine); md->setGroupId(root->mGrpId); md->setInline(root->inLine); + bool ambig; + md->setBodyDef(findFileDef(&inputNameDict,root->fileName,ambig)); //md->setScopeTemplateArguments(root->tArgList); md->addSectionsToDefinition(root->anchors); QCString def; @@ -1167,7 +1273,6 @@ void buildMemberList(Entry *root) { if (md->getFileDef() && md->getFileDef()->absFilePath()==root->fileName && - /*matchArguments(md->argsString(),root->args)*/ matchArguments(md->argumentList(),root->argList) ) { @@ -1182,6 +1287,12 @@ void buildMemberList(Entry *root) { md->setBriefDescription(root->brief); } + if (md->getBodyLine()==-1 && root->bodyLine!=-1) + { + md->setBodyLine(root->bodyLine); + bool ambig; + md->setBodyDef(findFileDef(&inputNameDict,root->fileName,ambig)); + } md->addSectionsToDefinition(root->anchors); } md=mn->next(); @@ -1189,8 +1300,8 @@ void buildMemberList(Entry *root) } if (!found) /* global function is unique with respect to the file */ { - //printf("New function type=`%s' name=`%s' args=`%s'\n", - // root->type.data(),root->name.data(),root->args.data()); + //printf("New function type=`%s' name=`%s' args=`%s' bodyLine=%d\n", + // root->type.data(),root->name.data(),root->args.data(),root->bodyLine); // new global function QCString name=removeRedundantWhiteSpace(root->name); @@ -1202,7 +1313,11 @@ void buildMemberList(Entry *root) md->setDocumentation(root->doc); md->setBriefDescription(root->brief); md->setPrototype(root->proto); - md->setBody(root->body); + //md->setBody(root->body); + md->setBodyLine(root->bodyLine); + bool ambig; + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + md->setBodyDef(fd); md->addSectionsToDefinition(root->anchors); md->setGroupId(root->mGrpId); md->setInline(root->inLine); @@ -1257,11 +1372,12 @@ void buildMemberList(Entry *root) else { // find file definition - FileDef *fd=0; - bool ambig; - if (root->fileName.length()>0 && - (fd=findFileDef(&inputNameDict,root->fileName,ambig)) - ) + //FileDef *fd=0; + //bool ambig; + //if (root->fileName.length()>0 && + // (fd=findFileDef(&inputNameDict,root->fileName,ambig)) + // ) + if (fd) { // add member to the file fd->insertMember(md); @@ -1341,7 +1457,6 @@ void findFriends() ) // if the member is related and the arguments match then the // function is actually a friend. { - //printf("Found friend function\n"); mergeArguments(mmd->argumentList(),fmd->argumentList()); if (fmd->documentation()) mmd->setDocumentation(fmd->documentation()); @@ -1351,6 +1466,10 @@ void findFriends() mmd->setBriefDescription(fmd->briefDescription()); else if (mmd->briefDescription() && !fmd->briefDescription()) fmd->setBriefDescription(mmd->briefDescription()); + if (mmd->getBodyLine()==-1 && fmd->getBodyLine()!=-1) + mmd->setBodyLine(fmd->getBodyLine()); + else if (mmd->getBodyLine()!=-1 && fmd->getBodyLine()==-1) + fmd->setBodyLine(mmd->getBodyLine()); } } } @@ -1399,6 +1518,16 @@ void transferFunctionDocumentation() { mdef->setDocumentation(mdec->documentation()); } + if (mdec->getBodyLine()!=-1 && mdef->getBodyLine()==-1) + { + mdef->setBodyLine(mdec->getBodyLine()); + mdef->setBodyDef(mdec->getFileDef()); + } + else if (mdef->getBodyLine()!=-1 && mdec->getBodyLine()==-1) + { + mdec->setBodyLine(mdef->getBodyLine()); + mdec->setBodyDef(mdef->getFileDef()); + } } } } @@ -1451,7 +1580,7 @@ void computeClassRelations(Entry *root) QCString cName=removeRedundantWhiteSpace(scopePrefix+bi->name); //printf("Base class %s\n",cName.data()); ClassDef *baseClass=getClass(cName); - if (baseClass) // base class is documented + if (baseClass && cName!=cd->name()) // base class is documented { //printf("Adding!\n"); // add base class to this class @@ -1486,7 +1615,7 @@ void computeClassRelations(Entry *root) // ); int i; QCString templSpec; - if (!baseClass && (i=baseClassName.find('<'))!=-1) + if (baseClass==0 && (i=baseClassName.find('<'))!=-1) // base class has template specifiers { // TODO: here we should try to find the correct template specialization @@ -1495,42 +1624,64 @@ void computeClassRelations(Entry *root) baseClass=getClass(baseClassName); templSpec=bi->name.right(bi->name.length()-i); } - if (baseClass) // base class is documented + + bool found=baseClass!=0; + NamespaceDef *nd=cd->getNamespace(); + if (!found) + { + FileDef *fd=cd->getFileDef(); + if (fd) + { + // look for the using statement in this file in which the + // class was found + NamespaceList *nl = fd->getUsedNamespaces(); + if (nl) // try to prepend any of the using namespace scopes. + { + NamespaceListIterator nli(*nl); + NamespaceDef *nd; + for (nli.toFirst() ; (nd=nli.current()) && !found ; ++nli) + { + found = (baseClass=getClass(nd->name()+"::"+baseClassName)); + } + } + } + if (!found && nd) // class is inside a namespace + { + NamespaceList *nl = nd->getUsedNamespaces(); + found = (baseClass=getClass(nd->name()+"::"+baseClassName)); + if (nl) // try to prepend any of the using namespace scopes. + { + NamespaceListIterator nli(*nl); + NamespaceDef *nd; + for (nli.toFirst() ; (nd=nli.current()) && !found ; ++nli) + { + found = (baseClass=getClass(nd->name()+"::"+baseClassName)); + } + } + } + } + if (found) { // add base class to this class cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec); // add this class as super class to the base class baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec); } - else // base class not documented + else { - NamespaceDef *nd=cd->getNamespace(); - //printf("Found undocumented base class `%s' namespace scope=`%s'\n", - // bi->name.data(),nd ? nd->name().data() : "<none>"); - if (nd && (baseClass=getClass(nd->name()+"::"+baseClassName))) - // class is defined inside namespace - { - // add base class to this class - cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec); - // add this class as super class to the base class - baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec); - } - else // undocumented base class - { - //printf(">>> Undocumented base class = %s\n",bi->name.data()); - baseClass=new ClassDef(baseClassName,ClassDef::Class); - // add base class to this class - cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec); - // add this class as super class to the base class - baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec); - // the undocumented base was found in this file - baseClass->insertUsedFile(root->fileName); - // add class to the list - classList.inSort(baseClass); - //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data()); - //classDict.insert(resolveDefines(bi->name),baseClass); - classDict.insert(bi->name,baseClass); - } + //printf(">>> Undocumented base class = %s\n",bi->name.data()); + baseClass=new ClassDef(baseClassName,ClassDef::Class); + // add base class to this class + cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec); + // add this class as super class to the base class + baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec); + // the undocumented base was found in this file + baseClass->insertUsedFile(root->fileName); + // add class to the list + classList.inSort(baseClass); + //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data()); + //classDict.insert(resolveDefines(bi->name),baseClass); + classDict.insert(bi->name,baseClass); } bi=baseList->next(); } @@ -1655,9 +1806,16 @@ void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl, md->setBriefDescription(root->brief); } - if (md->bodyCode().isEmpty() && !root->body.isEmpty()) /* no body yet */ + //if (md->bodyCode().isEmpty() && !root->body.isEmpty()) /* no body yet */ + //{ + // md->setBody(root->body); + //} + if (md->getBodyLine()==-1 && root->bodyLine!=-1) { - md->setBody(root->body); + md->setBodyLine(root->bodyLine); + bool ambig; + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + md->setBodyDef(fd); } } md->setDefFile(root->fileName); @@ -1684,34 +1842,105 @@ void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl, } //---------------------------------------------------------------------- + +static QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &templ) +{ + QCString result=scope.copy(); + if (!templ.isEmpty() && scope.find('<')==-1) + { + int si,pi=0; + while ((si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) + && !getClass(scope.left(si))) + { //printf("Tried `%s'\n",(scope.left(si)+templ).data()); + pi=si+2; + } + if (si==-1) // not nested => append template specifier + { + result+=templ; + } + else // nested => insert template specifier before after first class name + { + result=scope.left(si) + templ + scope.right(scope.length()-si); + } + } + //printf("insertTemplateSpecifierInScope(`%s',`%s')=%s\n", + // scope.data(),templ.data(),result.data()); + return result; +} + +//---------------------------------------------------------------------- +// find a class definition given the scope name and (optionally) a +// template list specifier + +static ClassDef *findClassDefinition(const char *scopeName,const char *classTempList) +{ + ClassDef *tcd=0; + if (classTempList) // try to find the correct specialization + { + tcd=getClass( + insertTemplateSpecifierInScope( + scopeName, + classTempList + ) + ); // try specialization + } + if (tcd==0) + { + tcd=getClass(scopeName); // try general class + } + return tcd; +} + + +//---------------------------------------------------------------------- // Adds the documentation contained in `root' to a global function // with name `name' and argument list `args' (for overloading) and // function declaration `decl' to the corresponding member definition. -bool findUnrelatedFunction(Entry *root, +static bool findUnrelatedFunction(Entry *root, const QCString &namespaceName, const char *name, + const char *tempArg, const char *, const char *decl) { - MemberName *mn=0; QCString n=name; + if (n.length()==0) return FALSE; if (n.find("::")!=-1) return FALSE; // skip undefined class members - //printf("findUnrelatedFunction(%s)\n",name); - if (n.length()>0 && (mn=functionNameDict[n])) // function name defined + //printf("findUnrelatedFunction(namespace=%s,name=%s,tempArg=%s,decl=%s)\n", + // namespaceName.data(),name,tempArg,decl); + MemberName *mn=functionNameDict[n+tempArg]; // look in function dictionary + if (mn==0) + { + mn=functionNameDict[n]; // try with template arguments + } + if (mn) // function name defined { - int count=0; + //int count=0; MemberDef *md=mn->first(); + bool found=FALSE; while (md) { + bool ambig; NamespaceDef *nd=md->getNamespace(); - QCString nsName = nd ? nd->name().data() : ""; - if (namespaceName.length()==0 || - nsName==namespaceName) + //printf("Namespace %s\n",nd ? nd->name().data() : "<none>"); + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + //printf("File %s\n",fd ? fd->name().data() : "<none>"); + NamespaceList *nl = fd ? fd->getUsedNamespaces() : 0; + //printf("NamespaceList %p\n",nl); + bool viaUsingDirective = nl && nd && nl->find(nd)!=-1; + + if ((namespaceName.length()==0 && nd==0) || // not in a namespace + (nd && nd->name()==namespaceName) || // or in the same namespace + viaUsingDirective // member in `using' namespace + ) { + //printf("Adding docs `%s' to member `%s' in namespace `%s'\n", + // root->doc.data(),md->name().data(),namespaceName.data()); //printf("Searching for match between %s and %s\n", // argListToString(md->argumentList()).data(), // argListToString(root->argList).data()); + QCString nsName = nd ? nd->name().data() : ""; bool matching= /*matchArguments(md->argsString(),args);*/ (md->argumentList()==0 && root->argList->count()==0) || @@ -1720,33 +1949,17 @@ bool findUnrelatedFunction(Entry *root, { //printf("Match found\n"); addMemberDocs(root,md,decl,FALSE); - count++; + found=TRUE; } } md=mn->next(); } - if (count==0) // more than one match (each member will get the same docs)! + if (!found) // no match { - warn("Warning: no matching members found for \n%s\n" + warn("Warning: no matching member found for \n%s\n" "in file %s at line %d\n", decl,root->fileName.data(),root->startLine); } -#if 0 - else if (count>1) // no match! - { - warn("Warning: multiple matching members for\n%s\n",decl); - if (mn->count()>0) // there is a member with that name - { - warn("Possible candidates are:\n"); - MemberDef *md=mn->first(); - while (md) // list all possible members with the same name - { - warn(" %s%s\n",md->name(),md->argsString()); - md=mn->next(); - } - } - } -#endif } else // got docs for an undefined member! { @@ -1841,31 +2054,6 @@ void substituteTemplateArgNames(ArgumentList *src, } -QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &templ) -{ - QCString result=scope.copy(); - if (!templ.isEmpty() && scope.find('<')==-1) - { - int si,pi=0; - while ((si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) - && !getClass(scope.left(si))) - { //printf("Tried `%s'\n",(scope.left(si)+templ).data()); - pi=si+2; - } - if (si==-1) // not nested => append template specifier - { - result+=templ; - } - else // nested => insert template specifier before after first class name - { - result=scope.left(si) + templ + scope.right(scope.length()-si); - } - } - //printf("insertTemplateSpecifierInScope(`%s',`%s')=%s\n", - // scope.data(),templ.data(),result.data()); - return result; -} - //---------------------------------------------------------------------- // This function tries to find a member (in a documented class/file/namespace) // that corresponds to the function declaration given in `funcDecl'. @@ -1888,11 +2076,11 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, root->tArgList,tempArgListToString(root->tArgList).data(), root->scopeSpec.data(),root->memberSpec.data(),root->inLine ); - if (Config::includeSourceFlag && !root->body.isEmpty()) - { - //printf("Function: %s\n-----------------\n%s\n------------------\n", - //root->name.data(),root->body.data()); - } + //if (Config::includeSourceFlag && !root->body.isEmpty()) + //{ + // //printf("Function: %s\n-----------------\n%s\n------------------\n", + // //root->name.data(),root->body.data()); + //} QCString scopeName; QCString className; @@ -2181,19 +2369,35 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, ClassDef *cd=md->memberClass(); //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data()); ClassDef *tcd=0; - if (classTempList.length()>0) // try to find the correct specialization - { - tcd=getClass( - insertTemplateSpecifierInScope( - scopeName, - classTempList - ) - ); // try specialization - } + + tcd = findClassDefinition(scopeName,classTempList); + if (tcd==0) { - tcd=getClass(scopeName); // try general class + bool ambig; + NamespaceDef *nd = 0; + FileDef *fd = 0; + NamespaceList *nl = 0; + if (namespaceName.length()>0 && (nd=namespaceDict[namespaceName])) + { + nl=nd->getUsedNamespaces(); + } + else if ((fd=findFileDef(&inputNameDict,root->fileName,ambig))) + { + nl=fd->getUsedNamespaces(); + } + if (nl) + { + NamespaceListIterator nli(*nl); + NamespaceDef *nd; + for (;(nd=nli.current()) && tcd==0;++nli) + { + //printf("Trying with scope=%s\n",nd->name().data()); + tcd = findClassDefinition(nd->name()+"::"+scopeName,classTempList); + } + } } + if (cd && tcd==cd) // member's classes match { Debug::print(Debug::FindMembers,0, @@ -2375,7 +2579,11 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, md->setDefLine(root->startLine); md->setPrototype(root->proto); md->addSectionsToDefinition(root->anchors); - md->setBody(root->body); + //md->setBody(root->body); + md->setBodyLine(root->bodyLine); + bool ambig; + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + md->setBodyDef(fd); md->setInline(root->inLine); mn->inSort(md); cd->insertMember(md); @@ -2384,7 +2592,7 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, } else // unrelated function with the same name as a member { - if (!findUnrelatedFunction(root,namespaceName,funcName+funcTempList,funcArgs,funcDecl)) + if (!findUnrelatedFunction(root,namespaceName,funcName,funcTempList,funcArgs,funcDecl)) { warn("Warning: Cannot determine class for function\n%s\n" "in file %s at line %d\n",fullFuncDecl.data(), @@ -2416,9 +2624,11 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, } if (!newMember && rmd) // member already exists as rmd -> add docs { + //printf("addMemberDocs for related member %s\n",root->name.data()); addMemberDocs(root,rmd,funcDecl,overloaded); } } + if (newMember) // need to create a new member { MemberDef::MemberType mtype; @@ -2433,16 +2643,55 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, MemberDef *md=new MemberDef(funcType,funcName,funcArgs,exceptions, root->protection,root->virt,root->stat,TRUE, mtype,root->tArgList,root->argList); - //printf("Related member name=`%s' decl=`%s'\n",funcName.data(),funcDecl.data()); + //printf("Related member name=`%s' decl=`%s' bodyLine=`%d'\n", + // funcName.data(),funcDecl.data(),root->bodyLine); + + // try to find the matching line number of the body from the + // global function list + bool found=FALSE; + if (root->bodyLine==-1) + { + MemberName *rmn=functionNameDict[funcName]; + if (rmn) + { + MemberDef *rmd=rmn->first(); + while (rmd && !found) // see if we got another member with matching arguments + { + // check for matching argument lists + if (matchArguments(rmd->argumentList(), + root->argList, + className, + namespaceName) + ) + { + found=TRUE; + } + if (!found) rmd=rmn->next(); + } + if (rmd) // member found -> copy line number info + { + md->setBodyLine(rmd->getBodyLine()); + md->setBodyDef(rmd->getBodyDef()); + } + } + } + if (!found) // line number could not be found or is available in this + // entry + { + md->setBodyLine(root->bodyLine); + bool ambig; + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + md->setBodyDef(fd); + } + md->setMemberClass(cd); + md->setInline(root->inLine); md->setDefinition(funcDecl); - md->setDocumentation(root->doc); - md->setBriefDescription(root->brief); md->setDefFile(root->fileName); md->setDefLine(root->startLine); md->setPrototype(root->proto); - md->setBody(root->body); - md->setInline(root->inLine); + md->setDocumentation(root->doc); + md->setBriefDescription(root->brief); md->addSectionsToDefinition(root->anchors); mn->inSort(md); cd->insertMember(md); @@ -2464,7 +2713,7 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, else // unrelated not overloaded member found { if (className.length()==0 && - !findUnrelatedFunction(root,namespaceName,funcName+funcTempList,funcArgs,funcDecl)) + !findUnrelatedFunction(root,namespaceName,funcName,funcTempList,funcArgs,funcDecl)) { warn("Warning: class for member %s (file %s at line %d) cannot " "be found\n", funcName.data(),root->fileName.data(), @@ -2526,7 +2775,7 @@ void findMemberDocumentation(Entry *root) else if (root->section==Entry::FUNCTION_SEC && (!root->doc.isEmpty() || !root->brief.isEmpty() || - !root->body.isEmpty() || root->mGrpId!=-1 /*|| Config::extractAllFlag*/ + root->bodyLine!=-1 || root->mGrpId!=-1 /*|| Config::extractAllFlag*/ || root->inLine ) ) @@ -2656,6 +2905,10 @@ void findEnums(Entry *root) if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd); md->setDefFile(root->fileName); md->setDefLine(root->startLine); + md->setBodyLine(root->bodyLine); + bool ambig; + md->setBodyDef(findFileDef(&inputNameDict,root->fileName,ambig)); + //printf("Enum definition at line %d of %s\n",root->bodyLine,root->fileName.data()); md->addSectionsToDefinition(root->anchors); if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') { @@ -3163,6 +3416,90 @@ void generateFileDocs() } //---------------------------------------------------------------------------- + +void generateSources() +{ + if (Config::sourceBrowseFlag) + { + writeSourceIndex(*outputList); + + if (inputNameList.count()>0) + { + FileName *fn=inputNameList.first(); + while (fn) + { + FileDef *fd=fn->first(); + while (fd) + { + msg("Generating source listing for file %s...\n",fd->name().data()); + fd->writeSource(*outputList); + fd=fn->next(); + } + fn=inputNameList.next(); + } + } + } +} + +void addSourceReferences() +{ + ClassListIterator cli(classList); + ClassDef *cd=0; + for (cli.toFirst();(cd=cli.current());++cli) + { + FileDef *fd=cd->getBodyDef(); + if (fd && cd->isLinkableInProject() && cd->getBodyLine()!=-1) + { + fd->addSourceRef(cd->getBodyLine(),cd,0); + } + } + MemberNameListIterator mnli(memberNameList); + MemberName *mn=0; + for (mnli.toFirst();(mn=mnli.current());++mnli) + { + MemberNameIterator mni(*mn); + MemberDef *md=0; + for (mni.toFirst();(md=mni.current());++mni) + { + ClassDef *cd=md->memberClass(); + FileDef *fd=md->getBodyDef(); + if (fd && cd && cd->isLinkableInProject() && md->getBodyLine()!=-1 && + md->isLinkableInProject()) + { + //printf("Found member `%s' in file `%s' at line `%d'\n", + // md->name().data(),fd->name().data(),md->getBodyLine()); + Definition *d=cd; + if (d==0) d=md->getNamespace(); + if (d==0) d=md->getFileDef(); + fd->addSourceRef(md->getBodyLine(),d,md->anchor()); + } + } + } + MemberNameListIterator fnli(functionNameList); + for (fnli.toFirst();(mn=fnli.current());++fnli) + { + MemberNameIterator mni(*mn); + MemberDef *md=0; + for (mni.toFirst();(md=mni.current());++mni) + { + NamespaceDef *nd=md->getNamespace(); + FileDef *fd=md->getBodyDef(); + if (md->getBodyLine()!=-1 && md->isLinkableInProject() && + (nd && nd->isLinkableInProject()) || + (fd && fd->isLinkableInProject()) + ) + { + //printf("Found member `%s' in file `%s' at line `%d'\n", + // md->name().data(),fd->name().data(),md->getBodyLine()); + Definition *d=md->getFileDef(); + if (d==0) d=md->getNamespace(); + fd->addSourceRef(md->getBodyLine(),d,md->anchor()); + } + } + } +} + +//---------------------------------------------------------------------------- // generate the documentation of all classes void generateClassDocs() @@ -3281,13 +3618,18 @@ void findDefineDocumentation(Entry *root) md->setDocumentation(root->doc); if (md->briefDescription().isEmpty()) md->setBriefDescription(root->brief); + md->setBodyLine(root->bodyLine); + bool ambig; + md->setBodyDef(findFileDef(&inputNameDict,root->fileName,ambig)); md->addSectionsToDefinition(root->anchors); } md=mn->next(); } } - else if (count>1 && (root->doc.length()>0 || root->brief.length()>0)) + else if (count>1 && + (root->doc.length()>0 || root->brief.length()>0 || root->bodyLine!=-1)) // multiple defines don't know where to add docs + // but maybe they are in different files together with their documentation { md=mn->first(); while (md) @@ -3302,6 +3644,9 @@ void findDefineDocumentation(Entry *root) md->setDocumentation(root->doc); if (md->briefDescription().isEmpty()) md->setBriefDescription(root->brief); + md->setBodyLine(root->bodyLine); + bool ambig; + md->setBodyDef(findFileDef(&inputNameDict,root->fileName,ambig)); md->addSectionsToDefinition(root->anchors); } } @@ -3398,6 +3743,7 @@ void findMainPage(Entry *root) //printf("Found main page! \n======\n%s\n=======\n",root->doc.data()); mainPage = new PageInfo("index", root->doc, root->args.stripWhiteSpace()); + setFileNameForSections(root->anchors,"index"); } else { @@ -3533,7 +3879,9 @@ void generateExampleDocs() msg("Generating docs for example %s...\n",pi->name.data()); QCString n=convertSlashes(pi->name,TRUE)+"-example"; startFile(*outputList,n,"Example Documentation"); - //outputList->writeTitle(pi->name,pi->name); + startTitle(*outputList,n); + outputList->docify(pi->name); + endTitle(*outputList,n,0); parseExample(*outputList,pi->doc+"\n\\include "+pi->name,pi->name); endFile(*outputList); pi=exampleList.next(); @@ -3740,25 +4088,39 @@ void generateSearchIndex() void generateConfigFile(const char *configFile,bool shortList) { - QFileInfo fi(configFile); - QFile f(configFile); - - if (fi.exists()) // create a backup + QFile f; + bool fileOpened=FALSE; + bool writeToStdout=(configFile[0]=='-' && configFile[1]==0); + if (writeToStdout) // write to stdout { - QDir dir=fi.dir(); - dir.rename(fi.fileName(),fi.fileName()+".bak"); - } - if (f.open(IO_WriteOnly)) + fileOpened = f.open(IO_WriteOnly,stdout); + } + else // write to file + { + QFileInfo fi(configFile); + if (fi.exists()) // create a backup + { + QDir dir=fi.dir(); + dir.rename(fi.fileName(),fi.fileName()+".bak"); + } + f.setName(configFile); + fileOpened = f.open(IO_WriteOnly); + } + + if (fileOpened) { writeTemplateConfig(&f,shortList); f.close(); - msg("\n\nConfiguration file `%s' created.\n\n",configFile); - msg("Now edit the configuration file and enter\n\n"); - if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile")) - msg(" doxygen %s\n\n",configFile); - else - msg(" doxygen\n\n"); - msg("to generate the documentation for your project\n\n"); + if (!writeToStdout) + { + msg("\n\nConfiguration file `%s' created.\n\n",configFile); + msg("Now edit the configuration file and enter\n\n"); + if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile")) + msg(" doxygen %s\n\n",configFile); + else + msg(" doxygen\n\n"); + msg("to generate the documentation for your project\n\n"); + } } else { @@ -3869,6 +4231,37 @@ void copyAndFilterFile(const char *fileName,BufStr &dest) } //---------------------------------------------------------------------------- +void copyStyleSheet() +{ + if (!Config::htmlStyleSheet.isEmpty()) + { + QFile cssf(Config::htmlStyleSheet); + if (cssf.open(IO_ReadOnly)) + { + QCString destFileName = Config::htmlOutputDir+"/"+Config::htmlStyleSheet; + QFile df(destFileName); + if (df.open(IO_WriteOnly)) + { + char *buffer = new char[cssf.size()]; + cssf.readBlock(buffer,cssf.size()); + df.writeBlock(buffer,cssf.size()); + df.flush(); + delete buffer; + } + else + { + warn("Warning: could not write to style sheet %s\n",destFileName.data()); + } + } + else + { + warn("Warning: could not open user specified style sheet %s\n",Config::htmlStyleSheet.data()); + Config::htmlStyleSheet.resize(0); // revert to the default + } + } +} + +//---------------------------------------------------------------------------- // Reads a file to a string. // The name of the file is written in front of the file's contents and // between 0x06 markers @@ -3970,7 +4363,7 @@ int readDir(QFileInfo *fi, } else { - fn = new FileName(name); + fn = new FileName(cfi->absFilePath(),name); fn->append(fd); if (fnList) fnList->inSort(fn); fnDict->insert(name,fn); @@ -4071,7 +4464,7 @@ int readFileOrDirectory(const char *s, } else { - fn = new FileName(name); + fn = new FileName(fi.absFilePath(),name); fn->append(fd); if (fnList) fnList->inSort(fn); fnDict->insert(name,fn); @@ -4133,10 +4526,12 @@ void usage(const char *name) msg("You can use doxygen in two ways:\n\n"); msg("1) Use doxygen to generate a template configuration file:\n"); msg(" %s [-s] -g [configName]\n\n",name); - msg(" if -s is specified the comments in the config file will be omitted.\n\n"); + msg(" If -s is specified the comments in the config file will be omitted.\n"); + msg(" If - is used for configName doxygen will write to standard output.\n\n"); msg("2) Use doxygen to generate documentation using an existing "); msg("configuration file:\n"); msg(" %s [configName]\n\n",name); + msg(" If - is used for configName doxygen will read from standard input.\n\n"); msg("If configName is omitted `Doxyfile' will be used as a default.\n\n"); exit(1); } @@ -4172,7 +4567,9 @@ int main(int argc,char **argv) const char *debugLabel; bool genConfig=FALSE; bool shortList=FALSE; - while (optind<argc && argv[optind][0]=='-') + while (optind<argc && argv[optind][0]=='-' && + (isalpha(argv[optind][1]) || argv[optind][1]=='?') + ) { switch(argv[optind][1]) { @@ -4230,6 +4627,7 @@ int main(int argc,char **argv) parseConfig(config); checkConfig(); + spaces.fill(' ',Config::tabSize); /************************************************************************** * Initialize output generators * @@ -4241,6 +4639,7 @@ int main(int argc,char **argv) outputList->add(new HtmlGenerator); HtmlGenerator::init(); if (Config::htmlHelpFlag) HtmlHelp::getInstance()->initialize(); + copyStyleSheet(); } if (Config::generateLatex) { @@ -4271,11 +4670,20 @@ int main(int argc,char **argv) s=Config::examplePath.first(); while (s) { - readFileOrDirectory(s,0,&exampleNameDict,0,&Config::filePatternList, - &Config::excludePatternList,0,0); + readFileOrDirectory(s,0,&exampleNameDict,0,&Config::examplePatternList, + 0,0,0); s=Config::examplePath.next(); } + msg("Searching for images...\n"); + s=Config::imagePath.first(); + while (s) + { + readFileOrDirectory(s,0,&imageNameDict,0,&Config::imagePatternList, + 0,0,0); + s=Config::imagePath.next(); + } + msg("Searching for files to exclude\n"); s=Config::excludeSources.first(); while (s) @@ -4361,6 +4769,7 @@ int main(int argc,char **argv) msg("Building namespace list...\n"); buildNamespaceList(root); + findUsingDirectives(root); msg("Building group list...\n"); buildGroupList(root); @@ -4431,6 +4840,9 @@ int main(int argc,char **argv) msg("Determining member group documentation...\n"); computeMemberGroupDocumentation(); + + msg("Adding source references...\n"); + addSourceReferences(); //unrelatedFunctionsUsed=hasUnrelatedFunctions(); @@ -4472,6 +4884,9 @@ int main(int argc,char **argv) msg("Generating file documentation...\n"); generateFileDocs(); + msg("Generating source listings...\n"); + generateSources(); + msg("Generating class documentation...\n"); generateClassDocs(); |