From c8b3a0f8232656c1a11c185d595f19eb65c56c82 Mon Sep 17 00:00:00 2001
From: Dimitri van Heesch <dimitri@stack.nl>
Date: Mon, 27 Feb 2006 20:11:09 +0000
Subject: Release-1.4.6-20060227

---
 INSTALL                         |  4 +-
 README                          |  4 +-
 configure                       |  2 +-
 doc/Makefile.latex              |  6 ---
 doc/docblocks.doc               |  2 +-
 doc/doxygen.sty                 | 14 +++++++
 doc/doxygen_manual.tex          |  1 +
 doc/index.doc                   |  2 +-
 src/commentscan.l               | 36 ----------------
 src/doxygen.cpp                 | 16 +++++--
 src/htmlgen.cpp                 |  9 +++-
 src/latexdocvisitor.cpp         | 16 +++----
 src/latexgen.cpp                | 18 ++++----
 src/memberdef.cpp               |  2 +-
 src/perlmodgen.cpp              | 58 ++++++++++++++++++++++++-
 src/pyscanner.l                 | 18 +++++---
 src/scanner.l                   | 17 +++++---
 src/util.cpp                    | 93 ++++++++++++++++++++++++++---------------
 src/util.h                      |  2 +
 src/xmlgen.cpp                  |  2 +-
 tmake/lib/macosx-c++/tmake.conf |  4 +-
 21 files changed, 206 insertions(+), 120 deletions(-)

diff --git a/INSTALL b/INSTALL
index 160d550..a15915f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
-DOXYGEN Version 1.4.6-20060202
+DOXYGEN Version 1.4.6-20060227
 
 Please read the installation section of the manual 
 (http://www.doxygen.org/install.html) for instructions.
 
 --------
-Dimitri van Heesch (02 February 2006)
+Dimitri van Heesch (27 February 2006)
diff --git a/README b/README
index 8353851..23994a1 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-DOXYGEN Version 1.4.6_20060202
+DOXYGEN Version 1.4.6_20060227
 
 Please read INSTALL for compilation instructions.
 
@@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives.
 
 Enjoy,
 
-Dimitri van Heesch (dimitri@stack.nl) (02 February 2006)
+Dimitri van Heesch (dimitri@stack.nl) (27 February 2006)
diff --git a/configure b/configure
index 8fdc977..be9a96d 100755
--- a/configure
+++ b/configure
@@ -20,7 +20,7 @@ doxygen_version_minor=4
 doxygen_version_revision=6
 
 #NOTE: Setting version_mmn to "NO" will omit mmn info from the package.
-doxygen_version_mmn=20060202
+doxygen_version_mmn=20060227
 
 bin_dirs=`echo $PATH | sed -e "s/:/ /g"`
 
diff --git a/doc/Makefile.latex b/doc/Makefile.latex
index 8a47094..c460700 100644
--- a/doc/Makefile.latex
+++ b/doc/Makefile.latex
@@ -14,12 +14,6 @@
 
 all: doxygen_manual.pdf
 
-#doxygen_manual.pdf: doxygen_manual.ps
-#	ps2pdf doxygen_manual.ps doxygen_manual.pdf
-
-#doxygen_manual.ps: doxygen_manual.dvi
-#	dvips -o doxygen_manual.ps doxygen_manual.dvi
-
 doxygen_manual.pdf: doxygen_manual.tex doxygen.sty
 	echo "Running latex..."
 	pdflatex doxygen_manual.tex 
diff --git a/doc/docblocks.doc b/doc/docblocks.doc
index 789cc92..10f6801 100644
--- a/doc/docblocks.doc
+++ b/doc/docblocks.doc
@@ -374,7 +374,7 @@ are supported.
 
 There is also another way to document Python code using comments that 
 start with "##". These type of comment blocks are more in line with the 
-way documentation blocks work for the other languages support doxygen 
+way documentation blocks work for the other languages supported by doxygen 
 and this also allows the use of special commands. 
 
 Here is the same example again but now using doxygen style comments:
diff --git a/doc/doxygen.sty b/doc/doxygen.sty
index 7c24e26..ce75b30 100644
--- a/doc/doxygen.sty
+++ b/doc/doxygen.sty
@@ -27,6 +27,20 @@
 \rfoot[\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-2004}]{}
 \lfoot[]{\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-2004}}
 \cfoot{}
+\newenvironment{Code}
+{\footnotesize}
+{\normalsize}
+\newcommand{\doxyref}[3]{\textbf{#1} (\textnormal{#2}\,\pageref{#3})}
+\newenvironment{DocInclude}
+{\footnotesize}
+{\normalsize}
+\newenvironment{VerbInclude}
+{\footnotesize}
+{\normalsize}
+\newenvironment{Image}
+{\begin{figure}[H]}
+{\end{figure}}
+\newenvironment{ImageNoCaption}{}{}
 \newenvironment{CompactList}
 {\begin{list}{}{
   \setlength{\leftmargin}{0.5cm}
diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex
index 0514222..8d5d178 100644
--- a/doc/doxygen_manual.tex
+++ b/doc/doxygen_manual.tex
@@ -69,6 +69,7 @@ Written by Dimitri van Heesch\\[2ex]
 \input{config}
 \input{commands}
 \input{htmlcmds}
+\input{xmlcmds}
 \part{Developers Manual}
 \input{arch}
 \input{perlmod}
diff --git a/doc/index.doc b/doc/index.doc
index 42f1444..d4d0493 100644
--- a/doc/index.doc
+++ b/doc/index.doc
@@ -174,7 +174,7 @@ Thanks go to:
     given me a good start in writing doxygen.
 <li>All people at Troll Tech, for creating a beautiful GUI Toolkit
     (which is very useful as a Windows/Unix platform abstraction layer :-)
-<li>My brother <a href="http://www.stack.nl/~fidget/index.html">Frank</a>
+<li>My brother Frank
     for rendering the logos.
 <li>Harm van der Heijden for adding HTML help support.
 <li>Wouter Slegers of 
diff --git a/src/commentscan.l b/src/commentscan.l
index fba617b..efd46b3 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -515,39 +515,6 @@ static QCString addFormula()
 static void checkFormula();
 //-----------------------------------------------------------------------------
 
-static void prependScope()
-{
-#if 0
-  Entry *current_root = current->parent;
-  if (current_root && current_root->section & Entry::SCOPE_MASK)
-  {
-    current->name.prepend(current_root->name+"::");
-    if (current_root->tArgLists)
-    {
-      if (current->tArgLists==0)
-      {
-	current->tArgLists = new QList<ArgumentList>;
-	current->tArgLists->setAutoDelete(TRUE);
-      }
-      QListIterator<ArgumentList> talsi(*current_root->tArgLists);
-      ArgumentList *srcAl=0;
-      for (talsi.toLast();(srcAl=talsi.current());--talsi)
-      {
-        ArgumentList *dstAl = new ArgumentList;
-	dstAl->setAutoDelete(TRUE);
-	QListIterator<Argument> tali(*srcAl);
-        Argument *a;
-        for (;(a=tali.current());++tali)
-        {
-          dstAl->append(new Argument(*a));
-        }	  
-        current->tArgLists->insert(0,dstAl);	
-      }
-    }
-  }
-#endif
-}
-
 static void addSection()
 {
   sectionTitle+=yytext;
@@ -994,7 +961,6 @@ MAILADR   [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
 
 <EnumDocArg1>{SCOPEID}			{ // handle argument
   					  current->name = yytext;
-					  prependScope();
 					  BEGIN( Comment );
   					}
 <EnumDocArg1>{LC}			{ // line continuation
@@ -1065,12 +1031,10 @@ MAILADR   [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
 					    current->name+="-p";
 					  }
 					  // prepend outer scope name 
-					  prependScope();
 					  BEGIN( ClassDocArg2 );
 					}
 <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" {
 					  current->name = yytext;
-					  prependScope();
 					  BEGIN( ClassDocArg2 );
    					}
 <ClassDocArg1,CategoryDocArg1>{LC}      { // line continuation
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 9b5bb60..abb655b 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -2185,13 +2185,14 @@ done:
 
 static void buildVarList(Entry *root)
 {
+  int isFuncPtr=-1;
   if (!root->name.isEmpty() &&
       (root->type.isEmpty() || compoundKeywordDict.find(root->type)==0) &&
       (
        (root->section==Entry::VARIABLE_SEC    // it's a variable
        ) ||
        (root->section==Entry::FUNCTION_SEC && // or maybe a function pointer variable 
-        findFunctionPtr(root->type)!=-1
+        (isFuncPtr=findFunctionPtr(root->type))!=-1
        ) ||
        (root->section==Entry::FUNCTION_SEC && // class variable initialized by constructor
         isVarWithConstructor(root)
@@ -2228,7 +2229,7 @@ static void buildVarList(Entry *root)
     }
     else
     {
-      int i=findFunctionPtr(root->type);
+      int i=isFuncPtr;
       if (i!=-1) // function pointer
       {
         int ai = root->type.find('[',i);
@@ -2244,6 +2245,11 @@ static void buildVarList(Entry *root)
           //printf("root->type=%s root->args=%s\n",root->type.data(),root->args.data());
         }
       }
+      else if (root->type.find("typedef ")!=-1 && root->type.right(2)=="()") // typedef void (func)(int)
+      {
+        root->type=root->type.left(root->type.length()-1);
+        root->args.prepend(")");
+      }
     }
     
     QCString scope,name=removeRedundantWhiteSpace(root->name);
@@ -3911,9 +3917,12 @@ static bool findClassRelation(
 
         }
         bool isATemplateArgument = templateNames!=0 && templateNames->find(biName)!=0;
+        // make templSpec canonical
+        templSpec = getCanonicalTemplateSpec(cd, cd->getFileDef(), templSpec);
+
         if (found)
         {
-          Debug::print(Debug::Classes,0,"    Documented class `%s' templSpec=%s\n",biName.data(),templSpec.data());
+          Debug::print(Debug::Classes,0,"    Documented class `%s' templSpec=%s\n",biName.data(),templSpec.isEmpty()?"":templSpec.data());
           // add base class to this class
 
           // if templSpec is not empty then we should "instantiate"
@@ -8903,7 +8912,6 @@ void parseInput()
   Doxygen::memberNameSDict.sort();
   Doxygen::functionNameSDict.sort();
   Doxygen::hiddenClasses.sort();
-  printf("Sorting %d classes\n",Doxygen::classSDict.count());
   Doxygen::classSDict.sort();
   
   msg("Freeing entry tree\n");
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index c6666bd..e2df6a0 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -1817,7 +1817,14 @@ static void writeDefaultQuickLinks(QTextStream &t,bool compact,
     {
       startQuickIndexItem(t,"namespacemembers"+Doxygen::htmlFileExtension,
           hli==HLI_NamespaceMembers,compact,first,relPath);
-      t << fixSpaces(theTranslator->trNamespaceMembers());
+      if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
+      {
+        t << fixSpaces(theTranslator->trPackageMembers());
+      }
+      else
+      {
+        t << fixSpaces(theTranslator->trNamespaceMembers());
+      }
       endQuickIndexItem(t);
     }
     endQuickIndexList(t,compact);
diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp
index edbe979..9712e27 100644
--- a/src/latexdocvisitor.cpp
+++ b/src/latexdocvisitor.cpp
@@ -36,7 +36,7 @@ static QString escapeLabelName(const char *s)
     switch (c)
     {
       case '%': result+="\\%"; break;
-      case '|': result+="\\texttt{\"|}"; break;
+      case '|': result+="\\tt{\"|}"; break;
       case '!': result+="\"!"; break;
       default: result+=c;
     }
@@ -69,7 +69,7 @@ QString LatexDocVisitor::escapeMakeIndexChars(const char *s)
       case '!': m_t << "\"!"; break;
       case '"': m_t << "\"\""; break;
       case '@': m_t << "\"@"; break;
-      case '|': m_t << "\\texttt{\"|}"; break;
+      case '|': m_t << "\\tt{\"|}"; break;
       case '[': m_t << "["; break;
       case ']': m_t << "]"; break;
       default:  str[0]=c; filter(str); break;
@@ -191,7 +191,7 @@ void LatexDocVisitor::visit(DocURL *u)
     if (u->isEmail()) m_t << "mailto:";
     m_t << u->url() << "}";
   }
-  m_t << "\\texttt{";
+  m_t << "\\tt{";
   filter(u->url());
   m_t << "}";
 }
@@ -214,13 +214,13 @@ void LatexDocVisitor::visit(DocStyleChange *s)
   switch (s->style())
   {
     case DocStyleChange::Bold:
-      if (s->enable()) m_t << "\\textbf{";      else m_t << "}";
+      if (s->enable()) m_t << "{\\bf ";      else m_t << "}";
       break;
     case DocStyleChange::Italic:
-      if (s->enable()) m_t << "\\textit{";     else m_t << "\\/}";
+      if (s->enable()) m_t << "{\\em ";     else m_t << "\\/}";
       break;
     case DocStyleChange::Code:
-      if (s->enable()) m_t << "\\texttt{ ";   else m_t << "}";
+      if (s->enable()) m_t << "{\\tt ";   else m_t << "}";
       break;
     case DocStyleChange::Subscript:
       if (s->enable()) m_t << "$_{\\mbox{";    else m_t << "}}$ ";
@@ -718,7 +718,7 @@ void LatexDocVisitor::visitPre(DocHRef *href)
     m_t << href->url();
     m_t << "}";
   }
-  m_t << "\texttt{";
+  m_t << "{\\tt ";
 }
 
 void LatexDocVisitor::visitPost(DocHRef *) 
@@ -972,7 +972,7 @@ void LatexDocVisitor::visitPre(DocXRefItem *x)
   }
   else
   {
-    m_t << "\\textbf{";
+    m_t << "\\bf{";
   }
   m_insideItem=TRUE;
   filter(x->title());
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index 66aa16c..601c7f4 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -63,7 +63,7 @@ static QCString escapeLabelName(const char *s)
     switch (c)
     {
       case '%': result+="\\%"; break;
-      case '|': result+="\\texttt{\"|}"; break;
+      case '|': result+="\\tt{\"|}"; break;
       case '!': result+="\"!"; break;
       default: result+=c;
     }
@@ -85,7 +85,7 @@ static QCString escapeMakeIndexChars(LatexGenerator *g,QTextStream &t,const char
       case '!': t << "\"!"; break;
       case '"': t << "\"\""; break;
       case '@': t << "\"@"; break;
-      case '|': t << "\\texttt{\"|}"; break;
+      case '|': t << "\\tt{\"|}"; break;
       case '[': t << "["; break;
       case ']': t << "]"; break;
       default:  str[0]=c; g->docify(str); break;
@@ -355,7 +355,7 @@ static void writeDefaultStyleSheetPart3(QTextStream &t)
   t << "  \\setlength{\\itemsep}{0pt}\n";
   t << "  \\setlength{\\parsep}{0pt}\n";
   t << "  \\setlength{\\topsep}{0pt}\n";
-  t << "  \\renewcommand{\\makelabel}{}}}\n";
+  t << "  \\renewcommand{\\makelabel}{\\hfill}}}\n";
   t << "{\\end{list}}\n";
   t << "\\newenvironment{CompactItemize}\n";
   t << "{\n";
@@ -377,7 +377,7 @@ static void writeDefaultStyleSheetPart3(QTextStream &t)
   t << "}\n";
   t << "{\\end{tabular*}\\par}\n";
   t << "\\newcommand{\\entrylabel}[1]{\n";
-  t << "   {\\parbox[b]{\\labelwidth-4pt}{\\makebox[0pt][l]{\\textbf{#1}}\\\\}}}\n";
+  t << "   {\\parbox[b]{\\labelwidth-4pt}{\\makebox[0pt][l]{\\textbf{#1}}\\vspace{1.5\\baselineskip}}}}\n";
   t << "\\newenvironment{Desc}\n";
   t << "{\\begin{list}{}\n";
   t << "  {\n";
@@ -924,7 +924,7 @@ void LatexGenerator::endHtmlLink()
 void LatexGenerator::writeStartAnnoItem(const char *,const char *,
                                         const char *path,const char *name)
 {
-  t << "\\item\\contentsline{section}{\\textbf{";
+  t << "\\item\\contentsline{section}{\\bf ";
   if (path) docify(path);
   docify(name); 
   t << "} ";
@@ -959,7 +959,7 @@ void LatexGenerator::endIndexValue(const char *name,bool hasBrief)
 //void LatexGenerator::writeClassLink(const char *,const char *,
 //                                    const char *,const char *name)
 //{
-//  t << "\\textbf{";
+//  t << "{\\bf";
 //  docify(name);
 //  t << "}"; 
 //}
@@ -975,7 +975,7 @@ void LatexGenerator::startTextLink(const char *f,const char *anchor)
   }
   else
   {
-    t << "\\textbf{";
+    t << "{\\bf ";
   }
 }
 
@@ -999,7 +999,7 @@ void LatexGenerator::writeObjectLink(const char *ref, const char *f,
   }
   else
   {
-    t << "\\textbf{";
+    t << "\\bf{";
     docify(text);
     t << "}";
   } 
@@ -1420,7 +1420,7 @@ void LatexGenerator::endMemberList()
 void LatexGenerator::startMemberGroupHeader(bool hasHeader)
 {
   if (hasHeader) t << "\\begin{Indent}";
-  t << "\\textbf{";
+  t << "{\\bf ";
 }
 
 void LatexGenerator::endMemberGroupHeader()
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 6d2761c..23d5a4b 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -2503,7 +2503,7 @@ void MemberDef::setTagInfo(TagInfo *ti)
 {
   if (ti)
   {
-    setAnchor(ti->anchor);
+    anc=ti->anchor;
     setReference(ti->tagName);
     explicitOutputFileBase = stripExtension(ti->fileName);
   }
diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp
index 7e772ec..9ec71c6 100644
--- a/src/perlmodgen.cpp
+++ b/src/perlmodgen.cpp
@@ -2231,11 +2231,67 @@ bool PerlModGenerator::generateDoxyStructurePM()
     "\t\t  [ \"hash\", \"ClassDetailed\",\n"
     "\t\t    {\n"
     "\t\t      doc => [ \"doc\", \"ClassDetailedDoc\" ],\n"
-    " \t\t    },\n"
+    "\t\t    },\n"
     "\t\t  ],\n"
     "\t      },\n"
     "\t    ],\n"
     "\t  ],\n"
+    "\tgroups =>\n"
+    "\t  [ \"list\", \"Groups\",\n"
+    "\t    [ \"hash\", \"Group\",\n"
+    "\t      {\n"
+    "\t\tname => [ \"string\", \"GroupName\" ],\n"
+    "\t\ttitle => [ \"string\", \"GroupTitle\" ],\n"
+    "\t\tfiles =>\n"
+    "\t\t  [ \"list\", \"Files\",\n"
+    "\t\t    [ \"hash\", \"File\",\n"
+    "\t\t      {\n"
+    "\t\t        name => [ \"string\", \"Filename\" ]\n"
+    "\t\t      }\n"
+    "\t\t    ],\n"
+    "\t\t  ],\n"
+    "\t\tclasses  =>\n"
+    "\t\t  [ \"list\", \"Classes\",\n"
+    "\t\t    [ \"hash\", \"Class\",\n"
+    "\t\t      {\n" 
+    "\t\t        name => [ \"string\", \"Classname\" ]\n"
+    "\t\t      }\n"
+    "\t\t    ],\n"
+    "\t\t  ],\n"
+    "\t\tnamespaces =>\n"
+    "\t\t  [ \"list\", \"Namespaces\",\n"
+    "\t\t    [ \"hash\", \"Namespace\",\n"
+    "\t\t      {\n" 
+    "\t\t        name => [ \"string\", \"NamespaceName\" ]\n"
+    "\t\t      }\n"
+    "\t\t    ],\n"
+    "\t\t  ],\n"
+    "\t\tpages =>\n"
+    "\t\t  [ \"list\", \"Pages\",\n"
+    "\t\t    [ \"hash\", \"Page\","
+    "\t\t      {\n"
+    "\t\t        title => [ \"string\", \"PageName\" ]\n"
+    "\t\t      }\n"
+    "\t\t    ],\n"
+    "\t\t  ],\n"
+    "\t\tgroups =>\n"
+    "\t\t  [ \"list\", \"Groups\",\n"
+    "\t\t    [ \"hash\", \"Group\",\n"
+    "\t\t      {\n"
+    "\t\t        title => [ \"string\", \"GroupName\" ]\n"
+    "\t\t      }\n"
+    "\t\t    ],\n"
+    "\t\t  ],\n"
+    "\t\tfunctions => memberlist(\"GroupFunction\"),\n"
+    "\t\tdetailed =>\n"
+    "\t\t  [ \"hash\", \"GroupDetailed\",\n"
+    "\t\t    {\n"
+    "\t\t      doc => [ \"doc\", \"GroupDetailedDoc\" ],\n"
+    "\t\t    },\n"
+    "\t\t  ],\n"
+    "\t      }\n"
+    "\t    ],\n"
+    "\t  ],\n"
     "      },\n"
     "    ];\n"
     "\n"
diff --git a/src/pyscanner.l b/src/pyscanner.l
index d29b2c1..ba6784a 100644
--- a/src/pyscanner.l
+++ b/src/pyscanner.l
@@ -414,6 +414,7 @@ EXPCHAR           [#(){}\[\],:.%/\\=`*~|&<>!;+-]
 NONEMPTYEXP       [^ \t\n:]
 PARAMNONEMPTY     [^ \t\n():]
 IDENTIFIER        ({LETTER}|"_")({LETTER}|{DIGIT}|"_")*  
+SCOPE             {IDENTIFIER}("."{IDENTIFIER})*
 BORDER            ([^A-Za-z0-9])
 
 TRISINGLEQUOTE    "'''"(!)?
@@ -899,13 +900,15 @@ STARTDOCSYMS      ^{B}"##"/[^#]
 			YY_CURRENT_BUFFER->yy_at_bol=TRUE;
                         BEGIN(Search);
                       }
-    \n/"##"	      {
+    /*
+    ^{B}/"##"         {  // start of a special comment
                         yyLineNr++;
 			endOfDef();
 			g_hideClassDocs = FALSE;
 			YY_CURRENT_BUFFER->yy_at_bol=TRUE;
                         BEGIN(Search);
                       }
+    */
     ^{BB}/\n	      { // skip empty line
       		        current->program+=yytext;
       	              }
@@ -953,7 +956,7 @@ STARTDOCSYMS      ^{B}"##"/[^#]
       		        current->program+=*yytext;
 			yyLineNr++; 
 		      }
-    ^{POUNDCOMMENT}   { // normal comment
+    {POUNDCOMMENT}    { // normal comment
       		        current->program+=yytext;
                       }
     .                 { // any character
@@ -1007,9 +1010,9 @@ STARTDOCSYMS      ^{B}"##"/[^#]
       			 BEGIN(ClassCaptureIndent);
                        }
 
-    {IDENTIFIER}       {
+    {SCOPE}            {
                          current->extends->append(
-					      new BaseInfo(yytext,Public,Normal)
+					      new BaseInfo(substitute(yytext,".","::"),Public,Normal)
 					    );
                          //Has base class-do stuff
                        }
@@ -1040,7 +1043,7 @@ STARTDOCSYMS      ^{B}"##"/[^#]
 				 //fprintf(stderr,"setting indent %d\n",g_curIndent);
 				 //printf("current->program=[%s]\n",current->program.data());
 				 g_hideClassDocs = TRUE;
-				 BEGIN( ClassBody );
+			         BEGIN(ClassBody);
                                }
 
     ""/({NONEMPTY}|{EXPCHAR})  {
@@ -1492,6 +1495,11 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt)
 static void parsePrototype(const QCString &text)
 {
   //printf("**** parsePrototype(%s) begin\n",text.data());
+  if (text.isEmpty()) 
+  {
+    warn(yyFileName,yyLineNr,"Empty prototype found!");
+    return;
+  }
 
   //g_expectModuleDocs = FALSE;
   g_specialBlock = FALSE;
diff --git a/src/scanner.l b/src/scanner.l
index bb941f7..7a3a8c0 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -543,7 +543,8 @@ ID        "$"?[a-z_A-Z][a-z_A-Z0-9]*
 LABELID   [a-z_A-Z][a-z_A-Z0-9\-]*
 SCOPEID   {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
 SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID})
-TSCOPE    {ID}("<"[a-z_A-Z0-9 \t\*\&]*">")?
+TSCOPE    {ID}("<"[a-z_A-Z0-9 \t\*\&,]*">")?
+FTSCOPE   {ID}("<"[a-z_A-Z0-9\*\&,]*">")?
 CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID})
 ATTR      ({B}+[^>\n]*)?
 A         [aA]
@@ -1486,7 +1487,7 @@ IDLATTR   ("["[^\]]*"]"){BN}*
 <QtPropType>{B}+			{
   				          current->type+=yytext;
   					}
-<QtPropType>({ID}"::")*{ID}		{
+<QtPropType>({FTSCOPE}"::")*{FTSCOPE}	{
   					  current->type+=yytext;
                                           BEGIN(QtPropName);
   					}
@@ -2408,6 +2409,10 @@ IDLATTR   ("["[^\]]*"]"){BN}*
 <ReadBody,ReadNSBody,ReadBodyIntf>"{"       { current->program += yytext ;
 					  ++curlyCount ;
 					}
+<ReadBodyIntf>"}"			{
+					  current->program += yytext ;
+					  --curlyCount ;
+  					}
 <ReadBody,ReadNSBody>"}"		{ //err("ReadBody count=%d\n",curlyCount);
   					  if ( curlyCount>0 )
 					  {
@@ -2681,7 +2686,7 @@ IDLATTR   ("["[^\]]*"]"){BN}*
   					}
 <ReadBody,ReadNSBody,ReadBodyIntf>.	{ current->program += yytext ; }
 
-<FindMembers>"("/({BN}*{TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A<int>::func_t)(args...) */
+<FindMembers>"("/{BN}*({TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A<int>::func_t)(args...) */
 <FindMembers>("("({BN}*{TSCOPE}{BN}*"::")*({BN}*"*"{BN}*)+)+ {   /* typedef void (A::*ptr_t)(args...) */
   					  current->bodyLine = yyLineNr;
   					  lineCount();
@@ -3485,7 +3490,7 @@ IDLATTR   ("["[^\]]*"]"){BN}*
   					  yyLineNr++;
   				          //addToBody(yytext);
   					}
-<SkipCurly,SkipCurlyCpp>[^\n"'@\\/{}]+	{
+<SkipCurly,SkipCurlyCpp>[^\n#"'@\\/{}]+	{
   				          //addToBody(yytext);
   					}
 <SkipCurlyCpp>\n			{ 
@@ -3783,8 +3788,8 @@ IDLATTR   ("["[^\]]*"]"){BN}*
 					    current->name.sprintf("@%d",anonCount++);
 					  }
 					  curlyCount=0;
-					  if (/*current->section==Entry::PROTOCOL_SEC ||
-					      current->section==Entry::OBJCIMPL_SEC*/
+					  if (current_root && // not a nested struct inside an @interface section
+					      current_root->section!=Entry::INTERFACE_SEC &&
 					      insideObjC
 					     )
 					  { // ObjC body that ends with @end
diff --git a/src/util.cpp b/src/util.cpp
index 231910b..4164398 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -2750,13 +2750,24 @@ static QCString stripDeclKeywords(const QCString &s)
   return s;
 }
 
+// forward decl for circular dependencies
+static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type);
+
+QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec)
+{
+   QCString templSpec = spec.stripWhiteSpace();
+   if (templSpec.isEmpty() || templSpec.at(0) != '<') return templSpec;
+   return "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1));
+}
+
+
 static QCString getCanonicalTypeForIdentifier(
                   Definition *d,FileDef *fs,const QCString &word,
                   QCString *tSpec)
 {
   QCString symName,scope,result,templSpec,tmpName;
   //DefinitionList *defList=0;
-  if (tSpec) templSpec = stripDeclKeywords(*tSpec);
+  if (tSpec) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec));
 
   if (word.findRev("::")!=-1 && !(tmpName=stripScope(word)).isEmpty())
   {
@@ -2770,20 +2781,16 @@ static QCString getCanonicalTypeForIdentifier(
   ClassDef *cd = 0;
   MemberDef *mType = 0;
   QCString ts;
-  if (!templSpec.isEmpty())
-  {
-    cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE);
-    if (cd && tSpec) *tSpec="";
-  }
-  if (cd==0)
+
+  // lookup class / class template instance
+  cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE);
+  bool isTemplInst = cd && !templSpec.isEmpty();
+  if (!cd && !templSpec.isEmpty())
   {
+     // class template specialization not known, look up class template
     cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE);
   }
 
-  if (!ts.isEmpty() && templSpec.isEmpty())
-  {
-    templSpec = stripDeclKeywords(ts);
-  }
   //printf("symbol=%s word=%s cd=%s d=%s fs=%s\n",
   //    symName.data(),
   //    word.data(),
@@ -2794,12 +2801,25 @@ static QCString getCanonicalTypeForIdentifier(
 
   //printf(">>>> word '%s' => '%s' templSpec=%s ts=%s\n",
   //    (word+templSpec).data(),
-  //    cd?cd->qualifiedNameWithTemplateParameters().data():"<none>",
+  //    cd?cd->qualifiedName().data():"<none>",
   //    templSpec.data(),ts.data());
-  if (cd) // known type
+
+  if (cd) // known class type
   {
-    //result = cd->qualifiedNameWithTemplateParameters();
-    result = removeRedundantWhiteSpace(cd->qualifiedName()+templSpec);
+    if (isTemplInst)
+    {
+      // spec is already part of class type
+      templSpec="";
+      if (tSpec) *tSpec="";
+    }
+    else if (!ts.isEmpty() && templSpec.isEmpty())
+    {
+      // use formal template args for spec
+      templSpec = stripDeclKeywords(ts);
+    }
+
+    result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec);
+
     if (cd->isTemplate() && tSpec)
     {
       *tSpec="";
@@ -2809,7 +2829,7 @@ static QCString getCanonicalTypeForIdentifier(
   {
     result = mType->qualifiedName();
   }
-  else // not known as a class
+  else
   {
     QCString resolvedType = resolveTypeDef(d,word);
     if (resolvedType.isEmpty()) // not known as a typedef either
@@ -2824,21 +2844,9 @@ static QCString getCanonicalTypeForIdentifier(
   return result;
 }
 
-static QCString extractCanonicalType(Definition *d,FileDef *fs,const Argument *arg)
+static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type)
 {
-  QCString type = arg->type.stripWhiteSpace();
-  QCString name = arg->name;
-  //printf("extractCanonicalType(type=%s,name=%s)\n",type.data(),name.data());
-  if ((type=="const" || type=="volatile") && !name.isEmpty()) 
-  { // name is part of type => correct
-    type+=" ";
-    type+=name;
-  } 
-  if (name=="const" || name=="volatile")
-  { // name is part of type => correct
-    if (!type.isEmpty()) type+=" ";
-    type+=name;
-  }
+  type = type.stripWhiteSpace();
 
   // strip const and volatile keywords that are not relevant for the type
   stripIrrelevantConstVolatile(type);
@@ -2851,7 +2859,7 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,const Argument *a
   type.stripPrefix("typename ");
 
   type = removeRedundantWhiteSpace(type);
-  //printf("extractCanonicalTyp2(type=%s,name=%s)\n",type.data(),name.data());
+  //printf("extractCanonicalType(type=%s,name=%s)\n",type.data(),name.data());
 
   static QRegExp id("[a-z_A-Z][:a-z_A-Z0-9]*");
   
@@ -2890,6 +2898,25 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,const Argument *a
   return removeRedundantWhiteSpace(canType);
 }
 
+static QCString extractCanonicalArgType(Definition *d,FileDef *fs,const Argument *arg)
+{
+  QCString type = arg->type.stripWhiteSpace();
+  QCString name = arg->name;
+  //printf("extractCanonicalArgType(type=%s,name=%s)\n",type.data(),name.data());
+  if ((type=="const" || type=="volatile") && !name.isEmpty()) 
+  { // name is part of type => correct
+    type+=" ";
+    type+=name;
+  } 
+  if (name=="const" || name=="volatile")
+  { // name is part of type => correct
+    if (!type.isEmpty()) type+=" ";
+    type+=name;
+  }
+
+  return extractCanonicalType(d,fs,type);
+}
+
 static bool matchArgument2(
                    Definition *srcScope,FileDef *srcFileScope,Argument *srcA,
                    Definition *dstScope,FileDef *dstFileScope,Argument *dstA
@@ -2929,11 +2956,11 @@ static bool matchArgument2(
 
   if (srcA->canType.isEmpty())
   {
-    srcA->canType = extractCanonicalType(srcScope,srcFileScope,srcA);
+    srcA->canType = extractCanonicalArgType(srcScope,srcFileScope,srcA);
   }
   if (dstA->canType.isEmpty())
   {
-    dstA->canType = extractCanonicalType(dstScope,dstFileScope,dstA);
+    dstA->canType = extractCanonicalArgType(dstScope,dstFileScope,dstA);
   }
   
   if (srcA->canType==dstA->canType)
diff --git a/src/util.h b/src/util.h
index 52b2316..2add1da 100644
--- a/src/util.h
+++ b/src/util.h
@@ -152,6 +152,8 @@ void generateFileRef(OutputDocInterface &od,const char *,
 
 void writePageRef(OutputDocInterface &od,const char *cn,const char *mn);
 
+QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec);
+
 bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *srcAl,
                      Definition *dstScope,FileDef *dstFileScope,ArgumentList *dstAl,
                      bool checkCV
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
index a479842..ef19e15 100644
--- a/src/xmlgen.cpp
+++ b/src/xmlgen.cpp
@@ -613,7 +613,7 @@ static void generateXMLForMember(MemberDef *md,QTextStream &ti,QTextStream &t,De
     if (md->isReadable()) t << "yes"; else t << "no";
     t << "\"";
 
-    t << "\" writable=\"";
+    t << " writable=\"";
     if (md->isWritable()) t << "yes"; else t << "no";
     t << "\"";
   }
diff --git a/tmake/lib/macosx-c++/tmake.conf b/tmake/lib/macosx-c++/tmake.conf
index ef24a31..0df5e06 100755
--- a/tmake/lib/macosx-c++/tmake.conf
+++ b/tmake/lib/macosx-c++/tmake.conf
@@ -8,7 +8,7 @@ TEMPLATE		= app
 CONFIG			= qt warn_on release
 
 TMAKE_CC		= cc
-TMAKE_CFLAGS		= -pipe
+TMAKE_CFLAGS		= -pipe -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc
 TMAKE_CFLAGS_WARN_ON	= -Wall -W
 TMAKE_CFLAGS_WARN_OFF	=
 TMAKE_CFLAGS_RELEASE	= -O2
@@ -36,7 +36,7 @@ TMAKE_LIBDIR_OPENGL	= /usr/X11R6/lib
 
 TMAKE_LINK		= c++
 TMAKE_LINK_SHLIB	= c++
-TMAKE_LFLAGS		= -Wl,-search_paths_first
+TMAKE_LFLAGS		= -Wl,-search_paths_first -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc
 TMAKE_LFLAGS_RELEASE	=
 TMAKE_LFLAGS_DEBUG	=
 TMAKE_LFLAGS_SHLIB	= -shared
-- 
cgit v0.12

