X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fdocparser.cpp;h=dcdd9ef2f484869de7f48ecd05a4408aa24c59bb;hb=14adf159fc9eb1212b2e61ea78e94c135abde0fe;hp=88c97f0f869fac967ba262ca3a0d6e8a2f895d8e;hpb=cfd886868fa8595b045007a2ad673c18c5f222b3;p=platform%2Fupstream%2Fdoxygen.git diff --git a/src/docparser.cpp b/src/docparser.cpp index 88c97f0..dcdd9ef 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -37,16 +37,16 @@ #include "printdocvisitor.h" #include "util.h" #include "indexlist.h" +#include "trace.h" -// debug off -#define DBG(x) do {} while(0) - -// debug to stdout -//#define DBG(x) printf x - -// debug to stderr -//#define myprintf(...) fprintf(stderr,__VA_ARGS__) -//#define DBG(x) myprintf x +#if !ENABLE_DOCPARSER_TRACING +#undef AUTO_TRACE +#undef AUTO_TRACE_ADD +#undef AUTO_TRACE_EXIT +#define AUTO_TRACE(...) (void)0 +#define AUTO_TRACE_ADD(...) (void)0 +#define AUTO_TRACE_EXIT(...) (void)0 +#endif //--------------------------------------------------------------------------- @@ -59,14 +59,6 @@ IDocParserPtr createDocParser() //--------------------------------------------------------------------------- DocParser::~DocParser() { - try - { - searchData.transfer(); - } - catch(...) - { - err("Unexpected exception caught in DocParser\n"); - } } void DocParser::pushContext() @@ -80,7 +72,7 @@ void DocParser::pushContext() auto &ctx = contextStack.top(); ctx = context; ctx.lineNo = tokenizer.getLineNr(); - context.token = tokenizer.newToken(); + context.token = tokenizer.token(); } void DocParser::popContext() @@ -88,10 +80,9 @@ void DocParser::popContext() auto &ctx = contextStack.top(); context = ctx; tokenizer.setLineNr(ctx.lineNo); - context.token = ctx.token; - tokenizer.replaceToken(context.token); contextStack.pop(); tokenizer.popContext(); + context.token = tokenizer.token(); //QCString indent; //indent.fill(' ',contextStack.size()*2+2); @@ -189,12 +180,10 @@ QCString DocParser::findAndCopyImage(const QCString &fileName, DocImage::Type ty epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"", qPrint(outputDir), qPrint(baseName), qPrint(outputDir), qPrint(baseName)); - Portable::sysTimerStart(); if (Portable::system("epstopdf",epstopdfArgs)!=0) { err("Problems running epstopdf. Check your TeX installation!\n"); } - Portable::sysTimerStop(); return baseName; } } @@ -373,7 +362,7 @@ void DocParser::checkUnOrMultipleDocumentedParams() } else { - if (!context.paramsFound.size() && Config_getBool(WARN_IF_DOC_ERROR)) + if (context.paramsFound.empty() && Config_getBool(WARN_IF_DOC_ERROR)) { warn_doc_error(context.memberDef->docFile(), context.memberDef->docLine(), @@ -483,24 +472,21 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName, QCString name=removeRedundantWhiteSpace(cmdArg.left(funcStart)); QCString args=cmdArg.right(l-funcStart); // try if the link is to a member - const MemberDef *md=0; - const ClassDef *cd=0; - const NamespaceDef *nd=0; - bool found = getDefs( - context.context.find('.')==-1?context.context:QCString(), // find('.') is a hack to detect files + GetDefInput input( + context.context.find('.')==-1 ? context.context : QCString(), // find('.') is a hack to detect files name, - args.isEmpty() ? QCString() : args, - md,cd,fd,nd,gd,FALSE,0,TRUE); + args.isEmpty() ? QCString() : args); + input.checkCV=true; + GetDefResult result = getDefs(input); //printf("found=%d context=%s name=%s\n",found,qPrint(context.context),qPrint(name)); - if (found && md) + if (result.found && result.md) { - *pDoc=md->documentation(); - *pBrief=md->briefDescription(); - *pDef=md; + *pDoc=result.md->documentation(); + *pBrief=result.md->briefDescription(); + *pDef=result.md; return TRUE; } - int scopeOffset=static_cast(context.context.length()); do // for each scope { @@ -512,7 +498,7 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName, //printf("Trying fullName='%s'\n",qPrint(fullName)); // try class, namespace, group, page, file reference - cd = Doxygen::classLinkedMap->find(fullName); + const ClassDef *cd = Doxygen::classLinkedMap->find(fullName); if (cd) // class { *pDoc=cd->documentation(); @@ -520,7 +506,7 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName, *pDef=cd; return TRUE; } - nd = Doxygen::namespaceLinkedMap->find(fullName); + const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(fullName); if (nd) // namespace { *pDoc=nd->documentation(); @@ -562,6 +548,10 @@ void DocParser::errorHandleDefaultToken(DocNodeVariant *parent,int tok, warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported symbol %s found as part of a %s", qPrint(context.token->name), qPrint(txt)); break; + case TK_HTMLTAG: + warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported HTML tag <%s%s> found as part of a %s", + context.token->endTag ? "/" : "",qPrint(context.token->name), qPrint(txt)); + break; default: children.append(this,parent,context.token->name); warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unexpected token %s found as part of a %s", @@ -574,7 +564,7 @@ void DocParser::errorHandleDefaultToken(DocNodeVariant *parent,int tok, int DocParser::handleStyleArgument(DocNodeVariant *parent,DocNodeList &children,const QCString &cmdName) { - DBG(("handleStyleArgument(%s)\n",qPrint(cmdName))); + AUTO_TRACE("cmdName={}",cmdName); QCString saveCmdName = cmdName; int tok=tokenizer.lex(); if (tok!=TK_WHITESPACE) @@ -606,7 +596,7 @@ int DocParser::handleStyleArgument(DocNodeVariant *parent,DocNodeList &children, { // ignore as the end of a style command continue; } - DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok))); + AUTO_TRACE_EXIT("end tok={}",DocTokenizer::tokToString(tok)); return tok; break; default: @@ -616,7 +606,7 @@ int DocParser::handleStyleArgument(DocNodeVariant *parent,DocNodeList &children, break; } } - DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok))); + AUTO_TRACE_EXIT("end tok={}",DocTokenizer::tokToString(tok)); return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST ) ? tok : RetVal_OK; } @@ -627,7 +617,7 @@ int DocParser::handleStyleArgument(DocNodeVariant *parent,DocNodeList &children, void DocParser::handleStyleEnter(DocNodeVariant *parent,DocNodeList &children, DocStyleChange::Style s,const QCString &tagName,const HtmlAttribList *attribs) { - DBG(("HandleStyleEnter\n")); + AUTO_TRACE("tagName={}",tagName); children.append(this,parent,context.nodeStack.size(),s,tagName,TRUE,attribs); context.styleStack.push(&children.back()); } @@ -638,7 +628,7 @@ void DocParser::handleStyleEnter(DocNodeVariant *parent,DocNodeList &children, void DocParser::handleStyleLeave(DocNodeVariant *parent,DocNodeList &children, DocStyleChange::Style s,const QCString &tagName) { - DBG(("HandleStyleLeave\n")); + AUTO_TRACE("tagName={}",tagName); QCString tagNameLower = QCString(tagName).lower(); auto topStyleChange = [](const DocStyleChangeStack &stack) -> const DocStyleChange & @@ -688,6 +678,7 @@ void DocParser::handleStyleLeave(DocNodeVariant *parent,DocNodeList &children, */ void DocParser::handlePendingStyleCommands(DocNodeVariant *parent,DocNodeList &children) { + AUTO_TRACE(); if (!context.styleStack.empty()) { const DocStyleChange *sc = &std::get(*context.styleStack.top()); @@ -704,6 +695,7 @@ void DocParser::handlePendingStyleCommands(DocNodeVariant *parent,DocNodeList &c void DocParser::handleInitialStyleCommands(DocNodeVariant *parent,DocNodeList &children) { + AUTO_TRACE(); while (!context.initialStyleStack.empty()) { const DocStyleChange &sc = std::get(*context.initialStyleStack.top()); @@ -715,7 +707,8 @@ void DocParser::handleInitialStyleCommands(DocNodeVariant *parent,DocNodeList &c int DocParser::handleAHref(DocNodeVariant *parent,DocNodeList &children, const HtmlAttribList &tagHtmlAttribs) { - uint index=0; + AUTO_TRACE(); + uint32_t index=0; int retval = RetVal_OK; for (const auto &opt : tagHtmlAttribs) { @@ -739,12 +732,11 @@ int DocParser::handleAHref(DocNodeVariant *parent,DocNodeList &children, attrList.erase(attrList.begin()+index); QCString relPath; if (opt.value.at(0) != '#') relPath = context.relPath; - auto vDocHRef = children.append(this, parent, attrList, - opt.value, relPath, - convertNameToFile(context.fileName, FALSE, TRUE)); - DocHRef *href = children.get_last(); + children.append(this, parent, attrList, + opt.value, relPath, + convertNameToFile(context.fileName, FALSE, TRUE)); context.insideHtmlLink=TRUE; - retval = href->parse(vDocHRef); + retval = children.get_last()->parse(); context.insideHtmlLink=FALSE; break; } @@ -758,6 +750,7 @@ int DocParser::handleAHref(DocNodeVariant *parent,DocNodeList &children, void DocParser::handleUnclosedStyleCommands() { + AUTO_TRACE(); if (!context.initialStyleStack.empty()) { QCString tagName = std::get(*context.initialStyleStack.top()).tagName(); @@ -772,6 +765,7 @@ void DocParser::handleUnclosedStyleCommands() void DocParser::handleLinkedWord(DocNodeVariant *parent,DocNodeList &children,bool ignoreAutoLinkFlag) { QCString name = linkToText(SrcLangExt_Unknown,context.token->name,TRUE); + AUTO_TRACE("word={}",name); bool autolinkSupport = Config_getBool(AUTOLINK_SUPPORT); if (!autolinkSupport && !ignoreAutoLinkFlag) // no autolinking -> add as normal word { @@ -783,7 +777,7 @@ void DocParser::handleLinkedWord(DocNodeVariant *parent,DocNodeList &children,bo const Definition *compound=0; const MemberDef *member=0; - uint len = context.token->name.length(); + uint32_t len = context.token->name.length(); ClassDef *cd=0; bool ambig; FileDef *fd = findFileDef(Doxygen::inputNameLinkedMap,context.fileName,ambig); @@ -880,6 +874,7 @@ void DocParser::handleLinkedWord(DocNodeVariant *parent,DocNodeList &children,bo void DocParser::handleParameterType(DocNodeVariant *parent,DocNodeList &children,const QCString ¶mTypes) { QCString name = context.token->name; // save token name + AUTO_TRACE("name={}",name); QCString name1; int p=0,i,ii; while ((i=paramTypes.find('|',p))!=-1) @@ -902,9 +897,9 @@ void DocParser::handleParameterType(DocNodeVariant *parent,DocNodeList &children void DocParser::handleInternalRef(DocNodeVariant *parent,DocNodeList &children) { - //printf("CMD_INTERNALREF\n"); int tok=tokenizer.lex(); QCString tokenName = context.token->name; + AUTO_TRACE("name={}",tokenName); if (tok!=TK_WHITESPACE) { warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\%s command", @@ -919,12 +914,13 @@ void DocParser::handleInternalRef(DocNodeVariant *parent,DocNodeList &children) DocTokenizer::tokToString(tok),qPrint(tokenName)); return; } - auto vDocInternalRef = children.append(this,parent,context.token->name); - children.get_last()->parse(vDocInternalRef); + children.append(this,parent,context.token->name); + children.get_last()->parse(); } void DocParser::handleAnchor(DocNodeVariant *parent,DocNodeList &children) { + AUTO_TRACE(); int tok=tokenizer.lex(); if (tok!=TK_WHITESPACE) { @@ -962,6 +958,7 @@ void DocParser::handleAnchor(DocNodeVariant *parent,DocNodeList &children) */ void DocParser::defaultHandleTitleAndSize(const int cmd, DocNodeVariant *parent, DocNodeList &children, QCString &width,QCString &height) { + AUTO_TRACE(); auto ns = AutoNodeStack(this,parent); // parse title @@ -1032,10 +1029,12 @@ void DocParser::defaultHandleTitleAndSize(const int cmd, DocNodeVariant *parent, tokenizer.setStatePara(); handlePendingStyleCommands(parent,children); + AUTO_TRACE_EXIT("width={} height={}",width,height); } void DocParser::handleImage(DocNodeVariant *parent, DocNodeList &children) { + AUTO_TRACE(); bool inlineImage = false; QCString anchorStr; @@ -1047,7 +1046,7 @@ void DocParser::handleImage(DocNodeVariant *parent, DocNodeList &children) if (context.token->name == "{") { tokenizer.setStateOptions(); - tok=tokenizer.lex(); + tokenizer.lex(); tokenizer.setStatePara(); StringVector optList=split(context.token->name.str(),","); for (const auto &opt : optList) @@ -1136,9 +1135,9 @@ void DocParser::handleImage(DocNodeVariant *parent, DocNodeList &children) children.append(this,parent,anchorStr,true); } HtmlAttribList attrList; - auto vDocImage = children.append(this,parent,attrList, + children.append(this,parent,attrList, findAndCopyImage(context.token->name,t),t,"",inlineImage); - children.get_last()->parse(vDocImage); + children.get_last()->parse(); } @@ -1155,16 +1154,15 @@ void DocParser::handleImage(DocNodeVariant *parent, DocNodeList &children) */ bool DocParser::defaultHandleToken(DocNodeVariant *parent,int tok, DocNodeList &children,bool handleWord) { - DBG(("token %s at %d",DocTokenizer::tokToString(tok),tokenizer.getLineNr())); + AUTO_TRACE("token={} handleWord={}",DocTokenizer::tokToString(tok),handleWord); if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || tok==TK_COMMAND_AT || tok==TK_COMMAND_BS || tok==TK_HTMLTAG ) { - DBG((" name=%s",qPrint(context.token->name))); } - DBG(("\n")); reparsetoken: QCString tokenName = context.token->name; + AUTO_TRACE_ADD("tokenName={}",tokenName); switch (tok) { case TK_COMMAND_AT: @@ -1232,7 +1230,7 @@ reparsetoken: if (tok==TK_NEWPARA) goto handlepara; else if (tok==TK_WORD || tok==TK_HTMLTAG) { - DBG(("CMD_EMPHASIS: reparsing command %s\n",qPrint(context.token->name))); + AUTO_TRACE_ADD("CMD_EMPHASIS: reparsing"); goto reparsetoken; } } @@ -1246,7 +1244,7 @@ reparsetoken: if (tok==TK_NEWPARA) goto handlepara; else if (tok==TK_WORD || tok==TK_HTMLTAG) { - DBG(("CMD_BOLD: reparsing command %s\n",qPrint(context.token->name))); + AUTO_TRACE_ADD("CMD_BOLD: reparsing"); goto reparsetoken; } } @@ -1260,7 +1258,7 @@ reparsetoken: if (tok==TK_NEWPARA) goto handlepara; else if (tok==TK_WORD || tok==TK_HTMLTAG) { - DBG(("CMD_CODE: reparsing command %s\n",qPrint(context.token->name))); + AUTO_TRACE_ADD("CMD_CODE: reparsing"); goto reparsetoken; } } @@ -1325,6 +1323,7 @@ reparsetoken: } break; case CMD_ANCHOR: + case CMD_IANCHOR: { handleAnchor(parent,children); } @@ -1358,10 +1357,10 @@ reparsetoken: switch (Mappers::htmlTagMapper->map(tokenName)) { case HTML_DIV: - warn_doc_error(context.fileName,tokenizer.getLineNr(),"found
tag in heading\n"); + warn_doc_error(context.fileName,tokenizer.getLineNr(),"found
tag in heading"); break; case HTML_PRE: - warn_doc_error(context.fileName,tokenizer.getLineNr(),"found
 tag in heading\n");
+            warn_doc_error(context.fileName,tokenizer.getLineNr(),"found 
 tag in heading");
             break;
           case HTML_BOLD:
             if (!context.token->endTag)
@@ -1561,11 +1560,12 @@ handlepara:
 
 void DocParser::handleImg(DocNodeVariant *parent, DocNodeList &children,const HtmlAttribList &tagHtmlAttribs)
 {
+  AUTO_TRACE();
   bool found=FALSE;
-  uint index=0;
+  uint32_t index=0;
   for (const auto &opt : tagHtmlAttribs)
   {
-    //printf("option name=%s value=%s\n",qPrint(opt.name),qPrint(opt.value));
+    AUTO_TRACE_ADD("option name={} value='{}'",opt.name,opt.value);
     if (opt.name=="src" && !opt.value.isEmpty())
     {
       // copy attributes
@@ -1583,7 +1583,7 @@ void DocParser::handleImg(DocNodeVariant *parent, DocNodeList &children,const Ht
   }
   if (!found)
   {
-    warn_doc_error(context.fileName,tokenizer.getLineNr(),"IMG tag does not have a SRC attribute!\n");
+    warn_doc_error(context.fileName,tokenizer.getLineNr(),"IMG tag does not have a SRC attribute!");
   }
 }
 
@@ -1592,11 +1592,12 @@ void DocParser::handleImg(DocNodeVariant *parent, DocNodeList &children,const Ht
 int DocParser::internalValidatingParseDoc(DocNodeVariant *parent,DocNodeList &children,
                                     const QCString &doc)
 {
+  AUTO_TRACE();
   int retval = RetVal_OK;
 
   if (doc.isEmpty()) return retval;
 
-  tokenizer.init(doc.data(),context.fileName,context.markdownSupport);
+  tokenizer.init(doc.data(),context.fileName,context.markdownSupport,context.insideHtmlLink);
 
   // first parse any number of paragraphs
   bool isFirst=TRUE;
@@ -1607,10 +1608,10 @@ int DocParser::internalValidatingParseDoc(DocNodeVariant *parent,DocNodeList &ch
   }
   do
   {
-    auto vDocPara = children.append(this,parent);
+    children.append(this,parent);
     DocPara *par  = children.get_last();
     if (isFirst) { par->markFirst(); isFirst=FALSE; }
-    retval=par->parse(vDocPara);
+    retval=par->parse();
     if (!par->isEmpty())
     {
       if (lastPar) lastPar->markLast(FALSE);
@@ -1623,9 +1624,7 @@ int DocParser::internalValidatingParseDoc(DocNodeVariant *parent,DocNodeList &ch
   } while (retval==TK_NEWPARA);
   if (lastPar) lastPar->markLast();
 
-  //printf("internalValidateParsingDoc: %p: isFirst=%d isLast=%d\n",
-  //   lastPar,lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
-
+  AUTO_TRACE_EXIT("isFirst={} isLast={}",lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
   return retval;
 }
 
@@ -1633,6 +1632,7 @@ int DocParser::internalValidatingParseDoc(DocNodeVariant *parent,DocNodeList &ch
 
 void DocParser::readTextFileByName(const QCString &file,QCString &text)
 {
+  AUTO_TRACE("file={} text={}",file,text);
   if (Portable::isAbsolutePath(file))
   {
     FileInfo fi(file.str());
@@ -1677,9 +1677,9 @@ void DocParser::readTextFileByName(const QCString &file,QCString &text)
 
 //---------------------------------------------------------------------------
 
-static QCString extractCopyDocId(const char *data, uint &j, uint len)
+static QCString extractCopyDocId(const char *data, uint32_t &j, size_t len)
 {
-  uint s=j;
+  uint32_t s=j;
   int round=0;
   bool insideDQuote=FALSE;
   bool insideSQuote=FALSE;
@@ -1725,7 +1725,7 @@ static QCString extractCopyDocId(const char *data, uint &j, uint len)
   {
     j+=9;
   }
-  uint e=j;
+  uint32_t e=j;
   if (j>0 && data[j-1]=='.') { e--; } // do not include punctuation added by Definition::_setBriefDescription()
   QCString id(data+s,e-s);
   //printf("extractCopyDocId='%s' input='%s'\n",qPrint(id),&data[s]);
@@ -1740,9 +1740,9 @@ static QCString extractCopyDocId(const char *data, uint &j, uint len)
    do if ((i+sizeof(str)(len);
 }
 
 
-QCString DocParser::processCopyDoc(const char *data,uint &len)
+QCString DocParser::processCopyDoc(const char *data,size_t &len)
 {
-  //printf("processCopyDoc start '%s'\n",data);
+  AUTO_TRACE("data={} len={}",Trace::trunc(data),len);
   GrowBuf buf;
-  uint i=0;
+  uint32_t i=0;
   int lineNr = tokenizer.getLineNr();
   while (i0)
       {
         // skip whitespace
@@ -1824,28 +1824,37 @@ QCString DocParser::processCopyDoc(const char *data,uint &len)
           {
             QCString orgFileName = context.fileName;
             context.copyStack.push_back(def);
+            auto addDocs = [&](const QCString &file_,int line_,const QCString &doc_)
+            {
+              buf.addStr(" \\ilinebr\\ifile \""+file_+"\" ");
+              buf.addStr("\\iline "+QCString().setNum(line_)+" ");
+              size_t len_ = doc_.length();
+              buf.addStr(processCopyDoc(doc_.data(),len_));
+            };
             if (isBrief)
             {
-              buf.addStr("\\ifile \""+QCString(def->briefFile())+"\" ");
-              buf.addStr("\\iline "+QCString().setNum(def->briefLine())+" ");
-              uint l=static_cast(brief.length());
-              buf.addStr(processCopyDoc(brief.data(),l));
+              addDocs(def->briefFile(),def->briefLine(),brief);
             }
             else
             {
-              buf.addStr("\\ifile \""+QCString(def->docFile())+"\" ");
-              buf.addStr("\\iline "+QCString().setNum(def->docLine())+" ");
-              uint l=static_cast(doc.length());
-              buf.addStr(processCopyDoc(doc.data(),l));
+              addDocs(def->docFile(),def->docLine(),doc);
+              if (def->definitionType()==Definition::TypeMember)
+              {
+                const MemberDef *md = toMemberDef(def);
+                const ArgumentList &docArgList = md->templateMaster() ?
+                    md->templateMaster()->argumentList() :
+                    md->argumentList();
+                buf.addStr(inlineArgListToDoc(docArgList));
+              }
             }
             context.copyStack.pop_back();
-            buf.addStr("\\ifile \""+context.fileName+"\" ");
+            buf.addStr(" \\ilinebr\\ifile \""+context.fileName+"\" ");
             buf.addStr("\\iline "+QCString().setNum(lineNr)+" ");
           }
           else
           {
             warn_doc_error(context.fileName,tokenizer.getLineNr(),
-	         "Found recursive @copy%s or @copydoc relation for argument '%s'.\n",
+	         "Found recursive @copy%s or @copydoc relation for argument '%s'.",
                  isBrief?"brief":"details",qPrint(id));
           }
         }
@@ -1861,10 +1870,10 @@ QCString DocParser::processCopyDoc(const char *data,uint &len)
       else
       {
         QCString endMarker;
-        uint k = isVerbatimSection(data,i,len,endMarker);
+        uint32_t k = isVerbatimSection(data,i,len,endMarker);
         if (k>0)
         {
-          uint orgPos = i;
+          uint32_t orgPos = i;
           i=skipToEndMarker(data,k,len,endMarker);
           buf.addStr(data+orgPos,i-orgPos);
           // TODO: adjust lineNr
@@ -1883,8 +1892,9 @@ QCString DocParser::processCopyDoc(const char *data,uint &len)
       lineNr += (c=='\n') ? 1 : 0;
     }
   }
-  len = static_cast(buf.getPos());
+  len = static_cast(buf.getPos());
   buf.addChar(0);
+  AUTO_TRACE_EXIT("result={}",Trace::trunc(buf.get()));
   return buf.get();
 }
 
@@ -1907,11 +1917,9 @@ IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf,
   //                                     input);
   //printf("========== validating %s at line %d\n",qPrint(fileName),startLine);
   //printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",qPrint(input));
-  //parser->context.token = new TokenInfo;
 
-  // store parser state so we can re-enter this function if needed
-  //bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
-  parser->pushContext();
+  // set initial token
+  parser->context.token = parser->tokenizer.resetToken();
 
   if (ctx && ctx!=Doxygen::globalScope &&
       (ctx->definitionType()==Definition::TypeClass ||
@@ -1919,7 +1927,7 @@ IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf,
       )
      )
   {
-    parser->context.context = ctx->name();
+    parser->context.context = ctx->qualifiedName();
   }
   else if (ctx && ctx->definitionType()==Definition::TypePage)
   {
@@ -1942,12 +1950,12 @@ IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf,
     if (md)
     {
       parser->context.searchUrl=md->getOutputFileBase();
-      parser->searchData.setCurrentDoc(md,md->anchor(),false);
+      Doxygen::searchIndex->setCurrentDoc(md,md->anchor(),false);
     }
     else if (ctx)
     {
       parser->context.searchUrl=ctx->getOutputFileBase();
-      parser->searchData.setCurrentDoc(ctx,ctx->anchor(),false);
+      Doxygen::searchIndex->setCurrentDoc(ctx,ctx->anchor(),false);
     }
   }
   else
@@ -1980,18 +1988,19 @@ IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf,
 
   //printf("Starting comment block at %s:%d\n",qPrint(parser->context.fileName),startLine);
   parser->tokenizer.setLineNr(startLine);
-  uint ioLen = static_cast(input.length());
+  size_t ioLen = input.length();
   QCString inpStr = parser->processCopyDoc(input.data(),ioLen);
   if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n')
   {
     inpStr+='\n';
   }
   //printf("processCopyDoc(in='%s' out='%s')\n",input,qPrint(inpStr));
-  parser->tokenizer.init(inpStr.data(),parser->context.fileName,markdownSupport);
+  parser->tokenizer.init(inpStr.data(),parser->context.fileName,
+                         parser->context.markdownSupport,parser->context.insideHtmlLink);
 
   // build abstract syntax tree
   auto ast = std::make_unique(DocRoot(parser,md!=0,singleLine));
-  std::get(ast->root).parse(&ast->root);
+  std::get(ast->root).parse();
 
   if (Debug::isFlagSet(Debug::PrintTree))
   {
@@ -1999,16 +2008,14 @@ IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf,
     std::visit(PrintDocVisitor{},ast->root);
   }
 
-  parser->checkUnOrMultipleDocumentedParams();
+  if (md && md->isFunction())
+  {
+    parser->checkUnOrMultipleDocumentedParams();
+  }
   if (parser->context.memberDef) parser->context.memberDef->detectUndocumentedParams(parser->context.hasParamCommand,parser->context.hasReturnCommand);
 
-  // TODO: These should be called at the end of the program.
-  //parser->tokenizer.cleanup();
-  //Mappers::cmdMapper->freeInstance();
-  //Mappers::htmlTagMapper->freeInstance();
-
-  // restore original parser state
-  parser->popContext();
+  // reset token
+  parser->tokenizer.resetToken();
 
   //printf(">>>>>> end validatingParseDoc(%s,%s)\n",ctx?qPrint(ctx->name()):"",
   //                                     md?qPrint(md->name()):"");
@@ -2022,8 +2029,8 @@ IDocNodeASTPtr validatingParseText(IDocParser &parserIntf,const QCString &input)
   assert(parser!=0);
   if (parser==0) return 0;
 
-  // store parser state so we can re-enter this function if needed
-  parser->pushContext();
+  // set initial token
+  parser->context.token = parser->tokenizer.resetToken();
 
   //printf("------------ input ---------\n%s\n"
   //       "------------ end input -----\n",input);
@@ -2048,6 +2055,7 @@ IDocNodeASTPtr validatingParseText(IDocParser &parserIntf,const QCString &input)
   parser->context.retvalsFound.clear();
   parser->context.paramsFound.clear();
   parser->context.searchUrl="";
+  parser->context.markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
 
 
   auto ast = std::make_unique(DocText(parser));
@@ -2055,10 +2063,11 @@ IDocNodeASTPtr validatingParseText(IDocParser &parserIntf,const QCString &input)
   if (!input.isEmpty())
   {
     parser->tokenizer.setLineNr(1);
-    parser->tokenizer.init(input.data(),parser->context.fileName,Config_getBool(MARKDOWN_SUPPORT));
+    parser->tokenizer.init(input.data(),parser->context.fileName,
+                           parser->context.markdownSupport,parser->context.insideHtmlLink);
 
     // build abstract syntax tree
-    std::get(ast->root).parse(&ast->root);
+    std::get(ast->root).parse();
 
     if (Debug::isFlagSet(Debug::PrintTree))
     {
@@ -2067,8 +2076,6 @@ IDocNodeASTPtr validatingParseText(IDocParser &parserIntf,const QCString &input)
     }
   }
 
-  // restore original parser state
-  parser->popContext();
   return ast;
 }