summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDimitri van Heesch <dimitri@stack.nl>2006-10-04 20:28:41 (GMT)
committerDimitri van Heesch <dimitri@stack.nl>2006-10-04 20:28:41 (GMT)
commitca720513ae89ad82fd8d8c4340271375ae1e9f64 (patch)
treed2526ce0c99b1f268769fd8bd1c56e6dda83fd7f /src
parentb1dbef9886c3bf49050a5f49b9ae9d12021e4b50 (diff)
downloadDoxygen-ca720513ae89ad82fd8d8c4340271375ae1e9f64.zip
Doxygen-ca720513ae89ad82fd8d8c4340271375ae1e9f64.tar.gz
Doxygen-ca720513ae89ad82fd8d8c4340271375ae1e9f64.tar.bz2
Release-1.4.7-20061004
Diffstat (limited to 'src')
-rw-r--r--src/classdef.cpp85
-rw-r--r--src/classdef.h8
-rw-r--r--src/code.l3
-rw-r--r--src/commentscan.l278
-rw-r--r--src/definition.cpp88
-rw-r--r--src/definition.h14
-rw-r--r--src/docparser.cpp11
-rw-r--r--src/doxygen.cpp247
-rw-r--r--src/doxygen.h6
-rw-r--r--src/filedef.cpp20
-rw-r--r--src/filedef.h1
-rw-r--r--src/lockingptr.h5
-rw-r--r--src/marshal.h12
-rw-r--r--src/memberdef.cpp122
-rw-r--r--src/memberdef.h11
-rw-r--r--src/membergroup.cpp1
-rw-r--r--src/memberlist.cpp3
-rw-r--r--src/namespacedef.cpp32
-rw-r--r--src/namespacedef.h2
-rw-r--r--src/objcache.cpp33
-rw-r--r--src/pre.l14
-rw-r--r--src/translator_jp.h26
-rw-r--r--src/util.cpp233
-rw-r--r--src/util.h6
24 files changed, 829 insertions, 432 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp
index 1470ee3..8dffbd9 100644
--- a/src/classdef.cpp
+++ b/src/classdef.cpp
@@ -168,6 +168,8 @@ class ClassDefImpl
* groups?
*/
bool subGrouping;
+
+ bool usedOnly;
};
void ClassDefImpl::init(const char *defFileName, const char *name,
@@ -206,6 +208,7 @@ void ClassDefImpl::init(const char *defFileName, const char *name,
isTemplArg = FALSE;
membersMerged = FALSE;
categoryOf = 0;
+ usedOnly = FALSE;
QCString ns;
extractNamespaceName(name,className,ns);
//printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data());
@@ -258,78 +261,11 @@ ClassDef::ClassDef(
m_impl->isObjC = FALSE;
m_impl->init(defFileName,name(),compoundTypeString(),fName);
-#if 0
- m_compType=ct;
- m_isObjC = FALSE;
- QCString compoundName=compoundTypeString();
- if (fName)
- {
- m_fileName=stripExtension(fName);
- }
- else
- {
- m_fileName=compoundName+name();
- }
- m_exampleSDict = 0;
- m_inherits = 0;
- m_inheritedBy = 0;
- m_allMemberNameInfoSDict = 0;
- m_incInfo=0;
- m_tempArgs=0;
- m_prot=Public;
- m_nspace=0;
- m_fileDef=0;
- m_usesImplClassDict=0;
- m_usedByImplClassDict=0;
- m_usesIntfClassDict=0;
- memberGroupSDict = 0;
- m_innerClasses = 0;
- m_subGrouping=Config_getBool("SUBGROUPING");
- m_templateInstances = 0;
- m_variableInstances = 0;
- m_templateMaster =0;
- m_templBaseClassNames = 0;
- m_artificial = FALSE;
- m_isAbstract = FALSE;
- m_isStatic = FALSE;
- m_isTemplArg = FALSE;
- m_membersMerged = FALSE;
- m_categoryOf = 0;
- QCString ns;
- extractNamespaceName(name(),m_className,ns);
- //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data());
-
- if (((QCString)defFileName).right(5)!=".java" &&
- guessSection(defFileName)==Entry::SOURCE_SEC)
- {
- m_isLocal=TRUE;
- }
- else
- {
- m_isLocal=FALSE;
- }
-#endif
}
// destroy the class definition
ClassDef::~ClassDef()
{
-#if 0
- delete m_inherits;
- delete m_inheritedBy;
- delete m_allMemberNameInfoSDict;
- delete m_exampleSDict;
- delete m_usesImplClassDict;
- delete m_usedByImplClassDict;
- delete m_usesIntfClassDict;
- delete m_incInfo;
- delete memberGroupSDict;
- delete m_innerClasses;
- delete m_templateInstances;
- delete m_variableInstances;
- delete m_templBaseClassNames;
- delete m_tempArgs;
-#endif
delete m_impl;
}
@@ -3080,6 +3016,11 @@ MemberDef *ClassDef::getMemberByName(const QCString &name) const
return xmd;
}
+bool ClassDef::isAccessibleMember(MemberDef *md)
+{
+ return md->getClassDef() && isBaseClass(md->getClassDef(),TRUE);
+}
+
MemberList *ClassDef::createMemberList(MemberList::ListType lt)
{
m_impl->memberLists.setAutoDelete(TRUE);
@@ -3321,3 +3262,13 @@ void ClassDef::setCategoryOf(ClassDef *cd)
m_impl->categoryOf = cd;
}
+void ClassDef::setUsedOnly(bool b)
+{
+ m_impl->usedOnly = b;
+}
+
+bool ClassDef::isUsedOnly() const
+{
+ return m_impl->usedOnly;
+}
+
diff --git a/src/classdef.h b/src/classdef.h
index c417244..3646d9b 100644
--- a/src/classdef.h
+++ b/src/classdef.h
@@ -188,6 +188,11 @@ class ClassDef : public Definition
*/
bool isBaseClass(ClassDef *bcd,bool followInstances,int level=0);
+ /*! returns TRUE iff \a md is a member of this class or of the
+ * the public/protected members of a base class
+ */
+ bool isAccessibleMember(MemberDef *md);
+
/*! Returns a sorted dictionary with all template instances found for
* this template class. Returns 0 if not a template or no instances.
*/
@@ -258,6 +263,8 @@ class ClassDef : public Definition
ClassDef *getVariableInstance(const char *templSpec);
+ bool isUsedOnly() const;
+
//-----------------------------------------------------------------------------------
// --- setters ----
//-----------------------------------------------------------------------------------
@@ -290,6 +297,7 @@ class ClassDef : public Definition
void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec);
void makeTemplateArgument(bool b=TRUE);
void setCategoryOf(ClassDef *cd);
+ void setUsedOnly(bool b);
//-----------------------------------------------------------------------------------
// --- actions ----
diff --git a/src/code.l b/src/code.l
index f14434e..16a1dc3 100644
--- a/src/code.l
+++ b/src/code.l
@@ -798,7 +798,7 @@ static bool getLinkInScope(const QCString &c, // scope
FileDef *fd;
NamespaceDef *nd;
GroupDef *gd;
- //printf("Trying `%s'::`%s'\n",c.data(),m.data());
+ //printf("getLinkInScope: trying `%s'::`%s'\n",c.data(),m.data());
if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) &&
md->isLinkable())
{
@@ -851,6 +851,7 @@ static bool getLink(const char *className,
CodeOutputInterface &ol,
const char *text=0)
{
+ //printf("getLink(%s,%s)\n",className,memberName);
QCString m=removeRedundantWhiteSpace(memberName);
QCString c=className;
if (!getLinkInScope(c,m,memberName,ol,text))
diff --git a/src/commentscan.l b/src/commentscan.l
index 95404b5..dc80846 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -107,96 +107,125 @@ static bool handlePublicSection(const QCString &s);
static bool handleInherit(const QCString &);
typedef bool (*DocCmdFunc)(const QCString &name);
-
+
struct DocCmdMap
{
const char *cmdName;
DocCmdFunc handler;
+ bool endsBrief;
};
// map of command to handler function
static DocCmdMap docCmdMap[] =
{
- { "brief", &handleBrief },
- { "short", &handleBrief },
- { "fn", &handleFn },
- { "var", &handleFn },
- { "typedef", &handleFn },
- { "property", &handleFn },
- { "def", &handleDef },
- { "overload", &handleOverload },
- { "enum", &handleEnum },
- { "defgroup", &handleDefGroup },
- { "addtogroup", &handleAddToGroup },
- { "weakgroup", &handleWeakGroup },
- { "namespace", &handleNamespace },
- { "package", &handlePackage },
- { "class", &handleClass },
- { "protocol", &handleProtocol },
- { "category", &handleCategory },
- { "union", &handleUnion },
- { "struct", &handleStruct },
- { "interface", &handleInterface },
- { "idlexcept", &handleIdlException },
- { "page", &handlePage },
- { "mainpage", &handleMainpage },
- { "file", &handleFile },
- { "dir", &handleDir },
- { "example", &handleExample },
- { "details", &handleDetails },
- { "name", &handleName },
- { "todo", &handleTodo },
- { "test", &handleTest },
- { "bug", &handleBug },
- { "deprecated", &handleDeprecated },
- { "xrefitem", &handleXRefItem },
- { "related", &handleRelated },
- { "relates", &handleRelated },
- { "relatedalso", &handleRelatedAlso },
- { "relatesalso", &handleRelatedAlso },
- { "refitem", &handleRefItem },
- { "subpage", &handleSubpage },
- { "section", &handleSection },
- { "subsection", &handleSection },
- { "subsubsection", &handleSection },
- { "paragraph", &handleSection },
- { "anchor", &handleAnchor },
- { "verbatim", &handleFormatBlock },
- { "latexonly", &handleFormatBlock },
- { "htmlonly", &handleFormatBlock },
- { "xmlonly", &handleFormatBlock },
- { "rtfonly", &handleFormatBlock },
- { "manonly", &handleFormatBlock },
- { "dot", &handleFormatBlock },
- { "code", &handleFormatBlock },
- { "addindex", &handleAddIndex },
- { "if", &handleIf },
- { "ifnot", &handleIfNot },
- { "elseif", &handleElseIf },
- { "else", &handleElse },
- { "endif", &handleEndIf },
- { "ingroup", &handleIngroup },
- { "nosubgrouping", &handleNoSubGrouping },
- { "showinitializer", &handleShowInitializer },
- { "hideinitializer", &handleHideInitializer },
- { "callgraph", &handleCallgraph },
- { "callergraph", &handleCallergraph },
- { "internal", &handleInternal },
- { "_linebr", &handleLineBr },
- { "static", &handleStatic },
- { "pure", &handlePure },
- { "private", &handlePrivate},
- { "privatesection", &handlePrivateSection },
- { "protected", &handleProtected },
- { "protectedsection",&handleProtectedSection },
- { "public", &handlePublic },
- { "publicsection", &handlePublicSection },
- { "inherit", &handleInherit },
- { 0, 0 }
+ // command name handler function ends brief description
+ { "brief", &handleBrief, FALSE },
+ { "short", &handleBrief, FALSE },
+ { "fn", &handleFn, TRUE },
+ { "var", &handleFn, TRUE },
+ { "typedef", &handleFn, TRUE },
+ { "property", &handleFn, TRUE },
+ { "def", &handleDef, TRUE },
+ { "overload", &handleOverload, TRUE },
+ { "enum", &handleEnum, TRUE },
+ { "defgroup", &handleDefGroup, TRUE },
+ { "addtogroup", &handleAddToGroup, TRUE },
+ { "weakgroup", &handleWeakGroup, TRUE },
+ { "namespace", &handleNamespace, TRUE },
+ { "package", &handlePackage, TRUE },
+ { "class", &handleClass, TRUE },
+ { "protocol", &handleProtocol, TRUE },
+ { "category", &handleCategory, TRUE },
+ { "union", &handleUnion, TRUE },
+ { "struct", &handleStruct, TRUE },
+ { "interface", &handleInterface, TRUE },
+ { "idlexcept", &handleIdlException, TRUE },
+ { "page", &handlePage, TRUE },
+ { "mainpage", &handleMainpage, TRUE },
+ { "file", &handleFile, TRUE },
+ { "dir", &handleDir, TRUE },
+ { "example", &handleExample, TRUE },
+ { "details", &handleDetails, TRUE },
+ { "name", &handleName, TRUE },
+ { "todo", &handleTodo, TRUE },
+ { "test", &handleTest, TRUE },
+ { "bug", &handleBug, TRUE },
+ { "deprecated", &handleDeprecated, TRUE },
+ { "xrefitem", &handleXRefItem, TRUE },
+ { "related", &handleRelated, TRUE },
+ { "relates", &handleRelated, TRUE },
+ { "relatedalso", &handleRelatedAlso, TRUE },
+ { "relatesalso", &handleRelatedAlso, TRUE },
+ { "refitem", &handleRefItem, TRUE },
+ { "subpage", &handleSubpage, TRUE },
+ { "section", &handleSection, TRUE },
+ { "subsection", &handleSection, TRUE },
+ { "subsubsection", &handleSection, TRUE },
+ { "paragraph", &handleSection, TRUE },
+ { "anchor", &handleAnchor, TRUE },
+ { "verbatim", &handleFormatBlock, TRUE },
+ { "latexonly", &handleFormatBlock, FALSE },
+ { "htmlonly", &handleFormatBlock, FALSE },
+ { "xmlonly", &handleFormatBlock, FALSE },
+ { "rtfonly", &handleFormatBlock, FALSE },
+ { "manonly", &handleFormatBlock, FALSE },
+ { "dot", &handleFormatBlock, TRUE },
+ { "code", &handleFormatBlock, TRUE },
+ { "addindex", &handleAddIndex, TRUE },
+ { "if", &handleIf, FALSE },
+ { "ifnot", &handleIfNot, FALSE },
+ { "elseif", &handleElseIf, FALSE },
+ { "else", &handleElse, FALSE },
+ { "endif", &handleEndIf, FALSE },
+ { "ingroup", &handleIngroup, TRUE },
+ { "nosubgrouping", &handleNoSubGrouping, TRUE },
+ { "showinitializer", &handleShowInitializer, TRUE },
+ { "hideinitializer", &handleHideInitializer, TRUE },
+ { "callgraph", &handleCallgraph, TRUE },
+ { "callergraph", &handleCallergraph, TRUE },
+ { "internal", &handleInternal, TRUE },
+ { "_linebr", &handleLineBr, FALSE },
+ { "static", &handleStatic, TRUE },
+ { "pure", &handlePure, TRUE },
+ { "private", &handlePrivate, TRUE },
+ { "privatesection", &handlePrivateSection, TRUE },
+ { "protected", &handleProtected, TRUE },
+ { "protectedsection",&handleProtectedSection, TRUE },
+ { "public", &handlePublic, TRUE },
+ { "publicsection", &handlePublicSection, TRUE },
+ { "inherit", &handleInherit, TRUE },
+ { "arg", 0, TRUE },
+ { "attention", 0, TRUE },
+ { "author", 0, TRUE },
+ { "date", 0, TRUE },
+ { "dotfile", 0, TRUE },
+ { "htmlinclude", 0, TRUE },
+ { "image", 0, TRUE },
+ { "include", 0, TRUE },
+ { "includelineno", 0, TRUE },
+ { "invariant", 0, TRUE },
+ { "li", 0, TRUE },
+ { "line", 0, TRUE },
+ { "note", 0, TRUE },
+ { "par", 0, TRUE },
+ { "param", 0, TRUE },
+ { "post", 0, TRUE },
+ { "pre", 0, TRUE },
+ { "remarks", 0, TRUE },
+ { "return", 0, TRUE },
+ { "returns", 0, TRUE },
+ { "retval", 0, TRUE },
+ { "sa", 0, TRUE },
+ { "see", 0, TRUE },
+ { "since", 0, TRUE },
+ { "throw", 0, TRUE },
+ { "until", 0, TRUE },
+ { "verbinclude", 0, TRUE },
+ { "version", 0, TRUE },
+ { "warning", 0, TRUE },
+ { 0, 0, FALSE }
};
-
-
/** @brief Command mapper.
*
* Maps a command name (as found in a comment block) onto a
@@ -205,8 +234,14 @@ static DocCmdMap docCmdMap[] =
class DocCmdMapper
{
public:
+ struct Cmd
+ {
+ DocCmdFunc func;
+ bool endsBrief;
+ };
+
/** maps a command name to a handler function */
- static DocCmdFunc *map(const char *name)
+ static Cmd *map(const char *name)
{
return instance()->find(name);
}
@@ -224,21 +259,30 @@ class DocCmdMapper
return s_instance;
}
- DocCmdMapper() : m_map(89)
+ DocCmdMapper() : m_map(113)
{
+ m_map.setAutoDelete(TRUE);
DocCmdMap *p = docCmdMap;
while (p->cmdName)
{
- m_map.insert(p->cmdName,&p->handler);
+ if (m_map.find(p->cmdName)!=0)
+ {
+ printf("Error: command %s already added\n",p->cmdName);
+ exit(1);
+ }
+ Cmd *cmd = new Cmd;
+ cmd->func = p->handler;
+ cmd->endsBrief = p->endsBrief;
+ m_map.insert(p->cmdName,cmd);
p++;
}
}
- DocCmdFunc *find(const char *name)
+ Cmd *find(const char *name)
{
return m_map.find(name);
}
- QDict<DocCmdFunc> m_map;
+ QDict<Cmd> m_map;
static DocCmdMapper *s_instance;
};
@@ -656,6 +700,17 @@ static inline void addOutput(char c)
*pOutputString+=c;
}
+static void endBrief()
+{
+ if (!current->brief.stripWhiteSpace().isEmpty())
+ { // only go to the detailed description if we have
+ // found some brief description and not just whitespace
+ briefEndsAtDot=FALSE;
+ setOutput(OutputDoc);
+ addOutput(yytext);
+ }
+}
+
/* ----------------------------------------------------------------- */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
@@ -801,12 +856,14 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
// continue with the same input
REJECT;
}
+ /*
<Comment>{DETAILEDCMD}/[^a-z_A-Z]* { // command that can end a brief description
briefEndsAtDot=FALSE;
setOutput(OutputDoc);
// continue with the same input
REJECT;
}
+ */
<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description
setOutput(OutputDoc);
// continue with the same input
@@ -825,10 +882,16 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
}
<Comment>{CMD}[a-z_A-Z]+{B}* { // potentially interesting command
QCString cmdName = QCString(&yytext[1]).stripWhiteSpace();
- DocCmdFunc *funcPtr = DocCmdMapper::map(cmdName);
- if (funcPtr) // special action is required
+ DocCmdMapper::Cmd *cmdPtr = DocCmdMapper::map(cmdName);
+ if (cmdPtr) // special action is required
{
- if ((*funcPtr)(cmdName))
+ if (cmdPtr->endsBrief && !current->brief.stripWhiteSpace().isEmpty())
+ {
+ briefEndsAtDot=FALSE;
+ // this command forces the end of brief description
+ setOutput(OutputDoc);
+ }
+ if (cmdPtr->func && cmdPtr->func(cmdName))
{
// implicit split of the comment block into two
// entries. Restart the next block at the start
@@ -846,6 +909,12 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
#endif
yyterminate();
}
+ else if (cmdPtr->func==0)
+ {
+ // command without handler, to be processed
+ // later by parsedoc.cpp
+ addOutput(yytext);
+ }
}
else // command not relevant
{
@@ -911,11 +980,10 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
addOutput(yytext);
setOutput(OutputDoc);
}
- else if (!current->brief.stripWhiteSpace().isEmpty())
+ else
{ // only go to the detailed description if we have
// found some brief description and not just whitespace
- setOutput(OutputDoc);
- addOutput(yytext);
+ endBrief();
}
lineCount();
}
@@ -1853,7 +1921,7 @@ static bool handlePage(const QCString &)
static bool handleMainpage(const QCString &)
{
bool stop=makeStructuralIndicator(Entry::MAINPAGEDOC_SEC);
- current->name = "mainpage";
+ if (!stop) current->name = "mainpage";
BEGIN( PageDocArg2 );
return stop;
}
@@ -1861,7 +1929,7 @@ static bool handleMainpage(const QCString &)
static bool handleFile(const QCString &)
{
bool stop=makeStructuralIndicator(Entry::FILEDOC_SEC);
- current->name = yyFileName;
+ if (!stop) current->name = yyFileName;
BEGIN( FileDocArg1 );
return stop;
}
@@ -1869,7 +1937,7 @@ static bool handleFile(const QCString &)
static bool handleDir(const QCString &)
{
bool stop=makeStructuralIndicator(Entry::DIRDOC_SEC);
- current->name = yyFileName;
+ if (!stop) current->name = yyFileName;
BEGIN( FileDocArg1 );
return stop;
}
@@ -1877,7 +1945,7 @@ static bool handleDir(const QCString &)
static bool handleExample(const QCString &)
{
bool stop=makeStructuralIndicator(Entry::EXAMPLE_SEC);
- current->name = yyFileName;
+ if (!stop) current->name = yyFileName;
BEGIN( FileDocArg1 );
return stop;
}
@@ -1891,11 +1959,14 @@ static bool handleDetails(const QCString &)
static bool handleName(const QCString &)
{
bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC);
- g_memberGroupHeader.resize(0);
- BEGIN( NameParam );
- if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group
+ if (!stop)
{
- closeGroup(current,yyFileName,yyLineNr);
+ g_memberGroupHeader.resize(0);
+ BEGIN( NameParam );
+ if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group
+ {
+ closeGroup(current,yyFileName,yyLineNr);
+ }
}
return stop;
}
@@ -2123,54 +2194,63 @@ static bool handleLineBr(const QCString &)
static bool handleStatic(const QCString &)
{
+ endBrief();
current->stat = TRUE;
return FALSE;
}
static bool handlePure(const QCString &)
{
+ endBrief();
current->virt = Pure;
return FALSE;
}
static bool handlePrivate(const QCString &)
{
+ endBrief();
current->protection = Private;
return FALSE;
}
static bool handlePrivateSection(const QCString &)
{
+ endBrief();
current->protection = protection = Private;
return FALSE;
}
static bool handleProtected(const QCString &)
{
+ endBrief();
current->protection = Protected;
return FALSE;
}
static bool handleProtectedSection(const QCString &)
{
+ endBrief();
current->protection = protection = Protected ;
return FALSE;
}
static bool handlePublic(const QCString &)
{
+ endBrief();
current->protection = Public;
return FALSE;
}
static bool handlePublicSection(const QCString &)
{
+ endBrief();
current->protection = protection = Public;
return FALSE;
}
static bool handleInherit(const QCString &)
{
+ endBrief();
BEGIN(InheritParam);
return FALSE;
}
@@ -2200,7 +2280,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser,
/* out */ bool &newEntryNeeded
)
{
- //fprintf(stderr,"parseCommentBlock() isBrief=%d isJavaDocStyle=%d lineNr=%d\n",
+ //printf("parseCommentBlock() isBrief=%d isJavaDocStyle=%d lineNr=%d\n",
// isBrief,isJavaDocStyle,lineNr);
initParser();
diff --git a/src/definition.cpp b/src/definition.cpp
index b837a37..3c00fbb 100644
--- a/src/definition.cpp
+++ b/src/definition.cpp
@@ -34,7 +34,6 @@
#include "section.h"
#include "htags.h"
#include "parserintf.h"
-#include "objcache.h"
#include "marshal.h"
#if defined(_MSC_VER) || defined(__BORLANDC__)
@@ -237,14 +236,11 @@ Definition::Definition(const char *df,int dl,
const char *name,const char *b,
const char *d,bool isSymbol)
{
- m_storagePos=-1;
m_name = name;
m_impl = new DefinitionImpl;
m_impl->init(df,dl,name,b,d);
m_isSymbol = isSymbol;
if (isSymbol) addToMap(name,this);
- m_cacheHandle=-1;
- m_flushPending = FALSE;
}
Definition::~Definition()
@@ -258,11 +254,6 @@ Definition::~Definition()
delete m_impl;
m_impl=0;
}
- if (m_cacheHandle!=-1)
- {
- Doxygen::symbolCache->del(m_cacheHandle);
- m_cacheHandle=-1;
- }
}
void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList)
@@ -1173,74 +1164,14 @@ void Definition::setLocalName(const QCString name)
}
void Definition::makeResident() const
-{
- if (m_cacheHandle==-1) // not yet in cache
- {
- Definition *victim = 0;
- Definition *that = (Definition*)this; // fake method constness
- that->m_cacheHandle = Doxygen::symbolCache->add(that,(void **)&victim);
- //printf("adding %s to cache, handle=%d\n",m_impl->name.data(),that->m_cacheHandle);
- if (victim) // cache was full, victim was the least recently used item and has to go
- {
- victim->m_cacheHandle=-1; // invalidate cache handle
- victim->saveToDisk(); // store the item on disk
- }
- else // cache not yet full
- {
- //printf("Adding %s to cache, handle=%d\n",m_impl->name.data(),m_cacheHandle);
- }
- if (m_storagePos!=-1) // already been written to disk
- {
- if (isLocked()) // locked in memory
- {
- assert(m_impl!=0);
- that->m_flushPending=FALSE; // no need to flush anymore
- }
- else // not locked in memory
- {
- assert(m_impl==0);
- loadFromDisk();
- }
- }
- }
- else // already cached, make this object the most recently used.
- {
- assert(m_impl!=0);
- //printf("Touching symbol %s\n",m_impl->name.data());
- Doxygen::symbolCache->use(m_cacheHandle);
- }
-}
-
-void Definition::saveToDisk() const
{
- assert(m_impl!=0);
- Definition *that = (Definition *)this;
- if (isLocked()) // cannot flush the item as it is locked
- {
- that->m_flushPending=TRUE; // flush when unlocked
- }
- else // ready to flush the item to disk
- {
- //printf("Adding %s to cache, handle=%d by replacing %s\n",
- // m_impl->name.data(),m_cacheHandle,victim->m_impl->name.data());
- if (m_storagePos!=-1)
- // if victim was stored on disk already and is not locked
- {
- // free the storage space occupied by the old store item
- Doxygen::symbolStorage->release(m_storagePos); // free up space for others
- }
- // write a the new (possibly modified) instance to disk
- flushToDisk();
- // end to write sequence (unless nothing was written due to the lock)
- Doxygen::symbolStorage->end();
- }
}
+
void Definition::flushToDisk() const
{
//printf("%p: Definition::flushToDisk()\n",this);
Definition *that = (Definition *)this;
- that->m_storagePos = Doxygen::symbolStorage->alloc();
//printf("Definition::flushToDisk(): pos=%d\n",(int)m_storagePos);
marshalUInt(Doxygen::symbolStorage,START_MARKER);
marshalSectionDict (Doxygen::symbolStorage,m_impl->sectionDict);
@@ -1262,7 +1193,6 @@ void Definition::flushToDisk() const
marshalUInt(Doxygen::symbolStorage,END_MARKER);
delete that->m_impl;
that->m_impl = 0;
- that->m_flushPending=FALSE;
}
void Definition::loadFromDisk() const
@@ -1271,7 +1201,6 @@ void Definition::loadFromDisk() const
Definition *that = (Definition *)this;
assert(m_impl==0);
that->m_impl = new DefinitionImpl;
- Doxygen::symbolStorage->seek(m_storagePos);
uint marker = unmarshalUInt(Doxygen::symbolStorage);
assert(marker==START_MARKER);
m_impl->sectionDict = unmarshalSectionDict (Doxygen::symbolStorage);
@@ -1294,18 +1223,3 @@ void Definition::loadFromDisk() const
assert(marker==END_MARKER);
}
-void Definition::lock() const
-{
-}
-
-void Definition::unlock() const
-{
- if (m_flushPending && !isLocked())
- {
- // write a the new (possibly modified) instance to disk
- flushToDisk();
- // end to write sequence (unless nothing was written due to the lock)
- Doxygen::symbolStorage->end();
- }
-}
-
diff --git a/src/definition.h b/src/definition.h
index 8f46e7a..9e2790d 100644
--- a/src/definition.h
+++ b/src/definition.h
@@ -279,19 +279,14 @@ class Definition : public DefinitionIntf, public LockableObj
virtual void flushToDisk() const;
virtual void loadFromDisk() const;
- void makeResident() const;
- bool isResident() const
- {
- return m_cacheHandle!=-1;
- }
+ virtual void makeResident() const;
+ void lock() const {}
+ void unlock() const {}
private:
- void lock() const;
- void unlock() const;
static void addToMap(const char *name,Definition *d);
static void removeFromMap(Definition *d);
- void saveToDisk() const;
void _setSymbolName(const QCString &name);
@@ -299,10 +294,7 @@ class Definition : public DefinitionIntf, public LockableObj
void _writeSourceRefList(OutputList &ol,const char *scopeName,
const QCString &text,MemberSDict *members,bool);
DefinitionImpl *m_impl; // internal structure holding all private data
- off_t m_storagePos; // location where the item is stored in file (if impl==0)
- int m_cacheHandle;
QCString m_name;
- bool m_flushPending;
bool m_isSymbol;
QCString m_symbolName;
diff --git a/src/docparser.cpp b/src/docparser.cpp
index 3d34aa3..0cfeb88 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -339,6 +339,7 @@ static void checkUndocumentedParams()
}
if (found)
{
+ bool first=TRUE;
QString errMsg=
"Warning: The following parameters of "+
QString(g_memberDef->qualifiedName()) +
@@ -349,7 +350,15 @@ static void checkUndocumentedParams()
QString argName = g_memberDef->isDefine() ? a->type : a->name;
if (!argName.isEmpty() && g_paramsFound.find(argName)==0)
{
- errMsg+=" parameter "+argName+"\n";
+ if (!first)
+ {
+ errMsg+="\n";
+ }
+ else
+ {
+ first=FALSE;
+ }
+ errMsg+=" parameter "+argName;
}
}
if (g_memberDef->inheritsDocsFrom())
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 0b60c3d..695cfc9 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -879,7 +879,7 @@ static Definition *buildScopeFromQualifiedName(const QCString name,int level)
static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n,
FileDef *fileScope)
{
- //printf("findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data());
+ //printf("<findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data());
Definition *resultScope=startScope;
if (resultScope==0) resultScope=Doxygen::globalScope;
QCString scope=stripTemplateSpecifiersFromScope(n,FALSE);
@@ -887,7 +887,7 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr
i1=getScopeFragment(scope,0,&l1);
if (i1==-1)
{
- //printf("no fragments!\n");
+ //printf(">no fragments!\n");
return resultScope;
}
int p=i1+l1,l2=0,i2;
@@ -895,24 +895,34 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr
{
QCString nestedNameSpecifier = scope.mid(i1,l1);
Definition *orgScope = resultScope;
+ //printf(" nestedNameSpecifier=%s\n",nestedNameSpecifier.data());
resultScope = resultScope->findInnerCompound(nestedNameSpecifier);
- //printf("resultScope=%p\n",resultScope);
+ //printf(" resultScope=%p\n",resultScope);
if (resultScope==0)
{
- if (orgScope==Doxygen::globalScope && fileScope)
+ NamespaceSDict *usedNamespaces;
+ if (orgScope==Doxygen::globalScope && fileScope &&
+ (usedNamespaces = fileScope->getUsedNamespaces()))
// also search for used namespaces
{
- NamespaceSDict *usedNamespaces = fileScope->getUsedNamespaces();
- if (usedNamespaces)
+ NamespaceSDict::Iterator ni(*usedNamespaces);
+ NamespaceDef *nd;
+ for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni)
{
- NamespaceSDict::Iterator ni(*usedNamespaces);
- NamespaceDef *nd;
- for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni)
+ // restart search within the used namespace
+ resultScope = findScopeFromQualifiedName(nd,n,fileScope);
+ }
+ if (resultScope)
+ {
+ // for a nested class A::I in used namespace N, we get
+ // N::A::I while looking for A, so we should compare
+ // resultScope->name() against scope.left(i2+l2)
+ //printf(" -> result=%s scope=%s\n",resultScope->name().data(),scope.data());
+ if (rightScopeMatch(resultScope->name(),scope.left(i2+l2)))
{
- // restart search within the used namespace
- resultScope = findScopeFromQualifiedName(nd,n,fileScope);
+ break;
}
- if (resultScope) goto nextFragment;
+ goto nextFragment;
}
}
@@ -934,13 +944,15 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr
scope.right(scope.length()-p);
resultScope = buildScopeFromQualifiedName(fqn,fqn.contains("::"));
//printf("Creating scope from fqn=%s result %p\n",fqn.data(),resultScope);
- //resultScope = findScopeFromQualifiedName(startScope,fqn,usedFd);
- //printf("Match! resultScope=%p\n",resultScope);
- if (resultScope) return resultScope;
+ if (resultScope)
+ {
+ //printf("> Match! resultScope=%s\n",resultScope->name().data());
+ return resultScope;
+ }
}
}
- //printf("name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data());
+ //printf("> name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data());
return 0;
}
nextFragment:
@@ -948,7 +960,7 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr
l1=l2;
p=i2+l2;
}
- //printf("findScopeFromQualifiedName scope %s\n",resultScope->name().data());
+ //printf(">findScopeFromQualifiedName scope %s\n",resultScope->name().data());
return resultScope;
}
@@ -1061,9 +1073,9 @@ static void addClassToContext(EntryNav *rootNav)
{
warn(
root->fileName,root->startLine,
- "Warning: class %s already has a detailed description. "
+ "Warning: class %s already has a detailed description found in file %s at line %d. "
"Skipping the one found here.",
- fullName.data()
+ fullName.data(),cd->docFile().data(),cd->docLine()
);
}
else if (!root->doc.isEmpty())
@@ -1074,9 +1086,9 @@ static void addClassToContext(EntryNav *rootNav)
{
warn(
root->fileName,root->startLine,
- "Warning: class %s already has a brief description\n"
+ "Warning: class %s already has a brief description found in file %s at line %d\n"
" skipping the one found here.",
- fullName.data()
+ fullName.data(),cd->briefFile().data(),cd->briefLine()
);
}
else if (!root->brief.isEmpty())
@@ -1252,7 +1264,7 @@ static void resolveClassNestingRelations()
cd->setOuterScope(d);
warn(cd->getDefFileName(),cd->getDefLine(),
"Warning: Internal inconsistency: scope for class %s not "
- "found!\n",cd->name().data()
+ "found!",cd->name().data()
);
}
}
@@ -1286,7 +1298,7 @@ static void resolveClassNestingRelations()
cd->setOuterScope(d);
warn(cd->getDefFileName(),cd->getDefLine(),
"Warning: Internal inconsistency: scope for class %s not "
- "found!\n",cd->name().data()
+ "found!",cd->name().data()
);
}
}
@@ -1347,9 +1359,9 @@ static void buildNamespaceList(EntryNav *rootNav)
{
warn(
root->fileName,root->startLine,
- "Warning: namespace %s already has a detailed description. "
+ "Warning: namespace %s already has a detailed description found in file %s at line %d. "
"Skipping the documentation found here.",
- fullName.data());
+ fullName.data(),nd->docFile().data(),nd->docLine());
}
if (nd->briefDescription().isEmpty() && !root->brief.isEmpty())
{
@@ -1359,9 +1371,9 @@ static void buildNamespaceList(EntryNav *rootNav)
else if (!nd->briefDescription().isEmpty() && !root->brief.isEmpty())
{
warn(root->fileName,root->startLine,
- "Warning: namespace %s already has a brief description. "
+ "Warning: namespace %s already has a brief description found in file %s at line %d. "
"Skipping the documentation found here.",
- fullName.data()
+ fullName.data(),nd->docFile().data(),nd->docLine()
);
}
}
@@ -3642,6 +3654,7 @@ static void findUsedClassesForClass(EntryNav *rootNav,
usedName,ClassDef::Class);
//printf("making %s a template argument!!!\n",usedCd->name().data());
usedCd->makeTemplateArgument();
+ usedCd->setUsedOnly(TRUE);
Doxygen::hiddenClasses->append(usedName,usedCd);
}
if (usedCd)
@@ -3688,6 +3701,7 @@ static void findUsedClassesForClass(EntryNav *rootNav,
usedCd = new ClassDef(
masterCd->getDefFileName(),masterCd->getDefLine(),
type,ClassDef::Class);
+ usedCd->setUsedOnly(TRUE);
Doxygen::hiddenClasses->append(type,usedCd);
}
if (usedCd)
@@ -5250,6 +5264,7 @@ static void findMember(EntryNav *rootNav,
if (funcSpec.isEmpty()) // not a member specialization
{
int count=0;
+ int noMatchCount=0;
MemberNameIterator mni(*mn);
MemberDef *md;
bool memFound=FALSE;
@@ -5371,6 +5386,11 @@ static void findMember(EntryNav *rootNav,
memFound=TRUE;
}
}
+ else if (cd && cd!=tcd) // we did find a class with the same name as cd
+ // but in a different namespace
+ {
+ noMatchCount++;
+ }
}
if (count==0 && rootNav->parent() &&
rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
@@ -5402,7 +5422,8 @@ static void findMember(EntryNav *rootNav,
}
warn(root->fileName,root->startLine,
- "Warning: no matching class member found for"
+ "Warning: no %smatching class member found for",
+ noMatchCount>1 ? "uniquely " : ""
);
if (root->tArgLists)
@@ -5440,6 +5461,7 @@ static void findMember(EntryNav *rootNav,
QCString qScope = cd->qualifiedNameWithTemplateParameters();
if (!qScope.isEmpty()) warn_cont("%s::%s",qScope.data(),md->name().data());
if (md->argsString()) warn_cont("%s",md->argsString());
+ if (noMatchCount>1) warn_cont(" at line %d of file %s",md->getDefLine(),md->getDefFileName().data());
warn_cont("\n");
}
}
@@ -6146,6 +6168,7 @@ static void findEnums(EntryNav *rootNav)
}
addMemberToGroups(root,md);
+#if 0
if (rootNav->children())
{
EntryNavListIterator eli(*rootNav->children());
@@ -6209,6 +6232,7 @@ static void findEnums(EntryNav *rootNav)
}
}
}
+#endif
}
rootNav->releaseEntry();
@@ -6220,6 +6244,160 @@ static void findEnums(EntryNav *rootNav)
}
//----------------------------------------------------------------------
+
+static void addEnumValuesToEnums(EntryNav *rootNav)
+{
+ if (rootNav->section()==Entry::ENUM_SEC)
+ // non anonymous enumeration
+ {
+ rootNav->loadEntry(g_storage);
+ Entry *root = rootNav->entry();
+
+ ClassDef *cd=0;
+ FileDef *fd=0;
+ NamespaceDef *nd=0;
+ MemberNameSDict *mnsd=0;
+ bool isGlobal;
+ bool isRelated=FALSE;
+ //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data());
+ int i;
+
+ QCString name;
+ QCString scope;
+
+ if ((i=root->name.findRev("::"))!=-1) // scope is specified
+ {
+ scope=root->name.left(i); // extract scope
+ name=root->name.right(root->name.length()-i-2); // extract name
+ if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
+ }
+ else // no scope, check the scope in which the docs where found
+ {
+ if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
+ && !rootNav->parent()->name().isEmpty()
+ ) // found enum docs inside a compound
+ {
+ scope=rootNav->parent()->name();
+ if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
+ }
+ name=root->name;
+ }
+
+ if (!root->relates.isEmpty())
+ { // related member, prefix user specified scope
+ isRelated=TRUE;
+ if (getClass(root->relates)==0 && !scope.isEmpty())
+ scope=mergeScopes(scope,root->relates);
+ else
+ scope=root->relates.copy();
+ if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
+ }
+
+ if (cd && !name.isEmpty()) // found a enum inside a compound
+ {
+ //printf("Enum `%s'::`%s'\n",cd->name(),name.data());
+ fd=0;
+ mnsd=Doxygen::memberNameSDict;
+ isGlobal=FALSE;
+ }
+ else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace
+ {
+ mnsd=Doxygen::functionNameSDict;
+ isGlobal=TRUE;
+ }
+ else // found a global enum
+ {
+ fd=rootNav->fileDef();
+ mnsd=Doxygen::functionNameSDict;
+ isGlobal=TRUE;
+ }
+
+ if (!name.isEmpty())
+ {
+ MemberName *mn = mnsd->find(name);
+ if (mn)
+ {
+ MemberNameIterator mni(*mn);
+ MemberDef *md;
+ for (mni.toFirst(); (md=mni.current()) ; ++mni)
+ {
+ if (md->isEnumerate() && rootNav->children())
+ {
+ EntryNavListIterator eli(*rootNav->children());
+ EntryNav *e;
+ for (;(e=eli.current());++eli)
+ {
+ //printf("e->name=%s isRelated=%d\n",e->name.data(),isRelated);
+ MemberName *fmn=0;
+ MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd;
+ if (!e->name().isEmpty() && (fmn=(*emnsd)[e->name()]))
+ // get list of members with the same name as the field
+ {
+ MemberNameIterator fmni(*fmn);
+ MemberDef *fmd;
+ for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni)
+ {
+ if (fmd->isEnumValue())
+ {
+ //printf("found enum value with same name\n");
+ if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
+ {
+ NamespaceDef *fnd=fmd->getNamespaceDef();
+ if (fnd==nd) // enum value is inside a namespace
+ {
+ md->insertEnumField(fmd);
+ fmd->setEnumScope(md);
+ }
+ }
+ else if (isGlobal)
+ {
+ FileDef *ffd=fmd->getFileDef();
+ if (ffd==fd) // enum value has file scope
+ {
+ md->insertEnumField(fmd);
+ fmd->setEnumScope(md);
+ }
+ }
+ else if (isRelated && cd) // reparent enum value to
+ // match the enum's scope
+ {
+ md->insertEnumField(fmd); // add field def to list
+ fmd->setEnumScope(md); // cross ref with enum name
+ fmd->setEnumClassScope(cd); // cross ref with enum name
+ fmd->setOuterScope(cd);
+ fmd->makeRelated();
+ cd->insertMember(fmd);
+ }
+ else
+ {
+ ClassDef *fcd=fmd->getClassDef();
+ if (fcd==cd) // enum value is inside a class
+ {
+ //printf("Inserting enum field %s in enum scope %s\n",
+ // fmd->name().data(),md->name().data());
+ md->insertEnumField(fmd); // add field def to list
+ fmd->setEnumScope(md); // cross ref with enum name
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ rootNav->releaseEntry();
+ }
+ else
+ {
+ RECURSE_ENTRYTREE(addEnumValuesToEnums,rootNav);
+ }
+}
+
+
+//----------------------------------------------------------------------
// find the documentation blocks for the enumerations
static void findEnumDocumentation(EntryNav *rootNav)
@@ -7203,7 +7381,6 @@ static void buildPageList(EntryNav *rootNav)
{
if (rootNav->section() == Entry::PAGEDOC_SEC)
{
- //printf("buildPageList %s\n",root->name.data());
rootNav->loadEntry(g_storage);
Entry *root = rootNav->entry();
@@ -8801,8 +8978,8 @@ void parseInput()
**************************************************************************/
Doxygen::symbolMap = new QDict<DefinitionIntf>(1000);
- Doxygen::symbolCache = new ObjCache(15); // 15 -> room for 32768 elements,
- // ~1.0 MByte "overhead"
+ Doxygen::symbolCache = new ObjCache(16); // 16 -> room for 65536 elements,
+ // ~2.0 MByte "overhead"
Doxygen::symbolStorage = new Store;
if (Doxygen::symbolStorage->open(outputDirectory+"/doxygen_objdb.tmp")==-1)
@@ -9182,6 +9359,9 @@ void parseInput()
msg("Building example list...\n");
buildExampleList(rootNav);
+ msg("Searching for enumerations...\n");
+ findEnums(rootNav);
+
msg("Searching for documented variables...\n");
buildVarList(rootNav);
@@ -9210,10 +9390,9 @@ void parseInput()
computeClassRelations();
classEntries.clear();
- msg("Searching for enumerations...\n");
- findEnums(rootNav);
+ addEnumValuesToEnums(rootNav);
findEnumDocumentation(rootNav);
-
+
msg("Searching for member function documentation...\n");
findObjCMethodDefinitions(rootNav);
findMemberDocumentation(rootNav); // may introduce new members !
diff --git a/src/doxygen.h b/src/doxygen.h
index 43ee18b..92c09ba 100644
--- a/src/doxygen.h
+++ b/src/doxygen.h
@@ -59,11 +59,13 @@ class StringDict : public QDict<QCString>
struct LookupInfo
{
- LookupInfo(ClassDef *cd=0,MemberDef *td=0,QCString ts="")
- : classDef(cd), typeDef(td), templSpec(ts) {}
+ LookupInfo() : classDef(0), typeDef(0) {}
+ LookupInfo(ClassDef *cd,MemberDef *td,QCString ts,QCString rt)
+ : classDef(cd), typeDef(td), templSpec(ts),resolvedType(rt) {}
ClassDef *classDef;
MemberDef *typeDef;
QCString templSpec;
+ QCString resolvedType;
};
extern QCString spaces;
diff --git a/src/filedef.cpp b/src/filedef.cpp
index c43cd72..7214a56 100644
--- a/src/filedef.cpp
+++ b/src/filedef.cpp
@@ -93,6 +93,7 @@ FileDef::FileDef(const char *p,const char *nm,
m_isJava = name().right(5)==".java";
memberGroupSDict = 0;
acquireFileVersion();
+ m_subGrouping=Config_getBool("SUBGROUPING");
}
/*! destroy the file definition */
@@ -491,7 +492,8 @@ void FileDef::writeDocumentation(OutputList &ol)
MemberGroup *mg;
for (;(mg=mgli.current());++mgli)
{
- if (mg->header()!="[NOHEADER]")
+ if ((!mg->allMembersInSameSection() || !m_subGrouping)
+ && mg->header()!="[NOHEADER]")
{
mg->writeDeclarations(ol,0,0,this,0);
}
@@ -689,6 +691,21 @@ void FileDef::addMembersToMemberGroup()
::addMembersToMemberGroup(ml,&memberGroupSDict,this);
}
}
+
+ // add members inside sections to their groups
+ if (memberGroupSDict)
+ {
+ MemberGroupSDict::Iterator mgli(*memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ if (mg->allMembersInSameSection() && m_subGrouping)
+ {
+ //printf("----> addToDeclarationSection(%s)\n",mg->header().data());
+ mg->addToDeclarationSection();
+ }
+ }
+ }
}
/*! Adds member definition \a md to the list of all members of this file */
@@ -1363,6 +1380,7 @@ void FileDef::addMemberToList(MemberList::ListType lt,MemberDef *md)
{
ml->setInFile(TRUE);
}
+ if (ml->listType()&MemberList::declarationLists) md->setSectionList(this,ml);
}
MemberList *FileDef::getMemberList(MemberList::ListType lt) const
diff --git a/src/filedef.h b/src/filedef.h
index c794b70..15554e2 100644
--- a/src/filedef.h
+++ b/src/filedef.h
@@ -214,6 +214,7 @@ class FileDef : public Definition
MemberGroupSDict *memberGroupSDict;
NamespaceSDict *namespaceSDict;
ClassSDict *classSDict;
+ bool m_subGrouping;
};
diff --git a/src/lockingptr.h b/src/lockingptr.h
index e981056..1936bec 100644
--- a/src/lockingptr.h
+++ b/src/lockingptr.h
@@ -37,20 +37,15 @@ class LockableObj
/*! Returns TRUE if the object is currently locked. */
bool isLocked() const { return m_lockCount>0; }
-#ifndef _WIN32
protected:
-#endif
/*! Called when the object is locked. */
virtual void lock() const = 0;
/*! Called when the object is unlocked. */
virtual void unlock() const = 0;
-#ifndef _WIN32 // HACK: VC++ 6.0 does not understand friend template classes.
private:
template<class T> friend class LockingPtr;
-#endif
-
int m_lockCount;
};
diff --git a/src/marshal.h b/src/marshal.h
index dd751fa..864e8b3 100644
--- a/src/marshal.h
+++ b/src/marshal.h
@@ -7,17 +7,17 @@
#include "store.h"
class ArgumentList;
-class BaseInfo;
-class Grouping;
-class SectionInfo;
-class ListItemInfo;
+struct BaseInfo;
+struct Grouping;
+struct SectionInfo;
+struct ListItemInfo;
class QCString;
class QGString;
class SectionDict;
class MemberSDict;
class GroupList;
-class BodyInfo;
-class DocInfo;
+struct BodyInfo;
+struct DocInfo;
class MemberList;
class ExampleSDict;
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 9ae8123..976fdc8 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -37,6 +37,7 @@
#include "searchindex.h"
#include "parserintf.h"
#include "marshal.h"
+#include "objcache.h"
#define START_MARKER 0x4D454D5B // MEM[
#define END_MARKER 0x4D454D5D // MEM]
@@ -367,6 +368,7 @@ class MemberDefImpl
bool isTypedefValCached;
ClassDef *cachedTypedefValue;
QCString cachedTypedefTemplSpec;
+ QCString cachedResolvedType;
// inbody documentation
int inbodyLine;
@@ -574,8 +576,11 @@ MemberDef::MemberDef(const char *df,int dl,
const ArgumentList *tal,const ArgumentList *al
) : Definition(df,dl,removeRedundantWhiteSpace(na))
{
+ m_storagePos=-1;
+ m_cacheHandle=-1;
m_impl = new MemberDefImpl;
m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al);
+ m_flushPending = FALSE;
#if 0
//printf("++++++ MemberDef(%s file=%s,line=%d static=%d) ++++++ \n",
@@ -697,6 +702,11 @@ MemberDef::MemberDef(const char *df,int dl,
MemberDef::~MemberDef()
{
delete m_impl;
+ if (m_cacheHandle!=-1)
+ {
+ Doxygen::symbolCache->del(m_cacheHandle);
+ m_cacheHandle=-1;
+ }
}
void MemberDef::setReimplements(MemberDef *md)
@@ -774,7 +784,10 @@ QCString MemberDef::getOutputFileBase() const
makeResident();
static bool separateMemberPages = Config_getBool("SEPARATE_MEMBER_PAGES");
QCString baseName;
- if (m_impl->explicitOutputFileBase)
+ //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n",
+ // name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef,
+ // m_impl->nspace,m_impl->fileDef);
+ if (!m_impl->explicitOutputFileBase.isEmpty())
{
return m_impl->explicitOutputFileBase;
}
@@ -805,6 +818,7 @@ QCString MemberDef::getOutputFileBase() const
"Warning: Internal inconsistency: member %s does not belong to any"
" container!",name().data()
);
+ exit(1);
return "dummy";
}
else if (separateMemberPages)
@@ -3375,6 +3389,12 @@ QCString MemberDef::getCachedTypedefTemplSpec() const
return m_impl->cachedTypedefTemplSpec;
}
+QCString MemberDef::getCachedResolvedTypedef() const
+{
+ makeResident();
+ return m_impl->cachedResolvedType;
+}
+
MemberDef *MemberDef::memberDefinition() const
{
makeResident();
@@ -3591,21 +3611,24 @@ void MemberDef::setMemberDeclaration(MemberDef *md)
m_impl->memDec=md;
}
-void MemberDef::cacheTypedefVal(ClassDef*val, QCString const& templSpec)
+void MemberDef::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType)
{
makeResident();
m_impl->isTypedefValCached=TRUE;
m_impl->cachedTypedefValue=val;
m_impl->cachedTypedefTemplSpec=templSpec;
+ m_impl->cachedResolvedType=resolvedType;
}
void MemberDef::flushToDisk() const
{
+ if (isLocked()) return;
+ MemberDef *that = (MemberDef*)this;
+ that->m_storagePos = Doxygen::symbolStorage->alloc();
//printf("%p: MemberDef::flushToDisk()\n",this);
// write the definition base class member variables to disk
Definition::flushToDisk();
- if (isLocked()) return;
//printf("%p: flushing specific part\n",this);
// write the memberdef member variables to disk
@@ -3658,6 +3681,7 @@ void MemberDef::flushToDisk() const
marshalBool (Doxygen::symbolStorage,m_impl->isTypedefValCached);
marshalObjPointer (Doxygen::symbolStorage,m_impl->cachedTypedefValue);
marshalQCString (Doxygen::symbolStorage,m_impl->cachedTypedefTemplSpec);
+ marshalQCString (Doxygen::symbolStorage,m_impl->cachedResolvedType);
marshalInt (Doxygen::symbolStorage,m_impl->inbodyLine);
marshalQCString (Doxygen::symbolStorage,m_impl->inbodyFile);
marshalQCString (Doxygen::symbolStorage,m_impl->inbodyDocs);
@@ -3682,25 +3706,27 @@ void MemberDef::flushToDisk() const
marshalUInt(Doxygen::symbolStorage,END_MARKER);
// function doesn't modify the object conceptually but compiler doesn't know this.
- MemberDef *that = (MemberDef *)this;
delete that->m_impl;
that->m_impl=0;
+ that->m_flushPending=FALSE;
}
void MemberDef::loadFromDisk() const
{
//printf("%p: MemberDef::loadFromDisk()\n",this);
- Definition::loadFromDisk();
-
+ MemberDef *that = (MemberDef *)this;
if (isLocked())
{
assert(m_impl!=0);
return;
}
assert(m_impl==0);
+
+ Doxygen::symbolStorage->seek(m_storagePos);
+ Definition::loadFromDisk();
+
//printf("%p: loading specific part\n",this);
- MemberDef *that = (MemberDef *)this;
that->m_impl = new MemberDefImpl;
uint marker = unmarshalUInt(Doxygen::symbolStorage);
@@ -3753,6 +3779,7 @@ void MemberDef::loadFromDisk() const
m_impl->isTypedefValCached = unmarshalBool (Doxygen::symbolStorage);
m_impl->cachedTypedefValue = (ClassDef*)unmarshalObjPointer (Doxygen::symbolStorage);
m_impl->cachedTypedefTemplSpec = unmarshalQCString (Doxygen::symbolStorage);
+ m_impl->cachedResolvedType = unmarshalQCString (Doxygen::symbolStorage);
m_impl->inbodyLine = unmarshalInt (Doxygen::symbolStorage);
m_impl->inbodyFile = unmarshalQCString (Doxygen::symbolStorage);
m_impl->inbodyDocs = unmarshalQCString (Doxygen::symbolStorage);
@@ -3778,3 +3805,84 @@ void MemberDef::loadFromDisk() const
assert(marker==END_MARKER);
}
+void MemberDef::makeResident() const
+{
+ if (m_cacheHandle==-1) // not yet in cache
+ {
+ MemberDef *victim = 0;
+ MemberDef *that = (MemberDef*)this; // fake method constness
+ that->m_cacheHandle = Doxygen::symbolCache->add(that,(void **)&victim);
+ //printf("adding %s to cache, handle=%d\n",m_impl->name.data(),that->m_cacheHandle);
+ if (victim) // cache was full, victim was the least recently used item and has to go
+ {
+ victim->m_cacheHandle=-1; // invalidate cache handle
+ victim->saveToDisk(); // store the item on disk
+ }
+ else // cache not yet full
+ {
+ //printf("Adding %s to cache, handle=%d\n",m_impl->name.data(),m_cacheHandle);
+ }
+ if (m_storagePos!=-1) // already been written to disk
+ {
+ if (isLocked()) // locked in memory
+ {
+ assert(m_impl!=0);
+ that->m_flushPending=FALSE; // no need to flush anymore
+ }
+ else // not locked in memory
+ {
+ assert(m_impl==0);
+ loadFromDisk();
+ }
+ }
+ }
+ else // already cached, make this object the most recently used.
+ {
+ assert(m_impl!=0);
+ //printf("Touching symbol %s\n",m_impl->name.data());
+ Doxygen::symbolCache->use(m_cacheHandle);
+ }
+}
+
+void MemberDef::saveToDisk() const
+{
+ assert(m_impl!=0);
+ MemberDef *that = (MemberDef *)this;
+ if (isLocked()) // cannot flush the item as it is locked
+ {
+ that->m_flushPending=TRUE; // flush when unlocked
+ }
+ else // ready to flush the item to disk
+ {
+ //printf("Adding %s to cache, handle=%d by replacing %s\n",
+ // m_impl->name.data(),m_cacheHandle,victim->m_impl->name.data());
+ if (m_storagePos!=-1)
+ // if victim was stored on disk already and is not locked
+ {
+ // free the storage space occupied by the old store item
+ Doxygen::symbolStorage->release(m_storagePos); // free up space for others
+ }
+ // write a the new (possibly modified) instance to disk
+ flushToDisk();
+ // end to write sequence (unless nothing was written due to the lock)
+ Doxygen::symbolStorage->end();
+ }
+}
+
+void MemberDef::lock() const
+{
+}
+
+void MemberDef::unlock() const
+{
+ if (m_flushPending && !isLocked())
+ {
+ // write a the new (possibly modified) instance to disk
+ flushToDisk();
+ // end to write sequence (unless nothing was written due to the lock)
+ Doxygen::symbolStorage->end();
+ }
+}
+
+
+
diff --git a/src/memberdef.h b/src/memberdef.h
index 52ee455..f0935a4 100644
--- a/src/memberdef.h
+++ b/src/memberdef.h
@@ -209,6 +209,7 @@ class MemberDef : public Definition
bool isTypedefValCached() const;
ClassDef *getCachedTypedefVal() const;
QCString getCachedTypedefTemplSpec() const;
+ QCString getCachedResolvedTypedef() const;
MemberDef *memberDefinition() const;
MemberDef *memberDeclaration() const;
@@ -294,7 +295,7 @@ class MemberDef : public Definition
void setDocsForDefinition(bool b);
void setGroupAlias(MemberDef *md);
- void cacheTypedefVal(ClassDef *val,const QCString &templSpec);
+ void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType);
void invalidateTypedefValCache();
// declaration <-> definition relation
@@ -330,6 +331,11 @@ class MemberDef : public Definition
void flushToDisk() const;
void loadFromDisk() const;
private:
+ void lock() const;
+ void unlock() const;
+ void saveToDisk() const;
+ void makeResident() const;
+
static int s_indentLevel;
// disable copying of member defs
MemberDef(const MemberDef &);
@@ -340,6 +346,9 @@ class MemberDef : public Definition
bool onlyText=FALSE);
MemberDefImpl *m_impl;
+ int m_cacheHandle;
+ off_t m_storagePos; // location where the item is stored in file (if impl==0)
+ bool m_flushPending;
};
#endif
diff --git a/src/membergroup.cpp b/src/membergroup.cpp
index 786b38f..ba599da 100644
--- a/src/membergroup.cpp
+++ b/src/membergroup.cpp
@@ -133,6 +133,7 @@ void MemberGroup::addToDeclarationSection()
{
if (inDeclSection)
{
+ //printf("Adding group %p to list %p\n",this,inDeclSection);
inDeclSection->addMemberGroup(this);
}
}
diff --git a/src/memberlist.cpp b/src/memberlist.cpp
index 78509bb..218bbd3 100644
--- a/src/memberlist.cpp
+++ b/src/memberlist.cpp
@@ -316,7 +316,8 @@ void MemberList::writeDeclarations(OutputList &ol,
//printf("----- writeDeclaration() ----\n");
countDecMembers(showEnumValues); // count member not in group
if (numDecMembers()==0) return;
- //printf("MemberList::writeDeclaration(title=`%s',subtitle=`%s')=%d\n",title,subtitle,numDecMembers());
+ //printf("%p: MemberList::writeDeclaration(title=`%s',subtitle=`%s')=%d\n",
+ // this,title,subtitle,numDecMembers());
if (title)
{
ol.startMemberHeader();
diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp
index e216081..1cbe197 100644
--- a/src/namespacedef.cpp
+++ b/src/namespacedef.cpp
@@ -51,6 +51,7 @@ NamespaceDef::NamespaceDef(const char *df,int dl,
memberGroupSDict = new MemberGroupSDict;
memberGroupSDict->setAutoDelete(TRUE);
visited=FALSE;
+ m_subGrouping=Config_getBool("SUBGROUPING");
}
NamespaceDef::~NamespaceDef()
@@ -151,6 +152,21 @@ void NamespaceDef::addMembersToMemberGroup()
::addMembersToMemberGroup(ml,&memberGroupSDict,this);
}
}
+
+ // add members inside sections to their groups
+ if (memberGroupSDict)
+ {
+ MemberGroupSDict::Iterator mgli(*memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ if (mg->allMembersInSameSection() && m_subGrouping)
+ {
+ //printf("----> addToDeclarationSection(%s)\n",mg->header().data());
+ mg->addToDeclarationSection();
+ }
+ }
+ }
}
void NamespaceDef::insertMember(MemberDef *md)
@@ -316,11 +332,18 @@ void NamespaceDef::writeDocumentation(OutputList &ol)
namespaceSDict->writeDeclaration(ol,TRUE);
/* write user defined member groups */
- MemberGroupSDict::Iterator mgli(*memberGroupSDict);
- MemberGroup *mg;
- for (;(mg=mgli.current());++mgli)
+ if (memberGroupSDict)
{
- mg->writeDeclarations(ol,0,this,0,0);
+ MemberGroupSDict::Iterator mgli(*memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ if ((!mg->allMembersInSameSection() || !m_subGrouping)
+ && mg->header()!="[NOHEADER]")
+ {
+ mg->writeDeclarations(ol,0,this,0,0);
+ }
+ }
}
writeMemberDeclarations(ol,MemberList::decDefineMembers,theTranslator->trDefines());
@@ -676,6 +699,7 @@ void NamespaceDef::addMemberToList(MemberList::ListType lt,MemberDef *md)
ml->inSort(md);
else
ml->append(md);
+ if (ml->listType()&MemberList::declarationLists) md->setSectionList(this,ml);
}
MemberList *NamespaceDef::getMemberList(MemberList::ListType lt) const
diff --git a/src/namespacedef.h b/src/namespacedef.h
index a1355d5..b720912 100644
--- a/src/namespacedef.h
+++ b/src/namespacedef.h
@@ -106,7 +106,7 @@ class NamespaceDef : public Definition
MemberGroupSDict *memberGroupSDict;
ClassSDict *classSDict;
NamespaceSDict *namespaceSDict;
-
+ bool m_subGrouping;
};
class NamespaceList : public QList<NamespaceDef>
diff --git a/src/objcache.cpp b/src/objcache.cpp
index c192504..63e7eb7 100644
--- a/src/objcache.cpp
+++ b/src/objcache.cpp
@@ -176,16 +176,31 @@ void ObjCache::moveToFront(int index)
unsigned int ObjCache::hash(void *addr)
{
- // Thomas Wang's 32 bit Mix Function
+ static bool isPtr64 = sizeof(addr)==8 && sizeof(long)==8;
- // TODO: what if sizeof(void*)!=4 ?
- unsigned int key = (unsigned int)addr;
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
+ unsigned long key = (unsigned long)addr;
+ if (isPtr64)
+ {
+ // Thomas Wang's 64 bit Mix Function
+ key += ~(key << 32);
+ key ^= (key >> 22);
+ key += ~(key << 13);
+ key ^= (key >> 8);
+ key += (key << 3);
+ key ^= (key >> 15);
+ key += ~(key << 27);
+ key ^= (key >> 31);
+ }
+ else
+ {
+ // Thomas Wang's 32 bit Mix Function
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ }
return key & (m_size-1);
}
diff --git a/src/pre.l b/src/pre.l
index ba206ec..08a8486 100644
--- a/src/pre.l
+++ b/src/pre.l
@@ -69,6 +69,7 @@ struct FileState
static int g_yyLineNr = 1;
static QCString g_yyFileName;
static FileDef *g_yyFileDef;
+static FileDef *g_inputFileDef;
static int g_ifcount = 0;
static QStrList *g_pathList = 0;
static QStack<FileState> g_includeStack;
@@ -1043,17 +1044,13 @@ void addDefine()
}
md->setInitializer(g_defLitText.stripWhiteSpace());
- //md->setDefFile(g_yyFileName);
- //md->setDefLine(g_yyLineNr);
- md->setFileDef(g_yyFileDef);
+ md->setFileDef(g_inputFileDef);
md->setDefinition("#define "+g_defName);
MemberName *mn=Doxygen::functionNameSDict->find(g_defName);
if (mn==0)
{
mn = new MemberName(g_defName);
- //Doxygen::functionNameList.append(mn);
- //Doxygen::functionNameDict.insert(g_defName,mn);
Doxygen::functionNameSDict->append(g_defName,mn);
}
mn->append(md);
@@ -1790,6 +1787,12 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
g_insideComment=FALSE;
BEGIN(DefineText);
}
+<DefineArg>"..." { // Variadic macro
+ g_defVarArgs = TRUE;
+ g_defArgsStr+=yytext;
+ g_argDict->insert("__VA_ARGS__",new int(g_defArgs));
+ g_defArgs++;
+ }
<DefineArg>{ID}{B}*("..."?) {
//printf("Define addArg(%s)\n",yytext);
QCString argName=yytext;
@@ -2372,6 +2375,7 @@ void preprocessFile(const char *fileName,BufStr &output)
g_level = 0;
g_ifcount = 0;
setFileName(fileName);
+ g_inputFileDef = g_yyFileDef;
BEGIN( Start );
g_lastGuardName.resize(0);
diff --git a/src/translator_jp.h b/src/translator_jp.h
index 9ab9fbc..01aec89 100644
--- a/src/translator_jp.h
+++ b/src/translator_jp.h
@@ -29,7 +29,7 @@
#ifndef TRANSLATOR_JP_H
#define TRANSLATOR_JP_H
-class TranslatorJapanese : public TranslatorAdapter_1_4_6
+class TranslatorJapanese : public Translator
{
private:
/*! The decode() can change euc into sjis */
@@ -454,12 +454,6 @@ class TranslatorJapanese : public TranslatorAdapter_1_4_6
{ return decode("列挙型"); }
/*! This is used in the documentation of a file/namespace before the list
- * of documentation blocks for enumeration values
- */
- virtual QCString trEnumerationValueDocumentation()
- { return decode("列挙型の値"); }
-
- /*! This is used in the documentation of a file/namespace before the list
* of documentation blocks for functions
*/
virtual QCString trFunctionDocumentation()
@@ -1562,5 +1556,23 @@ class TranslatorJapanese : public TranslatorAdapter_1_4_6
"利便性のために用意されています。"
"元の関数との違いは引き数のみです。");
}
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.4.6
+//////////////////////////////////////////////////////////////////////////
+
+ /*! This is used to introduce a caller (or called-by) graph */
+ virtual QCString trCallerGraph()
+ {
+ // return "Here is the caller graph for this function:";
+ return "呼出しグラフ:";
+ }
+
+ /*! This is used in the documentation of a file/namespace before the list
+ * of documentation blocks for enumeration values
+ */
+ virtual QCString trEnumerationValueDocumentation()
+ { return "列挙型"; }
+
};
#endif
diff --git a/src/util.cpp b/src/util.cpp
index c9993a1..0ae6fa2 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -594,7 +594,8 @@ ClassDef *getResolvedClassRec(Definition *scope,
FileDef *fileScope,
const char *n,
MemberDef **pTypeDef,
- QCString *pTemplSpec
+ QCString *pTemplSpec,
+ QCString *pResolvedType
);
int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,Definition *item,
const QCString &explicitScopePart);
@@ -607,7 +608,8 @@ int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,Definition
* Example: typedef int T; will return 0, since "int" is not a class.
*/
ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md,
- MemberDef **pMemType,QCString *pTemplSpec)
+ MemberDef **pMemType,QCString *pTemplSpec,
+ QCString *pResolvedType)
{
//printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal());
bool isCached = md->isTypedefValCached(); // value already cached
@@ -616,7 +618,8 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md,
//printf("Already cached %s->%s\n",
// md->name().data(),
// md->getCachedTypedefVal()?md->getCachedTypedefVal()->name().data():"<none>");
- if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec();
+ if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec();
+ if (pResolvedType) *pResolvedType = md->getCachedResolvedTypedef();
return md->getCachedTypedefVal();
}
QCString qname = md->qualifiedName();
@@ -625,29 +628,33 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md,
g_resolvedTypedefs.insert(qname,md); // put on the trace list
QCString type = md->typeString(); // get the "value" of the typedef
- int ip=type.length()-1; // remove * and & at the end
+ QCString typedefValue = type;
+ int tl=type.length();
+ int ip=tl-1; // remove * and & at the end
while (ip>=0 && (type.at(ip)=='*' || type.at(ip)=='&' || type.at(ip)==' '))
{
ip--;
}
type=type.left(ip+1);
- type.stripPrefix("const "); // strip leading "const"
- type.stripPrefix("struct "); // strip leading "struct"
- type.stripPrefix("union "); // strip leading "union"
- type=type.stripWhiteSpace(); // strip leading and trailing whitespace
+ int sp=0;
+ if (type.stripPrefix("const ")) sp+=6; // strip leading "const"
+ if (type.stripPrefix("struct ")) sp+=7; // strip leading "struct"
+ if (type.stripPrefix("union ")) sp+=6; // strip leading "union"
+ while (sp<tl && type.at(sp)==' ') sp++;
MemberDef *memTypeDef = 0;
ClassDef *result = getResolvedClassRec(md->getOuterScope(),
- fileScope,type,&memTypeDef,0);
- // if type is a typedef than return what it resolves to.
+ fileScope,type,&memTypeDef,0,pResolvedType);
+ // if type is a typedef then return what it resolves to.
if (memTypeDef && memTypeDef->isTypedef())
{
- return newResolveTypedef(fileScope,memTypeDef,pMemType,pTemplSpec);
+ result=newResolveTypedef(fileScope,memTypeDef,pMemType,pTemplSpec);
+ goto done;
}
else if (memTypeDef && memTypeDef->isEnumerate() && pMemType)
{
*pMemType = memTypeDef;
}
-
+
//printf("type=%s result=%p\n",type.data(),result);
if (result==0)
{
@@ -656,8 +663,9 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md,
int i=type.find('<');
if (si==-1 && i!=-1) // typedef of a template => try the unspecialized version
{
- *pTemplSpec = type.mid(i);
- result = getResolvedClassRec(md->getOuterScope(),fileScope,type.left(i),0,0);
+ if (pTemplSpec) *pTemplSpec = type.mid(i);
+ result = getResolvedClassRec(md->getOuterScope(),fileScope,
+ type.left(i),0,0,pResolvedType);
}
else if (si!=-1) // A::B
{
@@ -671,7 +679,25 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md,
if (pTemplSpec) *pTemplSpec = type.mid(i);
}
result = getResolvedClassRec(md->getOuterScope(),fileScope,
- stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0);
+ stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0,
+ pResolvedType);
+ }
+
+ if (result) ip=si+sp+1;
+ }
+
+done:
+ if (pResolvedType)
+ {
+ if (result)
+ {
+ *pResolvedType=result->qualifiedName();
+ if (sp>0) pResolvedType->prepend(typedefValue.left(sp));
+ if (ip<tl-1) pResolvedType->append(typedefValue.right(tl-ip-1));
+ }
+ else
+ {
+ *pResolvedType=typedefValue;
}
}
@@ -682,14 +708,10 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md,
{
//printf("setting cached typedef %p in result %p\n",md,result);
//printf("==> %s (%s,%d)\n",result->name().data(),result->getDefFileName().data(),result->getDefLine());
- if (pTemplSpec)
- {
- md->cacheTypedefVal(result,*pTemplSpec);
- }
- else
- {
- md->cacheTypedefVal(result,"");
- }
+ md->cacheTypedefVal(result,
+ pTemplSpec ? *pTemplSpec : QCString(),
+ pResolvedType ? *pResolvedType : QCString()
+ );
}
g_resolvedTypedefs.remove(qname); // remove from the trace list
@@ -914,7 +936,15 @@ int isAccessibleFrom(Definition *scope,FileDef *fileScope,Definition *item)
int result=0; // assume we found it
int i;
- if (item->getOuterScope()==scope)
+ Definition *itemScope=item->getOuterScope();
+
+ if (itemScope==scope ||
+ (item->definitionType()==Definition::TypeMember &&
+ itemScope && itemScope->definitionType()==Definition::TypeClass &&
+ scope->definitionType()==Definition::TypeClass &&
+ ((ClassDef*)scope)->isAccessibleMember((MemberDef *)item)
+ )
+ )
{
//printf("> found it\n");
}
@@ -1118,14 +1148,15 @@ int computeQualifiedIndex(const QCString &name)
return name.findRev("::",i==-1 ? name.length() : i);
}
-void getResolvedSymbol(Definition *scope,
+static void getResolvedSymbol(Definition *scope,
FileDef *fileScope,
Definition *d,
const QCString &explicitScopePart,
int &minDistance,
ClassDef *&bestMatch,
MemberDef *&bestTypedef,
- QCString &bestTemplSpec
+ QCString &bestTemplSpec,
+ QCString &bestResolvedType
)
{
//printf(" found type %x name=%s d=%p\n",
@@ -1161,6 +1192,7 @@ void getResolvedSymbol(Definition *scope,
bestMatch = cd;
bestTypedef = 0;
bestTemplSpec.resize(0);
+ bestResolvedType = cd->qualifiedName();
}
else if (distance==minDistance &&
fileScope && bestMatch &&
@@ -1181,6 +1213,7 @@ void getResolvedSymbol(Definition *scope,
bestMatch = cd;
bestTypedef = 0;
bestTemplSpec.resize(0);
+ bestResolvedType = cd->qualifiedName();
}
}
else
@@ -1206,22 +1239,25 @@ void getResolvedSymbol(Definition *scope,
if (distance<minDistance)
{
QCString spec;
+ QCString type;
minDistance=distance;
MemberDef *enumType = 0;
- ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec);
- if (cd) // shouldn't be 0, but could in some weird cases
+ ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type);
+ if (cd) // type resolves to a class
{
- //printf(" bestTypeDef=%p spec=%s\n",md,spec.data());
+ //printf(" bestTypeDef=%p spec=%s type=%s\n",md,spec.data(),type.data());
bestMatch = cd;
bestTypedef = md;
bestTemplSpec = spec;
+ bestResolvedType = type;
}
- else if (enumType)
+ else if (enumType) // type resolves to a enum
{
//printf(" is enum\n");
bestMatch = 0;
bestTypedef = enumType;
bestTemplSpec = "";
+ bestResolvedType = enumType->qualifiedName();
}
else
{
@@ -1246,6 +1282,7 @@ void getResolvedSymbol(Definition *scope,
bestMatch = 0;
bestTypedef = md;
bestTemplSpec = "";
+ bestResolvedType = md->qualifiedName();
}
}
}
@@ -1255,6 +1292,7 @@ void getResolvedSymbol(Definition *scope,
//printf(" Not accessible!\n");
}
} // if definition is a class or member
+ //printf(" bestMatch=%p bestResolvedType=%s\n",bestMatch,bestResolvedType.data());
}
/* Find the fully qualified class name refered to by the input class
@@ -1267,7 +1305,8 @@ ClassDef *getResolvedClassRec(Definition *scope,
FileDef *fileScope,
const char *n,
MemberDef **pTypeDef,
- QCString *pTemplSpec
+ QCString *pTemplSpec,
+ QCString *pResolvedType
)
{
//printf("[getResolvedClassRec(%s,%s)\n",scope?scope->name().data():"<global>",n);
@@ -1345,8 +1384,9 @@ ClassDef *getResolvedClassRec(Definition *scope,
//printf("Searching for %s result=%p\n",key.data(),pval);
if (pval)
{
- if (pTemplSpec) *pTemplSpec=pval->templSpec;
- if (pTypeDef) *pTypeDef=pval->typeDef;
+ if (pTemplSpec) *pTemplSpec=pval->templSpec;
+ if (pTypeDef) *pTypeDef=pval->typeDef;
+ if (pResolvedType) *pResolvedType=pval->resolvedType;
//printf("] cachedMatch=%s\n",
// pval->classDef?pval->classDef->name().data():"<none>");
//if (pTemplSpec)
@@ -1362,6 +1402,7 @@ ClassDef *getResolvedClassRec(Definition *scope,
ClassDef *bestMatch=0;
MemberDef *bestTypedef=0;
QCString bestTemplSpec;
+ QCString bestResolvedType;
int minDistance=10000; // init at "infinite"
if (di->definitionType()==DefinitionIntf::TypeSymbolList)
@@ -1372,14 +1413,16 @@ ClassDef *getResolvedClassRec(Definition *scope,
for (dli.toFirst();(d=dli.current());++dli,++count) // foreach definition
{
getResolvedSymbol(scope,fileScope,d,explicitScopePart,
- minDistance,bestMatch,bestTypedef,bestTemplSpec);
+ minDistance,bestMatch,bestTypedef,bestTemplSpec,
+ bestResolvedType);
}
}
else
{
Definition *d = (Definition *)di;
getResolvedSymbol(scope,fileScope,d,explicitScopePart,
- minDistance,bestMatch,bestTypedef,bestTemplSpec);
+ minDistance,bestMatch,bestTypedef,bestTemplSpec,
+ bestResolvedType);
}
if (pTypeDef)
@@ -1390,17 +1433,24 @@ ClassDef *getResolvedClassRec(Definition *scope,
{
*pTemplSpec = bestTemplSpec;
}
+ if (pResolvedType)
+ {
+ *pResolvedType = bestResolvedType;
+ }
+ //printf("getResolvedClassRec: bestMatch=%p pval->resolvedType=%s\n",
+ // bestMatch,bestResolvedType.data());
pval=Doxygen::lookupCache.find(key);
if (pval)
{
- pval->classDef = bestMatch;
- pval->typeDef = bestTypedef;
- pval->templSpec = bestTemplSpec;
+ pval->classDef = bestMatch;
+ pval->typeDef = bestTypedef;
+ pval->templSpec = bestTemplSpec;
+ pval->resolvedType = bestResolvedType;
}
else
{
- Doxygen::lookupCache.insert(key,new LookupInfo(bestMatch,bestTypedef,bestTemplSpec));
+ Doxygen::lookupCache.insert(key,new LookupInfo(bestMatch,bestTypedef,bestTemplSpec,bestResolvedType));
}
//printf("] bestMatch=%s distance=%d\n",
// bestMatch?bestMatch->name().data():"<none>",minDistance);
@@ -1420,7 +1470,8 @@ ClassDef *getResolvedClass(Definition *scope,
MemberDef **pTypeDef,
QCString *pTemplSpec,
bool mayBeUnlinkable,
- bool mayBeHidden
+ bool mayBeHidden,
+ QCString *pResolvedType
)
{
g_resolvedTypedefs.clear();
@@ -1439,7 +1490,7 @@ ClassDef *getResolvedClass(Definition *scope,
// n,
// mayBeUnlinkable
// );
- ClassDef *result = getResolvedClassRec(scope,fileScope,n,pTypeDef,pTemplSpec);
+ ClassDef *result = getResolvedClassRec(scope,fileScope,n,pTypeDef,pTemplSpec,pResolvedType);
if (!mayBeUnlinkable && result && !result->isLinkable())
{
if (!mayBeHidden || !result->isHidden())
@@ -2115,7 +2166,7 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level)
if (level==256)
{
err("Error: Internal inconsistency: found class %s seem to have a recursive "
- "inheritance relation! Please send a bug report to dimitri@stack.nl\n",cd->name().data());
+ "inheritance relation! Please send a bug report to dimitri@stack.nl",cd->name().data());
return -1;
}
int m=maxInheritanceDepth;
@@ -2531,7 +2582,6 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
dstAType = dstAType.right(dstAType.length()-9);
}
-
srcAType = removeRedundantWhiteSpace(srcAType);
dstAType = removeRedundantWhiteSpace(dstAType);
@@ -2883,9 +2933,10 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type);
QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec)
{
+ //printf("getCanonicalTemplateSpec(%s)\n",spec.data());
QCString templSpec = spec.stripWhiteSpace();
if (templSpec.isEmpty() || templSpec.at(0) != '<') return templSpec;
- return "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1));
+ return "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1).stripWhiteSpace());
}
@@ -2895,7 +2946,7 @@ static QCString getCanonicalTypeForIdentifier(
{
QCString symName,scope,result,templSpec,tmpName;
//DefinitionList *defList=0;
- if (tSpec) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec));
+ if (tSpec && !tSpec->isEmpty()) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec));
if (word.findRev("::")!=-1 && !(tmpName=stripScope(word)).isEmpty())
{
@@ -2909,17 +2960,19 @@ static QCString getCanonicalTypeForIdentifier(
ClassDef *cd = 0;
MemberDef *mType = 0;
QCString ts;
+ QCString resolvedType;
// lookup class / class template instance
- cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE);
+ cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE,TRUE,&resolvedType);
bool isTemplInst = cd && !templSpec.isEmpty();
if (!cd && !templSpec.isEmpty())
{
// class template specialization not known, look up class template
- cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE);
+ cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE,TRUE,&resolvedType);
}
+ if (cd && cd->isUsedOnly()) cd=0; // ignore types introduced by usage relations
- //printf("symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n",
+ //printf(" symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n",
// symName.data(),
// word.data(),
// cd?cd->name().data():"<none>",
@@ -2928,38 +2981,57 @@ static QCString getCanonicalTypeForIdentifier(
// cd?cd->isTemplate():-1
// );
- //printf(">>>> word '%s' => '%s' templSpec=%s ts=%s tSpec=%s\n",
+ //printf(" >>>> word '%s' => '%s' templSpec=%s ts=%s tSpec=%s isTemplate=%d resolvedType=%s\n",
// (word+templSpec).data(),
// cd?cd->qualifiedName().data():"<none>",
- // templSpec.data(),ts.data(),
- // tSpec?tSpec->data():"<null>");
+ // templSpec.data(),ts.data(),
+ // tSpec?tSpec->data():"<null>",
+ // cd?cd->isTemplate():FALSE,
+ // resolvedType.data());
- if (cd) // known class type
+ //printf(" mtype=%s\n",mType?mType->name().data():"<none>");
+
+ if (cd) // resolves to a known class type
{
- if (isTemplInst)
+ if (mType && mType->isTypedef()) // but via a typedef
{
- // spec is already part of class type
- templSpec="";
- if (tSpec) *tSpec="";
+ result = resolvedType;
}
- else if (!ts.isEmpty() && templSpec.isEmpty())
+ else
{
- // use formal template args for spec
- templSpec = stripDeclKeywords(ts);
- }
+ if (isTemplInst)
+ {
+ // spec is already part of class type
+ templSpec="";
+ if (tSpec) *tSpec="";
+ }
+ else if (!ts.isEmpty() && templSpec.isEmpty())
+ {
+ // use formal template args for spec
+ templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,ts));
+ }
- result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec);
+ result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec);
- if (cd->isTemplate() && tSpec)
- {
- // template class, so remove the template part (it is part of the class name)
- *tSpec="";
- }
- else if (ts.isEmpty() && !templSpec.isEmpty() && cd && !cd->isTemplate() && tSpec)
- {
- // obscure case, where a class is used as a template, but doxygen think it is
- // not (could happen when loading the class from a tag file).
- *tSpec="";
+ if (cd->isTemplate() && tSpec) //
+ {
+ if (!templSpec.isEmpty()) // specific instance
+ {
+ result=cd->name()+templSpec;
+ }
+ else // use template type
+ {
+ result=cd->qualifiedNameWithTemplateParameters();
+ }
+ // template class, so remove the template part (it is part of the class name)
+ *tSpec="";
+ }
+ else if (ts.isEmpty() && !templSpec.isEmpty() && cd && !cd->isTemplate() && tSpec)
+ {
+ // obscure case, where a class is used as a template, but doxygen think it is
+ // not (could happen when loading the class from a tag file).
+ *tSpec="";
+ }
}
}
else if (mType && mType->isEnumerate()) // an enum
@@ -2968,7 +3040,7 @@ static QCString getCanonicalTypeForIdentifier(
}
else
{
- QCString resolvedType = resolveTypeDef(d,word);
+ resolvedType = resolveTypeDef(d,word);
if (resolvedType.isEmpty()) // not known as a typedef either
{
result = word;
@@ -2996,7 +3068,8 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type)
type.stripPrefix("typename ");
type = removeRedundantWhiteSpace(type);
- //printf("extractCanonicalType(type=%s)\n",type.data());
+ //printf("extractCanonicalType(type=%s) def=%s file=%s\n",type.data(),
+ // d ? d->name().data() : "<null>",fs ? fs->name().data() : "<null>");
static QRegExp id("[a-z_A-Z][:a-z_A-Z0-9]*");
@@ -3008,7 +3081,7 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type)
//printf(" i=%d p=%d\n",i,p);
canType += type.mid(pp,i-pp);
- //printf("word=%s templSpec=%s\n",word.data(),templSpec.data());
+ //printf(" word=%s templSpec=%s\n",word.data(),templSpec.data());
canType += getCanonicalTypeForIdentifier(d,fs,word,&templSpec);
if (!templSpec.isEmpty()) // if we didn't use up the templSpec already
@@ -3668,14 +3741,13 @@ bool getDefs(const QCString &scName,const QCString &memberName,
MemberListIterator mli(*mn);
for (mli.toFirst();(md=mli.current());++mli)
{
- //if (md->isLinkable())
- //{
fd=md->getFileDef();
gd=md->getGroupDef();
//printf(" md->name()=`%s' md->args=`%s' fd=%p gd=%p\n",
// md->name().data(),args,fd,gd);
if (
- (gd && gd->isLinkable()) || (fd && fd->isLinkable())
+ ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) &&
+ md->getNamespaceDef()==0
)
{
//printf(" fd=%p gd=%p args=`%s'\n",fd,gd,args);
@@ -3698,7 +3770,6 @@ bool getDefs(const QCString &scName,const QCString &memberName,
members.append(md);
}
}
- //}
}
if (members.count()!=1 && args && !strcmp(args,"()"))
{
@@ -3739,12 +3810,12 @@ bool getDefs(const QCString &scName,const QCString &memberName,
MemberDef *bmd = 0;
for (md=members.first(); md; md=members.next())
{
- if (md->getFileDef() == currentFile)
+ if (currentFile && md->getBodyDef()==currentFile)
{
bmd = 0;
break;
}
- if (!(md->isStatic()) || Config_getBool("EXTRACT_STATIC")) bmd = md;
+ if (!md->isStatic() || Config_getBool("EXTRACT_STATIC")) bmd = md;
}
if (bmd) md=bmd;
}
@@ -4174,7 +4245,7 @@ bool generateLink(OutputDocInterface &od,const char *clName,
}
else
{
- err("%s:%d: Internal error: resolveLink successful but no compound found!\n",__FILE__,__LINE__);
+ err("%s:%d: Internal error: resolveLink successful but no compound found!",__FILE__,__LINE__);
}
return TRUE;
}
diff --git a/src/util.h b/src/util.h
index 881ad78..fb6de09 100644
--- a/src/util.h
+++ b/src/util.h
@@ -175,7 +175,8 @@ ClassDef *getResolvedClass(Definition *scope,
MemberDef **pTypeDef=0,
QCString *pTemplSpec=0,
bool mayBeUnlinkable=FALSE,
- bool mayBeHidden=FALSE);
+ bool mayBeHidden=FALSE,
+ QCString *pResolvedType=0);
NamespaceDef *getResolvedNamespace(const char *key);
@@ -326,7 +327,8 @@ SrcLangExt getLanguageFromFileName(const QCString fileName);
bool checkIfTypedef(Definition *scope,FileDef *fileScope,const char *n);
ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md,
- MemberDef **pMemType=0,QCString *pTemplSpec=0);
+ MemberDef **pMemType=0,QCString *pTemplSpec=0,
+ QCString *pResolvedType=0);
#endif