diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/classdef.cpp | 2 | ||||
-rw-r--r-- | src/code.l | 139 | ||||
-rw-r--r-- | src/config.l | 9 | ||||
-rw-r--r-- | src/doc.l | 2 | ||||
-rw-r--r-- | src/dot.cpp | 96 | ||||
-rw-r--r-- | src/dot.h | 5 | ||||
-rw-r--r-- | src/doxygen.cpp | 113 | ||||
-rw-r--r-- | src/doxytag.l | 1 | ||||
-rw-r--r-- | src/entry.h | 2 | ||||
-rw-r--r-- | src/htmlgen.cpp | 8 | ||||
-rw-r--r-- | src/htmlgen.h | 2 | ||||
-rw-r--r-- | src/latexgen.cpp | 12 | ||||
-rw-r--r-- | src/latexgen.h | 2 | ||||
-rw-r--r-- | src/mangen.h | 2 | ||||
-rw-r--r-- | src/memberdef.cpp | 28 | ||||
-rw-r--r-- | src/memberdef.h | 1 | ||||
-rw-r--r-- | src/memberlist.cpp | 24 | ||||
-rw-r--r-- | src/outputgen.h | 2 | ||||
-rw-r--r-- | src/outputlist.h | 6 | ||||
-rw-r--r-- | src/pre.l | 63 | ||||
-rw-r--r-- | src/rtfgen.h | 2 | ||||
-rw-r--r-- | src/scanner.l | 11 | ||||
-rw-r--r-- | src/translator_en.h | 2 | ||||
-rw-r--r-- | src/util.cpp | 87 | ||||
-rw-r--r-- | src/util.h | 1 | ||||
-rw-r--r-- | src/xmlgen.cpp | 106 |
26 files changed, 516 insertions, 212 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp index 54f78e4..cb453ec 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -2264,7 +2264,7 @@ bool ClassDef::isReference() const { if (m_templateMaster) { - return m_templateMaster->getReference(); + return m_templateMaster->isReference(); } else { @@ -127,6 +127,7 @@ static int g_bodyCurlyCount; static ClassDef * g_classVar; static QCString g_saveName; static QCString g_saveType; +static int g_memCallContext; /*! add class/namespace name s to the scope */ static void pushScope(const char *s) @@ -196,6 +197,7 @@ static void startCodeLine() lineAnchor.sprintf("l%05d",g_yyLineNr); Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); + g_code->startLineNumber(); if (!g_includeCodeFragment && d && d->isLinkableInProject()) { g_currentDefinition = d; @@ -211,13 +213,12 @@ static void startCodeLine() g_code->writeCodeLink(d->getReference(),d->getOutputFileBase(), anchor,lineNumber); g_code->endCodeAnchor(); - g_code->codify(" "); } else { g_code->codify(lineNumber); - g_code->codify(" "); } + g_code->endLineNumber(); } g_code->startCodeLine(); if (g_currentFontClass) @@ -352,12 +353,14 @@ static void addParameter() { g_cvd.name=g_parmName.copy().simplifyWhiteSpace(); g_cvd.type=g_parmType.copy().simplifyWhiteSpace(); + //printf("searching for parameter `%s' `%s'\n",g_cvd.type.data(),g_cvd.name.data()); if (g_cvd.type.isEmpty()) { return; } else { + if (g_cvd.type.left(7)=="struct ") g_cvd.type=g_cvd.type.right(g_cvd.type.length()-7); int i; if ((getResolvedClass(g_currentDefinition,g_cvd.type)) || (g_codeClassDict[g_cvd.type])) { @@ -375,6 +378,10 @@ static void addParameter() g_codeParmList.append(new CodeVarDef(g_cvd)); } } + else + { + //printf("parameter `%s' `%s' not found!\n",g_cvd.type.data(),g_cvd.name.data()); + } //printf("g_codeParmList.count()=%d\n",g_codeParmList.count()); } } @@ -440,6 +447,21 @@ static void generateClassLink(OutputDocInterface &ol,char *clName,int *clNameLen } else { + MemberName *mn; + if (cd==0 && (mn=Doxygen::functionNameDict[clName])) + { + if (mn->count()==1) + { + MemberDef *md=mn->getFirst(); + Definition *d=md->getNamespaceDef(); + if (d==0) d=md->getFileDef(); + if (d && md->isLinkable()) + { + writeMultiLineCodeLink(ol,d->getReference(),d->getOutputFileBase(),md->anchor(),clName); + return; + } + } + } codifyLines(clName); if (clNameLen) *clNameLen=className.length()-1; } @@ -466,10 +488,12 @@ static ClassDef *stripClassName(const char *s) } if (cd) { + //printf("stripClassName(%s)=%s\n",s,cd->name().data()); return cd; } p=i+l; } + //printf("stripClassName(%s)=<null>\n",s); return 0; } @@ -578,7 +602,10 @@ static void generateMemberLink(OutputDocInterface &ol,const char *varName, //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n", // varName,memName,g_classScope.data()); CodeVarDef *cvd=g_codeParmList.last(); - while (cvd && cvd->name!=varName) cvd=g_codeParmList.prev(); + while (cvd && cvd->name!=varName) + { + cvd=g_codeParmList.prev(); + } if (!cvd) { cvd=g_codeVarList.last(); @@ -813,6 +840,7 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" %x MemberCall2 %x SkipInits %x ClassName +%x ClassVar %x Bases %x SkipSharp %x ReadInclude @@ -899,12 +927,12 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" g_insideBody=FALSE; } } -<ClassName>";" { +<ClassName,ClassVar>";" { g_code->codify(yytext); g_searchingForBody=FALSE; BEGIN( Body ); } -<ClassName>[*&]+ { +<ClassName,ClassVar>[*&]+ { addType(); g_code->codify(yytext); } @@ -912,12 +940,19 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" g_ccd.name=yytext; addType(); generateClassLink(*g_code,yytext); + BEGIN( ClassVar ); } -<ClassName>[ \t\n]*":"[ \t\n]* { +<ClassVar>{ID} { + g_type = g_ccd.name.copy(); + g_name = yytext; + addVariable(); + g_code->codify(yytext); + } +<ClassName,ClassVar>[ \t\n]*":"[ \t\n]* { codifyLines(yytext); BEGIN( Bases ); } -<Bases,ClassName>[ \t]*"{"[ \t]* { +<Bases,ClassName,ClassVar>[ \t]*"{"[ \t]* { g_code->codify(yytext); g_curlyCount++; g_inClass=TRUE; @@ -1038,7 +1073,7 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" addType(); g_name+=yytext; } -<Body>{SCOPENAME}{B}*"<"[^\n\/\{\"\>]*">"/{B}* { // A<T> *pt; +<Body>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"/{B}* { // A<T> *pt; generateClassLink(*g_code,yytext); addType(); g_name+=yytext; @@ -1048,19 +1083,18 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" addType(); g_name+=yytext; } -<Body>"("{B}*"*"{B}*{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() - QCString text=yytext; - int s=0; - while (s<yyleng && (text.at(s)=='(' || isspace(text.at(s)))) s++; - int e=yyleng-1; - while (e>=0 && (text.at(e)==')' || isspace(yytext[e]))) e--; - QCString varname = text.mid(s+1,e-s); - QCString tmp=varname.copy(); - g_code->codify(text.left(s+1)); - generateClassLink(*g_code,tmp.data()); - g_code->codify(text.right(yyleng-e-1)); +<Body>"("{B}*("*"{B}*)*{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() + g_code->codify(yytext); + int s=0;while (!isId(yytext[s])) s++; + int e=yyleng-1;while (!isId(yytext[e])) e--; + QCString varname = ((QCString)yytext).mid(s,e-s+1); + //QCString text=yytext; + //QCString tmp=varname.copy(); + //g_code->codify(text.left(s+1)); + //generateClassLink(*g_code,tmp.data()); + //g_code->codify(text.right(yyleng-e-1)); addType(); - g_name+=varname; + g_name=varname; } <Body>{SCOPETNAME}/{B}*"(" { // a() or c::a() or t<A,B>::a() addType(); @@ -1119,12 +1153,14 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" <Body>"this->" { g_code->codify(yytext); } <Body>"."|"->" { g_code->codify(yytext); + g_memCallContext = YY_START; BEGIN( MemberCall ); } <MemberCall>{SCOPETNAME}/{B}*"(" { if (!g_name.isEmpty()) { generateMemberLink(*g_code,g_name,yytext); + g_name=yytext; } else if (g_classVar) { @@ -1133,20 +1169,52 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" g_code->codify(yytext); } g_classVar=0; + g_name.resize(0); } else { g_code->codify(yytext); + g_name.resize(0); } - g_name.resize(0);g_type.resize(0); + g_type.resize(0); g_bracketCount=0; - BEGIN(FuncCall); + if (g_memCallContext==Body) + { + BEGIN(FuncCall); + } + else + { + BEGIN(g_memCallContext); + } + } +<MemberCall>{SCOPENAME}/{B}* { + if (!g_name.isEmpty()) + { + generateMemberLink(*g_code,g_name,yytext); + g_name=yytext; + } + else if (g_classVar) + { + if (!generateClassMemberLink(*g_code,g_classVar,yytext)) + { + g_code->codify(yytext); + } + g_classVar=0; + g_name.resize(0); + } + else + { + g_code->codify(yytext); + g_name.resize(0); + } + g_type.resize(0); + BEGIN(g_memCallContext); } <MemberCall>[^a-z_A-Z0-9(\n] { g_code->codify(yytext); g_type.resize(0); g_name.resize(0); - BEGIN(Body); + BEGIN(g_memCallContext); } <Body>[,=;\[] { g_code->codify(yytext); @@ -1211,9 +1279,11 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" <MemberCall2,FuncCall>")" { g_code->codify(yytext); if (--g_bracketCount<=0) - g_name.resize(0);g_args.resize(0); - g_parmType.resize(0);g_parmName.resize(0); - BEGIN( Body ); + { + g_name.resize(0);g_args.resize(0); + g_parmType.resize(0);g_parmName.resize(0); + BEGIN( Body ); + } } <MemberCall2,FuncCall>")"[ \t\n]*[;:] { codifyLines(yytext); @@ -1295,7 +1365,14 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" } <FuncCall>([a-z_A-Z][a-z_A-Z0-9]*)/("."|"->") { g_code->codify(yytext); - g_args=yytext; + g_name=yytext; + BEGIN( MemberCall2 ); + } +<FuncCall,MemberCall2>("("{B}*("*"{B}*)*[a-z_A-Z][a-z_A-Z0-9]*{B}*")"{B}*)/("."|"->") { + g_code->codify(yytext); + int s=0;while (!isId(yytext[s])) s++; + int e=yyleng-1;while (!isId(yytext[e])) e--; + g_name=((QCString)yytext).mid(s,e-s+1); BEGIN( MemberCall2 ); } <MemberCall2>([a-z_A-Z][a-z_A-Z0-9]*)/([ \t\n]*"(") { @@ -1308,8 +1385,14 @@ TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"short"|"signed"|"unsigned" } <MemberCall2>([a-z_A-Z][a-z_A-Z0-9]*)/([ \t\n]*("."|"->")) { g_code->codify(yytext); - g_args=yytext; + g_name=yytext; + BEGIN( MemberCall2 ); } +<MemberCall2>"->"|"." { + g_code->codify(yytext); + g_memCallContext = YY_START; + BEGIN( MemberCall ); + } <SkipComment>"//" { g_code->codify(yytext); } diff --git a/src/config.l b/src/config.l index 6725e9d..006bd7e 100644 --- a/src/config.l +++ b/src/config.l @@ -1979,6 +1979,15 @@ void Config::create() "Use the PREDEFINED tag if you want to use a different macro definition. \n" ); cl->addDependency("ENABLE_PREPROCESSING"); + cb = addBool( + "SKIP_FUNCTION_MACROS", + "If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then \n" + "doxygen's preprocessor will remove all function-like macros that are alone \n" + "on a line and do not end with a semicolon. Such function macros are typically \n" + "used for boiler-plate code, and will confuse the parser if not removed. \n", + TRUE + ); + cb->addDependency("ENABLE_PREPROCESSING"); //----------------------------------------------------------------------------------------------- addInfo( "External","Configuration::addtions related to external references "); //----------------------------------------------------------------------------------------------- @@ -838,7 +838,7 @@ static void writeDotFile(const char *fileName, const char *captionText) static int yyread(char *buf,int max_size) { int c=0; - while( c < max_size && inputString[inputPosition] ) + while ( c < max_size && inputString[inputPosition] ) { *buf = inputString[inputPosition++] ; //printf("%d (%c)\n",*buf,*buf); diff --git a/src/dot.cpp b/src/dot.cpp index e9b739b..4e43b2d 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -428,6 +428,68 @@ void DotNode::write(QTextStream &t, } } +void DotNode::writeXML(QTextStream &t) +{ + t << " <node id=\"" << m_number << "\">" << endl; + t << " <label>" << m_label << "</label>" << endl; + if (!m_url.isEmpty()) + { + QCString url(m_url); + char *refPtr = url.data(); + char *urlPtr = strchr(url.data(),'$'); + if (urlPtr) + { + *urlPtr++='\0'; + t << " <link id=\"" << urlPtr << "\""; + if (*refPtr!='\0') + { + t << " external=\"" << refPtr << "\""; + } + t << "/>" << endl; + } + } + if (m_children) + { + QListIterator<DotNode> nli(*m_children); + QListIterator<EdgeInfo> eli(*m_edgeInfo); + DotNode *childNode; + EdgeInfo *edgeInfo; + for (;(childNode=nli.current());++nli,++eli) + { + edgeInfo=eli.current(); + t << " <childnode id=\"" << childNode->m_number << "\" relation=\""; + switch(edgeInfo->m_color) + { + case EdgeInfo::Blue: t << "public-inheritance"; break; + case EdgeInfo::Green: t << "protected-inheritance"; break; + case EdgeInfo::Red: t << "private-inheritance"; break; + case EdgeInfo::Purple: t << "usage"; break; + case EdgeInfo::Orange: t << "template-instance"; break; + case EdgeInfo::Grey: ASSERT(0); break; + } + t << "\">" << endl; + if (!edgeInfo->m_label.isEmpty()) + { + int p=0; + int ni; + while ((ni=edgeInfo->m_label.find("\\n",p))!=-1) + { + t << " <edgelabel>" + << edgeInfo->m_label.mid(p,ni-p) + << "</edgelabel>" << endl; + p=ni+2; + } + t << " <edgelabel>" + << edgeInfo->m_label.right(edgeInfo->m_label.length()-p) + << "</edgelabel>" << endl; + } + t << " </childnode>" << endl; + } + } + t << " </node>" << endl; +} + + void DotNode::clearWriteFlag() { m_written=FALSE; @@ -555,18 +617,6 @@ void DotGfxHierarchyTable::writeGraph(QTextStream &out,const char *path) { 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"; @@ -604,9 +654,10 @@ void DotGfxHierarchyTable::writeGraph(QTextStream &out,const char *path) out << "</table>" << endl; return; } + QCString mapLabel = convertNameToFile(n->m_label); out << "<tr><td><img src=\"" << gifName << "\" border=\"0\" usemap=\"#" - << n->m_label << "_map\"></td></tr>" << endl; - out << "<map name=\"" << n->m_label << "_map\">" << endl; + << mapLabel << "_map\"></td></tr>" << endl; + out << "<map name=\"" << mapLabel << "_map\">" << endl; convertMapFile(out,mapName); out << "</map>" << endl; if (Config_getBool("DOT_CLEANUP")) thisDir.remove(dotName); @@ -1181,8 +1232,9 @@ QCString DotClassGraph::writeGraph(QTextStream &out, QDir::setCurrent(oldDir); return baseName; } + QCString mapLabel = convertNameToFile(m_startNode->m_label+"_"+mapName); out << "<p><center><img src=\"" << baseName << ".gif\" border=\"0\" usemap=\"#" - << m_startNode->m_label << "_" << mapName << "\" alt=\""; + << mapLabel << "\" alt=\""; switch (m_graphType) { case Implementation: @@ -1196,7 +1248,7 @@ QCString DotClassGraph::writeGraph(QTextStream &out, break; } out << "\"></center>" << endl; - out << "<map name=\"" << m_startNode->m_label << "_" << mapName << "\">" << endl; + out << "<map name=\"" << mapLabel << "\">" << endl; convertMapFile(out,baseName+".map"); out << "</map>" << endl; thisDir.remove(baseName+".map"); @@ -1249,6 +1301,18 @@ QCString DotClassGraph::writeGraph(QTextStream &out, //-------------------------------------------------------------------- +void DotClassGraph::writeXML(QTextStream &t) +{ + QDictIterator<DotNode> dni(*m_usedNodes); + DotNode *node; + for (;(node=dni.current());++dni) + { + node->writeXML(t); + } +} + +//-------------------------------------------------------------------- + int DotInclDepGraph::m_curNodeNumber; void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd,int distance) @@ -76,6 +76,7 @@ class DotNode int maxDistance=1000,bool backArrows=TRUE); int m_subgraphId; void clearWriteFlag(); + void writeXML(QTextStream &t); private: void colorConnectedNodes(int curColor); @@ -86,7 +87,7 @@ class DotNode const DotNode *findDocNode() const; // only works for acyclic graphs! int m_number; QCString m_label; //!< label text - QCString m_url; //!< url of the node (format: remove$local) + QCString m_url; //!< url of the node (format: remote$local) QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows) QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows) QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child @@ -123,6 +124,8 @@ class DotClassGraph bool isTrivial() const; QCString writeGraph(QTextStream &t,GraphOutputFormat f,const char *path, bool TBRank=TRUE,bool imageMap=TRUE); + + void writeXML(QTextStream &t); QCString diskName() const; private: diff --git a/src/doxygen.cpp b/src/doxygen.cpp index f19f411..d6c5911 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -1689,13 +1689,26 @@ void buildVarList(Entry *root) QCString type=root->type.stripWhiteSpace(); ClassDef *cd=0; - if (root->name.findRev("::")!=-1) goto nextMember; + if (root->name.findRev("::")!=-1) + { + if (root->type=="friend class" || root->type=="friend struct" || + root->type=="friend union") + { + cd=getClass(scope); + if (cd) + { + addVariableToClass(root,cd,MemberDef::Friend,scope, + root->name,FALSE,0,0,Public); + } + } + goto nextMember; /* skip this member, because it is a * static variable definition (always?), which will be * found in a class scope as well, but then we know the * correct protection level, so only then it will be * inserted in the correct list! */ + } if (type=="@") mtype=MemberDef::EnumValue; @@ -1708,6 +1721,7 @@ void buildVarList(Entry *root) else mtype=MemberDef::Variable; + QCString classScope=stripAnonymousNamespaceScope(scope); classScope=stripTemplateSpecifiersFromScope(classScope,FALSE); QCString annScopePrefix=scope.left(scope.length()-classScope.length()); @@ -1780,7 +1794,7 @@ nextMember: // Searches the Entry tree for Function sections. // If found they are stored in their class or in the global list. -static void buildMemberList(Entry *root) +static void buildFunctionList(Entry *root) { if (root->section==Entry::FUNCTION_SEC) { @@ -2205,7 +2219,7 @@ static void buildMemberList(Entry *root) Entry *e; for (;(e=eli.current());++eli) { - buildMemberList(e); + buildFunctionList(e); } } @@ -2467,7 +2481,6 @@ static void findUsedClassesForClass(Entry *root, QDict<int> *templateNames=0 ) { - //if (masterCd->visited) return; masterCd->visited=TRUE; ArgumentList *formalArgs = masterCd->templateArguments(); MemberNameInfoSDict::Iterator mnili(*masterCd->memberNameInfoSDict()); @@ -2490,7 +2503,7 @@ static void findUsedClassesForClass(Entry *root, { type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs); } - //printf("extractClassNameFromType(%s)\n",type.data()); + //printf("findUsedClassesForClass(%s)=%s\n",masterCd->name().data(),type.data()); while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec)) { QCString typeName = resolveTypeDef(masterCd,usedClassName); @@ -2577,6 +2590,20 @@ static void findUsedClassesForClass(Entry *root, templateNames=0; } } + if (!found && !type.isEmpty()) // used class is not documented in any scope + { + ClassDef *usedCd = Doxygen::hiddenClasses.find(type); + if (usedCd==0) + { + Debug::print(Debug::Classes,0," New undocumented used class `%s'\n", type.data()); + usedCd = new ClassDef( + masterCd->getDefFileName(),masterCd->getDefLine(), + type,ClassDef::Class); + Doxygen::hiddenClasses.inSort(type,usedCd); + } + if (isArtificial) usedCd->setClassIsArtificial(); + instanceCd->addUsedClass(usedCd,md->name()); + } } } } @@ -2897,9 +2924,9 @@ static bool findClassRelation( } } bool isATemplateArgument = templateNames!=0 && templateNames->find(bi->name)!=0; - if (!isATemplateArgument && found) + if (/*!isATemplateArgument &&*/ found) { - Debug::print(Debug::Classes,0," Documented base class `%s' templSpec=%s\n",bi->name.data(),templSpec.data()); + Debug::print(Debug::Classes,0," Documented class `%s' templSpec=%s\n",bi->name.data(),templSpec.data()); // add base class to this class // if templSpec is not empty then we should "instantiate" @@ -2956,19 +2983,6 @@ static bool findClassRelation( baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); // the undocumented base was found in this file baseClass->insertUsedFile(root->fileName); - // is this an inherited template argument? - //printf("%s->setIsTemplateBaseClass(%d)\n",baseClass->name().data(),isTemplBaseClass); - //if (isATemplateArgument) - //{ - // baseClass->setIsTemplateBaseClass(*templateNames->find(bi->name)); - //} - // add class to the list - //if (!isATemplateArgument) - //{ - //} - //else - //{ - //} return TRUE; } else @@ -3370,8 +3384,6 @@ static void addTodoTestBugReferences() addFileMemberTodoTestBugReferences(0); } - - //---------------------------------------------------------------------- // Copy the documentation in entry `root' to member definition `md' and // set the function declaration of the member to `funcDecl'. If the boolean @@ -3828,18 +3840,6 @@ static void findMember(Entry *root, } } while (!done); - if (isFriend) - { - if (funcDecl.left(6)=="class ") - { - funcDecl=funcDecl.right(funcDecl.length()-6); - } - else if (funcDecl.left(7)=="struct ") - { - funcDecl=funcDecl.right(funcDecl.length()-7); - } - } - // delete any ; from the function declaration int sep; while ((sep=funcDecl.find(';'))!=-1) @@ -3857,12 +3857,27 @@ static void findMember(Entry *root, ":: ","::" ), " ::","::" - ); + ).stripWhiteSpace(); - // extract information from the declarations - parseFuncDecl(funcDecl,scopeName,funcType,funcName, + //printf("funcDecl=`%s'\n",funcDecl.data()); + if (isFriend && funcDecl.left(6)=="class ") + { + //printf("friend class\n"); + funcDecl=funcDecl.right(funcDecl.length()-6); + funcName = funcDecl.copy(); + } + else if (isFriend && funcDecl.left(7)=="struct ") + { + funcDecl=funcDecl.right(funcDecl.length()-7); + funcName = funcDecl.copy(); + } + else + { + // extract information from the declarations + parseFuncDecl(funcDecl,scopeName,funcType,funcName, funcArgs,funcTempList,exceptions ); + } //printf("scopeName=`%s' funcType=`%s' funcName=`%s'\n", // scopeName.data(),funcType.data(),funcName.data()); @@ -4473,8 +4488,17 @@ static void findMemberDocumentation(Entry *root) // root->name.data(),root->args.data(),root->exception.data()); //if (root->relates.length()) printf(" Relates %s\n",root->relates.data()); //printf("Inside=%s\n Relates=%s\n",root->inside.data(),root->relates.data()); - - if (!root->type.isEmpty()) + if (root->type=="friend class" || root->type=="friend struct" || + root->type=="friend union") + { + findMember(root, + root->type+" "+ + root->name, + root->relates, + FALSE,FALSE); + + } + else if (!root->type.isEmpty()) { findMember(root, root->type+" "+ @@ -6098,15 +6122,20 @@ static void copyAndFilterFile(const char *fileName,BufStr &dest) pclose(f); } // filter unwanted bytes from the resulting data - uchar *p=(uchar *)dest.data()+oldPos; uchar conv[256]; int i; for (i=0;i<256;i++) conv[i]=i; conv[0x06]=0x20; // replace the offending characters with spaces conv[0x00]=0x20; // remove any special markers from the input + uchar *p=(uchar *)dest.data()+oldPos; for (i=0;i<size;i++,p++) *p=conv[*p]; - // adjust pointer + // and translate CR's + int newSize=filterCRLF(dest.data()+oldPos,size); + if (newSize!=size) // we removed chars + { + dest.resize(newSize); // resize the array + } } //---------------------------------------------------------------------------- @@ -7054,7 +7083,7 @@ void parseInput() buildVarList(root); msg("Building member list...\n"); // using class info only ! - buildMemberList(root); + buildFunctionList(root); transferFunctionDocumentation(); msg("Searching for friends...\n"); diff --git a/src/doxytag.l b/src/doxytag.l index 95e7cbe..b8f1279 100644 --- a/src/doxytag.l +++ b/src/doxytag.l @@ -220,6 +220,7 @@ QCString unhtmlify(const char *str) <Start>^"<li>" { BEGIN( SearchClassFile ); } +<Start>^"<td"[^\n]*"<h1 align=center>" | // Qt-3.x.x+ <Start>^"<h1 align=center>" { // Qt variant BEGIN( ReadClassName ); } diff --git a/src/entry.h b/src/entry.h index 146ce57..3646d40 100644 --- a/src/entry.h +++ b/src/entry.h @@ -216,7 +216,7 @@ class Entry MEMBERGRP_SEC = 0x01300000, USINGDECL_SEC = 0x01400000, PACKAGE_SEC = 0x01500000, - PACKAGEDOC_SEC = 0x01600000, + PACKAGEDOC_SEC = 0x01600000 }; enum MemberSpecifier { diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 31c24fc..2320473 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -831,7 +831,7 @@ void HtmlGenerator::endAlphabeticalIndexList() void HtmlGenerator::writeIndexHeading(const char *s) { t << "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td><div class=\"ah\"> " << s - << " </td</tr></table>"; + << " </td></tr></table>"; } void HtmlGenerator::startImage(const char *name,const char *,bool hasCaption) @@ -940,7 +940,7 @@ void HtmlGenerator::startParameterType(bool first) if (first) { DBG_HTML(t << "<!-- startFirstParameterType -->" << endl;) - t << " <td class=\"md\">"; + t << " <td class=\"md\" nowrap>"; } else { @@ -948,14 +948,14 @@ void HtmlGenerator::startParameterType(bool first) t << " <tr>" << endl; t << " <td></td>" << endl; t << " <td></td>" << endl; - t << " <td class=\"md\">"; + t << " <td class=\"md\" nowrap>"; } } void HtmlGenerator::endParameterType() { DBG_HTML(t << "<!-- endParameterType -->" << endl;) - t << "</td>" << endl; + t << " </td>" << endl; } void HtmlGenerator::startParameterName(bool oneArgOnly) diff --git a/src/htmlgen.h b/src/htmlgen.h index cbc40f1..caed87f 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -120,6 +120,8 @@ class HtmlGenerator : public OutputGenerator void endCodeFragment() { t << "</pre></div>"; } void startPreFragment() { t << "<pre>"; } void endPreFragment() { t << "</pre>"; } + void startLineNumber() {} + void endLineNumber() { t << " "; } void startCodeLine() { col=0; } void endCodeLine() { codify("\n"); } //void writeBoldString(const char *text) diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 7e072ac..7bdfbdf 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -1529,9 +1529,14 @@ void LatexGenerator::endMemberList() void LatexGenerator::startImage(const char *name,const char *size,bool hasCaption) { if (hasCaption) - t << "\\begin{figure}[H]" << endl; + { + t << "\\begin{figure}[h]" << endl; + t << "\\begin{center}" << endl; + } else + { t << "\\mbox{"; + } QCString gfxName = name; if (gfxName.right(4)==".eps") gfxName.left(gfxName.length()-4); // "\\epsfig{file=" << name; @@ -1539,9 +1544,13 @@ void LatexGenerator::startImage(const char *name,const char *size,bool hasCaptio if (size) t << "[" << size << "]"; t << "{" << gfxName << "}"; if (hasCaption) + { t << "\\caption{"; + } else + { t << "}" << endl; + } } void LatexGenerator::endImage(bool hasCaption) @@ -1549,6 +1558,7 @@ void LatexGenerator::endImage(bool hasCaption) if (hasCaption) { t << "}" << endl; + t << "\\end{center}" << endl; t << "\\end{figure}" << endl; } } diff --git a/src/latexgen.h b/src/latexgen.h index 3b09340..bf3e530 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -118,6 +118,8 @@ class LatexGenerator : public OutputGenerator void endPreFragment() { t << "\\end{alltt}\\normalsize " << endl; insidePre=FALSE; } + void startLineNumber() {} + void endLineNumber() { t << " "; } void startCodeLine() { col=0; } void endCodeLine() { codify("\n"); } //void writeBoldString(const char *text) diff --git a/src/mangen.h b/src/mangen.h index 5ce5a7c..e87cbc7 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -110,6 +110,8 @@ class ManGenerator : public OutputGenerator void endCodeFragment(); void startPreFragment() { startCodeFragment(); } void endPreFragment() { endCodeFragment(); } + void startLineNumber() {} + void endLineNumber() { t << " "; } void startCodeLine() {} void endCodeLine() { codify("\n"); col=0; } //void writeBoldString(const char *text) diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 8aaa7cc..afdcab6 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -558,7 +558,8 @@ bool MemberDef::isBriefSectionVisible() const // only include members is the are documented or // HIDE_UNDOC_MEMBERS is NO in the config file bool visibleIfDocumented = (!Config_getBool("HIDE_UNDOC_MEMBERS") || - hasDocumentation() + hasDocumentation() || + isDocumentedFriendClass() ); // hide members with no detailed description and brief descriptions @@ -767,7 +768,7 @@ void MemberDef::writeDeclaration(OutputList &ol, if (!name().isEmpty() && name().at(0)!='@') { //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable()); - if (/*d->isLinkable() &&*/ isLinkable()) + if (isLinkable()) { if (annMemb) { @@ -786,7 +787,14 @@ void MemberDef::writeDeclaration(OutputList &ol, writeLink(ol,cd,nd,fd,gd); } } - else // there is a brief member description and brief member + else if (isDocumentedFriendClass()) + // if the member is an undocumented friend declaration for some class, + // then maybe we can link to the class + { + writeLink(ol,getClass(name()),0,0,0); + } + else + // there is a brief member description and brief member // descriptions are enabled or there is no detailed description. { if (annMemb) annMemb->annUsed=annUsed=TRUE; @@ -1479,7 +1487,8 @@ void MemberDef::warnIfUndocumented() else t="file", d=fd; - if (d && d->isLinkable() && !isLinkable() && name().find('@')==-1) + if (d && d->isLinkable() && !isLinkable() && !isDocumentedFriendClass() + && name().find('@')==-1) warn_undoc(m_defFileName,m_defLine,"Warning: Member %s of %s %s is not documented.", name().data(),t,d->name().data()); } @@ -1520,11 +1529,20 @@ void MemberDef::setEnumDecl(OutputList &ed) *enumDeclList+=ed; } +bool MemberDef::isDocumentedFriendClass() const +{ + ClassDef *fcd=0; + return (isFriend() && + (type=="friend class" || type=="friend struct" || + type=="friend union") && + (fcd=getClass(name())) && fcd->isLinkable()); +} + bool MemberDef::hasDocumentation() const { return Definition::hasDocumentation() || (mtype==Enumeration && docEnumValues) || // has enum values - (argList!=0 && argList->hasDocumentation()); + (argList!=0 && argList->hasDocumentation()); // has doc arguments } void MemberDef::setMemberGroup(MemberGroup *grp) diff --git a/src/memberdef.h b/src/memberdef.h index 9b9280e..4af6f66 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -129,6 +129,7 @@ class MemberDef : public Definition bool isBriefSectionVisible() const; bool isDetailedSectionVisible(bool inGroup=FALSE) const; bool isDetailedSectionLinkable() const; + bool isDocumentedFriendClass() const; // set functions void setMemberType(MemberType t) { mtype=t; } diff --git a/src/memberlist.cpp b/src/memberlist.cpp index c591ffc..bc9195b 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -250,20 +250,20 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool fmdVisible = fmd->isBriefSectionVisible(); while (fmd) { - /* in html we start a new line after a number of items */ - if (numVisibleEnumValues>enumValuesPerLine - && (enumMemCount%enumValuesPerLine)==0 - ) - { - typeDecl.pushGeneratorState(); - typeDecl.disableAllBut(OutputGenerator::Html); - typeDecl.lineBreak(); - typeDecl.writeString(" "); - typeDecl.popGeneratorState(); - } - if (fmdVisible) { + /* in html we start a new line after a number of items */ + if (numVisibleEnumValues>enumValuesPerLine + && (enumMemCount%enumValuesPerLine)==0 + ) + { + typeDecl.pushGeneratorState(); + typeDecl.disableAllBut(OutputGenerator::Html); + typeDecl.lineBreak(); + typeDecl.writeString(" "); + typeDecl.popGeneratorState(); + } + if (fmd->hasDocumentation()) // enum value has docs { if (!Config_getString("GENERATE_TAGFILE").isEmpty()) diff --git a/src/outputgen.h b/src/outputgen.h index 4b60bbd..15cab68 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -248,6 +248,8 @@ class BaseOutputDocInterface virtual void endPageRef(const char *,const char *) = 0; + virtual void startLineNumber() = 0; + virtual void endLineNumber() = 0; virtual void startCodeLine() = 0; virtual void endCodeLine() = 0; virtual void startCodeAnchor(const char *label) = 0; diff --git a/src/outputlist.h b/src/outputlist.h index 3cc0b44..8583e56 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -206,8 +206,10 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startCodeLine); } void endCodeLine() { forall(&OutputGenerator::endCodeLine); } - //void writeBoldString(const char *text) - //{ forall(&OutputGenerator::writeBoldString,text); } + void startLineNumber() + { forall(&OutputGenerator::startLineNumber); } + void endLineNumber() + { forall(&OutputGenerator::endLineNumber); } void startEmphasis() { forall(&OutputGenerator::startEmphasis); } void endEmphasis() @@ -977,6 +977,22 @@ static void readIncludeFile(const QCString &inc) /* ----------------------------------------------------------------- */ +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); + +static int yyread(char *buf,int max_size) +{ + int len = fread( buf, 1, max_size, yyin ); + if (len==0 && ferror( yyin )) + { + yy_fatal_error( "input in flex scanner failed" ); + return len; + } + return filterCRLF(buf,len); +} + +/* ----------------------------------------------------------------- */ + %} ID [a-z_A-Z][a-z_A-Z0-9]* @@ -1018,30 +1034,39 @@ BN [ \t\r\n] <*>\x06 <*>\x00 <*>\r - /* -<Start>^{B}*([^ \t#\n\/][^\n]*)?"\n" { - //printf("%s line %d: %s",g_yyFileName.data(),g_yyLineNr,yytext); - if (g_includeStack.isEmpty()) - { - //preprocessedFile+=yytext; - //char *s=yytext,c; - //if (s) while ((c=*s++)) *dataPtr++=c; - g_outputBuf->addArray(yytext,yyleng); - } - g_yyLineNr++; - } - */ <Start>^{B}*"#" { BEGIN(Command); } <Start>^{B}*/[^#] { outputArray(yytext,yyleng); BEGIN(CopyLine); } - /* -<CopyLine>[^\n/]+ { - outputArray(yytext,yyleng); +<Start>^{B}*[_A-Z][_A-Z0-9]*"("[^\)\n]*")"{B}*\n { // function like macro + static bool skipFuncMacros = Config_getBool("SKIP_FUNCTION_MACROS"); + QCString name(yytext); + name=name.left(name.find('(')).stripWhiteSpace(); + + Define *def=0; + if (skipFuncMacros && + !( + (g_includeStack.isEmpty() || g_curlyCount>0) && + g_macroExpansion && + (def=g_fileDefineDict->find(name)) && + (!g_expandOnlyPredef || def->isPredefined) + ) + ) + { + outputChar('\n'); + g_yyLineNr++; + } + else // don't skip + { + int i; + for (i=yyleng-1;i>=0;i--) + { + unput(yytext[i]); + } + BEGIN(CopyLine); + } } - */ - <CopyLine>"{" { // count brackets inside the main file if (g_includeStack.isEmpty()) g_curlyCount++; @@ -1843,9 +1868,7 @@ void cleanupPreprocessor() void preprocessFile(const char *fileName,BufStr &output) { -//#if DUMP_OUTPUT uint orgOffset=output.curPos(); -//#endif g_macroExpansion = Config_getBool("MACRO_EXPANSION"); g_expandOnlyPredef = Config_getBool("EXPAND_ONLY_PREDEF"); diff --git a/src/rtfgen.h b/src/rtfgen.h index ce1b71d..5569328 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -110,6 +110,8 @@ class RTFGenerator : public OutputGenerator void endCodeFragment(); void startPreFragment() { startCodeFragment(); } void endPreFragment() { endCodeFragment(); } + void startLineNumber() {} + void endLineNumber() { t << " "; } void startCodeLine() { col=0; } void endCodeLine() { lineBreak(); } //void writeBoldString(const char *text) diff --git a/src/scanner.l b/src/scanner.l index 65e50b6..0088e9a 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -598,7 +598,6 @@ TITLE [tT][iI][tT][lL][eE] } BEGIN( FindMembers ); } -<*>\x0d <NextSemi>"{" { curlyCount=0; needsSemi = TRUE; @@ -733,7 +732,7 @@ TITLE [tT][iI][tT][lL][eE] current->argList->clear(); lineCount() ; } -<FindMembers>{BN}+ { +<FindMembers>{BN}{1,80} { lineCount(); } <FindMembers>{B}*"package"{BN}+ { // Java package @@ -1751,9 +1750,9 @@ TITLE [tT][iI][tT][lL][eE] //if (!current->name.isEmpty() && current->name[0]!='@' && // current->parent->section & Entry::COMPOUND_MASK) // varEntry->type+=current->parent->name+"::"; - //if (isTypedef) - //{ - // varEntry->type.prepend("typedef "); + if (isTypedef) + { + varEntry->type.prepend("typedef "); // //printf("current->name = %s %s\n",current->name.data(),msName.data()); // if (!current->name.isEmpty() && current->name.at(0)!='@') // { @@ -1762,7 +1761,7 @@ TITLE [tT][iI][tT][lL][eE] // if (current_root->section & Entry::SCOPE_MASK) scope=current_root->name; // Doxygen::typedefDict.insert(msName,new TypedefInfo(current->name,scope)); // } - //} + } varEntry->type+=current->name+msType; varEntry->fileName = yyFileName; varEntry->startLine = yyLineNr; diff --git a/src/translator_en.h b/src/translator_en.h index edffbb9..9e841e2 100644 --- a/src/translator_en.h +++ b/src/translator_en.h @@ -534,7 +534,7 @@ class TranslatorEnglish : public Translator */ virtual QCString trGeneratedAt(const char *date,const char *projName) { - QCString result=(QCString)"Generated at "+date; + QCString result=(QCString)"Generated on "+date; if (projName) result+=(QCString)" for "+projName; result+=(QCString)" by"; return result; diff --git a/src/util.cpp b/src/util.cpp index 95193f7..5f54a61 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -365,6 +365,7 @@ QCString resolveTypeDef(Definition *d,const QCString &name) //printf("resolveTypeDef(%s,%s)\n",d ? d->name().data() : "<none>",name.data()); QCString result; if (name.isEmpty()) return result; + Definition *mContext=d; MemberDef *md=0; while (mContext && md==0) @@ -409,26 +410,6 @@ QCString resolveTypeDef(Definition *d,const QCString &name) } return result; -#if 0 - QCString typeName; - if (!name.isEmpty()) - { - TypedefInfo *ti = Doxygen::typedefDict[name]; - if (ti) - { - int count=0; - typeName=ti->value; - TypedefInfo *newTi; - while ((newTi=Doxygen::typedefDict[typeName]) && count<10) - { - if (typeName==newTi->value) break; // prevent lock-up - typeName=newTi->value; - count++; - } - } - } - return typeName; -#endif } /*! Get a class definition given its name. @@ -472,16 +453,11 @@ ClassDef *getResolvedClass( QCString *pTemplSpec ) { - //printf("getResolvedClass(%s,%s)\n",scope ? scope->name().data() : "<none>", - // n); + //printf("getResolvedClass(%s,%s)\n",scope ? scope->name().data() : "<none>", n); QCString name = n; if (name.isEmpty()) return 0; if (scope==0) scope=Doxygen::globalScope; int i = name.findRev("::"); - //QCString subst = 0; - //if (i!=-1) subst = Doxygen::typedefDict[name.right(name.length()-i-2)]; - //if (subst==0) subst = Doxygen::typedefDict[name],i=-1; - //if (subst) // there is a typedef with this name QCString subst; if (i!=-1) { @@ -491,11 +467,17 @@ ClassDef *getResolvedClass( { subst = resolveTypeDef(scope,name); } + //printf(" typedef subst=`%s'\n",subst.data()); if (!subst.isEmpty()) { + // strip * and & from n + int ip=subst.length()-1; + while (subst.at(ip)=='*' || subst.at(ip)=='&' || subst.at(ip)==' ') ip--; + subst=subst.left(ip+1); + if (pIsTypeDef) *pIsTypeDef=TRUE; - //printf("getResolvedClass `%s'->`%s'\n",name.data(),subst->data()); + //printf(" getResolvedClass `%s'->`%s'\n",name.data(),subst.data()); if (subst==name) // avoid resolving typedef struct foo foo; { return Doxygen::classSDict.find(name); @@ -503,15 +485,24 @@ ClassDef *getResolvedClass( int count=0; // recursion detection guard QCString newSubst; QCString typeName = subst; + if (i!=-1) typeName.prepend(name.left(i)+"::"); while (!(newSubst=resolveTypeDef(scope,typeName)).isEmpty() && count<10) { if (typeName==newSubst) { - return Doxygen::classSDict.find(subst); // for breaking typedef struct A A; + ClassDef *cd = Doxygen::classSDict.find(subst); // for breaking typedef struct A A; + //printf(" getClass: exit `%s' %p\n",subst.data(),cd); + return cd; } subst=newSubst; + // strip * and & from n + int ip=subst.length()-1; + while (subst.at(ip)=='*' || subst.at(ip)=='&' || subst.at(ip)==' ') ip--; + subst=subst.left(ip+1); + //printf(" getResolvedClass `%s'->`%s'\n",name.data(),subst.data()); + typeName=newSubst; if (i!=-1) typeName.prepend(name.left(i)+"::"); count++; @@ -523,9 +514,9 @@ ClassDef *getResolvedClass( } else { - //printf("getClass: subst %s->%s\n",name.data(),typeName.data()); int i; ClassDef *cd = Doxygen::classSDict.find(typeName); + //printf(" getClass: subst %s->%s cd=%p\n",name.data(),typeName.data(),cd); if (cd==0 && (i=typeName.find('<'))>0) // try unspecialized version as well { if (pTemplSpec) *pTemplSpec = typeName.right(typeName.length()-i); @@ -899,8 +890,33 @@ void setAnchors(char id,MemberList *ml,int groupId) } //---------------------------------------------------------------------------- -// read a file with `name' to a string. +int filterCRLF(char *buf,int len) +{ + char *ps=buf; + char *pd=buf; + char c; + int i; + for (i=0;i<len;i++) + { + c=*ps++; + if (c=='\r') + { + if (*ps=='\n') ps++; // DOS: CR+LF -> LF + *pd++='\n'; // MAC: CR -> LF + } + else + { + *pd++=c; + } + } + return len+pd-ps; +} + +/*! reads a file with name \a name and returns it as a string. If \a filter + * is TRUE the file will be filtered by any user specified input filter. + * If \a name is "-" the string will be read from standard input. + */ QCString fileToString(const char *name,bool filter) { if (name==0 || name[0]==0) return 0; @@ -921,7 +937,7 @@ QCString fileToString(const char *name,bool filter) totalSize+=bSize; contents.resize(totalSize+bSize); } - totalSize+=size+2; + totalSize = filterCRLF(contents.data(),totalSize+size)+2; contents.resize(totalSize); contents.at(totalSize-2)='\n'; // to help the scanner contents.at(totalSize-1)='\0'; @@ -951,6 +967,11 @@ QCString fileToString(const char *name,bool filter) contents[fsize]='\n'; // to help the scanner contents[fsize+1]='\0'; f.close(); + int newSize = filterCRLF(contents.data(),fsize+2); + if (newSize!=fsize+2) + { + contents.resize(newSize); + } return contents; } } @@ -972,7 +993,7 @@ QCString fileToString(const char *name,bool filter) totalSize+=bSize; contents.resize(totalSize+bSize); } - totalSize+=size+2; + totalSize = filterCRLF(contents.data(),totalSize+size)+2; contents.resize(totalSize); contents.at(totalSize-2)='\n'; // to help the scanner contents.at(totalSize-1)='\0'; @@ -3212,7 +3233,7 @@ QCString substituteTemplateArgumentsInString( } else if (formArg->name==n && actArg==0 && !formArg->defval.isEmpty()) { - result += formArg->defval; + result += substituteTemplateArgumentsInString(formArg->defval,formalArgs,actualArgs); found=TRUE; } } @@ -164,6 +164,7 @@ QCString stripTemplateSpecifiersFromScope(const QCString &fullName, QCString resolveTypeDef(Definition *d,const QCString &name); QCString mergeScopes(const QCString &leftScope,const QCString &rightScope); int getScopeFragment(const QCString &s,int p,int *l); +int filterCRLF(char *buf,int len); #endif diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index f18c2f3..dfe19b9 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -28,12 +28,14 @@ #include "defargs.h" #include "outputgen.h" #include "doc.h" +#include "dot.h" +#include "code.h" #include <qdir.h> #include <qfile.h> #include <qtextstream.h> -static QCString sectionTypeToString(BaseOutputDocInterface::SectionTypes t) +QCString sectionTypeToString(BaseOutputDocInterface::SectionTypes t) { switch (t) { @@ -62,15 +64,19 @@ static QCString sectionTypeToString(BaseOutputDocInterface::SectionTypes t) return "illegal"; } -static inline void writeXMLString(QTextStream &t,const char *s) +inline void writeXMLString(QTextStream &t,const char *s) { t << convertToXML(s); } -static void writeXMLLink(QTextStream &t,const char *compoundId, +void writeXMLLink(QTextStream &t,const char *extRef,const char *compoundId, const char *anchorId,const char *text) { t << "<ref idref=\"" << compoundId << "\""; + if (extRef) + { + t << " external=\"" << extRef << "\""; + } if (anchorId) { t << " anchor=\"" << anchorId << "\""; @@ -93,10 +99,7 @@ class TextGeneratorXMLImpl : public TextGeneratorIntf const char *anchor,const char *text ) const { - if (extRef==0) - { writeXMLLink(m_t,file,anchor,text); } - else // external references are not supported for XML - { writeXMLString(m_t,text); } + writeXMLLink(m_t,extRef,file,anchor,text); } private: QTextStream &m_t; @@ -418,26 +421,12 @@ class XMLGenerator : public OutputDocInterface void writeObjectLink(const char *ref,const char *file, const char *anchor, const char *text) { - if (ref) // TODO: add support for external references - { - docify(text); - } - else - { - writeXMLLink(m_t,file,anchor,text); - } + writeXMLLink(m_t,ref,file,anchor,text); } void writeCodeLink(const char *ref,const char *file, const char *anchor,const char *text) { - if (ref) // TODO: add support for external references - { - docify(text); - } - else - { - writeXMLLink(m_t,file,anchor,text); - } + writeXMLLink(m_t,ref,file,anchor,text); } void startHtmlLink(const char *url) { @@ -628,14 +617,22 @@ class XMLGenerator : public OutputDocInterface void endPageRef(const char *,const char *) { } + void startLineNumber() + { + m_t << "<linenumber>"; + } + void endLineNumber() + { + m_t << "</linenumber>"; + } void startCodeLine() { startParMode(); - m_t << "<linenumber>"; // non DocBook + m_t << "<codeline>"; // non DocBook } void endCodeLine() { - m_t << "</linenumber>"; // non DocBook + m_t << "</codeline>" << endl; // non DocBook } void startCodeAnchor(const char *id) { @@ -740,6 +737,8 @@ class XMLGenerator : public OutputDocInterface ValStack<bool> m_inParStack; ValStack<bool> m_inListStack; bool m_inParamList; + + friend void writeXMLCodeBlock(QTextStream &t,FileDef *fd); }; void writeXMLDocBlock(QTextStream &t, @@ -762,6 +761,21 @@ void writeXMLDocBlock(QTextStream &t, delete xmlGen; } +void writeXMLCodeBlock(QTextStream &t,FileDef *fd) +{ + initParseCodeContext(); + XMLGenerator *xmlGen = new XMLGenerator; + xmlGen->m_inParStack.push(TRUE); + parseCode(*xmlGen, + 0, + fileToString(fd->absFilePath(),Config_getBool("FILTER_SOURCE_FILES")), + FALSE, + 0, + fd); + t << xmlGen->getContents(); + delete xmlGen; +} + void generateXMLForMember(MemberDef *md,QTextStream &t,Definition *def) @@ -952,19 +966,18 @@ void generateXMLClassSection(ClassDef *cd,QTextStream &t,MemberList *ml,const ch void generateXMLForClass(ClassDef *cd,QTextStream &t) { - // brief description - // detailed description - // template arguments - // include files - // inheritance diagram - // list of direct super classes - // list of direct sub classes - // collaboration diagram - // list of all members - // user defined member sections - // standard member sections - // detailed documentation - // detailed member documentation + // + brief description + // + detailed description + // - template arguments + // - include files + // + inheritance diagram + // + list of direct super classes + // + list of direct sub classes + // + collaboration diagram + // - list of all members + // + user defined member sections + // + standard member sections + // + detailed member documentation if (cd->name().find('@')!=-1) return; // skip anonymous compounds. if (cd->templateMaster()!=0) return; // skip generated template instances. @@ -1071,6 +1084,20 @@ void generateXMLForClass(ClassDef *cd,QTextStream &t) t << " <detaileddescription>" << endl; writeXMLDocBlock(t,cd->getDefFileName(),cd->getDefLine(),cd->name(),0,cd->documentation()); t << " </detaileddescription>" << endl; + DotClassGraph inheritanceGraph(cd,DotClassGraph::Inheritance); + if (!inheritanceGraph.isTrivial()) + { + t << " <inheritancegraph>" << endl; + inheritanceGraph.writeXML(t); + t << " </inheritancegraph>" << endl; + } + DotClassGraph collaborationGraph(cd,DotClassGraph::Implementation); + if (!collaborationGraph.isTrivial()) + { + t << " <collaborationgraph>" << endl; + collaborationGraph.writeXML(t); + t << " </collaborationgraph>" << endl; + } t << " </compounddef>" << endl; } @@ -1118,6 +1145,9 @@ void generateXMLForFile(FileDef *fd,QTextStream &t) t << " <detaileddescription>" << endl; writeXMLDocBlock(t,fd->getDefFileName(),fd->getDefLine(),0,0,fd->documentation()); t << " </detaileddescription>" << endl; + t << " <sourcecode>" << endl; + writeXMLCodeBlock(t,fd); + t << " </sourcecode>" << endl; t << " </compounddef>" << endl; } |