Orb/Doxygen/src/docparser.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  *
       
     6  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     7  *
       
     8  * Permission to use, copy, modify, and distribute this software and its
       
     9  * documentation under the terms of the GNU General Public License is hereby 
       
    10  * granted. No representations are made about the suitability of this software 
       
    11  * for any purpose. It is provided "as is" without express or implied warranty.
       
    12  * See the GNU General Public License for more details.
       
    13  *
       
    14  * Documents produced by Doxygen are derivative works derived from the
       
    15  * input used in their production; they are not affected by this license.
       
    16  *
       
    17  */
       
    18 
       
    19 #include <stdio.h>
       
    20 #include <stdlib.h>
       
    21 
       
    22 #include <qfile.h>
       
    23 #include <qfileinfo.h>
       
    24 #include <qcstring.h>
       
    25 #include <qstack.h>
       
    26 #include <qdict.h>
       
    27 #include <qregexp.h>
       
    28 #include <ctype.h>
       
    29 
       
    30 #include "doxygen.h"
       
    31 #include "debug.h"
       
    32 #include "util.h"
       
    33 #include "pagedef.h"
       
    34 
       
    35 #include "docparser.h"
       
    36 #include "doctokenizer.h"
       
    37 #include "cmdmapper.h"
       
    38 #include "printdocvisitor.h"
       
    39 #include "message.h"
       
    40 #include "section.h"
       
    41 #include "searchindex.h"
       
    42 #include "language.h"
       
    43 #include "portable.h"
       
    44 
       
    45 // debug off
       
    46 #define DBG(x) do {} while(0)
       
    47 
       
    48 // debug to stdout
       
    49 //#define DBG(x) printf x
       
    50 
       
    51 // debug to stderr
       
    52 //#define myprintf(x...) fprintf(stderr,x)
       
    53 //#define DBG(x) myprintf x
       
    54 
       
    55 #define INTERNAL_ASSERT(x) do {} while(0)
       
    56 //#define INTERNAL_ASSERT(x) if (!(x)) DBG(("INTERNAL_ASSERT(%s) failed retval=0x%x: file=%s line=%d\n",#x,retval,__FILE__,__LINE__)); 
       
    57 
       
    58 //---------------------------------------------------------------------------
       
    59 
       
    60 static const char *sectionLevelToName[] = 
       
    61 {
       
    62   "page",
       
    63   "section",
       
    64   "subsection",
       
    65   "subsubsection",
       
    66   "paragraph"
       
    67 };
       
    68 
       
    69 //---------------------------------------------------------------------------
       
    70 
       
    71 // Parser state: global variables during a call to validatingParseDoc
       
    72 static Definition *           g_scope;
       
    73 static QString                g_context;
       
    74 static bool                   g_inSeeBlock;
       
    75 static bool                   g_insideHtmlLink;
       
    76 static QStack<DocNode>        g_nodeStack;
       
    77 static QStack<DocStyleChange> g_styleStack;
       
    78 static QStack<DocStyleChange> g_initialStyleStack;
       
    79 static QList<Definition>      g_copyStack;
       
    80 static QString                g_fileName;
       
    81 static QString                g_relPath;
       
    82 
       
    83 static bool                   g_hasParamCommand;
       
    84 static bool                   g_hasReturnCommand;
       
    85 static QDict<void>            g_paramsFound;
       
    86 static MemberDef *            g_memberDef;
       
    87 static bool                   g_isExample;
       
    88 static QCString               g_exampleName;
       
    89 static SectionDict *          g_sectionDict;
       
    90 static QCString               g_searchUrl;
       
    91 
       
    92 static QString                g_includeFileText;
       
    93 static uint                   g_includeFileOffset;
       
    94 static uint                   g_includeFileLength;
       
    95 
       
    96 // parser's context to store all global variables
       
    97 struct DocParserContext
       
    98 {
       
    99   Definition *scope;
       
   100   QString context;
       
   101   bool inSeeBlock;
       
   102   bool insideHtmlLink;
       
   103   QStack<DocNode> nodeStack;
       
   104   QStack<DocStyleChange> styleStack;
       
   105   QStack<DocStyleChange> initialStyleStack;
       
   106   QList<Definition> copyStack;
       
   107   QString fileName;
       
   108   QString relPath;
       
   109 
       
   110   bool         hasParamCommand;
       
   111   bool         hasReturnCommand;
       
   112   MemberDef *  memberDef;
       
   113   QDict<void>  paramsFound;
       
   114   bool         isExample;
       
   115   QCString     exampleName;
       
   116   SectionDict *sectionDict;
       
   117   QCString     searchUrl;
       
   118 
       
   119   QString  includeFileText;
       
   120   uint     includeFileOffset;
       
   121   uint     includeFileLength;
       
   122 
       
   123   TokenInfo *token;
       
   124 };
       
   125 
       
   126 static QStack<DocParserContext> g_parserStack;
       
   127 
       
   128 //---------------------------------------------------------------------------
       
   129 
       
   130 static void docParserPushContext(bool saveParamInfo=TRUE)
       
   131 {
       
   132   //QCString indent;
       
   133   //indent.fill(' ',g_parserStack.count()*2+2);
       
   134   //printf("%sdocParserPushContext() count=%d\n",indent.data(),g_nodeStack.count());
       
   135 
       
   136   doctokenizerYYpushContext();
       
   137   DocParserContext *ctx   = new DocParserContext;
       
   138   ctx->scope              = g_scope;
       
   139   ctx->context            = g_context;
       
   140   ctx->inSeeBlock         = g_inSeeBlock;
       
   141   ctx->insideHtmlLink     = g_insideHtmlLink;
       
   142   ctx->nodeStack          = g_nodeStack;
       
   143   ctx->styleStack         = g_styleStack;
       
   144   ctx->initialStyleStack  = g_initialStyleStack;
       
   145   ctx->copyStack          = g_copyStack;
       
   146   ctx->fileName           = g_fileName;
       
   147   ctx->relPath            = g_relPath;
       
   148 
       
   149   if (saveParamInfo)
       
   150   {
       
   151     ctx->hasParamCommand    = g_hasParamCommand;
       
   152     ctx->hasReturnCommand   = g_hasReturnCommand;
       
   153     ctx->paramsFound        = g_paramsFound;
       
   154   }
       
   155 
       
   156   ctx->memberDef          = g_memberDef;
       
   157   ctx->isExample          = g_isExample;
       
   158   ctx->exampleName        = g_exampleName;
       
   159   ctx->sectionDict        = g_sectionDict;
       
   160   ctx->searchUrl          = g_searchUrl;
       
   161 
       
   162   ctx->includeFileText    = g_includeFileText;
       
   163   ctx->includeFileOffset  = g_includeFileOffset;
       
   164   ctx->includeFileLength  = g_includeFileLength;
       
   165   
       
   166   ctx->token              = g_token;
       
   167   g_token = new TokenInfo;
       
   168 
       
   169   g_parserStack.push(ctx);
       
   170 }
       
   171 
       
   172 static void docParserPopContext(bool keepParamInfo=FALSE)
       
   173 {
       
   174   DocParserContext *ctx = g_parserStack.pop();
       
   175   g_scope               = ctx->scope;
       
   176   g_context             = ctx->context;
       
   177   g_inSeeBlock          = ctx->inSeeBlock;
       
   178   g_insideHtmlLink      = ctx->insideHtmlLink;
       
   179   g_nodeStack           = ctx->nodeStack;
       
   180   g_styleStack          = ctx->styleStack;
       
   181   g_initialStyleStack   = ctx->initialStyleStack;
       
   182   g_copyStack           = ctx->copyStack;
       
   183   g_fileName            = ctx->fileName;
       
   184   g_relPath             = ctx->relPath;
       
   185 
       
   186   if (!keepParamInfo)
       
   187   {
       
   188     g_hasParamCommand     = ctx->hasParamCommand;
       
   189     g_hasReturnCommand    = ctx->hasReturnCommand;
       
   190     g_paramsFound         = ctx->paramsFound;
       
   191   }
       
   192   g_memberDef           = ctx->memberDef;
       
   193   g_isExample           = ctx->isExample;
       
   194   g_exampleName         = ctx->exampleName;
       
   195   g_sectionDict         = ctx->sectionDict;
       
   196   g_searchUrl           = ctx->searchUrl;
       
   197 
       
   198   g_includeFileText     = ctx->includeFileText;
       
   199   g_includeFileOffset   = ctx->includeFileOffset;
       
   200   g_includeFileLength   = ctx->includeFileLength;
       
   201 
       
   202   delete g_token;
       
   203   g_token               = ctx->token;
       
   204 
       
   205   delete ctx;
       
   206   doctokenizerYYpopContext();
       
   207 
       
   208   //QCString indent;
       
   209   //indent.fill(' ',g_parserStack.count()*2+2);
       
   210   //printf("%sdocParserPopContext() count=%d\n",indent.data(),g_nodeStack.count());
       
   211 }
       
   212 
       
   213 //---------------------------------------------------------------------------
       
   214 
       
   215 /*! search for an image in the imageNameDict and if found
       
   216  * copies the image to the output directory (which depends on the \a type
       
   217  * parameter).
       
   218  */
       
   219 static QCString findAndCopyImage(const char *fileName,DocImage::Type type)
       
   220 {
       
   221   QCString result;
       
   222   bool ambig;
       
   223   FileDef *fd;
       
   224   //printf("Search for %s\n",fileName);
       
   225   if ((fd=findFileDef(Doxygen::imageNameDict,fileName,ambig)))
       
   226   {
       
   227     QCString inputFile = fd->absFilePath();
       
   228     QFile inImage(inputFile);
       
   229     if (inImage.open(IO_ReadOnly))
       
   230     {
       
   231       result = fileName;
       
   232       int i;
       
   233       if ((i=result.findRev('/'))!=-1 || (i=result.findRev('\\'))!=-1)
       
   234       {
       
   235 	result = result.right(result.length()-i-1);
       
   236       }
       
   237       //printf("fileName=%s result=%s\n",fileName,result.data());
       
   238       QCString outputDir;
       
   239       switch(type)
       
   240       {
       
   241         case DocImage::Html: 
       
   242 	  if (!Config_getBool("GENERATE_HTML")) return result;
       
   243 	  outputDir = Config_getString("HTML_OUTPUT");
       
   244 	  break;
       
   245         case DocImage::Latex: 
       
   246 	  if (!Config_getBool("GENERATE_LATEX")) return result;
       
   247 	  outputDir = Config_getString("LATEX_OUTPUT");
       
   248 	  break;
       
   249         case DocImage::Rtf:
       
   250 	  if (!Config_getBool("GENERATE_RTF")) return result;
       
   251 	  outputDir = Config_getString("RTF_OUTPUT");
       
   252 	  break;
       
   253       }
       
   254       QCString outputFile = outputDir+"/"+result;
       
   255       if (outputFile!=inputFile) // prevent copying to ourself
       
   256       {
       
   257         QFile outImage(outputFile.data());
       
   258         if (outImage.open(IO_WriteOnly)) // copy the image
       
   259         {
       
   260           char *buffer = new char[inImage.size()];
       
   261           inImage.readBlock(buffer,inImage.size());
       
   262           outImage.writeBlock(buffer,inImage.size());
       
   263           outImage.flush();
       
   264           delete[] buffer;
       
   265           if (type==DocImage::Html) Doxygen::indexList.addImageFile(result);
       
   266         }
       
   267         else
       
   268         {
       
   269           warn_doc_error(g_fileName,doctokenizerYYlineno,
       
   270               "Warning: could not write output image %s",outputFile.data());
       
   271         }
       
   272       }
       
   273     }
       
   274     else
       
   275     {
       
   276       warn_doc_error(g_fileName,doctokenizerYYlineno,
       
   277 	  "Warning: could not open image %s",fileName);
       
   278     }
       
   279 
       
   280     if (type==DocImage::Latex && Config_getBool("USE_PDFLATEX") && 
       
   281 	fd->name().right(4)==".eps"
       
   282        )
       
   283     { // we have an .eps image in pdflatex mode => convert it to a pdf.
       
   284       QCString outputDir = Config_getString("LATEX_OUTPUT");
       
   285       QCString baseName  = fd->name().left(fd->name().length()-4);
       
   286       QCString epstopdfArgs(4096);
       
   287       epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"",
       
   288                            outputDir.data(), baseName.data(),
       
   289 			   outputDir.data(), baseName.data());
       
   290       if (portable_system("epstopdf",epstopdfArgs)!=0)
       
   291       {
       
   292 	err("Error: Problems running epstopdf. Check your TeX installation!\n");
       
   293       }
       
   294       return baseName;
       
   295     }
       
   296   }
       
   297   else if (ambig)
       
   298   {
       
   299     QCString text;
       
   300     text.sprintf("Warning: image file name %s is ambigious.\n",fileName);
       
   301     text+="Possible candidates:\n";
       
   302     text+=showFileDefMatches(Doxygen::imageNameDict,fileName);
       
   303     warn_doc_error(g_fileName,doctokenizerYYlineno,text);
       
   304   }
       
   305   else
       
   306   {
       
   307     result=fileName;
       
   308     if (result.left(5)!="http:" && result.left(6)!="https:")
       
   309     {
       
   310       warn_doc_error(g_fileName,doctokenizerYYlineno,
       
   311            "Warning: image file %s is not found in IMAGE_PATH: "  
       
   312 	   "assuming external image.",fileName
       
   313           );
       
   314     }
       
   315   }
       
   316   return result;
       
   317 }
       
   318 
       
   319 /*! Collects the parameters found with \@param or \@retval commands
       
   320  *  in a global list g_paramsFound. If \a isParam is set to TRUE
       
   321  *  and the parameter is not an actual parameter of the current
       
   322  *  member g_memberDef, then a warning is raised (unless warnings
       
   323  *  are disabled altogether).
       
   324  */
       
   325 static void checkArgumentName(const QString &name,bool isParam)
       
   326 {                
       
   327   if (!Config_getBool("WARN_IF_DOC_ERROR")) return;
       
   328   if (g_memberDef==0) return; // not a member
       
   329   LockingPtr<ArgumentList> al=g_memberDef->isDocsForDefinition() ? 
       
   330 		   g_memberDef->argumentList() :
       
   331                    g_memberDef->declArgumentList();
       
   332   //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition());
       
   333   if (al==0) return; // no argument list
       
   334 
       
   335   static QRegExp re("[a-zA-Z0-9_\\x80-\\xFF]+\\.*");
       
   336   int p=0,i=0,l;
       
   337   while ((i=re.match(name,p,&l))!=-1) // to handle @param x,y
       
   338   {
       
   339     QString aName=name.mid(i,l);
       
   340     //printf("aName=`%s'\n",aName.data());
       
   341     ArgumentListIterator ali(*al);
       
   342     Argument *a;
       
   343     bool found=FALSE;
       
   344     for (ali.toFirst();(a=ali.current());++ali)
       
   345     {
       
   346       QString argName = g_memberDef->isDefine() ? a->type : a->name;
       
   347       argName=argName.stripWhiteSpace();
       
   348       //printf("argName=`%s'\n",argName.data());
       
   349       if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
       
   350       if (aName==argName) 
       
   351       {
       
   352 	//printf("adding `%s'\n",aName.data());
       
   353 	g_paramsFound.insert(aName,(void *)(0x8));
       
   354 	found=TRUE;
       
   355 	break;
       
   356       }
       
   357     }
       
   358     if (!found && isParam)
       
   359     {
       
   360       //printf("member type=%d\n",memberDef->memberType());
       
   361       QString scope=g_memberDef->getScopeString();
       
   362       if (!scope.isEmpty()) scope+="::"; else scope="";
       
   363       QString inheritedFrom = "";
       
   364       QString docFile = g_memberDef->docFile();
       
   365       int docLine = g_memberDef->docLine();
       
   366       MemberDef *inheritedMd = g_memberDef->inheritsDocsFrom();
       
   367       if (inheritedMd) // documentation was inherited
       
   368       {
       
   369         inheritedFrom.sprintf(" inherited from member %s at line "
       
   370             "%d in file %s",inheritedMd->name().data(),
       
   371             inheritedMd->docLine(),inheritedMd->docFile().data());
       
   372         docFile = g_memberDef->getDefFileName();
       
   373         docLine = g_memberDef->getDefLine();
       
   374         
       
   375       }
       
   376       warn_doc_error(docFile,docLine,
       
   377 	  "Warning: argument '%s' of command @param "
       
   378 	  "is not found in the argument list of %s%s%s%s",
       
   379 	  aName.data(),scope.data(),g_memberDef->name().data(),
       
   380 	  argListToString(al.pointer()).data(),inheritedFrom.data());
       
   381     }
       
   382     p=i+l;
       
   383   }
       
   384 }
       
   385 
       
   386 /*! Checks if the parameters that have been specified using \@param are
       
   387  *  indeed all paramters.
       
   388  *  Must be called after checkArgumentName() has been called for each
       
   389  *  argument.
       
   390  */
       
   391 static void checkUndocumentedParams()
       
   392 {
       
   393   if (g_memberDef && g_hasParamCommand && Config_getBool("WARN_IF_DOC_ERROR"))
       
   394   {
       
   395     LockingPtr<ArgumentList> al=g_memberDef->isDocsForDefinition() ? 
       
   396       g_memberDef->argumentList() :
       
   397       g_memberDef->declArgumentList();
       
   398     if (al!=0)
       
   399     {
       
   400       ArgumentListIterator ali(*al);
       
   401       Argument *a;
       
   402       bool found=FALSE;
       
   403       for (ali.toFirst();(a=ali.current());++ali)
       
   404       {
       
   405         QString argName = g_memberDef->isDefine() ? a->type : a->name;
       
   406         argName=argName.stripWhiteSpace();
       
   407         if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
       
   408         if (getLanguageFromFileName(g_memberDef->getDefFileName())==SrcLangExt_Python && argName=="self")
       
   409         { 
       
   410           // allow undocumented self parameter for Python
       
   411         }
       
   412         else if (!argName.isEmpty() && g_paramsFound.find(argName)==0 && a->docs.isEmpty()) 
       
   413         {
       
   414           found = TRUE;
       
   415           break;
       
   416         }
       
   417       }
       
   418       if (found)
       
   419       {
       
   420         bool first=TRUE;
       
   421         QString errMsg=
       
   422             "Warning: The following parameters of "+
       
   423             QString(g_memberDef->qualifiedName()) + 
       
   424             QString(argListToString(al.pointer())) +
       
   425             " are not documented:\n";
       
   426         for (ali.toFirst();(a=ali.current());++ali)
       
   427         {
       
   428           QString argName = g_memberDef->isDefine() ? a->type : a->name;
       
   429           argName=argName.stripWhiteSpace();
       
   430           if (getLanguageFromFileName(g_memberDef->getDefFileName())==SrcLangExt_Python && argName=="self")
       
   431           { 
       
   432             // allow undocumented self parameter for Python
       
   433           }
       
   434           else if (!argName.isEmpty() && g_paramsFound.find(argName)==0) 
       
   435           {
       
   436             if (!first)
       
   437             {
       
   438               errMsg+="\n";
       
   439             }
       
   440             else
       
   441             {
       
   442               first=FALSE;
       
   443             }
       
   444             errMsg+="  parameter '"+argName+"'";
       
   445           }
       
   446         }
       
   447         if (g_memberDef->inheritsDocsFrom())
       
   448         {
       
   449            warn_doc_error(g_memberDef->getDefFileName(),
       
   450                           g_memberDef->getDefLine(),
       
   451                           substitute(errMsg,"%","%%"));
       
   452         }
       
   453         else
       
   454         {
       
   455            warn_doc_error(g_memberDef->docFile(),
       
   456                           g_memberDef->docLine(),
       
   457                           substitute(errMsg,"%","%%"));
       
   458         }
       
   459       }
       
   460     }
       
   461   }
       
   462 }
       
   463 
       
   464 /*! Check if a member has documentation for its parameter and or return
       
   465  *  type, if applicable. If found this will be stored in the member, this
       
   466  *  is needed as a member can have brief and detailed documentation, while
       
   467  *  only one of these needs to document the parameters.
       
   468  */
       
   469 static void detectNoDocumentedParams()
       
   470 {
       
   471   if (g_memberDef && Config_getBool("WARN_NO_PARAMDOC"))
       
   472   {
       
   473     LockingPtr<ArgumentList> al     = g_memberDef->argumentList();
       
   474     LockingPtr<ArgumentList> declAl = g_memberDef->declArgumentList();
       
   475     QString returnType   = g_memberDef->typeString();
       
   476     bool isPython = getLanguageFromFileName(g_memberDef->getDefFileName())==SrcLangExt_Python;
       
   477 
       
   478     if (!g_memberDef->hasDocumentedParams() &&
       
   479         g_hasParamCommand)
       
   480     {
       
   481       //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
       
   482       g_memberDef->setHasDocumentedParams(TRUE);
       
   483     }
       
   484     else if (!g_memberDef->hasDocumentedParams())
       
   485     {
       
   486       bool allDoc=TRUE; // no paramater => all parameters are documented
       
   487       if ( // member has parameters
       
   488              al!=0 &&       // but the member has a parameter list
       
   489              al->count()>0  // with at least one parameter (that is not void)
       
   490          )
       
   491       {
       
   492         ArgumentListIterator ali(*al);
       
   493         Argument *a;
       
   494 
       
   495         // see if all parameters have documentation
       
   496         for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
       
   497         {
       
   498           if (!a->name.isEmpty() && a->type!="void" &&
       
   499               !(isPython && a->name=="self")
       
   500              )
       
   501           {
       
   502             allDoc = !a->docs.isEmpty();
       
   503           }
       
   504           //printf("a->type=%s a->name=%s doc=%s\n",
       
   505           //        a->type.data(),a->name.data(),a->docs.data());
       
   506         }
       
   507         if (!allDoc && declAl!=0) // try declaration arguments as well
       
   508         {
       
   509           allDoc=TRUE;
       
   510           ArgumentListIterator ali(*declAl);
       
   511           Argument *a;
       
   512           for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
       
   513           {
       
   514             if (!a->name.isEmpty() && a->type!="void" &&
       
   515                 !(isPython && a->name=="self")
       
   516                )
       
   517             {
       
   518               allDoc = !a->docs.isEmpty();
       
   519             }
       
   520             //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data());
       
   521           }
       
   522         }
       
   523       }
       
   524       if (allDoc) 
       
   525       {
       
   526         //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
       
   527         g_memberDef->setHasDocumentedParams(TRUE);
       
   528       }
       
   529     }
       
   530     //printf("Member %s hasReturnCommand=%d\n",g_memberDef->name().data(),g_hasReturnCommand);
       
   531     if (!g_memberDef->hasDocumentedReturnType() && // docs not yet found
       
   532         g_hasReturnCommand)
       
   533     {
       
   534       g_memberDef->setHasDocumentedReturnType(TRUE);
       
   535     }
       
   536     else if ( // see if return needs to documented 
       
   537         g_memberDef->hasDocumentedReturnType() ||
       
   538         returnType.isEmpty() ||          // empty return type
       
   539         returnType.find("void")!=-1  ||  // void return type
       
   540         !g_memberDef->isConstructor() || // a constructor
       
   541         !g_memberDef->isDestructor()     // or destructor
       
   542        )
       
   543     {
       
   544       g_memberDef->setHasDocumentedReturnType(TRUE);
       
   545     }
       
   546        
       
   547   }
       
   548 }
       
   549 
       
   550 
       
   551 //---------------------------------------------------------------------------
       
   552 
       
   553 /*! Strips known html and tex extensions from \a text. */
       
   554 static QString stripKnownExtensions(const char *text)
       
   555 {
       
   556   QString result=text;
       
   557   if (result.right(4)==".tex")
       
   558   {
       
   559     result=result.left(result.length()-4);
       
   560   }
       
   561   else if (result.right(Doxygen::htmlFileExtension.length())==
       
   562          QString(Doxygen::htmlFileExtension)) 
       
   563   {
       
   564     result=result.left(result.length()-Doxygen::htmlFileExtension.length());
       
   565   }
       
   566   return result;
       
   567 }
       
   568 
       
   569 
       
   570 //---------------------------------------------------------------------------
       
   571 
       
   572 /*! Returns TRUE iff node n is a child of a preformatted node */
       
   573 static bool insidePRE(DocNode *n)
       
   574 {
       
   575   while (n)
       
   576   {
       
   577     if (n->isPreformatted()) return TRUE;
       
   578     n=n->parent();
       
   579   }
       
   580   return FALSE;
       
   581 }
       
   582 
       
   583 //---------------------------------------------------------------------------
       
   584 
       
   585 /*! Returns TRUE iff node n is a child of a html list item node */
       
   586 static bool insideLI(DocNode *n)
       
   587 {
       
   588   while (n)
       
   589   {
       
   590     if (n->kind()==DocNode::Kind_HtmlListItem) return TRUE;
       
   591     n=n->parent();
       
   592   }
       
   593   return FALSE;
       
   594 }
       
   595 
       
   596 //---------------------------------------------------------------------------
       
   597 
       
   598 /*! Returns TRUE iff node n is a child of a unordered html list node */
       
   599 static bool insideUL(DocNode *n)
       
   600 {
       
   601   while (n)
       
   602   {
       
   603     if (n->kind()==DocNode::Kind_HtmlList && 
       
   604         ((DocHtmlList *)n)->type()==DocHtmlList::Unordered) return TRUE;
       
   605     n=n->parent();
       
   606   }
       
   607   return FALSE;
       
   608 }
       
   609 
       
   610 //---------------------------------------------------------------------------
       
   611 
       
   612 /*! Returns TRUE iff node n is a child of a ordered html list node */
       
   613 static bool insideOL(DocNode *n)
       
   614 {
       
   615   while (n)
       
   616   {
       
   617     if (n->kind()==DocNode::Kind_HtmlList && 
       
   618         ((DocHtmlList *)n)->type()==DocHtmlList::Ordered) return TRUE;
       
   619     n=n->parent();
       
   620   }
       
   621   return FALSE;
       
   622 }
       
   623 
       
   624 //---------------------------------------------------------------------------
       
   625 
       
   626 static bool insideTable(DocNode *n)
       
   627 {
       
   628   while (n)
       
   629   {
       
   630     if (n->kind()==DocNode::Kind_HtmlTable) return TRUE;
       
   631     n=n->parent();
       
   632   }
       
   633   return FALSE;
       
   634 }
       
   635 
       
   636 //---------------------------------------------------------------------------
       
   637 
       
   638 ///*! Returns TRUE iff node n is a child of a language node */
       
   639 //static bool insideLang(DocNode *n)
       
   640 //{
       
   641 //  while (n)
       
   642 //  {
       
   643 //    if (n->kind()==DocNode::Kind_Language) return TRUE;
       
   644 //    n=n->parent();
       
   645 //  }
       
   646 //  return FALSE;
       
   647 //}
       
   648 
       
   649 
       
   650 //---------------------------------------------------------------------------
       
   651 
       
   652 /*! Looks for a documentation block with name commandName in the current
       
   653  *  context (g_context). The resulting documentation string is
       
   654  *  put in pDoc, the definition in which the documentation was found is
       
   655  *  put in pDef.
       
   656  *  @retval TRUE if name was found.
       
   657  *  @retval FALSE if name was not found.
       
   658  */
       
   659 static bool findDocsForMemberOrCompound(const char *commandName,
       
   660                                  QString *pDoc,
       
   661                                  QString *pBrief,
       
   662                                  Definition **pDef)
       
   663 {
       
   664   //printf("findDocsForMemberOrCompound(%s)\n",commandName);
       
   665   *pDoc="";
       
   666   *pBrief="";
       
   667   *pDef=0;
       
   668   QString cmdArg=substitute(commandName,"#","::");
       
   669   int l=cmdArg.length();
       
   670   if (l==0) return FALSE;
       
   671 
       
   672   int funcStart=cmdArg.find('(');
       
   673   if (funcStart==-1) funcStart=l;
       
   674 
       
   675   QString name=removeRedundantWhiteSpace(cmdArg.left(funcStart).latin1());
       
   676   QString args=cmdArg.right(l-funcStart);
       
   677 
       
   678   // try if the link is to a member
       
   679   MemberDef    *md=0;
       
   680   ClassDef     *cd=0;
       
   681   FileDef      *fd=0;
       
   682   NamespaceDef *nd=0;
       
   683   GroupDef     *gd=0;
       
   684   PageDef      *pd=0;
       
   685   bool found = getDefs(
       
   686       g_context.find('.')==-1?g_context.latin1():"", // `find('.') is a hack to detect files
       
   687       name.latin1(),
       
   688       args.isEmpty()?0:args.latin1(),
       
   689       md,cd,fd,nd,gd,FALSE,0,TRUE);
       
   690   //printf("found=%d context=%s name=%s\n",found,g_context.data(),name.data());
       
   691   if (found && md)
       
   692   {
       
   693     *pDoc=md->documentation();
       
   694     *pBrief=md->briefDescription();
       
   695     *pDef=md;
       
   696     return TRUE;
       
   697   }
       
   698 
       
   699 
       
   700   int scopeOffset=g_context.length();
       
   701   do // for each scope
       
   702   {
       
   703     QString fullName=cmdArg;
       
   704     if (scopeOffset>0)
       
   705     {
       
   706       fullName.prepend(g_context.left(scopeOffset)+"::");
       
   707     }
       
   708     //printf("Trying fullName=`%s'\n",fullName.data());
       
   709 
       
   710     // try class, namespace, group, page, file reference
       
   711     cd = Doxygen::classSDict->find(fullName);
       
   712     if (cd) // class 
       
   713     {
       
   714       *pDoc=cd->documentation();
       
   715       *pBrief=cd->briefDescription();
       
   716       *pDef=cd;
       
   717       return TRUE;
       
   718     }
       
   719     nd = Doxygen::namespaceSDict->find(fullName);
       
   720     if (nd) // namespace
       
   721     {
       
   722       *pDoc=nd->documentation();
       
   723       *pBrief=nd->briefDescription();
       
   724       *pDef=nd;
       
   725       return TRUE;
       
   726     }
       
   727     gd = Doxygen::groupSDict->find(cmdArg);
       
   728     if (gd) // group
       
   729     {
       
   730       *pDoc=gd->documentation();
       
   731       *pBrief=gd->briefDescription();
       
   732       *pDef=gd;
       
   733       return TRUE;
       
   734     }
       
   735     pd = Doxygen::pageSDict->find(cmdArg);
       
   736     if (pd) // page
       
   737     {
       
   738       *pDoc=pd->documentation();
       
   739       *pBrief=pd->briefDescription();
       
   740       *pDef=pd;
       
   741       return TRUE;
       
   742     }
       
   743     bool ambig;
       
   744     fd = findFileDef(Doxygen::inputNameDict,cmdArg,ambig);
       
   745     if (fd && !ambig) // file
       
   746     {
       
   747       *pDoc=fd->documentation();
       
   748       *pBrief=fd->briefDescription();
       
   749       *pDef=fd;
       
   750       return TRUE;
       
   751     }
       
   752 
       
   753     if (scopeOffset==0)
       
   754     {
       
   755       scopeOffset=-1;
       
   756     }
       
   757     else
       
   758     {
       
   759       scopeOffset = g_context.findRev("::",scopeOffset-1);
       
   760       if (scopeOffset==-1) scopeOffset=0;
       
   761     }
       
   762   } while (scopeOffset>=0);
       
   763 
       
   764   
       
   765   return FALSE;
       
   766 }
       
   767 //---------------------------------------------------------------------------
       
   768 
       
   769 // forward declaration
       
   770 static bool defaultHandleToken(DocNode *parent,int tok, 
       
   771                                QList<DocNode> &children,bool
       
   772                                handleWord=TRUE);
       
   773 
       
   774 
       
   775 static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
       
   776                                const QString &cmdName)
       
   777 {
       
   778   DBG(("handleStyleArgument(%s)\n",cmdName.data()));
       
   779   QString tokenName = g_token->name;
       
   780   int tok=doctokenizerYYlex();
       
   781   if (tok!=TK_WHITESPACE)
       
   782   {
       
   783     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
   784 	cmdName.data());
       
   785     return tok;
       
   786   }
       
   787   while ((tok=doctokenizerYYlex()) && 
       
   788           tok!=TK_WHITESPACE && 
       
   789           tok!=TK_NEWPARA &&
       
   790           tok!=TK_LISTITEM && 
       
   791           tok!=TK_ENDLIST
       
   792         )
       
   793   {
       
   794     static QRegExp specialChar("[.,|()\\[\\]:;\\?]");
       
   795     if (tok==TK_WORD && g_token->name.length()==1 && 
       
   796         g_token->name.find(specialChar)!=-1)
       
   797     {
       
   798       // special character that ends the markup command
       
   799       return tok;
       
   800     }
       
   801     if (!defaultHandleToken(parent,tok,children))
       
   802     {
       
   803       switch (tok)
       
   804       {
       
   805         case TK_COMMAND: 
       
   806 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command \\%s as the argument of a \\%s command",
       
   807 	       g_token->name.data(),cmdName.data());
       
   808           break;
       
   809         case TK_SYMBOL: 
       
   810 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found while handling command %s",
       
   811                g_token->name.data(),cmdName.data());
       
   812           break;
       
   813         case TK_HTMLTAG:
       
   814           if (insideLI(parent) && Mappers::htmlTagMapper->map(g_token->name) && g_token->endTag)
       
   815           { // ignore </li> as the end of a style command
       
   816             continue; 
       
   817           }
       
   818           return tok;
       
   819           break;
       
   820         default:
       
   821 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s while handling command %s",
       
   822 	       tokToString(tok),cmdName.data());
       
   823           break;
       
   824       }
       
   825       break;
       
   826     }
       
   827   }
       
   828   DBG(("handleStyleArgument(%s) end tok=%x\n",cmdName.data(),tok));
       
   829   return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST
       
   830          ) ? tok : RetVal_OK; 
       
   831 }
       
   832 
       
   833 /*! Called when a style change starts. For instance a \<b\> command is
       
   834  *  encountered.
       
   835  */
       
   836 static void handleStyleEnter(DocNode *parent,QList<DocNode> &children,
       
   837           DocStyleChange::Style s,const HtmlAttribList *attribs)
       
   838 {
       
   839   DBG(("HandleStyleEnter\n"));
       
   840   DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,TRUE,attribs);
       
   841   children.append(sc);
       
   842   g_styleStack.push(sc);
       
   843 }
       
   844 
       
   845 /*! Called when a style change ends. For instance a \</b\> command is
       
   846  *  encountered.
       
   847  */
       
   848 static void handleStyleLeave(DocNode *parent,QList<DocNode> &children,
       
   849          DocStyleChange::Style s,const char *tagName)
       
   850 {
       
   851   DBG(("HandleStyleLeave\n"));
       
   852   if (g_styleStack.isEmpty() ||                           // no style change
       
   853       g_styleStack.top()->style()!=s ||                   // wrong style change
       
   854       g_styleStack.top()->position()!=g_nodeStack.count() // wrong position
       
   855      )
       
   856   {
       
   857     if (g_styleStack.isEmpty())
       
   858     {
       
   859       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </%s> tag without matching <%s>",
       
   860           tagName,tagName);
       
   861     }
       
   862     else
       
   863     {
       
   864       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </%s> tag while expecting </%s>",
       
   865           tagName,g_styleStack.top()->styleString());
       
   866     }
       
   867   }
       
   868   else // end the section
       
   869   {
       
   870     DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,FALSE);
       
   871     children.append(sc);
       
   872     g_styleStack.pop();
       
   873   }
       
   874 }
       
   875 
       
   876 /*! Called at the end of a paragraph to close all open style changes
       
   877  *  (e.g. a <b> without a </b>). The closed styles are pushed onto a stack
       
   878  *  and entered again at the start of a new paragraph.
       
   879  */
       
   880 static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children)
       
   881 {
       
   882   if (!g_styleStack.isEmpty())
       
   883   {
       
   884     DocStyleChange *sc = g_styleStack.top();
       
   885     while (sc && sc->position()>=g_nodeStack.count()) 
       
   886     { // there are unclosed style modifiers in the paragraph
       
   887       children.append(new DocStyleChange(parent,g_nodeStack.count(),sc->style(),FALSE));
       
   888       g_initialStyleStack.push(sc);
       
   889       g_styleStack.pop();
       
   890       sc = g_styleStack.top();
       
   891     }
       
   892   }
       
   893 }
       
   894 
       
   895 static void handleInitialStyleCommands(DocPara *parent,QList<DocNode> &children)
       
   896 {
       
   897   DocStyleChange *sc;
       
   898   while ((sc=g_initialStyleStack.pop()))
       
   899   {
       
   900     handleStyleEnter(parent,children,sc->style(),&sc->attribs());
       
   901   }
       
   902 }
       
   903 
       
   904 static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs)
       
   905 {
       
   906   HtmlAttribListIterator li(tagHtmlAttribs);
       
   907   HtmlAttrib *opt;
       
   908   int index=0;
       
   909   int retval = RetVal_OK;
       
   910   for (li.toFirst();(opt=li.current());++li,++index)
       
   911   {
       
   912     if (opt->name=="name") // <a name=label> tag
       
   913     {
       
   914       if (!opt->value.isEmpty())
       
   915       {
       
   916         DocAnchor *anc = new DocAnchor(parent,opt->value,TRUE);
       
   917         children.append(anc);
       
   918         break; // stop looking for other tag attribs
       
   919       }
       
   920       else
       
   921       {
       
   922         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found <a> tag with name option but without value!");
       
   923       }
       
   924     }
       
   925     else if (opt->name=="href") // <a href=url>..</a> tag
       
   926     {
       
   927       // copy attributes
       
   928       HtmlAttribList attrList = tagHtmlAttribs;
       
   929       // and remove the href attribute
       
   930       bool result = attrList.remove(index);
       
   931       ASSERT(result);
       
   932       DocHRef *href = new DocHRef(parent,attrList,opt->value);
       
   933       children.append(href);
       
   934       g_insideHtmlLink=TRUE;
       
   935       retval = href->parse();
       
   936       g_insideHtmlLink=FALSE;
       
   937       break;
       
   938     }
       
   939     else // unsupported option for tag a
       
   940     {
       
   941     }
       
   942   }
       
   943   return retval;
       
   944 }
       
   945 
       
   946 const char *DocStyleChange::styleString() const
       
   947 {
       
   948   switch (m_style)
       
   949   {
       
   950     case DocStyleChange::Bold:         return "b"; 
       
   951     case DocStyleChange::Italic:       return "em"; 
       
   952     case DocStyleChange::Code:         return "code"; 
       
   953     case DocStyleChange::Center:       return "center"; 
       
   954     case DocStyleChange::Small:        return "small"; 
       
   955     case DocStyleChange::Subscript:    return "subscript"; 
       
   956     case DocStyleChange::Superscript:  return "superscript"; 
       
   957     case DocStyleChange::Preformatted: return "pre"; 
       
   958     case DocStyleChange::Div:          return "div";
       
   959     case DocStyleChange::Span:         return "span";
       
   960   }
       
   961   return "<invalid>";
       
   962 }
       
   963 
       
   964 static void handleUnclosedStyleCommands()
       
   965 {
       
   966   if (!g_initialStyleStack.isEmpty())
       
   967   {
       
   968     DocStyleChange *sc = g_initialStyleStack.top();
       
   969     g_initialStyleStack.pop();
       
   970     handleUnclosedStyleCommands();
       
   971     warn_doc_error(g_fileName,doctokenizerYYlineno,
       
   972              "Warning: end of comment block while expecting "
       
   973              "command </%s>",sc->styleString());
       
   974   }
       
   975 }
       
   976 
       
   977 
       
   978 static void handleLinkedWord(DocNode *parent,QList<DocNode> &children)
       
   979 {
       
   980   Definition *compound=0;
       
   981   MemberDef  *member=0;
       
   982   QString name = linkToText(g_token->name,TRUE);
       
   983   int len = g_token->name.length();
       
   984   ClassDef *cd=0;
       
   985   bool ambig;
       
   986   FileDef *fd = findFileDef(Doxygen::inputNameDict,g_fileName,ambig);
       
   987   //printf("handleLinkedWord(%s) g_context=%s\n",name.data(),g_context.data());
       
   988   if (!g_insideHtmlLink && 
       
   989       (resolveRef(g_context,g_token->name,g_inSeeBlock,&compound,&member,TRUE,fd)
       
   990        || (!g_context.isEmpty() &&  // also try with global scope
       
   991            resolveRef("",g_token->name,g_inSeeBlock,&compound,&member))
       
   992       )
       
   993      )
       
   994   {
       
   995     //printf("resolveRef %s = %p (linkable?=%d)\n",g_token->name.data(),member,member ? member->isLinkable() : FALSE);
       
   996     if (member && member->isLinkable()) // member link
       
   997     {
       
   998       if (member->isObjCMethod()) 
       
   999       {
       
  1000         bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE;
       
  1001         name = member->objCMethodName(localLink,g_inSeeBlock);
       
  1002       }
       
  1003       children.append(new 
       
  1004           DocLinkedWord(parent,name,
       
  1005             member->getReference(),
       
  1006             member->getOutputFileBase(),
       
  1007             member->anchor(),
       
  1008             member->briefDescriptionAsTooltip()
       
  1009                        )
       
  1010                      );
       
  1011     }
       
  1012     else if (compound->isLinkable()) // compound link
       
  1013     {
       
  1014       if (compound->definitionType()==Definition::TypeFile)
       
  1015       {
       
  1016         name=g_token->name;
       
  1017       }
       
  1018       else if (compound->definitionType()==Definition::TypeGroup)
       
  1019       {
       
  1020         name=((GroupDef*)compound)->groupTitle();
       
  1021       }
       
  1022       children.append(new 
       
  1023           DocLinkedWord(parent,name,
       
  1024                         compound->getReference(),
       
  1025                         compound->getOutputFileBase(),
       
  1026                         "",
       
  1027                         compound->briefDescriptionAsTooltip()
       
  1028                        )
       
  1029                      );
       
  1030     }
       
  1031     else if (compound->definitionType()==Definition::TypeFile &&
       
  1032              ((FileDef*)compound)->generateSourceFile()
       
  1033             ) // undocumented file that has source code we can link to
       
  1034     {
       
  1035       children.append(new 
       
  1036           DocLinkedWord(parent,g_token->name,
       
  1037                          compound->getReference(),
       
  1038                          compound->getSourceFileBase(),
       
  1039                          "",
       
  1040                          compound->briefDescriptionAsTooltip()
       
  1041                        )
       
  1042                      );
       
  1043     }
       
  1044     else // not linkable
       
  1045     {
       
  1046       children.append(new DocWord(parent,name));
       
  1047     }
       
  1048   }
       
  1049   else if (!g_insideHtmlLink && len>1 && g_token->name.at(len-1)==':')
       
  1050   {
       
  1051     // special case, where matching Foo: fails to be an Obj-C reference, 
       
  1052     // but Foo itself might be linkable.
       
  1053     g_token->name=g_token->name.left(len-1);
       
  1054     handleLinkedWord(parent,children);
       
  1055     children.append(new DocWord(parent,":"));
       
  1056   }
       
  1057   else if (!g_insideHtmlLink && (cd=getClass(g_token->name+"-p")))
       
  1058   {
       
  1059     // special case 2, where the token name is not a class, but could
       
  1060     // be a Obj-C protocol
       
  1061     children.append(new 
       
  1062         DocLinkedWord(parent,name,
       
  1063           cd->getReference(),
       
  1064           cd->getOutputFileBase(),
       
  1065           "",
       
  1066           cd->briefDescriptionAsTooltip()
       
  1067           ));
       
  1068   }
       
  1069   else // normal non-linkable word
       
  1070   {
       
  1071     if (g_token->name.at(0)=='#')
       
  1072     {
       
  1073       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: explicit link request to '%s' could not be resolved",name.data());
       
  1074     }
       
  1075     children.append(new DocWord(parent,name));
       
  1076   }
       
  1077 }
       
  1078 
       
  1079 /* Helper function that deals with the most common tokens allowed in
       
  1080  * title like sections. 
       
  1081  * @param parent     Parent node, owner of the children list passed as 
       
  1082  *                   the third argument. 
       
  1083  * @param tok        The token to process.
       
  1084  * @param children   The list of child nodes to which the node representing
       
  1085  *                   the token can be added.
       
  1086  * @param handleWord Indicates if word token should be processed
       
  1087  * @retval TRUE      The token was handled.
       
  1088  * @retval FALSE     The token was not handled.
       
  1089  */
       
  1090 static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool
       
  1091     handleWord)
       
  1092 {
       
  1093   DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
       
  1094   if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || 
       
  1095       tok==TK_COMMAND || tok==TK_HTMLTAG
       
  1096      )
       
  1097   {
       
  1098     DBG((" name=%s",g_token->name.data()));
       
  1099   }
       
  1100   DBG(("\n"));
       
  1101 reparsetoken:
       
  1102   QString tokenName = g_token->name;
       
  1103   switch (tok)
       
  1104   {
       
  1105     case TK_COMMAND: 
       
  1106       switch (Mappers::cmdMapper->map(tokenName))
       
  1107       {
       
  1108         case CMD_BSLASH:
       
  1109           children.append(new DocSymbol(parent,DocSymbol::BSlash));
       
  1110           break;
       
  1111         case CMD_AT:
       
  1112           children.append(new DocSymbol(parent,DocSymbol::At));
       
  1113           break;
       
  1114         case CMD_LESS:
       
  1115           children.append(new DocSymbol(parent,DocSymbol::Less));
       
  1116           break;
       
  1117         case CMD_GREATER:
       
  1118           children.append(new DocSymbol(parent,DocSymbol::Greater));
       
  1119           break;
       
  1120         case CMD_AMP:
       
  1121           children.append(new DocSymbol(parent,DocSymbol::Amp));
       
  1122           break;
       
  1123         case CMD_DOLLAR:
       
  1124           children.append(new DocSymbol(parent,DocSymbol::Dollar));
       
  1125           break;
       
  1126         case CMD_HASH:
       
  1127           children.append(new DocSymbol(parent,DocSymbol::Hash));
       
  1128           break;
       
  1129         case CMD_PERCENT:
       
  1130           children.append(new DocSymbol(parent,DocSymbol::Percent));
       
  1131           break;
       
  1132         case CMD_QUOTE:
       
  1133           children.append(new DocSymbol(parent,DocSymbol::Quot));
       
  1134           break;
       
  1135         case CMD_EMPHASIS:
       
  1136           {
       
  1137             children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
       
  1138             tok=handleStyleArgument(parent,children,tokenName);
       
  1139             children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
       
  1140             if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
       
  1141             if (tok==TK_NEWPARA) goto handlepara;
       
  1142             else if (tok==TK_WORD || tok==TK_HTMLTAG) 
       
  1143             {
       
  1144 	      DBG(("CMD_EMPHASIS: reparsing command %s\n",g_token->name.data()));
       
  1145               goto reparsetoken;
       
  1146             }
       
  1147           }
       
  1148           break;
       
  1149         case CMD_BOLD:
       
  1150           {
       
  1151             children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
       
  1152             tok=handleStyleArgument(parent,children,tokenName);
       
  1153             children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
       
  1154             if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
       
  1155             if (tok==TK_NEWPARA) goto handlepara;
       
  1156             else if (tok==TK_WORD || tok==TK_HTMLTAG) 
       
  1157             {
       
  1158 	      DBG(("CMD_BOLD: reparsing command %s\n",g_token->name.data()));
       
  1159               goto reparsetoken;
       
  1160             }
       
  1161           }
       
  1162           break;
       
  1163         case CMD_CODE:
       
  1164           {
       
  1165             children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,TRUE));
       
  1166             tok=handleStyleArgument(parent,children,tokenName);
       
  1167             children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,FALSE));
       
  1168             if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
       
  1169             if (tok==TK_NEWPARA) goto handlepara;
       
  1170             else if (tok==TK_WORD || tok==TK_HTMLTAG) 
       
  1171             {
       
  1172 	      DBG(("CMD_CODE: reparsing command %s\n",g_token->name.data()));
       
  1173               goto reparsetoken;
       
  1174             }
       
  1175           }
       
  1176           break;
       
  1177         case CMD_HTMLONLY:
       
  1178           {
       
  1179             doctokenizerYYsetStateHtmlOnly();
       
  1180             tok = doctokenizerYYlex();
       
  1181             children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName));
       
  1182             if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: htmlonly section ended without end marker");
       
  1183             doctokenizerYYsetStatePara();
       
  1184           }
       
  1185           break;
       
  1186         case CMD_MANONLY:
       
  1187           {
       
  1188             doctokenizerYYsetStateManOnly();
       
  1189             tok = doctokenizerYYlex();
       
  1190             children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName));
       
  1191             if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: manonly section ended without end marker");
       
  1192             doctokenizerYYsetStatePara();
       
  1193           }
       
  1194           break;
       
  1195         case CMD_LATEXONLY:
       
  1196           {
       
  1197             doctokenizerYYsetStateLatexOnly();
       
  1198             tok = doctokenizerYYlex();
       
  1199             children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName));
       
  1200             if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: latexonly section ended without end marker",doctokenizerYYlineno);
       
  1201             doctokenizerYYsetStatePara();
       
  1202           }
       
  1203           break;
       
  1204         case CMD_XMLONLY:
       
  1205           {
       
  1206             doctokenizerYYsetStateXmlOnly();
       
  1207             tok = doctokenizerYYlex();
       
  1208             children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName));
       
  1209             if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: xmlonly section ended without end marker",doctokenizerYYlineno);
       
  1210             doctokenizerYYsetStatePara();
       
  1211           }
       
  1212           break;
       
  1213         case CMD_FORMULA:
       
  1214           {
       
  1215             DocFormula *form=new DocFormula(parent,g_token->id);
       
  1216             children.append(form);
       
  1217           }
       
  1218           break;
       
  1219         case CMD_ANCHOR:
       
  1220           {
       
  1221             tok=doctokenizerYYlex();
       
  1222             if (tok!=TK_WHITESPACE)
       
  1223             {
       
  1224               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  1225                   tokenName.data());
       
  1226               break;
       
  1227             }
       
  1228             tok=doctokenizerYYlex();
       
  1229             if (tok==0)
       
  1230             {
       
  1231               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the "
       
  1232                   "argument of command %s",tokenName.data());
       
  1233               break;
       
  1234             }
       
  1235             else if (tok!=TK_WORD && tok!=TK_LNKWORD)
       
  1236             {
       
  1237               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  1238                   tokToString(tok),tokenName.data());
       
  1239               break;
       
  1240             }
       
  1241             DocAnchor *anchor = new DocAnchor(parent,g_token->name,FALSE);
       
  1242             children.append(anchor);
       
  1243           }
       
  1244           break;
       
  1245         case CMD_INTERNALREF:
       
  1246           {
       
  1247             tok=doctokenizerYYlex();
       
  1248             if (tok!=TK_WHITESPACE)
       
  1249             {
       
  1250               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  1251                   tokenName.data());
       
  1252               break;
       
  1253             }
       
  1254             doctokenizerYYsetStateInternalRef();
       
  1255             tok=doctokenizerYYlex(); // get the reference id
       
  1256             DocInternalRef *ref=0;
       
  1257             if (tok!=TK_WORD && tok!=TK_LNKWORD)
       
  1258             {
       
  1259               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  1260                   tokToString(tok),tokenName.data());
       
  1261               doctokenizerYYsetStatePara();
       
  1262               break;
       
  1263             }
       
  1264             ref = new DocInternalRef(parent,g_token->name);
       
  1265             children.append(ref);
       
  1266             ref->parse();
       
  1267             doctokenizerYYsetStatePara();
       
  1268           }
       
  1269           break;
       
  1270         default:
       
  1271           return FALSE;
       
  1272       }
       
  1273       break;
       
  1274     case TK_HTMLTAG:
       
  1275       {
       
  1276         switch (Mappers::htmlTagMapper->map(tokenName))
       
  1277         {
       
  1278           case HTML_DIV:
       
  1279             warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found <div> tag in heading\n");
       
  1280             break;
       
  1281           case HTML_PRE:
       
  1282             warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found <pre> tag in heading\n");
       
  1283             break;
       
  1284           case HTML_BOLD:
       
  1285             if (!g_token->endTag)
       
  1286             {
       
  1287               handleStyleEnter(parent,children,DocStyleChange::Bold,&g_token->attribs);
       
  1288             }
       
  1289             else
       
  1290             {
       
  1291               handleStyleLeave(parent,children,DocStyleChange::Bold,tokenName);
       
  1292             }
       
  1293             break;
       
  1294           case HTML_CODE:
       
  1295           case XML_C:
       
  1296             if (!g_token->endTag)
       
  1297             {
       
  1298               handleStyleEnter(parent,children,DocStyleChange::Code,&g_token->attribs);
       
  1299             }
       
  1300             else
       
  1301             {
       
  1302               handleStyleLeave(parent,children,DocStyleChange::Code,tokenName);
       
  1303             }
       
  1304             break;
       
  1305           case HTML_EMPHASIS:
       
  1306             if (!g_token->endTag)
       
  1307             {
       
  1308               handleStyleEnter(parent,children,DocStyleChange::Italic,&g_token->attribs);
       
  1309             }
       
  1310             else
       
  1311             {
       
  1312               handleStyleLeave(parent,children,DocStyleChange::Italic,tokenName);
       
  1313             }
       
  1314             break;
       
  1315           case HTML_SUB:
       
  1316             if (!g_token->endTag)
       
  1317             {
       
  1318               handleStyleEnter(parent,children,DocStyleChange::Subscript,&g_token->attribs);
       
  1319             }
       
  1320             else
       
  1321             {
       
  1322               handleStyleLeave(parent,children,DocStyleChange::Subscript,tokenName);
       
  1323             }
       
  1324             break;
       
  1325           case HTML_SUP:
       
  1326             if (!g_token->endTag)
       
  1327             {
       
  1328               handleStyleEnter(parent,children,DocStyleChange::Superscript,&g_token->attribs);
       
  1329             }
       
  1330             else
       
  1331             {
       
  1332               handleStyleLeave(parent,children,DocStyleChange::Superscript,tokenName);
       
  1333             }
       
  1334             break;
       
  1335           case HTML_CENTER:
       
  1336             if (!g_token->endTag)
       
  1337             {
       
  1338               handleStyleEnter(parent,children,DocStyleChange::Center,&g_token->attribs);
       
  1339             }
       
  1340             else
       
  1341             {
       
  1342               handleStyleLeave(parent,children,DocStyleChange::Center,tokenName);
       
  1343             }
       
  1344             break;
       
  1345           case HTML_SMALL:
       
  1346             if (!g_token->endTag)
       
  1347             {
       
  1348               handleStyleEnter(parent,children,DocStyleChange::Small,&g_token->attribs);
       
  1349             }
       
  1350             else
       
  1351             {
       
  1352               handleStyleLeave(parent,children,DocStyleChange::Small,tokenName);
       
  1353             }
       
  1354             break;
       
  1355           default:
       
  1356             return FALSE;
       
  1357             break;
       
  1358         }
       
  1359       }
       
  1360       break;
       
  1361     case TK_SYMBOL: 
       
  1362       {
       
  1363         char letter='\0';
       
  1364         DocSymbol::SymType s = DocSymbol::decodeSymbol(tokenName,&letter);
       
  1365         if (s!=DocSymbol::Unknown)
       
  1366         {
       
  1367           children.append(new DocSymbol(parent,s,letter));
       
  1368         }
       
  1369         else
       
  1370         {
       
  1371           return FALSE;
       
  1372         }
       
  1373       }
       
  1374       break;
       
  1375     case TK_WHITESPACE: 
       
  1376     case TK_NEWPARA: 
       
  1377 handlepara:
       
  1378       if (insidePRE(parent) || !children.isEmpty())
       
  1379       {
       
  1380         children.append(new DocWhiteSpace(parent,g_token->chars));
       
  1381       }
       
  1382       break;
       
  1383     case TK_LNKWORD: 
       
  1384       if (handleWord)
       
  1385       {
       
  1386         handleLinkedWord(parent,children);
       
  1387       }
       
  1388       else
       
  1389         return FALSE;
       
  1390       break;
       
  1391     case TK_WORD: 
       
  1392       if (handleWord)
       
  1393       {
       
  1394         children.append(new DocWord(parent,g_token->name));
       
  1395       }
       
  1396       else
       
  1397         return FALSE;
       
  1398       break;
       
  1399     case TK_URL:
       
  1400       if (g_insideHtmlLink)
       
  1401       {
       
  1402         children.append(new DocWord(parent,g_token->name));
       
  1403       }
       
  1404       else
       
  1405       {
       
  1406         children.append(new DocURL(parent,g_token->name,g_token->isEMailAddr));
       
  1407       }
       
  1408       break;
       
  1409     default:
       
  1410       return FALSE;
       
  1411   }
       
  1412   return TRUE;
       
  1413 }
       
  1414 
       
  1415 
       
  1416 //---------------------------------------------------------------------------
       
  1417 
       
  1418 DocSymbol::SymType DocSymbol::decodeSymbol(const QString &symName,char *letter)
       
  1419 {
       
  1420   int l=symName.length();
       
  1421   DBG(("decodeSymbol(%s) l=%d\n",symName.data(),l));
       
  1422   if      (symName=="&copy;")  return DocSymbol::Copy;
       
  1423   else if (symName=="&trade;") return DocSymbol::Tm;
       
  1424   else if (symName=="&tm;")    return DocSymbol::Tm; // alias for &trade;
       
  1425   else if (symName=="&reg;")   return DocSymbol::Reg;
       
  1426   else if (symName=="&lt;")    return DocSymbol::Less;
       
  1427   else if (symName=="&gt;")    return DocSymbol::Greater;
       
  1428   else if (symName=="&amp;")   return DocSymbol::Amp;
       
  1429   else if (symName=="&apos;")  return DocSymbol::Apos;
       
  1430   else if (symName=="&quot;")  return DocSymbol::Quot;
       
  1431   else if (symName=="&lsquo;") return DocSymbol::Lsquo;
       
  1432   else if (symName=="&rsquo;") return DocSymbol::Rsquo;
       
  1433   else if (symName=="&ldquo;") return DocSymbol::Ldquo;
       
  1434   else if (symName=="&rdquo;") return DocSymbol::Rdquo;
       
  1435   else if (symName=="&ndash;") return DocSymbol::Ndash;
       
  1436   else if (symName=="&mdash;") return DocSymbol::Mdash;
       
  1437   else if (symName=="&szlig;") return DocSymbol::Szlig;
       
  1438   else if (symName=="&nbsp;")  return DocSymbol::Nbsp;
       
  1439   else if (symName=="&AElig;") return DocSymbol::AElig;
       
  1440   else if (symName=="&aelig;") return DocSymbol::Aelig;
       
  1441   else if (l==6 && symName.right(4)=="uml;")  
       
  1442   {
       
  1443     *letter=symName.at(1);
       
  1444     return DocSymbol::Uml;
       
  1445   }
       
  1446   else if (l==8 && symName.right(6)=="acute;")  
       
  1447   {
       
  1448     *letter=symName.at(1);
       
  1449     return DocSymbol::Acute;
       
  1450   }
       
  1451   else if (l==8 && symName.right(6)=="grave;")
       
  1452   {
       
  1453     *letter=symName.at(1);
       
  1454     return DocSymbol::Grave;
       
  1455   }
       
  1456   else if (l==7 && symName.right(5)=="circ;")
       
  1457   {
       
  1458     *letter=symName.at(1);
       
  1459     return DocSymbol::Circ;
       
  1460   }
       
  1461   else if (l==8 && symName.right(6)=="tilde;")
       
  1462   {
       
  1463     *letter=symName.at(1);
       
  1464     return DocSymbol::Tilde;
       
  1465   }
       
  1466   else if (l==8 && symName.right(6)=="cedil;")
       
  1467   {
       
  1468     *letter=symName.at(1);
       
  1469     return DocSymbol::Cedil;
       
  1470   }
       
  1471   else if (l==7 && symName.right(5)=="ring;")
       
  1472   {
       
  1473     *letter=symName.at(1);
       
  1474     return DocSymbol::Ring;
       
  1475   }
       
  1476   else if (l==8 && symName.right(6)=="slash;")
       
  1477   {
       
  1478     *letter=symName.at(1);
       
  1479     return DocSymbol::Slash;
       
  1480   }
       
  1481   return DocSymbol::Unknown;
       
  1482 }
       
  1483 
       
  1484 //---------------------------------------------------------------------------
       
  1485 
       
  1486 static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children,
       
  1487                                     const QString &doc)
       
  1488 {
       
  1489   int retval = RetVal_OK;
       
  1490 
       
  1491   if (doc.isEmpty()) return retval;
       
  1492 
       
  1493   doctokenizerYYinit(doc,g_fileName);
       
  1494 
       
  1495   // first parse any number of paragraphs
       
  1496   bool isFirst=TRUE;
       
  1497   DocPara *lastPar=0;
       
  1498   if (!children.isEmpty() && children.last()->kind()==DocNode::Kind_Para)
       
  1499   { // last child item was a paragraph
       
  1500     lastPar = (DocPara*)children.last();
       
  1501     isFirst=FALSE;
       
  1502   }
       
  1503   do
       
  1504   {
       
  1505     DocPara *par = new DocPara(parent);
       
  1506     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  1507     retval=par->parse();
       
  1508     if (!par->isEmpty()) 
       
  1509     {
       
  1510       children.append(par);
       
  1511       if (lastPar) lastPar->markLast(FALSE);
       
  1512       lastPar=par;
       
  1513     }
       
  1514     else
       
  1515     {
       
  1516       delete par;
       
  1517     }
       
  1518   } while (retval==TK_NEWPARA);
       
  1519   if (lastPar) lastPar->markLast();
       
  1520 
       
  1521   return retval;
       
  1522 }
       
  1523 
       
  1524 //---------------------------------------------------------------------------
       
  1525 
       
  1526 static void readTextFileByName(const QString &file,QString &text)
       
  1527 {
       
  1528   bool ambig;
       
  1529   FileDef *fd;
       
  1530   if ((fd=findFileDef(Doxygen::exampleNameDict,file,ambig)))
       
  1531   {
       
  1532     text = fileToString(fd->absFilePath(),Config_getBool("FILTER_SOURCE_FILES"));
       
  1533   }
       
  1534   else if (ambig)
       
  1535   {
       
  1536     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included file name %s is ambigious"
       
  1537            "Possible candidates:\n%s",file.data(),
       
  1538            showFileDefMatches(Doxygen::exampleNameDict,file).data()
       
  1539           );
       
  1540   }
       
  1541   else
       
  1542   {
       
  1543     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included file %s is not found. "
       
  1544            "Check your EXAMPLE_PATH",file.data());
       
  1545   }
       
  1546 }
       
  1547 
       
  1548 //---------------------------------------------------------------------------
       
  1549 
       
  1550 DocWord::DocWord(DocNode *parent,const QString &word) : 
       
  1551       m_parent(parent), m_word(word) 
       
  1552 {
       
  1553   //printf("new word %s url=%s\n",word.data(),g_searchUrl.data());
       
  1554   if (Doxygen::searchIndex && !g_searchUrl.isEmpty())
       
  1555   {
       
  1556     Doxygen::searchIndex->addWord(word,FALSE);
       
  1557   }
       
  1558 }
       
  1559 
       
  1560 //---------------------------------------------------------------------------
       
  1561 
       
  1562 DocLinkedWord::DocLinkedWord(DocNode *parent,const QString &word,
       
  1563                   const QString &ref,const QString &file,
       
  1564                   const QString &anchor,const QString &tooltip) : 
       
  1565       m_parent(parent), m_word(word), m_ref(ref), 
       
  1566       m_file(file), m_relPath(g_relPath), m_anchor(anchor),
       
  1567       m_tooltip(tooltip)
       
  1568 {
       
  1569   //printf("new word %s url=%s\n",word.data(),g_searchUrl.data());
       
  1570   if (Doxygen::searchIndex && !g_searchUrl.isEmpty())
       
  1571   {
       
  1572     Doxygen::searchIndex->addWord(word,FALSE);
       
  1573   }
       
  1574 }
       
  1575 
       
  1576 //---------------------------------------------------------------------------
       
  1577 
       
  1578 DocAnchor::DocAnchor(DocNode *parent,const QString &id,bool newAnchor) 
       
  1579   : m_parent(parent)
       
  1580 {
       
  1581   if (id.isEmpty())
       
  1582   {
       
  1583     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Empty anchor label");
       
  1584   }
       
  1585   if (newAnchor) // found <a name="label">
       
  1586   {
       
  1587     m_anchor = id;
       
  1588   }
       
  1589   else // found \anchor label
       
  1590   {
       
  1591     SectionInfo *sec = Doxygen::sectionDict[id];
       
  1592     if (sec)
       
  1593     {
       
  1594       //printf("Found anchor %s\n",id.data());
       
  1595       m_file   = sec->fileName;
       
  1596       m_anchor = sec->label;
       
  1597       if (g_sectionDict && g_sectionDict->find(id)==0)
       
  1598       {
       
  1599         //printf("Inserting in dictionary!\n");
       
  1600         g_sectionDict->insert(id,sec);
       
  1601       }
       
  1602     }
       
  1603     else
       
  1604     {
       
  1605       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid anchor id `%s'",id.data());
       
  1606       m_anchor = "invalid";
       
  1607       m_file = "invalid";
       
  1608     }
       
  1609   }
       
  1610 }
       
  1611 
       
  1612 //---------------------------------------------------------------------------
       
  1613 
       
  1614 DocVerbatim::DocVerbatim(DocNode *parent,const QString &context,
       
  1615     const QString &text, Type t,bool isExample,
       
  1616     const QString &exampleFile) 
       
  1617   : m_parent(parent), m_context(context), m_text(text), m_type(t),
       
  1618     m_isExample(isExample), m_exampleFile(exampleFile), m_relPath(g_relPath) 
       
  1619 {
       
  1620 }
       
  1621 
       
  1622 
       
  1623 //---------------------------------------------------------------------------
       
  1624 
       
  1625 void DocInclude::parse()
       
  1626 {
       
  1627   DBG(("DocInclude::parse(file=%s,text=%s)\n",m_file.data(),m_text.data()));
       
  1628   switch(m_type)
       
  1629   {
       
  1630     case IncWithLines:
       
  1631       // fall through
       
  1632     case Include:
       
  1633       // fall through
       
  1634     case DontInclude:
       
  1635       readTextFileByName(m_file,m_text);
       
  1636       g_includeFileText   = m_text;
       
  1637       g_includeFileOffset = 0;
       
  1638       g_includeFileLength = m_text.length();
       
  1639       //printf("g_includeFile=<<%s>>\n",g_includeFileText.data());
       
  1640       break;
       
  1641     case VerbInclude: 
       
  1642       // fall through
       
  1643     case HtmlInclude:
       
  1644       readTextFileByName(m_file,m_text);
       
  1645       break;
       
  1646   }
       
  1647 }
       
  1648 
       
  1649 //---------------------------------------------------------------------------
       
  1650 
       
  1651 void DocIncOperator::parse()
       
  1652 {
       
  1653   const char *p = g_includeFileText;
       
  1654   uint l = g_includeFileLength;
       
  1655   uint o = g_includeFileOffset;
       
  1656   DBG(("DocIncOperator::parse() text=%s off=%d len=%d\n",p,o,l));
       
  1657   uint so = o,bo;
       
  1658   bool nonEmpty = FALSE;
       
  1659   switch(type())
       
  1660   {
       
  1661     case Line:
       
  1662       while (o<l)
       
  1663       {
       
  1664         char c = p[o];
       
  1665         if (c=='\n') 
       
  1666         {
       
  1667           if (nonEmpty) break; // we have a pattern to match
       
  1668           so=o+1; // no pattern, skip empty line
       
  1669         }
       
  1670         else if (!isspace((uchar)c)) // no white space char
       
  1671         {
       
  1672           nonEmpty=TRUE;
       
  1673         }
       
  1674         o++;
       
  1675       }
       
  1676       if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
       
  1677       {
       
  1678         m_text = g_includeFileText.mid(so,o-so);
       
  1679         DBG(("DocIncOperator::parse() Line: %s\n",m_text.data()));
       
  1680       }
       
  1681       g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
       
  1682       break;
       
  1683     case SkipLine:
       
  1684       while (o<l)
       
  1685       {
       
  1686         so=o;
       
  1687         while (o<l)
       
  1688         {
       
  1689           char c = p[o];
       
  1690           if (c=='\n')
       
  1691           {
       
  1692             if (nonEmpty) break; // we have a pattern to match
       
  1693             so=o+1; // no pattern, skip empty line
       
  1694           }
       
  1695           else if (!isspace((uchar)c)) // no white space char
       
  1696           {
       
  1697             nonEmpty=TRUE;
       
  1698           }
       
  1699           o++;
       
  1700         }
       
  1701         if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
       
  1702         {
       
  1703           m_text = g_includeFileText.mid(so,o-so);
       
  1704           DBG(("DocIncOperator::parse() SkipLine: %s\n",m_text.data()));
       
  1705           break;
       
  1706         }
       
  1707         o++; // skip new line
       
  1708       }
       
  1709       g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
       
  1710       break;
       
  1711     case Skip:
       
  1712       while (o<l)
       
  1713       {
       
  1714         so=o;
       
  1715         while (o<l)
       
  1716         {
       
  1717           char c = p[o];
       
  1718           if (c=='\n')
       
  1719           {
       
  1720             if (nonEmpty) break; // we have a pattern to match
       
  1721             so=o+1; // no pattern, skip empty line
       
  1722           }
       
  1723           else if (!isspace((uchar)c)) // no white space char
       
  1724           {
       
  1725             nonEmpty=TRUE;
       
  1726           }
       
  1727           o++;
       
  1728         }
       
  1729         if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
       
  1730         {
       
  1731           break;
       
  1732         }
       
  1733         o++; // skip new line
       
  1734       }
       
  1735       g_includeFileOffset = so; // set pointer to start of new line
       
  1736       break;
       
  1737     case Until:
       
  1738       bo=o;
       
  1739       while (o<l)
       
  1740       {
       
  1741         so=o;
       
  1742         while (o<l)
       
  1743         {
       
  1744           char c = p[o];
       
  1745           if (c=='\n')
       
  1746           {
       
  1747             if (nonEmpty) break; // we have a pattern to match
       
  1748             so=o+1; // no pattern, skip empty line
       
  1749           }
       
  1750           else if (!isspace((uchar)c)) // no white space char
       
  1751           {
       
  1752             nonEmpty=TRUE;
       
  1753           }
       
  1754           o++;
       
  1755         }
       
  1756         if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
       
  1757         {
       
  1758           m_text = g_includeFileText.mid(bo,o-bo);
       
  1759           DBG(("DocIncOperator::parse() Until: %s\n",m_text.data()));
       
  1760           break;
       
  1761         }
       
  1762         o++; // skip new line
       
  1763       }
       
  1764       g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
       
  1765       break;
       
  1766   }
       
  1767 }
       
  1768 
       
  1769 //---------------------------------------------------------------------------
       
  1770 
       
  1771 void DocCopy::parse()
       
  1772 {
       
  1773   QString doc,brief;
       
  1774   Definition *def;
       
  1775   if (findDocsForMemberOrCompound(m_link,&doc,&brief,&def))
       
  1776   {
       
  1777     if (g_copyStack.findRef(def)==-1) // definition not parsed earlier
       
  1778     {
       
  1779       bool         hasParamCommand  = g_hasParamCommand;
       
  1780       bool         hasReturnCommand = g_hasReturnCommand;
       
  1781       QDict<void>  paramsFound      = g_paramsFound;
       
  1782       //printf("..1 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
       
  1783       //      g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
       
  1784 
       
  1785       docParserPushContext(FALSE);
       
  1786       g_scope = def;
       
  1787       if (def->definitionType()==Definition::TypeMember && def->getOuterScope())
       
  1788       {
       
  1789         g_context=def->getOuterScope()->name();
       
  1790       }
       
  1791       else
       
  1792       {
       
  1793         g_context=def->name();
       
  1794       }
       
  1795       g_styleStack.clear();
       
  1796       g_nodeStack.clear();
       
  1797       g_copyStack.append(def);
       
  1798       // make sure the descriptions end with a newline, so the parser will correctly
       
  1799       // handle them in all cases.
       
  1800       //printf("doc='%s'\n",doc.data());
       
  1801       //printf("brief='%s'\n",brief.data());
       
  1802       if (m_copyBrief)
       
  1803       {
       
  1804         brief+='\n';
       
  1805         internalValidatingParseDoc(this,m_children,brief);
       
  1806 
       
  1807         //printf("..2 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
       
  1808         //    g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
       
  1809         hasParamCommand  = hasParamCommand  || g_hasParamCommand;
       
  1810         hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
       
  1811         QDictIterator<void> it(g_paramsFound);
       
  1812         void *item;
       
  1813         for (;(item=it.current());++it)
       
  1814         {
       
  1815           paramsFound.insert(it.currentKey(),it.current());
       
  1816         }
       
  1817       }
       
  1818       if (m_copyDetails)
       
  1819       {
       
  1820         doc+='\n';
       
  1821         internalValidatingParseDoc(this,m_children,doc);
       
  1822 
       
  1823         //printf("..3 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
       
  1824         //    g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
       
  1825         hasParamCommand  = hasParamCommand  || g_hasParamCommand;
       
  1826         hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
       
  1827         QDictIterator<void> it(g_paramsFound);
       
  1828         void *item;
       
  1829         for (;(item=it.current());++it)
       
  1830         {
       
  1831           paramsFound.insert(it.currentKey(),it.current());
       
  1832         }
       
  1833       }
       
  1834       g_copyStack.remove(def);
       
  1835       ASSERT(g_styleStack.isEmpty());
       
  1836       ASSERT(g_nodeStack.isEmpty());
       
  1837       docParserPopContext(TRUE);
       
  1838 
       
  1839       g_hasParamCommand  = hasParamCommand;
       
  1840       g_hasReturnCommand = hasReturnCommand;
       
  1841       g_paramsFound      = paramsFound;
       
  1842 
       
  1843       //printf("..4 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
       
  1844       //      g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
       
  1845     }
       
  1846     else // oops, recursion
       
  1847     {
       
  1848       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: recursive call chain of \\copydoc commands detected at %d\n",
       
  1849           doctokenizerYYlineno);
       
  1850     }
       
  1851   }
       
  1852   else
       
  1853   {
       
  1854     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: target %s of \\copydoc command not found",
       
  1855         m_link.data());
       
  1856   }
       
  1857 }
       
  1858 
       
  1859 //---------------------------------------------------------------------------
       
  1860 
       
  1861 DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) : 
       
  1862    m_parent(parent), m_id(id), m_key(key), m_relPath(g_relPath)
       
  1863 {
       
  1864 }
       
  1865 
       
  1866 bool DocXRefItem::parse()
       
  1867 {
       
  1868   QString listName;
       
  1869   RefList *refList = Doxygen::xrefLists->find(m_key); 
       
  1870   if (refList && 
       
  1871       (
       
  1872        // either not a built-in list or the list is enabled
       
  1873        (m_key!="todo"       || Config_getBool("GENERATE_TODOLIST")) && 
       
  1874        (m_key!="test"       || Config_getBool("GENERATE_TESTLIST")) && 
       
  1875        (m_key!="bug"        || Config_getBool("GENERATE_BUGLIST"))  && 
       
  1876        (m_key!="deprecated" || Config_getBool("GENERATE_DEPRECATEDLIST"))
       
  1877       ) 
       
  1878      )
       
  1879   {
       
  1880     RefItem *item = refList->getRefItem(m_id);
       
  1881     ASSERT(item!=0);
       
  1882     if (item)
       
  1883     {
       
  1884       if (g_memberDef && g_memberDef->name().at(0)=='@')
       
  1885       {
       
  1886         m_file   = "@";  // can't cross reference anonymous enum
       
  1887         m_anchor = "@";
       
  1888       }
       
  1889       else
       
  1890       {
       
  1891         m_file   = refList->listName();
       
  1892         m_anchor = item->listAnchor;
       
  1893       }
       
  1894       m_title  = refList->sectionTitle();
       
  1895       //printf("DocXRefItem: file=%s anchor=%s title=%s\n",
       
  1896       //    m_file.data(),m_anchor.data(),m_title.data());
       
  1897 
       
  1898       if (!item->text.isEmpty())
       
  1899       {
       
  1900         docParserPushContext();
       
  1901         internalValidatingParseDoc(this,m_children,item->text);
       
  1902         docParserPopContext();
       
  1903       }
       
  1904     }
       
  1905     return TRUE;
       
  1906   }
       
  1907   return FALSE;
       
  1908 }
       
  1909 
       
  1910 //---------------------------------------------------------------------------
       
  1911 
       
  1912 DocFormula::DocFormula(DocNode *parent,int id) :
       
  1913       m_parent(parent), m_relPath(g_relPath)
       
  1914 {
       
  1915   QString formCmd;
       
  1916   formCmd.sprintf("\\form#%d",id);
       
  1917   Formula *formula=Doxygen::formulaNameDict[formCmd];
       
  1918   if (formula)
       
  1919   {
       
  1920     m_id = formula->getId();
       
  1921     m_name.sprintf("form_%d",m_id);
       
  1922     m_text = formula->getFormulaText();
       
  1923   }
       
  1924 }
       
  1925 
       
  1926 //---------------------------------------------------------------------------
       
  1927 
       
  1928 //int DocLanguage::parse()
       
  1929 //{
       
  1930 //  int retval;
       
  1931 //  DBG(("DocLanguage::parse() start\n"));
       
  1932 //  g_nodeStack.push(this);
       
  1933 //
       
  1934 //  // parse one or more paragraphs
       
  1935 //  bool isFirst=TRUE;
       
  1936 //  DocPara *par=0;
       
  1937 //  do
       
  1938 //  {
       
  1939 //    par = new DocPara(this);
       
  1940 //    if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  1941 //    m_children.append(par);
       
  1942 //    retval=par->parse();
       
  1943 //  }
       
  1944 //  while (retval==TK_NEWPARA);
       
  1945 //  if (par) par->markLast();
       
  1946 //
       
  1947 //  DBG(("DocLanguage::parse() end\n"));
       
  1948 //  DocNode *n = g_nodeStack.pop();
       
  1949 //  ASSERT(n==this);
       
  1950 //  return retval;
       
  1951 //}
       
  1952 
       
  1953 //---------------------------------------------------------------------------
       
  1954 
       
  1955 void DocSecRefItem::parse()
       
  1956 {
       
  1957   DBG(("DocSecRefItem::parse() start\n"));
       
  1958   g_nodeStack.push(this);
       
  1959 
       
  1960   doctokenizerYYsetStateTitle();
       
  1961   int tok;
       
  1962   while ((tok=doctokenizerYYlex()))
       
  1963   {
       
  1964     if (!defaultHandleToken(this,tok,m_children))
       
  1965     {
       
  1966       switch (tok)
       
  1967       {
       
  1968         case TK_COMMAND: 
       
  1969           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\refitem",
       
  1970 	       g_token->name.data());
       
  1971           break;
       
  1972         case TK_SYMBOL: 
       
  1973 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  1974                g_token->name.data());
       
  1975           break;
       
  1976         default:
       
  1977 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  1978 	       tokToString(tok));
       
  1979           break;
       
  1980       }
       
  1981     }
       
  1982   }
       
  1983   doctokenizerYYsetStatePara();
       
  1984   handlePendingStyleCommands(this,m_children);
       
  1985 
       
  1986   SectionInfo *sec=0;
       
  1987   if (!m_target.isEmpty())
       
  1988   {
       
  1989     sec=Doxygen::sectionDict[m_target];
       
  1990     if (sec)
       
  1991     {
       
  1992       m_file   = sec->fileName;
       
  1993       m_anchor = sec->label;
       
  1994       if (g_sectionDict && g_sectionDict->find(m_target)==0)
       
  1995       {
       
  1996         g_sectionDict->insert(m_target,sec);
       
  1997       }
       
  1998     }
       
  1999     else
       
  2000     {
       
  2001       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning reference to unknown section %s",
       
  2002           m_target.data());
       
  2003     }
       
  2004   } 
       
  2005   else
       
  2006   {
       
  2007     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning reference to empty target");
       
  2008   }
       
  2009   
       
  2010   DBG(("DocSecRefItem::parse() end\n"));
       
  2011   DocNode *n = g_nodeStack.pop();
       
  2012   ASSERT(n==this);
       
  2013 }
       
  2014 
       
  2015 //---------------------------------------------------------------------------
       
  2016 
       
  2017 void DocSecRefList::parse()
       
  2018 {
       
  2019   DBG(("DocSecRefList::parse() start\n"));
       
  2020   g_nodeStack.push(this);
       
  2021 
       
  2022   int tok=doctokenizerYYlex();
       
  2023   // skip white space
       
  2024   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  2025   // handle items
       
  2026   while (tok)
       
  2027   {
       
  2028     if (tok==TK_COMMAND)
       
  2029     {
       
  2030       switch (Mappers::cmdMapper->map(g_token->name))
       
  2031       {
       
  2032         case CMD_SECREFITEM:
       
  2033           {
       
  2034             int tok=doctokenizerYYlex();
       
  2035             if (tok!=TK_WHITESPACE)
       
  2036             {
       
  2037               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after \\refitem command");
       
  2038               break;
       
  2039             }
       
  2040             tok=doctokenizerYYlex();
       
  2041             if (tok!=TK_WORD && tok!=TK_LNKWORD)
       
  2042             {
       
  2043               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of \\refitem",
       
  2044                   tokToString(tok));
       
  2045               break;
       
  2046             }
       
  2047 
       
  2048             DocSecRefItem *item = new DocSecRefItem(this,g_token->name);
       
  2049             m_children.append(item);
       
  2050             item->parse();
       
  2051           }
       
  2052           break;
       
  2053         case CMD_ENDSECREFLIST:
       
  2054           goto endsecreflist;
       
  2055         default:
       
  2056           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\secreflist",
       
  2057               g_token->name.data());
       
  2058           goto endsecreflist;
       
  2059       }
       
  2060     }
       
  2061     else if (tok==TK_WHITESPACE)
       
  2062     {
       
  2063       // ignore whitespace
       
  2064     }
       
  2065     else
       
  2066     {
       
  2067       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s inside section reference list",
       
  2068           tokToString(tok));
       
  2069       goto endsecreflist;
       
  2070     }
       
  2071     tok=doctokenizerYYlex();
       
  2072   }
       
  2073 
       
  2074 endsecreflist:
       
  2075   DBG(("DocSecRefList::parse() end\n"));
       
  2076   DocNode *n = g_nodeStack.pop();
       
  2077   ASSERT(n==this);
       
  2078 }
       
  2079 
       
  2080 //---------------------------------------------------------------------------
       
  2081 
       
  2082 DocInternalRef::DocInternalRef(DocNode *parent,const QString &ref) 
       
  2083   : m_parent(parent), m_relPath(g_relPath)
       
  2084 {
       
  2085   int i=ref.find('#');
       
  2086   if (i!=-1)
       
  2087   {
       
  2088     m_anchor = ref.right(ref.length()-i-1);
       
  2089     m_file   = ref.left(i);
       
  2090   }
       
  2091   else
       
  2092   {
       
  2093     m_file = ref;
       
  2094   }
       
  2095 }
       
  2096 
       
  2097 void DocInternalRef::parse()
       
  2098 {
       
  2099   g_nodeStack.push(this);
       
  2100   DBG(("DocInternalRef::parse() start\n"));
       
  2101 
       
  2102   int tok;
       
  2103   while ((tok=doctokenizerYYlex()))
       
  2104   {
       
  2105     if (!defaultHandleToken(this,tok,m_children))
       
  2106     {
       
  2107       switch (tok)
       
  2108       {
       
  2109         case TK_COMMAND: 
       
  2110           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\ref",
       
  2111 	       g_token->name.data());
       
  2112           break;
       
  2113         case TK_SYMBOL: 
       
  2114 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2115                g_token->name.data());
       
  2116           break;
       
  2117         default:
       
  2118 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2119 		tokToString(tok));
       
  2120           break;
       
  2121       }
       
  2122     }
       
  2123   }
       
  2124 
       
  2125   handlePendingStyleCommands(this,m_children);
       
  2126   DBG(("DocInternalRef::parse() end\n"));
       
  2127   DocNode *n=g_nodeStack.pop();
       
  2128   ASSERT(n==this);
       
  2129 }
       
  2130 
       
  2131 //---------------------------------------------------------------------------
       
  2132 
       
  2133 DocRef::DocRef(DocNode *parent,const QString &target,const QString &context) : 
       
  2134    m_parent(parent), m_refToSection(FALSE), m_refToAnchor(FALSE)
       
  2135 {
       
  2136   Definition  *compound = 0;
       
  2137   QCString     anchor;
       
  2138   //printf("DocRef::DocRef(target=%s,context=%s\n",target.data(),context.data());
       
  2139   ASSERT(!target.isEmpty());
       
  2140   m_relPath = g_relPath;
       
  2141   SectionInfo *sec = Doxygen::sectionDict[target];
       
  2142   if (sec) // ref to section or anchor
       
  2143   {
       
  2144     m_text         = sec->title;
       
  2145     if (m_text.isEmpty()) m_text = sec->label;
       
  2146 
       
  2147     m_ref          = sec->ref;
       
  2148     m_file         = stripKnownExtensions(sec->fileName);
       
  2149     if (sec->type!=SectionInfo::Page) m_anchor = sec->label;
       
  2150     m_refToAnchor  = sec->type==SectionInfo::Anchor;
       
  2151     m_refToSection = sec->type!=SectionInfo::Anchor;
       
  2152     //printf("m_text=%s,m_ref=%s,m_file=%s,m_refToAnchor=%d type=%d\n",
       
  2153     //    m_text.data(),m_ref.data(),m_file.data(),m_refToAnchor,sec->type);
       
  2154     return;
       
  2155   }
       
  2156   else if (resolveLink(context,target,TRUE,&compound,anchor))
       
  2157   {
       
  2158     bool isFile = compound ? 
       
  2159                  (compound->definitionType()==Definition::TypeFile ? TRUE : FALSE) : 
       
  2160                  FALSE;
       
  2161     m_text = linkToText(target,isFile);
       
  2162     m_anchor = anchor;
       
  2163     if (compound && compound->isLinkable()) // ref to compound
       
  2164     {
       
  2165       if (anchor.isEmpty() &&                                  /* compound link */
       
  2166           compound->definitionType()==Definition::TypeGroup && /* is group */
       
  2167           ((GroupDef *)compound)->groupTitle()                 /* with title */
       
  2168          )
       
  2169       {
       
  2170         m_text=((GroupDef *)compound)->groupTitle(); // use group's title as link
       
  2171       }
       
  2172       else if (compound->definitionType()==Definition::TypeMember &&
       
  2173           ((MemberDef*)compound)->isObjCMethod())
       
  2174       {
       
  2175         // Objective C Method
       
  2176         MemberDef *member = (MemberDef*)compound;
       
  2177         bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE;
       
  2178         m_text = member->objCMethodName(localLink,g_inSeeBlock);
       
  2179       }
       
  2180 
       
  2181       m_file = compound->getOutputFileBase();
       
  2182       m_ref  = compound->getReference();
       
  2183       return;
       
  2184     }
       
  2185     else if (compound->definitionType()==Definition::TypeFile && 
       
  2186              ((FileDef*)compound)->generateSourceFile()
       
  2187             ) // undocumented file that has source code we can link to
       
  2188     {
       
  2189       m_file = compound->getSourceFileBase();
       
  2190       m_ref  = compound->getReference();
       
  2191       return;
       
  2192     }
       
  2193   }
       
  2194   m_text = linkToText(target,FALSE);
       
  2195   warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unable to resolve reference to `%s' for \\ref command",
       
  2196            target.data()); 
       
  2197   setDefinition(compound);
       
  2198 }
       
  2199 
       
  2200 static void flattenParagraphs(QList<DocNode> &children)
       
  2201 {
       
  2202   QListIterator<DocNode> li(children);
       
  2203   QList<DocNode> newChildren;
       
  2204   DocNode *dn;
       
  2205   for (li.toFirst();(dn=li.current());++li)
       
  2206   {
       
  2207     if (dn->kind()==DocNode::Kind_Para)
       
  2208     {
       
  2209       DocPara *para = (DocPara*)dn;
       
  2210       QList<DocNode> &paraChildren = para->children();
       
  2211       paraChildren.setAutoDelete(FALSE); // unlink children from paragraph node
       
  2212       QListIterator<DocNode> li2(paraChildren);
       
  2213       DocNode *dn2;
       
  2214       for (li2.toFirst();(dn2=li2.current());++li2)
       
  2215       {
       
  2216         newChildren.append(dn2); // add them to new node
       
  2217       }
       
  2218     }
       
  2219   }
       
  2220   children.clear();
       
  2221   QListIterator<DocNode> li3(newChildren);
       
  2222   for (li3.toFirst();(dn=li3.current());++li3)
       
  2223   {
       
  2224     children.append(dn);
       
  2225   }
       
  2226 }
       
  2227 
       
  2228 void DocRef::parse()
       
  2229 {
       
  2230   g_nodeStack.push(this);
       
  2231   DBG(("DocRef::parse() start\n"));
       
  2232 
       
  2233   int tok;
       
  2234   while ((tok=doctokenizerYYlex()))
       
  2235   {
       
  2236     if (!defaultHandleToken(this,tok,m_children))
       
  2237     {
       
  2238       switch (tok)
       
  2239       {
       
  2240         case TK_COMMAND: 
       
  2241           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\ref",
       
  2242 	       g_token->name.data());
       
  2243           break;
       
  2244         case TK_SYMBOL: 
       
  2245 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2246                g_token->name.data());
       
  2247           break;
       
  2248         case TK_HTMLTAG:
       
  2249           break;
       
  2250         default:
       
  2251 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2252 		tokToString(tok));
       
  2253           break;
       
  2254       }
       
  2255     }
       
  2256   }
       
  2257 
       
  2258   if (m_children.isEmpty() && !m_text.isEmpty())
       
  2259   {
       
  2260     g_insideHtmlLink=TRUE;
       
  2261     docParserPushContext();
       
  2262     internalValidatingParseDoc(this,m_children,m_text);
       
  2263     docParserPopContext();
       
  2264     g_insideHtmlLink=FALSE;
       
  2265     flattenParagraphs(m_children);
       
  2266   }
       
  2267 
       
  2268   handlePendingStyleCommands(this,m_children);
       
  2269   
       
  2270   DocNode *n=g_nodeStack.pop();
       
  2271   ASSERT(n==this);
       
  2272 }
       
  2273 
       
  2274 //---------------------------------------------------------------------------
       
  2275 
       
  2276 DocLink::DocLink(DocNode *parent,const QString &target) : 
       
  2277       m_parent(parent)
       
  2278 {
       
  2279   Definition *compound = 0;
       
  2280   //PageInfo *page;
       
  2281   QCString anchor;
       
  2282   m_refText = target;
       
  2283   m_relPath = g_relPath;
       
  2284   if (!m_refText.isEmpty() && m_refText.at(0)=='#')
       
  2285   {
       
  2286     m_refText = m_refText.right(m_refText.length()-1);
       
  2287   }
       
  2288   if (resolveLink(g_context,stripKnownExtensions(target),g_inSeeBlock,
       
  2289                   &compound,anchor))
       
  2290   {
       
  2291     m_anchor = anchor;
       
  2292     if (compound && compound->isLinkable())
       
  2293     {
       
  2294       m_file = compound->getOutputFileBase();
       
  2295       m_ref  = compound->getReference();
       
  2296     }
       
  2297     else if (compound->definitionType()==Definition::TypeFile && 
       
  2298              ((FileDef*)compound)->generateSourceFile()
       
  2299             ) // undocumented file that has source code we can link to
       
  2300     {
       
  2301       m_file = compound->getSourceFileBase();
       
  2302       m_ref  = compound->getReference();
       
  2303     }
       
  2304     setDefinition(compound);
       
  2305     return;
       
  2306   }
       
  2307 
       
  2308   setDefinition(compound);
       
  2309   // bogus link target
       
  2310   warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unable to resolve link to `%s' for \\link command",
       
  2311          target.data()); 
       
  2312 }
       
  2313 
       
  2314 
       
  2315 QString DocLink::parse(bool isJavaLink,bool isXmlLink)
       
  2316 {
       
  2317   QString result;
       
  2318   g_nodeStack.push(this);
       
  2319   DBG(("DocLink::parse() start\n"));
       
  2320 
       
  2321   int tok;
       
  2322   while ((tok=doctokenizerYYlex()))
       
  2323   {
       
  2324     if (!defaultHandleToken(this,tok,m_children,FALSE))
       
  2325     {
       
  2326       switch (tok)
       
  2327       {
       
  2328         case TK_COMMAND: 
       
  2329           switch (Mappers::cmdMapper->map(g_token->name))
       
  2330           {
       
  2331             case CMD_ENDLINK:
       
  2332               if (isJavaLink)
       
  2333               {
       
  2334                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: {@link.. ended with @endlink command");
       
  2335               }
       
  2336               goto endlink;
       
  2337             default:
       
  2338               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\link",
       
  2339                   g_token->name.data());
       
  2340               break;
       
  2341           }
       
  2342           break;
       
  2343         case TK_SYMBOL: 
       
  2344           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2345               g_token->name.data());
       
  2346           break;
       
  2347         case TK_HTMLTAG:
       
  2348           if (g_token->name!="see" || !isXmlLink)
       
  2349           {
       
  2350             warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected xml/html command %s found",
       
  2351                 g_token->name.data());
       
  2352           }
       
  2353           goto endlink;
       
  2354         case TK_LNKWORD: 
       
  2355         case TK_WORD: 
       
  2356           if (isJavaLink) // special case to detect closing }
       
  2357           {
       
  2358             QString w = g_token->name;
       
  2359             int p;
       
  2360             if (w=="}")
       
  2361             {
       
  2362               goto endlink;
       
  2363             }
       
  2364             else if ((p=w.find('}'))!=-1)
       
  2365             {
       
  2366               uint l=w.length();
       
  2367               m_children.append(new DocWord(this,w.left(p)));
       
  2368               if ((uint)p<l-1) // something left after the } (for instance a .)
       
  2369               {
       
  2370                 result=w.right(l-p-1);
       
  2371               }
       
  2372               goto endlink;
       
  2373             }
       
  2374           }
       
  2375           m_children.append(new DocWord(this,g_token->name));
       
  2376           break;
       
  2377         default:
       
  2378           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2379              tokToString(tok));
       
  2380         break;
       
  2381       }
       
  2382     }
       
  2383   }
       
  2384   if (tok==0)
       
  2385   {
       
  2386     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside"
       
  2387            " link command\n"); 
       
  2388   }
       
  2389 endlink:
       
  2390 
       
  2391   if (m_children.isEmpty()) // no link text
       
  2392   {
       
  2393     m_children.append(new DocWord(this,m_refText));
       
  2394   }
       
  2395 
       
  2396   handlePendingStyleCommands(this,m_children);
       
  2397   DBG(("DocLink::parse() end\n"));
       
  2398   DocNode *n=g_nodeStack.pop();
       
  2399   ASSERT(n==this);
       
  2400   return result;
       
  2401 }
       
  2402 
       
  2403 
       
  2404 //---------------------------------------------------------------------------
       
  2405 
       
  2406 DocDotFile::DocDotFile(DocNode *parent,const QString &name,const QString &context) : 
       
  2407       m_parent(parent), m_name(name), m_relPath(g_relPath), m_context(context)
       
  2408 {
       
  2409 }
       
  2410 
       
  2411 void DocDotFile::parse()
       
  2412 {
       
  2413   g_nodeStack.push(this);
       
  2414   DBG(("DocDotFile::parse() start\n"));
       
  2415 
       
  2416   doctokenizerYYsetStateTitle();
       
  2417   int tok;
       
  2418   while ((tok=doctokenizerYYlex()))
       
  2419   {
       
  2420     if (!defaultHandleToken(this,tok,m_children))
       
  2421     {
       
  2422       switch (tok)
       
  2423       {
       
  2424         case TK_COMMAND: 
       
  2425           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\dotfile",
       
  2426 	       g_token->name.data());
       
  2427           break;
       
  2428         case TK_SYMBOL: 
       
  2429 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2430                g_token->name.data());
       
  2431           break;
       
  2432         default:
       
  2433 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2434 		tokToString(tok));
       
  2435           break;
       
  2436       }
       
  2437     }
       
  2438   }
       
  2439   tok=doctokenizerYYlex();
       
  2440   while (tok==TK_WORD) // there are values following the title
       
  2441   {
       
  2442     if (g_token->name=="width") 
       
  2443     {
       
  2444       m_width=g_token->chars;
       
  2445     }
       
  2446     else if (g_token->name=="height") 
       
  2447     {
       
  2448       m_height=g_token->chars;
       
  2449     }
       
  2450     else 
       
  2451     {
       
  2452       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unknown option %s after image title",
       
  2453             g_token->name.data());
       
  2454     }
       
  2455     tok=doctokenizerYYlex();
       
  2456   }
       
  2457   ASSERT(tok==0);
       
  2458   doctokenizerYYsetStatePara();
       
  2459   handlePendingStyleCommands(this,m_children);
       
  2460 
       
  2461   bool ambig;
       
  2462   FileDef *fd = findFileDef(Doxygen::dotFileNameDict,m_name,ambig);
       
  2463   if (fd)
       
  2464   {
       
  2465     m_file = fd->absFilePath();
       
  2466   }
       
  2467   else if (ambig)
       
  2468   {
       
  2469     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included dot file name %s is ambigious.\n"
       
  2470            "Possible candidates:\n%s",m_name.data(),
       
  2471            showFileDefMatches(Doxygen::exampleNameDict,m_name).data()
       
  2472           );
       
  2473   }
       
  2474   else
       
  2475   {
       
  2476     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included dot file %s is not found "
       
  2477            "in any of the paths specified via DOTFILE_DIRS!",m_name.data());
       
  2478   }
       
  2479 
       
  2480   DBG(("DocDotFile::parse() end\n"));
       
  2481   DocNode *n=g_nodeStack.pop();
       
  2482   ASSERT(n==this);
       
  2483 }
       
  2484 
       
  2485 
       
  2486 //---------------------------------------------------------------------------
       
  2487 
       
  2488 DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QString &name,Type t) : 
       
  2489       m_parent(parent), m_attribs(attribs), m_name(name), 
       
  2490       m_type(t), m_relPath(g_relPath)
       
  2491 {
       
  2492 }
       
  2493 
       
  2494 void DocImage::parse()
       
  2495 {
       
  2496   g_nodeStack.push(this);
       
  2497   DBG(("DocImage::parse() start\n"));
       
  2498 
       
  2499   // parse title
       
  2500   doctokenizerYYsetStateTitle();
       
  2501   int tok;
       
  2502   while ((tok=doctokenizerYYlex()))
       
  2503   {
       
  2504     if (tok==TK_WORD && (g_token->name=="width=" || g_token->name=="height="))
       
  2505     {
       
  2506       // special case: no title, but we do have a size indicator
       
  2507       doctokenizerYYsetStateTitleAttrValue();
       
  2508       // strip =
       
  2509       g_token->name=g_token->name.left(g_token->name.length()-1);
       
  2510       break;
       
  2511     } 
       
  2512     if (!defaultHandleToken(this,tok,m_children))
       
  2513     {
       
  2514       switch (tok)
       
  2515       {
       
  2516         case TK_COMMAND: 
       
  2517           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\image",
       
  2518               g_token->name.data());
       
  2519           break;
       
  2520         case TK_SYMBOL: 
       
  2521           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2522               g_token->name.data());
       
  2523           break;
       
  2524         default:
       
  2525           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2526               tokToString(tok));
       
  2527           break;
       
  2528       }
       
  2529     }
       
  2530   }
       
  2531   // parse size attributes
       
  2532   tok=doctokenizerYYlex();
       
  2533   while (tok==TK_WORD) // there are values following the title
       
  2534   {
       
  2535     if (g_token->name=="width") 
       
  2536     {
       
  2537       m_width=g_token->chars;
       
  2538     }
       
  2539     else if (g_token->name=="height") 
       
  2540     {
       
  2541       m_height=g_token->chars;
       
  2542     }
       
  2543     else 
       
  2544     {
       
  2545       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unknown option %s after image title",
       
  2546           g_token->name.data());
       
  2547     }
       
  2548     tok=doctokenizerYYlex();
       
  2549   }
       
  2550   doctokenizerYYsetStatePara();
       
  2551 
       
  2552   handlePendingStyleCommands(this,m_children);
       
  2553   DBG(("DocImage::parse() end\n"));
       
  2554   DocNode *n=g_nodeStack.pop();
       
  2555   ASSERT(n==this);
       
  2556 }
       
  2557 
       
  2558 
       
  2559 //---------------------------------------------------------------------------
       
  2560 
       
  2561 int DocHtmlHeader::parse()
       
  2562 {
       
  2563   int retval=RetVal_OK;
       
  2564   g_nodeStack.push(this);
       
  2565   DBG(("DocHtmlHeader::parse() start\n"));
       
  2566 
       
  2567   int tok;
       
  2568   while ((tok=doctokenizerYYlex()))
       
  2569   {
       
  2570     if (!defaultHandleToken(this,tok,m_children))
       
  2571     {
       
  2572       switch (tok)
       
  2573       {
       
  2574         case TK_COMMAND: 
       
  2575           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <h%d> tag",
       
  2576 	       g_token->name.data(),m_level);
       
  2577           break;
       
  2578         case TK_HTMLTAG:
       
  2579           {
       
  2580             int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  2581             if (tagId==HTML_H1 && g_token->endTag) // found </h1> tag
       
  2582             {
       
  2583               if (m_level!=1)
       
  2584               {
       
  2585                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h1>",
       
  2586                     m_level); 
       
  2587               }
       
  2588               goto endheader;
       
  2589             }
       
  2590             else if (tagId==HTML_H2 && g_token->endTag) // found </h2> tag
       
  2591             {
       
  2592               if (m_level!=2)
       
  2593               {
       
  2594                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h2>",
       
  2595                     m_level); 
       
  2596               }
       
  2597               goto endheader;
       
  2598             }
       
  2599             else if (tagId==HTML_H3 && g_token->endTag) // found </h3> tag
       
  2600             {
       
  2601               if (m_level!=3)
       
  2602               {
       
  2603                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h3>",
       
  2604                     m_level); 
       
  2605               }
       
  2606               goto endheader;
       
  2607             }
       
  2608             else if (tagId==HTML_H4 && g_token->endTag) // found </h4> tag
       
  2609             {
       
  2610               if (m_level!=4)
       
  2611               {
       
  2612                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h4>",
       
  2613                     m_level); 
       
  2614               }
       
  2615               goto endheader;
       
  2616             }
       
  2617             else if (tagId==HTML_H5 && g_token->endTag) // found </h5> tag
       
  2618             {
       
  2619               if (m_level!=5)
       
  2620               {
       
  2621                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h5>",
       
  2622                     m_level); 
       
  2623               }
       
  2624               goto endheader;
       
  2625             }
       
  2626             else if (tagId==HTML_H6 && g_token->endTag) // found </h6> tag
       
  2627             {
       
  2628               if (m_level!=6)
       
  2629               {
       
  2630                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h6>",
       
  2631                     m_level); 
       
  2632               }
       
  2633               goto endheader;
       
  2634             }
       
  2635             else if (tagId==HTML_A)
       
  2636             {
       
  2637               if (!g_token->endTag)
       
  2638               {
       
  2639                 handleAHref(this,m_children,g_token->attribs);
       
  2640               }
       
  2641             }
       
  2642             else if (tagId==HTML_BR)
       
  2643             {
       
  2644               DocLineBreak *lb = new DocLineBreak(this);
       
  2645               m_children.append(lb);
       
  2646             }
       
  2647             else
       
  2648             {
       
  2649               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <h%d> context",
       
  2650                   g_token->endTag?"/":"",g_token->name.data(),m_level);
       
  2651             }
       
  2652             
       
  2653           }
       
  2654           break;
       
  2655         case TK_SYMBOL: 
       
  2656 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2657                g_token->name.data());
       
  2658           break;
       
  2659         default:
       
  2660 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2661 		tokToString(tok));
       
  2662           break;
       
  2663       }
       
  2664     }
       
  2665   }
       
  2666   if (tok==0)
       
  2667   {
       
  2668     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside"
       
  2669            " <h%d> tag\n",m_level); 
       
  2670   }
       
  2671 endheader:
       
  2672   handlePendingStyleCommands(this,m_children);
       
  2673   DBG(("DocHtmlHeader::parse() end\n"));
       
  2674   DocNode *n=g_nodeStack.pop();
       
  2675   ASSERT(n==this);
       
  2676   return retval;
       
  2677 }
       
  2678 
       
  2679 //---------------------------------------------------------------------------
       
  2680 
       
  2681 int DocHRef::parse()
       
  2682 {
       
  2683   int retval=RetVal_OK;
       
  2684   g_nodeStack.push(this);
       
  2685   DBG(("DocHRef::parse() start\n"));
       
  2686 
       
  2687   int tok;
       
  2688   while ((tok=doctokenizerYYlex()))
       
  2689   {
       
  2690     if (!defaultHandleToken(this,tok,m_children))
       
  2691     {
       
  2692       switch (tok)
       
  2693       {
       
  2694         case TK_COMMAND: 
       
  2695           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <a>..</a> block",
       
  2696 	       g_token->name.data());
       
  2697           break;
       
  2698         case TK_SYMBOL: 
       
  2699 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2700                g_token->name.data());
       
  2701           break;
       
  2702         case TK_HTMLTAG:
       
  2703           {
       
  2704             int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  2705             if (tagId==HTML_A && g_token->endTag) // found </a> tag
       
  2706             {
       
  2707               goto endhref;
       
  2708             }
       
  2709             else
       
  2710             {
       
  2711               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <a href=...> context",
       
  2712                   g_token->endTag?"/":"",g_token->name.data(),doctokenizerYYlineno);
       
  2713             }
       
  2714           }
       
  2715           break;
       
  2716         default:
       
  2717 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2718 		tokToString(tok),doctokenizerYYlineno);
       
  2719           break;
       
  2720       }
       
  2721     }
       
  2722   }
       
  2723   if (tok==0)
       
  2724   {
       
  2725     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside"
       
  2726            " <a href=...> tag",doctokenizerYYlineno); 
       
  2727   }
       
  2728 endhref:
       
  2729   handlePendingStyleCommands(this,m_children);
       
  2730   DBG(("DocHRef::parse() end\n"));
       
  2731   DocNode *n=g_nodeStack.pop();
       
  2732   ASSERT(n==this);
       
  2733   return retval;
       
  2734 }
       
  2735 
       
  2736 //---------------------------------------------------------------------------
       
  2737 
       
  2738 int DocInternal::parse(int level)
       
  2739 {
       
  2740   int retval=RetVal_OK;
       
  2741   g_nodeStack.push(this);
       
  2742   DBG(("DocInternal::parse() start\n"));
       
  2743 
       
  2744   // first parse any number of paragraphs
       
  2745   bool isFirst=TRUE;
       
  2746   DocPara *lastPar=0;
       
  2747   do
       
  2748   {
       
  2749     DocPara *par = new DocPara(this);
       
  2750     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  2751     retval=par->parse();
       
  2752     if (!par->isEmpty()) 
       
  2753     {
       
  2754       m_children.append(par);
       
  2755       lastPar=par;
       
  2756     }
       
  2757     else
       
  2758     {
       
  2759       delete par;
       
  2760     }
       
  2761     if (retval==TK_LISTITEM)
       
  2762     {
       
  2763       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid list item found",doctokenizerYYlineno);
       
  2764     }
       
  2765   } while (retval!=0 && 
       
  2766            retval!=RetVal_Section &&
       
  2767            retval!=RetVal_Subsection &&
       
  2768            retval!=RetVal_Subsubsection &&
       
  2769            retval!=RetVal_Paragraph
       
  2770           );
       
  2771   if (lastPar) lastPar->markLast();
       
  2772 
       
  2773   // then parse any number of level-n sections
       
  2774   while ((level==1 && retval==RetVal_Section) || 
       
  2775          (level==2 && retval==RetVal_Subsection) ||
       
  2776          (level==3 && retval==RetVal_Subsubsection) ||
       
  2777          (level==4 && retval==RetVal_Paragraph)
       
  2778         )
       
  2779   {
       
  2780     DocSection *s=new DocSection(this,
       
  2781         QMIN(level+Doxygen::subpageNestingLevel,5),g_token->sectionId);
       
  2782     m_children.append(s);
       
  2783     retval = s->parse();
       
  2784   }
       
  2785 
       
  2786   if (retval==RetVal_Internal)
       
  2787   {
       
  2788     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: \\internal command found inside internal section");
       
  2789   }
       
  2790 
       
  2791   DBG(("DocInternal::parse() end\n"));
       
  2792   DocNode *n=g_nodeStack.pop();
       
  2793   ASSERT(n==this);
       
  2794   return retval;
       
  2795 }
       
  2796 
       
  2797 //---------------------------------------------------------------------------
       
  2798 
       
  2799 int DocIndexEntry::parse()
       
  2800 {
       
  2801   int retval=RetVal_OK;
       
  2802   g_nodeStack.push(this);
       
  2803   DBG(("DocIndexEntry::parse() start\n"));
       
  2804   int tok=doctokenizerYYlex();
       
  2805   if (tok!=TK_WHITESPACE)
       
  2806   {
       
  2807     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after \\addindex command");
       
  2808     goto endindexentry;
       
  2809   }
       
  2810   doctokenizerYYsetStateTitle();
       
  2811   m_entry="";
       
  2812   while ((tok=doctokenizerYYlex()))
       
  2813   {
       
  2814     switch (tok)
       
  2815     {
       
  2816       case TK_WHITESPACE:
       
  2817         m_entry+=" ";
       
  2818         break;
       
  2819       case TK_WORD: 
       
  2820       case TK_LNKWORD: 
       
  2821         m_entry+=g_token->name;
       
  2822         break;
       
  2823       case TK_SYMBOL:
       
  2824         {
       
  2825           char letter='\0';
       
  2826           DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name,&letter);
       
  2827           switch (s)
       
  2828           {
       
  2829             case DocSymbol::BSlash:  m_entry+='\\'; break;
       
  2830             case DocSymbol::At:      m_entry+='@';  break;
       
  2831             case DocSymbol::Less:    m_entry+='<';  break;
       
  2832             case DocSymbol::Greater: m_entry+='>';  break;
       
  2833             case DocSymbol::Amp:     m_entry+='&';  break;
       
  2834             case DocSymbol::Dollar:  m_entry+='$';  break;
       
  2835             case DocSymbol::Hash:    m_entry+='#';  break;
       
  2836             case DocSymbol::Percent: m_entry+='%';  break;
       
  2837             case DocSymbol::Apos:    m_entry+='\''; break;
       
  2838             case DocSymbol::Quot:    m_entry+='"';  break;
       
  2839             case DocSymbol::Lsquo:   m_entry+='`';  break;
       
  2840             case DocSymbol::Rsquo:   m_entry+='\'';  break;
       
  2841             case DocSymbol::Ldquo:   m_entry+="``";  break;
       
  2842             case DocSymbol::Rdquo:   m_entry+="''";  break;
       
  2843             case DocSymbol::Ndash:   m_entry+="--";  break;
       
  2844             case DocSymbol::Mdash:   m_entry+="---";  break;
       
  2845             default:
       
  2846               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected symbol found as argument of \\addindex");
       
  2847               break;
       
  2848           }
       
  2849         }
       
  2850         break;
       
  2851     case TK_COMMAND: 
       
  2852       switch (Mappers::cmdMapper->map(g_token->name))
       
  2853       {
       
  2854         case CMD_BSLASH:  m_entry+='\\'; break;
       
  2855         case CMD_AT:      m_entry+='@';  break;
       
  2856         case CMD_LESS:    m_entry+='<';  break;
       
  2857         case CMD_GREATER: m_entry+='>';  break;
       
  2858         case CMD_AMP:     m_entry+='&';  break;
       
  2859         case CMD_DOLLAR:  m_entry+='$';  break;
       
  2860         case CMD_HASH:    m_entry+='#';  break;
       
  2861         case CMD_PERCENT: m_entry+='%';  break;
       
  2862         case CMD_QUOTE:   m_entry+='"';  break;
       
  2863         default:
       
  2864           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected command %s found as argument of \\addindex",
       
  2865                     g_token->name.data());
       
  2866           break;
       
  2867       }
       
  2868       break;
       
  2869       default:
       
  2870         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2871             tokToString(tok));
       
  2872         break;
       
  2873     }
       
  2874   }
       
  2875   if (tok!=0) retval=tok;
       
  2876   doctokenizerYYsetStatePara();
       
  2877   m_entry = m_entry.stripWhiteSpace();
       
  2878 endindexentry:
       
  2879   DBG(("DocIndexEntry::parse() end retval=%x\n",retval));
       
  2880   DocNode *n=g_nodeStack.pop();
       
  2881   ASSERT(n==this);
       
  2882   return retval;
       
  2883 }
       
  2884 
       
  2885 //---------------------------------------------------------------------------
       
  2886 
       
  2887 int DocHtmlCaption::parse()
       
  2888 {
       
  2889   int retval=0;
       
  2890   g_nodeStack.push(this);
       
  2891   DBG(("DocHtmlCaption::parse() start\n"));
       
  2892   int tok;
       
  2893   while ((tok=doctokenizerYYlex()))
       
  2894   {
       
  2895     if (!defaultHandleToken(this,tok,m_children))
       
  2896     {
       
  2897       switch (tok)
       
  2898       {
       
  2899         case TK_COMMAND: 
       
  2900           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <caption> tag",
       
  2901               g_token->name.data());
       
  2902           break;
       
  2903         case TK_SYMBOL: 
       
  2904           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  2905               g_token->name.data());
       
  2906           break;
       
  2907         case TK_HTMLTAG:
       
  2908           {
       
  2909             int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  2910             if (tagId==HTML_CAPTION && g_token->endTag) // found </caption> tag
       
  2911             {
       
  2912               retval = RetVal_OK;
       
  2913               goto endcaption;
       
  2914             }
       
  2915             else
       
  2916             {
       
  2917               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <caption> context",
       
  2918                   g_token->endTag?"/":"",g_token->name.data());
       
  2919             }
       
  2920           }
       
  2921           break;
       
  2922         default:
       
  2923           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  2924               tokToString(tok));
       
  2925           break;
       
  2926       }
       
  2927     }
       
  2928   }
       
  2929   if (tok==0)
       
  2930   {
       
  2931     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside"
       
  2932            " <caption> tag",doctokenizerYYlineno); 
       
  2933   }
       
  2934 endcaption:
       
  2935   handlePendingStyleCommands(this,m_children);
       
  2936   DBG(("DocHtmlCaption::parse() end\n"));
       
  2937   DocNode *n=g_nodeStack.pop();
       
  2938   ASSERT(n==this);
       
  2939   return retval;
       
  2940 }
       
  2941 
       
  2942 //---------------------------------------------------------------------------
       
  2943 
       
  2944 int DocHtmlCell::parse()
       
  2945 {
       
  2946   int retval=RetVal_OK;
       
  2947   g_nodeStack.push(this);
       
  2948   DBG(("DocHtmlCell::parse() start\n"));
       
  2949 
       
  2950   // parse one or more paragraphs
       
  2951   bool isFirst=TRUE;
       
  2952   DocPara *par=0;
       
  2953   do
       
  2954   {
       
  2955     par = new DocPara(this);
       
  2956     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  2957     m_children.append(par);
       
  2958     retval=par->parse();
       
  2959     if (retval==TK_HTMLTAG)
       
  2960     {
       
  2961       int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  2962       if (tagId==HTML_TD && g_token->endTag) // found </dt> tag
       
  2963       {
       
  2964         retval=TK_NEWPARA; // ignore the tag
       
  2965       }
       
  2966       else if (tagId==HTML_TH && g_token->endTag) // found </th> tag
       
  2967       {
       
  2968         retval=TK_NEWPARA; // ignore the tag
       
  2969       }
       
  2970     }
       
  2971   }
       
  2972   while (retval==TK_NEWPARA);
       
  2973   if (par) par->markLast();
       
  2974 
       
  2975   DBG(("DocHtmlCell::parse() end\n"));
       
  2976   DocNode *n=g_nodeStack.pop();
       
  2977   ASSERT(n==this);
       
  2978   return retval;
       
  2979 }
       
  2980 
       
  2981 int DocHtmlCell::parseXml()
       
  2982 {
       
  2983   int retval=RetVal_OK;
       
  2984   g_nodeStack.push(this);
       
  2985   DBG(("DocHtmlCell::parseXml() start\n"));
       
  2986 
       
  2987   // parse one or more paragraphs
       
  2988   bool isFirst=TRUE;
       
  2989   DocPara *par=0;
       
  2990   do
       
  2991   {
       
  2992     par = new DocPara(this);
       
  2993     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  2994     m_children.append(par);
       
  2995     retval=par->parse();
       
  2996     if (retval==TK_HTMLTAG)
       
  2997     {
       
  2998       int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  2999       if (tagId==XML_ITEM && g_token->endTag) // found </item> tag
       
  3000       {
       
  3001         retval=TK_NEWPARA; // ignore the tag
       
  3002       }
       
  3003       else if (tagId==XML_DESCRIPTION && g_token->endTag) // found </description> tag
       
  3004       {
       
  3005         retval=TK_NEWPARA; // ignore the tag
       
  3006       }
       
  3007     }
       
  3008   }
       
  3009   while (retval==TK_NEWPARA);
       
  3010   if (par) par->markLast();
       
  3011 
       
  3012   DBG(("DocHtmlCell::parseXml() end\n"));
       
  3013   DocNode *n=g_nodeStack.pop();
       
  3014   ASSERT(n==this);
       
  3015   return retval;
       
  3016 }
       
  3017 
       
  3018 //---------------------------------------------------------------------------
       
  3019 
       
  3020 int DocHtmlRow::parse()
       
  3021 {
       
  3022   int retval=RetVal_OK;
       
  3023   g_nodeStack.push(this);
       
  3024   DBG(("DocHtmlRow::parse() start\n"));
       
  3025 
       
  3026   bool isHeading=FALSE;
       
  3027   bool isFirst=TRUE;
       
  3028   DocHtmlCell *cell=0;
       
  3029 
       
  3030   // get next token
       
  3031   int tok=doctokenizerYYlex();
       
  3032   // skip whitespace
       
  3033   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  3034   // should find a html tag now
       
  3035   if (tok==TK_HTMLTAG)
       
  3036   {
       
  3037     int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3038     if (tagId==HTML_TD && !g_token->endTag) // found <td> tag
       
  3039     {
       
  3040     }
       
  3041     else if (tagId==HTML_TH && !g_token->endTag) // found <th> tag
       
  3042     {
       
  3043       isHeading=TRUE;
       
  3044     }
       
  3045     else // found some other tag
       
  3046     {
       
  3047       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but "
       
  3048           "found <%s> instead!",g_token->name.data());
       
  3049       doctokenizerYYpushBackHtmlTag(g_token->name);
       
  3050       goto endrow;
       
  3051     }
       
  3052   }
       
  3053   else if (tok==0) // premature end of comment
       
  3054   {
       
  3055     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking"
       
  3056         " for a html description title");
       
  3057     goto endrow;
       
  3058   }
       
  3059   else // token other than html token
       
  3060   {
       
  3061     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but found %s token instead!",
       
  3062         tokToString(tok));
       
  3063     goto endrow;
       
  3064   }
       
  3065 
       
  3066   // parse one or more cells
       
  3067   do
       
  3068   {
       
  3069     cell=new DocHtmlCell(this,g_token->attribs,isHeading);
       
  3070     cell->markFirst(isFirst);
       
  3071     isFirst=FALSE;
       
  3072     m_children.append(cell);
       
  3073     retval=cell->parse();
       
  3074     isHeading = retval==RetVal_TableHCell;
       
  3075   }
       
  3076   while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
       
  3077   if (cell) cell->markLast(TRUE);
       
  3078 
       
  3079 endrow:
       
  3080   DBG(("DocHtmlRow::parse() end\n"));
       
  3081   DocNode *n=g_nodeStack.pop();
       
  3082   ASSERT(n==this);
       
  3083   return retval;
       
  3084 }
       
  3085 
       
  3086 int DocHtmlRow::parseXml(bool isHeading)
       
  3087 {
       
  3088   int retval=RetVal_OK;
       
  3089   g_nodeStack.push(this);
       
  3090   DBG(("DocHtmlRow::parseXml() start\n"));
       
  3091 
       
  3092   bool isFirst=TRUE;
       
  3093   DocHtmlCell *cell=0;
       
  3094 
       
  3095   // get next token
       
  3096   int tok=doctokenizerYYlex();
       
  3097   // skip whitespace
       
  3098   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  3099   // should find a html tag now
       
  3100   if (tok==TK_HTMLTAG)
       
  3101   {
       
  3102     int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3103     if (tagId==XML_TERM && !g_token->endTag) // found <term> tag
       
  3104     {
       
  3105     }
       
  3106     else if (tagId==XML_DESCRIPTION && !g_token->endTag) // found <description> tag
       
  3107     {
       
  3108     }
       
  3109     else // found some other tag
       
  3110     {
       
  3111       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <term> or <description> tag but "
       
  3112           "found <%s> instead!",g_token->name.data());
       
  3113       doctokenizerYYpushBackHtmlTag(g_token->name);
       
  3114       goto endrow;
       
  3115     }
       
  3116   }
       
  3117   else if (tok==0) // premature end of comment
       
  3118   {
       
  3119     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking"
       
  3120         " for a html description title");
       
  3121     goto endrow;
       
  3122   }
       
  3123   else // token other than html token
       
  3124   {
       
  3125     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but found %s token instead!",
       
  3126         tokToString(tok));
       
  3127     goto endrow;
       
  3128   }
       
  3129 
       
  3130   do
       
  3131   {
       
  3132     cell=new DocHtmlCell(this,g_token->attribs,isHeading);
       
  3133     cell->markFirst(isFirst);
       
  3134     isFirst=FALSE;
       
  3135     m_children.append(cell);
       
  3136     retval=cell->parseXml();
       
  3137   }
       
  3138   while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
       
  3139   if (cell) cell->markLast(TRUE);
       
  3140 
       
  3141 endrow:
       
  3142   DBG(("DocHtmlRow::parseXml() end\n"));
       
  3143   DocNode *n=g_nodeStack.pop();
       
  3144   ASSERT(n==this);
       
  3145   return retval;
       
  3146 }
       
  3147 
       
  3148 //---------------------------------------------------------------------------
       
  3149 
       
  3150 int DocHtmlTable::parse()
       
  3151 {
       
  3152   int retval=RetVal_OK;
       
  3153   g_nodeStack.push(this);
       
  3154   DBG(("DocHtmlTable::parse() start\n"));
       
  3155   
       
  3156 getrow:
       
  3157   // get next token
       
  3158   int tok=doctokenizerYYlex();
       
  3159   // skip whitespace
       
  3160   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  3161   // should find a html tag now
       
  3162   if (tok==TK_HTMLTAG)
       
  3163   {
       
  3164     int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3165     if (tagId==HTML_TR && !g_token->endTag) // found <tr> tag
       
  3166     {
       
  3167       // no caption, just rows
       
  3168       retval=RetVal_TableRow;
       
  3169     }
       
  3170     else if (tagId==HTML_CAPTION && !g_token->endTag) // found <caption> tag
       
  3171     {
       
  3172       if (m_caption)
       
  3173       {
       
  3174         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: table already has a caption, found another one");
       
  3175       }
       
  3176       else
       
  3177       {
       
  3178         m_caption = new DocHtmlCaption(this,g_token->attribs);
       
  3179         retval=m_caption->parse();
       
  3180 
       
  3181         if (retval==RetVal_OK) // caption was parsed ok
       
  3182         {
       
  3183           goto getrow;
       
  3184         }
       
  3185       }
       
  3186     }
       
  3187     else // found wrong token
       
  3188     {
       
  3189       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <tr> or <caption> tag but "
       
  3190           "found <%s%s> instead!", g_token->endTag ? "/" : "", g_token->name.data());
       
  3191     }
       
  3192   }
       
  3193   else if (tok==0) // premature end of comment
       
  3194   {
       
  3195       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking"
       
  3196           " for a <tr> or <caption> tag");
       
  3197   }
       
  3198   else // token other than html token
       
  3199   {
       
  3200     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <tr> tag but found %s token instead!",
       
  3201         tokToString(tok));
       
  3202   }
       
  3203        
       
  3204   // parse one or more rows
       
  3205   while (retval==RetVal_TableRow)
       
  3206   {
       
  3207     DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs);
       
  3208     m_children.append(tr);
       
  3209     retval=tr->parse();
       
  3210   } 
       
  3211 
       
  3212   DBG(("DocHtmlTable::parse() end\n"));
       
  3213   DocNode *n=g_nodeStack.pop();
       
  3214   ASSERT(n==this);
       
  3215   return retval==RetVal_EndTable ? RetVal_OK : retval;
       
  3216 }
       
  3217 
       
  3218 int DocHtmlTable::parseXml()
       
  3219 {
       
  3220   int retval=RetVal_OK;
       
  3221   g_nodeStack.push(this);
       
  3222   DBG(("DocHtmlTable::parseXml() start\n"));
       
  3223   
       
  3224   // get next token
       
  3225   int tok=doctokenizerYYlex();
       
  3226   // skip whitespace
       
  3227   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  3228   // should find a html tag now
       
  3229   int tagId=0;
       
  3230   bool isHeader=FALSE;
       
  3231   if (tok==TK_HTMLTAG)
       
  3232   {
       
  3233     tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3234     if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag
       
  3235     {
       
  3236       retval=RetVal_TableRow;
       
  3237     }
       
  3238     if (tagId==XML_LISTHEADER && !g_token->endTag) // found <listheader> tag
       
  3239     {
       
  3240       retval=RetVal_TableRow;
       
  3241       isHeader=TRUE;
       
  3242     }
       
  3243   }
       
  3244 
       
  3245   // parse one or more rows
       
  3246   while (retval==RetVal_TableRow)
       
  3247   {
       
  3248     DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs);
       
  3249     m_children.append(tr);
       
  3250     retval=tr->parseXml(isHeader);
       
  3251     isHeader=FALSE;
       
  3252   } 
       
  3253 
       
  3254   DBG(("DocHtmlTable::parseXml() end\n"));
       
  3255   DocNode *n=g_nodeStack.pop();
       
  3256   ASSERT(n==this);
       
  3257   return retval==RetVal_EndTable ? RetVal_OK : retval;
       
  3258 }
       
  3259 
       
  3260 uint DocHtmlTable::numCols() const
       
  3261 {
       
  3262   uint cols=0;
       
  3263   QListIterator<DocNode> cli(m_children);
       
  3264   DocNode *n;
       
  3265   for (cli.toFirst();(n=cli.current());++cli)
       
  3266   {
       
  3267     ASSERT(n->kind()==DocNode::Kind_HtmlRow);
       
  3268     cols=QMAX(cols,((DocHtmlRow *)n)->numCells());
       
  3269   }
       
  3270   return cols;
       
  3271 }
       
  3272 
       
  3273 void DocHtmlTable::accept(DocVisitor *v) 
       
  3274 { 
       
  3275   v->visitPre(this); 
       
  3276   // for HTML output we put the caption first
       
  3277   if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v);
       
  3278   QListIterator<DocNode> cli(m_children);
       
  3279   DocNode *n;
       
  3280   for (cli.toFirst();(n=cli.current());++cli) n->accept(v);
       
  3281   // for other output formats we put the caption last
       
  3282   if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v);
       
  3283   v->visitPost(this); 
       
  3284 }
       
  3285 
       
  3286 //---------------------------------------------------------------------------
       
  3287 
       
  3288 int DocHtmlDescTitle::parse()
       
  3289 {
       
  3290   int retval=0;
       
  3291   g_nodeStack.push(this);
       
  3292   DBG(("DocHtmlDescTitle::parse() start\n"));
       
  3293 
       
  3294   int tok;
       
  3295   while ((tok=doctokenizerYYlex()))
       
  3296   {
       
  3297     if (!defaultHandleToken(this,tok,m_children))
       
  3298     {
       
  3299       switch (tok)
       
  3300       {
       
  3301         case TK_COMMAND: 
       
  3302           {
       
  3303             QString cmdName=g_token->name;
       
  3304             bool isJavaLink=FALSE;
       
  3305             switch (Mappers::cmdMapper->map(cmdName))
       
  3306             {
       
  3307               case CMD_REF:
       
  3308                 {
       
  3309                   int tok=doctokenizerYYlex();
       
  3310                   if (tok!=TK_WHITESPACE)
       
  3311                   {
       
  3312                     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  3313                         g_token->name.data());
       
  3314                   }
       
  3315                   else
       
  3316                   {
       
  3317                     doctokenizerYYsetStateRef();
       
  3318                     tok=doctokenizerYYlex(); // get the reference id
       
  3319                     if (tok!=TK_WORD)
       
  3320                     {
       
  3321                       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  3322                           tokToString(tok),cmdName.data());
       
  3323                     }
       
  3324                     else
       
  3325                     {
       
  3326                       DocRef *ref = new DocRef(this,g_token->name,g_context);
       
  3327                       m_children.append(ref);
       
  3328                       ref->parse();
       
  3329                     }
       
  3330                     doctokenizerYYsetStatePara();
       
  3331                   }
       
  3332                 }
       
  3333                 break;
       
  3334               case CMD_JAVALINK:
       
  3335                 isJavaLink=TRUE;
       
  3336                 // fall through
       
  3337               case CMD_LINK:
       
  3338                 {
       
  3339                   int tok=doctokenizerYYlex();
       
  3340                   if (tok!=TK_WHITESPACE)
       
  3341                   {
       
  3342                     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  3343                         cmdName.data());
       
  3344                   }
       
  3345                   else
       
  3346                   {
       
  3347                     doctokenizerYYsetStateLink();
       
  3348                     tok=doctokenizerYYlex();
       
  3349                     if (tok!=TK_WORD)
       
  3350                     {
       
  3351                       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  3352                           tokToString(tok),cmdName.data());
       
  3353                     }
       
  3354                     else
       
  3355                     {
       
  3356                       doctokenizerYYsetStatePara();
       
  3357                       DocLink *lnk = new DocLink(this,g_token->name);
       
  3358                       m_children.append(lnk);
       
  3359                       QString leftOver = lnk->parse(isJavaLink);
       
  3360                       if (!leftOver.isEmpty())
       
  3361                       {
       
  3362                         m_children.append(new DocWord(this,leftOver));
       
  3363                       }
       
  3364                     }
       
  3365                   }
       
  3366                 }
       
  3367 
       
  3368                 break;
       
  3369               default:
       
  3370                 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <dt> tag",
       
  3371                                g_token->name.data());
       
  3372             }
       
  3373           }
       
  3374           break;
       
  3375         case TK_SYMBOL: 
       
  3376           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  3377               g_token->name.data());
       
  3378           break;
       
  3379         case TK_HTMLTAG:
       
  3380           {
       
  3381             int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3382             if (tagId==HTML_DD && !g_token->endTag) // found <dd> tag
       
  3383             {
       
  3384               retval = RetVal_DescData;
       
  3385               goto endtitle;
       
  3386             }
       
  3387             else if (tagId==HTML_DT && g_token->endTag)
       
  3388             {
       
  3389               // ignore </dt> tag.
       
  3390             }
       
  3391             else if (tagId==HTML_DT)
       
  3392             {
       
  3393               // missing <dt> tag.
       
  3394               retval = RetVal_DescTitle;
       
  3395               goto endtitle;
       
  3396             }
       
  3397             else if (tagId==HTML_DL && g_token->endTag)
       
  3398             {
       
  3399               retval=RetVal_EndDesc;
       
  3400               goto endtitle;
       
  3401             }
       
  3402             else
       
  3403             {
       
  3404               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <dt> context",
       
  3405                   g_token->endTag?"/":"",g_token->name.data());
       
  3406             }
       
  3407           }
       
  3408           break;
       
  3409         default:
       
  3410           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  3411               tokToString(tok));
       
  3412           break;
       
  3413       }
       
  3414     }
       
  3415   }
       
  3416   if (tok==0)
       
  3417   {
       
  3418     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside"
       
  3419         " <dt> tag"); 
       
  3420   }
       
  3421 endtitle:
       
  3422   handlePendingStyleCommands(this,m_children);
       
  3423   DBG(("DocHtmlDescTitle::parse() end\n"));
       
  3424   DocNode *n=g_nodeStack.pop();
       
  3425   ASSERT(n==this);
       
  3426   return retval;
       
  3427 }
       
  3428 
       
  3429 //---------------------------------------------------------------------------
       
  3430 
       
  3431 int DocHtmlDescData::parse()
       
  3432 {
       
  3433   m_attribs = g_token->attribs;
       
  3434   int retval=0;
       
  3435   g_nodeStack.push(this);
       
  3436   DBG(("DocHtmlDescData::parse() start\n"));
       
  3437 
       
  3438   bool isFirst=TRUE;
       
  3439   DocPara *par=0;
       
  3440   do
       
  3441   {
       
  3442     par = new DocPara(this);
       
  3443     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  3444     m_children.append(par);
       
  3445     retval=par->parse();
       
  3446   }
       
  3447   while (retval==TK_NEWPARA);
       
  3448   if (par) par->markLast();
       
  3449   
       
  3450   DBG(("DocHtmlDescData::parse() end\n"));
       
  3451   DocNode *n=g_nodeStack.pop();
       
  3452   ASSERT(n==this);
       
  3453   return retval;
       
  3454 }
       
  3455 
       
  3456 //---------------------------------------------------------------------------
       
  3457 
       
  3458 int DocHtmlDescList::parse()
       
  3459 {
       
  3460   int retval=RetVal_OK;
       
  3461   g_nodeStack.push(this);
       
  3462   DBG(("DocHtmlDescList::parse() start\n"));
       
  3463 
       
  3464   // get next token
       
  3465   int tok=doctokenizerYYlex();
       
  3466   // skip whitespace
       
  3467   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  3468   // should find a html tag now
       
  3469   if (tok==TK_HTMLTAG)
       
  3470   {
       
  3471     int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3472     if (tagId==HTML_DT && !g_token->endTag) // found <dt> tag
       
  3473     {
       
  3474       // continue
       
  3475     }
       
  3476     else // found some other tag
       
  3477     {
       
  3478       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <dt> tag but "
       
  3479           "found <%s> instead!",g_token->name.data());
       
  3480       doctokenizerYYpushBackHtmlTag(g_token->name);
       
  3481       goto enddesclist;
       
  3482     }
       
  3483   }
       
  3484   else if (tok==0) // premature end of comment
       
  3485   {
       
  3486     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking"
       
  3487         " for a html description title");
       
  3488     goto enddesclist;
       
  3489   }
       
  3490   else // token other than html token
       
  3491   {
       
  3492     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <dt> tag but found %s token instead!",
       
  3493         tokToString(tok));
       
  3494     goto enddesclist;
       
  3495   }
       
  3496 
       
  3497   do
       
  3498   {
       
  3499     DocHtmlDescTitle *dt=new DocHtmlDescTitle(this,g_token->attribs);
       
  3500     m_children.append(dt);
       
  3501     DocHtmlDescData *dd=new DocHtmlDescData(this);
       
  3502     m_children.append(dd);
       
  3503     retval=dt->parse();
       
  3504     if (retval==RetVal_DescData)
       
  3505     {
       
  3506       retval=dd->parse();
       
  3507     }
       
  3508     else if (retval!=RetVal_DescTitle)
       
  3509     {
       
  3510       // error
       
  3511       break;
       
  3512     }
       
  3513   } while (retval==RetVal_DescTitle);
       
  3514 
       
  3515   if (retval==0)
       
  3516   {
       
  3517     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while inside <dl> block");
       
  3518   }
       
  3519 
       
  3520 enddesclist:
       
  3521 
       
  3522   DocNode *n=g_nodeStack.pop();
       
  3523   ASSERT(n==this);
       
  3524   DBG(("DocHtmlDescList::parse() end\n"));
       
  3525   return retval==RetVal_EndDesc ? RetVal_OK : retval;
       
  3526 }
       
  3527 
       
  3528 //---------------------------------------------------------------------------
       
  3529 
       
  3530 int DocHtmlListItem::parse()
       
  3531 {
       
  3532   DBG(("DocHtmlListItem::parse() start\n"));
       
  3533   int retval=0;
       
  3534   g_nodeStack.push(this);
       
  3535 
       
  3536   // parse one or more paragraphs
       
  3537   bool isFirst=TRUE;
       
  3538   DocPara *par=0;
       
  3539   do
       
  3540   {
       
  3541     par = new DocPara(this);
       
  3542     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  3543     m_children.append(par);
       
  3544     retval=par->parse();
       
  3545   }
       
  3546   while (retval==TK_NEWPARA);
       
  3547   if (par) par->markLast();
       
  3548 
       
  3549   DocNode *n=g_nodeStack.pop();
       
  3550   ASSERT(n==this);
       
  3551   DBG(("DocHtmlListItem::parse() end retval=%x\n",retval));
       
  3552   return retval;
       
  3553 }
       
  3554 
       
  3555 int DocHtmlListItem::parseXml()
       
  3556 {
       
  3557   DBG(("DocHtmlListItem::parseXml() start\n"));
       
  3558   int retval=0;
       
  3559   g_nodeStack.push(this);
       
  3560 
       
  3561   // parse one or more paragraphs
       
  3562   bool isFirst=TRUE;
       
  3563   DocPara *par=0;
       
  3564   do
       
  3565   {
       
  3566     par = new DocPara(this);
       
  3567     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  3568     m_children.append(par);
       
  3569     retval=par->parse();
       
  3570     if (retval==0) break;
       
  3571 
       
  3572     //printf("new item: retval=%x g_token->name=%s g_token->endTag=%d\n",
       
  3573     //    retval,g_token->name.data(),g_token->endTag);
       
  3574     if (retval==RetVal_ListItem)
       
  3575     {
       
  3576       break;
       
  3577     }
       
  3578   }
       
  3579   while (retval!=RetVal_CloseXml);
       
  3580 
       
  3581   if (par) par->markLast();
       
  3582 
       
  3583   DocNode *n=g_nodeStack.pop();
       
  3584   ASSERT(n==this);
       
  3585   DBG(("DocHtmlListItem::parseXml() end retval=%x\n",retval));
       
  3586   return retval;
       
  3587 }
       
  3588 
       
  3589 //---------------------------------------------------------------------------
       
  3590 
       
  3591 int DocHtmlList::parse()
       
  3592 {
       
  3593   DBG(("DocHtmlList::parse() start\n"));
       
  3594   int retval=RetVal_OK;
       
  3595   int num=1;
       
  3596   g_nodeStack.push(this);
       
  3597 
       
  3598   // get next token
       
  3599   int tok=doctokenizerYYlex();
       
  3600   // skip whitespace and paragraph breaks
       
  3601   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  3602   // should find a html tag now
       
  3603   if (tok==TK_HTMLTAG)
       
  3604   {
       
  3605     int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3606     if (tagId==HTML_LI && !g_token->endTag) // found <li> tag
       
  3607     {
       
  3608       // ok, we can go on.
       
  3609     }
       
  3610     else // found some other tag
       
  3611     {
       
  3612       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <li> tag but "
       
  3613           "found <%s> instead!",g_token->name.data());
       
  3614       doctokenizerYYpushBackHtmlTag(g_token->name);
       
  3615       goto endlist;
       
  3616     }
       
  3617   }
       
  3618   else if (tok==0) // premature end of comment
       
  3619   {
       
  3620     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking"
       
  3621         " for a html list item");
       
  3622     goto endlist;
       
  3623   }
       
  3624   else // token other than html token
       
  3625   {
       
  3626     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <li> tag but found %s token instead!",
       
  3627         tokToString(tok));
       
  3628     goto endlist;
       
  3629   }
       
  3630 
       
  3631   do
       
  3632   {
       
  3633     DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++);
       
  3634     m_children.append(li);
       
  3635     retval=li->parse();
       
  3636   } while (retval==RetVal_ListItem);
       
  3637   
       
  3638   if (retval==0)
       
  3639   {
       
  3640     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while inside <%cl> block",
       
  3641         m_type==Unordered ? 'u' : 'o');
       
  3642   }
       
  3643 
       
  3644 endlist:
       
  3645   DBG(("DocHtmlList::parse() end retval=%x\n",retval));
       
  3646   DocNode *n=g_nodeStack.pop();
       
  3647   ASSERT(n==this);
       
  3648   return retval==RetVal_EndList ? RetVal_OK : retval;
       
  3649 }
       
  3650 
       
  3651 int DocHtmlList::parseXml()
       
  3652 {
       
  3653   DBG(("DocHtmlList::parseXml() start\n"));
       
  3654   int retval=RetVal_OK;
       
  3655   int num=1;
       
  3656   g_nodeStack.push(this);
       
  3657 
       
  3658   // get next token
       
  3659   int tok=doctokenizerYYlex();
       
  3660   // skip whitespace and paragraph breaks
       
  3661   while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
       
  3662   // should find a html tag now
       
  3663   if (tok==TK_HTMLTAG)
       
  3664   {
       
  3665     int tagId=Mappers::htmlTagMapper->map(g_token->name);
       
  3666     //printf("g_token->name=%s g_token->endTag=%d\n",g_token->name.data(),g_token->endTag);
       
  3667     if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag
       
  3668     {
       
  3669       // ok, we can go on.
       
  3670     }
       
  3671     else // found some other tag
       
  3672     {
       
  3673       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <item> tag but "
       
  3674           "found <%s> instead!",g_token->name.data());
       
  3675       doctokenizerYYpushBackHtmlTag(g_token->name);
       
  3676       goto endlist;
       
  3677     }
       
  3678   }
       
  3679   else if (tok==0) // premature end of comment
       
  3680   {
       
  3681     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking"
       
  3682         " for a html list item");
       
  3683     goto endlist;
       
  3684   }
       
  3685   else // token other than html token
       
  3686   {
       
  3687     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <item> tag but found %s token instead!",
       
  3688         tokToString(tok));
       
  3689     goto endlist;
       
  3690   }
       
  3691 
       
  3692   do
       
  3693   {
       
  3694     DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++);
       
  3695     m_children.append(li);
       
  3696     retval=li->parseXml();
       
  3697     if (retval==0) break;
       
  3698     //printf("retval=%x g_token->name=%s\n",retval,g_token->name.data());
       
  3699   } while (retval==RetVal_ListItem);
       
  3700   
       
  3701   if (retval==0)
       
  3702   {
       
  3703     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while inside <list type=\"%s\"> block",
       
  3704         m_type==Unordered ? "bullet" : "number");
       
  3705   }
       
  3706 
       
  3707 endlist:
       
  3708   DBG(("DocHtmlList::parseXml() end retval=%x\n",retval));
       
  3709   DocNode *n=g_nodeStack.pop();
       
  3710   ASSERT(n==this);
       
  3711   return retval==RetVal_EndList || 
       
  3712          (retval==RetVal_CloseXml || g_token->name=="list") ? 
       
  3713          RetVal_OK : retval;
       
  3714 }
       
  3715 
       
  3716 //---------------------------------------------------------------------------
       
  3717 
       
  3718 int DocSimpleListItem::parse()
       
  3719 {
       
  3720   g_nodeStack.push(this);
       
  3721   int rv=m_paragraph->parse();
       
  3722   m_paragraph->markFirst();
       
  3723   m_paragraph->markLast();
       
  3724   DocNode *n=g_nodeStack.pop();
       
  3725   ASSERT(n==this);
       
  3726   return rv;
       
  3727 }
       
  3728 
       
  3729 //--------------------------------------------------------------------------
       
  3730 
       
  3731 int DocSimpleList::parse()
       
  3732 {
       
  3733   g_nodeStack.push(this);
       
  3734   int rv;
       
  3735   do
       
  3736   {
       
  3737     DocSimpleListItem *li=new DocSimpleListItem(this);
       
  3738     m_children.append(li);
       
  3739     rv=li->parse();
       
  3740   } while (rv==RetVal_ListItem);
       
  3741   DocNode *n=g_nodeStack.pop();
       
  3742   ASSERT(n==this);
       
  3743   return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
       
  3744 }
       
  3745 
       
  3746 //--------------------------------------------------------------------------
       
  3747 
       
  3748 int DocAutoListItem::parse()
       
  3749 {
       
  3750   int retval = RetVal_OK;
       
  3751   g_nodeStack.push(this);
       
  3752   retval=m_paragraph->parse();
       
  3753   m_paragraph->markFirst();
       
  3754   m_paragraph->markLast();
       
  3755   DocNode *n=g_nodeStack.pop();
       
  3756   ASSERT(n==this);
       
  3757   return retval;
       
  3758 }
       
  3759 
       
  3760 //--------------------------------------------------------------------------
       
  3761 
       
  3762 int DocAutoList::parse()
       
  3763 {
       
  3764   int retval = RetVal_OK;
       
  3765   int num=1;
       
  3766   g_nodeStack.push(this);
       
  3767 	  // first item or sub list => create new list
       
  3768   do
       
  3769   {
       
  3770     DocAutoListItem *li = new DocAutoListItem(this,num++);
       
  3771     m_children.append(li);
       
  3772     retval=li->parse();
       
  3773   } 
       
  3774   while (retval==TK_LISTITEM &&              // new list item
       
  3775          m_indent==g_token->indent &&        // at same indent level
       
  3776 	 m_isEnumList==g_token->isEnumList   // of the same kind
       
  3777         );
       
  3778 
       
  3779   DocNode *n=g_nodeStack.pop();
       
  3780   ASSERT(n==this);
       
  3781   return retval;
       
  3782 }
       
  3783 
       
  3784 //--------------------------------------------------------------------------
       
  3785 
       
  3786 void DocTitle::parse()
       
  3787 {
       
  3788   DBG(("DocTitle::parse() start\n"));
       
  3789   g_nodeStack.push(this);
       
  3790   doctokenizerYYsetStateTitle();
       
  3791   int tok;
       
  3792   while ((tok=doctokenizerYYlex()))
       
  3793   {
       
  3794     if (!defaultHandleToken(this,tok,m_children))
       
  3795     {
       
  3796       switch (tok)
       
  3797       {
       
  3798         case TK_COMMAND: 
       
  3799           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a title section",
       
  3800 	       g_token->name.data());
       
  3801           break;
       
  3802         case TK_SYMBOL: 
       
  3803 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  3804                g_token->name.data());
       
  3805           break;
       
  3806         default:
       
  3807 	  warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  3808 		tokToString(tok));
       
  3809           break;
       
  3810       }
       
  3811     }
       
  3812   }
       
  3813   doctokenizerYYsetStatePara();
       
  3814   handlePendingStyleCommands(this,m_children);
       
  3815   DBG(("DocTitle::parse() end\n"));
       
  3816   DocNode *n = g_nodeStack.pop();
       
  3817   ASSERT(n==this);
       
  3818 }
       
  3819 
       
  3820 void DocTitle::parseFromString(const QString &text)
       
  3821 {
       
  3822   m_children.append(new DocWord(this,text));
       
  3823 }
       
  3824 
       
  3825 //--------------------------------------------------------------------------
       
  3826 
       
  3827 DocSimpleSect::DocSimpleSect(DocNode *parent,Type t) : 
       
  3828      m_parent(parent), m_type(t)
       
  3829 { 
       
  3830   m_title=0; 
       
  3831 }
       
  3832 
       
  3833 DocSimpleSect::~DocSimpleSect()
       
  3834 { 
       
  3835   delete m_title; 
       
  3836 }
       
  3837 
       
  3838 void DocSimpleSect::accept(DocVisitor *v)
       
  3839 {
       
  3840   v->visitPre(this);
       
  3841   if (m_title) m_title->accept(v);
       
  3842   QListIterator<DocNode> cli(m_children);
       
  3843   DocNode *n;
       
  3844   for (cli.toFirst();(n=cli.current());++cli) n->accept(v);
       
  3845   v->visitPost(this);
       
  3846 }
       
  3847 
       
  3848 int DocSimpleSect::parse(bool userTitle,bool needsSeparator)
       
  3849 {
       
  3850   DBG(("DocSimpleSect::parse() start\n"));
       
  3851   g_nodeStack.push(this);
       
  3852 
       
  3853   // handle case for user defined title
       
  3854   if (userTitle)
       
  3855   {
       
  3856     m_title = new DocTitle(this);
       
  3857     m_title->parse();
       
  3858   }
       
  3859   
       
  3860   // add new paragraph as child
       
  3861   DocPara *par = new DocPara(this);
       
  3862   if (m_children.isEmpty()) 
       
  3863   {
       
  3864     par->markFirst();
       
  3865   }
       
  3866   else
       
  3867   {
       
  3868     ASSERT(m_children.last()->kind()==DocNode::Kind_Para);
       
  3869     ((DocPara *)m_children.last())->markLast(FALSE);
       
  3870   }
       
  3871   par->markLast();
       
  3872   if (needsSeparator) m_children.append(new DocSimpleSectSep(this));
       
  3873   m_children.append(par);
       
  3874   
       
  3875   // parse the contents of the paragraph
       
  3876   int retval = par->parse();
       
  3877 
       
  3878   DBG(("DocSimpleSect::parse() end retval=%d\n",retval));
       
  3879   DocNode *n=g_nodeStack.pop();
       
  3880   ASSERT(n==this);
       
  3881   return retval; // 0==EOF, TK_NEWPARA, TK_LISTITEM, TK_ENDLIST, RetVal_SimpleSec
       
  3882 }
       
  3883 
       
  3884 int DocSimpleSect::parseRcs()
       
  3885 {
       
  3886   DBG(("DocSimpleSect::parseRcs() start\n"));
       
  3887   g_nodeStack.push(this);
       
  3888 
       
  3889   m_title = new DocTitle(this);
       
  3890   m_title->parseFromString(g_token->name);
       
  3891 
       
  3892   QString text = g_token->text;
       
  3893   docParserPushContext(); // this will create a new g_token
       
  3894   internalValidatingParseDoc(this,m_children,text);
       
  3895   docParserPopContext(); // this will restore the old g_token
       
  3896 
       
  3897   DBG(("DocSimpleSect::parseRcs()\n"));
       
  3898   DocNode *n=g_nodeStack.pop();
       
  3899   ASSERT(n==this);
       
  3900   return RetVal_OK; 
       
  3901 }
       
  3902 
       
  3903 int DocSimpleSect::parseXml()
       
  3904 {
       
  3905   DBG(("DocSimpleSect::parse() start\n"));
       
  3906   g_nodeStack.push(this);
       
  3907 
       
  3908   int retval = RetVal_OK;
       
  3909   for (;;) 
       
  3910   {
       
  3911     // add new paragraph as child
       
  3912     DocPara *par = new DocPara(this);
       
  3913     if (m_children.isEmpty()) 
       
  3914     {
       
  3915       par->markFirst();
       
  3916     }
       
  3917     else
       
  3918     {
       
  3919       ASSERT(m_children.last()->kind()==DocNode::Kind_Para);
       
  3920       ((DocPara *)m_children.last())->markLast(FALSE);
       
  3921     }
       
  3922     par->markLast();
       
  3923     m_children.append(par);
       
  3924 
       
  3925     // parse the contents of the paragraph
       
  3926     retval = par->parse();
       
  3927     if (retval == 0) break;
       
  3928     if (retval == RetVal_CloseXml) 
       
  3929     {
       
  3930       retval = RetVal_OK;
       
  3931       break;
       
  3932     }
       
  3933   }
       
  3934   
       
  3935   DBG(("DocSimpleSect::parseXml() end retval=%d\n",retval));
       
  3936   DocNode *n=g_nodeStack.pop();
       
  3937   ASSERT(n==this);
       
  3938   return retval; 
       
  3939 }
       
  3940 
       
  3941 void DocSimpleSect::appendLinkWord(const QString &word)
       
  3942 {
       
  3943   DocPara *p;
       
  3944   if (m_children.isEmpty() || m_children.last()->kind()!=DocNode::Kind_Para)
       
  3945   {
       
  3946     p = new DocPara(this);
       
  3947     m_children.append(p);
       
  3948   }
       
  3949   else
       
  3950   {
       
  3951     p = (DocPara *)m_children.last();
       
  3952     
       
  3953     // Comma-seperate <seealso> links.
       
  3954     p->injectToken(TK_WORD,",");
       
  3955     p->injectToken(TK_WHITESPACE," ");
       
  3956   }
       
  3957   
       
  3958   g_inSeeBlock=TRUE;
       
  3959   p->injectToken(TK_LNKWORD,word);
       
  3960   g_inSeeBlock=FALSE;
       
  3961 }
       
  3962 
       
  3963 QCString DocSimpleSect::typeString() const
       
  3964 {
       
  3965   switch (m_type)
       
  3966   {
       
  3967     case Unknown:    break;
       
  3968     case See:        return "see";
       
  3969     case Return:     return "return";
       
  3970     case Author:     // fall through
       
  3971     case Authors:    return "author";
       
  3972     case Version:    return "version";
       
  3973     case Since:      return "since";
       
  3974     case Date:       return "date";
       
  3975     case Note:       return "note";
       
  3976     case Warning:    return "warning";
       
  3977     case Pre:        return "pre";
       
  3978     case Post:       return "post";
       
  3979     case Invar:      return "invariant";
       
  3980     case Remark:     return "remark";
       
  3981     case Attention:  return "attention";
       
  3982     case User:       return "user";
       
  3983     case Rcs:        return "rcs";
       
  3984   }
       
  3985   return "unknown";
       
  3986 }
       
  3987 
       
  3988 //--------------------------------------------------------------------------
       
  3989 
       
  3990 int DocParamList::parse(const QString &cmdName)
       
  3991 {
       
  3992   int retval=RetVal_OK;
       
  3993   DBG(("DocParamList::parse() start\n"));
       
  3994   g_nodeStack.push(this);
       
  3995   DocPara *par=0;
       
  3996 
       
  3997   int tok=doctokenizerYYlex();
       
  3998   if (tok!=TK_WHITESPACE)
       
  3999   {
       
  4000     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4001         cmdName.data());
       
  4002   }
       
  4003   doctokenizerYYsetStateParam();
       
  4004   tok=doctokenizerYYlex();
       
  4005   while (tok==TK_WORD) /* there is a parameter name */
       
  4006   {
       
  4007     if (m_type==DocParamSect::Param)
       
  4008     {
       
  4009       g_hasParamCommand=TRUE;
       
  4010       checkArgumentName(g_token->name,TRUE);
       
  4011     }
       
  4012     else if (m_type==DocParamSect::RetVal)
       
  4013     {
       
  4014       g_hasReturnCommand=TRUE;
       
  4015       checkArgumentName(g_token->name,FALSE);
       
  4016     }
       
  4017     //m_params.append(g_token->name);
       
  4018     handleLinkedWord(this,m_params);
       
  4019     tok=doctokenizerYYlex();
       
  4020   }
       
  4021   doctokenizerYYsetStatePara();
       
  4022   if (tok==0) /* premature end of comment block */
       
  4023   {
       
  4024     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the "
       
  4025         "argument of command %s",cmdName.data());
       
  4026     retval=0;
       
  4027     goto endparamlist;
       
  4028   }
       
  4029   ASSERT(tok==TK_WHITESPACE);
       
  4030 
       
  4031   par = new DocPara(this);
       
  4032   m_paragraphs.append(par);
       
  4033   retval = par->parse();
       
  4034   par->markFirst();
       
  4035   par->markLast();
       
  4036 
       
  4037 endparamlist:
       
  4038   DBG(("DocParamList::parse() end retval=%d\n",retval));
       
  4039   DocNode *n=g_nodeStack.pop();
       
  4040   ASSERT(n==this);
       
  4041   return retval;
       
  4042 }
       
  4043 
       
  4044 int DocParamList::parseXml(const QString &paramName)
       
  4045 {
       
  4046   int retval=RetVal_OK;
       
  4047   DBG(("DocParamList::parseXml() start\n"));
       
  4048   g_nodeStack.push(this);
       
  4049 
       
  4050   g_token->name = paramName;
       
  4051   if (m_type==DocParamSect::Param)
       
  4052   {
       
  4053     g_hasParamCommand=TRUE;
       
  4054     checkArgumentName(g_token->name,TRUE);
       
  4055   }
       
  4056   else if (m_type==DocParamSect::RetVal)
       
  4057   {
       
  4058     g_hasReturnCommand=TRUE;
       
  4059     checkArgumentName(g_token->name,FALSE);
       
  4060   }
       
  4061   
       
  4062   handleLinkedWord(this,m_params);
       
  4063 
       
  4064   do
       
  4065   {
       
  4066     DocPara *par = new DocPara(this);
       
  4067     retval = par->parse();
       
  4068     if (par->isEmpty()) // avoid adding an empty paragraph for the whitespace
       
  4069                         // after </para> and before </param>
       
  4070     {
       
  4071       delete par;
       
  4072       break;
       
  4073     }
       
  4074     else // append the paragraph to the list
       
  4075     {
       
  4076       if (m_paragraphs.isEmpty())
       
  4077       {
       
  4078         par->markFirst();
       
  4079       }
       
  4080       else
       
  4081       {
       
  4082         m_paragraphs.last()->markLast(FALSE);
       
  4083       }
       
  4084       par->markLast();
       
  4085       m_paragraphs.append(par);
       
  4086     }
       
  4087 
       
  4088     if (retval == 0) break;
       
  4089 
       
  4090   } while (retval==RetVal_CloseXml && 
       
  4091            Mappers::htmlTagMapper->map(g_token->name)!=XML_PARAM &&
       
  4092            Mappers::htmlTagMapper->map(g_token->name)!=XML_TYPEPARAM &&
       
  4093            Mappers::htmlTagMapper->map(g_token->name)!=XML_EXCEPTION);
       
  4094   
       
  4095 
       
  4096   if (retval==0) /* premature end of comment block */
       
  4097   {
       
  4098     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unterminated param or exception tag");
       
  4099   }
       
  4100   else
       
  4101   {
       
  4102     retval=RetVal_OK;
       
  4103   }
       
  4104 
       
  4105 
       
  4106   DBG(("DocParamList::parse() end retval=%d\n",retval));
       
  4107   DocNode *n=g_nodeStack.pop();
       
  4108   ASSERT(n==this);
       
  4109   return retval;
       
  4110 }
       
  4111 
       
  4112 //--------------------------------------------------------------------------
       
  4113 
       
  4114 int DocParamSect::parse(const QString &cmdName,bool xmlContext, Direction d)
       
  4115 {
       
  4116   int retval=RetVal_OK;
       
  4117   DBG(("DocParamSect::parse() start\n"));
       
  4118   g_nodeStack.push(this);
       
  4119 
       
  4120   DocParamList *pl = new DocParamList(this,m_type,d);
       
  4121   if (m_children.isEmpty())
       
  4122   {
       
  4123     pl->markFirst();
       
  4124     pl->markLast();
       
  4125   }
       
  4126   else
       
  4127   {
       
  4128     ASSERT(m_children.last()->kind()==DocNode::Kind_ParamList);
       
  4129     ((DocParamList *)m_children.last())->markLast(FALSE);
       
  4130     pl->markLast();
       
  4131   }
       
  4132   m_children.append(pl);
       
  4133   if (xmlContext)
       
  4134   {
       
  4135     retval = pl->parseXml(cmdName);
       
  4136   }
       
  4137   else
       
  4138   {
       
  4139     retval = pl->parse(cmdName);
       
  4140   }
       
  4141   
       
  4142   DBG(("DocParamSect::parse() end retval=%d\n",retval));
       
  4143   DocNode *n=g_nodeStack.pop();
       
  4144   ASSERT(n==this);
       
  4145   return retval;
       
  4146 }
       
  4147 
       
  4148 //--------------------------------------------------------------------------
       
  4149 
       
  4150 int DocPara::handleSimpleSection(DocSimpleSect::Type t, bool xmlContext)
       
  4151 {
       
  4152   DocSimpleSect *ss=0;
       
  4153   bool needsSeparator = FALSE;
       
  4154   if (!m_children.isEmpty() &&                           // previous element
       
  4155       m_children.last()->kind()==Kind_SimpleSect &&      // was a simple sect
       
  4156       ((DocSimpleSect *)m_children.last())->type()==t && // of same type
       
  4157       t!=DocSimpleSect::User)                            // but not user defined
       
  4158   {
       
  4159     // append to previous section
       
  4160     ss=(DocSimpleSect *)m_children.last();
       
  4161     needsSeparator = TRUE;
       
  4162   }
       
  4163   else // start new section
       
  4164   {
       
  4165     ss=new DocSimpleSect(this,t);
       
  4166     m_children.append(ss);
       
  4167   }
       
  4168   int rv = RetVal_OK;
       
  4169   if (xmlContext)
       
  4170   {
       
  4171     return ss->parseXml();
       
  4172   }
       
  4173   else
       
  4174   {
       
  4175     rv = ss->parse(t==DocSimpleSect::User,needsSeparator);
       
  4176   }
       
  4177   return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
       
  4178 }
       
  4179 
       
  4180 int DocPara::handleParamSection(const QString &cmdName,
       
  4181                                 DocParamSect::Type t,
       
  4182                                 bool xmlContext=FALSE,
       
  4183                                 int direction=DocParamSect::Unspecified)
       
  4184 {
       
  4185   DocParamSect *ps=0;
       
  4186   if (!m_children.isEmpty() &&                        // previous element
       
  4187       m_children.last()->kind()==Kind_ParamSect &&    // was a param sect
       
  4188       ((DocParamSect *)m_children.last())->type()==t) // of same type
       
  4189   {
       
  4190     // append to previous section
       
  4191     ps=(DocParamSect *)m_children.last();
       
  4192   }
       
  4193   else // start new section
       
  4194   {
       
  4195     ps=new DocParamSect(this,t);
       
  4196     m_children.append(ps);
       
  4197   }
       
  4198   int rv=ps->parse(cmdName,xmlContext,(DocParamSect::Direction)direction);
       
  4199   return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
       
  4200 }
       
  4201 
       
  4202 int DocPara::handleXRefItem()
       
  4203 {
       
  4204   int retval=doctokenizerYYlex();
       
  4205   ASSERT(retval==TK_WHITESPACE);
       
  4206   doctokenizerYYsetStateXRefItem();
       
  4207   retval=doctokenizerYYlex();
       
  4208   if (retval==RetVal_OK)
       
  4209   {
       
  4210     DocXRefItem *ref = new DocXRefItem(this,g_token->id,g_token->name);
       
  4211     if (ref->parse())
       
  4212     {
       
  4213       m_children.append(ref);
       
  4214     }
       
  4215     else 
       
  4216     {
       
  4217       delete ref;
       
  4218     }
       
  4219   }
       
  4220   doctokenizerYYsetStatePara();
       
  4221   return retval;
       
  4222 }
       
  4223 
       
  4224 void DocPara::handleIncludeOperator(const QString &cmdName,DocIncOperator::Type t)
       
  4225 {
       
  4226   DBG(("handleIncludeOperator(%s)\n",cmdName.data()));
       
  4227   int tok=doctokenizerYYlex();
       
  4228   if (tok!=TK_WHITESPACE)
       
  4229   {
       
  4230     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4231         cmdName.data());
       
  4232     return;
       
  4233   }
       
  4234   doctokenizerYYsetStatePattern();
       
  4235   tok=doctokenizerYYlex();
       
  4236   doctokenizerYYsetStatePara();
       
  4237   if (tok==0)
       
  4238   {
       
  4239     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the "
       
  4240         "argument of command %s", cmdName.data());
       
  4241     return;
       
  4242   }
       
  4243   else if (tok!=TK_WORD)
       
  4244   {
       
  4245     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4246         tokToString(tok),cmdName.data());
       
  4247     return;
       
  4248   }
       
  4249   DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName);
       
  4250   DocNode *n1 = m_children.last();
       
  4251   DocNode *n2 = n1!=0 ? m_children.prev() : 0;
       
  4252   bool isFirst = n1==0 || // no last node
       
  4253                  (n1->kind()!=DocNode::Kind_IncOperator && 
       
  4254                   n1->kind()!=DocNode::Kind_WhiteSpace
       
  4255                  ) || // last node is not operator or whitespace
       
  4256                  (n1->kind()==DocNode::Kind_WhiteSpace && 
       
  4257                   n2!=0 && n2->kind()!=DocNode::Kind_IncOperator
       
  4258                  ); // previous not is not operator
       
  4259   op->markFirst(isFirst);
       
  4260   op->markLast(TRUE);
       
  4261   if (n1!=0 && n1->kind()==DocNode::Kind_IncOperator)
       
  4262   {
       
  4263     ((DocIncOperator *)n1)->markLast(FALSE);
       
  4264   }
       
  4265   else if (n1!=0 && n1->kind()==DocNode::Kind_WhiteSpace &&
       
  4266            n2!=0 && n2->kind()==DocNode::Kind_IncOperator
       
  4267           )
       
  4268   {
       
  4269     ((DocIncOperator *)n2)->markLast(FALSE);
       
  4270   }
       
  4271   m_children.append(op);
       
  4272   op->parse();
       
  4273 }
       
  4274 
       
  4275 void DocPara::handleImage(const QString &cmdName)
       
  4276 {
       
  4277   int tok=doctokenizerYYlex();
       
  4278   if (tok!=TK_WHITESPACE)
       
  4279   {
       
  4280     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4281         cmdName.data());
       
  4282     return;
       
  4283   }
       
  4284   tok=doctokenizerYYlex();
       
  4285   if (tok!=TK_WORD && tok!=TK_LNKWORD)
       
  4286   {
       
  4287     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4288         tokToString(tok),cmdName.data());
       
  4289     return;
       
  4290   }
       
  4291   tok=doctokenizerYYlex();
       
  4292   if (tok!=TK_WHITESPACE)
       
  4293   {
       
  4294     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4295         cmdName.data());
       
  4296     return;
       
  4297   }
       
  4298   DocImage::Type t;
       
  4299   QString imgType = g_token->name.lower();
       
  4300   if      (imgType=="html")  t=DocImage::Html;
       
  4301   else if (imgType=="latex") t=DocImage::Latex;
       
  4302   else if (imgType=="rtf")   t=DocImage::Rtf;
       
  4303   else
       
  4304   {
       
  4305     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: image type %s specified as the first argument of "
       
  4306         "%s is not valid",
       
  4307         imgType.data(),cmdName.data());
       
  4308     return;
       
  4309   } 
       
  4310   doctokenizerYYsetStateFile();
       
  4311   tok=doctokenizerYYlex();
       
  4312   doctokenizerYYsetStatePara();
       
  4313   if (tok!=TK_WORD)
       
  4314   {
       
  4315     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4316         tokToString(tok),cmdName.data());
       
  4317     return;
       
  4318   }
       
  4319   HtmlAttribList attrList;
       
  4320   DocImage *img = new DocImage(this,attrList,findAndCopyImage(g_token->name,t),t);
       
  4321   m_children.append(img);
       
  4322   img->parse();
       
  4323 }
       
  4324 
       
  4325 void DocPara::handleDotFile(const QString &cmdName)
       
  4326 {
       
  4327   int tok=doctokenizerYYlex();
       
  4328   if (tok!=TK_WHITESPACE)
       
  4329   {
       
  4330     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4331         cmdName.data());
       
  4332     return;
       
  4333   }
       
  4334   doctokenizerYYsetStateFile();
       
  4335   tok=doctokenizerYYlex();
       
  4336   doctokenizerYYsetStatePara();
       
  4337   if (tok!=TK_WORD)
       
  4338   {
       
  4339     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4340         tokToString(tok),cmdName.data());
       
  4341     return;
       
  4342   }
       
  4343   QString name = g_token->name;
       
  4344   DocDotFile *df = new DocDotFile(this,name,g_context);
       
  4345   m_children.append(df);
       
  4346   df->parse();
       
  4347 }
       
  4348 
       
  4349 void DocPara::handleLink(const QString &cmdName,bool isJavaLink)
       
  4350 {
       
  4351   int tok=doctokenizerYYlex();
       
  4352   if (tok!=TK_WHITESPACE)
       
  4353   {
       
  4354     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4355         cmdName.data());
       
  4356     return;
       
  4357   }
       
  4358   doctokenizerYYsetStateLink();
       
  4359   tok=doctokenizerYYlex();
       
  4360   if (tok!=TK_WORD)
       
  4361   {
       
  4362     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4363         tokToString(tok),cmdName.data());
       
  4364     return;
       
  4365   }
       
  4366   doctokenizerYYsetStatePara();
       
  4367   DocLink *lnk = new DocLink(this,g_token->name);
       
  4368   m_children.append(lnk);
       
  4369   QString leftOver = lnk->parse(isJavaLink);
       
  4370   if (!leftOver.isEmpty())
       
  4371   {
       
  4372     m_children.append(new DocWord(this,leftOver));
       
  4373   }
       
  4374 }
       
  4375 
       
  4376 void DocPara::handleRef(const QString &cmdName)
       
  4377 {
       
  4378   DBG(("handleRef(%s)\n",cmdName.data()));
       
  4379   int tok=doctokenizerYYlex();
       
  4380   if (tok!=TK_WHITESPACE)
       
  4381   {
       
  4382     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4383         cmdName.data());
       
  4384     return;
       
  4385   }
       
  4386   doctokenizerYYsetStateRef();
       
  4387   tok=doctokenizerYYlex(); // get the reference id
       
  4388   DocRef *ref=0;
       
  4389   if (tok!=TK_WORD)
       
  4390   {
       
  4391     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4392         tokToString(tok),cmdName.data());
       
  4393     goto endref;
       
  4394   }
       
  4395   ref = new DocRef(this,g_token->name,g_context);
       
  4396   m_children.append(ref);
       
  4397   ref->parse();
       
  4398 endref:
       
  4399   doctokenizerYYsetStatePara();
       
  4400 }
       
  4401 
       
  4402 
       
  4403 void DocPara::handleInclude(const QString &cmdName,DocInclude::Type t)
       
  4404 {
       
  4405   DBG(("handleInclude(%s)\n",cmdName.data()));
       
  4406   int tok=doctokenizerYYlex();
       
  4407   if (tok!=TK_WHITESPACE)
       
  4408   {
       
  4409     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4410         cmdName.data());
       
  4411     return;
       
  4412   }
       
  4413   doctokenizerYYsetStateFile();
       
  4414   tok=doctokenizerYYlex();
       
  4415   doctokenizerYYsetStatePara();
       
  4416   if (tok==0)
       
  4417   {
       
  4418     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the "
       
  4419         "argument of command %s",cmdName.data());
       
  4420     return;
       
  4421   }
       
  4422   else if (tok!=TK_WORD)
       
  4423   {
       
  4424     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4425         tokToString(tok),cmdName.data());
       
  4426     return;
       
  4427   }
       
  4428   DocInclude *inc = new DocInclude(this,g_token->name,g_context,t,g_isExample,g_exampleName);
       
  4429   m_children.append(inc);
       
  4430   inc->parse();
       
  4431 }
       
  4432 
       
  4433 void DocPara::handleSection(const QString &cmdName)
       
  4434 {
       
  4435   // get the argument of the section command.
       
  4436   int tok=doctokenizerYYlex();
       
  4437   if (tok!=TK_WHITESPACE)
       
  4438   {
       
  4439     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4440         cmdName.data());
       
  4441     return;
       
  4442   }
       
  4443   tok=doctokenizerYYlex();
       
  4444   if (tok==0)
       
  4445   {
       
  4446     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the "
       
  4447         "argument of command %s\n", cmdName.data());
       
  4448     return;
       
  4449   }
       
  4450   else if (tok!=TK_WORD && tok!=TK_LNKWORD)
       
  4451   {
       
  4452     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4453         tokToString(tok),cmdName.data());
       
  4454     return;
       
  4455   }
       
  4456   g_token->sectionId = g_token->name;
       
  4457   doctokenizerYYsetStateSkipTitle();
       
  4458   doctokenizerYYlex();
       
  4459   doctokenizerYYsetStatePara();
       
  4460 }
       
  4461 
       
  4462 int DocPara::handleHtmlHeader(const HtmlAttribList &tagHtmlAttribs,int level)
       
  4463 {
       
  4464   DocHtmlHeader *header = new DocHtmlHeader(this,tagHtmlAttribs,level);
       
  4465   m_children.append(header);
       
  4466   int retval = header->parse();
       
  4467   return (retval==RetVal_OK) ? TK_NEWPARA : retval;
       
  4468 }
       
  4469 
       
  4470 // For XML tags whose content is stored in attributes rather than
       
  4471 // contained within the element, we need a way to inject the attribute
       
  4472 // text into the current paragraph.
       
  4473 bool DocPara::injectToken(int tok,const QString &tokText) 
       
  4474 {
       
  4475   g_token->name = tokText;
       
  4476   return defaultHandleToken(this,tok,m_children);
       
  4477 }
       
  4478 
       
  4479 int DocPara::handleStartCode()
       
  4480 {
       
  4481   int retval = doctokenizerYYlex();
       
  4482   // search for the first non-whitespace line, index is stored in li
       
  4483   int i=0,li=0,l=g_token->verb.length();
       
  4484   while (i<l && (g_token->verb.at(i)==' ' || g_token->verb.at(i)=='\n'))
       
  4485   {
       
  4486     if (g_token->verb.at(i)=='\n') li=i+1;
       
  4487     i++;
       
  4488   }
       
  4489   m_children.append(new DocVerbatim(this,g_context,g_token->verb.mid(li),DocVerbatim::Code,g_isExample,g_exampleName));
       
  4490   if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: code section ended without end marker");
       
  4491   doctokenizerYYsetStatePara();
       
  4492   return retval;
       
  4493 }
       
  4494 
       
  4495 void DocPara::handleInheritDoc()
       
  4496 {
       
  4497   if (g_memberDef) // inheriting docs from a member
       
  4498   {
       
  4499     MemberDef *reMd = g_memberDef->reimplements();
       
  4500     if (reMd) // member from which was inherited.
       
  4501     {
       
  4502       MemberDef *thisMd = g_memberDef;
       
  4503       //printf("{InheritDocs:%s=>%s}\n",g_memberDef->qualifiedName().data(),reMd->qualifiedName().data());
       
  4504       docParserPushContext();
       
  4505       g_scope=reMd->getOuterScope();
       
  4506       g_context=g_scope->name();
       
  4507       g_memberDef=reMd;
       
  4508       g_styleStack.clear();
       
  4509       g_nodeStack.clear();
       
  4510       g_copyStack.append(reMd);
       
  4511       internalValidatingParseDoc(this,m_children,reMd->briefDescription());
       
  4512       internalValidatingParseDoc(this,m_children,reMd->documentation());
       
  4513       g_copyStack.remove(reMd);
       
  4514       docParserPopContext(TRUE);
       
  4515       g_memberDef = thisMd;
       
  4516     }
       
  4517   }
       
  4518 }
       
  4519 
       
  4520 
       
  4521 int DocPara::handleCommand(const QString &cmdName)
       
  4522 {
       
  4523   DBG(("handleCommand(%s)\n",cmdName.data()));
       
  4524   int retval = RetVal_OK;
       
  4525   int cmdId = Mappers::cmdMapper->map(cmdName);
       
  4526   switch (cmdId)
       
  4527   {
       
  4528     case CMD_UNKNOWN:
       
  4529       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Found unknown command `\\%s'",cmdName.data());
       
  4530       break;
       
  4531     case CMD_EMPHASIS:
       
  4532       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
       
  4533       retval=handleStyleArgument(this,m_children,cmdName); 
       
  4534       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
       
  4535       if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
       
  4536       break;
       
  4537     case CMD_BOLD:
       
  4538       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
       
  4539       retval=handleStyleArgument(this,m_children,cmdName); 
       
  4540       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
       
  4541       if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
       
  4542       break;
       
  4543     case CMD_CODE:
       
  4544       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,TRUE));
       
  4545       retval=handleStyleArgument(this,m_children,cmdName); 
       
  4546       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,FALSE));
       
  4547       if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
       
  4548       break;
       
  4549     case CMD_BSLASH:
       
  4550       m_children.append(new DocSymbol(this,DocSymbol::BSlash));
       
  4551       break;
       
  4552     case CMD_AT:
       
  4553       m_children.append(new DocSymbol(this,DocSymbol::At));
       
  4554       break;
       
  4555     case CMD_LESS:
       
  4556       m_children.append(new DocSymbol(this,DocSymbol::Less));
       
  4557       break;
       
  4558     case CMD_GREATER:
       
  4559       m_children.append(new DocSymbol(this,DocSymbol::Greater));
       
  4560       break;
       
  4561     case CMD_AMP:
       
  4562       m_children.append(new DocSymbol(this,DocSymbol::Amp));
       
  4563       break;
       
  4564     case CMD_DOLLAR:
       
  4565       m_children.append(new DocSymbol(this,DocSymbol::Dollar));
       
  4566       break;
       
  4567     case CMD_HASH:
       
  4568       m_children.append(new DocSymbol(this,DocSymbol::Hash));
       
  4569       break;
       
  4570     case CMD_PERCENT:
       
  4571       m_children.append(new DocSymbol(this,DocSymbol::Percent));
       
  4572       break;
       
  4573     case CMD_QUOTE:
       
  4574       m_children.append(new DocSymbol(this,DocSymbol::Quot));
       
  4575       break;
       
  4576     case CMD_SA:
       
  4577       g_inSeeBlock=TRUE;
       
  4578       retval = handleSimpleSection(DocSimpleSect::See);
       
  4579       g_inSeeBlock=FALSE;
       
  4580       break;
       
  4581     case CMD_RETURN:
       
  4582       retval = handleSimpleSection(DocSimpleSect::Return);
       
  4583       g_hasReturnCommand=TRUE;
       
  4584       break;
       
  4585     case CMD_AUTHOR:
       
  4586       retval = handleSimpleSection(DocSimpleSect::Author);
       
  4587       break;
       
  4588     case CMD_AUTHORS:
       
  4589       retval = handleSimpleSection(DocSimpleSect::Authors);
       
  4590       break;
       
  4591     case CMD_VERSION:
       
  4592       retval = handleSimpleSection(DocSimpleSect::Version);
       
  4593       break;
       
  4594     case CMD_SINCE:
       
  4595       retval = handleSimpleSection(DocSimpleSect::Since);
       
  4596       break;
       
  4597     case CMD_DATE:
       
  4598       retval = handleSimpleSection(DocSimpleSect::Date);
       
  4599       break;
       
  4600     case CMD_NOTE:
       
  4601       retval = handleSimpleSection(DocSimpleSect::Note);
       
  4602       break;
       
  4603     case CMD_WARNING:
       
  4604       retval = handleSimpleSection(DocSimpleSect::Warning);
       
  4605       break;
       
  4606     case CMD_PRE:
       
  4607       retval = handleSimpleSection(DocSimpleSect::Pre);
       
  4608       break;
       
  4609     case CMD_POST:
       
  4610       retval = handleSimpleSection(DocSimpleSect::Post);
       
  4611       break;
       
  4612     case CMD_INVARIANT:
       
  4613       retval = handleSimpleSection(DocSimpleSect::Invar);
       
  4614       break;
       
  4615     case CMD_REMARK:
       
  4616       retval = handleSimpleSection(DocSimpleSect::Remark);
       
  4617       break;
       
  4618     case CMD_ATTENTION:
       
  4619       retval = handleSimpleSection(DocSimpleSect::Attention);
       
  4620       break;
       
  4621     case CMD_PAR:
       
  4622       retval = handleSimpleSection(DocSimpleSect::User);
       
  4623       break;
       
  4624     case CMD_LI:
       
  4625       {
       
  4626 	DocSimpleList *sl=new DocSimpleList(this);
       
  4627 	m_children.append(sl);
       
  4628         retval = sl->parse();
       
  4629       }
       
  4630       break;
       
  4631     case CMD_SECTION:
       
  4632       {
       
  4633         handleSection(cmdName);
       
  4634 	retval = RetVal_Section;
       
  4635       }
       
  4636       break;
       
  4637     case CMD_SUBSECTION:
       
  4638       {
       
  4639         handleSection(cmdName);
       
  4640         retval = RetVal_Subsection;
       
  4641       }
       
  4642       break;
       
  4643     case CMD_SUBSUBSECTION:
       
  4644       {
       
  4645         handleSection(cmdName);
       
  4646         retval = RetVal_Subsubsection;
       
  4647       }
       
  4648       break;
       
  4649     case CMD_PARAGRAPH:
       
  4650       {
       
  4651         handleSection(cmdName);
       
  4652         retval = RetVal_Paragraph;
       
  4653       }
       
  4654       break;
       
  4655     case CMD_STARTCODE:
       
  4656       {
       
  4657         doctokenizerYYsetStateCode();
       
  4658         retval = handleStartCode();
       
  4659       }
       
  4660       break;
       
  4661     case CMD_HTMLONLY:
       
  4662       {
       
  4663         doctokenizerYYsetStateHtmlOnly();
       
  4664         retval = doctokenizerYYlex();
       
  4665         m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName));
       
  4666         if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: htmlonly section ended without end marker");
       
  4667         doctokenizerYYsetStatePara();
       
  4668       }
       
  4669       break;
       
  4670     case CMD_MANONLY:
       
  4671       {
       
  4672         doctokenizerYYsetStateManOnly();
       
  4673         retval = doctokenizerYYlex();
       
  4674         m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName));
       
  4675         if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: manonly section ended without end marker");
       
  4676         doctokenizerYYsetStatePara();
       
  4677       }
       
  4678       break;
       
  4679     case CMD_LATEXONLY:
       
  4680       {
       
  4681         doctokenizerYYsetStateLatexOnly();
       
  4682         retval = doctokenizerYYlex();
       
  4683         m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName));
       
  4684         if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: latexonly section ended without end marker");
       
  4685         doctokenizerYYsetStatePara();
       
  4686       }
       
  4687       break;
       
  4688     case CMD_XMLONLY:
       
  4689       {
       
  4690         doctokenizerYYsetStateXmlOnly();
       
  4691         retval = doctokenizerYYlex();
       
  4692         m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName));
       
  4693         if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: xmlonly section ended without end marker");
       
  4694         doctokenizerYYsetStatePara();
       
  4695       }
       
  4696       break;
       
  4697     case CMD_VERBATIM:
       
  4698       {
       
  4699         doctokenizerYYsetStateVerbatim();
       
  4700         retval = doctokenizerYYlex();
       
  4701         m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Verbatim,g_isExample,g_exampleName));
       
  4702         if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: verbatim section ended without end marker");
       
  4703         doctokenizerYYsetStatePara();
       
  4704       }
       
  4705       break;
       
  4706     case CMD_DOT:
       
  4707       {
       
  4708         doctokenizerYYsetStateDot();
       
  4709         retval = doctokenizerYYlex();
       
  4710         m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Dot,g_isExample,g_exampleName));
       
  4711         if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: dot section ended without end marker");
       
  4712         doctokenizerYYsetStatePara();
       
  4713       }
       
  4714       break;
       
  4715     case CMD_MSC:
       
  4716       {
       
  4717         doctokenizerYYsetStateMsc();
       
  4718         retval = doctokenizerYYlex();
       
  4719         m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName));
       
  4720         if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: msc section ended without end marker");
       
  4721         doctokenizerYYsetStatePara();
       
  4722       }
       
  4723       break;
       
  4724     case CMD_ENDCODE:
       
  4725     case CMD_ENDHTMLONLY:
       
  4726     case CMD_ENDMANONLY:
       
  4727     case CMD_ENDLATEXONLY:
       
  4728     case CMD_ENDXMLONLY:
       
  4729     case CMD_ENDLINK:
       
  4730     case CMD_ENDVERBATIM:
       
  4731     case CMD_ENDDOT:
       
  4732       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data());
       
  4733       break; 
       
  4734     case CMD_ENDMSC:
       
  4735       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data());
       
  4736       break; 
       
  4737     case CMD_PARAM:
       
  4738       retval = handleParamSection(cmdName,DocParamSect::Param,FALSE,g_token->paramDir);
       
  4739       break;
       
  4740     case CMD_TPARAM:
       
  4741       retval = handleParamSection(cmdName,DocParamSect::TemplateParam,FALSE,g_token->paramDir);
       
  4742       break;
       
  4743     case CMD_RETVAL:
       
  4744       retval = handleParamSection(cmdName,DocParamSect::RetVal);
       
  4745       break;
       
  4746     case CMD_EXCEPTION:
       
  4747       retval = handleParamSection(cmdName,DocParamSect::Exception);
       
  4748       break;
       
  4749     case CMD_XREFITEM:
       
  4750       retval = handleXRefItem();
       
  4751       break;
       
  4752     case CMD_LINEBREAK:
       
  4753       {
       
  4754         DocLineBreak *lb = new DocLineBreak(this);
       
  4755         m_children.append(lb);
       
  4756       }
       
  4757       break;
       
  4758     case CMD_ANCHOR:
       
  4759       {
       
  4760         int tok=doctokenizerYYlex();
       
  4761         if (tok!=TK_WHITESPACE)
       
  4762         {
       
  4763           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4764               cmdName.data());
       
  4765           break;
       
  4766         }
       
  4767         tok=doctokenizerYYlex();
       
  4768         if (tok==0)
       
  4769         {
       
  4770           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the "
       
  4771               "argument of command %s",cmdName.data());
       
  4772           break;
       
  4773         }
       
  4774         else if (tok!=TK_WORD && tok!=TK_LNKWORD)
       
  4775         {
       
  4776           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4777               tokToString(tok),cmdName.data());
       
  4778           break;
       
  4779         }
       
  4780         DocAnchor *anchor = new DocAnchor(this,g_token->name,FALSE);
       
  4781         m_children.append(anchor);
       
  4782       }
       
  4783       break;
       
  4784     case CMD_ADDINDEX:
       
  4785       {
       
  4786         DocIndexEntry *ie = new DocIndexEntry(this,
       
  4787                      g_scope!=Doxygen::globalScope?g_scope:0,
       
  4788                      g_memberDef);
       
  4789         m_children.append(ie);
       
  4790         retval = ie->parse();
       
  4791       }
       
  4792       break;
       
  4793     case CMD_INTERNAL:
       
  4794       retval = RetVal_Internal;
       
  4795       break;
       
  4796     case CMD_COPYDOC:   // fall through
       
  4797     case CMD_COPYBRIEF: // fall through
       
  4798     case CMD_COPYDETAILS:
       
  4799       {
       
  4800         int tok=doctokenizerYYlex();
       
  4801         if (tok!=TK_WHITESPACE)
       
  4802         {
       
  4803           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
       
  4804               cmdName.data());
       
  4805           break;
       
  4806         }
       
  4807         tok=doctokenizerYYlex();
       
  4808         if (tok==0)
       
  4809         {
       
  4810           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the "
       
  4811               "argument of command %s\n", cmdName.data());
       
  4812           break;
       
  4813         }
       
  4814         else if (tok!=TK_WORD && tok!=TK_LNKWORD)
       
  4815         {
       
  4816           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
       
  4817               tokToString(tok),cmdName.data());
       
  4818           break;
       
  4819         }
       
  4820         DocCopy *cpy = new DocCopy(this,g_token->name,
       
  4821             cmdId==CMD_COPYDOC || cmdId==CMD_COPYBRIEF,
       
  4822             cmdId==CMD_COPYDOC || cmdId==CMD_COPYDETAILS);
       
  4823         m_children.append(cpy);
       
  4824         cpy->parse();
       
  4825       }
       
  4826       break;
       
  4827     case CMD_INCLUDE:
       
  4828       handleInclude(cmdName,DocInclude::Include);
       
  4829       break;
       
  4830     case CMD_INCWITHLINES:
       
  4831       handleInclude(cmdName,DocInclude::IncWithLines);
       
  4832       break;
       
  4833     case CMD_DONTINCLUDE:
       
  4834       handleInclude(cmdName,DocInclude::DontInclude);
       
  4835       break;
       
  4836     case CMD_HTMLINCLUDE:
       
  4837       handleInclude(cmdName,DocInclude::HtmlInclude);
       
  4838       break;
       
  4839     case CMD_VERBINCLUDE:
       
  4840       handleInclude(cmdName,DocInclude::VerbInclude);
       
  4841       break;
       
  4842     case CMD_SKIP:
       
  4843       handleIncludeOperator(cmdName,DocIncOperator::Skip);
       
  4844       break;
       
  4845     case CMD_UNTIL:
       
  4846       handleIncludeOperator(cmdName,DocIncOperator::Until);
       
  4847       break;
       
  4848     case CMD_SKIPLINE:
       
  4849       handleIncludeOperator(cmdName,DocIncOperator::SkipLine);
       
  4850       break;
       
  4851     case CMD_LINE:
       
  4852       handleIncludeOperator(cmdName,DocIncOperator::Line);
       
  4853       break;
       
  4854     case CMD_IMAGE:
       
  4855       handleImage(cmdName);
       
  4856       break;
       
  4857     case CMD_DOTFILE:
       
  4858       handleDotFile(cmdName);
       
  4859       break;
       
  4860     case CMD_LINK:
       
  4861       handleLink(cmdName,FALSE);
       
  4862       break;
       
  4863     case CMD_JAVALINK:
       
  4864       handleLink(cmdName,TRUE);
       
  4865       break;
       
  4866     case CMD_REF: // fall through
       
  4867     case CMD_SUBPAGE:
       
  4868       handleRef(cmdName);
       
  4869       break;
       
  4870     case CMD_SECREFLIST:
       
  4871       {
       
  4872         DocSecRefList *list = new DocSecRefList(this);
       
  4873         m_children.append(list);
       
  4874         list->parse();
       
  4875       }
       
  4876       break;
       
  4877     case CMD_SECREFITEM:
       
  4878       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data());
       
  4879       break;
       
  4880     case CMD_ENDSECREFLIST:
       
  4881       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data());
       
  4882       break;
       
  4883     case CMD_FORMULA:
       
  4884       {
       
  4885         DocFormula *form=new DocFormula(this,g_token->id);
       
  4886         m_children.append(form);
       
  4887       }
       
  4888       break;
       
  4889     //case CMD_LANGSWITCH:
       
  4890     //  retval = handleLanguageSwitch();
       
  4891     //  break;
       
  4892     case CMD_INTERNALREF:
       
  4893       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data());
       
  4894       break;
       
  4895     case CMD_INHERITDOC:
       
  4896       handleInheritDoc();
       
  4897       break;
       
  4898     default:
       
  4899       // we should not get here!
       
  4900       ASSERT(0);
       
  4901       break;
       
  4902   }
       
  4903   INTERNAL_ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec || 
       
  4904          retval==TK_LISTITEM || retval==TK_ENDLIST || retval==TK_NEWPARA ||
       
  4905          retval==RetVal_Section || retval==RetVal_EndList || 
       
  4906          retval==RetVal_Internal || retval==RetVal_SwitchLang
       
  4907         );
       
  4908   DBG(("handleCommand(%s) end retval=%x\n",cmdName.data(),retval));
       
  4909   return retval;
       
  4910 }
       
  4911 
       
  4912 static bool findAttribute(const HtmlAttribList &tagHtmlAttribs, 
       
  4913                           const char *attrName, 
       
  4914                           QString *result) 
       
  4915 {
       
  4916 
       
  4917   HtmlAttribListIterator li(tagHtmlAttribs);
       
  4918   HtmlAttrib *opt;
       
  4919   for (li.toFirst();(opt=li.current());++li)
       
  4920   {
       
  4921     if (opt->name==attrName) 
       
  4922     {
       
  4923       *result = opt->value;
       
  4924       return TRUE;
       
  4925     }
       
  4926   }
       
  4927   return FALSE;
       
  4928 }
       
  4929 
       
  4930 int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tagHtmlAttribs)
       
  4931 {
       
  4932   DBG(("handleHtmlStartTag(%s,%d)\n",tagName.data(),tagHtmlAttribs.count()));
       
  4933   int retval=RetVal_OK;
       
  4934   int tagId = Mappers::htmlTagMapper->map(tagName);
       
  4935   if (g_token->emptyTag && !(tagId&XML_CmdMask) && tagId!=HTML_UNKNOWN)
       
  4936       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: HTML tags may not use the 'empty tag' XHTML syntax.");
       
  4937   switch (tagId)
       
  4938   {
       
  4939     case HTML_UL: 
       
  4940       {
       
  4941         DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Unordered);
       
  4942         m_children.append(list);
       
  4943         retval=list->parse();
       
  4944       }
       
  4945       break;
       
  4946     case HTML_OL: 
       
  4947       {
       
  4948         DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Ordered);
       
  4949         m_children.append(list);
       
  4950         retval=list->parse();
       
  4951       }
       
  4952       break;
       
  4953     case HTML_LI:
       
  4954       if (!insideUL(this) && !insideOL(this))
       
  4955       {
       
  4956         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <li> tag found");
       
  4957       }
       
  4958       else
       
  4959       {
       
  4960         retval=RetVal_ListItem;
       
  4961       }
       
  4962       break;
       
  4963     case HTML_BOLD:
       
  4964       handleStyleEnter(this,m_children,DocStyleChange::Bold,&g_token->attribs);
       
  4965       break;
       
  4966     case HTML_CODE:
       
  4967       if (g_fileName.right(3)==".cs") 
       
  4968         // for C# code we treat <code> as an XML tag
       
  4969       {
       
  4970         doctokenizerYYsetStateXmlCode();
       
  4971         retval = handleStartCode();
       
  4972       }
       
  4973       else // normal HTML markup
       
  4974       {
       
  4975         handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs);
       
  4976       }
       
  4977       break;
       
  4978     case HTML_EMPHASIS:
       
  4979       handleStyleEnter(this,m_children,DocStyleChange::Italic,&g_token->attribs);
       
  4980       break;
       
  4981     case HTML_DIV:
       
  4982       handleStyleEnter(this,m_children,DocStyleChange::Div,&g_token->attribs);
       
  4983       break;
       
  4984     case HTML_SPAN:
       
  4985       handleStyleEnter(this,m_children,DocStyleChange::Span,&g_token->attribs);
       
  4986       break;
       
  4987     case HTML_SUB:
       
  4988       handleStyleEnter(this,m_children,DocStyleChange::Subscript,&g_token->attribs);
       
  4989       break;
       
  4990     case HTML_SUP:
       
  4991       handleStyleEnter(this,m_children,DocStyleChange::Superscript,&g_token->attribs);
       
  4992       break;
       
  4993     case HTML_CENTER:
       
  4994       handleStyleEnter(this,m_children,DocStyleChange::Center,&g_token->attribs);
       
  4995       break;
       
  4996     case HTML_SMALL:
       
  4997       handleStyleEnter(this,m_children,DocStyleChange::Small,&g_token->attribs);
       
  4998       break;
       
  4999     case HTML_PRE:
       
  5000       handleStyleEnter(this,m_children,DocStyleChange::Preformatted,&g_token->attribs);
       
  5001       setInsidePreformatted(TRUE);
       
  5002       //doctokenizerYYsetInsidePre(TRUE);
       
  5003       break;
       
  5004     case HTML_P:
       
  5005       retval=TK_NEWPARA;
       
  5006       break;
       
  5007     case HTML_DL:
       
  5008       {
       
  5009         DocHtmlDescList *list = new DocHtmlDescList(this,tagHtmlAttribs);
       
  5010         m_children.append(list);
       
  5011         retval=list->parse();
       
  5012       }
       
  5013       break;
       
  5014     case HTML_DT:
       
  5015       retval = RetVal_DescTitle;
       
  5016       break;
       
  5017     case HTML_DD:
       
  5018       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag <dd> found");
       
  5019       break;
       
  5020     case HTML_TABLE:
       
  5021       {
       
  5022         DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs);
       
  5023         m_children.append(table);
       
  5024         retval=table->parse();
       
  5025       }
       
  5026       break;
       
  5027     case HTML_TR:
       
  5028       retval = RetVal_TableRow;
       
  5029       break;
       
  5030     case HTML_TD:
       
  5031       retval = RetVal_TableCell;
       
  5032       break;
       
  5033     case HTML_TH:
       
  5034       retval = RetVal_TableHCell;
       
  5035       break;
       
  5036     case HTML_CAPTION:
       
  5037       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag <caption> found");
       
  5038       break;
       
  5039     case HTML_BR:
       
  5040       {
       
  5041         DocLineBreak *lb = new DocLineBreak(this);
       
  5042         m_children.append(lb);
       
  5043       }
       
  5044       break;
       
  5045     case HTML_HR:
       
  5046       {
       
  5047         DocHorRuler *hr = new DocHorRuler(this);
       
  5048         m_children.append(hr);
       
  5049       }
       
  5050       break;
       
  5051     case HTML_A:
       
  5052       retval=handleAHref(this,m_children,tagHtmlAttribs);
       
  5053       break;
       
  5054     case HTML_H1:
       
  5055       retval=handleHtmlHeader(tagHtmlAttribs,1);
       
  5056       break;
       
  5057     case HTML_H2:
       
  5058       retval=handleHtmlHeader(tagHtmlAttribs,2);
       
  5059       break;
       
  5060     case HTML_H3:
       
  5061       retval=handleHtmlHeader(tagHtmlAttribs,3);
       
  5062       break;
       
  5063     case HTML_H4:
       
  5064       retval=handleHtmlHeader(tagHtmlAttribs,4);
       
  5065       break;
       
  5066     case HTML_H5:
       
  5067       retval=handleHtmlHeader(tagHtmlAttribs,5);
       
  5068       break;
       
  5069     case HTML_H6:
       
  5070       retval=handleHtmlHeader(tagHtmlAttribs,6);
       
  5071       break;
       
  5072     case HTML_IMG:
       
  5073       {
       
  5074         HtmlAttribListIterator li(tagHtmlAttribs);
       
  5075         HtmlAttrib *opt;
       
  5076         bool found=FALSE;
       
  5077         int index=0;
       
  5078         for (li.toFirst();(opt=li.current());++li,++index)
       
  5079         {
       
  5080           //printf("option name=%s value=%s\n",opt->name.data(),opt->value.data());
       
  5081           if (opt->name=="src" && !opt->value.isEmpty())
       
  5082           {
       
  5083             // copy attributes
       
  5084             HtmlAttribList attrList = tagHtmlAttribs;
       
  5085             // and remove the href attribute
       
  5086             bool result = attrList.remove(index);
       
  5087             ASSERT(result);
       
  5088             DocImage *img = new DocImage(this,attrList,opt->value,DocImage::Html);
       
  5089             m_children.append(img);
       
  5090             found = TRUE;
       
  5091           }
       
  5092         }
       
  5093         if (!found)
       
  5094         {
       
  5095           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: IMG tag does not have a SRC attribute!\n");
       
  5096         }
       
  5097       }
       
  5098       break;
       
  5099 
       
  5100     case XML_SUMMARY:
       
  5101     case XML_REMARKS:
       
  5102     case XML_VALUE:
       
  5103     case XML_PARA:
       
  5104       if (!m_children.isEmpty())
       
  5105       {
       
  5106         retval = TK_NEWPARA;
       
  5107       }
       
  5108       break;
       
  5109     case XML_EXAMPLE:
       
  5110     case XML_DESCRIPTION:
       
  5111       if (insideTable(this))
       
  5112       {
       
  5113         retval=RetVal_TableCell;
       
  5114       }
       
  5115       break;
       
  5116     case XML_C:
       
  5117       handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs);
       
  5118       break;
       
  5119     case XML_PARAM:
       
  5120     case XML_TYPEPARAM:
       
  5121       {
       
  5122         QString paramName;
       
  5123         if (findAttribute(tagHtmlAttribs,"name",&paramName))
       
  5124         {
       
  5125           retval = handleParamSection(paramName,
       
  5126               tagId==XML_PARAM ? DocParamSect::Param : DocParamSect::TemplateParam,
       
  5127               TRUE);
       
  5128         }
       
  5129         else
       
  5130         {
       
  5131           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'name' attribute from <param> tag.");
       
  5132         }
       
  5133       }
       
  5134       break;
       
  5135     case XML_PARAMREF:
       
  5136     case XML_TYPEPARAMREF:
       
  5137       {
       
  5138         QString paramName;
       
  5139         if (findAttribute(tagHtmlAttribs,"name",&paramName))
       
  5140         {
       
  5141           //printf("paramName=%s\n",paramName.data());
       
  5142           m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
       
  5143           m_children.append(new DocWord(this,paramName)); 
       
  5144           m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
       
  5145           if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
       
  5146         }
       
  5147         else
       
  5148         {
       
  5149           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type");
       
  5150         }
       
  5151       }
       
  5152       break;
       
  5153     case XML_EXCEPTION:
       
  5154       {
       
  5155         QString exceptName;
       
  5156         if (findAttribute(tagHtmlAttribs,"cref",&exceptName))
       
  5157         {
       
  5158           retval = handleParamSection(exceptName,DocParamSect::Exception,TRUE);
       
  5159         }
       
  5160         else
       
  5161         {
       
  5162           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'name' attribute from <exception> tag.");
       
  5163         }
       
  5164       }
       
  5165       break;
       
  5166     case XML_ITEM:
       
  5167     case XML_LISTHEADER:
       
  5168       if (insideTable(this))
       
  5169       {
       
  5170         retval=RetVal_TableRow;
       
  5171       }
       
  5172       else if (insideUL(this) || insideOL(this))
       
  5173       {
       
  5174         retval=RetVal_ListItem;
       
  5175       }
       
  5176       else
       
  5177       {
       
  5178         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <item> tag found");
       
  5179       }
       
  5180       break;
       
  5181     case XML_RETURNS:
       
  5182       retval = handleSimpleSection(DocSimpleSect::Return,TRUE);
       
  5183       g_hasReturnCommand=TRUE;
       
  5184       break;
       
  5185     case XML_TERM:
       
  5186       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
       
  5187       if (insideTable(this))
       
  5188       {
       
  5189         retval=RetVal_TableCell;
       
  5190       }
       
  5191       break;
       
  5192     case XML_SEE:
       
  5193       // I'm not sure if <see> is the same as <seealso> or if it
       
  5194       // should you link a member without producing a section. The
       
  5195       // C# specification is extremely vague about this (but what else 
       
  5196       // can we expect from Microsoft...)
       
  5197       {
       
  5198         QString cref;
       
  5199         //printf("XML_SEE: empty tag=%d\n",g_token->emptyTag);
       
  5200         if (findAttribute(tagHtmlAttribs,"cref",&cref))
       
  5201         {
       
  5202           if (g_token->emptyTag) // <see cref="..."/> style
       
  5203           {
       
  5204             bool inSeeBlock = g_inSeeBlock;
       
  5205             g_token->name = cref;
       
  5206             g_inSeeBlock = TRUE;
       
  5207             handleLinkedWord(this,m_children);
       
  5208             g_inSeeBlock = inSeeBlock;
       
  5209           }
       
  5210           else // <see cref="...">...</see> style
       
  5211           {
       
  5212             //DocRef *ref = new DocRef(this,cref);
       
  5213             //m_children.append(ref);
       
  5214             //ref->parse();
       
  5215             doctokenizerYYsetStatePara();
       
  5216             DocLink *lnk = new DocLink(this,cref);
       
  5217             m_children.append(lnk);
       
  5218             QString leftOver = lnk->parse(FALSE,TRUE);
       
  5219             if (!leftOver.isEmpty())
       
  5220             {
       
  5221               m_children.append(new DocWord(this,leftOver));
       
  5222             }
       
  5223           }
       
  5224         }
       
  5225         else
       
  5226         {
       
  5227           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'cref' attribute from <see> tag.");
       
  5228         }
       
  5229       }
       
  5230       break;
       
  5231     case XML_SEEALSO:
       
  5232       {
       
  5233         QString cref;
       
  5234         if (findAttribute(tagHtmlAttribs,"cref",&cref))
       
  5235         {
       
  5236           // Look for an existing "see" section
       
  5237           DocSimpleSect *ss=0;
       
  5238           QListIterator<DocNode> cli(m_children);
       
  5239           DocNode *n;
       
  5240           for (cli.toFirst();(n=cli.current());++cli)
       
  5241           {
       
  5242             if (n->kind()==Kind_SimpleSect && ((DocSimpleSect *)n)->type()==DocSimpleSect::See)
       
  5243             {
       
  5244               ss = (DocSimpleSect *)n;
       
  5245             }
       
  5246           }
       
  5247 
       
  5248           if (!ss)  // start new section
       
  5249           {
       
  5250             ss=new DocSimpleSect(this,DocSimpleSect::See);
       
  5251             m_children.append(ss);
       
  5252           }
       
  5253 
       
  5254           ss->appendLinkWord(cref);
       
  5255           retval = RetVal_OK;
       
  5256         }
       
  5257         else
       
  5258         {
       
  5259           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'cref' attribute from <seealso> tag.");
       
  5260         }
       
  5261       }
       
  5262       break;
       
  5263     case XML_LIST:
       
  5264       {
       
  5265         QString type;
       
  5266         findAttribute(tagHtmlAttribs,"type",&type);
       
  5267         DocHtmlList::Type listType = DocHtmlList::Unordered;
       
  5268         if (type=="number")
       
  5269         {
       
  5270           listType=DocHtmlList::Ordered;
       
  5271         }
       
  5272         if (type=="table")
       
  5273         {
       
  5274           DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs);
       
  5275           m_children.append(table);
       
  5276           retval=table->parseXml();
       
  5277         }
       
  5278         else
       
  5279         {
       
  5280           HtmlAttribList emptyList;
       
  5281           DocHtmlList *list = new DocHtmlList(this,emptyList,listType);
       
  5282           m_children.append(list);
       
  5283           retval=list->parseXml();
       
  5284         }
       
  5285       }
       
  5286       break;
       
  5287     case XML_INCLUDE:
       
  5288     case XML_PERMISSION:
       
  5289       // These tags are defined in .Net but are currently unsupported
       
  5290       break;
       
  5291     case HTML_UNKNOWN:
       
  5292       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported xml/html tag <%s> found", tagName.data());
       
  5293       m_children.append(new DocWord(this, "<"+tagName+tagHtmlAttribs.toString()+">"));
       
  5294       break;
       
  5295     default:
       
  5296       // we should not get here!
       
  5297       ASSERT(0);
       
  5298       break;
       
  5299   }
       
  5300   return retval;
       
  5301 }
       
  5302 
       
  5303 int DocPara::handleHtmlEndTag(const QString &tagName)
       
  5304 {
       
  5305   DBG(("handleHtmlEndTag(%s)\n",tagName.data()));
       
  5306   int tagId = Mappers::htmlTagMapper->map(tagName);
       
  5307   int retval=RetVal_OK;
       
  5308   switch (tagId)
       
  5309   {
       
  5310     case HTML_UL: 
       
  5311       if (!insideUL(this))
       
  5312       {
       
  5313         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </ul> tag without matching <ul>");
       
  5314       }
       
  5315       else
       
  5316       {
       
  5317         retval=RetVal_EndList;
       
  5318       }
       
  5319       break;
       
  5320     case HTML_OL: 
       
  5321       if (!insideOL(this))
       
  5322       {
       
  5323         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </ol> tag without matching <ol>");
       
  5324       }
       
  5325       else
       
  5326       {
       
  5327         retval=RetVal_EndList;
       
  5328       }
       
  5329       break;
       
  5330     case HTML_LI:
       
  5331       if (!insideLI(this))
       
  5332       {
       
  5333         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </li> tag without matching <li>");
       
  5334       }
       
  5335       else
       
  5336       {
       
  5337         // ignore </li> tags
       
  5338       }
       
  5339       break;
       
  5340     //case HTML_PRE:
       
  5341     //  if (!insidePRE(this))
       
  5342     //  {
       
  5343     //    warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </pre> tag without matching <pre>");
       
  5344     //  }
       
  5345     //  else
       
  5346     //  {
       
  5347     //    retval=RetVal_EndPre;
       
  5348     //  }
       
  5349     //  break;
       
  5350     case HTML_BOLD:
       
  5351       handleStyleLeave(this,m_children,DocStyleChange::Bold,"b");
       
  5352       break;
       
  5353     case HTML_CODE:
       
  5354       handleStyleLeave(this,m_children,DocStyleChange::Code,"code");
       
  5355       break;
       
  5356     case HTML_EMPHASIS:
       
  5357       handleStyleLeave(this,m_children,DocStyleChange::Italic,"em");
       
  5358       break;
       
  5359     case HTML_DIV:
       
  5360       handleStyleLeave(this,m_children,DocStyleChange::Div,"div");
       
  5361       break;
       
  5362     case HTML_SPAN:
       
  5363       handleStyleLeave(this,m_children,DocStyleChange::Span,"span");
       
  5364       break;
       
  5365     case HTML_SUB:
       
  5366       handleStyleLeave(this,m_children,DocStyleChange::Subscript,"sub");
       
  5367       break;
       
  5368     case HTML_SUP:
       
  5369       handleStyleLeave(this,m_children,DocStyleChange::Superscript,"sup");
       
  5370       break;
       
  5371     case HTML_CENTER:
       
  5372       handleStyleLeave(this,m_children,DocStyleChange::Center,"center");
       
  5373       break;
       
  5374     case HTML_SMALL:
       
  5375       handleStyleLeave(this,m_children,DocStyleChange::Small,"small");
       
  5376       break;
       
  5377     case HTML_PRE:
       
  5378       handleStyleLeave(this,m_children,DocStyleChange::Preformatted,"pre");
       
  5379       setInsidePreformatted(FALSE);
       
  5380       //doctokenizerYYsetInsidePre(FALSE);
       
  5381       break;
       
  5382     case HTML_P:
       
  5383       // ignore </p> tag
       
  5384       break;
       
  5385     case HTML_DL:
       
  5386       retval=RetVal_EndDesc;
       
  5387       break;
       
  5388     case HTML_DT:
       
  5389       // ignore </dt> tag
       
  5390       break;
       
  5391     case HTML_DD:
       
  5392       // ignore </dd> tag
       
  5393       break;
       
  5394     case HTML_TABLE:
       
  5395       retval=RetVal_EndTable;
       
  5396       break;
       
  5397     case HTML_TR:
       
  5398       // ignore </tr> tag
       
  5399       break;
       
  5400     case HTML_TD:
       
  5401       // ignore </td> tag
       
  5402       break;
       
  5403     case HTML_TH:
       
  5404       // ignore </th> tag
       
  5405       break;
       
  5406     case HTML_CAPTION:
       
  5407       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </caption> found");
       
  5408       break;
       
  5409     case HTML_BR:
       
  5410       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal </br> tag found\n");
       
  5411       break;
       
  5412     case HTML_H1:
       
  5413       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </h1> found");
       
  5414       break;
       
  5415     case HTML_H2:
       
  5416       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </h2> found");
       
  5417       break;
       
  5418     case HTML_H3:
       
  5419       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </h3> found");
       
  5420       break;
       
  5421     case HTML_IMG:
       
  5422       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </img> found");
       
  5423       break;
       
  5424     case HTML_HR:
       
  5425       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </hr> found");
       
  5426       break;
       
  5427     case HTML_A:
       
  5428       //warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </a> found");
       
  5429       // ignore </a> tag (can be part of <a name=...></a>
       
  5430       break;
       
  5431 
       
  5432     case XML_TERM:
       
  5433       m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
       
  5434       break;
       
  5435     case XML_SUMMARY:
       
  5436     case XML_REMARKS:
       
  5437     case XML_PARA:
       
  5438     case XML_VALUE:
       
  5439     case XML_LIST:
       
  5440     case XML_EXAMPLE:
       
  5441     case XML_PARAM:
       
  5442     case XML_TYPEPARAM:
       
  5443     case XML_RETURNS:
       
  5444     case XML_SEEALSO:
       
  5445     case XML_EXCEPTION:
       
  5446       retval = RetVal_CloseXml;
       
  5447       break;
       
  5448     case XML_C:
       
  5449       handleStyleLeave(this,m_children,DocStyleChange::Code,"c");
       
  5450       break;
       
  5451     case XML_ITEM:
       
  5452     case XML_LISTHEADER:
       
  5453     case XML_INCLUDE:
       
  5454     case XML_PERMISSION:
       
  5455     case XML_DESCRIPTION:
       
  5456     case XML_PARAMREF:
       
  5457     case XML_TYPEPARAMREF:
       
  5458       // These tags are defined in .Net but are currently unsupported
       
  5459       break;
       
  5460     case HTML_UNKNOWN:
       
  5461       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported xml/html tag </%s> found", tagName.data());
       
  5462       m_children.append(new DocWord(this,"</"+tagName+">"));
       
  5463       break;
       
  5464     default:
       
  5465       // we should not get here!
       
  5466       warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end tag %s\n",tagName.data());
       
  5467       ASSERT(0);
       
  5468       break;
       
  5469   }
       
  5470   return retval;
       
  5471 }
       
  5472 
       
  5473 int DocPara::parse()
       
  5474 {
       
  5475   DBG(("DocPara::parse() start\n"));
       
  5476   g_nodeStack.push(this);
       
  5477   // handle style commands "inherited" from the previous paragraph
       
  5478   handleInitialStyleCommands(this,m_children);
       
  5479   int tok;
       
  5480   int retval=0;
       
  5481   while ((tok=doctokenizerYYlex())) // get the next token
       
  5482   {
       
  5483 reparsetoken:
       
  5484     DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
       
  5485     if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || 
       
  5486         tok==TK_COMMAND || tok==TK_HTMLTAG
       
  5487        )
       
  5488     {
       
  5489       DBG((" name=%s",g_token->name.data()));
       
  5490     }
       
  5491     DBG(("\n"));
       
  5492     switch(tok)
       
  5493     {
       
  5494       case TK_WORD:
       
  5495         m_children.append(new DocWord(this,g_token->name));
       
  5496         break;
       
  5497       case TK_LNKWORD:
       
  5498         handleLinkedWord(this,m_children);
       
  5499         break;
       
  5500       case TK_URL:
       
  5501         m_children.append(new DocURL(this,g_token->name,g_token->isEMailAddr));
       
  5502         break;
       
  5503       case TK_WHITESPACE:
       
  5504         {
       
  5505           // prevent leading whitespace and collapse multiple whitespace areas
       
  5506           DocNode::Kind k;
       
  5507           if (insidePRE(this) || // all whitespace is relevant
       
  5508               (
       
  5509                // remove leading whitespace 
       
  5510                !m_children.isEmpty()  && 
       
  5511                // and whitespace after certain constructs
       
  5512                (k=m_children.last()->kind())!=DocNode::Kind_HtmlDescList &&
       
  5513                k!=DocNode::Kind_HtmlTable &&
       
  5514                k!=DocNode::Kind_HtmlList &&
       
  5515                k!=DocNode::Kind_SimpleSect &&
       
  5516                k!=DocNode::Kind_AutoList &&
       
  5517                k!=DocNode::Kind_SimpleList &&
       
  5518                /*k!=DocNode::Kind_Verbatim &&*/
       
  5519                k!=DocNode::Kind_HtmlHeader &&
       
  5520                k!=DocNode::Kind_ParamSect &&
       
  5521                k!=DocNode::Kind_XRefItem
       
  5522               )
       
  5523              )
       
  5524           {
       
  5525             m_children.append(new DocWhiteSpace(this,g_token->chars));
       
  5526           }
       
  5527         }
       
  5528         break;
       
  5529       case TK_LISTITEM:
       
  5530         {
       
  5531           DBG(("found list item at %d parent=%d\n",g_token->indent,parent()->kind()));
       
  5532           DocNode *n=parent();
       
  5533           while (n && n->kind()!=DocNode::Kind_AutoList) n=n->parent();
       
  5534           if (n) // we found an auto list up in the hierarchy
       
  5535           {
       
  5536             DocAutoList *al = (DocAutoList *)n;
       
  5537             DBG(("previous list item at %d\n",al->indent()));
       
  5538             if (al->indent()>=g_token->indent) 
       
  5539               // new item at the same or lower indent level
       
  5540             {
       
  5541               retval=TK_LISTITEM;
       
  5542               goto endparagraph;
       
  5543             }
       
  5544           }
       
  5545 
       
  5546           // determine list depth
       
  5547           int depth = 0;
       
  5548           n=parent();
       
  5549           while(n) 
       
  5550           {
       
  5551             if(n->kind() == DocNode::Kind_AutoList) ++depth;
       
  5552             n=n->parent();
       
  5553           }
       
  5554 
       
  5555           // first item or sub list => create new list
       
  5556           DocAutoList *al=0;
       
  5557           do
       
  5558           {
       
  5559             al = new DocAutoList(this,g_token->indent,g_token->isEnumList,
       
  5560                 depth);
       
  5561             m_children.append(al);
       
  5562             retval = al->parse();
       
  5563           } while (retval==TK_LISTITEM &&         // new list
       
  5564               al->indent()==g_token->indent  // at same indent level
       
  5565               );
       
  5566 
       
  5567           // check the return value
       
  5568           if (retval==RetVal_SimpleSec) // auto list ended due to simple section command
       
  5569           {
       
  5570             // Reparse the token that ended the section at this level,
       
  5571             // so a new simple section will be started at this level.
       
  5572             // This is the same as unputting the last read token and continuing.
       
  5573             g_token->name = g_token->simpleSectName;
       
  5574             if (g_token->name.left(4)=="rcs:") // RCS section
       
  5575             {
       
  5576               g_token->name = g_token->name.mid(4);
       
  5577               g_token->text = g_token->simpleSectText;
       
  5578               tok = TK_RCSTAG;
       
  5579             }
       
  5580             else // other section
       
  5581             {
       
  5582               tok = TK_COMMAND;
       
  5583             }
       
  5584             DBG(("reparsing command %s\n",g_token->name.data()));
       
  5585             goto reparsetoken;
       
  5586           }
       
  5587           else if (retval==TK_ENDLIST)
       
  5588           {
       
  5589             if (al->indent()>g_token->indent) // end list
       
  5590             {
       
  5591               goto endparagraph;
       
  5592             }
       
  5593             else // continue with current paragraph
       
  5594             {
       
  5595             }
       
  5596           }
       
  5597           else // paragraph ended due to TK_NEWPARA, TK_LISTITEM, or EOF
       
  5598           {
       
  5599             goto endparagraph;
       
  5600           }
       
  5601         }
       
  5602         break;
       
  5603       case TK_ENDLIST:     
       
  5604         DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno));
       
  5605         if (parent()->kind()==DocNode::Kind_AutoListItem)
       
  5606         {
       
  5607           ASSERT(parent()->parent()->kind()==DocNode::Kind_AutoList);
       
  5608           DocAutoList *al = (DocAutoList *)parent()->parent();
       
  5609           if (al->indent()>=g_token->indent)
       
  5610           {
       
  5611             // end of list marker ends this paragraph
       
  5612             retval=TK_ENDLIST;
       
  5613             goto endparagraph;
       
  5614           }
       
  5615           else
       
  5616           {
       
  5617             warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: End of list marker found "
       
  5618                 "has invalid indent level");
       
  5619           }
       
  5620         }
       
  5621         else
       
  5622         {
       
  5623           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: End of list marker found without any preceding "
       
  5624               "list items");
       
  5625         }
       
  5626         break;
       
  5627       case TK_COMMAND:    
       
  5628         {
       
  5629           // see if we have to start a simple section
       
  5630           int cmd = Mappers::cmdMapper->map(g_token->name);
       
  5631           DocNode *n=parent();
       
  5632           while (n && 
       
  5633               n->kind()!=DocNode::Kind_SimpleSect && 
       
  5634               n->kind()!=DocNode::Kind_ParamSect
       
  5635               ) 
       
  5636           {
       
  5637             n=n->parent();
       
  5638           }
       
  5639           if (cmd&SIMPLESECT_BIT)
       
  5640           {
       
  5641             if (n)  // already in a simple section
       
  5642             {
       
  5643               // simple section cannot start in this paragraph, need
       
  5644               // to unwind the stack and remember the command.
       
  5645               g_token->simpleSectName = g_token->name.copy();
       
  5646               retval=RetVal_SimpleSec;
       
  5647               goto endparagraph;
       
  5648             }
       
  5649           }
       
  5650           // see if we are in a simple list
       
  5651           n=parent();
       
  5652           while (n && n->kind()!=DocNode::Kind_SimpleListItem) n=n->parent();
       
  5653           if (n)
       
  5654           {
       
  5655             if (cmd==CMD_LI)
       
  5656             {
       
  5657               retval=RetVal_ListItem;
       
  5658               goto endparagraph;
       
  5659             }
       
  5660           }
       
  5661 
       
  5662           // handle the command
       
  5663           retval=handleCommand(g_token->name.copy());
       
  5664           DBG(("handleCommand returns %x\n",retval));
       
  5665 
       
  5666           // check the return value
       
  5667           if (retval==RetVal_SimpleSec)
       
  5668           {
       
  5669             // Reparse the token that ended the section at this level,
       
  5670             // so a new simple section will be started at this level.
       
  5671             // This is the same as unputting the last read token and continuing.
       
  5672             g_token->name = g_token->simpleSectName;
       
  5673             if (g_token->name.left(4)=="rcs:") // RCS section
       
  5674             {
       
  5675               g_token->name = g_token->name.mid(4);
       
  5676               g_token->text = g_token->simpleSectText;
       
  5677               tok = TK_RCSTAG;
       
  5678             }
       
  5679             else // other section
       
  5680             {
       
  5681               tok = TK_COMMAND;
       
  5682             }
       
  5683             DBG(("reparsing command %s\n",g_token->name.data()));
       
  5684             goto reparsetoken;
       
  5685           }
       
  5686           else if (retval==RetVal_OK) 
       
  5687           {
       
  5688             // the command ended normally, keep scanning for new tokens.
       
  5689             retval = 0;
       
  5690           }
       
  5691           else if (retval>0 && retval<RetVal_OK)
       
  5692           { 
       
  5693             // the command ended with a new command, reparse this token
       
  5694             tok = retval;
       
  5695             goto reparsetoken;
       
  5696           }
       
  5697           else // end of file, end of paragraph, start or end of section 
       
  5698             // or some auto list marker
       
  5699           {
       
  5700             goto endparagraph;
       
  5701           }
       
  5702         }
       
  5703         break;
       
  5704       case TK_HTMLTAG:    
       
  5705         {
       
  5706           if (!g_token->endTag) // found a start tag
       
  5707           {
       
  5708             retval = handleHtmlStartTag(g_token->name,g_token->attribs);
       
  5709           }
       
  5710           else // found an end tag
       
  5711           {
       
  5712             retval = handleHtmlEndTag(g_token->name);
       
  5713           }
       
  5714           if (retval==RetVal_OK) 
       
  5715           {
       
  5716             // the command ended normally, keep scanner for new tokens.
       
  5717             retval = 0;
       
  5718           }
       
  5719           else
       
  5720           {
       
  5721             goto endparagraph;
       
  5722           }
       
  5723         }
       
  5724         break;
       
  5725       case TK_SYMBOL:     
       
  5726         {
       
  5727           char letter='\0';
       
  5728           DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name,&letter);
       
  5729           if (s!=DocSymbol::Unknown)
       
  5730           {
       
  5731             m_children.append(new DocSymbol(this,s,letter));
       
  5732           }
       
  5733           else
       
  5734           {
       
  5735             warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  5736                 g_token->name.data());
       
  5737           }
       
  5738           break;
       
  5739         }
       
  5740       case TK_NEWPARA:     
       
  5741         retval=TK_NEWPARA;
       
  5742         goto endparagraph;
       
  5743       case TK_RCSTAG:
       
  5744         {
       
  5745           DocNode *n=parent();
       
  5746           while (n && 
       
  5747               n->kind()!=DocNode::Kind_SimpleSect && 
       
  5748               n->kind()!=DocNode::Kind_ParamSect
       
  5749               ) 
       
  5750           {
       
  5751             n=n->parent();
       
  5752           }
       
  5753           if (n)  // already in a simple section
       
  5754           {
       
  5755             // simple section cannot start in this paragraph, need
       
  5756             // to unwind the stack and remember the command.
       
  5757             g_token->simpleSectName = "rcs:"+g_token->name;
       
  5758             g_token->simpleSectText = g_token->text;
       
  5759             retval=RetVal_SimpleSec;
       
  5760             goto endparagraph;
       
  5761           }
       
  5762 
       
  5763           // see if we are in a simple list
       
  5764           DocSimpleSect *ss=new DocSimpleSect(this,DocSimpleSect::Rcs);
       
  5765           m_children.append(ss);
       
  5766           ss->parseRcs();
       
  5767         }
       
  5768         break;
       
  5769       default:
       
  5770         warn_doc_error(g_fileName,doctokenizerYYlineno,
       
  5771             "Warning: Found unexpected token (id=%x)\n",tok);
       
  5772         break;
       
  5773     }
       
  5774   }
       
  5775   retval=0;
       
  5776 endparagraph:
       
  5777   handlePendingStyleCommands(this,m_children);
       
  5778   DocNode *n = g_nodeStack.pop();
       
  5779   ASSERT(n==this);
       
  5780   DBG(("DocPara::parse() end retval=%x\n",retval));
       
  5781   INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM || 
       
  5782          retval==TK_ENDLIST || retval>RetVal_OK 
       
  5783 	);
       
  5784 
       
  5785   return retval; 
       
  5786 }
       
  5787 
       
  5788 //--------------------------------------------------------------------------
       
  5789 
       
  5790 int DocSection::parse()
       
  5791 {
       
  5792   DBG(("DocSection::parse() start %s level=%d\n",g_token->sectionId.data(),m_level));
       
  5793   int retval=RetVal_OK;
       
  5794   g_nodeStack.push(this);
       
  5795 
       
  5796   SectionInfo *sec;
       
  5797   if (!m_id.isEmpty())
       
  5798   {
       
  5799     sec=Doxygen::sectionDict[m_id];
       
  5800     if (sec)
       
  5801     {
       
  5802       m_file   = sec->fileName;
       
  5803       m_anchor = sec->label;
       
  5804       m_title  = sec->title;
       
  5805       if (m_title.isEmpty()) m_title = sec->label;
       
  5806       if (g_sectionDict && g_sectionDict->find(m_id)==0)
       
  5807       {
       
  5808         g_sectionDict->insert(m_id,sec);
       
  5809       }
       
  5810     }
       
  5811   }
       
  5812 
       
  5813   // first parse any number of paragraphs
       
  5814   bool isFirst=TRUE;
       
  5815   DocPara *lastPar=0;
       
  5816   do
       
  5817   {
       
  5818     DocPara *par = new DocPara(this);
       
  5819     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  5820     retval=par->parse();
       
  5821     if (!par->isEmpty()) 
       
  5822     {
       
  5823       m_children.append(par);
       
  5824       lastPar=par;
       
  5825     }
       
  5826     else
       
  5827     {
       
  5828       delete par;
       
  5829     }
       
  5830     if (retval==TK_LISTITEM)
       
  5831     {
       
  5832       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid list item found");
       
  5833     }
       
  5834   } while (retval!=0 && 
       
  5835            retval!=RetVal_Internal      &&
       
  5836            retval!=RetVal_Section       &&
       
  5837            retval!=RetVal_Subsection    &&
       
  5838            retval!=RetVal_Subsubsection &&
       
  5839            retval!=RetVal_Paragraph    
       
  5840           );
       
  5841 
       
  5842   if (lastPar) lastPar->markLast();
       
  5843 
       
  5844   //printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel);
       
  5845 
       
  5846   if (retval==RetVal_Subsection && m_level==Doxygen::subpageNestingLevel+1)
       
  5847   {
       
  5848     // then parse any number of nested sections
       
  5849     while (retval==RetVal_Subsection) // more sections follow
       
  5850     {
       
  5851       //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
       
  5852       DocSection *s=new DocSection(this,
       
  5853           QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId);
       
  5854       m_children.append(s);
       
  5855       retval = s->parse();
       
  5856     }
       
  5857   }
       
  5858   else if (retval==RetVal_Subsubsection && m_level==Doxygen::subpageNestingLevel+2)
       
  5859   {
       
  5860     // then parse any number of nested sections
       
  5861     while (retval==RetVal_Subsubsection) // more sections follow
       
  5862     {
       
  5863       //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
       
  5864       DocSection *s=new DocSection(this,
       
  5865           QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId);
       
  5866       m_children.append(s);
       
  5867       retval = s->parse();
       
  5868     }
       
  5869   }
       
  5870   else if (retval==RetVal_Paragraph && m_level==QMIN(5,Doxygen::subpageNestingLevel+3))
       
  5871   {
       
  5872     // then parse any number of nested sections
       
  5873     while (retval==RetVal_Paragraph) // more sections follow
       
  5874     {
       
  5875       //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
       
  5876       DocSection *s=new DocSection(this,
       
  5877           QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId);
       
  5878       m_children.append(s);
       
  5879       retval = s->parse();
       
  5880     }
       
  5881   }
       
  5882   else if ((m_level<=1+Doxygen::subpageNestingLevel && retval==RetVal_Subsubsection) ||
       
  5883            (m_level<=2+Doxygen::subpageNestingLevel && retval==RetVal_Paragraph)
       
  5884           ) 
       
  5885   {
       
  5886     int level; 
       
  5887     if (retval==RetVal_Subsection) level=2; 
       
  5888     else if (retval==RetVal_Subsubsection) level=3;
       
  5889     else level=4;
       
  5890     warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected %s "
       
  5891             "command found inside %s!",
       
  5892             sectionLevelToName[level],sectionLevelToName[m_level]);
       
  5893     retval=0; // stop parsing
       
  5894             
       
  5895   }
       
  5896   else if (retval==RetVal_Internal)
       
  5897   {
       
  5898     DocInternal *in = new DocInternal(this);
       
  5899     m_children.append(in);
       
  5900     retval = in->parse(m_level+1);
       
  5901   }
       
  5902   else
       
  5903   {
       
  5904   }
       
  5905 
       
  5906   INTERNAL_ASSERT(retval==0 || 
       
  5907                   retval==RetVal_Section || 
       
  5908                   retval==RetVal_Subsection || 
       
  5909                   retval==RetVal_Subsubsection || 
       
  5910                   retval==RetVal_Paragraph || 
       
  5911                   retval==RetVal_Internal
       
  5912                  );
       
  5913 
       
  5914   DBG(("DocSection::parse() end\n"));
       
  5915   DocNode *n = g_nodeStack.pop();
       
  5916   ASSERT(n==this);
       
  5917   return retval;
       
  5918 }
       
  5919 
       
  5920 //--------------------------------------------------------------------------
       
  5921 
       
  5922 void DocText::parse()
       
  5923 {
       
  5924   DBG(("DocText::parse() start\n"));
       
  5925   g_nodeStack.push(this);
       
  5926   doctokenizerYYsetStateText();
       
  5927   
       
  5928   int tok;
       
  5929   while ((tok=doctokenizerYYlex())) // get the next token
       
  5930   {
       
  5931     switch(tok)
       
  5932     {
       
  5933       case TK_WORD:        
       
  5934 	m_children.append(new DocWord(this,g_token->name));
       
  5935 	break;
       
  5936       case TK_WHITESPACE:  
       
  5937         m_children.append(new DocWhiteSpace(this,g_token->chars));
       
  5938 	break;
       
  5939       case TK_SYMBOL:     
       
  5940         {
       
  5941           char letter='\0';
       
  5942           DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name,&letter);
       
  5943           if (s!=DocSymbol::Unknown)
       
  5944           {
       
  5945             m_children.append(new DocSymbol(this,s,letter));
       
  5946           }
       
  5947           else
       
  5948           {
       
  5949             warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
       
  5950                 g_token->name.data());
       
  5951           }
       
  5952         }
       
  5953         break;
       
  5954       case TK_COMMAND: 
       
  5955         switch (Mappers::cmdMapper->map(g_token->name))
       
  5956         {
       
  5957           case CMD_BSLASH:
       
  5958             m_children.append(new DocSymbol(this,DocSymbol::BSlash));
       
  5959             break;
       
  5960           case CMD_AT:
       
  5961             m_children.append(new DocSymbol(this,DocSymbol::At));
       
  5962             break;
       
  5963           case CMD_LESS:
       
  5964             m_children.append(new DocSymbol(this,DocSymbol::Less));
       
  5965             break;
       
  5966           case CMD_GREATER:
       
  5967             m_children.append(new DocSymbol(this,DocSymbol::Greater));
       
  5968             break;
       
  5969           case CMD_AMP:
       
  5970             m_children.append(new DocSymbol(this,DocSymbol::Amp));
       
  5971             break;
       
  5972           case CMD_DOLLAR:
       
  5973             m_children.append(new DocSymbol(this,DocSymbol::Dollar));
       
  5974             break;
       
  5975           case CMD_HASH:
       
  5976             m_children.append(new DocSymbol(this,DocSymbol::Hash));
       
  5977             break;
       
  5978           case CMD_PERCENT:
       
  5979             m_children.append(new DocSymbol(this,DocSymbol::Percent));
       
  5980             break;
       
  5981           case CMD_QUOTE:
       
  5982             m_children.append(new DocSymbol(this,DocSymbol::Quot));
       
  5983             break;
       
  5984           default:
       
  5985             warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected command `%s' found",
       
  5986                       g_token->name.data());
       
  5987             break;
       
  5988         }
       
  5989         break;
       
  5990       default:
       
  5991         warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s",
       
  5992             tokToString(tok));
       
  5993         break;
       
  5994     }
       
  5995   }
       
  5996 
       
  5997   handleUnclosedStyleCommands();
       
  5998 
       
  5999   DocNode *n = g_nodeStack.pop();
       
  6000   ASSERT(n==this);
       
  6001   DBG(("DocText::parse() end\n"));
       
  6002 }
       
  6003 
       
  6004 
       
  6005 //--------------------------------------------------------------------------
       
  6006 
       
  6007 void DocRoot::parse()
       
  6008 {
       
  6009   DBG(("DocRoot::parse() start\n"));
       
  6010   g_nodeStack.push(this);
       
  6011   doctokenizerYYsetStatePara();
       
  6012   int retval=0;
       
  6013 
       
  6014   // first parse any number of paragraphs
       
  6015   bool isFirst=TRUE;
       
  6016   DocPara *lastPar=0;
       
  6017   do
       
  6018   {
       
  6019     DocPara *par = new DocPara(this);
       
  6020     if (isFirst) { par->markFirst(); isFirst=FALSE; }
       
  6021     retval=par->parse();
       
  6022     if (!par->isEmpty()) 
       
  6023     {
       
  6024       m_children.append(par);
       
  6025       lastPar=par;
       
  6026     }
       
  6027     else
       
  6028     {
       
  6029       delete par;
       
  6030     }
       
  6031     if (retval==TK_LISTITEM)
       
  6032     {
       
  6033       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid list item found");
       
  6034     }
       
  6035     else if (retval==RetVal_Subsection)
       
  6036     {
       
  6037       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found subsection command outside of section context!");
       
  6038     }
       
  6039     else if (retval==RetVal_Subsubsection)
       
  6040     {
       
  6041       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found subsubsection command outside of subsection context!");
       
  6042     }
       
  6043     else if (retval==RetVal_Paragraph)
       
  6044     {
       
  6045       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found paragraph command outside of subsubsection context!");
       
  6046     }
       
  6047   } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Internal);
       
  6048   if (lastPar) lastPar->markLast();
       
  6049 
       
  6050   //printf("DocRoot::parse() retval=%d %d\n",retval,RetVal_Section);
       
  6051   // then parse any number of level1 sections
       
  6052   while (retval==RetVal_Section)
       
  6053   {
       
  6054     SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
       
  6055     if (sec)
       
  6056     {
       
  6057       DocSection *s=new DocSection(this,
       
  6058           QMIN(1+Doxygen::subpageNestingLevel,5),g_token->sectionId);
       
  6059       m_children.append(s);
       
  6060       retval = s->parse();
       
  6061     }
       
  6062     else
       
  6063     {
       
  6064       warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid section id `%s'; ignoring section",g_token->sectionId.data());
       
  6065       retval = 0;
       
  6066     }
       
  6067   }
       
  6068 
       
  6069   if (retval==RetVal_Internal)
       
  6070   {
       
  6071     DocInternal *in = new DocInternal(this);
       
  6072     m_children.append(in);
       
  6073     retval = in->parse(1);
       
  6074   }
       
  6075 
       
  6076 
       
  6077   handleUnclosedStyleCommands();
       
  6078 
       
  6079   DocNode *n = g_nodeStack.pop();
       
  6080   ASSERT(n==this);
       
  6081   DBG(("DocRoot::parse() end\n"));
       
  6082 }
       
  6083 
       
  6084 //--------------------------------------------------------------------------
       
  6085 
       
  6086 DocNode *validatingParseDoc(const char *fileName,int startLine,
       
  6087                             Definition *ctx,MemberDef *md,
       
  6088                             const char *input,bool indexWords,
       
  6089                             bool isExample, const char *exampleName,
       
  6090                             bool singleLine, bool linkFromIndex)
       
  6091 {
       
  6092   //printf("validatingParseDoc(%s,%s)=[%s]\n",ctx?ctx->name().data():"<none>",
       
  6093   //                                     md?md->name().data():"<none>",
       
  6094   //                                     input);
       
  6095   //printf("========== validating %s at line %d\n",fileName,startLine);
       
  6096   //printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",input);
       
  6097   //g_token = new TokenInfo;
       
  6098 
       
  6099   // store parser state so we can re-enter this function if needed
       
  6100   bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
       
  6101   docParserPushContext();
       
  6102 
       
  6103   if (ctx &&
       
  6104       (ctx->definitionType()==Definition::TypeClass || 
       
  6105        ctx->definitionType()==Definition::TypeNamespace
       
  6106       )
       
  6107      ) 
       
  6108   {
       
  6109     g_context = ctx->name();
       
  6110   }
       
  6111   else if (ctx && ctx->definitionType()==Definition::TypePage)
       
  6112   {
       
  6113     Definition *scope = ((PageDef*)ctx)->getPageScope();
       
  6114     if (scope) g_context = scope->name();
       
  6115   }
       
  6116   else if (ctx && ctx->definitionType()==Definition::TypeGroup)
       
  6117   {
       
  6118     Definition *scope = ((GroupDef*)ctx)->getGroupScope();
       
  6119     if (scope) g_context = scope->name();
       
  6120   }
       
  6121   else
       
  6122   {
       
  6123     g_context = "";
       
  6124   }
       
  6125   g_scope = ctx;
       
  6126   //printf("g_context=%s\n",g_context.data());
       
  6127 
       
  6128   if (indexWords && md && Doxygen::searchIndex)
       
  6129   {
       
  6130     g_searchUrl=md->getOutputFileBase();
       
  6131     Doxygen::searchIndex->setCurrentDoc(
       
  6132         (fortranOpt?theTranslator->trSubprogram(TRUE,TRUE):theTranslator->trMember(TRUE,TRUE))+" "+md->qualifiedName(),
       
  6133         g_searchUrl,
       
  6134         md->anchor());
       
  6135   }
       
  6136   else if (indexWords && ctx && Doxygen::searchIndex)
       
  6137   {
       
  6138     g_searchUrl=ctx->getOutputFileBase();
       
  6139     QCString name = ctx->qualifiedName();
       
  6140     if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
       
  6141     {
       
  6142       name = substitute(name,"::",".");
       
  6143     }
       
  6144     switch (ctx->definitionType())
       
  6145     {
       
  6146       case Definition::TypePage:
       
  6147         {
       
  6148           PageDef *pd = (PageDef *)ctx;
       
  6149           if (!pd->title().isEmpty())
       
  6150           {
       
  6151             name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title();
       
  6152           }
       
  6153           else
       
  6154           {
       
  6155             name = theTranslator->trPage(TRUE,TRUE)+" "+pd->name();
       
  6156           }
       
  6157         }
       
  6158         break;
       
  6159       case Definition::TypeClass:
       
  6160         {
       
  6161           ClassDef *cd = (ClassDef *)ctx;
       
  6162           name.prepend(cd->compoundTypeString()+" ");
       
  6163         }
       
  6164         break;
       
  6165       case Definition::TypeNamespace:
       
  6166         {
       
  6167           if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
       
  6168           {
       
  6169             name = theTranslator->trPackage(name);
       
  6170           }
       
  6171           else if(fortranOpt)
       
  6172           {
       
  6173             name.prepend(theTranslator->trModule(TRUE,TRUE)+" ");
       
  6174           }
       
  6175             else
       
  6176           {
       
  6177             name.prepend(theTranslator->trNamespace(TRUE,TRUE)+" ");
       
  6178           }
       
  6179         }
       
  6180         break;
       
  6181       case Definition::TypeGroup:
       
  6182         {
       
  6183           GroupDef *gd = (GroupDef *)ctx;
       
  6184           if (gd->groupTitle())
       
  6185           {
       
  6186             name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle();
       
  6187           }
       
  6188           else
       
  6189           {
       
  6190             name.prepend(theTranslator->trGroup(TRUE,TRUE)+" ");
       
  6191           }
       
  6192         }
       
  6193         break;
       
  6194       default:
       
  6195         break;
       
  6196     }
       
  6197     Doxygen::searchIndex->setCurrentDoc(name,g_searchUrl);
       
  6198   }
       
  6199   else
       
  6200   {
       
  6201     g_searchUrl="";
       
  6202   }
       
  6203 
       
  6204   g_fileName = fileName;
       
  6205   g_relPath = (!linkFromIndex && ctx) ? 
       
  6206                QString(relativePathToRoot(ctx->getOutputFileBase())) : 
       
  6207                QString("");
       
  6208   //printf("ctx->name=%s relPath=%s\n",ctx->name().data(),g_relPath.data());
       
  6209   g_memberDef = md;
       
  6210   g_nodeStack.clear();
       
  6211   g_styleStack.clear();
       
  6212   g_initialStyleStack.clear();
       
  6213   g_inSeeBlock = FALSE;
       
  6214   g_insideHtmlLink = FALSE;
       
  6215   g_includeFileText = "";
       
  6216   g_includeFileOffset = 0;
       
  6217   g_includeFileLength = 0;
       
  6218   g_isExample = isExample;
       
  6219   g_exampleName = exampleName;
       
  6220   g_hasParamCommand = FALSE;
       
  6221   g_hasReturnCommand = FALSE;
       
  6222   g_paramsFound.setAutoDelete(FALSE);
       
  6223   g_paramsFound.clear();
       
  6224   g_sectionDict = 0; //sections;
       
  6225   
       
  6226   //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine);
       
  6227   doctokenizerYYlineno=startLine;
       
  6228   doctokenizerYYinit(input,g_fileName);
       
  6229 
       
  6230 
       
  6231   // build abstract syntax tree
       
  6232   DocRoot *root = new DocRoot(md!=0,singleLine);
       
  6233   root->parse();
       
  6234 
       
  6235 
       
  6236   if (Debug::isFlagSet(Debug::PrintTree))
       
  6237   {
       
  6238     // pretty print the result
       
  6239     PrintDocVisitor *v = new PrintDocVisitor;
       
  6240     root->accept(v);
       
  6241     delete v;
       
  6242   }
       
  6243 
       
  6244 
       
  6245   checkUndocumentedParams();
       
  6246   detectNoDocumentedParams();
       
  6247 
       
  6248   // TODO: These should be called at the end of the program.
       
  6249   //doctokenizerYYcleanup();
       
  6250   //Mappers::cmdMapper->freeInstance();
       
  6251   //Mappers::htmlTagMapper->freeInstance();
       
  6252 
       
  6253   // restore original parser state
       
  6254   docParserPopContext();
       
  6255 
       
  6256   //printf(">>>>>> end validatingParseDoc(%s,%s)\n",ctx?ctx->name().data():"<none>",
       
  6257   //                                     md?md->name().data():"<none>");
       
  6258   
       
  6259   return root;
       
  6260 }
       
  6261 
       
  6262 DocNode *validatingParseText(const char *input)
       
  6263 {
       
  6264   // store parser state so we can re-enter this function if needed
       
  6265   docParserPushContext();
       
  6266 
       
  6267   //printf("------------ input ---------\n%s\n"
       
  6268   //       "------------ end input -----\n",input);
       
  6269   //g_token = new TokenInfo;
       
  6270   g_context = "";
       
  6271   g_fileName = "<parseText>";
       
  6272   g_relPath = "";
       
  6273   g_memberDef = 0;
       
  6274   g_nodeStack.clear();
       
  6275   g_styleStack.clear();
       
  6276   g_initialStyleStack.clear();
       
  6277   g_inSeeBlock = FALSE;
       
  6278   g_insideHtmlLink = FALSE;
       
  6279   g_includeFileText = "";
       
  6280   g_includeFileOffset = 0;
       
  6281   g_includeFileLength = 0;
       
  6282   g_isExample = FALSE;
       
  6283   g_exampleName = "";
       
  6284   g_hasParamCommand = FALSE;
       
  6285   g_hasReturnCommand = FALSE;
       
  6286   g_paramsFound.setAutoDelete(FALSE);
       
  6287   g_paramsFound.clear();
       
  6288   g_searchUrl="";
       
  6289 
       
  6290   DocText *txt = new DocText;
       
  6291 
       
  6292   if (input)
       
  6293   {
       
  6294     doctokenizerYYlineno=1;
       
  6295     doctokenizerYYinit(input,g_fileName);
       
  6296 
       
  6297     // build abstract syntax tree
       
  6298     txt->parse();
       
  6299 
       
  6300     if (Debug::isFlagSet(Debug::PrintTree))
       
  6301     {
       
  6302       // pretty print the result
       
  6303       PrintDocVisitor *v = new PrintDocVisitor;
       
  6304       txt->accept(v);
       
  6305       delete v;
       
  6306     }
       
  6307   }
       
  6308 
       
  6309   // restore original parser state
       
  6310   docParserPopContext();
       
  6311   return txt;
       
  6312 }
       
  6313 
       
  6314 void docFindSections(const char *input,
       
  6315                      Definition *d,
       
  6316                      MemberGroup *mg,
       
  6317                      const char *fileName)
       
  6318 {
       
  6319   doctokenizerYYFindSections(input,d,mg,fileName);
       
  6320 }
       
  6321 
       
  6322 void initDocParser()
       
  6323 {
       
  6324   static bool searchEngine = Config_getBool("SEARCHENGINE");
       
  6325   static bool serverBasedSearch = Config_getBool("SERVER_BASED_SEARCH");
       
  6326   if (searchEngine && serverBasedSearch)
       
  6327   {
       
  6328     Doxygen::searchIndex = new SearchIndex;
       
  6329   }
       
  6330   else // no search engine or pure javascript based search function
       
  6331   {
       
  6332     Doxygen::searchIndex = 0;
       
  6333   }
       
  6334 }
       
  6335 
       
  6336 void finializeDocParser()
       
  6337 {
       
  6338   delete Doxygen::searchIndex;
       
  6339 }
       
  6340