summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/classdef.cpp2
-rw-r--r--src/code.l139
-rw-r--r--src/config.l9
-rw-r--r--src/doc.l2
-rw-r--r--src/dot.cpp96
-rw-r--r--src/dot.h5
-rw-r--r--src/doxygen.cpp113
-rw-r--r--src/doxytag.l1
-rw-r--r--src/entry.h2
-rw-r--r--src/htmlgen.cpp8
-rw-r--r--src/htmlgen.h2
-rw-r--r--src/latexgen.cpp12
-rw-r--r--src/latexgen.h2
-rw-r--r--src/mangen.h2
-rw-r--r--src/memberdef.cpp28
-rw-r--r--src/memberdef.h1
-rw-r--r--src/memberlist.cpp24
-rw-r--r--src/outputgen.h2
-rw-r--r--src/outputlist.h6
-rw-r--r--src/pre.l63
-rw-r--r--src/rtfgen.h2
-rw-r--r--src/scanner.l11
-rw-r--r--src/translator_en.h2
-rw-r--r--src/util.cpp87
-rw-r--r--src/util.h1
-rw-r--r--src/xmlgen.cpp106
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
{
diff --git a/src/code.l b/src/code.l
index c07841b..39fc7d6 100644
--- a/src/code.l
+++ b/src/code.l
@@ -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 ");
//-----------------------------------------------------------------------------------------------
diff --git a/src/doc.l b/src/doc.l
index 59b714c..7868c9a 100644
--- a/src/doc.l
+++ b/src/doc.l
@@ -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)
diff --git a/src/dot.h b/src/dot.h
index 7539dbe..99a51be 100644
--- a/src/dot.h
+++ b/src/dot.h
@@ -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\">&nbsp;&nbsp;" << s
- << "&nbsp;&nbsp;</td</tr></table>";
+ << "&nbsp;&nbsp;</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 << "&nbsp;</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("&nbsp;&nbsp;");
- 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("&nbsp;&nbsp;");
+ 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()
diff --git a/src/pre.l b/src/pre.l
index 3832f27..40bb394 100644
--- a/src/pre.l
+++ b/src/pre.l
@@ -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;
}
}
diff --git a/src/util.h b/src/util.h
index c61bd33..b9a4bf1 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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;
}