diff options
Diffstat (limited to 'src')
39 files changed, 1712 insertions, 442 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp index f2c733b..f7c0550 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -33,7 +33,8 @@ #include "example.h" #include "outputlist.h" #include "dot.h" -//#include "xml.h" +#include "defargs.h" +#include "debug.h" static QCString stripExtension(const char *fName) { @@ -98,8 +99,10 @@ ClassDef::ClassDef( } m_subGrouping=TRUE; m_isTemplBaseClass=-1; - m_templateMapping = new StringDict; - m_templateMapping->setAutoDelete(TRUE); + m_templateInstances = 0; + m_templateMaster =0; + m_templBaseClassNames = 0; + m_artificial = FALSE; } // destroy the class definition @@ -115,19 +118,26 @@ ClassDef::~ClassDef() delete m_memberGroupList; delete m_memberGroupDict; delete m_innerClasses; - delete m_templateMapping; + delete m_templateInstances; + delete m_templBaseClassNames; } QCString ClassDef::displayName() const { + QCString n; if (Config_getBool("HIDE_SCOPE_NAMES")) { - return stripScope(name()); + n=stripScope(name()); } else { - return name(); + n=name(); } + if (m_tempArgs) + { + n+=tempArgListToString(m_tempArgs); + } + return n; } // inserts a base class in the inheritance list @@ -527,6 +537,15 @@ void ClassDef::distributeMemberGroupDocumentation() void ClassDef::insertUsedFile(const char *f) { if (m_files.find(f)==-1) m_files.append(f); + if (m_templateInstances) + { + QDictIterator<ClassDef> qdi(*m_templateInstances); + ClassDef *cd; + for (qdi.toFirst();(cd=qdi.current());++qdi) + { + cd->insertUsedFile(f); + } + } } static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) @@ -566,6 +585,7 @@ void ClassDef::setIncludeFile(FileDef *fd,const char *includeName,bool local) } } +// TODO: fix this: a nested template class can have multiple outer templates ArgumentList *ClassDef::outerTemplateArguments() const { int ti; @@ -700,6 +720,15 @@ void ClassDef::writeDocumentation(OutputList &ol) Doxygen::tagFile << "\">" << endl; Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << ".html</filename>" << endl; + if (m_tempArgs) + { + ArgumentListIterator ali(*m_tempArgs); + Argument *a; + for (;(a=ali.current());++ali) + { + Doxygen::tagFile << " <templarg>" << convertToXML(a->name) << "</templarg>" << endl; + } + } } @@ -1145,15 +1174,16 @@ void ClassDef::writeMemberList(OutputList &ol) ClassDef *cd=md->getClassDef(); // compute the protection level for this member - Protection prot=md->protection(); - if (mi->prot==Protected) // inherited protection: Protected - { - if (prot==Public) prot=Protected; - } - else if (mi->prot==Private) // inherited protection: Private - { - prot=Private; - } + //Protection prot=md->protection(); + //if (mi->prot==Protected) // inherited protection: Protected + //{ + // if (prot==Public) prot=Protected; + //} + //else if (mi->prot==Private) // inherited protection: Private + //{ + // prot=Private; + //} + Protection prot = mi->prot; //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n", // name().data(),md->name().data(),cd->name().data(),md->protection(),mi->prot,prot,mi->inherited); @@ -1166,13 +1196,15 @@ void ClassDef::writeMemberList(OutputList &ol) rmd = rmd->reimplements(); } - if (cd && !md->name().isEmpty() && md->name()[0]!='@' && - ( - md->isFriend() || - (/*mi->prot!=Private &&*/ - (prot!=Private || Config_getBool("EXTRACT_PRIVATE")) - ) - ) + if (cd && !md->name().isEmpty() && md->name()[0]!='@' + // && + //( + // md->isFriend() + // || + //(/*mi->prot!=Private &&*/ + // (prot!=Private || Config_getBool("EXTRACT_PRIVATE")) + //) + //) ) { bool memberWritten=FALSE; @@ -1416,7 +1448,7 @@ void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup) } /*! a link to this class is possible within this project */ -bool ClassDef::isLinkableInProject() +bool ClassDef::isLinkableInProject() const { return !name().isEmpty() && /* no name */ m_isTemplBaseClass==-1 && /* template base class */ @@ -1432,8 +1464,10 @@ bool ClassDef::isVisibleInHierarchy() (Config_getBool("ALLEXTERNALS") || hasNonReferenceSuperClass()) && // and not an annonymous compound name().find('@')==-1 && + // not an artifically introduced class + !m_artificial && // and not an inherited template argument - m_isTemplBaseClass==-1 && + //m_isTemplBaseClass==-1 && // and not privately inherited (m_prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && // documented or show anyway or documentation is external @@ -1642,6 +1676,7 @@ void ClassDef::mergeMembers() Specifier virt=mi->virt; if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + //printf("Adding!\n"); MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE); newMi->scopePath=bClass->name()+"::"+mi->scopePath; newMi->ambigClass=mi->ambigClass; @@ -1660,6 +1695,22 @@ void ClassDef::mergeMembers() //---------------------------------------------------------------------------- +void ClassDef::addUsedClass(ClassDef *cd,const char *accessName) +{ + if (m_usesImplClassDict==0) m_usesImplClassDict = new UsesClassDict(17); + UsesClassDef *ucd=m_usesImplClassDict->find(cd->name()); + if (ucd==0 /*|| ucd->templSpecifiers!=templSpec*/) + { + ucd = new UsesClassDef(cd); + m_usesImplClassDict->insert(cd->name(),ucd); + //ucd->templSpecifiers = templSpec; + //printf("Adding used class %s to class %s\n", + // cd->name().data(),name().data()); + } + ucd->addAccessor(accessName); +} + +#if 0 /*! Builds up a dictionary of all classes that are used by the state of this * class (the "implementation"). * Must be called before mergeMembers() is called! @@ -1772,7 +1823,6 @@ void ClassDef::determineImplUsageRelation() //---------------------------------------------------------------------------- -#if 0 // I have disabled this code because the graphs it renders quickly become // too large to be of practical use. @@ -1873,6 +1923,22 @@ QCString ClassDef::compoundTypeString() const QCString ClassDef::getOutputFileBase() const { + if (m_templateMaster) + { + return m_templateMaster->getOutputFileBase(); + } + else if (isReference()) + { + return m_fileName; + } + else + { + return convertNameToFile(m_fileName); + } +} + +QCString ClassDef::getInstanceOutputFileBase() const +{ if (isReference()) { return m_fileName; @@ -1885,12 +1951,26 @@ QCString ClassDef::getOutputFileBase() const QCString ClassDef::getFileBase() const { - return m_fileName; + if (m_templateMaster) + { + return m_templateMaster->getFileBase(); + } + else + { + return m_fileName; + } } QCString ClassDef::getSourceFileBase() const { - return convertNameToFile(m_fileName+"-source"); + if (m_templateMaster) + { + return m_templateMaster->getSourceFileBase(); + } + else + { + return convertNameToFile(m_fileName+"-source"); + } } void ClassDef::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) @@ -1925,44 +2005,147 @@ Definition *ClassDef::findInnerCompound(const char *name) return m_innerClasses->find(name); } -void ClassDef::initTemplateMapping() +//void ClassDef::initTemplateMapping() +//{ +// m_templateMapping->clear(); +// ArgumentList *al = templateArguments(); +// if (al) +// { +// ArgumentListIterator ali(*al); +// Argument *arg; +// for (ali.toFirst();(arg=ali.current());++ali) +// { +// setTemplateArgumentMapping(arg->name,arg->defval); +// } +// } +//} +//void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual) +//{ +// //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual); +// if (m_templateMapping && formal) +// { +// if (m_templateMapping->find(formal)) +// { +// m_templateMapping->remove(formal); +// } +// m_templateMapping->insert(formal,new QCString(actual)); +// } +//} +// +//QCString ClassDef::getTemplateArgumentMapping(const char *formal) const +//{ +// if (m_templateMapping && formal) +// { +// QCString *s = m_templateMapping->find(formal); +// if (s) +// { +// return *s; +// } +// } +// return ""; +//} + +ClassDef *ClassDef::insertTemplateInstance(const QCString &fileName, + int startLine, const QCString &templSpec,bool &freshInstance) +{ + freshInstance = FALSE; + if (m_templateInstances==0) + { + m_templateInstances = new QDict<ClassDef>(17); + } + ClassDef *templateClass=m_templateInstances->find(templSpec); + if (templateClass==0) + { + Debug::print(Debug::Classes,0," New template instance class %s%s\n",name().data(),templSpec.data()); + templateClass = new ClassDef( + fileName,startLine,name()+templSpec,ClassDef::Class); + //templateClass->setBriefDescription(briefDescription()); + //templateClass->setDocumentation(documentation()); + templateClass->setTemplateMaster(this); + m_templateInstances->insert(templSpec,templateClass); + freshInstance=TRUE; + } + return templateClass; +} + +void ClassDef::setTemplateBaseClassNames(QDict<int> *templateNames) { - m_templateMapping->clear(); - ArgumentList *al = templateArguments(); - if (al) + if (templateNames==0) return; + if (m_templBaseClassNames==0) + { + m_templBaseClassNames = new QDict<int>(17); + m_templBaseClassNames->setAutoDelete(TRUE); + } + // make a deep copy of the dictionary. + QDictIterator<int> qdi(*templateNames); + for (;qdi.current();++qdi) { - ArgumentListIterator ali(*al); - Argument *arg; - for (ali.toFirst();(arg=ali.current());++ali) + if (m_templBaseClassNames->find(qdi.currentKey())==0) { - setTemplateArgumentMapping(arg->name,arg->defval); + m_templBaseClassNames->insert(qdi.currentKey(),new int(*qdi.current())); } } } -void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual) +QDict<int> *ClassDef::getTemplateBaseClassNames() const +{ + return m_templBaseClassNames; +} + +void ClassDef::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec) { - //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual); - if (m_templateMapping && formal) + //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec); + MemberNameInfoSDict::Iterator mnili(*cd->m_allMemberNameInfoSDict); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) { - if (m_templateMapping->find(formal)) + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) { - m_templateMapping->remove(formal); + ArgumentList *actualArguments = new ArgumentList; + stringToArgumentList(templSpec,actualArguments); + MemberDef *md = mi->memberDef; + MemberDef *imd = md->createTemplateInstanceMember( + cd->templateArguments(),actualArguments); + delete actualArguments; + //printf("%s->setMemberClass(%p)\n",imd->name().data(),this); + imd->setMemberClass(this); + imd->setTemplateMaster(md); + //imd->setDocumentation(md->documentation()); + //imd->setBriefDescription(md->briefDescription()); + imd->setMemberSpecifiers(md->getMemberSpecifiers()); + insertMember(imd); + //printf("Adding member=%s%s to class %s\n",imd->name().data(),imd->argsString(),imd->getClassDef()->name().data()); + // insert imd in the list of all members + //printf("Adding member=%s class=%s\n",imd->name().data(),name().data()); +#if 0 + MemberName *mn; + if ((mn=Doxygen::memberNameDict[imd->name()])) + { + mn->append(md); + } + else + { + mn = new MemberName(imd->name()); + mn->append(md); + Doxygen::memberNameDict.insert(imd->name(),mn); + Doxygen::memberNameList.append(mn); + } +#endif } - m_templateMapping->insert(formal,new QCString(actual)); } } -QCString ClassDef::getTemplateArgumentMapping(const char *formal) const +QCString ClassDef::getReference() const { - if (m_templateMapping && formal) + if (m_templateMaster) { - QCString *s = m_templateMapping->find(formal); - if (s) - { - return *s; - } + return m_templateMaster->getReference(); + } + else + { + return Definition::getReference(); } - return ""; } diff --git a/src/classdef.h b/src/classdef.h index b39b87d..323b7bd 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -26,6 +26,7 @@ #include "entry.h" #include "memberlist.h" #include "definition.h" +#include "sortdict.h" class MemberDict; class ClassList; @@ -67,8 +68,10 @@ class ClassDef : public Definition }; DefType definitionType() { return TypeClass; } QCString getOutputFileBase() const; + QCString getInstanceOutputFileBase() const; QCString getFileBase() const; QCString getSourceFileBase() const; + QCString getReference() const; bool hasDocumentation() const; @@ -106,12 +109,12 @@ class ClassDef : public Definition /*! returns TRUE iff a link is possible to an item within this project. */ - bool isLinkableInProject(); + bool isLinkableInProject() const; /*! return TRUE iff a link to this class is possible (either within * this project, or as a cross-reference to another project). */ - bool isLinkable() + bool isLinkable() const { return isLinkableInProject() || isReference(); } @@ -156,6 +159,15 @@ class ClassDef : public Definition */ int isTemplateBaseClass() const { return m_isTemplBaseClass; } + /*! Returns a sorted dictionary with all template instances found for + * this template class. Returns 0 if not a template or no instances. + */ + QDict<ClassDef> *getTemplateInstances() const { return m_templateInstances; } + /*! Returns the template master of which this class is an instance. + * Returns 0 if not applicable. + */ + ClassDef *templateMaster() const { return m_templateMaster; } + UsesClassDict *usedImplementationClasses() const { return m_usesImplClassDict; @@ -166,8 +178,13 @@ class ClassDef : public Definition return m_usesIntfClassDict; } + /*! Returns the definition of a nested compound if + * available, or 0 otherwise. + * @param name The name of the nested compound + */ virtual Definition *findInnerCompound(const char *name); + /* member lists by protection */ MemberList pubMembers; MemberList proMembers; @@ -224,16 +241,24 @@ class ClassDef : public Definition void setTemplateArguments(ArgumentList *al); void mergeMembers(); void setFileDef(FileDef *fd) { m_fileDef=fd; } - void determineImplUsageRelation(); - void determineIntfUsageRelation(); + //void determineImplUsageRelation(); + //void determineIntfUsageRelation(); void setSubGrouping(bool enabled) { m_subGrouping = enabled; } void setProtection(Protection p) { m_prot=p; } void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs); void addInnerCompound(Definition *d); void setIsTemplateBaseClass(int num) { m_isTemplBaseClass = num; } - void initTemplateMapping(); - void setTemplateArgumentMapping(const char *formal,const char *actual); - QCString getTemplateArgumentMapping(const char *formal) const; + void addUsedClass(ClassDef *cd,const char *accessName); + //void initTemplateMapping(); + //void setTemplateArgumentMapping(const char *formal,const char *actual); + //QCString getTemplateArgumentMapping(const char *formal) const; + ClassDef *insertTemplateInstance(const QCString &fileName,int startLine, + const QCString &templSpec,bool &freshInstance); + void setTemplateBaseClassNames(QDict<int> *templateNames); + QDict<int> *getTemplateBaseClassNames() const; + void setTemplateMaster(ClassDef *tm) { m_templateMaster=tm; } + void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec); + void setClassIsArtificial() { m_artificial = TRUE; } /*! Creates a new compound definition. * \param outerScope class, file or namespace in which this class is @@ -351,11 +376,22 @@ class ClassDef : public Definition */ int m_isTemplBaseClass; - /*! A mapping used by template classes, which maps formal - * template arguments to their actual instantiations. - * This is used while generating inheritance graphs. + /*! Template instances that exists of this class, the key in the + * dictionary is the template argument list. + */ + QDict<ClassDef> *m_templateInstances; + + QDict<int> *m_templBaseClassNames; + + /*! The class this class is an instance of. */ + ClassDef *m_templateMaster; + + /*! Indicated whether this class exists because it is used by + * some other class only (TRUE) or if some class inherits from + * it (FALSE). This is need to remove used-only classes from + * the inheritance tree. */ - StringDict *m_templateMapping; + bool m_artificial; }; /*! \brief Class that contains information about a usage relation. @@ -21,7 +21,7 @@ * includes */ #include <stdio.h> -#include <iostream.h> +//#include <iostream.h> #include <assert.h> #include <ctype.h> #include <qregexp.h> diff --git a/src/config.h b/src/config.h index 8874cff..02a3389 100644 --- a/src/config.h +++ b/src/config.h @@ -290,7 +290,7 @@ class ConfigBool : public ConfigOption t << endl; } t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "= "; - if (upd) + if (upd && !m_valueString.isEmpty()) { writeStringValue(t,m_valueString); } diff --git a/src/config.l b/src/config.l index dd704b0..9ffdf55 100644 --- a/src/config.l +++ b/src/config.l @@ -19,7 +19,7 @@ */ #include <stdio.h> #include <stdlib.h> -#include <iostream.h> +//#include <iostream.h> #include <assert.h> #include <ctype.h> diff --git a/src/constexp.h b/src/constexp.h index 2b09ed9..6f230f9 100644 --- a/src/constexp.h +++ b/src/constexp.h @@ -22,10 +22,12 @@ #include "qtbc.h" #include "cppvalue.h" -extern bool parseCppExpression(const QCString &s); +extern bool parseCppExpression(const char *fileName,int line,const QCString &s); extern int cppExpYYparse(); extern int cppExpYYdebug; -extern QCString strToken; -extern CPPValue resultValue; +extern QCString g_strToken; +extern CPPValue g_resultValue; +extern QCString g_constExpFileName; +extern int g_constExpLineNr; #endif diff --git a/src/constexp.l b/src/constexp.l index b6604ff..92b3da4 100644 --- a/src/constexp.l +++ b/src/constexp.l @@ -25,11 +25,13 @@ #define YY_NO_UNPUT #define YY_NEVER_INTERACTIVE 1 -QCString strToken; +QCString g_strToken; +CPPValue g_resultValue; +int g_constExpLineNr; +QCString g_constExpFileName; -static const char *inputString; -static int inputPosition; -CPPValue resultValue; +static const char *g_inputString; +static int g_inputPosition; #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); @@ -37,9 +39,9 @@ CPPValue resultValue; static int yyread(char *buf,int max_size) { int c=0; - while( c < max_size && inputString[inputPosition] ) + while( c < max_size && g_inputString[g_inputPosition] ) { - *buf = inputString[inputPosition++] ; + *buf = g_inputString[g_inputPosition++] ; c++; buf++; } return c; @@ -74,36 +76,38 @@ static int yyread(char *buf,int max_size) "(" { return TOK_LPAREN; } ")" { return TOK_RPAREN; } "'"(([^\'\n\r\\]+)|(\\(([ntvbrfa\\?'\"])|([0-9]+)|([xX][0-9a-fA-F]+))))"'" { - strToken=yytext; + g_strToken=yytext; return TOK_CHARACTER; } -0[0-7]*[uUlL]* { strToken=yytext; +0[0-7]*[uUlL]* { g_strToken=yytext; return TOK_OCTALINT; } -[1-9][0-9]*[uUlL]* { strToken=yytext; +[1-9][0-9]*[uUlL]* { g_strToken=yytext; return TOK_DECIMALINT; } -(0x|0X)[0-9a-fA-F]+[uUlL]* { strToken=yytext; return TOK_HEXADECIMALINT; } +(0x|0X)[0-9a-fA-F]+[uUlL]* { g_strToken=yytext; return TOK_HEXADECIMALINT; } (([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+))([eE]([\-\+])?[0-9]+)?([fFlL])? { - strToken=yytext; return TOK_FLOAT; + g_strToken=yytext; return TOK_FLOAT; } ([0-9]+[eE])([\-\+])?[0-9]+([fFlL])? { - strToken=yytext; return TOK_FLOAT; + g_strToken=yytext; return TOK_FLOAT; } . \n %% -bool parseCppExpression(const QCString &s) +bool parseCppExpression(const char *fileName,int lineNr,const QCString &s) { //printf("Expression: `%s'\n",s.data()); - inputString = s; - inputPosition = 0; + g_constExpFileName = fileName; + g_constExpLineNr = lineNr; + g_inputString = s; + g_inputPosition = 0; cppExpYYrestart( cppExpYYin ); cppExpYYparse(); //printf("Result: %ld\n",(long)resultValue); - return (long)resultValue!=0; + return (long)g_resultValue!=0; } extern "C" { diff --git a/src/constexp.y b/src/constexp.y index f5565bc..9063c52 100644 --- a/src/constexp.y +++ b/src/constexp.y @@ -20,6 +20,7 @@ #include "cppvalue.h" #include "constexp.h" +#include "message.h" #if defined(_MSC_VER) #define MSDOS @@ -32,7 +33,8 @@ int cppExpYYerror(const char *s) { - printf("Error in constant expression evaluation: %s\n",s); + warn(g_constExpFileName,g_constExpLineNr, + "Problem during constant expression evaluation: %s",s); return 0; } @@ -73,7 +75,7 @@ int cppExpYYlex(); %% start: constant_expression - { resultValue = $1; return 0; } + { g_resultValue = $1; return 0; } ; constant_expression: logical_or_expression diff --git a/src/cppvalue.cpp b/src/cppvalue.cpp index 62d73dd..be1018a 100644 --- a/src/cppvalue.cpp +++ b/src/cppvalue.cpp @@ -24,7 +24,7 @@ CPPValue parseOctal() { long val = 0; - for (const char *p = strToken.data(); *p != 0; p++) + for (const char *p = g_strToken.data(); *p != 0; p++) { if (*p >= '0' && *p <= '7') val = val * 8 + *p - '0'; } @@ -34,7 +34,7 @@ CPPValue parseOctal() CPPValue parseDecimal() { long val = 0; - for (const char *p = strToken.data(); *p != 0; p++) + for (const char *p = g_strToken.data(); *p != 0; p++) { if (*p >= '0' && *p <= '9') val = val * 10 + *p - '0'; } @@ -44,7 +44,7 @@ CPPValue parseDecimal() CPPValue parseHexadecimal() { long val = 0; - for (const char *p = strToken.data(); *p != 0; p++) + for (const char *p = g_strToken.data(); *p != 0; p++) { if (*p >= '0' && *p <= '9') val = val * 16 + *p - '0'; else if (*p >= 'a' && *p <= 'f') val = val * 16 + *p - 'a' + 10; @@ -55,9 +55,9 @@ CPPValue parseHexadecimal() CPPValue parseCharacter() // does not work for '\n' and the alike { - if (strToken[1]=='\\') + if (g_strToken[1]=='\\') { - switch(strToken[2]) + switch(g_strToken[2]) { case 'n': return CPPValue((long)'\n'); case 't': return CPPValue((long)'\t'); @@ -73,14 +73,14 @@ CPPValue parseCharacter() // does not work for '\n' and the alike case '0': return parseOctal(); case 'x': case 'X': return parseHexadecimal(); - default: printf("Invalid escape sequence %s found!\n",strToken.data()); + default: printf("Invalid escape sequence %s found!\n",g_strToken.data()); return CPPValue(0L); } } - return CPPValue((long)strToken[1]); + return CPPValue((long)g_strToken[1]); } CPPValue parseFloat() { - return CPPValue(atof(strToken)); + return CPPValue(atof(g_strToken)); } diff --git a/src/cppvalue.h b/src/cppvalue.h index 159e217..def31c9 100644 --- a/src/cppvalue.h +++ b/src/cppvalue.h @@ -24,13 +24,9 @@ class CPPValue { - friend CPPValue parseOctal(); - friend CPPValue parseDecimal(); - friend CPPValue parseHexadecimal(); - friend CPPValue parseCharacter(); - friend CPPValue parseFloat(); - public: + + enum Type { Int, Float }; CPPValue(long val=0) : type(Int) { v.l = val; } @@ -57,4 +53,10 @@ class CPPValue } v; }; +extern CPPValue parseOctal(); +extern CPPValue parseDecimal(); +extern CPPValue parseHexadecimal(); +extern CPPValue parseCharacter(); +extern CPPValue parseFloat(); + #endif diff --git a/src/declinfo.l b/src/declinfo.l index 6a689c0..18e39d8 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -21,7 +21,7 @@ * includes */ #include <stdio.h> -#include <iostream.h> +//#include <iostream.h> #include <assert.h> #include <ctype.h> diff --git a/src/defargs.l b/src/defargs.l index 68eaa91..ebdb6ad 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -47,7 +47,7 @@ */ #include "qtbc.h" #include <stdio.h> -#include <iostream.h> +//#include <iostream.h> #include <assert.h> #include <ctype.h> #include <qregexp.h> diff --git a/src/definition.cpp b/src/definition.cpp index 87f5855..f17d980 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -452,7 +452,11 @@ void Definition::addInnerCompound(Definition *) QCString Definition::qualifiedName() const { //printf("start Definition::qualifiedName()\n"); - if (m_outerScope==0) return m_localName; // TODO: remove this check + if (m_outerScope==0) + { + if (m_localName=="<globalScope>") return ""; + else return m_localName; + } QCString qualifiedName; if (m_outerScope->name()=="<globalScope>") diff --git a/src/definition.h b/src/definition.h index 6136cc6..e881e43 100644 --- a/src/definition.h +++ b/src/definition.h @@ -76,12 +76,12 @@ class Definition void setBriefDescription(const char *b); /*! Returns TRUE iff the definition is documented */ virtual bool hasDocumentation() const; - virtual bool isLinkableInProject() = 0; - virtual bool isLinkable() = 0; + virtual bool isLinkableInProject() const = 0; + virtual bool isLinkable() const = 0; + virtual QCString getReference() const { return m_ref; } bool isReference() const { return !m_ref.isEmpty(); } void setReference(const char *r) { m_ref=r; } - QCString getReference() const { return m_ref; } /*! Add the list of anchors that mark the sections that are found in the * documentation. @@ -22,7 +22,7 @@ */ #include <stdio.h> #include <stdlib.h> -#include <iostream.h> +//#include <iostream.h> #include <assert.h> #include <ctype.h> @@ -828,7 +828,7 @@ ID [a-z_A-Z][a-z_A-Z0-9]* SCOPENAME (({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID}) SCOPEMASK {ID}?(("::"|"#")?(~)?{ID})+ URLMASK [a-z_A-Z0-9\~\:\?\@\&\%\#\.\-\+\/\=]+ -NONTERM [\{\}\[\]\`\~\@\|\-\+\#\$\/\\\!\%\^\&\*()a-z_A-Z<>0-9] +NONTERM [\{\}\[\]\`\~\@\|\-\+\#\$\/\\\!\%\^\&\*()a-z_A-Z<>0-9\x80-\xff] WORD ({NONTERM}+([^\n\t ]*{NONTERM}+)?)|("\""[^\n\"]"\"") ATTR ({B}+[^>\n]*)? A [aA] diff --git a/src/dot.cpp b/src/dot.cpp index f7be7d5..20666e6 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -176,6 +176,7 @@ static bool isLeaf(ClassDef *cd) return TRUE; } +#if 0 /*! Builds a mapping from formal arguments of class \a tcd to the * actual arguments stored in templSpec. To properly initialize * the mapping with the default template values @@ -320,6 +321,7 @@ static void computeTemplateInstance( actualArg.resize(0); result = 0; } +#endif //-------------------------------------------------------------------- @@ -693,20 +695,24 @@ void DotGfxHierarchyTable::writeGraph(QTextStream &out,const char *path) QListIterator<DotNode> dnli(*m_rootSubgraphs); DotNode *n; + int count=0; for (dnli.toFirst();(n=dnli.current());++dnli) { - QCString baseName="inherit_graph_"; - QCString diskName=n->m_url.copy(); - int i=diskName.find('$'); - if (i!=-1) - { - diskName=diskName.right(diskName.length()-i-1); - } - else /* take the label name as the file name (and strip any template stuff) */ - { - diskName=n->m_label; - } - baseName = convertNameToFile(baseName+diskName); + QCString baseName; + baseName.sprintf("inherit_graph_%d",count++); + //="inherit_graph_"; + //QCString diskName=n->m_url.copy(); + //int i=diskName.find('$'); + //if (i!=-1) + //{ + // diskName=diskName.right(diskName.length()-i-1); + //} + //else /* take the label name as the file name (and strip any template stuff) */ + //{ + // diskName=n->m_label; + //} + //baseName = convertNameToFile(baseName+diskName); + baseName = convertNameToFile(baseName); QCString dotName=baseName+".dot"; QCString gifName=baseName+".gif"; QCString mapName=baseName+".map"; @@ -817,18 +823,9 @@ void DotGfxHierarchyTable::addHierarchy(DotNode *n,ClassDef *cd,bool hideSuper) } } -DotGfxHierarchyTable::DotGfxHierarchyTable() +void DotGfxHierarchyTable::addClassList(ClassSDict *cl) { - m_curNodeNumber=0; - m_rootNodes = new QList<DotNode>; - //m_rootNodes->setAutoDelete(TRUE); // rootNodes owns the nodes - m_usedNodes = new QDict<DotNode>(1009); // virtualNodes only aliases nodes - m_rootSubgraphs = new DotNodeList; - - // build a graph with each class as a node and the inheritance relations - // as edges - initClassHierarchy(&Doxygen::classSDict); - ClassSDict::Iterator cli(Doxygen::classSDict); + ClassSDict::Iterator cli(*cl); ClassDef *cd; for (cli.toLast();(cd=cli.current());--cli) { @@ -857,6 +854,22 @@ DotGfxHierarchyTable::DotGfxHierarchyTable() } } } +} + +DotGfxHierarchyTable::DotGfxHierarchyTable() +{ + m_curNodeNumber=0; + m_rootNodes = new QList<DotNode>; + //m_rootNodes->setAutoDelete(TRUE); // rootNodes owns the nodes + m_usedNodes = new QDict<DotNode>(1009); // virtualNodes only aliases nodes + m_rootSubgraphs = new DotNodeList; + + // build a graph with each class as a node and the inheritance relations + // as edges + initClassHierarchy(&Doxygen::classSDict); + initClassHierarchy(&Doxygen::hiddenClasses); + addClassList(&Doxygen::classSDict); + addClassList(&Doxygen::hiddenClasses); // m_usedNodes now contains all nodes in the graph // color the graph into a set of independent subgraphs @@ -918,8 +931,6 @@ int DotClassGraph::m_curNodeNumber; void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, const char *label,int distance,const char *usedName,const char *templSpec,bool base) { - //printf("DoxClassGraph::addClass(class=%s,parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n", - // cd->name().data(),n->m_label.data(),prot,label,distance,usedName,templSpec,base); int edgeStyle = label ? EdgeInfo::Dashed : EdgeInfo::Solid; QCString className; if (usedName) // name is a typedef @@ -932,8 +943,10 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, } else // just a normal name { - className=cd->name(); + className=cd->displayName(); } + //printf("DotClassGraph::addClass(class=`%s',parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n", + // className.data(),n->m_label.data(),prot,label,distance,usedName,templSpec,base); DotNode *bn = m_usedNodes->find(className); if (bn) // class already inserted { @@ -955,7 +968,10 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, QCString displayName=className; if (Config_getBool("HIDE_SCOPE_NAMES")) displayName=stripScope(displayName); QCString tmp_url; - if (cd->isLinkable()) tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); + if (cd->isLinkable()) + { + tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); + } bn = new DotNode(m_curNodeNumber++, displayName, tmp_url.data(), @@ -973,7 +989,7 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, n->addParent(bn); } m_usedNodes->insert(className,bn); - //printf(" add used node %s of %s\n",cd->name().data(),n->m_label.data()); + //printf(" add new child node `%s' to %s\n",className.data(),n->m_label.data()); if (distance<m_recDepth) buildGraph(cd,bn,distance+1,base); } } @@ -986,23 +1002,25 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,int distance,bool base) { //printf("-------- inheritance relation %s->%s templ=`%s'\n", // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); - QCString templSpec; - if (base) templSpec = substituteTemplateSpec( - cd,bcd->templSpecifiers); - ClassDef *acd=0; - QCString actualArg; - computeTemplateInstance(cd,bcd->classDef,templSpec,acd,actualArg); + //QCString templSpec; + //if (base) templSpec = substituteTemplateSpec( + // cd,bcd->templSpecifiers); + //ClassDef *acd=0; + //QCString actualArg; + //computeTemplateInstance(cd,bcd->classDef,templSpec,acd,actualArg); //printf("acd=%p actualArg=%s\n",acd,actualArg.data()); - if (acd) - { - addClass(acd,n,bcd->prot,0,distance,actualArg, - templSpec,base); - } - else - { - addClass(bcd->classDef,n,bcd->prot,0,distance,bcd->usedName, - templSpec,base); - } + //if (acd) + //{ + // addClass(acd,n,bcd->prot,0,distance,actualArg, + // templSpec,base); + //} + //else + //{ + // addClass(bcd->classDef,n,bcd->prot,0,distance,bcd->usedName, + // templSpec,base); + //} + addClass(bcd->classDef,n,bcd->prot,0,distance,bcd->usedName, + bcd->templSpecifiers,base); } if (m_graphType != Inheritance) { @@ -1031,25 +1049,27 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,int distance,bool base) label+=QCString("\\n")+s; } } - QCString actualArg; - ClassDef *acd=0; + //QCString actualArg; + //ClassDef *acd=0; //printf("-------- usage relation %s->%s templ=`%s'\n", // cd->name().data(),ucd->classDef->name().data(), // ucd->templSpecifiers.data()); - QCString templSpec = substituteTemplateSpec( - cd,ucd->templSpecifiers); - computeTemplateInstance(cd,ucd->classDef, templSpec, acd,actualArg); - if (acd) - { - addClass(acd,n,EdgeInfo::Black,label,distance,actualArg, - templSpec,base); - } - else - { - //printf("Found label=`%s'\n",label.data()); - addClass(ucd->classDef,n,EdgeInfo::Black,label,distance,0, - templSpec,base); - } + //QCString templSpec = substituteTemplateSpec( + // cd,ucd->templSpecifiers); + //computeTemplateInstance(cd,ucd->classDef, templSpec, acd,actualArg); + //if (acd) + //{ + // addClass(acd,n,EdgeInfo::Black,label,distance,actualArg, + // templSpec,base); + //} + //else + //{ + // //printf("Found label=`%s'\n",label.data()); + // addClass(ucd->classDef,n,EdgeInfo::Black,label,distance,0, + // templSpec,base); + //} + addClass(ucd->classDef,n,EdgeInfo::Black,label,distance,0, + ucd->templSpecifiers,base); } } } @@ -1057,17 +1077,17 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,int distance,bool base) DotClassGraph::DotClassGraph(ClassDef *cd,GraphType t,int maxRecursionDepth) { - //printf("DotGfxUsage::DotGfxUsage %s\n",cd->name().data()); + //printf("--------------- DotClassGraph::DotClassGraph `%s'\n",cd->displayName().data()); m_graphType = t; m_maxDistance = 0; m_recDepth = maxRecursionDepth; QCString tmp_url=""; if (cd->isLinkable()) tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); QCString className = cd->displayName(); - if (cd->templateArguments()) - { - className+=tempArgListToString(cd->templateArguments()); - } + //if (cd->templateArguments()) + //{ + // className+=tempArgListToString(cd->templateArguments()); + //} m_startNode = new DotNode(m_curNodeNumber++, className, tmp_url.data(), @@ -1075,11 +1095,11 @@ DotClassGraph::DotClassGraph(ClassDef *cd,GraphType t,int maxRecursionDepth) TRUE // is a root node ); m_usedNodes = new QDict<DotNode>(1009); - m_usedNodes->insert(cd->name(),m_startNode); + m_usedNodes->insert(className,m_startNode); - ClassSDict::Iterator cli(Doxygen::classSDict); - ClassDef *icd; - for (cli.toFirst();(icd=cli.current());++cli) icd->initTemplateMapping(); + //ClassSDict::Iterator cli(Doxygen::classSDict); + //ClassDef *icd; + //for (cli.toFirst();(icd=cli.current());++cli) icd->initTemplateMapping(); //printf("Root node %s\n",cd->name().data()); if (m_recDepth>0) @@ -24,6 +24,7 @@ class ClassDef; class FileDef; class QTextStream; class DotNodeList; +class ClassSDict; enum GraphOutputFormat { GIF , EPS }; @@ -105,6 +106,7 @@ class DotGfxHierarchyTable private: void addHierarchy(DotNode *n,ClassDef *cd,bool hide); + void addClassList(ClassSDict *cl); QList<DotNode> *m_rootNodes; QDict<DotNode> *m_usedNodes; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 8d786ad..c7a64eb 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -65,8 +65,10 @@ #define pclose _pclose #endif +static QDict<Entry> classEntries(1009); + ClassSDict Doxygen::classSDict(1009); -ClassList Doxygen::hiddenClasses; +ClassSDict Doxygen::hiddenClasses(257); NamespaceList Doxygen::namespaceList; // all namespaces NamespaceDict Doxygen::namespaceDict(257); @@ -209,7 +211,7 @@ static void addRelatedPage(const char *name,const QCString &ptitle, ) { PageInfo *pi=0; - if ((pi=Doxygen::pageSDict->find(name))) + if ((pi=Doxygen::pageSDict->find(name)) && !tagInfo) { // append documentation block to the page. pi->doc+="\n\n"+doc; @@ -392,7 +394,8 @@ static void addRefItem(int todoId,int testId,int bugId,const char *prefix, static void buildGroupList(Entry *root) { - if (root->section==Entry::GROUPDOC_SEC && !root->name.isEmpty()) + if (root->section==Entry::GROUPDOC_SEC && !root->name.isEmpty() && + (Config_getBool("EXTRACT_ALL") || root->tagInfo)) { //printf("Found group %s title=`%s'\n",root->name.data(),root->type.data()); @@ -883,7 +886,6 @@ static void buildClassList(Entry *root) cd->setBriefDescription(root->brief); cd->insertUsedFile(root->fileName); - // add class to the list //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data()); Doxygen::classSDict.inSort(fullName,cd); @@ -1336,6 +1338,7 @@ static MemberDef *addVariableToClass( bool ambig; md->setBodyDef(findFileDef(Doxygen::inputNameDict,root->fileName,ambig)); + //printf("Adding member=%s\n",md->name().data()); // add the member to the global list if (mn) { @@ -1510,6 +1513,7 @@ static MemberDef *addVariableToFile( } } + //printf("Adding member=%s\n",md->name().data()); // add member definition to the list of globals if (mn) { @@ -1911,6 +1915,7 @@ static void buildMemberList(Entry *root) ); // add member to the global list of all members + //printf("Adding member=%s class=%s\n",md->name().data(),cd->name().data()); MemberName *mn; if ((mn=Doxygen::memberNameDict[name])) { @@ -1920,7 +1925,6 @@ static void buildMemberList(Entry *root) { mn = new MemberName(name); mn->append(md); - //printf("Adding memberName=%s\n",mn->memberName()); Doxygen::memberNameDict.insert(name,mn); Doxygen::memberNameList.append(mn); } @@ -2109,6 +2113,7 @@ static void buildMemberList(Entry *root) } // add member to the list of file members + //printf("Adding member=%s\n",md->name().data()); MemberName *mn; if ((mn=Doxygen::functionNameDict[name])) { @@ -2343,15 +2348,332 @@ static void replaceNamespaceAliases(QCString &scope,int i) //printf("replaceNamespaceAliases() result=%s\n",scope.data()); } +static QCString resolveTypeDef(const QCString &name) +{ + QCString typeName; + if (!name.isEmpty()) + { + QCString *subst = Doxygen::typedefDict[name]; + if (subst) + { + int count=0; + typeName=*subst; + QCString *newSubst; + while ((newSubst=Doxygen::typedefDict[typeName]) && count<10) + { + if (typeName==*newSubst) break; // prevent lock-up + typeName=*newSubst; + count++; + } + } + } + return typeName; +} + +/*! make a dictionary of all template arguments of class cd + * that are part of the base class name. + * Example: A template class A with template arguments <R,S,T> + * that inherits from B<T,T,S> will have T and S in the dictionary. + */ +static QDict<int> *getTemplateArgumentsInName(ArgumentList *templateArguments,const QCString &name) +{ + QDict<int> *templateNames = new QDict<int>(17); + templateNames->setAutoDelete(TRUE); + static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*"); + if (templateArguments) + { + ArgumentListIterator ali(*templateArguments); + Argument *arg; + int count=0; + for (ali.toFirst();(arg=ali.current());++ali,count++) + { + int i,p=0,l; + while ((i=re.match(name,p,&l))!=-1) + { + QCString n = name.mid(i,l); + if (n==arg->name) + { + if (templateNames->find(n)==0) + { + templateNames->insert(n,new int(count)); + } + } + p=i+l; + } + } + } + return templateNames; +} + + +enum FindBaseClassRelation_Mode +{ + TemplateInstances, + DocumentedOnly, + Undocumented +}; -static bool findBaseClassRelation( +static bool findClassRelation( Entry *root, ClassDef *cd, BaseInfo *bi, - int isTemplBaseClass, - bool insertUndocumented + QDict<int> *templateNames, + /*bool insertUndocumented*/ + FindBaseClassRelation_Mode mode, + bool isArtificial + ); + + +static void findUsedClassesForClass(Entry *root, + ClassDef *masterCd, + ClassDef *instanceCd, + bool isArtificial, + ArgumentList *actualArgs=0, + QDict<int> *templateNames=0 + ) +{ + //if (masterCd->visited) return; + masterCd->visited=TRUE; + ArgumentList *formalArgs = masterCd->templateArguments(); + MemberNameInfoSDict::Iterator mnili(*masterCd->memberNameInfoSDict()); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) + { + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + MemberDef *md=mi->memberDef; + if (md->isVariable()) // for each member variable in this class + { + QCString type=removeRedundantWhiteSpace(md->typeString()); + int pos=0; + QCString usedClassName; + QCString templSpec; + bool found=FALSE; + if (actualArgs) + { + type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs); + } + //printf("extractClassNameFromType(%s)\n",type.data()); + while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec)) + { + QCString typeName = resolveTypeDef(usedClassName); + QCString usedName = usedClassName+templSpec; + if (!typeName.isEmpty()) + { + usedName=typeName; + } + //printf("usedName=`%s'\n",usedName.data()); + + bool delTempNames=FALSE; + if (templateNames==0) + { + templateNames = getTemplateArgumentsInName(formalArgs,usedName); + delTempNames=TRUE; + } + BaseInfo bi(usedName,Public,Normal); + findClassRelation(root,instanceCd,&bi,templateNames,TemplateInstances,isArtificial); + + if (masterCd->templateArguments()) + { + ArgumentListIterator ali(*masterCd->templateArguments()); + Argument *arg; + int count=0; + for (ali.toFirst();(arg=ali.current());++ali,++count) + { + if (arg->name==usedName) // type is a template argument + { + found=TRUE; + Debug::print(Debug::Classes,0," New used class `%s'\n", usedName.data()); + + ClassDef *usedCd = Doxygen::hiddenClasses.find(usedName); + if (usedCd==0) + { + usedCd = new ClassDef( + masterCd->getDefFileName(),masterCd->getDefLine(), + usedName,ClassDef::Class); + usedCd->setIsTemplateBaseClass(count); + Doxygen::hiddenClasses.inSort(usedName,usedCd); + } + if (isArtificial) usedCd->setClassIsArtificial(); + instanceCd->addUsedClass(usedCd,md->name()); + + //if (m_usesImplClassDict==0) m_usesImplClassDict = new UsesClassDict(257); + //UsesClassDef *ucd = new UsesClassDef(cd); + //m_usesImplClassDict->insert(cd->name(),ucd); + //ucd->templSpecifiers = templSpec; + //ucd->addAccessor(md->name()); + } + } + } + + if (!found) + { + Definition *scope=masterCd->getOuterScope(); + ClassDef *usedCd=0; + do + { + QCString scopeName = scope ? scope->qualifiedName().data() : 0; + if (!scopeName.isEmpty()) + { + usedCd=getResolvedClass(scopeName+"::"+usedName,0,&templSpec); + if (usedCd==0) usedCd=getResolvedClass(scopeName+"::"+usedClassName,0,&templSpec); + //printf("Search for class %s result=%p\n",(scopeName+"::"+usedName).data(),usedCd); + } + else + { + usedCd=getResolvedClass(usedName,0,&templSpec); + if (usedCd==0) usedCd=getResolvedClass(usedClassName,0,&templSpec); + //printf("Search for class %s result=%p\n",usedName.data(),usedCd); + } + if (scope) scope=scope->getOuterScope(); + } while (scope && usedCd==0); + + if (usedCd) + { + found=TRUE; + instanceCd->addUsedClass(usedCd,md->name()); // class exists + } + } + if (delTempNames) + { + delete templateNames; + templateNames=0; + } + } + } + } + } +} + +static void findBaseClassesForClass( + Entry *root, + ClassDef *masterCd, + ClassDef *instanceCd, + FindBaseClassRelation_Mode mode, + bool isArtificial, + ArgumentList *actualArgs=0, + QDict<int> *templateNames=0 + ) +{ + //if (masterCd->visited) return; + masterCd->visited=TRUE; + // The base class could ofcouse also be a non-nested class + ArgumentList *formalArgs = masterCd->templateArguments(); + QListIterator<BaseInfo> bii(*root->extends); + BaseInfo *bi=0; + for (bii.toFirst();(bi=bii.current());++bii) + { + bool delTempNames=FALSE; + if (templateNames==0) + { + templateNames = getTemplateArgumentsInName(formalArgs,bi->name); + delTempNames=TRUE; + } + BaseInfo tbi(bi->name,bi->prot,bi->virt); + if (actualArgs) // substitute the formal template arguments of the base class + { + tbi.name = substituteTemplateArgumentsInString(bi->name,formalArgs,actualArgs); + } + + if (mode==DocumentedOnly) + { + // find a documented base class in the correct scope + if (!findClassRelation(root,instanceCd,&tbi,templateNames,DocumentedOnly,isArtificial)) + { + // no documented base class -> try to find an undocumented one + findClassRelation(root,instanceCd,&tbi,templateNames,Undocumented,isArtificial); + } + } + else if (mode==TemplateInstances) + { + findClassRelation(root,instanceCd,&tbi,templateNames,TemplateInstances,isArtificial); + } + if (delTempNames) + { + delete templateNames; + templateNames=0; + } + } +} + +//---------------------------------------------------------------------- + +static bool findTemplateInstanceRelation(Entry *root, + ClassDef *templateClass,const QCString &templSpec, + QDict<int> *templateNames, + bool isArtificial) +{ + Debug::print(Debug::Classes,0," derived from template %s with parameters %s\n", + templateClass->name().data(),templSpec.data()); + //printf("findTemplateInstanceRelation(base=%s templSpec=%s templateNames=", + // templateClass->name().data(),templSpec.data()); + //if (templateNames) + //{ + // QDictIterator<int> qdi(*templateNames); + // int *tempArgIndex; + // for (;(tempArgIndex=qdi.current());++qdi) + // { + // printf("(%s->%d) ",qdi.currentKey().data(),*tempArgIndex); + // } + //} + //printf("\n"); + + bool existingClass = (templSpec==tempArgListToString(templateClass->templateArguments())); + if (existingClass) return TRUE; + + bool freshInstance=FALSE; + ClassDef *instanceClass = templateClass->insertTemplateInstance( + root->fileName,root->startLine,templSpec,freshInstance); + if (isArtificial) instanceClass->setClassIsArtificial(); + + if (freshInstance) + { + Doxygen::classSDict.inSort(instanceClass->name(),instanceClass); + instanceClass->setTemplateBaseClassNames(templateNames); + + // search for new template instances caused by base classes of + // instanceClass + Entry *templateRoot = classEntries.find(templateClass->name()); + + ArgumentList *templArgs = new ArgumentList; + stringToArgumentList(templSpec,templArgs); + findBaseClassesForClass(templateRoot,templateClass,instanceClass, + TemplateInstances,isArtificial,templArgs,templateNames); + + findUsedClassesForClass(templateRoot,templateClass,instanceClass, + isArtificial,templArgs,templateNames); + + //Debug::print(Debug::Classes,0," Template instance %s : \n",instanceClass->name().data()); + //ArgumentList *tl = templateClass->templateArguments(); + } + return TRUE; +} + +static bool findClassRelation( + Entry *root, + ClassDef *cd, + BaseInfo *bi, + QDict<int> *templateNames, + FindBaseClassRelation_Mode mode, + bool isArtificial ) { + //printf("findClassRelation(class=%s base=%s templateNames=", + // cd->name().data(),bi->name.data()); + //if (templateNames) + //{ + // QDictIterator<int> qdi(*templateNames); + // int *tempArgIndex; + // for (;(tempArgIndex=qdi.current());++qdi) + // { + // printf("(%s->%d) ",qdi.currentKey().data(),*tempArgIndex); + // } + //} + //printf("\n"); + + Entry *parentNode=root->parent; bool lastParent=FALSE; do // for each parent scope, starting with the largest scope @@ -2377,8 +2699,9 @@ static bool findBaseClassRelation( // baseClass?baseClass->name().data():"<none>", // templSpec.data() // ); - if (baseClassName!=root->name) // check for base class with the same name, - // look in the outer scope for a match + if (baseClassName!=root->name) // Check for base class with the same name. + // If found then look in the outer scope for a match + // and prevent recursion. { Debug::print( Debug::Classes,0," class relation %s inherited by %s found (%s and %s)\n", @@ -2420,7 +2743,7 @@ static bool findBaseClassRelation( } } - bool found=baseClass!=0 && baseClass!=cd; + bool found=baseClass!=0 && (baseClass!=cd || mode==TemplateInstances); NamespaceDef *nd=cd->getNamespaceDef(); if (!found && (i=baseClassName.findRev("::"))!=-1) { @@ -2520,25 +2843,60 @@ static bool findBaseClassRelation( } } } - if (isTemplBaseClass==-1 && found) + bool isATemplateArgument = templateNames!=0 && templateNames->find(bi->name)!=0; + if (!isATemplateArgument && found) { Debug::print(Debug::Classes,0," Documented base class `%s' templSpec=%s\n",bi->name.data(),templSpec.data()); // add base class to this class - QCString usedName; - if (baseClassIsTypeDef) usedName=bi->name; - cd->insertBaseClass(baseClass,usedName,bi->prot,bi->virt,templSpec); - // add this class as super class to the base class - baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); + + // if templSpec is not empty then we should "instantiate" + // the template baseClass. A new ClassDef should be created + // to represent the instance. To be able to add the (instantiated) + // members and documentation of a template class + // (inserted in that template class at a later stage), + // the template should know about its instances. + // the instantiation process, should be done in a recursive way, + // since instantiating a template may introduce new inheritance + // relations. + if (!templSpec.isEmpty() && mode==TemplateInstances) + { + findTemplateInstanceRelation(root,baseClass,templSpec,templateNames,isArtificial); + } + else if (mode==DocumentedOnly) + { + QCString usedName; + if (baseClassIsTypeDef) usedName=bi->name; + cd->insertBaseClass(baseClass,usedName,bi->prot,bi->virt,templSpec); + // add this class as super class to the base class + baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); + } return TRUE; } - else if ((scopeOffset==0 && insertUndocumented) || isTemplBaseClass!=-1) + else if (mode==Undocumented && (scopeOffset==0 || isATemplateArgument)) { Debug::print(Debug::Classes,0, - " Undocumented base class `%s' baseClassName=%s\n", + " New undocumented base class `%s' baseClassName=%s\n", bi->name.data(),baseClassName.data() ); - baseClass=new ClassDef(root->fileName,root->startLine, + baseClass=0; + if (isATemplateArgument) + { + baseClass=Doxygen::hiddenClasses.find(baseClassName); + if (baseClass==0) + { + baseClass=new ClassDef(root->fileName,root->startLine, baseClassName,ClassDef::Class); + Doxygen::hiddenClasses.inSort(baseClassName,baseClass); + if (isArtificial) baseClass->setClassIsArtificial(); + } + } + else + { + baseClass=new ClassDef(root->fileName,root->startLine, + baseClassName,ClassDef::Class); + Doxygen::classSDict.inSort(baseClassName,baseClass); + if (isArtificial) baseClass->setClassIsArtificial(); + } // add base class to this class cd->insertBaseClass(baseClass,bi->name,bi->prot,bi->virt,templSpec); // add this class as super class to the base class @@ -2547,15 +2905,16 @@ static bool findBaseClassRelation( baseClass->insertUsedFile(root->fileName); // is this an inherited template argument? //printf("%s->setIsTemplateBaseClass(%d)\n",baseClass->name().data(),isTemplBaseClass); - baseClass->setIsTemplateBaseClass(isTemplBaseClass); + if (isATemplateArgument) + { + baseClass->setIsTemplateBaseClass(*templateNames->find(bi->name)); + } // add class to the list - if (isTemplBaseClass==-1) + if (!isATemplateArgument) { - Doxygen::classSDict.inSort(baseClassName,baseClass); } else { - Doxygen::hiddenClasses.append(baseClass); } return TRUE; } @@ -2591,23 +2950,54 @@ static bool findBaseClassRelation( //---------------------------------------------------------------------- // Computes the base and super classes for each class in the tree -static void computeClassRelations(Entry *root) +static bool isClassSection(Entry *root) { - if ( + return + ( ( - ( - // is it a compound (class, struct, union, interface ...) - root->section & Entry::COMPOUND_MASK - ) - || - ( - // is it a documentation block with inheritance info. - (root->section & Entry::COMPOUNDDOC_MASK) && root->extends->count()>0 - ) + ( + // is it a compound (class, struct, union, interface ...) + root->section & Entry::COMPOUND_MASK + ) + || + ( + // is it a documentation block with inheritance info. + (root->section & Entry::COMPOUNDDOC_MASK) && root->extends->count()>0 + ) ) - && - !root->name.isEmpty() // sanity check - ) + && !root->name.isEmpty() // sanity check + ); +} + + +/*! Builds a dictionary of all entry nodes in the tree starting with \a root + */ +static void findClassEntries(Entry *root) +{ + if (isClassSection(root)) + { + classEntries.insert(root->name,root); + } + EntryListIterator eli(*root->sublist); + Entry *e; + for (;(e=eli.current());++eli) + { + findClassEntries(e); + } +} + +/*! Using the dictionary build by findClassEntries(), this + * function will look for additional template specialization that + * exists as inheritance relations only. These instances will be + * added to the template they are derived from. + */ +static void findInheritedTemplateInstances() +{ + ClassSDict::Iterator cli(Doxygen::classSDict); + for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE; + QDictIterator<Entry> edi(classEntries); + Entry *root; + for (;(root=edi.current());++edi) { ClassDef *cd; // strip any annonymous scopes first @@ -2616,61 +3006,133 @@ static void computeClassRelations(Entry *root) if ((cd=getClass(bName))) { //printf("Class %s %d\n",cd->name().data(),root->extends->count()); - if (!cd->visited) // check integrity of the tree + findBaseClassesForClass(root,cd,cd,TemplateInstances,FALSE); + } + } +} + +static void findUsedTemplateInstances() +{ + ClassSDict::Iterator cli(Doxygen::classSDict); + for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE; + QDictIterator<Entry> edi(classEntries); + Entry *root; + for (;(root=edi.current());++edi) + { + ClassDef *cd; + // strip any annonymous scopes first + QCString bName=stripAnonymousNamespaceScope(root->name); + Debug::print(Debug::Classes,0," Class %s : \n",bName.data()); + if ((cd=getClass(bName))) + { + findUsedClassesForClass(root,cd,cd,TRUE); + } + } +} + +static void computeClassRelations() +{ + ClassSDict::Iterator cli(Doxygen::classSDict); + for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE; + QDictIterator<Entry> edi(classEntries); + Entry *root; + for (;(root=edi.current());++edi) + { + ClassDef *cd; + // strip any annonymous scopes first + QCString bName=stripAnonymousNamespaceScope(root->name); + Debug::print(Debug::Classes,0," Class %s : \n",bName.data()); + if ((cd=getClass(bName))) + { + findBaseClassesForClass(root,cd,cd,DocumentedOnly,FALSE); + } + else if (bName.right(2)!="::") + { + if (!root->name.isEmpty() && root->name[0]!='@') + warn_undoc( + root->fileName,root->startLine, + "Warning: Compound %s is not documented.", + root->name.data() + ); + } + } +} + +static void computeTemplateClassRelations() +{ + QDictIterator<Entry> edi(classEntries); + Entry *root; + for (;(root=edi.current());++edi) + { + QCString bName=stripAnonymousNamespaceScope(root->name); + ClassDef *cd=getClass(bName); + // strip any annonymous scopes first + QDict<ClassDef> *templInstances = 0; + if (cd && (templInstances=cd->getTemplateInstances())) + { + Debug::print(Debug::Classes,0," Template class %s : \n",cd->name().data()); + QDictIterator<ClassDef> tdi(*templInstances); + ClassDef *tcd; + for (tdi.toFirst();(tcd=tdi.current());++tdi) // for each template instance { - cd->visited=TRUE; // mark class as used - if (root->extends->count()>0) // there are base classes + Debug::print(Debug::Classes,0," Template instance %s : \n",tcd->name().data()); + //QCString templName = tcd->name(); + //int index = templName.find('<'); + //ASSERT(index!=-1); + // templName.right(templName.length()-index); + QCString templSpec = tdi.currentKey().data(); + ArgumentList *templArgs = new ArgumentList; + stringToArgumentList(templSpec,templArgs); + QList<BaseInfo> *baseList=root->extends; + BaseInfo *bi=baseList->first(); + while (bi) // for each base class of the template { - - // The base class could ofcouse also be a non-nested class - QList<BaseInfo> *baseList=root->extends; - BaseInfo *bi=baseList->first(); - while (bi) // for each base class + // check if the base class is a template argument + BaseInfo tbi(bi->name,bi->prot,bi->virt); + ArgumentList *tl = cd->templateArguments(); + if (tl) { - // check if the base class is a template argument - int isTemplBaseClass = -1; - ArgumentList *tl = cd->templateArguments(); - if (tl) + QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames(); + QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi->name); + // for each template name that we inherit from we need to + // substitute the formal with the actual arguments + QDict<int> *actualTemplateNames = new QDict<int>(17); + actualTemplateNames->setAutoDelete(TRUE); + QDictIterator<int> qdi(*templateNames); + for (qdi.toFirst();qdi.current();++qdi) { - ArgumentListIterator ali(*tl); - Argument *arg; - int count=0; - for (ali.toFirst();(arg=ali.current());++ali,++count) + int templIndex = *qdi.current(); + Argument *actArg = 0; + if (templIndex<(int)templArgs->count()) { - if (arg->name==bi->name) // base class is a template argument - { - isTemplBaseClass = count; - break; - } + actArg=templArgs->at(templIndex); + } + if (actArg!=0 && + baseClassNames!=0 && + baseClassNames->find(actArg->type)!=0 && + actualTemplateNames->find(actArg->type)==0 + ) + { + actualTemplateNames->insert(actArg->type,new int(templIndex)); } } + delete templateNames; + + tbi.name = substituteTemplateArgumentsInString(bi->name,tl,templArgs); // find a documented base class in the correct scope - if (!findBaseClassRelation(root,cd,bi,isTemplBaseClass,FALSE)) + if (!findClassRelation(root,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE)) { // no documented base class -> try to find an undocumented one - findBaseClassRelation(root,cd,bi,isTemplBaseClass,TRUE); + findClassRelation(root,tcd,&tbi,actualTemplateNames,Undocumented,FALSE); } - bi=baseList->next(); + delete actualTemplateNames; } - } // class has no base classes - } // else class is already found - } - else if (bName.right(2)!="::") - { - if (!root->name.isEmpty() && root->name[0]!='@') - warn_undoc( - root->fileName,root->startLine, - "Warning: Compound %s is not documented.", - root->name.data() - ); + bi=baseList->next(); + } + delete templArgs; + } // class has no base classes } } - EntryListIterator eli(*root->sublist); - Entry *e; - for (;(e=eli.current());++eli) - { - computeClassRelations(e); - } } //----------------------------------------------------------------------- @@ -2800,7 +3262,6 @@ static void addTodoTestBugReferences() if (d) scopeName=d->name(); if (d==0) d=md->getGroupDef(); if (d==0) d=md->getFileDef(); - // TODO: i18n this QCString memLabel; if (Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) { @@ -2994,7 +3455,7 @@ static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd, { cl=nd->getUsedClasses(); } - else + else if (fd) { cl=fd->getUsedClasses(); } @@ -3629,7 +4090,7 @@ static void findMember(Entry *root, if (!isRelated && mn) // function name already found { Debug::print(Debug::FindMembers,0, - "2. member name exists \n"); + "2. member name exists (%d members with this name)\n",mn->count()); if (!className.isEmpty()) // class name is valid { int count=0; @@ -3637,9 +4098,11 @@ static void findMember(Entry *root, MemberDef *md; for (mni.toFirst();(md=mni.current());++mni) { - Debug::print(Debug::FindMembers,0, - "3. member definition found scopeName=`%s'\n",scopeName.data()); ClassDef *cd=md->getClassDef(); + Debug::print(Debug::FindMembers,0, + "3. member definition found scope needed=`%s' scope=`%s' args=`%s'\n", + scopeName.data(),cd ? cd->name().data() : "<none>", + md->argsString()); //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; @@ -3773,6 +4236,7 @@ static void findMember(Entry *root, // root->inLine,md->isInline()); addMemberDocs(root,md,funcDecl,0,overloaded,nl); count++; + break; } } } @@ -3985,9 +4449,9 @@ static void findMember(Entry *root, cd->insertUsedFile(root->fileName); md->setRefItems(root->todoId,root->testId,root->bugId); addMemberToGroups(root,md); + //printf("Adding member=%s\n",md->name().data()); if (newMemberName) { - //printf("Adding memberName=%s\n",mn->memberName()); Doxygen::memberNameList.append(mn); Doxygen::memberNameDict.insert(funcName,mn); } @@ -4077,14 +4541,7 @@ static void findMemberDocumentation(Entry *root) compoundKeywordDict.find(root->type)==0 // that is not a keyword // (to skip forward declaration of class etc.) ) - ) /* - && (!root->stat && !root->parent) // not static & global: TODO: fix this hack! - && ( - !root->doc.isEmpty() || // has detailed docs - !root->brief.isEmpty() || // has brief docs - (root->memSpec&Entry::Inline) || // is inline - root->mGrpId!=-1 || // is part of a group - ) */ + ) ) { //printf("Documentation for member `%s' found args=`%s' excp=`%s'\n", @@ -4261,6 +4718,7 @@ static void findEnums(Entry *root) md->setDocumentation(root->doc); md->setBriefDescription(root->brief); + //printf("Adding member=%s\n",md->name().data()); MemberName *mn; if ((mn=(*mnd)[name])) { @@ -4545,13 +5003,37 @@ static void computeMemberRelations() //---------------------------------------------------------------------------- -static void computeClassImplUsageRelations() +//static void computeClassImplUsageRelations() +//{ +// ClassDef *cd; +// ClassSDict::Iterator cli(Doxygen::classSDict); +// for (;(cd=cli.current());++cli) +// { +// cd->determineImplUsageRelation(); +// } +//} + +//---------------------------------------------------------------------------- + +static void createTemplateInstanceMembers() { - ClassDef *cd; ClassSDict::Iterator cli(Doxygen::classSDict); - for (;(cd=cli.current());++cli) + ClassDef *cd; + // for each class + for (cli.toFirst();(cd=cli.current());++cli) { - cd->determineImplUsageRelation(); + // that is a template + QDict<ClassDef> *templInstances = cd->getTemplateInstances(); + if (templInstances) + { + QDictIterator<ClassDef> qdi(*templInstances); + ClassDef *tcd=0; + // for each instance of the template + for (qdi.toFirst();(tcd=qdi.current());++qdi) + { + tcd->addMembersToTemplateInstance(cd,qdi.currentKey().data()); + } + } } } @@ -4747,8 +5229,8 @@ static void generateClassDocs() for ( ; cli.current() ; ++cli ) { ClassDef *cd=cli.current(); - if ( cd->isLinkableInProject() ) - // skip external references and anonymous compounds + if ( cd->isLinkableInProject() && cd->templateMaster()==0 ) + // skip external references, anonymous compounds and template instances { msg("Generating docs for compound %s...\n",cd->name().data()); @@ -4892,6 +5374,7 @@ static void findDefineDocumentation(Entry *root) FileDef *fd=findFileDef(Doxygen::inputNameDict,filePathName,ambig); //printf("Searching for `%s' fd=%p\n",filePathName.data(),fd); md->setFileDef(fd); + //printf("Adding member=%s\n",md->name().data()); MemberName *mn; if ((mn=Doxygen::functionNameDict[root->name])) { @@ -6592,8 +7075,24 @@ void parseInput() msg("Searching for documented defines...\n"); findDefineDocumentation(root); - msg("Computing class relations...\n"); - computeClassRelations(root); + msg("Computing template instances..."); + findClassEntries(root); + findInheritedTemplateInstances(); + findUsedTemplateInstances(); + + msg("Creating members for template instances...\n"); + createTemplateInstanceMembers(); + + //if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH")) + //{ + // msg("Computing class implementation usage relations...\n"); + // computeClassImplUsageRelations(); + //} + + msg("Computing class relations..."); + computeTemplateClassRelations(); + computeClassRelations(); + classEntries.clear(); msg("Searching for enumerations...\n"); findEnums(root); @@ -6631,12 +7130,6 @@ void parseInput() msg("Adding classes to their packages...\n"); addClassesToPackages(); - if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH")) - { - msg("Computing class implementation usage relations...\n"); - computeClassImplUsageRelations(); - } - msg("Adding members to member groups.\n"); addMembersToMemberGroup(); diff --git a/src/doxygen.h b/src/doxygen.h index f81241a..47310b8 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -59,7 +59,7 @@ class Doxygen { public: static ClassSDict classSDict; - static ClassList hiddenClasses; + static ClassSDict hiddenClasses; static PageSDict *exampleSDict; static PageSDict *pageSDict; static PageInfo *mainPage; diff --git a/src/filedef.h b/src/filedef.h index 2bdbbcf..79525b0 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -110,12 +110,12 @@ class FileDef : public Definition /*! Returns the absolute path of this file. */ QCString getPath() const { return path; } - bool isLinkableInProject() + bool isLinkableInProject() const { return hasDocumentation() && !isReference(); } - bool isLinkable() + bool isLinkable() const { return isLinkableInProject() || isReference(); } diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index 38c2e72..a49ff2f 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -311,13 +311,14 @@ static void generateFolderTreeViewData() QTextStream t(&f); t << "<html><head>" << endl; t << "<link rel=\"stylesheet\" href=\""; - if (Config_getString("HTML_STYLESHEET").isEmpty()) + QCString cssname=Config_getString("HTML_STYLESHEET"); + if (cssname.isEmpty()) { t << "doxygen.css"; } else { - QFileInfo cssfi(Config_getString("HTML_STYLESHEET")); + QFileInfo cssfi(cssname); if (!cssfi.exists()) { err("Error: user specified HTML style sheet file does not exist!\n"); diff --git a/src/groupdef.h b/src/groupdef.h index c2d413a..b4a446e 100644 --- a/src/groupdef.h +++ b/src/groupdef.h @@ -62,11 +62,11 @@ class GroupDef : public Definition bool containsGroup(const GroupDef *def); // true if def is already a subgroup void writeDocumentation(OutputList &ol); int countMembers() const; - bool isLinkableInProject() + bool isLinkableInProject() const { return hasDocumentation() && !isReference(); } - bool isLinkable() + bool isLinkable() const { return isLinkableInProject() || isReference(); } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 0c82986..57ce664 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -46,10 +46,10 @@ static const char *defaultStyleSheet = "A.codeRef { font-weight: normal; color: #4444ee }\n" "DL.el { margin-left: -1cm }\n" "DIV.fragment { width: 100%; border: none; background-color: #eeeeee }\n" - "DIV.ah { background-color: black; margin-bottom: 3; margin-top: 3 }\n" + "DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }\n" "TD.md { background-color: #f2f2ff }\n" - "DIV.groupHeader { margin-left: 16; margin-top: 12; margin-bottom: 6; font-weight: bold }\n" - "DIV.groupText { margin-left: 16; font-style: italic; font-size: smaller }\n" + "DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold }\n" + "DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller }\n" "FONT.keyword { color: #008000 }\n" "FONT.keywordtype { color: #604020 }\n" "FONT.keywordflow { color: #e08000 }\n" @@ -80,13 +80,14 @@ void HtmlGenerator::append(const OutputGenerator *g) void HtmlGenerator::init() { - QDir d(Config_getString("HTML_OUTPUT")); - if (!d.exists() && !d.mkdir(Config_getString("HTML_OUTPUT"))) + QCString dname=Config_getString("HTML_OUTPUT"); + QDir d(dname); + if (!d.exists() && !d.mkdir(dname)) { - err("Could not create output directory %s\n",Config_getString("HTML_OUTPUT").data()); + err("Could not create output directory %s\n",dname.data()); exit(1); } - writeLogo(Config_getString("HTML_OUTPUT")); + writeLogo(dname); if (!Config_getString("HTML_HEADER").isEmpty()) g_header=fileToString(Config_getString("HTML_HEADER")); if (!Config_getString("HTML_FOOTER").isEmpty()) g_footer=fileToString(Config_getString("HTML_FOOTER")); } @@ -117,7 +118,8 @@ static void writeDefaultHeaderFile(QTextStream &t,const char *title, } else { - QFileInfo cssfi(Config_getString("HTML_STYLESHEET")); + QCString cssname=Config_getString("HTML_STYLESHEET"); + QFileInfo cssfi(cssname); if (!cssfi.exists()) { err("Error: user specified HTML style sheet file does not exist!\n"); @@ -278,7 +280,8 @@ void HtmlGenerator::writeStyleInfo(int part) } else // write user defined style sheet { - QFileInfo cssfi(Config_getString("HTML_STYLESHEET")); + QCString cssname=Config_getString("HTML_STYLESHEET"); + QFileInfo cssfi(cssname); if (!cssfi.exists() || !cssfi.isFile() || !cssfi.isReadable()) { err("Error: style sheet %s does not exist or is not readable!", Config_getString("HTML_STYLESHEET").data()); @@ -286,7 +289,7 @@ void HtmlGenerator::writeStyleInfo(int part) else { startPlainFile(cssfi.fileName()); - t << fileToString(Config_getString("HTML_STYLESHEET")); + t << fileToString(cssname); endPlainFile(); } } @@ -813,7 +816,7 @@ void HtmlGenerator::endIndexList() void HtmlGenerator::startAlphabeticalIndexList() { - t << "<table align=center width=\"95%\" border=0 cellspacing=0 cellpadding=0>" << endl; + t << "<table align=center width=\"95%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">" << endl; } void HtmlGenerator::endAlphabeticalIndexList() @@ -823,8 +826,8 @@ void HtmlGenerator::endAlphabeticalIndexList() void HtmlGenerator::writeIndexHeading(const char *s) { - t << "<div class=\"ah\"><font color=\"white\"><b> " << s - << " </b></font></div>"; + t << "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td><div class=\"ah\"> " << s + << " </td</tr></table>"; } void HtmlGenerator::startImage(const char *name,const char *,bool hasCaption) diff --git a/src/index.cpp b/src/index.cpp index 9ce2f94..97957fe 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -356,6 +356,7 @@ void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper) bool hasChildren = !cd->visited && !hideSuper && cd->subClasses()->count()>0; if (cd->isLinkable()) { + //printf("Writing class %s\n",cd->displayName().data()); ol.writeIndexItem(cd->getReference(),cd->getOutputFileBase(),cd->displayName()); if (cd->isReference()) { @@ -518,10 +519,8 @@ void writeClassTree(ClassSDict *d) //---------------------------------------------------------------------------- -void writeClassHierarchy(OutputList &ol) +static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started) { - initClassHierarchy(&Doxygen::classSDict); - HtmlHelp *htmlHelp=0; FTVHelp *ftvHelp=0; bool &generateHtml = Config_getBool("GENERATE_HTML") ; @@ -536,8 +535,7 @@ void writeClassHierarchy(OutputList &ol) ftvHelp = FTVHelp::getInstance(); } - bool started=FALSE; - ClassSDict::Iterator cli(Doxygen::classSDict); + ClassSDict::Iterator cli(*cl); for (;cli.current(); ++cli) { ClassDef *cd=cli.current(); @@ -560,7 +558,7 @@ void writeClassHierarchy(OutputList &ol) bool hasChildren = !cd->visited && cd->subClasses()->count()>0; if (cd->isLinkable()) { - //printf("Writing class %s\n",cd->name().data()); + //printf("Writing class %s\n",cd->displayName().data()); ol.writeIndexItem(cd->getReference(),cd->getOutputFileBase(),cd->displayName()); if (cd->isReference()) { @@ -597,6 +595,30 @@ void writeClassHierarchy(OutputList &ol) } } } +} + +void writeClassHierarchy(OutputList &ol) +{ + HtmlHelp *htmlHelp=0; + FTVHelp *ftvHelp=0; + bool &generateHtml = Config_getBool("GENERATE_HTML") ; + bool hasHtmlHelp = generateHtml && Config_getBool("GENERATE_HTMLHELP"); + bool hasFtvHelp = generateHtml && Config_getBool("GENERATE_TREEVIEW"); + if (hasHtmlHelp) + { + htmlHelp = HtmlHelp::getInstance(); + } + if (hasFtvHelp) + { + ftvHelp = FTVHelp::getInstance(); + } + + initClassHierarchy(&Doxygen::classSDict); + initClassHierarchy(&Doxygen::hiddenClasses); + + bool started=FALSE; + writeClassTreeForList(ol,&Doxygen::classSDict,started); + writeClassTreeForList(ol,&Doxygen::hiddenClasses,started); if (started) { ol.endIndexList(); @@ -1062,7 +1084,7 @@ int countAnnotatedClasses() ClassDef *cd; for (;(cd=cli.current());++cli) { - if (cd->isLinkableInProject()) + if (cd->isLinkableInProject() && cd->templateMaster()==0) { //printf("Annotated class %s\n",cd->name().data()); count++; @@ -1085,7 +1107,7 @@ void writeAnnotatedClassList(OutputList &ol) ClassDef *cd; for (;(cd=cli.current());++cli) { - if (cd->isLinkableInProject()) + if (cd->isLinkableInProject() && cd->templateMaster()==0) { QCString type=cd->compoundTypeString(); ol.writeStartAnnoItem(type,cd->getOutputFileBase(),0,cd->displayName()); @@ -1168,7 +1190,7 @@ void writeAlphabeticalClassList(OutputList &ol) int headerItems=0; for (;(cd=cli.current());++cli) { - if (cd->isLinkableInProject()) + if (cd->isLinkableInProject() && cd->templateMaster()==0) { int index = getPrefixIndex(cd->name()); if (toupper(cd->name().at(index))!=startLetter) // new begin letter => new header @@ -1201,7 +1223,7 @@ void writeAlphabeticalClassList(OutputList &ol) startLetter=0; for (cli.toFirst();(cd=cli.current());++cli) { - if (cd->isLinkableInProject()) + if (cd->isLinkableInProject() && cd->templateMaster()==0) { int index = getPrefixIndex(cd->name()); if (toupper(cd->name().at(index))!=startLetter) @@ -1443,7 +1465,7 @@ void writeMemberList(OutputList &ol,bool useSections) if ( md->isLinkableInProject() && (cd=md->getClassDef()) && - cd->isLinkableInProject() + cd->isLinkableInProject() && cd->templateMaster()==0 ) { found=TRUE; @@ -1489,7 +1511,7 @@ void writeMemberList(OutputList &ol,bool useSections) if ( md->isLinkableInProject() && prevName!=cd->displayName() && - cd->isLinkableInProject() + cd->isLinkableInProject() && cd->templateMaster()==0 ) { if (count==0) @@ -2632,6 +2654,26 @@ void writeIndex(OutputList &ol) if (Doxygen::mainPage) { parseDoc(ol,defFileName,defLine,0,0,Doxygen::mainPage->doc); + + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <compound kind=\"page\">" << endl + << " <filename>" + << convertToXML(Doxygen::mainPage->fileName) + << "</filename>" + << endl + << " <title>" + << convertToXML(Doxygen::mainPage->title) + << "</title>" + << endl + << " <name>" + << convertToXML(Doxygen::mainPage->name) + << "</name>" + << endl; + + Doxygen::mainPage->writeDocAnchorsToTagFile(); + Doxygen::tagFile << " </compound>" << endl; + } } endFile(ol); diff --git a/src/libdoxygen.pro.in b/src/libdoxygen.pro.in index 319cf3a..c86e343 100644 --- a/src/libdoxygen.pro.in +++ b/src/libdoxygen.pro.in @@ -139,6 +139,7 @@ SOURCES = ce_lex.cpp \ searchindex.cpp \ suffixtree.cpp \ tagreader.cpp \ + translator.cpp \ util.cpp \ version.cpp diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 3a26976..bcefdf7 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -309,6 +309,7 @@ MemberDef::MemberDef(const char *df,int dl, { argList=0; } + m_templateMaster=0; } /*! Destroys the member definition. */ @@ -361,7 +362,11 @@ bool MemberDef::hasExamples() QCString MemberDef::getOutputFileBase() const { - if (classDef) + if (m_templateMaster) + { + return m_templateMaster->getOutputFileBase(); + } + else if (classDef) { return classDef->getOutputFileBase(); } @@ -570,6 +575,7 @@ void MemberDef::writeDeclaration(OutputList &ol, Doxygen::tagFile << "\" static=\"yes"; } Doxygen::tagFile << "\">" << endl; + Doxygen::tagFile << " <type>" << convertToXML(typeString()) << "</type>" << endl; Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; Doxygen::tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>" << endl; Doxygen::tagFile << " <arglist>" << convertToXML(argsString()) << "</arglist>" << endl; @@ -963,7 +969,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),ldef.right(ldef.length()-ei)); } } - else + else // not an enum value { ol.startDoxyAnchor(cfname,cname,anchor(),doxyName); ol.startMemberDoc(cname,name(),anchor(),name()); @@ -998,7 +1004,6 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, if (cd) { QCString cName=cd->name(); - //printf("cName=%s\n",cName.data()); int il=cName.find('<'); int ir=cName.findRev('>'); if (il!=-1 && ir!=-1 && ir>il) @@ -1273,11 +1278,16 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, parseText(ol,reimplFromLine.left(markerPos)); //text left from marker if (bmd->isLinkable()) // replace marker with link { - ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + Definition *bd=bmd->group; + if (bd==0) bd=bcd; + ol.writeObjectLink(bd->getReference(),bd->getOutputFileBase(), bmd->anchor(),bcd->name()); - if ( bcd->isLinkableInProject()/* && !Config_getBool("PDF_HYPERLINKS")*/ ) + + //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + // bmd->anchor(),bcd->name()); + if ( bd->isLinkableInProject() ) { - writePageRef(ol,bcd->getOutputFileBase(),bmd->anchor()); + writePageRef(ol,bd->getOutputFileBase(),bmd->anchor()); } } else @@ -1348,11 +1358,17 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, if (ok && bcd && bmd) // write link for marker { - ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + // bmd->anchor(),bcd->name()); + Definition* bd; + if (bmd->group) bd=bmd->group; else bd=bcd; + + ol.writeObjectLink(bd->getReference(),bd->getOutputFileBase(), bmd->anchor(),bcd->name()); - if (bcd->isLinkableInProject()/* && !Config_getBool("PDF_HYPERLINKS")*/ ) + + if (bd->isLinkableInProject() ) { - writePageRef(ol,bcd->getOutputFileBase(),bmd->anchor()); + writePageRef(ol,bd->getOutputFileBase(),bmd->anchor()); } } ++mli; @@ -1415,7 +1431,7 @@ void MemberDef::warnIfUndocumented() } -bool MemberDef::isLinkableInProject() +bool MemberDef::isLinkableInProject() const { return !name().isEmpty() && name().at(0)!='@' && ((hasDocumentation() && !isReference()) @@ -1424,7 +1440,7 @@ bool MemberDef::isLinkableInProject() (classDef!=0 || Config_getBool("EXTRACT_STATIC") || !isStatic()); // not a static file/namespace member } -bool MemberDef::isLinkable() +bool MemberDef::isLinkable() const { return isLinkableInProject() || isReference(); } @@ -1515,3 +1531,35 @@ void MemberDef::setNamespace(NamespaceDef *nd) setOuterScope(nd); } +MemberDef *MemberDef::createTemplateInstanceMember( + ArgumentList *formalArgs,ArgumentList *actualArgs) +{ + //printf(" Member %s %s %s\n",typeString(),name().data(),argsString()); + ArgumentList *actualArgList = 0; + if (argList) + { + actualArgList = new ArgumentList; + ArgumentListIterator ali(*argList); + Argument *arg; + for (;(arg=ali.current());++ali) + { + Argument *actArg = new Argument(*arg); + actArg->type = substituteTemplateArgumentsInString(actArg->type,formalArgs,actualArgs); + actualArgList->append(actArg); + } + } + + MemberDef *imd = new MemberDef( + getDefFileName(),getDefLine(), + substituteTemplateArgumentsInString(type,formalArgs,actualArgs), + name(), + substituteTemplateArgumentsInString(args,formalArgs,actualArgs), + exception, prot, + virt, stat, related, mtype, 0, 0 + ); + imd->argList = actualArgList; + imd->def = substituteTemplateArgumentsInString(def,formalArgs,actualArgs); + // TODO: init other member variables. + return imd; +} + diff --git a/src/memberdef.h b/src/memberdef.h index bf40f1b..5a2e279 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -35,6 +35,7 @@ class ExampleSDict; class OutputList; class GroupDef; class QTextStream; +class ArgumentList; struct SourceReference { @@ -121,8 +122,8 @@ class MemberDef : public Definition bool isExternal() const { return explExt; } // output info - bool isLinkableInProject(); - bool isLinkable(); + bool isLinkableInProject() const; + bool isLinkable() const; bool hasDocumentation() const; // overrides hasDocumentation in definition.h bool isBriefSectionVisible() const; bool isDetailedSectionVisible(bool inGroup=FALSE) const; @@ -219,10 +220,15 @@ class MemberDef : public Definition int indentDepth() { return indDepth; } bool visibleMemberGroup(bool hideNoHeader); + MemberDef *templateMaster() const { return m_templateMaster; } QCString getScopeString() const; ClassDef *getClassDefOfAnonymousType(); + MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs, + ArgumentList *actualArgs); + void setTemplateMaster(MemberDef *mt) { m_templateMaster=mt; } + private: ClassDef *classDef; // member of or related to @@ -285,7 +291,7 @@ class MemberDef : public Definition QCString groupFileName; // file where this grouping was defined int groupStartLine; // line " " " " " bool groupHasDocs; // true if the entry that caused the grouping was documented - + MemberDef *m_templateMaster; // disable copying of member defs diff --git a/src/namespacedef.h b/src/namespacedef.h index bcfee88..514d250 100644 --- a/src/namespacedef.h +++ b/src/namespacedef.h @@ -57,14 +57,14 @@ class NamespaceDef : public Definition void addUsingDeclaration(ClassDef *cd); ClassList *getUsedClasses() const { return usingDeclList; } - bool isLinkableInProject() + bool isLinkableInProject() const { int i = name().findRev("::"); if (i==-1) i=0; else i+=2; return !name().isEmpty() && name().at(i)!='@' && hasDocumentation() && !isReference(); } - bool isLinkable() + bool isLinkable() const { return isLinkableInProject() || isReference(); } diff --git a/src/packagedef.h b/src/packagedef.h index fbaefa5..945b229 100644 --- a/src/packagedef.h +++ b/src/packagedef.h @@ -38,11 +38,11 @@ class PackageDef : public Definition QCString getOutputFileBase() const ; void addClass(const ClassDef *def); void writeDocumentation(OutputList &ol); - bool isLinkableInProject() + bool isLinkableInProject() const { return hasDocumentation() && !isReference(); } - bool isLinkable() + bool isLinkable() const { return isLinkableInProject() || isReference(); } @@ -22,7 +22,7 @@ */ #include <stdio.h> -#include <iostream.h> +//#include <iostream.h> #include <assert.h> #include <ctype.h> @@ -796,7 +796,7 @@ bool computeExpression(const QCString &expr) e = removeIdsAndMarkers(e); if (e.isEmpty()) return FALSE; //printf("parsing `%s'\n",e.data()); - return parseCppExpression(e); + return parseCppExpression(g_yyFileName,g_yyLineNr,e); } /*! expands the macro definition in \a name diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 4582025..e3345ca 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -1127,7 +1127,9 @@ void RTFGenerator::endIndexSection(IndexSections is) case isMainPage: t << "\\par " << Rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trMainPage() << "}"<< endl; - t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"index.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; + t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; + if (Config_getBool("GENERATE_TREEVIEW")) t << "main"; else t << "index"; + t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isPackageIndex: t << "\\par " << Rtf_Style_Reset << endl; diff --git a/src/scanner.l b/src/scanner.l index 087c258..eba34de 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -22,7 +22,7 @@ */ #include <stdio.h> #include <stdlib.h> -#include <iostream.h> +//#include <iostream.h> #include <assert.h> #include <ctype.h> @@ -727,9 +727,11 @@ TITLE [tT][iI][tT][lL][eE] <FindMembers>{B}*"explicit"{BN}+ { current->memSpec|=Entry::Explicit; lineCount(); } + /* <FindMembers>{B}*"import"{BN}+ { // IDL import keyword BEGIN( NextSemi ); } + */ <FindMembers>{B}*"typename"{BN}+ { lineCount(); } <FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] { isTypedef=FALSE; @@ -1035,7 +1037,9 @@ TITLE [tT][iI][tT][lL][eE] } <FindMembers,FindMemberName>{SCOPENAME} { // correct for misinterpreting return type as scope name: example: A<T> func() - if (YY_START==FindMembers && current->tArgList && current->mtArgList==0) + //printf("YY_START=%d current->tArgList=%p current->mtArgList=%p\n", + // YY_START,current->tArgList,current->mtArgList); + if (YY_START==FindMembers /*&& current->tArgList*/ && current->mtArgList==0) { current->mtArgList=current->tArgList; current->tArgList=0; @@ -1046,6 +1050,10 @@ TITLE [tT][iI][tT][lL][eE] { BEGIN(CppQuote); } + else if (insideIDL && yyleng==6 && strcmp(yytext,"import")==0) + { + BEGIN(NextSemi); + } else if (insideIDL && strcmp(yytext,"case")==0) { BEGIN(IDLUnionCase); @@ -3400,7 +3408,7 @@ TITLE [tT][iI][tT][lL][eE] <DocBaseClass>{ID} { //printf("Adding base class %s\n",yytext); current->extends->append( - new BaseInfo(yytext,Public,Normal) + new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) ); } <DocBaseClass>\n { yyLineNr++; BEGIN( ClassDoc ); } diff --git a/src/tagreader.cpp b/src/tagreader.cpp index ed684c9..26b2b0a 100644 --- a/src/tagreader.cpp +++ b/src/tagreader.cpp @@ -39,6 +39,7 @@ class TagMemberInfo { public: TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) {} + QString type; QString name; QString anchor; QString arglist; @@ -54,13 +55,14 @@ class TagClassInfo { public: enum Kind { Class, Struct, Union, Interface, Exception }; - TagClassInfo() { bases=0, members.setAutoDelete(TRUE); } - ~TagClassInfo() { delete bases; } + TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); } + ~TagClassInfo() { delete bases; delete templateArguments; } QString name; QString filename; QStrList docAnchors; QList<BaseInfo> *bases; QList<TagMemberInfo> members; + QList<QString> *templateArguments; Kind kind; }; @@ -168,7 +170,11 @@ class TagFileParser : public QXmlDefaultHandler }; public: - TagFileParser(const char *tagName) : m_tagName(tagName) {} + TagFileParser(const char *tagName) : m_startElementHandlers(17), + m_endElementHandlers(17), + m_tagName(tagName) + { + } void startCompound( const QXmlAttributes& attrib ) { @@ -351,6 +357,17 @@ class TagFileParser : public QXmlDefaultHandler { m_curString = ""; } + void endType() + { + if (m_state==InMember) + { + m_curMember->type = m_curString; + } + else + { + err("Error: Unexpected tag `type' found\n"); + } + } void endName() { switch (m_state) @@ -386,7 +403,11 @@ class TagFileParser : public QXmlDefaultHandler { virt = Virtual; } - if (m_curClass->bases==0) m_curClass->bases = new QList<BaseInfo>; + if (m_curClass->bases==0) + { + m_curClass->bases = new QList<BaseInfo>; + m_curClass->bases->setAutoDelete(TRUE); + } m_curClass->bases->append(new BaseInfo(m_curString,prot,virt)); } else @@ -405,6 +426,22 @@ class TagFileParser : public QXmlDefaultHandler err("Error: Unexpected tag `base' found\n"); } } + void endTemplateArg() + { + if (m_state==InClass && m_curClass) + { + if (m_curClass->templateArguments==0) + { + m_curClass->templateArguments = new QList<QString>; + m_curClass->templateArguments->setAutoDelete(TRUE); + } + m_curClass->templateArguments->append(new QString(m_curString)); + } + else + { + err("Error: Unexpected tag `templarg' found\n"); + } + } void endFilename() { switch (m_state) @@ -510,6 +547,8 @@ class TagFileParser : public QXmlDefaultHandler m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue)); m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startStringValue)); m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement)); + m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue)); + m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue)); m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound)); m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember)); @@ -527,6 +566,8 @@ class TagFileParser : public QXmlDefaultHandler m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage)); m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor)); m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement)); + m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg)); + m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType)); return TRUE; } @@ -811,6 +852,7 @@ void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members) for (;(tmi=mii.current());++mii) { Entry *me = new Entry; + me->type = tmi->type; me->name = tmi->name; me->args = tmi->arglist; me->protection = tmi->prot; @@ -929,6 +971,18 @@ void TagFileParser::buildLists(Entry *root) { ce->extends = tci->bases; tci->bases = 0; } + if (tci->templateArguments) + { + if (ce->tArgList==0) ce->tArgList = new ArgumentList; + QListIterator<QString> sli(*tci->templateArguments); + QString *argName; + for (;(argName=sli.current());++sli) + { + Argument *a = new Argument; + a->name = *argName; + ce->tArgList->append(a); + } + } buildMemberList(ce,tci->members); root->addSubEntry(ce); diff --git a/src/translator.cpp b/src/translator.cpp new file mode 100644 index 0000000..1cb3040 --- /dev/null +++ b/src/translator.cpp @@ -0,0 +1,84 @@ +#include "translator.h" + +const char Translator::WinToISOTab[] = +{ + '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', + '\x88', '\x89', '\xA9', '\x8B', '\xA6', '\xAB', '\xAE', '\xAC', + '\x90', '\x91', '\x92', '\x93', '\x94', '\x2E', '\x96', '\x97', + '\x98', '\x99', '\xB9', '\x9B', '\xB6', '\xBB', '\xBE', '\xBC', + '\xA0', '\x20', '\x20', '\xA3', '\xA4', '\xA1', '\xA6', '\xA7', + '\x22', '\xA9', '\xAA', '\x3C', '\xAC', '\x2D', '\xAE', '\xAF', + '\x2E', '\x2B', '\x20', '\xB3', '\x27', '\x75', '\xB6', '\xB7', + '\x20', '\xB1', '\xBA', '\x3E', '\xA5', '\x22', '\xB5', '\xBF', + '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', + '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', + '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', + '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', + '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', + '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', + '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\x2D', + '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', + '\0' +}; + + +const char Translator::ISOToWinTab[] = { + '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', + '\x88', '\x89', '\x8A', '\x8B', '\x8C', '\x8D', '\x8E', '\x8F', + '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', + '\x98', '\x99', '\x9A', '\x9B', '\x9C', '\x9D', '\x9E', '\x9F', + '\xA0', '\xA5', '\xA2', '\xA3', '\xA4', '\xBC', '\x8C', '\xA7', + '\xA8', '\x8A', '\xAA', '\x8D', '\x8F', '\xAD', '\x8E', '\xAF', + '\xB0', '\xB9', '\xB2', '\xB3', '\xB4', '\xBE', '\x9C', '\xB7', + '\xB8', '\x9A', '\xBA', '\x9D', '\x9F', '\xBD', '\x9E', '\xBF', + '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', + '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', + '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', + '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', + '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', + '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', + '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', + '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', + '\0' +}; + +Q_UINT16 Translator::koi8_r[128] = +{ 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, + 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, + 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219/**/, 0x221A, 0x2248, + 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, + 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, + 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, + 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, + 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9, + 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, + 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, + 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, + 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A +}; + + +Q_UINT16 Translator::windows_1251[128] = +{ 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F +}; + + diff --git a/src/translator.h b/src/translator.h index 1119118..852b997 100644 --- a/src/translator.h +++ b/src/translator.h @@ -26,6 +26,10 @@ class Translator { protected: + static const char WinToISOTab[]; + static const char ISOToWinTab[]; + static Q_UINT16 koi8_r[128]; + static Q_UINT16 windows_1251[128]; /*! Returns the string converted from windows-1250 to iso-8859-2. */ /* The method was designed initially for translator_cz.h. * It is used for on-line encoding conversion related to @@ -46,25 +50,6 @@ class Translator { // The conversion table for characters >127 // - static const char WinToISOTab[] = { - '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', - '\x88', '\x89', '\xA9', '\x8B', '\xA6', '\xAB', '\xAE', '\xAC', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x2E', '\x96', '\x97', - '\x98', '\x99', '\xB9', '\x9B', '\xB6', '\xBB', '\xBE', '\xBC', - '\xA0', '\x20', '\x20', '\xA3', '\xA4', '\xA1', '\xA6', '\xA7', - '\x22', '\xA9', '\xAA', '\x3C', '\xAC', '\x2D', '\xAE', '\xAF', - '\x2E', '\x2B', '\x20', '\xB3', '\x27', '\x75', '\xB6', '\xB7', - '\x20', '\xB1', '\xBA', '\x3E', '\xA5', '\x22', '\xB5', '\xBF', - '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', - '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', - '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', - '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', - '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', - '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', - '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\x2D', - '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', - '\0' - }; QCString result; int len = sInput.length(); @@ -83,25 +68,6 @@ class Translator { // The conversion table for characters >127 // - static const char ISOToWinTab[] = { - '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', - '\x88', '\x89', '\x8A', '\x8B', '\x8C', '\x8D', '\x8E', '\x8F', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', - '\x98', '\x99', '\x9A', '\x9B', '\x9C', '\x9D', '\x9E', '\x9F', - '\xA0', '\xA5', '\xA2', '\xA3', '\xA4', '\xBC', '\x8C', '\xA7', - '\xA8', '\x8A', '\xAA', '\x8D', '\x8F', '\xAD', '\x8E', '\xAF', - '\xB0', '\xB9', '\xB2', '\xB3', '\xB4', '\xBE', '\x9C', '\xB7', - '\xB8', '\x9A', '\xBA', '\x9D', '\x9F', '\xBD', '\x9E', '\xBF', - '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', - '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', - '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', - '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', - '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', - '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', - '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', - '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', - '\0' - }; QCString result; int len = sInput.length(); @@ -122,24 +88,6 @@ class Translator */ QCString Koi8RToWindows1251( const QCString & sInput ) { - static Q_UINT16 koi8_r[128] = - { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, - 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, - 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219/**/, 0x221A, 0x2248, - 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, - 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, - 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, - 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, - 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9, - 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, - 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, - 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, - 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, - 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, - 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, - 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, - 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A - }; QString result; int len = sInput.length(); @@ -160,25 +108,6 @@ class Translator Encoding table got from QT:qtextcodec.cpp */ QCString Windows1251ToKoi8R( const QCString & sInput ) { - static Q_UINT16 windows_1251[128] = - { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, - 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, - 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0xFFFD, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, - 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, - 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, - 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, - 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F - }; - QString result; int len = sInput.length(); @@ -267,7 +196,7 @@ class Translator */ virtual QCString trGeneratedAutomatically(const char *s) = 0; - /*! put after an enum name in the list of all members */ + virtual QCString trEnumName() = 0; /*! put after an enum value in the list of all members */ diff --git a/src/translator_en.h b/src/translator_en.h index 16b2c65..edffbb9 100644 --- a/src/translator_en.h +++ b/src/translator_en.h @@ -397,7 +397,16 @@ class TranslatorEnglish : public Translator * the documentation of all classes, structs and unions. */ virtual QCString trClassDocumentation() - { return "Class Documentation"; } + { + if (Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) + { + return "Data Structure Documentation"; + } + else + { + return "Class Documentation"; + } + } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all files. @@ -1024,7 +1033,9 @@ class TranslatorEnglish : public Translator { return "Graph Legend"; } - /*! page explaining how the dot graph's should be interpreted */ + /*! page explaining how the dot graph's should be interpreted + * The %A in the text below are to prevent link to classes called "A". + */ virtual QCString trLegendDocs() { return @@ -1062,21 +1073,21 @@ class TranslatorEnglish : public Translator "<p>\n" "The boxes in the above graph have the following meaning:\n" "<ul>\n" - "<li>A filled black box represents the struct or class for which the " + "<li>%A filled black box represents the struct or class for which the " "graph is generated.\n" - "<li>A box with a black border denotes a documented struct or class.\n" - "<li>A box with a grey border denotes an undocumented struct or class.\n" - "<li>A box with a red border denotes a documented struct or class for\n" - "which not all inheritance/containment relations are shown. A graph is " + "<li>%A box with a black border denotes a documented struct or class.\n" + "<li>%A box with a grey border denotes an undocumented struct or class.\n" + "<li>%A box with a red border denotes a documented struct or class for\n" + "which not all inheritance/containment relations are shown. %A graph is " "truncated if it does not fit within the specified boundaries." "</ul>\n" "The arrows have the following meaning:\n" "<ul>\n" - "<li>A dark blue arrow is used to visualize a public inheritance " + "<li>%A dark blue arrow is used to visualize a public inheritance " "relation between two classes.\n" - "<li>A dark green arrow is used for protected inheritance.\n" - "<li>A dark red arrow is used for private inheritance.\n" - "<li>A purple dashed arrow is used if a class is contained or used " + "<li>%A dark green arrow is used for protected inheritance.\n" + "<li>%A dark red arrow is used for private inheritance.\n" + "<li>%A purple dashed arrow is used if a class is contained or used " "by another class. The arrow is labeled with the variable(s) " "through which the pointed class or struct is accessible. \n" "</ul>\n"; diff --git a/src/translator_fr.h b/src/translator_fr.h index 82af3d5..c7a7f3f 100644 --- a/src/translator_fr.h +++ b/src/translator_fr.h @@ -15,18 +15,37 @@ * * The translation into French was provided by * Christophe Bordeux (bordeux@lig.di.epfl.ch) + * and after version 1.2.0 by Xavier Outhier (xouthier@yahoo.fr) + * member of of the non for profit association D2SET (http://www.d2set.org, + * d2set@d2set.org). */ #ifndef TRANSLATOR_FR_H #define TRANSLATOR_FR_H -#include "translator_adapter.h" - -class TranslatorFrench : public TranslatorAdapter_1_2_0 +class TranslatorFrench : public Translator { public: QCString idLanguage() { return "french"; } + /*! Used to get the LaTeX command(s) for the language support. + * This method should return string with commands that switch + * LaTeX to the desired language. For example + * <pre>"\\usepackage[german]{babel}\n" + * </pre> + * or + * <pre>"\\usepackage{polski}\n" + * "\\usepackage[latin2]{inputenc}\n" + * "\\usepackage[T1]{fontenc}\n" + * </pre> + * + * The Dutch LaTeX does not use such commands. Because of this + * the empty string is returned in this implementation. + */ + QCString latexLanguageSupportCommand() + { + return "\\usepackage[french]{babel}\n"; + } /*! returns the name of the package that is included by LaTeX */ QCString latexBabelPackage() { return "french"; } @@ -851,7 +870,7 @@ class TranslatorFrench : public TranslatorAdapter_1_2_0 /*! Used as a marker that is put before a todo item */ virtual QCString trTodo() { - return "A Faire"; + return "À Faire"; } /*! Used as the header of the todo list */ virtual QCString trTodoList() @@ -947,7 +966,7 @@ class TranslatorFrench : public TranslatorAdapter_1_2_0 "entre deux classes.\n" "<li>Une flèche vert foncé est utilisée pour une relation d'héritage protégé.\n" "<li>Une flèche rouge foncé est utilisée pour une relation d'héritage privé.\n" - "<li>Une fléche violette en pointillés est utilisée si une classe est contenue ou " + "<li>Une flèche violette en pointillés est utilisée si une classe est contenue ou " "utilisée par une autre classe. La flèche est étiquetée avec la ou les variable(s) " "qui permettent d'acceder à la classe ou structure pointée. \n" "</ul>\n"; @@ -957,6 +976,262 @@ class TranslatorFrench : public TranslatorAdapter_1_2_0 { return "Légende"; } -}; +////////////////////////////////////////////////////////////////////////// +// new since 1.2.0 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a marker that is put before a test item */ + virtual QCString trTest() + { + return "Test"; + } + /*! Used as the header of the test list */ + virtual QCString trTestList() + { + return "Liste des tests"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.1 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a section header for KDE-2 IDL methods */ + virtual QCString trDCOPMethods() + { + return "Méthodes DCOP"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.2 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a section header for IDL properties */ + virtual QCString trProperties() + { + return "Propriétés"; + } + /*! Used as a section header for IDL property documentation */ + virtual QCString trPropertyDocumentation() + { + return "Documentation des propriétés"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.4 +////////////////////////////////////////////////////////////////////////// + + /*! Used for Java interfaces in the summary section of Java packages */ + virtual QCString trInterfaces() + { + return "Interfaces"; + } + /*! Used for Java classes in the summary section of Java packages */ + virtual QCString trClasses() + { + if (Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) + { + return "Structures de données"; + } + else + { + return "Classes"; + } + } + /*! Used as the title of a Java package */ + virtual QCString trPackage(const char *name) + { + return (QCString)"Paquetage "+name; + } + /*! Title of the package index page */ + virtual QCString trPackageList() + { + return "Liste des paquetages"; + } + /*! The description of the package index page */ + virtual QCString trPackageListDescription() + { + return "Liste des paquetages avec une brève description (si disponible):"; + } + /*! The link name in the Quick links header for each page */ + virtual QCString trPackages() + { + return "Paquetages"; + } + /*! Used as a chapter title for Latex & RTF output */ + virtual QCString trPackageDocumentation() + { + return "Documentation des paquetages"; + } + /*! Text shown before a multi-line define */ + virtual QCString trDefineValue() + { + return "Valeur:"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.5 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a marker that is put before a \\bug item */ + virtual QCString trBug() + { + return "Bogue"; + } + /*! Used as the header of the bug list */ + virtual QCString trBugList() + { + return "Liste des bogues"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.6 +////////////////////////////////////////////////////////////////////////// + + /*! Used as ansicpg for RTF file + * + * The following table shows the correlation of Charset name, Charset Value and + * <pre> + * Codepage number: + * Charset Name Charset Value(hex) Codepage number + * ------------------------------------------------------ + * DEFAULT_CHARSET 1 (x01) + * SYMBOL_CHARSET 2 (x02) + * OEM_CHARSET 255 (xFF) + * ANSI_CHARSET 0 (x00) 1252 + * RUSSIAN_CHARSET 204 (xCC) 1251 + * EE_CHARSET 238 (xEE) 1250 + * GREEK_CHARSET 161 (xA1) 1253 + * TURKISH_CHARSET 162 (xA2) 1254 + * BALTIC_CHARSET 186 (xBA) 1257 + * HEBREW_CHARSET 177 (xB1) 1255 + * ARABIC _CHARSET 178 (xB2) 1256 + * SHIFTJIS_CHARSET 128 (x80) 932 + * HANGEUL_CHARSET 129 (x81) 949 + * GB2313_CHARSET 134 (x86) 936 + * CHINESEBIG5_CHARSET 136 (x88) 950 + * </pre> + * + */ + virtual QCString trRTFansicp() + { + return "1252"; + } + + + /*! Used as ansicpg for RTF fcharset + * \see trRTFansicp() for a table of possible values. + */ + virtual QCString trRTFCharSet() + { + return "0"; + } + + /*! Used as header RTF general index */ + virtual QCString trRTFGeneralIndex() + { + return "Index"; + } + + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trClass(bool first_capital, bool singular) + { + QCString result((first_capital ? "Classe" : "classe")); + if (!singular) result+="s"; + return result; + } + + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trFile(bool first_capital, bool singular) + { + QCString result((first_capital ? "Fichier" : "fichier")); + if (!singular) result+="s"; + return result; + } + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trNamespace(bool first_capital, bool singular) + { + QCString result((first_capital ? "Namespace" : "namespace")); + if (!singular) result+="s"; + return result; + } + + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trGroup(bool first_capital, bool singular) + { + QCString result((first_capital ? "Groupe" : "groupe")); + if (!singular) result+="s"; + return result; + } + + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trPage(bool first_capital, bool singular) + { + QCString result((first_capital ? "Page" : "page")); + if (!singular) result+="s"; + return result; + } + + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trMember(bool first_capital, bool singular) + { + QCString result((first_capital ? "Membre" : "membre")); + if (!singular) result+="s"; + return result; + } + + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trField(bool first_capital, bool singular) + { + QCString result((first_capital ? "Champ" : "champ")); + if (!singular) result+="s"; + return result; + } + + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ + virtual QCString trGlobal(bool first_capital, bool singular) + { + QCString result((first_capital ? "Global(e)" : "global(e)")); + if (!singular) result+="s"; + return result; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.7 +////////////////////////////////////////////////////////////////////////// + + /*! This text is generated when the \\author command is used and + * for the author section in man pages. */ + virtual QCString trAuthor(bool first_capital, bool singular) + { + QCString result((first_capital ? "Auteur" : "auteur")); + if (!singular) result+="s"; + return result; + } + +}; #endif diff --git a/src/util.cpp b/src/util.cpp index c4b2606..6a022af 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -715,7 +715,7 @@ QCString argListToString(ArgumentList *al) result+=")"; if (al->constSpecifier) result+=" const"; if (al->volatileSpecifier) result+=" volatile"; - return result; + return removeRedundantWhiteSpace(result); } QCString tempArgListToString(ArgumentList *al) @@ -743,7 +743,7 @@ QCString tempArgListToString(ArgumentList *al) if (a) result+=", "; } result+=">"; - return result; + return removeRedundantWhiteSpace(result); } @@ -2804,8 +2804,7 @@ void addMembersToMemberGroup(MemberList *ml,MemberGroupDict *memberGroupDict, * could form a class. When TRUE is returned the result is the * class \a name and a template argument list \a templSpec. */ -bool extractClassNameFromType(const QCString &type,int &pos, - QCString &name,QCString &templSpec) +bool extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCString &templSpec) { static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*"); name.resize(0); @@ -2818,7 +2817,8 @@ bool extractClassNameFromType(const QCString &type,int &pos, { int ts=i+l; int te=ts; - while (type.at(ts)==' ' && ts<typeLen) ts++; // skip any whitespace + int tl=0; + while (type.at(ts)==' ' && ts<typeLen) ts++,tl++; // skip any whitespace if (type.at(ts)=='<') // assume template instance { // locate end of template @@ -2837,12 +2837,68 @@ bool extractClassNameFromType(const QCString &type,int &pos, te++; } } - if (te>ts) templSpec = type.mid(ts,te-ts); + if (te>ts) templSpec = type.mid(ts,te-ts),tl+=te-ts; name = type.mid(i,l); - pos=i+l; + pos=i+l+tl; + //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE\n", + // type.data(),pos,name.data(),templSpec.data()); return TRUE; } } + //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=FALSE\n", + // type.data(),pos,name.data(),templSpec.data()); return FALSE; } +/*! Substitutes any occurrence of a formal argument from argument list + * \a formalArgs in \a name by the corresponding actual argument in + * argument list \a actualArgs. The result after substitution + * is returned as a string. + */ +QCString substituteTemplateArgumentsInString( + const QCString &name,ArgumentList *formalArgs,ArgumentList *actualArgs) +{ + if (formalArgs==0) return name; + QCString result; + static QRegExp re("[a-z_A-Z][:a-z_A-Z0-9]*"); + int p=0,l,i; + // for each identifier in the base class name (e.g. B<T> -> B and T) + while ((i=re.match(name,p,&l))!=-1) + { + result += name.mid(p,i-p); + QCString n = name.mid(i,l); + ArgumentListIterator formAli(*formalArgs); + Argument *formArg; + Argument *actArg=actualArgs->first(); + + // if n is a template argument, then we substitute it + // for its template instance argument. + bool found=FALSE; + for (formAli.toFirst(); + (formArg=formAli.current()) && !found; + ++formAli,actArg=actualArgs->next() + ) + { + if (formArg->name==n && actArg && !actArg->type.isEmpty()) // base class is a template argument + { + // replace formal argument with the actual argument of the instance + result += actArg->type; + found=TRUE; + } + else if (formArg->name==n && actArg==0 && !formArg->defval.isEmpty()) + { + result += formArg->defval; + found=TRUE; + } + } + if (!found) result += n; + p=i+l; + } + result+=name.right(name.length()-p); + //printf(" Inheritance relation %s -> %s\n", + // name.data(),result.data()); + return result; +} + + + @@ -150,6 +150,8 @@ void addMembersToMemberGroup(MemberList *ml,MemberGroupDict *memberGroupDict, MemberGroupList *memberGroupList); bool extractClassNameFromType(const QCString &type,int &pos, QCString &name,QCString &templSpec); +QCString substituteTemplateArgumentsInString( + const QCString &name,ArgumentList *formalArgs,ArgumentList *actualArgs); #endif |