summaryrefslogtreecommitdiffstats
path: root/src/util.cpp
diff options
context:
space:
mode:
authordimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7>2001-08-01 18:08:50 (GMT)
committerdimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7>2001-08-01 18:08:50 (GMT)
commit071e39254b00ad7ffed5de8cdeb44072278d4d57 (patch)
treedd7f0f7dd0875046b1426a541b00547a8af08af1 /src/util.cpp
parentea8a1bc7ccbd7b64a31c293caa31240bde7397cf (diff)
downloadDoxygen-071e39254b00ad7ffed5de8cdeb44072278d4d57.zip
Doxygen-071e39254b00ad7ffed5de8cdeb44072278d4d57.tar.gz
Doxygen-071e39254b00ad7ffed5de8cdeb44072278d4d57.tar.bz2
Release-1.2.9
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp297
1 files changed, 222 insertions, 75 deletions
diff --git a/src/util.cpp b/src/util.cpp
index 52045cb..576e1c1 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -332,6 +332,77 @@ int guessSection(const char *name)
return 0;
}
+QCString resolveTypeDef(Definition *d,const QCString &name)
+{
+ //printf("resolveTypeDef(%s,%s)\n",d ? d->name().data() : "<none>",name.data());
+ QCString result;
+ if (name.isEmpty()) return result;
+ Definition *mContext=d;
+ MemberDef *md=0;
+ while (mContext && md==0)
+ {
+ MemberNameDict *mnd=0;
+ if (mContext->definitionType()==Definition::TypeClass)
+ {
+ mnd=&Doxygen::memberNameDict;
+ }
+ else
+ {
+ mnd=&Doxygen::functionNameDict;
+ }
+ MemberName *mn=mnd->find(name);
+ if (mn)
+ {
+ MemberNameIterator mni(*mn);
+ MemberDef *tmd=0;
+ for (;(tmd=mni.current());++mni)
+ {
+ //printf("Found member %s scope=%p mContext=%p\n",tmd->name().data(),
+ // tmd->getOuterScope(),mContext);
+ if (tmd->isTypedef() && tmd->getOuterScope()==mContext)
+ {
+ md=tmd;
+ }
+ }
+ }
+ mContext=mContext->getOuterScope();
+ }
+ if (md)
+ {
+ //printf("Found typedef name `%s' in scope `%s' value=`%s'\n",
+ // name.data(),d->name().data(),md->typeString()
+ // );
+ result=md->typeString();
+ }
+ else
+ {
+ //printf("Typedef `%s' not found in scope `%s'!\n",
+ // name.data(),d ? d->name().data() : "<global>");
+ }
+ return result;
+
+#if 0
+ QCString typeName;
+ if (!name.isEmpty())
+ {
+ TypedefInfo *ti = Doxygen::typedefDict[name];
+ if (ti)
+ {
+ int count=0;
+ typeName=ti->value;
+ TypedefInfo *newTi;
+ while ((newTi=Doxygen::typedefDict[typeName]) && count<10)
+ {
+ if (typeName==newTi->value) break; // prevent lock-up
+ typeName=newTi->value;
+ count++;
+ }
+ }
+ }
+ return typeName;
+#endif
+}
+
/*! Get a class definition given its name.
* Returns 0 if the class is not found.
*/
@@ -366,32 +437,54 @@ NamespaceDef *getResolvedNamespace(const char *name)
}
}
-ClassDef *getResolvedClass(const char *n,bool *pIsTypeDef,QCString *pTemplSpec)
+ClassDef *getResolvedClass(
+ Definition *scope,
+ const char *n,
+ bool *pIsTypeDef,
+ QCString *pTemplSpec
+ )
{
+ //printf("getResolvedClass(%s,%s)\n",scope ? scope->name().data() : "<none>",
+ // n);
QCString name = n;
if (name.isEmpty()) return 0;
+ if (scope==0) scope=Doxygen::globalScope;
int i = name.findRev("::");
- QCString *subst = 0;
- if (i!=-1) subst = Doxygen::typedefDict[name.right(name.length()-i-2)];
- if (subst==0) subst = Doxygen::typedefDict[name],i=-1;
- if (subst) // there is a typedef with this name
+ //QCString subst = 0;
+ //if (i!=-1) subst = Doxygen::typedefDict[name.right(name.length()-i-2)];
+ //if (subst==0) subst = Doxygen::typedefDict[name],i=-1;
+ //if (subst) // there is a typedef with this name
+ QCString subst;
+ if (i!=-1)
+ {
+ subst = resolveTypeDef(scope,name.right(name.length()-i-2));
+ }
+ else
+ {
+ subst = resolveTypeDef(scope,name);
+ }
+
+ if (!subst.isEmpty())
{
if (pIsTypeDef) *pIsTypeDef=TRUE;
//printf("getResolvedClass `%s'->`%s'\n",name.data(),subst->data());
- if (*subst==name) // avoid resolving typedef struct foo foo;
+ if (subst==name) // avoid resolving typedef struct foo foo;
{
return Doxygen::classSDict.find(name);
}
int count=0; // recursion detection guard
- QCString *newSubst;
- QCString typeName = *subst;
+ QCString newSubst;
+ QCString typeName = subst;
if (i!=-1) typeName.prepend(name.left(i)+"::");
- while ((newSubst=Doxygen::typedefDict[typeName]) && count<10)
+ while (!(newSubst=resolveTypeDef(scope,typeName)).isEmpty()
+ && count<10)
{
- if (typeName==*newSubst)
- return Doxygen::classSDict.find(subst->data()); // for breaking typedef struct A A;
+ if (typeName==newSubst)
+ {
+ return Doxygen::classSDict.find(subst); // for breaking typedef struct A A;
+ }
subst=newSubst;
- typeName=*newSubst;
+ typeName=newSubst;
if (i!=-1) typeName.prepend(name.left(i)+"::");
count++;
}
@@ -437,15 +530,19 @@ static bool findOperator(const QCString &s,int i)
return TRUE;
}
+static const char constScope[] = { 'c', 'o', 'n', 's', 't', ':' };
+
QCString removeRedundantWhiteSpace(const QCString &s)
{
if (s.isEmpty()) return s;
QCString result;
uint i;
uint l=s.length();
+ uint csp=0;
for (i=0;i<l;i++)
{
char c=s.at(i);
+ if (csp<6 && c==constScope[csp]) csp++; else csp=0;
if (i<l-2 && c=='<' && // current char is a <
(isId(s.at(i+1)) || isspace(s.at(i+1))) && // next char is an id char or space
(i<8 || !findOperator(s,i)) // string in front is not "operator"
@@ -469,6 +566,11 @@ QCString removeRedundantWhiteSpace(const QCString &s)
result+=' ';
result+=s.at(i);
}
+ else if (c==':' && csp==6)
+ {
+ result+=" :";
+ csp=0;
+ }
else if (!isspace(c) ||
( i!=0 && i!=l-1 &&
(isId(s.at(i-1)) || s.at(i-1)==')' || s.at(i-1)==',' || s.at(i-1)=='>' || s.at(i-1)==']') &&
@@ -914,46 +1016,24 @@ int minClassDistance(ClassDef *cd,ClassDef *bcd,int level)
// strip any template specifiers that follow className in string s
static QCString trimTemplateSpecifiers(const QCString &className,const QCString &s)
{
- // first we resolve any defines
- //int i=0,p,l;
- //QCString result;
- //QRegExp r("[A-Z_a-z][A-Z_a-z0-9]*");
- //while ((p=r.match(s,i,&l))!=-1)
- //{
- // if (p>i) result+=s.mid(i,p-i);
- // result+=resolveDefines(s.mid(p,l));
- // i=p+l;
- //}
- //if (i<(int)s.length()) result+=s.mid(i,s.length()-i);
-
+ //printf("trimTemplateSpecifiers(%s,%s)\n",className.data(),s.data());
+ ClassDef *cd=getClass(className);
+ if (cd==0) return s;
+
+ QCString qualName=cd->qualifiedNameWithTemplateParameters();
+ //printf("QualifiedName = %s\n",qualName.data());
// We strip the template arguments following className (if any)
- QCString result=s.copy();
- int l=className.length();
- if (l>0) // there is a class name
+ QCString result=s;
+ if (!qualName.isEmpty()) // there is a class name
{
int i,p=0;
- while ((i=result.find(className,p))!=-1) // class name is in the argument type
+ // TODO: also try smaller parts of the qualName, since we
+ // could be inside a namespace or class.
+ while ((i=result.find(qualName,p))!=-1) // class name is in the argument type
{
- uint s=i+l;
- if (s<result.length() && result.at(s)=='<') // class has template args
- {
- int b=1;
- uint e=s+1;
- while (b>0 && e<result.length()) // find matching >
- {
- if (result.at(e)=='<') b++;
- else if (result.at(e)=='>') b--;
- e++;
- }
- // remove template argument
- result=result.left(s)+result.right(result.length()-e);
- if (result.length()>s && (result.at(s)=='*' || result.at(s)=='&'))
- {
- // insert a space to keep the argument in the canonical form
- result=result.left(s)+" "+result.right(result.length()-s);
- }
- }
- p=i+l;
+ int ql=qualName.length();
+ result=result.left(i)+cd->name()+result.right(result.length()-i-ql);
+ p=i+cd->name().length();
}
}
return result;
@@ -981,6 +1061,7 @@ static QCString trimScope(const QCString &name,const QCString &s)
scopeOffset=name.findRev("::",scopeOffset-1);
result = tmp;
} while (scopeOffset>0);
+ //printf("trimScope(name=%s,scope=%s)=%s\n",name.data(),s.data(),result.data());
return result;
}
@@ -1085,6 +1166,23 @@ void stripIrrelevantConstVolatile(QCString &s)
}
}
+#if 0 // should be done differently
+static QCString resolveTypeDefs(const QCString &s)
+{
+ QCString result;
+ static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*");
+ int p=0,l,i;
+ while ((i=re.match(s,p,&l))!=-1)
+ {
+ result += s.mid(p,i-p);
+ result += resolveTypeDef(s.mid(i,l));
+ p=i+l;
+ }
+ result+=s.right(s.length()-p);
+ return result;
+}
+#endif
+
// a bit of debug support for matchArguments
#define MATCH
#define NOMATCH
@@ -1097,6 +1195,15 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
NamespaceList *usingNamespaces,
ClassList *usingClasses)
{
+ //printf("match argument start %s:%s <-> %s:%s\n",
+ // srcA->type.data(),srcA->name.data(),
+ // dstA->type.data(),dstA->name.data());
+
+ // TODO: resolve any typedefs names that are part of srcA->type
+ // before matching. This should use className and namespaceName
+ // and usingNamespaces and usingClass to determine which typedefs
+ // are in-scope, so it will not be very efficient :-(
+
QCString srcAType=trimTemplateSpecifiers(className,srcA->type);
QCString dstAType=trimTemplateSpecifiers(className,dstA->type);
if (srcAType.left(6)=="class ") srcAType=srcAType.right(srcAType.length()-6);
@@ -1106,21 +1213,34 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
// from a syntactic point of view they would be two names of the same
// type "const". This is not fool prove ofcourse, but should at least
// catch the most common cases.
- if (srcAType=="const" && !srcA->name.isEmpty())
+ if ((srcAType=="const" || srcAType=="volatile") && !srcA->name.isEmpty())
{
srcAType+=" ";
srcAType+=srcA->name;
}
- if (dstAType=="const" && !dstA->name.isEmpty())
+ if ((dstAType=="const" || dstAType=="volatile") && !dstA->name.isEmpty())
{
dstAType+=" ";
dstAType+=dstA->name;
}
- //printf("scope=`%s': `%s' <=> `%s'\n",className.data(),srcAType.data(),dstAType.data());
+ if (srcA->name=="const" || srcA->name=="volatile")
+ {
+ srcAType+=srcA->name;
+ }
+ if (dstA->name=="const" || dstA->name=="volatile")
+ {
+ dstAType+=dstA->name;
+ }
stripIrrelevantConstVolatile(srcAType);
stripIrrelevantConstVolatile(dstAType);
+ //srcAType=stripTemplateSpecifiersFromScope(srcAType,FALSE);
+ //dstAType=stripTemplateSpecifiersFromScope(dstAType,FALSE);
+
+ //printf("srcA=%s:%s dstA=%s:%s\n",srcAType.data(),srcA->name.data(),
+ // dstAType.data(),dstA->name.data());
+
if (srcA->array!=dstA->array) // nomatch for char[] against char
{
NOMATCH
@@ -1132,7 +1252,7 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
// remove a namespace scope that is only in one type
// (assuming a using statement was used)
trimNamespaceScope(srcAType,dstAType);
-
+
//QCString srcScope;
//QCString dstScope;
@@ -1192,7 +1312,8 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
MATCH
return TRUE;
}
- //printf("srcA=%s::%s dstA=%s::%s\n",srcAType.data(),srcA->name.data(),
+
+ //printf("2. srcA=%s:%s dstA=%s:%s\n",srcAType.data(),srcA->name.data(),
// dstAType.data(),dstA->name.data());
uint srcPos=0,dstPos=0;
@@ -1309,10 +1430,28 @@ static void mergeArgument(Argument *srcA,Argument *dstA,
NamespaceList *usingNamespaces,
ClassList *usingClasses)
{
+ //printf("merge argument start %s:%s <-> %s:%s\n",
+ // srcA->type.data(),srcA->name.data(),
+ // dstA->type.data(),dstA->name.data());
+
+ if ((srcA->type=="const" || srcA->type=="volatile") && !srcA->name.isEmpty())
+ {
+ srcA->type+=" ";
+ srcA->type+=srcA->name;
+ srcA->name.resize(0);
+ }
+ if ((dstA->type=="const" || dstA->type=="volatile") && !dstA->name.isEmpty())
+ {
+ dstA->type+=" ";
+ dstA->type+=dstA->name;
+ dstA->name.resize(0);
+ }
+
QCString srcAType=trimTemplateSpecifiers(className,srcA->type);
QCString dstAType=trimTemplateSpecifiers(className,dstA->type);
if (srcAType.left(6)=="class ") srcAType=srcAType.right(srcAType.length()-6);
if (dstAType.left(6)=="class ") dstAType=dstAType.right(dstAType.length()-6);
+
stripIrrelevantConstVolatile(srcAType);
stripIrrelevantConstVolatile(dstAType);
@@ -1324,6 +1463,7 @@ static void mergeArgument(Argument *srcA,Argument *dstA,
// (assuming a using statement was used)
trimNamespaceScope(srcAType,dstAType);
+
//QCString srcScope;
//QCString dstScope;
@@ -1376,14 +1516,14 @@ static void mergeArgument(Argument *srcA,Argument *dstA,
{
srcA->type=srcAType+" "+srcA->name;
srcA->name.resize(0);
- return;
+ goto done;
}
else if (!dstA->name.isEmpty() && !srcA->type.isEmpty() &&
(dstAType+" "+dstA->name)==srcAType)
{
dstA->type=dstAType+" "+dstA->name;
dstA->name.resize(0);
- return;
+ goto done;
}
//printf("srcA=%s::%s dstA=%s::%s\n",srcAType.data(),srcA->name.data(),
// dstAType.data(),dstA->name.data());
@@ -1465,7 +1605,7 @@ static void mergeArgument(Argument *srcA,Argument *dstA,
srcA->type=srcAType.left(startPos).stripWhiteSpace();
}
}
- return;
+ goto done;
}
//printf("match exactly\n");
if (srcA->name.isEmpty() && dstA->name.isEmpty())
@@ -1491,6 +1631,10 @@ static void mergeArgument(Argument *srcA,Argument *dstA,
{
dstA->name = srcA->name.copy();
}
+done:
+ //printf("merge argument result %s:%s <-> %s:%s\n",
+ // srcA->type.data(),srcA->name.data(),
+ // dstA->type.data(),dstA->name.data());
return;
}
@@ -1632,23 +1776,26 @@ void mergeArguments(ArgumentList *srcAl,ArgumentList *dstAl)
//printf("Defval changing `%s'->`%s'\n",dstA->defval.data(),srcA->defval.data());
dstA->defval=srcA->defval.copy();
}
- if (srcA->name.isEmpty() && !dstA->name.isEmpty())
+ if (srcA->type==dstA->type)
{
- //printf("type: `%s':=`%s'\n",srcA->type.data(),dstA->type.data());
- //printf("name: `%s':=`%s'\n",srcA->name.data(),dstA->name.data());
- srcA->type = dstA->type.copy();
- srcA->name = dstA->name.copy();
- }
- else if (!srcA->name.isEmpty() && dstA->name.isEmpty())
- {
- //printf("type: `%s':=`%s'\n",dstA->type.data(),srcA->type.data());
- //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
- dstA->type = srcA->type.copy();
- dstA->name = dstA->name.copy();
- }
- else if (!srcA->name.isEmpty() && !dstA->name.isEmpty())
- {
- srcA->name = dstA->name.copy();
+ if (srcA->name.isEmpty() && !dstA->name.isEmpty())
+ {
+ //printf("type: `%s':=`%s'\n",srcA->type.data(),dstA->type.data());
+ //printf("name: `%s':=`%s'\n",srcA->name.data(),dstA->name.data());
+ srcA->type = dstA->type.copy();
+ srcA->name = dstA->name.copy();
+ }
+ else if (!srcA->name.isEmpty() && dstA->name.isEmpty())
+ {
+ //printf("type: `%s':=`%s'\n",dstA->type.data(),srcA->type.data());
+ //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
+ dstA->type = srcA->type.copy();
+ dstA->name = dstA->name.copy();
+ }
+ else if (!srcA->name.isEmpty() && !dstA->name.isEmpty())
+ {
+ srcA->name = dstA->name.copy();
+ }
}
int i1=srcA->type.find("::"),
i2=dstA->type.find("::"),
@@ -1766,7 +1913,7 @@ bool getDefs(const QCString &scName,const QCString &memberName,
//printf("Trying class scope %s\n",className.data());
ClassDef *fcd=0;
- if ((fcd=getResolvedClass(className)) && // is it a documented class
+ if ((fcd=getResolvedClass(Doxygen::globalScope,className)) && // is it a documented class
fcd->isLinkable()
)
{
@@ -2002,7 +2149,7 @@ bool getDefs(const QCString &scName,const QCString &memberName,
bmd = 0;
break;
}
- if (!(md->isStatic())) bmd = md;
+ if (!(md->isStatic()) || Config_getBool("EXTRACT_STATIC")) bmd = md;
}
if (bmd) md=bmd;
}
@@ -2195,7 +2342,7 @@ bool generateRef(OutputDocInterface &od,const char *scName,
if (getDefs(scopeStr,nameStr,argsStr,md,cd,fd,nd,gd,
scopePos==0 && !memberScopeFirst))
{
- //printf("after getDefs nd=%p\n",nd);
+ //printf("after getDefs md=%p cd=%p fd=%p nd=%p gd=%p\n",md,cd,fd,nd,gd);
QCString anchor;
if (md->isLinkable()) anchor = md->anchor();
QCString cName,aName;