Doxygen
docparser.cpp
浏览该文件的文档.
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2021 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <cassert>
19 
20 #include <ctype.h>
21 
22 #include "qcstring.h"
23 #include "regex.h"
24 #include "doxygen.h"
25 #include "debug.h"
26 #include "util.h"
27 #include "pagedef.h"
28 #include "docparser.h"
29 #include "doctokenizer.h"
30 #include "cmdmapper.h"
31 #include "printdocvisitor.h"
32 #include "message.h"
33 #include "section.h"
34 #include "searchindex.h"
35 #include "language.h"
36 #include "portable.h"
37 #include "cite.h"
38 #include "arguments.h"
39 #include "vhdldocgen.h"
40 #include "groupdef.h"
41 #include "classlist.h"
42 #include "filedef.h"
43 #include "memberdef.h"
44 #include "namespacedef.h"
45 #include "reflist.h"
46 #include "formula.h"
47 #include "config.h"
48 #include "growbuf.h"
49 #include "markdown.h"
50 #include "htmlentity.h"
51 #include "emoji.h"
52 #include "fileinfo.h"
53 #include "dir.h"
54 
55 #define TK_COMMAND_CHAR(token) ((token)==TK_COMMAND_AT ? "@" : "\\")
56 
57 // debug off
58 #define DBG(x) do {} while(0)
59 
60 // debug to stdout
61 //#define DBG(x) printf x
62 
63 // debug to stderr
64 //#define myprintf(...) fprintf(stderr,__VA_ARGS__)
65 //#define DBG(x) myprintf x
66 
67 #define INTERNAL_ASSERT(x) do {} while(0)
68 //#define INTERNAL_ASSERT(x) if (!(x)) DBG(("INTERNAL_ASSERT(%s) failed retval=0x%x: file=%s line=%d\n",#x,retval,__FILE__,__LINE__));
69 
70 //---------------------------------------------------------------------------
71 
72 static const char *g_sectionLevelToName[] =
73 {
74  "page",
75  "section",
76  "subsection",
77  "subsubsection",
78  "paragraph",
79  "subparagraph"
80 };
81 
82 static const std::set<std::string> g_plantumlEngine {
83  "uml", "bpm", "wire", "dot", "ditaa",
84  "salt", "math", "latex", "gantt", "mindmap",
85  "wbs", "yaml", "creole", "json", "flow",
86  "board", "git"
87 };
88 
89 //---------------------------------------------------------------------------
90 
91 //---------------------------------------------------------------------------
92 
93 using DefinitionStack = std::vector<const Definition *>;
94 using DocNodeStack = std::stack<const DocNode *>;
95 using DocStyleChangeStack = std::stack<const DocStyleChange *>;
96 
97 /** Parser's context to store all global variables.
98  */
100 {
112 
118  bool isExample;
121 
128 
130  int lineNo;
132 };
133 
134 class DocParser : public IDocParser
135 {
136  public:
137  void pushContext();
138  void popContext();
139  void handleImg(DocNode *parent,DocNodeList &children,const HtmlAttribList &tagHtmlAttribs);
140  int internalValidatingParseDoc(DocNode *parent,DocNodeList &children,
141  const QCString &doc);
142  QCString processCopyDoc(const char *data,uint &len);
143  QCString findAndCopyImage(const QCString &fileName,DocImage::Type type, bool doWarn = true);
144  void checkArgumentName();
145  void checkRetvalName();
147  bool findDocsForMemberOrCompound(const QCString &commandName,
148  QCString *pDoc,
149  QCString *pBrief,
150  const Definition **pDef);
151  bool defaultHandleToken(DocNode *parent,int tok,
152  DocNodeList &children,bool
153  handleWord=TRUE);
154  void errorHandleDefaultToken(DocNode *parent,int tok,
155  DocNodeList &children,const QCString &txt);
156  void defaultHandleTitleAndSize(const int cmd, DocNode *parent,
157  DocNodeList &children, QCString &width,QCString &height);
158  int handleStyleArgument(DocNode *parent,DocNodeList &children,
159  const QCString &cmdName);
160  void handleStyleEnter(DocNode *parent,DocNodeList &children, DocStyleChange::Style s,
161  const QCString &tagName,const HtmlAttribList *attribs);
162  void handleStyleLeave(DocNode *parent,DocNodeList &children, DocStyleChange::Style s,
163  const QCString &tagName);
164  void handlePendingStyleCommands(DocNode *parent,DocNodeList &children);
165  void handleInitialStyleCommands(DocPara *parent,DocNodeList &children);
166  int handleAHref(DocNode *parent,DocNodeList &children,const HtmlAttribList &tagHtmlAttribs);
168  void handleLinkedWord(DocNode *parent,DocNodeList &children,bool ignoreAutoLinkFlag=FALSE);
169  void handleParameterType(DocNode *parent,DocNodeList &children,const QCString &paramTypes);
171  DocAnchor *handleAnchor(DocNode *parent);
172  void readTextFileByName(const QCString &file,QCString &text);
173 
174  std::stack< DocParserContext > contextStack;
177 };
178 
179 std::unique_ptr<IDocParser> createDocParser()
180 {
181  return std::make_unique<DocParser>();
182 }
183 
184 //---------------------------------------------------------------------------
185 
187 {
188  public:
189  AutoNodeStack(DocParser &parser,const DocNode* node)
190  : m_parser(parser), m_node(node) { m_parser.context.nodeStack.push(node); }
192 #if defined(NDEBUG)
193  (void)m_node;
194  if (!m_parser.context.nodeStack.empty()) m_parser.context.nodeStack.pop(); // robust version that does not assert
195 #else
196  assert(m_parser.context.nodeStack.top()==m_node); m_parser.context.nodeStack.pop(); // error checking version
197 #endif
198  }
199 
200  private:
202  const DocNode *m_node;
203 };
204 
205 //---------------------------------------------------------------------------
206 
207 //---------------------------------------------------------------------------
209 {
210  //QCString indent;
211  //indent.fill(' ',contextStack.size()*2+2);
212  //printf("%sdocParserPushContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
213 
216  auto &ctx = contextStack.top();
217  ctx = context;
218  ctx.lineNo = tokenizer.getLineNr();
220 }
221 
223 {
224  auto &ctx = contextStack.top();
225  context = ctx;
226  tokenizer.setLineNr(ctx.lineNo);
227  context.token = ctx.token;
229  contextStack.pop();
231 
232  //QCString indent;
233  //indent.fill(' ',contextStack.size()*2+2);
234  //printf("%sdocParserPopContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
235 }
236 
237 //---------------------------------------------------------------------------
238 
239 // replaces { with < and } with > and also
240 // replaces &gt; with < and &gt; with > within string s
241 static void unescapeCRef(QCString &s)
242 {
243  QCString result;
244  const char *p = s.data();
245  if (p)
246  {
247  char c;
248  while ((c=*p++))
249  {
250  if (c=='{') c='<'; else if (c=='}') c='>';
251  result+=c;
252  }
253  }
254 
255  result=substitute(result,"&lt;","<");
256  result=substitute(result,"&gt;",">");
257  s = result;
258 }
259 
260 //---------------------------------------------------------------------------
261 
262 /*! search for an image in the imageNameDict and if found
263  * copies the image to the output directory (which depends on the \a type
264  * parameter).
265  */
266 QCString DocParser::findAndCopyImage(const QCString &fileName, DocImage::Type type, bool doWarn)
267 {
268  QCString result;
269  bool ambig;
270  FileDef *fd = findFileDef(Doxygen::imageNameLinkedMap,fileName,ambig);
271  //printf("Search for %s\n",fileName);
272  if (fd)
273  {
274  if (ambig & doWarn)
275  {
276  QCString text;
277  text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName));
278  text+="Possible candidates:\n";
281  }
282 
283  QCString inputFile = fd->absFilePath();
284  FileInfo infi(inputFile.str());
285  if (infi.exists())
286  {
287  result = fileName;
288  int i;
289  if ((i=result.findRev('/'))!=-1 || (i=result.findRev('\\'))!=-1)
290  {
291  result = result.right((int)result.length()-i-1);
292  }
293  //printf("fileName=%s result=%s\n",fileName,qPrint(result));
294  QCString outputDir;
295  switch(type)
296  {
297  case DocImage::Html:
298  if (!Config_getBool(GENERATE_HTML)) return result;
299  outputDir = Config_getString(HTML_OUTPUT);
300  break;
301  case DocImage::Latex:
302  if (!Config_getBool(GENERATE_LATEX)) return result;
303  outputDir = Config_getString(LATEX_OUTPUT);
304  break;
305  case DocImage::DocBook:
306  if (!Config_getBool(GENERATE_DOCBOOK)) return result;
307  outputDir = Config_getString(DOCBOOK_OUTPUT);
308  break;
309  case DocImage::Rtf:
310  if (!Config_getBool(GENERATE_RTF)) return result;
311  outputDir = Config_getString(RTF_OUTPUT);
312  break;
313  case DocImage::Xml:
314  if (!Config_getBool(GENERATE_XML)) return result;
315  outputDir = Config_getString(XML_OUTPUT);
316  break;
317  }
318  QCString outputFile = outputDir+"/"+result;
319  FileInfo outfi(outputFile.str());
320  if (outfi.isSymLink())
321  {
322  Dir().remove(outputFile.str());
324  "destination of image %s is a symlink, replacing with image",
325  qPrint(outputFile));
326  }
327  if (outputFile!=inputFile) // prevent copying to ourself
328  {
329  if (copyFile(inputFile,outputFile) && type==DocImage::Html)
330  {
332  }
333  }
334  }
335  else
336  {
338  "could not open image %s",qPrint(fileName));
339  }
340 
341  if (type==DocImage::Latex && Config_getBool(USE_PDFLATEX) &&
342  fd->name().right(4)==".eps"
343  )
344  { // we have an .eps image in pdflatex mode => convert it to a pdf.
345  QCString outputDir = Config_getString(LATEX_OUTPUT);
346  QCString baseName = fd->name().left(fd->name().length()-4);
347  QCString epstopdfArgs(4096);
348  epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"",
349  qPrint(outputDir), qPrint(baseName),
350  qPrint(outputDir), qPrint(baseName));
352  if (Portable::system("epstopdf",epstopdfArgs)!=0)
353  {
354  err("Problems running epstopdf. Check your TeX installation!\n");
355  }
357  return baseName;
358  }
359  }
360  else
361  {
362  result=fileName;
363  if (result.left(5)!="http:" && result.left(6)!="https:" && doWarn)
364  {
366  "image file %s is not found in IMAGE_PATH: "
367  "assuming external image.",qPrint(fileName)
368  );
369  }
370  }
371  return result;
372 }
373 
374 /*! Collects the parameters found with \@param command
375  * in a list context.paramsFound. If
376  * the parameter is not an actual parameter of the current
377  * member context.memberDef, then a warning is raised (unless warnings
378  * are disabled altogether).
379  */
381 {
382  if (!Config_getBool(WARN_IF_DOC_ERROR)) return;
383  if (context.memberDef==0) return; // not a member
384  std::string name = context.token->name.str();
389  //printf("isDocsForDefinition()=%d\n",context.memberDef->isDocsForDefinition());
390  if (al.empty()) return; // no argument list
391 
392  static const reg::Ex re(R"(\$?\w+\.*)");
393  reg::Iterator it(name,re);
395  for (; it!=end ; ++it)
396  {
397  const auto &match = *it;
398  QCString aName=match.str();
399  if (lang==SrcLangExt_Fortran) aName=aName.lower();
400  //printf("aName='%s'\n",qPrint(aName));
401  bool found=FALSE;
402  for (const Argument &a : al)
403  {
404  QCString argName = context.memberDef->isDefine() ? a.type : a.name;
405  if (lang==SrcLangExt_Fortran) argName=argName.lower();
406  argName=argName.stripWhiteSpace();
407  //printf("argName='%s' aName=%s\n",qPrint(argName),qPrint(aName));
408  if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
409  if (aName==argName)
410  {
411  context.paramsFound.insert(aName.str());
412  found=TRUE;
413  break;
414  }
415  }
416  if (!found)
417  {
418  //printf("member type=%d\n",context.memberDef->memberType());
420  if (!scope.isEmpty()) scope+="::"; else scope="";
421  QCString inheritedFrom = "";
422  QCString docFile = context.memberDef->docFile();
423  int docLine = context.memberDef->docLine();
424  const MemberDef *inheritedMd = context.memberDef->inheritsDocsFrom();
425  if (inheritedMd) // documentation was inherited
426  {
427  inheritedFrom.sprintf(" inherited from member %s at line "
428  "%d in file %s",qPrint(inheritedMd->name()),
429  inheritedMd->docLine(),qPrint(inheritedMd->docFile()));
430  docFile = context.memberDef->getDefFileName();
431  docLine = context.memberDef->getDefLine();
432  }
433  QCString alStr = argListToString(al);
434  warn_doc_error(docFile,docLine,
435  "argument '%s' of command @param "
436  "is not found in the argument list of %s%s%s%s",
437  qPrint(aName), qPrint(scope), qPrint(context.memberDef->name()),
438  qPrint(alStr), qPrint(inheritedFrom));
439  }
440  }
441 }
442 /*! Collects the return values found with \@retval command
443  * in a global list g_parserContext.retvalsFound.
444  */
446 {
447  QCString name = context.token->name;
448  if (!Config_getBool(WARN_IF_DOC_ERROR)) return;
449  if (context.memberDef==0 || name.isEmpty()) return; // not a member or no valid name
450  if (context.retvalsFound.count(name.str())==1) // only report the first double entry
451  {
454  "%s",
455  qPrint("return value '" + name + "' of " +
457  " has multiple documentation sections"));
458  }
459  context.retvalsFound.insert(name.str());
460 }
461 
462 /*! Checks if the parameters that have been specified using \@param are
463  * indeed all parameters and that a parameter does not have multiple
464  * \@param blocks.
465  * Must be called after checkArgumentName() has been called for each
466  * argument.
467  */
469 {
471  {
476  if (!al.empty())
477  {
478  ArgumentList undocParams;
479  for (const Argument &a: al)
480  {
481  QCString argName = context.memberDef->isDefine() ? a.type : a.name;
482  if (lang==SrcLangExt_Fortran) argName = argName.lower();
483  argName=argName.stripWhiteSpace();
484  QCString aName = argName;
485  if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
486  if (lang==SrcLangExt_Python && (argName=="self" || argName=="cls"))
487  {
488  // allow undocumented self / cls parameter for Python
489  }
490  else if (!argName.isEmpty())
491  {
492  size_t count = context.paramsFound.count(argName.str());
493  if (count==0 && a.docs.isEmpty())
494  {
495  undocParams.push_back(a);
496  }
497  else if (count>1 && Config_getBool(WARN_IF_DOC_ERROR))
498  {
501  "%s",
502  qPrint("argument '" + aName +
503  "' from the argument list of " +
505  " has multiple @param documentation sections"));
506  }
507  }
508  }
509  if (!undocParams.empty() && Config_getBool(WARN_IF_INCOMPLETE_DOC))
510  {
511  bool first=TRUE;
512  QCString errMsg = "The following parameter";
513  if (undocParams.size()>1) errMsg+="s";
514  errMsg+=" of "+
517  (undocParams.size()>1 ? " are" : " is") + " not documented:\n";
518  for (const Argument &a : undocParams)
519  {
520  QCString argName = context.memberDef->isDefine() ? a.type : a.name;
521  if (lang==SrcLangExt_Fortran) argName = argName.lower();
522  argName=argName.stripWhiteSpace();
523  if (!first) errMsg+="\n";
524  first=FALSE;
525  errMsg+=" parameter '"+argName+"'";
526  }
529  "%s",
530  qPrint(substitute(errMsg,"%","%%")));
531  }
532  }
533  }
534 }
535 
536 //---------------------------------------------------------------------------
537 
538 /*! Strips known html and tex extensions from \a text. */
540 {
541  QCString result=text;
542  if (result.right(4)==".tex")
543  {
544  result=result.left(result.length()-4);
545  }
546  else if (result.right(Doxygen::htmlFileExtension.length())==
548  {
549  result=result.left(result.length()-Doxygen::htmlFileExtension.length());
550  }
551  return result;
552 }
553 
554 
555 //---------------------------------------------------------------------------
556 
557 /*! Returns TRUE iff node n is a child of a preformatted node */
558 static bool insidePRE(DocNode *n)
559 {
560  while (n)
561  {
562  if (n->isPreformatted()) return TRUE;
563  n=n->parent();
564  }
565  return FALSE;
566 }
567 
568 //---------------------------------------------------------------------------
569 
570 /*! Returns TRUE iff node n is a child of a html list item node */
571 static bool insideLI(DocNode *n)
572 {
573  while (n)
574  {
575  if (n->kind()==DocNode::Kind_HtmlListItem) return TRUE;
576  n=n->parent();
577  }
578  return FALSE;
579 }
580 
581 //---------------------------------------------------------------------------
582 
583 /*! Returns TRUE iff node n is a child of a unordered html list node */
584 static bool insideUL(DocNode *n)
585 {
586  while (n)
587  {
588  if (n->kind()==DocNode::Kind_HtmlList &&
589  ((DocHtmlList *)n)->type()==DocHtmlList::Unordered) return TRUE;
590  n=n->parent();
591  }
592  return FALSE;
593 }
594 
595 //---------------------------------------------------------------------------
596 
597 /*! Returns TRUE iff node n is a child of a ordered html list node */
598 static bool insideOL(DocNode *n)
599 {
600  while (n)
601  {
602  if (n->kind()==DocNode::Kind_HtmlList &&
603  ((DocHtmlList *)n)->type()==DocHtmlList::Ordered) return TRUE;
604  n=n->parent();
605  }
606  return FALSE;
607 }
608 
609 //---------------------------------------------------------------------------
610 
611 static bool insideTable(DocNode *n)
612 {
613  while (n)
614  {
615  if (n->kind()==DocNode::Kind_HtmlTable) return TRUE;
616  n=n->parent();
617  }
618  return FALSE;
619 }
620 
621 //---------------------------------------------------------------------------
622 /*! Looks for a documentation block with name commandName in the current
623  * context (g_parserContext.context). The resulting documentation string is
624  * put in pDoc, the definition in which the documentation was found is
625  * put in pDef.
626  * @retval TRUE if name was found.
627  * @retval FALSE if name was not found.
628  */
630  QCString *pDoc,
631  QCString *pBrief,
632  const Definition **pDef)
633 {
634  //printf("findDocsForMemberOrCompound(%s)\n",commandName);
635  *pDoc="";
636  *pBrief="";
637  *pDef=0;
638  QCString cmdArg=commandName;
639  if (cmdArg.isEmpty()) return FALSE;
640 
641  const FileDef *fd=0;
642  const GroupDef *gd=0;
643  const PageDef *pd=0;
644  gd = Doxygen::groupLinkedMap->find(cmdArg);
645  if (gd) // group
646  {
647  *pDoc=gd->documentation();
648  *pBrief=gd->briefDescription();
649  *pDef=gd;
650  return TRUE;
651  }
652  pd = Doxygen::pageLinkedMap->find(cmdArg);
653  if (pd) // page
654  {
655  *pDoc=pd->documentation();
656  *pBrief=pd->briefDescription();
657  *pDef=pd;
658  return TRUE;
659  }
660  bool ambig;
661  fd = findFileDef(Doxygen::inputNameLinkedMap,cmdArg,ambig);
662  if (fd && !ambig) // file
663  {
664  *pDoc=fd->documentation();
665  *pBrief=fd->briefDescription();
666  *pDef=fd;
667  return TRUE;
668  }
669 
670  // for symbols we need to normalize the separator, so A#B, or A\B, or A.B becomes A::B
671  cmdArg = substitute(cmdArg,"#","::");
672  cmdArg = substitute(cmdArg,"\\","::");
673  static bool extractAnonNs = Config_getBool(EXTRACT_ANON_NSPACES);
674  if (extractAnonNs &&
675  cmdArg.startsWith("anonymous_namespace{")
676  )
677  {
678  size_t rightBracePos = cmdArg.find("}", static_cast<int>(qstrlen("anonymous_namespace{")));
679  QCString leftPart = cmdArg.left(rightBracePos + 1);
680  QCString rightPart = cmdArg.right(cmdArg.size() - rightBracePos - 1);
681  rightPart = substitute(rightPart, ".", "::");
682  cmdArg = leftPart + rightPart;
683  }
684  else
685  {
686  cmdArg = substitute(cmdArg,".","::");
687  }
688 
689  int l=(int)cmdArg.length();
690 
691  int funcStart=cmdArg.find('(');
692  if (funcStart==-1)
693  {
694  funcStart=l;
695  }
696  else
697  {
698  // Check for the case of operator() and the like.
699  // beware of scenarios like operator()((foo)bar)
700  int secondParen = cmdArg.find('(', funcStart+1);
701  int leftParen = cmdArg.find(')', funcStart+1);
702  if (leftParen!=-1 && secondParen!=-1)
703  {
704  if (leftParen<secondParen)
705  {
706  funcStart=secondParen;
707  }
708  }
709  }
710 
711  QCString name=removeRedundantWhiteSpace(cmdArg.left(funcStart));
712  QCString args=cmdArg.right(l-funcStart);
713  // try if the link is to a member
714  const MemberDef *md=0;
715  const ClassDef *cd=0;
716  const NamespaceDef *nd=0;
717  bool found = getDefs(
718  context.context.find('.')==-1?context.context:QCString(), // find('.') is a hack to detect files
719  name,
720  args.isEmpty() ? QCString() : args,
721  md,cd,fd,nd,gd,FALSE,0,TRUE);
722  //printf("found=%d context=%s name=%s\n",found,qPrint(context.context),qPrint(name));
723  if (found && md)
724  {
725  *pDoc=md->documentation();
726  *pBrief=md->briefDescription();
727  *pDef=md;
728  return TRUE;
729  }
730 
731 
732  int scopeOffset=(int)context.context.length();
733  do // for each scope
734  {
735  QCString fullName=cmdArg;
736  if (scopeOffset>0)
737  {
738  fullName.prepend(context.context.left(scopeOffset)+"::");
739  }
740  //printf("Trying fullName='%s'\n",qPrint(fullName));
741 
742  // try class, namespace, group, page, file reference
743  cd = Doxygen::classLinkedMap->find(fullName);
744  if (cd) // class
745  {
746  *pDoc=cd->documentation();
747  *pBrief=cd->briefDescription();
748  *pDef=cd;
749  return TRUE;
750  }
751  nd = Doxygen::namespaceLinkedMap->find(fullName);
752  if (nd) // namespace
753  {
754  *pDoc=nd->documentation();
755  *pBrief=nd->briefDescription();
756  *pDef=nd;
757  return TRUE;
758  }
759  if (scopeOffset==0)
760  {
761  scopeOffset=-1;
762  }
763  else
764  {
765  scopeOffset = context.context.findRev("::",scopeOffset-1);
766  if (scopeOffset==-1) scopeOffset=0;
767  }
768  } while (scopeOffset>=0);
769 
770 
771  return FALSE;
772 }
773 
774 //---------------------------------------------------------------------------
776  DocNodeList &children,const QCString &txt)
777 {
778  const char *cmd_start = "\\";
779  switch (tok)
780  {
781  case TK_COMMAND_AT:
782  cmd_start = "@";
783  // fall through
784  case TK_COMMAND_BS:
785  children.push_back(std::make_unique<DocWord>(*this,parent,TK_COMMAND_CHAR(tok) + context.token->name));
786  warn_doc_error(context.fileName,tokenizer.getLineNr(),"Illegal command %s as part of a %s",
787  qPrint(cmd_start + context.token->name),qPrint(txt));
788  break;
789  case TK_SYMBOL:
790  warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported symbol %s found found as part of a %s",
791  qPrint(context.token->name), qPrint(txt));
792  break;
793  default:
794  children.push_back(std::make_unique<DocWord>(*this,parent,context.token->name));
795  warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unexpected token %s found as part of a %s",
796  DocTokenizer::tokToString(tok), qPrint(txt));
797  break;
798  }
799 }
800 
801 //---------------------------------------------------------------------------
802 
803 int DocParser::handleStyleArgument(DocNode *parent,DocNodeList &children,const QCString &cmdName)
804 {
805  DBG(("handleStyleArgument(%s)\n",qPrint(cmdName)));
806  QCString saveCmdName = cmdName;
807  int tok=tokenizer.lex();
808  if (tok!=TK_WHITESPACE)
809  {
810  warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\%s command",
811  qPrint(saveCmdName));
812  return tok;
813  }
814  while ((tok=tokenizer.lex()) &&
815  tok!=TK_WHITESPACE &&
816  tok!=TK_NEWPARA &&
817  tok!=TK_LISTITEM &&
818  tok!=TK_ENDLIST
819  )
820  {
821  static const reg::Ex specialChar(R"([.,|()\[\]:;?])");
822  if (tok==TK_WORD && context.token->name.length()==1 &&
823  reg::match(context.token->name.str(),specialChar))
824  {
825  // special character that ends the markup command
826  return tok;
827  }
828  if (!defaultHandleToken(parent,tok,children))
829  {
830  switch (tok)
831  {
832  case TK_HTMLTAG:
834  { // ignore </li> as the end of a style command
835  continue;
836  }
837  DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok)));
838  return tok;
839  break;
840  default:
841  errorHandleDefaultToken(parent,tok,children,"\\" + saveCmdName + " command");
842  break;
843  }
844  break;
845  }
846  }
847  DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok)));
848  return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST
849  ) ? tok : RetVal_OK;
850 }
851 
852 /*! Called when a style change starts. For instance a <b> command is
853  * encountered.
854  */
856  DocStyleChange::Style s,const QCString &tagName,const HtmlAttribList *attribs)
857 {
858  DBG(("HandleStyleEnter\n"));
859  DocStyleChange *sc= new DocStyleChange(*this,parent,(uint)context.nodeStack.size(),s,tagName,TRUE,attribs);
860  children.push_back(std::unique_ptr<DocStyleChange>(sc));
861  context.styleStack.push(sc);
862 }
863 
864 /*! Called when a style change ends. For instance a </b> command is
865  * encountered.
866  */
868  DocStyleChange::Style s,const QCString &tagName)
869 {
870  DBG(("HandleStyleLeave\n"));
871  QCString tagNameLower = QCString(tagName).lower();
872  if (context.styleStack.empty() || // no style change
873  context.styleStack.top()->style()!=s || // wrong style change
874  context.styleStack.top()->tagName()!=tagNameLower || // wrong style change
875  context.styleStack.top()->position()!=context.nodeStack.size() // wrong position
876  )
877  {
878  if (context.styleStack.empty())
879  {
880  warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </%s> tag without matching <%s>",
881  qPrint(tagName),qPrint(tagName));
882  }
883  else if (context.styleStack.top()->tagName()!=tagNameLower)
884  {
885  warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </%s> tag while expecting </%s>",
886  qPrint(tagName),qPrint(context.styleStack.top()->tagName()));
887  }
888  else if (context.styleStack.top()->style()!=s)
889  {
890  warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </%s> tag while expecting </%s>",
891  qPrint(tagName),qPrint(context.styleStack.top()->tagName()));
892  }
893  else
894  {
895  warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </%s> at different nesting level (%zu) than expected (%d)",
896  qPrint(tagName),context.nodeStack.size(),context.styleStack.top()->position());
897  }
898  }
899  else // end the section
900  {
901  children.push_back(
902  std::make_unique<DocStyleChange>(
903  *this,parent,(uint)context.nodeStack.size(),s,context.styleStack.top()->tagName(),FALSE));
904  context.styleStack.pop();
905  }
906 }
907 
908 /*! Called at the end of a paragraph to close all open style changes
909  * (e.g. a <b> without a </b>). The closed styles are pushed onto a stack
910  * and entered again at the start of a new paragraph.
911  */
913 {
914  if (!context.styleStack.empty())
915  {
916  const DocStyleChange *sc = context.styleStack.top();
917  while (sc && sc->position()>=context.nodeStack.size())
918  { // there are unclosed style modifiers in the paragraph
919  children.push_back(std::make_unique<DocStyleChange>(*this,parent,(uint)context.nodeStack.size(),sc->style(),sc->tagName(),FALSE));
920  context.initialStyleStack.push(sc);
921  context.styleStack.pop();
922  sc = !context.styleStack.empty() ? context.styleStack.top() : 0;
923  }
924  }
925 }
926 
928 {
929  while (!context.initialStyleStack.empty())
930  {
931  const DocStyleChange *sc = context.initialStyleStack.top();
932  handleStyleEnter(parent,children,sc->style(),sc->tagName(),&sc->attribs());
934  }
935 }
936 
938  const HtmlAttribList &tagHtmlAttribs)
939 {
940  uint index=0;
941  int retval = RetVal_OK;
942  for (const auto &opt : tagHtmlAttribs)
943  {
944  if (opt.name=="name" || opt.name=="id") // <a name=label> or <a id=label> tag
945  {
946  if (!opt.value.isEmpty())
947  {
948  children.push_back(std::make_unique<DocAnchor>(*this,parent,opt.value,TRUE));
949  break; // stop looking for other tag attribs
950  }
951  else
952  {
953  warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <a> tag with name option but without value!");
954  }
955  }
956  else if (opt.name=="href") // <a href=url>..</a> tag
957  {
958  // copy attributes
959  HtmlAttribList attrList = tagHtmlAttribs;
960  // and remove the href attribute
961  attrList.erase(attrList.begin()+index);
962  QCString relPath;
963  if (opt.value.at(0) != '#') relPath = context.relPath;
964  DocHRef *href = new DocHRef(*this,parent,attrList,opt.value,relPath,convertNameToFile(context.fileName,FALSE,TRUE));
965  children.push_back(std::unique_ptr<DocHRef>(href));
967  retval = href->parse();
969  break;
970  }
971  else // unsupported option for tag a
972  {
973  }
974  ++index;
975  }
976  return retval;
977 }
978 
979 const char *DocStyleChange::styleString() const
980 {
981  switch (m_style)
982  {
983  case DocStyleChange::Bold: return "b";
984  case DocStyleChange::Italic: return "em";
985  case DocStyleChange::Code: return "code";
986  case DocStyleChange::Center: return "center";
987  case DocStyleChange::Small: return "small";
988  case DocStyleChange::Subscript: return "subscript";
989  case DocStyleChange::Superscript: return "superscript";
990  case DocStyleChange::Preformatted: return "pre";
991  case DocStyleChange::Div: return "div";
992  case DocStyleChange::Span: return "span";
993  case DocStyleChange::Strike: return "strike";
994  case DocStyleChange::S: return "s";
995  case DocStyleChange::Del: return "del";
996  case DocStyleChange::Underline: return "u";
997  case DocStyleChange::Ins: return "ins";
998  }
999  return "<invalid>";
1000 }
1001 
1003 {
1004  if (!context.initialStyleStack.empty())
1005  {
1006  const DocStyleChange *sc = context.initialStyleStack.top();
1007  context.initialStyleStack.pop();
1010  "end of comment block while expecting "
1011  "command </%s>",qPrint(sc->tagName()));
1012  }
1013 }
1014 
1015 void DocParser::handleLinkedWord(DocNode *parent,DocNodeList &children,bool ignoreAutoLinkFlag)
1016 {
1018  static bool autolinkSupport = Config_getBool(AUTOLINK_SUPPORT);
1019  if (!autolinkSupport && !ignoreAutoLinkFlag) // no autolinking -> add as normal word
1020  {
1021  children.push_back(std::make_unique<DocWord>(*this,parent,name));
1022  return;
1023  }
1024 
1025  // ------- try to turn the word 'name' into a link
1026 
1027  const Definition *compound=0;
1028  const MemberDef *member=0;
1029  uint len = context.token->name.length();
1030  ClassDef *cd=0;
1031  bool ambig;
1033  //printf("handleLinkedWord(%s) context.context=%s\n",qPrint(context.token->name),qPrint(context.context));
1034  if (!context.insideHtmlLink &&
1036  || (!context.context.isEmpty() && // also try with global scope
1037  resolveRef("",context.token->name,context.inSeeBlock,&compound,&member,FALSE,0,TRUE))
1038  )
1039  )
1040  {
1041  //printf("resolveRef %s = %p (linkable?=%d)\n",qPrint(context.token->name),member,member ? member->isLinkable() : FALSE);
1042  if (member && member->isLinkable()) // member link
1043  {
1044  if (member->isObjCMethod())
1045  {
1046  bool localLink = context.memberDef ? member->getClassDef()==context.memberDef->getClassDef() : FALSE;
1047  name = member->objCMethodName(localLink,context.inSeeBlock);
1048  }
1049  children.push_back(
1050  std::make_unique<DocLinkedWord>(
1051  *this,parent,name,
1052  member->getReference(),
1053  member->getOutputFileBase(),
1054  member->anchor(),
1055  member->briefDescriptionAsTooltip()));
1056  }
1057  else if (compound->isLinkable()) // compound link
1058  {
1059  QCString anchor = compound->anchor();
1060  if (compound->definitionType()==Definition::TypeFile)
1061  {
1062  name=context.token->name;
1063  }
1064  else if (compound->definitionType()==Definition::TypeGroup)
1065  {
1066  name=toGroupDef(compound)->groupTitle();
1067  }
1068  children.push_back(
1069  std::make_unique<DocLinkedWord>(
1070  *this,parent,name,
1071  compound->getReference(),
1072  compound->getOutputFileBase(),
1073  anchor,
1074  compound->briefDescriptionAsTooltip()));
1075  }
1076  else if (compound->definitionType()==Definition::TypeFile &&
1077  (toFileDef(compound))->generateSourceFile()
1078  ) // undocumented file that has source code we can link to
1079  {
1080  children.push_back(
1081  std::make_unique<DocLinkedWord>(
1082  *this,parent,context.token->name,
1083  compound->getReference(),
1084  compound->getSourceFileBase(),
1085  "",
1086  compound->briefDescriptionAsTooltip()));
1087  }
1088  else // not linkable
1089  {
1090  children.push_back(std::make_unique<DocWord>(*this,parent,name));
1091  }
1092  }
1093  else if (!context.insideHtmlLink && len>1 && context.token->name.at(len-1)==':')
1094  {
1095  // special case, where matching Foo: fails to be an Obj-C reference,
1096  // but Foo itself might be linkable.
1097  context.token->name=context.token->name.left(len-1);
1098  handleLinkedWord(parent,children,ignoreAutoLinkFlag);
1099  children.push_back(std::make_unique<DocWord>(*this,parent,":"));
1100  }
1101  else if (!context.insideHtmlLink && (cd=getClass(context.token->name+"-p")))
1102  {
1103  // special case 2, where the token name is not a class, but could
1104  // be a Obj-C protocol
1105  children.push_back(
1106  std::make_unique<DocLinkedWord>(
1107  *this,parent,name,
1108  cd->getReference(),
1109  cd->getOutputFileBase(),
1110  cd->anchor(),
1111  cd->briefDescriptionAsTooltip()));
1112  }
1113  else // normal non-linkable word
1114  {
1115  if (context.token->name.left(1)=="#" || context.token->name.left(2)=="::")
1116  {
1117  warn_doc_error(context.fileName,tokenizer.getLineNr(),"explicit link request to '%s' could not be resolved",qPrint(name));
1118  children.push_back(std::make_unique<DocWord>(*this,parent,context.token->name));
1119  }
1120  else
1121  {
1122  children.push_back(std::make_unique<DocWord>(*this,parent,name));
1123  }
1124  }
1125 }
1126 
1127 void DocParser::handleParameterType(DocNode *parent,DocNodeList &children,const QCString &paramTypes)
1128 {
1129  QCString name = context.token->name; // save token name
1130  QCString name1;
1131  int p=0,i,ii;
1132  while ((i=paramTypes.find('|',p))!=-1)
1133  {
1134  name1 = paramTypes.mid(p,i-p);
1135  ii=name1.find('[');
1136  context.token->name=ii!=-1 ? name1.mid(0,ii) : name1; // take part without []
1137  handleLinkedWord(parent,children);
1138  if (ii!=-1) children.push_back(std::make_unique<DocWord>(*this,parent,name1.mid(ii))); // add [] part
1139  p=i+1;
1140  children.push_back(std::make_unique<DocSeparator>(*this,parent,"|"));
1141  }
1142  name1 = paramTypes.mid(p);
1143  ii=name1.find('[');
1144  context.token->name=ii!=-1 ? name1.mid(0,ii) : name1;
1145  handleLinkedWord(parent,children);
1146  if (ii!=-1) children.push_back(std::make_unique<DocWord>(*this,parent,name1.mid(ii)));
1147  context.token->name = name; // restore original token name
1148 }
1149 
1151 {
1152  //printf("CMD_INTERNALREF\n");
1153  int tok=tokenizer.lex();
1154  QCString tokenName = context.token->name;
1155  if (tok!=TK_WHITESPACE)
1156  {
1157  warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\%s command",
1158  qPrint(tokenName));
1159  return 0;
1160  }
1162  tok=tokenizer.lex(); // get the reference id
1163  if (tok!=TK_WORD && tok!=TK_LNKWORD)
1164  {
1165  warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
1166  DocTokenizer::tokToString(tok),qPrint(tokenName));
1167  return 0;
1168  }
1169  return new DocInternalRef(*this,parent,context.token->name);
1170 }
1171 
1173 {
1174  int tok=tokenizer.lex();
1175  if (tok!=TK_WHITESPACE)
1176  {
1177  warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\%s command",
1178  qPrint(context.token->name));
1179  return 0;
1180  }
1182  tok=tokenizer.lex();
1183  if (tok==0)
1184  {
1185  warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
1186  "argument of command %s",qPrint(context.token->name));
1187  return 0;
1188  }
1189  else if (tok!=TK_WORD && tok!=TK_LNKWORD)
1190  {
1191  warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
1193  return 0;
1194  }
1196  return new DocAnchor(*this,parent,context.token->name,FALSE);
1197 }
1198 
1199 
1200 /* Helper function that deals with the title, width, and height arguments of various commands.
1201  * @param[in] cmd Command id for which to extract caption and size info.
1202  * @param[in] parent Parent node, owner of the children list passed as
1203  * the third argument.
1204  * @param[in] children The list of child nodes to which the node representing
1205  * the token can be added.
1206  * @param[out] width the extracted width specifier
1207  * @param[out] height the extracted height specifier
1208  */
1209 void DocParser::defaultHandleTitleAndSize(const int cmd, DocNode *parent, DocNodeList &children, QCString &width,QCString &height)
1210 {
1211  auto ns = AutoNodeStack(*this,parent);
1212 
1213  // parse title
1215  int tok;
1216  while ((tok=tokenizer.lex()))
1217  {
1218  if (tok==TK_WORD && (context.token->name=="width=" || context.token->name=="height="))
1219  {
1220  // special case: no title, but we do have a size indicator
1221  break;
1222  }
1223  if (!defaultHandleToken(parent,tok,children))
1224  {
1225  errorHandleDefaultToken(parent,tok,children,Mappers::cmdMapper->find(cmd));
1226  }
1227  }
1228  // parse size attributes
1229  if (tok == 0)
1230  {
1231  tok=tokenizer.lex();
1232  }
1233  while (tok==TK_WHITESPACE || tok==TK_WORD) // there are values following the title
1234  {
1235  if(tok == TK_WORD)
1236  {
1237  if (context.token->name=="width=" || context.token->name=="height=")
1238  {
1241  }
1242 
1243  if (context.token->name=="width")
1244  {
1245  width = context.token->chars;
1246  }
1247  else if (context.token->name=="height")
1248  {
1249  height = context.token->chars;
1250  }
1251  else
1252  {
1253  warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unknown option '%s' after \\%s command, expected 'width' or 'height'",
1255  break;
1256  }
1257  }
1258 
1259  tok=tokenizer.lex();
1260  }
1262 
1263  handlePendingStyleCommands(parent,children);
1264 }
1265 
1266 /* Helper function that deals with the most common tokens allowed in
1267  * title like sections.
1268  * @param parent Parent node, owner of the children list passed as
1269  * the third argument.
1270  * @param tok The token to process.
1271  * @param children The list of child nodes to which the node representing
1272  * the token can be added.
1273  * @param handleWord Indicates if word token should be processed
1274  * @retval TRUE The token was handled.
1275  * @retval FALSE The token was not handled.
1276  */
1277 bool DocParser::defaultHandleToken(DocNode *parent,int tok, DocNodeList &children,bool handleWord)
1278 {
1279  DBG(("token %s at %d",DocTokenizer::tokToString(tok),tokenizer.getLineNr()));
1280  if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
1281  tok==TK_COMMAND_AT || tok==TK_COMMAND_BS || tok==TK_HTMLTAG
1282  )
1283  {
1284  DBG((" name=%s",qPrint(context.token->name)));
1285  }
1286  DBG(("\n"));
1287 reparsetoken:
1288  QCString tokenName = context.token->name;
1289  switch (tok)
1290  {
1291  case TK_COMMAND_AT:
1292  // fall through
1293  case TK_COMMAND_BS:
1294  switch (Mappers::cmdMapper->map(tokenName))
1295  {
1296  case CMD_BSLASH:
1297  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_BSlash));
1298  break;
1299  case CMD_AT:
1300  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_At));
1301  break;
1302  case CMD_LESS:
1303  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Less));
1304  break;
1305  case CMD_GREATER:
1306  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Greater));
1307  break;
1308  case CMD_AMP:
1309  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Amp));
1310  break;
1311  case CMD_DOLLAR:
1312  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Dollar));
1313  break;
1314  case CMD_HASH:
1315  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Hash));
1316  break;
1317  case CMD_DCOLON:
1318  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_DoubleColon));
1319  break;
1320  case CMD_PERCENT:
1321  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Percent));
1322  break;
1323  case CMD_NDASH:
1324  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Minus));
1325  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Minus));
1326  break;
1327  case CMD_MDASH:
1328  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Minus));
1329  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Minus));
1330  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Minus));
1331  break;
1332  case CMD_QUOTE:
1333  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Quot));
1334  break;
1335  case CMD_PUNT:
1336  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Dot));
1337  break;
1338  case CMD_PLUS:
1339  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Plus));
1340  break;
1341  case CMD_MINUS:
1342  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Minus));
1343  break;
1344  case CMD_EQUAL:
1345  children.push_back(std::make_unique<DocSymbol>(*this,parent,DocSymbol::Sym_Equal));
1346  break;
1347  case CMD_EMPHASIS:
1348  {
1349  children.push_back(std::make_unique<DocStyleChange>(*this,parent,(uint)context.nodeStack.size(),DocStyleChange::Italic,tokenName,TRUE));
1350  tok=handleStyleArgument(parent,children,tokenName);
1351  children.push_back(std::make_unique<DocStyleChange>(*this,parent,(uint)context.nodeStack.size(),DocStyleChange::Italic,tokenName,FALSE));
1352  if (tok!=TK_WORD) children.push_back(std::make_unique<DocWhiteSpace>(*this,parent," "));
1353  if (tok==TK_NEWPARA) goto handlepara;
1354  else if (tok==TK_WORD || tok==TK_HTMLTAG)
1355  {
1356  DBG(("CMD_EMPHASIS: reparsing command %s\n",qPrint(context.token->name)));
1357  goto reparsetoken;
1358  }
1359  }
1360  break;
1361  case CMD_BOLD:
1362  {
1363  children.push_back(std::make_unique<DocStyleChange>(*this,parent,(uint)context.nodeStack.size(),DocStyleChange::Bold,tokenName,TRUE));
1364  tok=handleStyleArgument(parent,children,tokenName);
1365  children.push_back(std::make_unique<DocStyleChange>(*this,parent,(uint)context.nodeStack.size(),DocStyleChange::Bold,tokenName,FALSE));
1366  if (tok!=TK_WORD) children.push_back(std::make_unique<DocWhiteSpace>(*this,parent," "));
1367  if (tok==TK_NEWPARA) goto handlepara;
1368  else if (tok==TK_WORD || tok==TK_HTMLTAG)
1369  {
1370  DBG(("CMD_BOLD: reparsing command %s\n",qPrint(context.token->name)));
1371  goto reparsetoken;
1372  }
1373  }
1374  break;
1375  case CMD_CODE:
1376  {
1377  children.push_back(std::make_unique<DocStyleChange>(*this,parent,(uint)context.nodeStack.size(),DocStyleChange::Code,tokenName,TRUE));
1378  tok=handleStyleArgument(parent,children,tokenName);
1379  children.push_back(std::make_unique<DocStyleChange>(*this,parent,(uint)context.nodeStack.size(),DocStyleChange::Code,tokenName,FALSE));
1380  if (tok!=TK_WORD) children.push_back(std::make_unique<DocWhiteSpace>(*this,parent," "));
1381  if (tok==TK_NEWPARA) goto handlepara;
1382  else if (tok==TK_WORD || tok==TK_HTMLTAG)
1383  {
1384  DBG(("CMD_CODE: reparsing command %s\n",qPrint(context.token->name)));
1385  goto reparsetoken;
1386  }
1387  }
1388  break;
1389  case CMD_HTMLONLY:
1390  {
1392  tok = tokenizer.lex();
1393  children.push_back(std::make_unique<DocVerbatim>(*this,parent,context.context,context.token->verb,DocVerbatim::HtmlOnly,context.isExample,context.exampleName,context.token->name=="block"));
1394  if (tok==0) warn_doc_error(context.fileName,tokenizer.getLineNr(),"htmlonly section ended without end marker");
1396  }
1397  break;
1398  case CMD_MANONLY:
1399  {
1401  tok = tokenizer.lex();
1402  children.push_back(std::make_unique<DocVerbatim>(*this,parent,context.context,context.token->verb,DocVerbatim::ManOnly,context.isExample,context.exampleName));
1403  if (tok==0) warn_doc_error(context.fileName,tokenizer.getLineNr(),"manonly section ended without end marker");
1405  }
1406  break;
1407  case CMD_RTFONLY:
1408  {
1410  tok = tokenizer.lex();
1411  children.push_back(std::make_unique<DocVerbatim>(*this,parent,context.context,context.token->verb,DocVerbatim::RtfOnly,context.isExample,context.exampleName));
1412  if (tok==0) warn_doc_error(context.fileName,tokenizer.getLineNr(),"rtfonly section ended without end marker");
1414  }
1415  break;
1416  case CMD_LATEXONLY:
1417  {
1419  tok = tokenizer.lex();
1420  children.push_back(std::make_unique<DocVerbatim>(*this,parent,context.context,context.token->verb,DocVerbatim::LatexOnly,context.isExample,context.exampleName));
1421  if (tok==0) warn_doc_error(context.fileName,tokenizer.getLineNr(),"latexonly section ended without end marker");
1423  }
1424  break;
1425  case CMD_XMLONLY:
1426  {
1428  tok = tokenizer.lex();
1429  children.push_back(std::make_unique<DocVerbatim>(*this,parent,context.context,context.token->verb,DocVerbatim::XmlOnly,context.isExample,context.exampleName));
1430  if (tok==0) warn_doc_error(context.fileName,tokenizer.getLineNr(),"xmlonly section ended without end marker");
1432  }
1433  break;
1434  case CMD_DBONLY:
1435  {
1437  tok = tokenizer.lex();
1438  children.push_back(std::make_unique<DocVerbatim>(*this,parent,context.context,context.token->verb,DocVerbatim::DocbookOnly,context.isExample,context.exampleName));
1439  if (tok==0) warn_doc_error(context.fileName,tokenizer.getLineNr(),"docbookonly section ended without end marker");
1441  }
1442  break;
1443  case CMD_FORMULA:
1444  {
1445  children.push_back(std::make_unique<DocFormula>(*this,parent,context.token->id));
1446  }
1447  break;
1448  case CMD_ANCHOR:
1449  {
1450  DocAnchor *anchor = handleAnchor(parent);
1451  if (anchor)
1452  {
1453  children.push_back(std::unique_ptr<DocAnchor>(anchor));
1454  }
1455  }
1456  break;
1457  case CMD_INTERNALREF:
1458  {
1459  DocInternalRef *ref = handleInternalRef(parent);
1460  if (ref)
1461  {
1462  children.push_back(std::unique_ptr<DocInternalRef>(ref));
1463  ref->parse();
1464  }
1466  }
1467  break;
1468  case CMD_SETSCOPE:
1469  {
1470  QCString scope;
1472  (void)tokenizer.lex();
1473  scope = context.token->name;
1474  context.context = scope;
1475  //printf("Found scope='%s'\n",qPrint(scope));
1477  }
1478  break;
1479  case CMD_IMAGE:
1480  ((DocPara *)parent) -> handleImage("image");
1481  break;
1482  default:
1483  return FALSE;
1484  }
1485  break;
1486  case TK_HTMLTAG:
1487  {
1488  switch (Mappers::htmlTagMapper->map(tokenName))
1489  {
1490  case HTML_DIV:
1491  warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <div> tag in heading\n");
1492  break;
1493  case HTML_PRE:
1494  warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <pre> tag in heading\n");
1495  break;
1496  case HTML_BOLD:
1497  if (!context.token->endTag)
1498  {
1499  handleStyleEnter(parent,children,DocStyleChange::Bold,tokenName,&context.token->attribs);
1500  }
1501  else
1502  {
1503  handleStyleLeave(parent,children,DocStyleChange::Bold,tokenName);
1504  }
1505  break;
1506  case HTML_S:
1507  if (!context.token->endTag)
1508  {
1509  handleStyleEnter(parent,children,DocStyleChange::S,tokenName,&context.token->attribs);
1510  }
1511  else
1512  {
1513  handleStyleLeave(parent,children,DocStyleChange::S,tokenName);
1514  }
1515  break;
1516  case HTML_STRIKE:
1517  if (!context.token->endTag)
1518  {
1519  handleStyleEnter(parent,children,DocStyleChange::Strike,tokenName,&context.token->attribs);
1520  }
1521  else
1522  {
1523  handleStyleLeave(parent,children,DocStyleChange::Strike,tokenName);
1524  }
1525  break;
1526  case HTML_DEL:
1527  if (!context.token->endTag)
1528  {
1529  handleStyleEnter(parent,children,DocStyleChange::Del,tokenName,&context.token->attribs);
1530  }
1531  else
1532  {
1533  handleStyleLeave(parent,children,DocStyleChange::Del,tokenName);
1534  }
1535  break;
1536  case HTML_UNDERLINE:
1537  if (!context.token->endTag)
1538  {
1539  handleStyleEnter(parent,children,DocStyleChange::Underline,tokenName,&context.token->attribs);
1540  }
1541  else
1542  {
1543  handleStyleLeave(parent,children,DocStyleChange::Underline,tokenName);
1544  }
1545  break;
1546  case HTML_INS:
1547  if (!context.token->endTag)
1548  {
1549  handleStyleEnter(parent,children,DocStyleChange::Ins,tokenName,&context.token->attribs);
1550  }
1551  else
1552  {
1553  handleStyleLeave(parent,children,DocStyleChange::Ins,tokenName);
1554  }
1555  break;
1556  case HTML_CODE:
1557  case XML_C:
1558  if (!context.token->endTag)
1559  {
1560  handleStyleEnter(parent,children,DocStyleChange::Code,tokenName,&context.token->attribs);
1561  }
1562  else
1563  {
1564  handleStyleLeave(parent,children,DocStyleChange::Code,tokenName);
1565  }
1566  break;
1567  case HTML_EMPHASIS:
1568  if (!context.token->endTag)
1569  {
1570  handleStyleEnter(parent,children,DocStyleChange::Italic,tokenName,&context.token->attribs);
1571  }
1572  else
1573  {
1574  handleStyleLeave(parent,children,DocStyleChange::Italic,tokenName);
1575  }
1576  break;
1577  case HTML_SUB:
1578  if (!context.token->endTag)
1579  {
1580  handleStyleEnter(parent,children,DocStyleChange::Subscript,tokenName,&context.token->attribs);
1581  }
1582  else
1583  {
1584  handleStyleLeave(parent,children,DocStyleChange::Subscript,tokenName);
1585  }
1586  break;
1587  case HTML_SUP:
1588  if (!context.token->endTag)
1589  {
1590  handleStyleEnter(parent,children,DocStyleChange::Superscript,tokenName,&context.token->attribs);
1591  }
1592  else
1593  {
1594  handleStyleLeave(parent,children,DocStyleChange::Superscript,tokenName);
1595  }
1596  break;
1597  case HTML_CENTER:
1598  if (!context.token->endTag)
1599  {
1600  handleStyleEnter(parent,children,DocStyleChange::Center,tokenName,&context.token->attribs);
1601  }
1602  else
1603  {
1604  handleStyleLeave(parent,children,DocStyleChange::Center,tokenName);
1605  }
1606  break;
1607  case HTML_SMALL:
1608  if (!context.token->endTag)
1609  {
1610  handleStyleEnter(parent,children,DocStyleChange::Small,tokenName,&context.token->attribs);
1611  }
1612  else
1613  {
1614  handleStyleLeave(parent,children,DocStyleChange::Small,tokenName);
1615  }
1616  break;
1617  case HTML_IMG:
1618  if (!context.token->endTag)
1619  handleImg(parent,children,context.token->attribs);
1620  break;
1621  default:
1622  return FALSE;
1623  break;
1624  }
1625  }
1626  break;
1627  case TK_SYMBOL:
1628  {
1630  if (s!=DocSymbol::Sym_Unknown)
1631  {
1632  children.push_back(std::make_unique<DocSymbol>(*this,parent,s));
1633  }
1634  else
1635  {
1636  return FALSE;
1637  }
1638  }
1639  break;
1640  case TK_WHITESPACE:
1641  case TK_NEWPARA:
1642 handlepara:
1643  if (insidePRE(parent) || !children.empty())
1644  {
1645  children.push_back(std::make_unique<DocWhiteSpace>(*this,parent,context.token->chars));
1646  }
1647  break;
1648  case TK_LNKWORD:
1649  if (handleWord)
1650  {
1651  handleLinkedWord(parent,children);
1652  }
1653  else
1654  return FALSE;
1655  break;
1656  case TK_WORD:
1657  if (handleWord)
1658  {
1659  children.push_back(std::make_unique<DocWord>(*this,parent,context.token->name));
1660  }
1661  else
1662  return FALSE;
1663  break;
1664  case TK_URL:
1665  if (context.insideHtmlLink)
1666  {
1667  children.push_back(std::make_unique<DocWord>(*this,parent,context.token->name));
1668  }
1669  else
1670  {
1671  children.push_back(std::make_unique<DocURL>(*this,parent,context.token->name,context.token->isEMailAddr));
1672  }
1673  break;
1674  default:
1675  return FALSE;
1676  }
1677  return TRUE;
1678 }
1679 
1680 //---------------------------------------------------------------------------
1681 
1682 void DocParser::handleImg(DocNode *parent, DocNodeList &children,const HtmlAttribList &tagHtmlAttribs)
1683 {
1684  bool found=FALSE;
1685  uint index=0;
1686  for (const auto &opt : tagHtmlAttribs)
1687  {
1688  //printf("option name=%s value=%s\n",qPrint(opt.name),qPrint(opt.value));
1689  if (opt.name=="src" && !opt.value.isEmpty())
1690  {
1691  // copy attributes
1692  HtmlAttribList attrList = tagHtmlAttribs;
1693  // and remove the src attribute
1694  attrList.erase(attrList.begin()+index);
1696  children.push_back(
1697  std::make_unique<DocImage>(
1698  *this,parent,attrList,
1699  findAndCopyImage(opt.value,t,false),
1700  t,opt.value));
1701  found = TRUE;
1702  }
1703  ++index;
1704  }
1705  if (!found)
1706  {
1707  warn_doc_error(context.fileName,tokenizer.getLineNr(),"IMG tag does not have a SRC attribute!\n");
1708  }
1709 }
1710 
1711 //---------------------------------------------------------------------------
1712 
1714 {
1715  DBG(("decodeSymbol(%s)\n",qPrint(symName)));
1716  return HtmlEntityMapper::instance()->name2sym(symName);
1717 }
1718 
1719 //---------------------------------------------------------------------------
1720 
1721 DocEmoji::DocEmoji(DocParser &parser,DocNode *parent,const QCString &symName) :
1722  DocNode(parser), m_symName(symName), m_index(-1)
1723 {
1724  m_parent = parent;
1725  QCString locSymName = symName;
1726  uint len=locSymName.length();
1727  if (len>0)
1728  {
1729  if (locSymName.at(len-1)!=':') locSymName.append(":");
1730  if (locSymName.at(0)!=':') locSymName.prepend(":");
1731  }
1732  m_symName = locSymName;
1734  if (m_index==-1)
1735  {
1736  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"Found unsupported emoji symbol '%s'\n",qPrint(m_symName));
1737  }
1738 }
1739 
1740 //---------------------------------------------------------------------------
1741 
1743  const QCString &doc)
1744 {
1745  int retval = RetVal_OK;
1746 
1747  if (doc.isEmpty()) return retval;
1748 
1750 
1751  // first parse any number of paragraphs
1752  bool isFirst=TRUE;
1753  DocPara *lastPar=0;
1754  if (!children.empty() && children.back()->kind()==DocNode::Kind_Para)
1755  { // last child item was a paragraph
1756  lastPar = (DocPara*)children.back().get();
1757  isFirst=FALSE;
1758  }
1759  do
1760  {
1761  DocPara *par = new DocPara(*this,parent);
1762  if (isFirst) { par->markFirst(); isFirst=FALSE; }
1763  retval=par->parse();
1764  if (!par->isEmpty())
1765  {
1766  children.push_back(std::unique_ptr<DocNode>(par));
1767  if (lastPar) lastPar->markLast(FALSE);
1768  lastPar=par;
1769  }
1770  else
1771  {
1772  delete par;
1773  }
1774  } while (retval==TK_NEWPARA);
1775  if (lastPar) lastPar->markLast();
1776 
1777  //printf("internalValidateParsingDoc: %p: isFirst=%d isLast=%d\n",
1778  // lastPar,lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
1779 
1780  return retval;
1781 }
1782 
1783 //---------------------------------------------------------------------------
1784 
1786 {
1787  if (Portable::isAbsolutePath(file))
1788  {
1789  FileInfo fi(file.str());
1790  if (fi.exists())
1791  {
1792  text = fileToString(file,Config_getBool(FILTER_SOURCE_FILES));
1793  return;
1794  }
1795  }
1796  const StringVector &examplePathList = Config_getList(EXAMPLE_PATH);
1797  for (const auto &s : examplePathList)
1798  {
1799  std::string absFileName = s+(Portable::pathSeparator()+file).str();
1800  FileInfo fi(absFileName);
1801  if (fi.exists())
1802  {
1803  text = fileToString(QCString(absFileName),Config_getBool(FILTER_SOURCE_FILES));
1804  return;
1805  }
1806  }
1807 
1808  // as a fallback we also look in the exampleNameDict
1809  bool ambig;
1811  if (fd)
1812  {
1813  text = fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES));
1814  if (ambig)
1815  {
1816  warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file name %s is ambiguous"
1817  "Possible candidates:\n%s",qPrint(file),
1819  );
1820  }
1821  }
1822  else
1823  {
1824  warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file %s is not found. "
1825  "Check your EXAMPLE_PATH",qPrint(file));
1826  }
1827 }
1828 
1829 //---------------------------------------------------------------------------
1830 
1831 DocWord::DocWord(DocParser &parser,DocNode *parent,const QCString &word) :
1832  DocNode(parser), m_word(word)
1833 {
1834  m_parent = parent;
1835  //printf("new word %s url=%s\n",qPrint(word),qPrint(parser.context.searchUrl));
1836  if (Doxygen::searchIndex && !parser.context.searchUrl.isEmpty())
1837  {
1839  }
1840 }
1841 
1842 //---------------------------------------------------------------------------
1843 
1845  const QCString &ref,const QCString &file,
1846  const QCString &anchor,const QCString &tooltip) :
1847  DocNode(parser), m_word(word), m_ref(ref),
1848  m_file(file), m_relPath(parser.context.relPath), m_anchor(anchor),
1849  m_tooltip(tooltip)
1850 {
1851  m_parent = parent;
1852  //printf("DocLinkedWord: new word %s url=%s tooltip='%s'\n",
1853  // qPrint(word),qPrint(parser.context.searchUrl),qPrint(tooltip));
1854  if (Doxygen::searchIndex && !parser.context.searchUrl.isEmpty())
1855  {
1857  }
1858 }
1859 
1860 //---------------------------------------------------------------------------
1861 
1862 DocAnchor::DocAnchor(DocParser &parser,DocNode *parent,const QCString &id,bool newAnchor) : DocNode(parser)
1863 {
1864  m_parent = parent;
1865  if (id.isEmpty())
1866  {
1867  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"Empty anchor label");
1868  return;
1869  }
1870 
1872  QCString anchorPrefix = ct.anchorPrefix();
1873  if (id.left(anchorPrefix.length()) == anchorPrefix)
1874  {
1875  const CiteInfo *cite = ct.find(id.mid(anchorPrefix.length()));
1876  if (cite)
1877  {
1879  m_anchor = id;
1880  }
1881  else
1882  {
1883  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"Invalid cite anchor id '%s'",qPrint(id));
1884  m_anchor = "invalid";
1885  m_file = "invalid";
1886  }
1887  }
1888  else if (newAnchor) // found <a name="label">
1889  {
1890  m_anchor = id;
1891  }
1892  else // found \anchor label
1893  {
1894  const SectionInfo *sec = SectionManager::instance().find(id);
1895  if (sec)
1896  {
1897  //printf("Found anchor %s\n",qPrint(id));
1898  m_file = sec->fileName();
1899  m_anchor = sec->label();
1900  }
1901  else
1902  {
1903  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"Invalid anchor id '%s'",qPrint(id));
1904  m_anchor = "invalid";
1905  m_file = "invalid";
1906  }
1907  }
1908 }
1909 
1910 //---------------------------------------------------------------------------
1911 
1912 DocVerbatim::DocVerbatim(DocParser &parser,DocNode *parent,const QCString &context,
1913  const QCString &text, Type t,bool isExample,
1914  const QCString &exampleFile,bool isBlock,const QCString &lang)
1915  : DocNode(parser), m_context(context), m_text(text), m_type(t),
1916  m_isExample(isExample), m_exampleFile(exampleFile),
1917  m_relPath(parser.context.relPath), m_lang(lang), m_isBlock(isBlock)
1918 {
1919  m_parent = parent;
1920 }
1921 
1922 
1923 //---------------------------------------------------------------------------
1924 
1926 {
1927  DBG(("DocInclude::parse(file=%s,text=%s)\n",qPrint(m_file),qPrint(m_text)));
1928  switch(m_type)
1929  {
1930  case DontIncWithLines:
1931  // fall through
1932  case IncWithLines:
1933  // fall through
1934  case Include:
1935  // fall through
1936  case DontInclude:
1944  //printf("parser.context.includeFile=<<%s>>\n",qPrint(parser.context.includeFileText));
1945  break;
1946  case VerbInclude:
1947  // fall through
1948  case HtmlInclude:
1949  case LatexInclude:
1955  break;
1956  case Snippet:
1957  case SnipWithLines:
1959  // check here for the existence of the blockId inside the file, so we
1960  // only generate the warning once.
1961  int count;
1962  if (!m_blockId.isEmpty() && (count=m_text.contains(m_blockId.data()))!=2)
1963  {
1964  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n",
1965  qPrint(m_blockId),qPrint(m_file),count);
1966  }
1967  break;
1970  err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
1971  "Please create a bug report\n",__FILE__);
1972  break;
1973  }
1974 }
1975 
1976 //---------------------------------------------------------------------------
1977 
1979 {
1981  {
1983  "No previous '\\include' or '\\dontinclude' command for '\\%s' present",
1984  typeAsString());
1985  }
1986 
1988  const char *p = m_parser.context.includeFileText.data();
1991  int il = m_parser.context.includeFileLine;
1992  DBG(("DocIncOperator::parse() text=%s off=%d len=%d\n",p,o,l));
1993  uint so = o,bo;
1994  bool nonEmpty = FALSE;
1995  switch(type())
1996  {
1997  case Line:
1998  while (o<l)
1999  {
2000  char c = p[o];
2001  if (c=='\n')
2002  {
2004  if (nonEmpty) break; // we have a pattern to match
2005  so=o+1; // no pattern, skip empty line
2006  }
2007  else if (!isspace((uchar)c)) // no white space char
2008  {
2009  nonEmpty=TRUE;
2010  }
2011  o++;
2012  }
2013  if (m_parser.context.includeFileText.mid(so,o-so).find(m_pattern)!=-1)
2014  {
2015  m_line = il;
2017  DBG(("DocIncOperator::parse() Line: %s\n",qPrint(m_text)));
2018  }
2019  m_parser.context.includeFileOffset = std::min(l,o+1); // set pointer to start of new line
2021  break;
2022  case SkipLine:
2023  while (o<l)
2024  {
2025  so=o;
2026  while (o<l)
2027  {
2028  char c = p[o];
2029  if (c=='\n')
2030  {
2032  if (nonEmpty) break; // we have a pattern to match
2033  so=o+1; // no pattern, skip empty line
2034  }
2035  else if (!isspace((uchar)c)) // no white space char
2036  {
2037  nonEmpty=TRUE;
2038  }
2039  o++;
2040  }
2041  if (m_parser.context.includeFileText.mid(so,o-so).find(m_pattern)!=-1)
2042  {
2043  m_line = il;
2045  DBG(("DocIncOperator::parse() SkipLine: %s\n",qPrint(m_text)));
2046  break;
2047  }
2048  o++; // skip new line
2049  }
2050  m_parser.context.includeFileOffset = std::min(l,o+1); // set pointer to start of new line
2052  break;
2053  case Skip:
2054  while (o<l)
2055  {
2056  so=o;
2057  while (o<l)
2058  {
2059  char c = p[o];
2060  if (c=='\n')
2061  {
2063  if (nonEmpty) break; // we have a pattern to match
2064  so=o+1; // no pattern, skip empty line
2065  }
2066  else if (!isspace((uchar)c)) // no white space char
2067  {
2068  nonEmpty=TRUE;
2069  }
2070  o++;
2071  }
2072  if (m_parser.context.includeFileText.mid(so,o-so).find(m_pattern)!=-1)
2073  {
2074  break;
2075  }
2076  o++; // skip new line
2077  }
2078  m_parser.context.includeFileOffset = so; // set pointer to start of new line
2080  break;
2081  case Until:
2082  bo=o;
2083  while (o<l)
2084  {
2085  so=o;
2086  while (o<l)
2087  {
2088  char c = p[o];
2089  if (c=='\n')
2090  {
2092  if (nonEmpty) break; // we have a pattern to match
2093  so=o+1; // no pattern, skip empty line
2094  }
2095  else if (!isspace((uchar)c)) // no white space char
2096  {
2097  nonEmpty=TRUE;
2098  }
2099  o++;
2100  }
2101  if (m_parser.context.includeFileText.mid(so,o-so).find(m_pattern)!=-1)
2102  {
2103  m_line = il;
2105  DBG(("DocIncOperator::parse() Until: %s\n",qPrint(m_text)));
2106  break;
2107  }
2108  o++; // skip new line
2109  }
2110  m_parser.context.includeFileOffset = std::min(l,o+1); // set pointer to start of new line
2112  break;
2113  }
2114 }
2115 
2116 //---------------------------------------------------------------------------
2117 
2118 DocXRefItem::DocXRefItem(DocParser &parser,DocNode *parent,int id,const QCString &key) :
2119  CompAccept<DocXRefItem>(parser), m_id(id), m_key(key), m_relPath(parser.context.relPath)
2120 {
2121  m_parent = parent;
2122 }
2123 
2125 {
2127  if (refList && refList->isEnabled())
2128  {
2129  RefItem *item = refList->find(m_id);
2130  ASSERT(item!=0);
2131  if (item)
2132  {
2134  {
2135  m_file = "@"; // can't cross reference anonymous enum
2136  m_anchor = "@";
2137  }
2138  else
2139  {
2140  m_file = refList->fileName();
2141  m_anchor = item->anchor();
2142  }
2143  m_title = refList->sectionTitle();
2144  //printf("DocXRefItem: file=%s anchor=%s title=%s\n",
2145  // qPrint(m_file),qPrint(m_anchor),qPrint(m_title));
2146 
2147  if (!item->text().isEmpty())
2148  {
2151  m_parser.popContext();
2152  }
2153  }
2154  return TRUE;
2155  }
2156  return FALSE;
2157 }
2158 
2159 //---------------------------------------------------------------------------
2160 
2161 DocFormula::DocFormula(DocParser &parser,DocNode *parent,int id) : DocNode(parser),
2162  m_relPath(parser.context.relPath)
2163 {
2164  m_parent = parent;
2166  if (!text.isEmpty())
2167  {
2168  m_id = id;
2169  m_name.sprintf("form_%d",m_id);
2170  m_text = text;
2171  }
2172  else // wrong \_form#<n> command
2173  {
2174  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"Wrong formula id %d",id);
2175  m_id = -1;
2176  }
2177 }
2178 
2179 //---------------------------------------------------------------------------
2180 
2181 //int DocLanguage::parse()
2182 //{
2183 // int retval;
2184 // DBG(("DocLanguage::parse() start\n"));
2185 // auto ns = AutoNodeStack(m_parser,this);
2186 //
2187 // // parse one or more paragraphs
2188 // bool isFirst=TRUE;
2189 // DocPara *par=0;
2190 // do
2191 // {
2192 // par = new DocPara(this);
2193 // if (isFirst) { par->markFirst(); isFirst=FALSE; }
2194 // m_children.push_back(std::unique_ptr<DocPara>(par));
2195 // retval=par->parse();
2196 // }
2197 // while (retval==TK_NEWPARA);
2198 // if (par) par->markLast();
2199 //
2200 // DBG(("DocLanguage::parse() end\n"));
2201 // return retval;
2202 //}
2203 
2204 //---------------------------------------------------------------------------
2205 
2206 DocSecRefItem::DocSecRefItem(DocParser &parser,DocNode *parent,const QCString &target) :
2207  CompAccept<DocSecRefItem>(parser), m_target(target), m_relPath(parser.context.relPath)
2208 {
2209  m_parent = parent;
2210 }
2211 
2213 {
2214  DBG(("DocSecRefItem::parse() start\n"));
2215  auto ns = AutoNodeStack(m_parser,this);
2216 
2218  int tok;
2219  while ((tok=m_parser.tokenizer.lex()))
2220  {
2221  if (!m_parser.defaultHandleToken(this,tok,m_children))
2222  {
2223  m_parser.errorHandleDefaultToken(this,tok,m_children,"\\refitem");
2224  }
2225  }
2228 
2229  if (!m_target.isEmpty())
2230  {
2233  if (sec==0 && lang==SrcLangExt_Markdown) // lookup as markdown file
2234  {
2236  }
2237  if (sec) // ref to section or anchor
2238  {
2239  // set defaults
2240  m_ref = sec->ref();
2242  m_refType = Section;
2243  m_anchor = sec->label();
2244  m_isSubPage = false;
2245  // adjust if needed
2246  switch (sec->type())
2247  {
2248  case SectionType::Page:
2249  {
2251  m_isSubPage = pd && pd->hasParentPage();
2252  if (!m_isSubPage)
2253  {
2254  m_anchor="";
2255  }
2256  }
2257  break;
2258  case SectionType::Anchor:
2259  m_refType = Anchor;
2260  break;
2261  case SectionType::Table:
2262  m_refType = Table;
2263  break;
2264  default:
2265  break;
2266  }
2267  //printf("m_ref=%s,m_file=%s,type=%d\n",
2268  // qPrint(m_ref),qPrint(m_file),m_refType);
2269  }
2270  else
2271  {
2272  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"reference to unknown section %s",
2273  qPrint(m_target));
2274  }
2275  }
2276  else
2277  {
2278  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"reference to empty target");
2279  }
2280 
2281  DBG(("DocSecRefItem::parse() end\n"));
2282 }
2283 
2284 //---------------------------------------------------------------------------
2285 
2287 {
2288  DBG(("DocSecRefList::parse() start\n"));
2289  auto ns = AutoNodeStack(m_parser,this);
2290 
2291  int tok=m_parser.tokenizer.lex();
2292  // skip white space
2293  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
2294  // handle items
2295  while (tok)
2296  {
2297  if (tok==TK_COMMAND_AT || tok == TK_COMMAND_BS)
2298  {
2299  const char *cmd_start = (tok==TK_COMMAND_AT ? "@" : "\\");
2300  switch (Mappers::cmdMapper->map(m_parser.context.token->name))
2301  {
2302  case CMD_SECREFITEM:
2303  {
2304  tok=m_parser.tokenizer.lex();
2305  if (tok!=TK_WHITESPACE)
2306  {
2307  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\refitem command");
2308  break;
2309  }
2310  tok=m_parser.tokenizer.lex();
2311  if (tok!=TK_WORD && tok!=TK_LNKWORD)
2312  {
2313  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of \\refitem",
2315  break;
2316  }
2317 
2319  m_children.push_back(std::unique_ptr<DocSecRefItem>(item));
2320  item->parse();
2321  }
2322  break;
2323  case CMD_ENDSECREFLIST:
2324  goto endsecreflist;
2325  default:
2326  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Illegal command %s as part of a \\secreflist",
2327  qPrint(cmd_start + m_parser.context.token->name));
2328  goto endsecreflist;
2329  }
2330  }
2331  else if (tok==TK_WHITESPACE)
2332  {
2333  // ignore whitespace
2334  }
2335  else
2336  {
2337  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected token %s inside section reference list",
2339  goto endsecreflist;
2340  }
2341  tok=m_parser.tokenizer.lex();
2342  }
2343 
2344 endsecreflist:
2345  DBG(("DocSecRefList::parse() end\n"));
2346 }
2347 
2348 //---------------------------------------------------------------------------
2349 
2351  : CompAccept<DocInternalRef>(parser), m_relPath(parser.context.relPath)
2352 {
2353  m_parent = parent;
2354  int i=ref.find('#');
2355  if (i!=-1)
2356  {
2357  m_anchor = ref.right((int)ref.length()-i-1);
2358  m_file = ref.left(i);
2359  }
2360  else
2361  {
2362  m_file = ref;
2363  }
2364 }
2365 
2367 {
2368  auto ns = AutoNodeStack(m_parser,this);
2369  DBG(("DocInternalRef::parse() start\n"));
2370 
2371  int tok;
2372  while ((tok=m_parser.tokenizer.lex()))
2373  {
2374  if (!m_parser.defaultHandleToken(this,tok,m_children))
2375  {
2376  m_parser.errorHandleDefaultToken(this,tok,m_children,"\\ref");
2377  }
2378  }
2379 
2381  DBG(("DocInternalRef::parse() end\n"));
2382 }
2383 
2384 //---------------------------------------------------------------------------
2385 
2386 DocRef::DocRef(DocParser &parser,DocNode *parent,const QCString &target,const QCString &context) :
2387  CompAccept<DocRef>(parser), m_refType(Unknown), m_isSubPage(FALSE)
2388 {
2389  m_parent = parent;
2390  const Definition *compound = 0;
2391  QCString anchor;
2392  //printf("DocRef::DocRef(target=%s,context=%s)\n",qPrint(target),qPrint(context));
2393  ASSERT(!target.isEmpty());
2394  SrcLangExt lang = getLanguageFromFileName(target);
2395  m_relPath = parser.context.relPath;
2396  const SectionInfo *sec = SectionManager::instance().find(target);
2397  if (sec==0 && lang==SrcLangExt_Markdown) // lookup as markdown file
2398  {
2400  }
2401  if (sec) // ref to section or anchor
2402  {
2403  PageDef *pd = 0;
2404  if (sec->type()==SectionType::Page)
2405  {
2406  pd = Doxygen::pageLinkedMap->find(target);
2407  }
2408  m_text = sec->title();
2409  if (m_text.isEmpty()) m_text = sec->label();
2410 
2411  m_ref = sec->ref();
2413  if (sec->type()==SectionType::Anchor)
2414  {
2415  m_refType = Anchor;
2416  }
2417  else if (sec->type()==SectionType::Table)
2418  {
2419  m_refType = Table;
2420  }
2421  else
2422  {
2423  m_refType = Section;
2424  }
2425  m_isSubPage = pd && pd->hasParentPage();
2426  if (sec->type()!=SectionType::Page || m_isSubPage) m_anchor = sec->label();
2427  //printf("m_text=%s,m_ref=%s,m_file=%s,type=%d\n",
2428  // qPrint(m_text),qPrint(m_ref),qPrint(m_file),m_refType);
2429  return;
2430  }
2431  else if (resolveLink(context,target,TRUE,&compound,anchor))
2432  {
2433  bool isFile = compound ?
2434  (compound->definitionType()==Definition::TypeFile ||
2435  compound->definitionType()==Definition::TypePage ? TRUE : FALSE) :
2436  FALSE;
2437  m_text = linkToText(compound?compound->getLanguage():SrcLangExt_Unknown,target,isFile);
2438  m_anchor = anchor;
2439  if (compound && compound->isLinkable()) // ref to compound
2440  {
2441  if (anchor.isEmpty() && /* compound link */
2442  compound->definitionType()==Definition::TypeGroup && /* is group */
2443  !toGroupDef(compound)->groupTitle().isEmpty() /* with title */
2444  )
2445  {
2446  m_text=(toGroupDef(compound))->groupTitle(); // use group's title as link
2447  }
2448  else if (compound->definitionType()==Definition::TypeMember &&
2449  toMemberDef(compound)->isObjCMethod())
2450  {
2451  // Objective C Method
2452  const MemberDef *member = toMemberDef(compound);
2453  bool localLink = parser.context.memberDef ? member->getClassDef()==parser.context.memberDef->getClassDef() : FALSE;
2454  m_text = member->objCMethodName(localLink,parser.context.inSeeBlock);
2455  }
2456 
2457  m_file = compound->getOutputFileBase();
2458  m_ref = compound->getReference();
2459  //printf("isFile=%d compound=%s (%d)\n",isFile,qPrint(compound->name()),
2460  // compound->definitionType());
2461  return;
2462  }
2463  else if (compound && compound->definitionType()==Definition::TypeFile &&
2464  toFileDef(compound)->generateSourceFile()
2465  ) // undocumented file that has source code we can link to
2466  {
2467  m_file = compound->getSourceFileBase();
2468  m_ref = compound->getReference();
2469  return;
2470  }
2471  }
2472  m_text = target;
2473  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"unable to resolve reference to '%s' for \\ref command",
2474  qPrint(target));
2475 }
2476 
2477 static void flattenParagraphs(DocNode *root,DocNodeList &children)
2478 {
2479  DocNodeList newChildren;
2480  for (const auto &dn : children)
2481  {
2482  if (dn->kind()==DocNode::Kind_Para)
2483  {
2484  DocPara *para = (DocPara*)dn.get();
2485  // move the children of the paragraph to the end of the newChildren list
2486  newChildren.insert(newChildren.end(),
2487  std::make_move_iterator(para->children().begin()),
2488  std::make_move_iterator(para->children().end()));
2489  }
2490  }
2491 
2492  // replace the children list by the newChildren list
2493  children.clear();
2494  children.insert(children.end(),
2495  std::make_move_iterator(newChildren.begin()),
2496  std::make_move_iterator(newChildren.end()));
2497  // reparent the children
2498  for (const auto &cn : children)
2499  {
2500  cn->setParent(root);
2501  }
2502 }
2503 
2505 {
2506  auto ns = AutoNodeStack(m_parser,this);
2507  DBG(("DocRef::parse() start\n"));
2508 
2509  int tok;
2510  while ((tok=m_parser.tokenizer.lex()))
2511  {
2512  if (!m_parser.defaultHandleToken(this,tok,m_children))
2513  {
2514  switch (tok)
2515  {
2516  case TK_HTMLTAG:
2517  break;
2518  default:
2519  m_parser.errorHandleDefaultToken(this,tok,m_children,"\\ref");
2520  break;
2521  }
2522  }
2523  }
2524 
2525  if (m_children.empty() && !m_text.isEmpty())
2526  {
2530  m_parser.popContext();
2533  }
2534 
2536 }
2537 
2538 //---------------------------------------------------------------------------
2539 
2540 DocCite::DocCite(DocParser &parser,DocNode *parent,const QCString &target,const QCString &) : DocNode(parser)
2541 {
2542  size_t numBibFiles = Config_getList(CITE_BIB_FILES).size();
2543  m_parent = parent;
2544  //printf("DocCite::DocCite(target=%s)\n",qPrint(target));
2545  ASSERT(!target.isEmpty());
2546  m_relPath = parser.context.relPath;
2548  const CiteInfo *cite = ct.find(target);
2549  //printf("cite=%p text='%s' numBibFiles=%d\n",cite,cite?qPrint(cite->text):"<null>",numBibFiles);
2550  if (numBibFiles>0 && cite && !cite->text().isEmpty()) // ref to citation
2551  {
2552  m_text = cite->text();
2553  m_ref = "";
2554  m_anchor = ct.anchorPrefix()+cite->label();
2556  //printf("CITE ==> m_text=%s,m_ref=%s,m_file=%s,m_anchor=%s\n",
2557  // qPrint(m_text),qPrint(m_ref),qPrint(m_file),qPrint(m_anchor));
2558  return;
2559  }
2560  m_text = target;
2561  if (numBibFiles==0)
2562  {
2563  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"\\cite command found but no bib files specified via CITE_BIB_FILES!");
2564  }
2565  else if (cite==0)
2566  {
2567  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"unable to resolve reference to '%s' for \\cite command",
2568  qPrint(target));
2569  }
2570  else
2571  {
2572  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"\\cite command to '%s' does not have an associated number",
2573  qPrint(target));
2574  }
2575 }
2576 
2577 //---------------------------------------------------------------------------
2578 
2579 DocLink::DocLink(DocParser &parser,DocNode *parent,const QCString &target) : CompAccept<DocLink>(parser)
2580 {
2581  m_parent = parent;
2582  const Definition *compound = 0;
2583  QCString anchor;
2584  m_refText = target;
2585  m_relPath = parser.context.relPath;
2586  if (!m_refText.isEmpty() && m_refText.at(0)=='#')
2587  {
2589  }
2590  if (resolveLink(parser.context.context,stripKnownExtensions(target),parser.context.inSeeBlock,&compound,anchor))
2591  {
2592  m_anchor = anchor;
2593  if (compound && compound->isLinkable())
2594  {
2595  m_file = compound->getOutputFileBase();
2596  m_ref = compound->getReference();
2597  }
2598  else if (compound && compound->definitionType()==Definition::TypeFile &&
2599  (toFileDef(compound))->generateSourceFile()
2600  ) // undocumented file that has source code we can link to
2601  {
2602  m_file = compound->getSourceFileBase();
2603  m_ref = compound->getReference();
2604  }
2605  return;
2606  }
2607 
2608  // bogus link target
2609  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"unable to resolve link to '%s' for \\link command",
2610  qPrint(target));
2611 }
2612 
2613 
2614 QCString DocLink::parse(bool isJavaLink,bool isXmlLink)
2615 {
2616  QCString result;
2617  auto ns = AutoNodeStack(m_parser,this);
2618  DBG(("DocLink::parse() start\n"));
2619 
2620  int tok;
2621  while ((tok=m_parser.tokenizer.lex()))
2622  {
2624  {
2625  const char *cmd_start = "\\";
2626  switch (tok)
2627  {
2628  case TK_COMMAND_AT:
2629  cmd_start = "@";
2630  // fall through
2631  case TK_COMMAND_BS:
2632  switch (Mappers::cmdMapper->map(m_parser.context.token->name))
2633  {
2634  case CMD_ENDLINK:
2635  if (isJavaLink)
2636  {
2637  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"{@link.. ended with @endlink command");
2638  }
2639  goto endlink;
2640  default:
2641  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Illegal command %s as part of a \\link",
2642  qPrint(cmd_start + m_parser.context.token->name));
2643  break;
2644  }
2645  break;
2646  case TK_SYMBOL:
2647  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unsupported symbol %s found as part of a \\link",
2649  break;
2650  case TK_HTMLTAG:
2651  if (m_parser.context.token->name!="see" || !isXmlLink)
2652  {
2653  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected xml/html command %s found as part of a \\link",
2655  }
2656  goto endlink;
2657  case TK_LNKWORD:
2658  case TK_WORD:
2659  if (isJavaLink) // special case to detect closing }
2660  {
2662  int p;
2663  if (w=="}")
2664  {
2665  goto endlink;
2666  }
2667  else if ((p=w.find('}'))!=-1)
2668  {
2669  uint l=w.length();
2670  m_children.push_back(std::make_unique<DocWord>(m_parser,this,w.left(p)));
2671  if ((uint)p<l-1) // something left after the } (for instance a .)
2672  {
2673  result=w.right((int)l-p-1);
2674  }
2675  goto endlink;
2676  }
2677  }
2678  m_children.push_back(std::make_unique<DocWord>(m_parser,this,m_parser.context.token->name));
2679  break;
2680  default:
2683  break;
2684  }
2685  }
2686  }
2687  if (tok==0)
2688  {
2689  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected end of comment while inside"
2690  " link command\n");
2691  }
2692 endlink:
2693 
2694  if (m_children.empty()) // no link text
2695  {
2696  m_children.push_back(std::make_unique<DocWord>(m_parser,this,m_refText));
2697  }
2698 
2700  DBG(("DocLink::parse() end\n"));
2701  return result;
2702 }
2703 
2704 
2705 //---------------------------------------------------------------------------
2706 
2707 DocDotFile::DocDotFile(DocParser &parser,DocNode *parent,const QCString &name,const QCString &context,
2708  const QCString &srcFile,int srcLine) :
2709  DocDiagramFileBase(parser,name,context,srcFile,srcLine)
2710 {
2711  m_relPath = parser.context.relPath;
2712  m_parent = parent;
2713 }
2714 
2716 {
2717  bool ok = false;
2719 
2720  bool ambig;
2722  if (fd==0 && m_name.right(4)!=".dot") // try with .dot extension as well
2723  {
2725  }
2726  if (fd)
2727  {
2728  m_file = fd->absFilePath();
2729  ok = true;
2730  if (ambig)
2731  {
2732  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"included dot file name %s is ambiguous.\n"
2733  "Possible candidates:\n%s",qPrint(m_name),
2735  );
2736  }
2737  }
2738  else
2739  {
2740  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"included dot file %s is not found "
2741  "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name));
2742  }
2743  return ok;
2744 }
2745 
2746 DocMscFile::DocMscFile(DocParser &parser,DocNode *parent,const QCString &name,const QCString &context,
2747  const QCString &srcFile, int srcLine) :
2748  DocDiagramFileBase(parser,name,context,srcFile,srcLine)
2749 {
2750  m_relPath = parser.context.relPath;
2751  m_parent = parent;
2752 }
2753 
2755 {
2756  bool ok = false;
2758 
2759  bool ambig;
2761  if (fd==0 && m_name.right(4)!=".msc") // try with .msc extension as well
2762  {
2764  }
2765  if (fd)
2766  {
2767  m_file = fd->absFilePath();
2768  ok = true;
2769  if (ambig)
2770  {
2771  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"included msc file name %s is ambiguous.\n"
2772  "Possible candidates:\n%s",qPrint(m_name),
2774  );
2775  }
2776  }
2777  else
2778  {
2779  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"included msc file %s is not found "
2780  "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name));
2781  }
2782  return ok;
2783 }
2784 
2785 //---------------------------------------------------------------------------
2786 
2787 DocDiaFile::DocDiaFile(DocParser &parser,DocNode *parent,const QCString &name,const QCString &context,
2788  const QCString &srcFile,int srcLine) :
2789  DocDiagramFileBase(parser,name,context,srcFile,srcLine)
2790 {
2791  m_relPath = parser.context.relPath;
2792  m_parent = parent;
2793 }
2794 
2796 {
2797  bool ok = false;
2799 
2800  bool ambig;
2802  if (fd==0 && m_name.right(4)!=".dia") // try with .dia extension as well
2803  {
2805  }
2806  if (fd)
2807  {
2808  m_file = fd->absFilePath();
2809  ok = true;
2810  if (ambig)
2811  {
2812  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"included dia file name %s is ambiguous.\n"
2813  "Possible candidates:\n%s",qPrint(m_name),
2815  );
2816  }
2817  }
2818  else
2819  {
2820  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"included dia file %s is not found "
2821  "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name));
2822  }
2823  return ok;
2824 }
2825 
2826 //---------------------------------------------------------------------------
2827 
2829 {
2830  m_parent = parent;
2831 }
2832 
2834 {
2835  auto ns = AutoNodeStack(m_parser,this);
2836  DBG(("DocVhdlFlow::parse() start\n"));
2837 
2839  int tok;
2840  while ((tok=m_parser.tokenizer.lex()))
2841  {
2842  if (!m_parser.defaultHandleToken(this,tok,m_children))
2843  {
2844  m_parser.errorHandleDefaultToken(this,tok,m_children,"\\vhdlflow");
2845  }
2846  }
2847  tok=m_parser.tokenizer.lex();
2848 
2851 
2852  DBG(("DocVhdlFlow::parse() end\n"));
2854 }
2855 
2856 
2857 //---------------------------------------------------------------------------
2858 
2859 DocImage::DocImage(DocParser &parser,DocNode *parent,const HtmlAttribList &attribs,const QCString &name,
2860  Type t,const QCString &url, bool inlineImage) :
2861  CompAccept<DocImage>(parser), m_attribs(attribs), m_name(name),
2862  m_type(t), m_relPath(parser.context.relPath),
2863  m_url(url), m_inlineImage(inlineImage)
2864 {
2865  m_parent = parent;
2866 }
2867 
2868 bool DocImage::isSVG() const
2869 {
2870  QCString locName = m_url.isEmpty() ? m_name : m_url;
2871  int len = (int)locName.length();
2872  int fnd = locName.find('?'); // ignore part from ? until end
2873  if (fnd==-1) fnd=len;
2874  return fnd>=4 && locName.mid(fnd-4,4)==".svg";
2875 }
2876 
2878 {
2880 }
2881 
2882 
2883 //---------------------------------------------------------------------------
2884 
2886 {
2887  int retval=RetVal_OK;
2888  auto ns = AutoNodeStack(m_parser,this);
2889  DBG(("DocHtmlHeader::parse() start\n"));
2890 
2891  int tok;
2892  while ((tok=m_parser.tokenizer.lex()))
2893  {
2894  if (!m_parser.defaultHandleToken(this,tok,m_children))
2895  {
2896  switch (tok)
2897  {
2898  case TK_HTMLTAG:
2899  {
2901  if (tagId==HTML_H1 && m_parser.context.token->endTag) // found </h1> tag
2902  {
2903  if (m_level!=1)
2904  {
2905  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"<h%d> ended with </h1>",
2906  m_level);
2907  }
2908  goto endheader;
2909  }
2910  else if (tagId==HTML_H2 && m_parser.context.token->endTag) // found </h2> tag
2911  {
2912  if (m_level!=2)
2913  {
2914  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"<h%d> ended with </h2>",
2915  m_level);
2916  }
2917  goto endheader;
2918  }
2919  else if (tagId==HTML_H3 && m_parser.context.token->endTag) // found </h3> tag
2920  {
2921  if (m_level!=3)
2922  {
2923  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"<h%d> ended with </h3>",
2924  m_level);
2925  }
2926  goto endheader;
2927  }
2928  else if (tagId==HTML_H4 && m_parser.context.token->endTag) // found </h4> tag
2929  {
2930  if (m_level!=4)
2931  {
2932  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"<h%d> ended with </h4>",
2933  m_level);
2934  }
2935  goto endheader;
2936  }
2937  else if (tagId==HTML_H5 && m_parser.context.token->endTag) // found </h5> tag
2938  {
2939  if (m_level!=5)
2940  {
2941  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"<h%d> ended with </h5>",
2942  m_level);
2943  }
2944  goto endheader;
2945  }
2946  else if (tagId==HTML_H6 && m_parser.context.token->endTag) // found </h6> tag
2947  {
2948  if (m_level!=6)
2949  {
2950  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"<h%d> ended with </h6>",
2951  m_level);
2952  }
2953  goto endheader;
2954  }
2955  else if (tagId==HTML_A)
2956  {
2957  if (!m_parser.context.token->endTag)
2958  {
2960  }
2961  }
2962  else if (tagId==HTML_BR)
2963  {
2964  m_children.push_back(std::make_unique<DocLineBreak>(m_parser,this,m_parser.context.token->attribs));
2965  }
2966  else
2967  {
2968  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected html tag <%s%s> found within <h%d> context",
2970  }
2971  }
2972  break;
2973  default:
2974  char tmp[20];
2975  sprintf(tmp,"<h%d>tag",m_level);
2977  }
2978  }
2979  }
2980  if (tok==0)
2981  {
2982  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected end of comment while inside"
2983  " <h%d> tag\n",m_level);
2984  }
2985 endheader:
2987  DBG(("DocHtmlHeader::parse() end\n"));
2988  return retval;
2989 }
2990 
2991 //---------------------------------------------------------------------------
2992 
2994 {
2995  int retval=RetVal_OK;
2996  auto ns = AutoNodeStack(m_parser,this);
2997  DBG(("DocHRef::parse() start\n"));
2998 
2999  int tok;
3000  while ((tok=m_parser.tokenizer.lex()))
3001  {
3002  if (!m_parser.defaultHandleToken(this,tok,m_children))
3003  {
3004  switch (tok)
3005  {
3006  case TK_HTMLTAG:
3007  {
3009  if (tagId==HTML_A && m_parser.context.token->endTag) // found </a> tag
3010  {
3011  goto endhref;
3012  }
3013  else if (tagId==HTML_BR)
3014  {
3015  m_children.push_back(std::make_unique<DocLineBreak>(m_parser,this,m_parser.context.token->attribs));
3016  }
3017  else
3018  {
3019  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected html tag <%s%s> found within <a href=...> context",
3021  }
3022  }
3023  break;
3024  default:
3025  m_parser.errorHandleDefaultToken(this,tok,m_children,"<a>..</a> block");
3026  break;
3027  }
3028  }
3029  }
3030  if (tok==0)
3031  {
3032  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected end of comment while inside"
3033  " <a href=...> tag");
3034  }
3035 endhref:
3037  DBG(("DocHRef::parse() end\n"));
3038  return retval;
3039 }
3040 
3041 //---------------------------------------------------------------------------
3042 
3043 int DocInternal::parse(int level)
3044 {
3045  int retval=RetVal_OK;
3046  auto ns = AutoNodeStack(m_parser,this);
3047  DBG(("DocInternal::parse() start\n"));
3048 
3049  // first parse any number of paragraphs
3050  bool isFirst=TRUE;
3051  DocPara *lastPar=0;
3052  do
3053  {
3054  DocPara *par = new DocPara(m_parser,this);
3055  if (isFirst) { par->markFirst(); isFirst=FALSE; }
3056  retval=par->parse();
3057  if (!par->isEmpty())
3058  {
3059  m_children.push_back(std::unique_ptr<DocPara>(par));
3060  lastPar=par;
3061  }
3062  else
3063  {
3064  delete par;
3065  }
3066  if (retval==TK_LISTITEM)
3067  {
3068  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Invalid list item found");
3069  }
3070  } while (retval!=0 &&
3071  retval!=RetVal_Section &&
3072  retval!=RetVal_Subsection &&
3073  retval!=RetVal_Subsubsection &&
3074  retval!=RetVal_Paragraph &&
3075  retval!=RetVal_EndInternal
3076  );
3077  if (lastPar) lastPar->markLast();
3078 
3079  // then parse any number of level-n sections
3080  while ((level==1 && retval==RetVal_Section) ||
3081  (level==2 && retval==RetVal_Subsection) ||
3082  (level==3 && retval==RetVal_Subsubsection) ||
3083  (level==4 && retval==RetVal_Paragraph)
3084  )
3085  {
3086  DocSection *s=new DocSection(m_parser,this,
3088  m_children.push_back(std::unique_ptr<DocSection>(s));
3089  retval = s->parse();
3090  }
3091 
3092  if (retval==RetVal_Internal)
3093  {
3094  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"\\internal command found inside internal section");
3095  }
3096 
3097  DBG(("DocInternal::parse() end: retval=%s\n",DocTokenizer::retvalToString(retval)));
3098  return retval;
3099 }
3100 
3101 //---------------------------------------------------------------------------
3102 
3104 {
3105  int retval=RetVal_OK;
3106  auto ns = AutoNodeStack(m_parser,this);
3107  DBG(("DocIndexEntry::parse() start\n"));
3108  int tok=m_parser.tokenizer.lex();
3109  if (tok!=TK_WHITESPACE)
3110  {
3111  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\addindex command");
3112  goto endindexentry;
3113  }
3115  m_entry="";
3116  while ((tok=m_parser.tokenizer.lex()))
3117  {
3118  switch (tok)
3119  {
3120  case TK_WHITESPACE:
3121  m_entry+=" ";
3122  break;
3123  case TK_WORD:
3124  case TK_LNKWORD:
3126  break;
3127  case TK_SYMBOL:
3128  {
3130  switch (s)
3131  {
3132  case DocSymbol::Sym_BSlash: m_entry+='\\'; break;
3133  case DocSymbol::Sym_At: m_entry+='@'; break;
3134  case DocSymbol::Sym_Less: m_entry+='<'; break;
3135  case DocSymbol::Sym_Greater: m_entry+='>'; break;
3136  case DocSymbol::Sym_Amp: m_entry+='&'; break;
3137  case DocSymbol::Sym_Dollar: m_entry+='$'; break;
3138  case DocSymbol::Sym_Hash: m_entry+='#'; break;
3139  case DocSymbol::Sym_Percent: m_entry+='%'; break;
3140  case DocSymbol::Sym_apos: m_entry+='\''; break;
3141  case DocSymbol::Sym_Quot: m_entry+='"'; break;
3142  case DocSymbol::Sym_lsquo: m_entry+='`'; break;
3143  case DocSymbol::Sym_rsquo: m_entry+='\''; break;
3144  case DocSymbol::Sym_ldquo: m_entry+="``"; break;
3145  case DocSymbol::Sym_rdquo: m_entry+="''"; break;
3146  case DocSymbol::Sym_ndash: m_entry+="--"; break;
3147  case DocSymbol::Sym_mdash: m_entry+="---"; break;
3148  default:
3149  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected symbol found as argument of \\addindex");
3150  break;
3151  }
3152  }
3153  break;
3154  case TK_COMMAND_AT:
3155  // fall through
3156  case TK_COMMAND_BS:
3157  switch (Mappers::cmdMapper->map(m_parser.context.token->name))
3158  {
3159  case CMD_BSLASH: m_entry+='\\'; break;
3160  case CMD_AT: m_entry+='@'; break;
3161  case CMD_LESS: m_entry+='<'; break;
3162  case CMD_GREATER: m_entry+='>'; break;
3163  case CMD_AMP: m_entry+='&'; break;
3164  case CMD_DOLLAR: m_entry+='$'; break;
3165  case CMD_HASH: m_entry+='#'; break;
3166  case CMD_DCOLON: m_entry+="::"; break;
3167  case CMD_PERCENT: m_entry+='%'; break;
3168  case CMD_NDASH: m_entry+="--"; break;
3169  case CMD_MDASH: m_entry+="---"; break;
3170  case CMD_QUOTE: m_entry+='"'; break;
3171  case CMD_PUNT: m_entry+='.'; break;
3172  case CMD_PLUS: m_entry+='+'; break;
3173  case CMD_MINUS: m_entry+='-'; break;
3174  case CMD_EQUAL: m_entry+='='; break;
3175  default:
3176  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected command %s found as argument of \\addindex",
3178  break;
3179  }
3180  break;
3181  default:
3184  break;
3185  }
3186  }
3189 endindexentry:
3190  DBG(("DocIndexEntry::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
3191  return retval;
3192 }
3193 
3194 //---------------------------------------------------------------------------
3195 
3197  : CompAccept<DocHtmlCaption>(parser)
3198 {
3200  for (const auto &opt : attribs)
3201  {
3202  if (opt.name=="id" && !opt.value.isEmpty()) // interpret id attribute as an anchor
3203  {
3204  const SectionInfo *sec = SectionManager::instance().find(opt.value);
3205  if (sec)
3206  {
3207  //printf("Found anchor %s\n",qPrint(id));
3208  m_file = sec->fileName();
3209  m_anchor = sec->label();
3210  m_hasCaptionId = TRUE;
3211  }
3212  else
3213  {
3214  warn_doc_error(parser.context.fileName,parser.tokenizer.getLineNr(),"Invalid caption id '%s'",qPrint(opt.value));
3215  }
3216  }
3217  else // copy attribute
3218  {
3219  m_attribs.push_back(opt);
3220  }
3221  }
3222  m_parent = parent;
3223 }
3224 
3226 {
3227  int retval=0;
3228  auto ns = AutoNodeStack(m_parser,this);
3229  DBG(("DocHtmlCaption::parse() start\n"));
3230  int tok;
3231  while ((tok=m_parser.tokenizer.lex()))
3232  {
3233  if (!m_parser.defaultHandleToken(this,tok,m_children))
3234  {
3235  switch (tok)
3236  {
3237  case TK_HTMLTAG:
3238  {
3240  if (tagId==HTML_CAPTION && m_parser.context.token->endTag) // found </caption> tag
3241  {
3242  retval = RetVal_OK;
3243  goto endcaption;
3244  }
3245  else
3246  {
3247  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected html tag <%s%s> found within <caption> context",
3249  }
3250  }
3251  break;
3252  default:
3253  m_parser.errorHandleDefaultToken(this,tok,m_children,"<caption> tag");
3254  break;
3255  }
3256  }
3257  }
3258  if (tok==0)
3259  {
3260  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected end of comment while inside"
3261  " <caption> tag");
3262  }
3263 endcaption:
3265  DBG(("DocHtmlCaption::parse() end\n"));
3266  return retval;
3267 }
3268 
3269 //---------------------------------------------------------------------------
3270 
3272 {
3273  int retval=RetVal_OK;
3274  auto ns = AutoNodeStack(m_parser,this);
3275  DBG(("DocHtmlCell::parse() start\n"));
3276 
3277  // parse one or more paragraphs
3278  bool isFirst=TRUE;
3279  DocPara *par=0;
3280  do
3281  {
3282  par = new DocPara(m_parser,this);
3283  if (isFirst) { par->markFirst(); isFirst=FALSE; }
3284  m_children.push_back(std::unique_ptr<DocPara>(par));
3285  retval=par->parse();
3286  if (retval==TK_HTMLTAG)
3287  {
3289  if (tagId==HTML_TD && m_parser.context.token->endTag) // found </td> tag
3290  {
3291  retval=TK_NEWPARA; // ignore the tag
3292  }
3293  else if (tagId==HTML_TH && m_parser.context.token->endTag) // found </th> tag
3294  {
3295  retval=TK_NEWPARA; // ignore the tag
3296  }
3297  }
3298  }
3299  while ((retval==TK_NEWPARA) || (retval==RetVal_EndParBlock));
3300  if (par) par->markLast();
3301 
3302  DBG(("DocHtmlCell::parse() end\n"));
3303  return retval;
3304 }
3305 
3307 {
3308  int retval=RetVal_OK;
3309  auto ns = AutoNodeStack(m_parser,this);
3310  DBG(("DocHtmlCell::parseXml() start\n"));
3311 
3312  // parse one or more paragraphs
3313  bool isFirst=TRUE;
3314  DocPara *par=0;
3315  do
3316  {
3317  par = new DocPara(m_parser,this);
3318  if (isFirst) { par->markFirst(); isFirst=FALSE; }
3319  m_children.push_back(std::unique_ptr<DocPara>(par));
3320  retval=par->parse();
3321  if (retval==TK_HTMLTAG)
3322  {
3324  if (tagId==XML_ITEM && m_parser.context.token->endTag) // found </item> tag
3325  {
3326  retval=TK_NEWPARA; // ignore the tag
3327  }
3328  else if (tagId==XML_DESCRIPTION && m_parser.context.token->endTag) // found </description> tag
3329  {
3330  retval=TK_NEWPARA; // ignore the tag
3331  }
3332  }
3333  }
3334  while (retval==TK_NEWPARA);
3335  if (par) par->markLast();
3336 
3337  DBG(("DocHtmlCell::parseXml() end\n"));
3338  return retval;
3339 }
3340 
3342 {
3343  for (const auto &attr : attribs())
3344  {
3345  if (attr.name.lower()=="rowspan")
3346  {
3347  return attr.value.toUInt();
3348  }
3349  }
3350  return 0;
3351 }
3352 
3354 {
3355  for (const auto &attr : attribs())
3356  {
3357  if (attr.name.lower()=="colspan")
3358  {
3359  return std::max(1u,attr.value.toUInt());
3360  }
3361  }
3362  return 1;
3363 }
3364 
3366 {
3367  for (const auto &attr : attribs())
3368  {
3369  QCString attrName = attr.name.lower();
3370  QCString attrValue = attr.value.lower();
3371  if (attrName=="align")
3372  {
3373  if (attrValue=="center")
3374  return Center;
3375  else if (attrValue=="right")
3376  return Right;
3377  else return Left;
3378  }
3379  else if (attrName=="class" && attrValue.startsWith("markdowntable"))
3380  {
3381  if (attrValue=="markdowntableheadcenter")
3382  return Center;
3383  else if (attrValue=="markdowntableheadright")
3384  return Right;
3385  else if (attrValue=="markdowntableheadleft")
3386  return Left;
3387  else if (attrValue=="markdowntableheadnone")
3388  return Center;
3389  else if (attrValue=="markdowntablebodycenter")
3390  return Center;
3391  else if (attrValue=="markdowntablebodyright")
3392  return Right;
3393  else if (attrValue=="markdowntablebodyleft")
3394  return Left;
3395  else if (attrValue=="markdowntablebodynone")
3396  return Left;
3397  else return Left;
3398  }
3399  }
3400  return Left;
3401 }
3402 
3404 {
3405  for (const auto &attr : attribs())
3406  {
3407  QCString attrName = attr.name.lower();
3408  QCString attrValue = attr.value.lower();
3409  if (attrName=="valign")
3410  {
3411  if (attrValue=="top")
3412  return Top;
3413  else if (attrValue=="bottom")
3414  return Bottom;
3415  else if (attrValue=="middle")
3416  return Middle;
3417  else return Middle;
3418  }
3419  }
3420  return Middle;
3421 }
3422 
3423 //---------------------------------------------------------------------------
3424 
3426 {
3427  int retval=RetVal_OK;
3428  auto ns = AutoNodeStack(m_parser,this);
3429  DBG(("DocHtmlRow::parse() start\n"));
3430 
3431  bool isHeading=FALSE;
3432  bool isFirst=TRUE;
3433  DocHtmlCell *cell=0;
3434 
3435  // get next token
3436  int tok=m_parser.tokenizer.lex();
3437  // skip whitespace
3438  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
3439  // should find a html tag now
3440  if (tok==TK_HTMLTAG)
3441  {
3443  if (tagId==HTML_TD && !m_parser.context.token->endTag) // found <td> tag
3444  {
3445  }
3446  else if (tagId==HTML_TH && !m_parser.context.token->endTag) // found <th> tag
3447  {
3448  isHeading=TRUE;
3449  }
3450  else // found some other tag
3451  {
3452  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <td> or <th> tag but "
3453  "found <%s> instead!",qPrint(m_parser.context.token->name));
3455  goto endrow;
3456  }
3457  }
3458  else if (tok==0) // premature end of comment
3459  {
3460  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while looking"
3461  " for a html description title");
3462  goto endrow;
3463  }
3464  else // token other than html token
3465  {
3466  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <td> or <th> tag but found %s token instead!",
3468  goto endrow;
3469  }
3470 
3471  // parse one or more cells
3472  do
3473  {
3475  cell->markFirst(isFirst);
3476  isFirst=FALSE;
3477  m_children.push_back(std::unique_ptr<DocHtmlCell>(cell));
3478  retval=cell->parse();
3479  isHeading = retval==RetVal_TableHCell;
3480  }
3481  while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
3482  if (cell) cell->markLast(TRUE);
3483 
3484 endrow:
3485  DBG(("DocHtmlRow::parse() end\n"));
3486  return retval;
3487 }
3488 
3489 int DocHtmlRow::parseXml(bool isHeading)
3490 {
3491  int retval=RetVal_OK;
3492  auto ns = AutoNodeStack(m_parser,this);
3493  DBG(("DocHtmlRow::parseXml() start\n"));
3494 
3495  bool isFirst=TRUE;
3496  DocHtmlCell *cell=0;
3497 
3498  // get next token
3499  int tok=m_parser.tokenizer.lex();
3500  // skip whitespace
3501  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
3502  // should find a html tag now
3503  if (tok==TK_HTMLTAG)
3504  {
3506  if (tagId==XML_TERM && !m_parser.context.token->endTag) // found <term> tag
3507  {
3508  }
3509  else if (tagId==XML_DESCRIPTION && !m_parser.context.token->endTag) // found <description> tag
3510  {
3511  }
3512  else // found some other tag
3513  {
3514  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <term> or <description> tag but "
3515  "found <%s> instead!",qPrint(m_parser.context.token->name));
3517  goto endrow;
3518  }
3519  }
3520  else if (tok==0) // premature end of comment
3521  {
3522  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while looking"
3523  " for a html description title");
3524  goto endrow;
3525  }
3526  else // token other than html token
3527  {
3528  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <td> or <th> tag but found %s token instead!",
3530  goto endrow;
3531  }
3532 
3533  do
3534  {
3536  cell->markFirst(isFirst);
3537  isFirst=FALSE;
3538  m_children.push_back(std::unique_ptr<DocHtmlCell>(cell));
3539  retval=cell->parseXml();
3540  }
3541  while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
3542  if (cell) cell->markLast(TRUE);
3543 
3544 endrow:
3545  DBG(("DocHtmlRow::parseXml() end\n"));
3546  return retval;
3547 }
3548 
3549 //---------------------------------------------------------------------------
3550 
3552 {
3553  int retval=RetVal_OK;
3554  auto ns = AutoNodeStack(m_parser,this);
3555  DBG(("DocHtmlTable::parse() start\n"));
3556 
3557 getrow:
3558  // get next token
3559  int tok=m_parser.tokenizer.lex();
3560  // skip whitespace
3561  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
3562  // should find a html tag now
3563  if (tok==TK_HTMLTAG)
3564  {
3566  if (tagId==HTML_TR && !m_parser.context.token->endTag) // found <tr> tag
3567  {
3568  // no caption, just rows
3569  retval=RetVal_TableRow;
3570  }
3571  else if (tagId==HTML_CAPTION && !m_parser.context.token->endTag) // found <caption> tag
3572  {
3573  if (m_caption)
3574  {
3575  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"table already has a caption, found another one");
3576  }
3577  else
3578  {
3580  retval=m_caption->parse();
3581 
3582  if (retval==RetVal_OK) // caption was parsed ok
3583  {
3584  goto getrow;
3585  }
3586  }
3587  }
3588  else // found wrong token
3589  {
3590  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <tr> or <caption> tag but "
3591  "found <%s%s> instead!", m_parser.context.token->endTag ? "/" : "", qPrint(m_parser.context.token->name));
3592  }
3593  }
3594  else if (tok==0) // premature end of comment
3595  {
3596  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while looking"
3597  " for a <tr> or <caption> tag");
3598  }
3599  else // token other than html token
3600  {
3601  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <tr> tag but found %s token instead!",
3603  }
3604 
3605  // parse one or more rows
3606  while (retval==RetVal_TableRow)
3607  {
3609  m_children.push_back(std::unique_ptr<DocHtmlRow>(tr));
3610  retval=tr->parse();
3611  }
3612 
3613  computeTableGrid();
3614 
3615  DBG(("DocHtmlTable::parse() end\n"));
3616  return retval==RetVal_EndTable ? RetVal_OK : retval;
3617 }
3618 
3620 {
3621  int retval=RetVal_OK;
3622  auto ns = AutoNodeStack(m_parser,this);
3623  DBG(("DocHtmlTable::parseXml() start\n"));
3624 
3625  // get next token
3626  int tok=m_parser.tokenizer.lex();
3627  // skip whitespace
3628  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
3629  // should find a html tag now
3630  int tagId=0;
3631  bool isHeader=FALSE;
3632  if (tok==TK_HTMLTAG)
3633  {
3635  if (tagId==XML_ITEM && !m_parser.context.token->endTag) // found <item> tag
3636  {
3637  retval=RetVal_TableRow;
3638  }
3639  if (tagId==XML_LISTHEADER && !m_parser.context.token->endTag) // found <listheader> tag
3640  {
3641  retval=RetVal_TableRow;
3642  isHeader=TRUE;
3643  }
3644  }
3645 
3646  // parse one or more rows
3647  while (retval==RetVal_TableRow)
3648  {
3650  m_children.push_back(std::unique_ptr<DocHtmlRow>(tr));
3651  retval=tr->parseXml(isHeader);
3652  isHeader=FALSE;
3653  }
3654 
3655  computeTableGrid();
3656 
3657  DBG(("DocHtmlTable::parseXml() end\n"));
3659  return tagId==XML_LIST && m_parser.context.token->endTag ? RetVal_OK : retval;
3660 }
3661 
3662 /** Helper class to compute the grid for an HTML style table */
3664 {
3665  ActiveRowSpan(uint rows,uint col) : rowsLeft(rows), column(col) {}
3668 };
3669 
3670 /** List of ActiveRowSpan classes. */
3671 typedef std::vector<ActiveRowSpan> RowSpanList;
3672 
3673 /** determines the location of all cells in a grid, resolving row and
3674  column spans. For each the total number of visible cells is computed,
3675  and the total number of visible columns over all rows is stored.
3676  */
3678 {
3679  //printf("computeTableGrid()\n");
3680  RowSpanList rowSpans;
3681  uint maxCols=0;
3682  uint rowIdx=1;
3683  for (const auto &rowNode : children())
3684  {
3685  uint colIdx=1;
3686  uint cells=0;
3687  if (rowNode->kind()==DocNode::Kind_HtmlRow)
3688  {
3689  size_t i;
3690  DocHtmlRow *row = (DocHtmlRow*)rowNode.get();
3691  for (const auto &cellNode : row->children())
3692  {
3693  if (cellNode->kind()==DocNode::Kind_HtmlCell)
3694  {
3695  DocHtmlCell *cell = (DocHtmlCell*)cellNode.get();
3696  uint rs = cell->rowSpan();
3697  uint cs = cell->colSpan();
3698 
3699  for (i=0;i<rowSpans.size();i++)
3700  {
3701  if (rowSpans[i].rowsLeft>0 &&
3702  rowSpans[i].column==colIdx)
3703  {
3704  colIdx=rowSpans[i].column+1;
3705  cells++;
3706  }
3707  }
3708  if (rs>0) rowSpans.emplace_back(rs,colIdx);
3709  //printf("found cell at (%d,%d)\n",rowIdx,colIdx);
3710  cell->setRowIndex(rowIdx);
3711  cell->setColumnIndex(colIdx);
3712  colIdx+=cs;
3713  cells++;
3714  }
3715  }
3716  for (i=0;i<rowSpans.size();i++)
3717  {
3718  if (rowSpans[i].rowsLeft>0) rowSpans[i].rowsLeft--;
3719  }
3720  row->setVisibleCells(cells);
3721  row->setRowIndex(rowIdx);
3722  rowIdx++;
3723  }
3724  if (colIdx-1>maxCols) maxCols=colIdx-1;
3725  }
3726  m_numCols = maxCols;
3727 }
3728 
3730 {
3731  v->visitPre(this);
3732  // for HTML output we put the caption first
3733  //if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v);
3734  // doxygen 1.8.11: always put the caption first
3735  if (m_caption) m_caption->accept(v);
3736  for (const auto &n : m_children) n->accept(v);
3737  // for other output formats we put the caption last
3738  //if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v);
3739  v->visitPost(this);
3740 }
3741 
3742 //---------------------------------------------------------------------------
3743 
3745 {
3746  int retval=0;
3747  auto ns = AutoNodeStack(m_parser,this);
3748  DBG(("DocHtmlDescTitle::parse() start\n"));
3749 
3750  int tok;
3751  while ((tok=m_parser.tokenizer.lex()))
3752  {
3753  if (!m_parser.defaultHandleToken(this,tok,m_children))
3754  {
3755  const char *cmd_start = "\\";
3756  switch (tok)
3757  {
3758  case TK_COMMAND_AT:
3759  cmd_start = "@";
3760  // fall through
3761  case TK_COMMAND_BS:
3762  {
3763  QCString cmdName=m_parser.context.token->name;
3764  bool isJavaLink=FALSE;
3765  switch (Mappers::cmdMapper->map(cmdName))
3766  {
3767  case CMD_REF:
3768  {
3769  tok=m_parser.tokenizer.lex();
3770  if (tok!=TK_WHITESPACE)
3771  {
3772  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
3774  }
3775  else
3776  {
3778  tok=m_parser.tokenizer.lex(); // get the reference id
3779  if (tok!=TK_WORD)
3780  {
3781  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of \\%s command",
3782  DocTokenizer::tokToString(tok),qPrint(cmdName));
3783  }
3784  else
3785  {
3787  m_children.push_back(std::unique_ptr<DocRef>(ref));
3788  ref->parse();
3789  }
3791  }
3792  }
3793  break;
3794  case CMD_JAVALINK:
3795  isJavaLink=TRUE;
3796  // fall through
3797  case CMD_LINK:
3798  {
3799  tok=m_parser.tokenizer.lex();
3800  if (tok!=TK_WHITESPACE)
3801  {
3802  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
3803  qPrint(cmdName));
3804  }
3805  else
3806  {
3808  tok=m_parser.tokenizer.lex();
3809  if (tok!=TK_WORD)
3810  {
3811  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of \\%s command",
3812  DocTokenizer::tokToString(tok),qPrint(cmdName));
3813  }
3814  else
3815  {
3817  DocLink *lnk = new DocLink(m_parser,this,m_parser.context.token->name);
3818  m_children.push_back(std::unique_ptr<DocLink>(lnk));
3819  QCString leftOver = lnk->parse(isJavaLink);
3820  if (!leftOver.isEmpty())
3821  {
3822  m_children.push_back(std::make_unique<DocWord>(m_parser,this,leftOver));
3823  }
3824  }
3825  }
3826  }
3827 
3828  break;
3829  default:
3830  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Illegal command %s found as part of a <dt> tag",
3831  qPrint(cmd_start + m_parser.context.token->name));
3832  }
3833  }
3834  break;
3835  case TK_SYMBOL:
3836  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unsupported symbol \\%s found as part of a <dt> tag",
3838  break;
3839  case TK_HTMLTAG:
3840  {
3842  if (tagId==HTML_DD && !m_parser.context.token->endTag) // found <dd> tag
3843  {
3844  retval = RetVal_DescData;
3845  goto endtitle;
3846  }
3847  else if (tagId==HTML_DT && m_parser.context.token->endTag)
3848  {
3849  // ignore </dt> tag.
3850  }
3851  else if (tagId==HTML_DT)
3852  {
3853  // missing <dt> tag.
3854  retval = RetVal_DescTitle;
3855  goto endtitle;
3856  }
3857  else if (tagId==HTML_DL && m_parser.context.token->endTag)
3858  {
3859  retval=RetVal_EndDesc;
3860  goto endtitle;
3861  }
3862  else if (tagId==HTML_A)
3863  {
3864  if (!m_parser.context.token->endTag)
3865  {
3867  }
3868  }
3869  else
3870  {
3871  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected html tag <%s%s> found within <dt> context",
3873  }
3874  }
3875  break;
3876  default:
3877  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected token %s found as part of a <dt> tag",
3879  break;
3880  }
3881  }
3882  }
3883  if (tok==0)
3884  {
3885  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected end of comment while inside"
3886  " <dt> tag");
3887  }
3888 endtitle:
3890  DBG(("DocHtmlDescTitle::parse() end\n"));
3891  return retval;
3892 }
3893 
3894 //---------------------------------------------------------------------------
3895 
3897 {
3899  int retval=0;
3900  auto ns = AutoNodeStack(m_parser,this);
3901  DBG(("DocHtmlDescData::parse() start\n"));
3902 
3903  bool isFirst=TRUE;
3904  DocPara *par=0;
3905  do
3906  {
3907  par = new DocPara(m_parser,this);
3908  if (isFirst) { par->markFirst(); isFirst=FALSE; }
3909  m_children.push_back(std::unique_ptr<DocPara>(par));
3910  retval=par->parse();
3911  }
3912  while (retval==TK_NEWPARA);
3913  if (par) par->markLast();
3914 
3915  DBG(("DocHtmlDescData::parse() end\n"));
3916  return retval;
3917 }
3918 
3919 //---------------------------------------------------------------------------
3920 
3922 {
3923  int retval=RetVal_OK;
3924  auto ns = AutoNodeStack(m_parser,this);
3925  DBG(("DocHtmlDescList::parse() start\n"));
3926 
3927  // get next token
3928  int tok=m_parser.tokenizer.lex();
3929  // skip whitespace
3930  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
3931  // should find a html tag now
3932  if (tok==TK_HTMLTAG)
3933  {
3935  if (tagId==HTML_DT && !m_parser.context.token->endTag) // found <dt> tag
3936  {
3937  // continue
3938  }
3939  else // found some other tag
3940  {
3942  "found <%s> instead!",qPrint(m_parser.context.token->name));
3944  goto enddesclist;
3945  }
3946  }
3947  else if (tok==0) // premature end of comment
3948  {
3949  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while looking"
3950  " for a html description title");
3951  goto enddesclist;
3952  }
3953  else // token other than html token
3954  {
3955  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <dt> tag but found %s token instead!",
3957  goto enddesclist;
3958  }
3959 
3960  do
3961  {
3963  m_children.push_back(std::unique_ptr<DocHtmlDescTitle>(dt));
3965  m_children.push_back(std::unique_ptr<DocHtmlDescData>(dd));
3966  retval=dt->parse();
3967  if (retval==RetVal_DescData)
3968  {
3969  retval=dd->parse();
3970  }
3971  else if (retval!=RetVal_DescTitle)
3972  {
3973  // error
3974  break;
3975  }
3976  } while (retval==RetVal_DescTitle);
3977 
3978  if (retval==0)
3979  {
3980  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while inside <dl> block");
3981  }
3982 
3983 enddesclist:
3984 
3985  DBG(("DocHtmlDescList::parse() end\n"));
3986  return retval==RetVal_EndDesc ? RetVal_OK : retval;
3987 }
3988 
3989 //---------------------------------------------------------------------------
3990 
3992 {
3993  DBG(("DocHtmlListItem::parse() start\n"));
3994  int retval=0;
3995  auto ns = AutoNodeStack(m_parser,this);
3996 
3997  // parse one or more paragraphs
3998  bool isFirst=TRUE;
3999  DocPara *par=0;
4000  do
4001  {
4002  par = new DocPara(m_parser,this);
4003  if (isFirst) { par->markFirst(); isFirst=FALSE; }
4004  m_children.push_back(std::unique_ptr<DocPara>(par));
4005  retval=par->parse();
4006  }
4007  while (retval==TK_NEWPARA);
4008  if (par) par->markLast();
4009 
4010  DBG(("DocHtmlListItem::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
4011  return retval;
4012 }
4013 
4015 {
4016  DBG(("DocHtmlListItem::parseXml() start\n"));
4017  int retval=0;
4018  auto ns = AutoNodeStack(m_parser,this);
4019 
4020  // parse one or more paragraphs
4021  bool isFirst=TRUE;
4022  DocPara *par=0;
4023  do
4024  {
4025  par = new DocPara(m_parser,this);
4026  if (isFirst) { par->markFirst(); isFirst=FALSE; }
4027  m_children.push_back(std::unique_ptr<DocPara>(par));
4028  retval=par->parse();
4029  if (retval==0) break;
4030 
4031  //printf("new item: retval=%x m_parser.context.token->name=%s m_parser.context.token->endTag=%d\n",
4032  // retval,qPrint(m_parser.context.token->name),m_parser.context.token->endTag);
4033  if (retval==RetVal_ListItem)
4034  {
4035  break;
4036  }
4037  }
4038  while (retval!=RetVal_CloseXml);
4039 
4040  if (par) par->markLast();
4041 
4042  DBG(("DocHtmlListItem::parseXml() end retval=%s\n",DocTokenizer::retvalToString(retval)));
4043  return retval;
4044 }
4045 
4046 //---------------------------------------------------------------------------
4047 
4049 {
4050  DBG(("DocHtmlList::parse() start\n"));
4051  int retval=RetVal_OK;
4052  int num=1;
4053  auto ns = AutoNodeStack(m_parser,this);
4054 
4055  // get next token
4056  int tok=m_parser.tokenizer.lex();
4057  // skip whitespace and paragraph breaks
4058  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
4059  // should find a html tag now
4060  if (tok==TK_HTMLTAG)
4061  {
4063  if (tagId==HTML_LI && !m_parser.context.token->endTag) // found <li> tag
4064  {
4065  // ok, we can go on.
4066  }
4067  else if (((m_type==Unordered && tagId==HTML_UL) ||
4068  (m_type==Ordered && tagId==HTML_OL)
4070  ) // found empty list
4071  {
4072  // add dummy item to obtain valid HTML
4073  m_children.push_back(std::make_unique<DocHtmlListItem>(m_parser,this,HtmlAttribList(),1));
4075  retval = RetVal_EndList;
4076  goto endlist;
4077  }
4078  else // found some other tag
4079  {
4080  // add dummy item to obtain valid HTML
4081  m_children.push_back(std::make_unique<DocHtmlListItem>(m_parser,this,HtmlAttribList(),1));
4083  "found <%s%s> instead!",m_parser.context.token->endTag?"/":"",qPrint(m_parser.context.token->name));
4085  goto endlist;
4086  }
4087  }
4088  else if (tok==0) // premature end of comment
4089  {
4090  // add dummy item to obtain valid HTML
4091  m_children.push_back(std::make_unique<DocHtmlListItem>(m_parser,this,HtmlAttribList(),1));
4092  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while looking"
4093  " for a html list item");
4094  goto endlist;
4095  }
4096  else // token other than html token
4097  {
4098  // add dummy item to obtain valid HTML
4099  m_children.push_back(std::make_unique<DocHtmlListItem>(m_parser,this,HtmlAttribList(),1));
4100  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <li> tag but found %s token instead!",
4102  goto endlist;
4103  }
4104 
4105  do
4106  {
4108  m_children.push_back(std::unique_ptr<DocHtmlListItem>(li));
4109  retval=li->parse();
4110  } while (retval==RetVal_ListItem);
4111 
4112  if (retval==0)
4113  {
4114  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while inside <%cl> block",
4115  m_type==Unordered ? 'u' : 'o');
4116  }
4117 
4118 endlist:
4119  DBG(("DocHtmlList::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
4120  return retval==RetVal_EndList ? RetVal_OK : retval;
4121 }
4122 
4124 {
4125  DBG(("DocHtmlList::parseXml() start\n"));
4126  int retval=RetVal_OK;
4127  int num=1;
4128  auto ns = AutoNodeStack(m_parser,this);
4129 
4130  // get next token
4131  int tok=m_parser.tokenizer.lex();
4132  // skip whitespace and paragraph breaks
4133  while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=m_parser.tokenizer.lex();
4134  // should find a html tag now
4135  if (tok==TK_HTMLTAG)
4136  {
4138  //printf("m_parser.context.token->name=%s m_parser.context.token->endTag=%d\n",qPrint(m_parser.context.token->name),m_parser.context.token->endTag);
4139  if (tagId==XML_ITEM && !m_parser.context.token->endTag) // found <item> tag
4140  {
4141  // ok, we can go on.
4142  }
4143  else // found some other tag
4144  {
4145  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <item> tag but "
4146  "found <%s> instead!",qPrint(m_parser.context.token->name));
4148  goto endlist;
4149  }
4150  }
4151  else if (tok==0) // premature end of comment
4152  {
4153  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while looking"
4154  " for a html list item");
4155  goto endlist;
4156  }
4157  else // token other than html token
4158  {
4159  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected <item> tag but found %s token instead!",
4161  goto endlist;
4162  }
4163 
4164  do
4165  {
4167  m_children.push_back(std::unique_ptr<DocHtmlListItem>(li));
4168  retval=li->parseXml();
4169  if (retval==0) break;
4170  //printf("retval=%x m_parser.context.token->name=%s\n",retval,qPrint(m_parser.context.token->name));
4171  } while (retval==RetVal_ListItem);
4172 
4173  if (retval==0)
4174  {
4175  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment while inside <list type=\"%s\"> block",
4176  m_type==Unordered ? "bullet" : "number");
4177  }
4178 
4179 endlist:
4180  DBG(("DocHtmlList::parseXml() end retval=%s\n",DocTokenizer::retvalToString(retval)));
4181  return retval==RetVal_EndList ||
4182  (retval==RetVal_CloseXml || m_parser.context.token->name=="list") ?
4183  RetVal_OK : retval;
4184 }
4185 
4186 //--------------------------------------------------------------------------
4187 
4189 {
4190  DBG(("DocHtmlBlockQuote::parse() start\n"));
4191  int retval=0;
4192  auto ns = AutoNodeStack(m_parser,this);
4193 
4194  // parse one or more paragraphs
4195  bool isFirst=TRUE;
4196  DocPara *par=0;
4197  do
4198  {
4199  par = new DocPara(m_parser,this);
4200  if (isFirst) { par->markFirst(); isFirst=FALSE; }
4201  m_children.push_back(std::unique_ptr<DocPara>(par));
4202  retval=par->parse();
4203  }
4204  while (retval==TK_NEWPARA);
4205  if (par) par->markLast();
4206 
4207  DBG(("DocHtmlBlockQuote::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
4208  return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
4209 }
4210 
4211 //---------------------------------------------------------------------------
4212 
4214 {
4215  DBG(("DocParBlock::parse() start\n"));
4216  int retval=0;
4217  auto ns = AutoNodeStack(m_parser,this);
4218 
4219  // parse one or more paragraphs
4220  bool isFirst=TRUE;
4221  DocPara *par=0;
4222  do
4223  {
4224  par = new DocPara(m_parser,this);
4225  if (isFirst) { par->markFirst(); isFirst=FALSE; }
4226  m_children.push_back(std::unique_ptr<DocPara>(par));
4227  retval=par->parse();
4228  }
4229  while (retval==TK_NEWPARA);
4230  if (par) par->markLast();
4231 
4232  DBG(("DocParBlock::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
4233  return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
4234 }
4235 
4236 //---------------------------------------------------------------------------
4237 
4239 {
4240  auto ns = AutoNodeStack(m_parser,this);
4241  int rv=m_paragraph->parse();
4243  m_paragraph->markLast();
4244  return rv;
4245 }
4246 
4247 //--------------------------------------------------------------------------
4248 
4250 {
4251  auto ns = AutoNodeStack(m_parser,this);
4252  int rv;
4253  do
4254  {
4256  m_children.push_back(std::unique_ptr<DocSimpleListItem>(li));
4257  rv=li->parse();
4258  } while (rv==RetVal_ListItem);
4259  return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4260 }
4261 
4262 //--------------------------------------------------------------------------
4263 
4264 DocAutoListItem::DocAutoListItem(DocParser &parser,DocNode *parent,int indent,int num)
4265  : CompAccept<DocAutoListItem>(parser), m_indent(indent), m_itemNum(num)
4266 {
4267  m_parent = parent;
4268 }
4269 
4271 {
4272  int retval = RetVal_OK;
4273  auto ns = AutoNodeStack(m_parser,this);
4274 
4275  // first parse any number of paragraphs
4276  bool isFirst=TRUE;
4277  DocPara *lastPar=0;
4278  do
4279  {
4280  DocPara *par = new DocPara(m_parser,this);
4281  if (isFirst) { par->markFirst(); isFirst=FALSE; }
4282  retval=par->parse();
4283  if (!par->isEmpty())
4284  {
4285  m_children.push_back(std::unique_ptr<DocPara>(par));
4286  if (lastPar) lastPar->markLast(FALSE);
4287  lastPar=par;
4288  }
4289  else
4290  {
4291  delete par;
4292  }
4293  // next paragraph should be more indented than the - marker to belong
4294  // to this item
4295  } while (retval==TK_NEWPARA && m_parser.context.token->indent>m_indent);
4296  if (lastPar) lastPar->markLast();
4297 
4298  //printf("DocAutoListItem: retval=%d indent=%d\n",retval,m_parser.context.token->indent);
4299  return retval;
4300 }
4301 
4302 //--------------------------------------------------------------------------
4303 
4304 DocAutoList::DocAutoList(DocParser &parser,DocNode *parent,int indent,bool isEnumList,
4305  int depth) :
4306  CompAccept<DocAutoList>(parser), m_indent(indent), m_isEnumList(isEnumList),
4307  m_depth(depth)
4308 {
4309  m_parent = parent;
4310 }
4311 
4313 {
4314  int retval = RetVal_OK;
4315  int num=1;
4316  auto ns = AutoNodeStack(m_parser,this);
4318  // first item or sub list => create new list
4319  do
4320  {
4321  if (m_parser.context.token->id!=-1) // explicitly numbered list
4322  {
4323  num=m_parser.context.token->id; // override num with real number given
4324  }
4325  DocAutoListItem *li = new DocAutoListItem(m_parser,this,m_indent,num++);
4326  m_children.push_back(std::unique_ptr<DocAutoListItem>(li));
4327  retval=li->parse();
4328  //printf("DocAutoList::parse(): retval=0x%x m_parser.context.token->indent=%d m_indent=%d "
4329  // "m_isEnumList=%d m_parser.context.token->isEnumList=%d m_parser.context.token->name=%s\n",
4330  // retval,m_parser.context.token->indent,m_indent,m_isEnumList,m_parser.context.token->isEnumList,
4331  // qPrint(m_parser.context.token->name));
4332  //printf("num=%d m_parser.context.token->id=%d\n",num,m_parser.context.token->id);
4333  }
4334  while (retval==TK_LISTITEM && // new list item
4335  m_indent==m_parser.context.token->indent && // at same indent level
4336  m_isEnumList==m_parser.context.token->isEnumList && // of the same kind
4337  (m_parser.context.token->id==-1 || m_parser.context.token->id>=num) // increasing number (or no number)
4338  );
4339 
4341  return retval;
4342 }
4343 
4344 //--------------------------------------------------------------------------
4345 
4347 {
4348  DBG(("DocTitle::parse() start\n"));
4349  auto ns = AutoNodeStack(m_parser,this);
4351  int tok;
4352  while ((tok=m_parser.tokenizer.lex()))
4353  {
4354  if (!m_parser.defaultHandleToken(this,tok,m_children))
4355  {
4356  m_parser.errorHandleDefaultToken(this,tok,m_children,"title section");
4357  }
4358  }
4361  DBG(("DocTitle::parse() end\n"));
4362 }
4363 
4365 {
4366  m_children.push_back(std::make_unique<DocWord>(m_parser,this,text));
4367 }
4368 
4369 //--------------------------------------------------------------------------
4370 
4372  CompAccept<DocSimpleSect>(parser), m_type(t)
4373 {
4374  m_parent = parent;
4375  m_title=0;
4376 }
4377 
4379 {
4380  delete m_title;
4381 }
4382 
4384 {
4385  v->visitPre(this);
4386  if (m_title) m_title->accept(v);
4387  for (const auto &n : m_children) n->accept(v);
4388  v->visitPost(this);
4389 }
4390 
4391 int DocSimpleSect::parse(bool userTitle,bool needsSeparator)
4392 {
4393  DBG(("DocSimpleSect::parse() start\n"));
4394  auto ns = AutoNodeStack(m_parser,this);
4395 
4396  // handle case for user defined title
4397  if (userTitle)
4398  {
4399  m_title = new DocTitle(m_parser,this);
4400  m_title->parse();
4401  }
4402 
4403  // add new paragraph as child
4404  DocPara *par = new DocPara(m_parser,this);
4405  if (m_children.empty())
4406  {
4407  par->markFirst();
4408  }
4409  else
4410  {
4411  ASSERT(m_children.back()->kind()==DocNode::Kind_Para);
4412  ((DocPara *)m_children.back().get())->markLast(FALSE);
4413  }
4414  par->markLast();
4415  if (needsSeparator) m_children.push_back(std::make_unique<DocSimpleSectSep>(m_parser,this));
4416  m_children.push_back(std::unique_ptr<DocPara>(par));
4417 
4418  // parse the contents of the paragraph
4419  int retval = par->parse();
4420 
4421  DBG(("DocSimpleSect::parse() end retval=%d\n",retval));
4422  return retval; // 0==EOF, TK_NEWPARA, TK_LISTITEM, TK_ENDLIST, RetVal_SimpleSec
4423 }
4424 
4426 {
4427  DBG(("DocSimpleSect::parseRcs() start\n"));
4428  auto ns = AutoNodeStack(m_parser,this);
4429 
4430  m_title = new DocTitle(m_parser,this);
4432 
4434  m_parser.pushContext(); // this will create a new parser.context.token
4436  m_parser.popContext(); // this will restore the old parser.context.token
4437 
4438  DBG(("DocSimpleSect::parseRcs()\n"));
4439  return RetVal_OK;
4440 }
4441 
4443 {
4444  DBG(("DocSimpleSect::parse() start\n"));
4445  auto ns = AutoNodeStack(m_parser,this);
4446 
4447  int retval = RetVal_OK;
4448  for (;;)
4449  {
4450  // add new paragraph as child
4451  DocPara *par = new DocPara(m_parser,this);
4452  if (m_children.empty())
4453  {
4454  par->markFirst();
4455  }
4456  else
4457  {
4458  ASSERT(m_children.back()->kind()==DocNode::Kind_Para);
4459  ((DocPara *)m_children.back().get())->markLast(FALSE);
4460  }
4461  par->markLast();
4462  m_children.push_back(std::unique_ptr<DocPara>(par));
4463 
4464  // parse the contents of the paragraph
4465  retval = par->parse();
4466  if (retval == 0) break;
4467  if (retval == RetVal_CloseXml)
4468  {
4469  retval = RetVal_OK;
4470  break;
4471  }
4472  }
4473 
4474  DBG(("DocSimpleSect::parseXml() end retval=%d\n",retval));
4475  return retval;
4476 }
4477 
4479 {
4480  DocPara *p;
4481  if (m_children.empty() || m_children.back()->kind()!=DocNode::Kind_Para)
4482  {
4483  p = new DocPara(m_parser,this);
4484  m_children.push_back(std::unique_ptr<DocPara>(p));
4485  }
4486  else
4487  {
4488  p = (DocPara *)m_children.back().get();
4489 
4490  // Comma-separate <seealso> links.
4491  p->injectToken(TK_WORD,",");
4492  p->injectToken(TK_WHITESPACE," ");
4493  }
4494 
4496  p->injectToken(TK_LNKWORD,word);
4498 }
4499 
4501 {
4502  switch (m_type)
4503  {
4504  case Unknown: break;
4505  case See: return "see";
4506  case Return: return "return";
4507  case Author: // fall through
4508  case Authors: return "author";
4509  case Version: return "version";
4510  case Since: return "since";
4511  case Date: return "date";
4512  case Note: return "note";
4513  case Warning: return "warning";
4514  case Pre: return "pre";
4515  case Post: return "post";
4516  case Copyright: return "copyright";
4517  case Invar: return "invariant";
4518  case Remark: return "remark";
4519  case Attention: return "attention";
4520  case User: return "user";
4521  case Rcs: return "rcs";
4522  }
4523  return "unknown";
4524 }
4525 
4526 //--------------------------------------------------------------------------
4527 
4528 int DocParamList::parse(const QCString &cmdName)
4529 {
4530  int retval=RetVal_OK;
4531  DBG(("DocParamList::parse() start\n"));
4532  auto ns = AutoNodeStack(m_parser,this);
4533  DocPara *par=0;
4534  QCString saveCmdName = cmdName;
4535 
4536  int tok=m_parser.tokenizer.lex();
4537  if (tok!=TK_WHITESPACE)
4538  {
4539  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
4540  qPrint(saveCmdName));
4541  retval=RetVal_EndParBlock;
4542  goto endparamlist;
4543  }
4545  tok=m_parser.tokenizer.lex();
4546  while (tok==TK_WORD) /* there is a parameter name */
4547  {
4549  {
4550  int typeSeparator = m_parser.context.token->name.find('#'); // explicit type position
4551  if (typeSeparator!=-1)
4552  {
4554  m_parser.context.token->name = m_parser.context.token->name.mid(typeSeparator+1);
4557  ((DocParamSect*)parent())->m_hasTypeSpecifier=TRUE;
4558  }
4559  else
4560  {
4563  }
4564  }
4565  else if (m_type==DocParamSect::RetVal)
4566  {
4569  }
4570  //m_params.append(m_parser.context.token->name);
4572  tok=m_parser.tokenizer.lex();
4573  }
4575  if (tok==0) /* premature end of comment block */
4576  {
4577  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
4578  "argument of command %s",qPrint(saveCmdName));
4579  retval=RetVal_EndParBlock;
4580  goto endparamlist;
4581  }
4582  if (tok!=TK_WHITESPACE) /* premature end of comment block */
4583  {
4584  if (tok!=TK_NEWPARA) /* empty param description */
4585  {
4586  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s in comment block while parsing the "
4587  "argument of command %s",DocTokenizer::tokToString(tok),qPrint(saveCmdName));
4588  }
4589  retval=RetVal_EndParBlock;
4590  goto endparamlist;
4591  }
4592 
4593  par = new DocPara(m_parser,this);
4594  m_paragraphs.push_back(std::unique_ptr<DocPara>(par));
4595  retval = par->parse();
4596  par->markFirst();
4597  par->markLast();
4598 
4599 endparamlist:
4600  DBG(("DocParamList::parse() end retval=%d\n",retval));
4601  return retval;
4602 }
4603 
4604 int DocParamList::parseXml(const QCString &paramName)
4605 {
4606  int retval=RetVal_OK;
4607  DBG(("DocParamList::parseXml() start\n"));
4608  auto ns = AutoNodeStack(m_parser,this);
4609 
4610  m_parser.context.token->name = paramName;
4612  {
4615  }
4616  else if (m_type==DocParamSect::RetVal)
4617  {
4620  }
4621 
4623 
4624  do
4625  {
4626  DocPara *par = new DocPara(m_parser,this);
4627  retval = par->parse();
4628  if (par->isEmpty()) // avoid adding an empty paragraph for the whitespace
4629  // after </para> and before </param>
4630  {
4631  delete par;
4632  break;
4633  }
4634  else // append the paragraph to the list
4635  {
4636  if (m_paragraphs.empty())
4637  {
4638  par->markFirst();
4639  }
4640  else
4641  {
4642  m_paragraphs.back()->markLast(FALSE);
4643  }
4644  par->markLast();
4645  m_paragraphs.push_back(std::unique_ptr<DocPara>(par));
4646  }
4647 
4648  if (retval == 0) break;
4649 
4650  } while (retval==RetVal_CloseXml &&
4654 
4655 
4656  if (retval==0) /* premature end of comment block */
4657  {
4658  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unterminated param or exception tag");
4659  }
4660  else
4661  {
4662  retval=RetVal_OK;
4663  }
4664 
4665 
4666  DBG(("DocParamList::parse() end retval=%d\n",retval));
4667  return retval;
4668 }
4669 
4670 //--------------------------------------------------------------------------
4671 
4672 int DocParamSect::parse(const QCString &cmdName,bool xmlContext, Direction d)
4673 {
4674  int retval=RetVal_OK;
4675  DBG(("DocParamSect::parse() start\n"));
4676  auto ns = AutoNodeStack(m_parser,this);
4677 
4678  if (d!=Unspecified)
4679  {
4681  }
4682 
4683  DocParamList *pl = new DocParamList(m_parser,this,m_type,d);
4684  if (m_children.empty())
4685  {
4686  pl->markFirst();
4687  pl->markLast();
4688  }
4689  else
4690  {
4691  ASSERT(m_children.back()->kind()==DocNode::Kind_ParamList);
4692  ((DocParamList *)m_children.back().get())->markLast(FALSE);
4693  pl->markLast();
4694  }
4695  m_children.push_back(std::unique_ptr<DocParamList>(pl));
4696  if (xmlContext)
4697  {
4698  retval = pl->parseXml(cmdName);
4699  }
4700  else
4701  {
4702  retval = pl->parse(cmdName);
4703  }
4704  if (retval==RetVal_EndParBlock)
4705  {
4706  retval = RetVal_OK;
4707  }
4708 
4709  DBG(("DocParamSect::parse() end retval=%d\n",retval));
4710  return retval;
4711 }
4712 
4713 //--------------------------------------------------------------------------
4714 
4716 {
4717  DocSimpleSect *ss=0;
4718  bool needsSeparator = FALSE;
4719  if (!m_children.empty() && // previous element
4720  m_children.back()->kind()==Kind_SimpleSect && // was a simple sect
4721  ((DocSimpleSect *)m_children.back().get())->type()==t && // of same type
4722  t!=DocSimpleSect::User) // but not user defined
4723  {
4724  // append to previous section
4725  ss=(DocSimpleSect *)m_children.back().get();
4726  needsSeparator = TRUE;
4727  }
4728  else // start new section
4729  {
4730  ss=new DocSimpleSect(m_parser,this,t);
4731  m_children.push_back(std::unique_ptr<DocSimpleSect>(ss));
4732  }
4733  int rv = RetVal_OK;
4734  if (xmlContext)
4735  {
4736  return ss->parseXml();
4737  }
4738  else
4739  {
4740  rv = ss->parse(t==DocSimpleSect::User,needsSeparator);
4741  }
4742  return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4743 }
4744 
4747  bool xmlContext=FALSE,
4748  int direction=DocParamSect::Unspecified)
4749 {
4750  DocParamSect *ps=0;
4751  if (!m_children.empty() && // previous element
4752  m_children.back()->kind()==Kind_ParamSect && // was a param sect
4753  ((DocParamSect *)m_children.back().get())->type()==t) // of same type
4754  {
4755  // append to previous section
4756  ps=(DocParamSect *)m_children.back().get();
4757  }
4758  else // start new section
4759  {
4760  ps=new DocParamSect(m_parser,this,t);
4761  m_children.push_back(std::unique_ptr<DocParamSect>(ps));
4762  }
4763  int rv=ps->parse(cmdName,xmlContext,(DocParamSect::Direction)direction);
4764  return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4765 }
4766 
4768 {
4769  // get the argument of the cite command.
4770  int tok=m_parser.tokenizer.lex();
4771  if (tok!=TK_WHITESPACE)
4772  {
4773  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
4774  qPrint("cite"));
4775  return;
4776  }
4778  tok=m_parser.tokenizer.lex();
4779  if (tok==0)
4780  {
4781  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
4782  "argument of command %s\n", qPrint("cite"));
4783  return;
4784  }
4785  else if (tok!=TK_WORD && tok!=TK_LNKWORD)
4786  {
4787  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
4788  DocTokenizer::tokToString(tok),qPrint("cite"));
4789  return;
4790  }
4792  m_children.push_back(
4793  std::make_unique<DocCite>(
4795 
4797 }
4798 
4800 {
4801  // get the argument of the emoji command.
4802  int tok=m_parser.tokenizer.lex();
4803  if (tok!=TK_WHITESPACE)
4804  {
4805  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
4806  qPrint("emoji"));
4807  return;
4808  }
4810  tok=m_parser.tokenizer.lex();
4811  if (tok==0)
4812  {
4813  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
4814  "argument of command %s\n", qPrint("emoji"));
4815  return;
4816  }
4817  else if (tok!=TK_WORD)
4818  {
4819  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
4820  DocTokenizer::tokToString(tok),qPrint("emoji"));
4821  return;
4822  }
4823  m_children.push_back(
4824  std::make_unique<DocEmoji>(
4827 }
4828 
4830 {
4831  int retval=m_parser.tokenizer.lex();
4832  ASSERT(retval==TK_WHITESPACE);
4834  retval=m_parser.tokenizer.lex();
4835  if (retval==RetVal_OK)
4836  {
4838  if (ref->parse())
4839  {
4840  m_children.push_back(std::unique_ptr<DocXRefItem>(ref));
4841  }
4842  else
4843  {
4844  delete ref;
4845  }
4846  }
4848  return retval;
4849 }
4850 
4852 {
4854  int tok = m_parser.tokenizer.lex();
4855  if (tok!=TK_WORD)
4856  {
4857  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"invalid argument for command '\\iline'\n");
4858  return;
4859  }
4861 }
4862 
4864 {
4865  QCString saveCmdName = cmdName;
4866  DBG(("handleIncludeOperator(%s)\n",qPrint(saveCmdName)));
4867  int tok=m_parser.tokenizer.lex();
4868  if (tok!=TK_WHITESPACE)
4869  {
4870  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
4871  qPrint(saveCmdName));
4872  return;
4873  }
4875  tok=m_parser.tokenizer.lex();
4877  if (tok==0)
4878  {
4879  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
4880  "argument of command %s", qPrint(saveCmdName));
4881  return;
4882  }
4883  else if (tok!=TK_WORD)
4884  {
4885  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
4886  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
4887  return;
4888  }
4890  DocNode *n1 = m_children.size()>=1 ? m_children.at(m_children.size()-1).get() : 0;
4891  DocNode *n2 = m_children.size()>=2 ? m_children.at(m_children.size()-2).get() : 0;
4892  bool isFirst = n1==0 || // no last node
4893  (n1->kind()!=DocNode::Kind_IncOperator &&
4895  ) || // last node is not operator or whitespace
4896  (n1->kind()==DocNode::Kind_WhiteSpace &&
4897  n2!=0 && n2->kind()!=DocNode::Kind_IncOperator
4898  ); // previous not is not operator
4899  op->markFirst(isFirst);
4900  op->markLast(TRUE);
4901  if (n1!=0 && n1->kind()==DocNode::Kind_IncOperator)
4902  {
4903  ((DocIncOperator *)n1)->markLast(FALSE);
4904  }
4905  else if (n1!=0 && n1->kind()==DocNode::Kind_WhiteSpace &&
4906  n2!=0 && n2->kind()==DocNode::Kind_IncOperator
4907  )
4908  {
4909  ((DocIncOperator *)n2)->markLast(FALSE);
4910  }
4911  m_children.push_back(std::unique_ptr<DocIncOperator>(op));
4912  op->parse();
4913 }
4914 
4915 void DocPara::handleImage(const QCString &cmdName)
4916 {
4917  QCString saveCmdName = cmdName;
4918  bool inlineImage = false;
4919  QCString anchorStr;
4920 
4921  int tok=m_parser.tokenizer.lex();
4922  if (tok!=TK_WHITESPACE)
4923  {
4924  if (tok==TK_WORD)
4925  {
4926  if (m_parser.context.token->name == "{")
4927  {
4929  tok=m_parser.tokenizer.lex();
4931  StringVector optList=split(m_parser.context.token->name.str(),",");
4932  for (const auto &opt : optList)
4933  {
4934  if (opt.empty()) continue;
4935  QCString locOpt(opt);
4936  QCString locOptLow;
4937  locOpt = locOpt.stripWhiteSpace();
4938  locOptLow = locOpt.lower();
4939  if (locOptLow == "inline")
4940  {
4941  inlineImage = true;
4942  }
4943  else if (locOptLow.startsWith("anchor:"))
4944  {
4945  if (!anchorStr.isEmpty())
4946  {
4948  "multiple use of option 'anchor' for '%s' command, ignoring: '%s'",
4949  qPrint(saveCmdName),qPrint(locOpt.mid(7)));
4950  }
4951  else
4952  {
4953  anchorStr = locOpt.mid(7);
4954  }
4955  }
4956  else
4957  {
4959  "unknown option '%s' for '%s' command specified",
4960  qPrint(locOpt), qPrint(saveCmdName));
4961  }
4962  }
4963  tok=m_parser.tokenizer.lex();
4964  if (tok!=TK_WHITESPACE)
4965  {
4966  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
4967  qPrint(saveCmdName));
4968  return;
4969  }
4970  }
4971  }
4972  else
4973  {
4974  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
4975  qPrint(saveCmdName));
4976  return;
4977  }
4978  }
4979  tok=m_parser.tokenizer.lex();
4980  if (tok!=TK_WORD && tok!=TK_LNKWORD)
4981  {
4982  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
4983  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
4984  return;
4985  }
4986  tok=m_parser.tokenizer.lex();
4987  if (tok!=TK_WHITESPACE)
4988  {
4989  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
4990  qPrint(saveCmdName));
4991  return;
4992  }
4993  DocImage::Type t;
4994  QCString imgType = m_parser.context.token->name.lower();
4995  if (imgType=="html") t=DocImage::Html;
4996  else if (imgType=="latex") t=DocImage::Latex;
4997  else if (imgType=="docbook") t=DocImage::DocBook;
4998  else if (imgType=="rtf") t=DocImage::Rtf;
4999  else if (imgType=="xml") t=DocImage::Xml;
5000  else
5001  {
5002  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"output format `%s` specified as the first argument of "
5003  "%s command is not valid",
5004  qPrint(imgType),qPrint(saveCmdName));
5005  return;
5006  }
5008  tok=m_parser.tokenizer.lex();
5010  if (tok!=TK_WORD)
5011  {
5012  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
5013  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
5014  return;
5015  }
5016  if (!anchorStr.isEmpty())
5017  {
5018  DocAnchor *anchor = new DocAnchor(m_parser,this,anchorStr,true);
5019  m_children.push_back(std::unique_ptr<DocAnchor>(anchor));
5020  }
5021  HtmlAttribList attrList;
5022  DocImage *img = new DocImage(m_parser,this,attrList,
5023  m_parser.findAndCopyImage(m_parser.context.token->name,t),t,"",inlineImage);
5024  m_children.push_back(std::unique_ptr<DocImage>(img));
5025  img->parse();
5026 }
5027 
5028 template<class T>
5029 void DocPara::handleFile(const QCString &cmdName)
5030 {
5031  QCString saveCmdName = cmdName;
5032  int tok=m_parser.tokenizer.lex();
5033  if (tok!=TK_WHITESPACE)
5034  {
5035  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
5036  qPrint(saveCmdName));
5037  return;
5038  }
5040  tok=m_parser.tokenizer.lex();
5042  if (tok!=TK_WORD)
5043  {
5044  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
5045  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
5046  return;
5047  }
5049  auto df = std::make_unique<T>(m_parser,this,name,m_parser.context.context,m_parser.context.fileName,m_parser.tokenizer.getLineNr());
5050  if (df->parse())
5051  {
5052  m_children.push_back(std::move(df));
5053  }
5054 }
5055 
5057 {
5058  DocVhdlFlow *vf = new DocVhdlFlow(m_parser,this);
5059  m_children.push_back(std::unique_ptr<DocVhdlFlow>(vf));
5060  vf->parse();
5061 }
5062 
5063 void DocPara::handleLink(const QCString &cmdName,bool isJavaLink)
5064 {
5065  QCString saveCmdName = cmdName;
5066  int tok=m_parser.tokenizer.lex();
5067  if (tok!=TK_WHITESPACE)
5068  {
5069  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
5070  qPrint(saveCmdName));
5071  return;
5072  }
5074  tok=m_parser.tokenizer.lex();
5075  if (tok!=TK_WORD)
5076  {
5077  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"%s as the argument of %s",
5078  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
5079  return;
5080  }
5082  DocLink *lnk = new DocLink(m_parser,this,m_parser.context.token->name);
5083  m_children.push_back(std::unique_ptr<DocLink>(lnk));
5084  QCString leftOver = lnk->parse(isJavaLink);
5085  if (!leftOver.isEmpty())
5086  {
5087  m_children.push_back(std::make_unique<DocWord>(m_parser,this,leftOver));
5088  }
5089 }
5090 
5091 void DocPara::handleRef(const QCString &cmdName)
5092 {
5093  QCString saveCmdName = cmdName;
5094  DBG(("handleRef(%s)\n",qPrint(saveCmdName)));
5095  int tok=m_parser.tokenizer.lex();
5096  if (tok!=TK_WHITESPACE)
5097  {
5098  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
5099  qPrint(saveCmdName));
5100  return;
5101  }
5103  tok=m_parser.tokenizer.lex(); // get the reference id
5104  DocRef *ref=0;
5105  if (tok!=TK_WORD)
5106  {
5107  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
5108  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
5109  goto endref;
5110  }
5112  m_children.push_back(std::unique_ptr<DocRef>(ref));
5113  ref->parse();
5114 endref:
5116 }
5117 
5119 {
5120  DBG(("handleInclude(%s)\n",qPrint(cmdName)));
5121  QCString saveCmdName = cmdName;
5122  int tok=m_parser.tokenizer.lex();
5123  bool isBlock = false;
5124  if (tok==TK_WORD && m_parser.context.token->name=="{")
5125  {
5127  tok=m_parser.tokenizer.lex();
5129  StringVector optList=split(m_parser.context.token->name.str(),",");
5130  auto contains = [&optList](const char *kw)
5131  {
5132  return std::find(optList.begin(),optList.end(),kw)!=optList.end();
5133  };
5134  if (t==DocInclude::Include && contains("lineno"))
5135  {
5137  }
5138  else if (t==DocInclude::Snippet && contains("lineno"))
5139  {
5141  }
5142  else if (t==DocInclude::DontInclude && contains("lineno"))
5143  {
5145  }
5146  else if (t==DocInclude::Include && contains("doc"))
5147  {
5149  }
5150  else if (t==DocInclude::Snippet && contains("doc"))
5151  {
5153  }
5154  tok=m_parser.tokenizer.lex();
5155  if (tok!=TK_WHITESPACE)
5156  {
5157  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
5158  qPrint(saveCmdName));
5159  return;
5160  }
5161  }
5162  else if (tok==TK_WORD && m_parser.context.token->name=="[")
5163  {
5165  tok=m_parser.tokenizer.lex();
5166  isBlock = (m_parser.context.token->name.stripWhiteSpace() == "block");
5168  tok=m_parser.tokenizer.lex();
5169  }
5170  else if (tok!=TK_WHITESPACE)
5171  {
5172  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
5173  qPrint(saveCmdName));
5174  return;
5175  }
5177  tok=m_parser.tokenizer.lex();
5179  if (tok==0)
5180  {
5181  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
5182  "argument of command %s",qPrint(saveCmdName));
5183  return;
5184  }
5185  else if (tok!=TK_WORD)
5186  {
5187  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
5188  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
5189  return;
5190  }
5191  QCString fileName = m_parser.context.token->name;
5192  QCString blockId;
5194  {
5195  if (fileName == "this") fileName=m_parser.context.fileName;
5197  tok=m_parser.tokenizer.lex();
5199  if (tok!=TK_WORD)
5200  {
5201  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected block identifier, but found token %s instead while parsing the %s command",
5202  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
5203  return;
5204  }
5205  blockId = "["+m_parser.context.token->name+"]";
5206  }
5207 
5208  // This is the only place to handle the \includedoc and \snippetdoc commands,
5209  // as the content is included here as if it is really here.
5211  {
5212  QCString inc_text;
5213  int inc_line = 1;
5214  m_parser.readTextFileByName(fileName,inc_text);
5215  if (t==DocInclude::SnippetDoc)
5216  {
5217  int count;
5218  if (!blockId.isEmpty() && (count=inc_text.contains(blockId.data()))!=2)
5219  {
5220  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n",
5221  qPrint(blockId),qPrint(fileName),count);
5222  }
5223  inc_line = lineBlock(inc_text, blockId);
5224  inc_text = extractBlock(inc_text, blockId);
5225  }
5226 
5227  Markdown markdown(fileName,inc_line);
5228  QCString strippedDoc = stripIndentation(inc_text);
5229  QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,inc_line) : strippedDoc;
5230 
5232  m_parser.context.fileName = fileName;
5233  m_parser.tokenizer.setLineNr(inc_line);
5234  m_parser.internalValidatingParseDoc(this,m_children,processedDoc);
5235  m_parser.popContext();
5236  }
5237  else
5238  {
5240  m_children.push_back(std::unique_ptr<DocInclude>(inc));
5241  inc->parse();
5242  }
5243 }
5244 
5245 void DocPara::handleSection(const QCString &cmdName)
5246 {
5247  QCString saveCmdName = cmdName;
5248  // get the argument of the section command.
5249  int tok=m_parser.tokenizer.lex();
5250  if (tok!=TK_WHITESPACE)
5251  {
5252  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"expected whitespace after \\%s command",
5253  qPrint(saveCmdName));
5254  return;
5255  }
5256  tok=m_parser.tokenizer.lex();
5257  if (tok==0)
5258  {
5259  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
5260  "argument of command %s\n", qPrint(saveCmdName));
5261  return;
5262  }
5263  else if (tok!=TK_WORD && tok!=TK_LNKWORD)
5264  {
5265  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s as the argument of %s",
5266  DocTokenizer::tokToString(tok),qPrint(saveCmdName));
5267  return;
5268  }
5273 }
5274 
5275 int DocPara::handleHtmlHeader(const HtmlAttribList &tagHtmlAttribs,int level)
5276 {
5277  DocHtmlHeader *header = new DocHtmlHeader(m_parser,this,tagHtmlAttribs,level);
5278  m_children.push_back(std::unique_ptr<DocHtmlHeader>(header));
5279  int retval = header->parse();
5280  return (retval==RetVal_OK) ? TK_NEWPARA : retval;
5281 }
5282 
5283 // For XML tags whose content is stored in attributes rather than
5284 // contained within the element, we need a way to inject the attribute
5285 // text into the current paragraph.
5286 bool DocPara::injectToken(int tok,const QCString &tokText)
5287 {
5288  m_parser.context.token->name = tokText;
5289  return m_parser.defaultHandleToken(this,tok,m_children);
5290 }
5291 
5293 {
5294  int retval = m_parser.tokenizer.lex();
5296  if (!lang.isEmpty() && lang.at(0)!='.')
5297  {
5298  lang="."+lang;
5299  }
5301  {
5302  m_parser.context.token->verb = substitute(substitute(m_parser.context.token->verb,"&lt;","<"),"&gt;",">");
5303  }
5304  // search for the first non-whitespace line, index is stored in li
5305  int i=0,li=0,l=m_parser.context.token->verb.length();
5306  while (i<l && (m_parser.context.token->verb.at(i)==' ' || m_parser.context.token->verb.at(i)=='\n'))
5307  {
5308  if (m_parser.context.token->verb.at(i)=='\n') li=i+1;
5309  i++;
5310  }
5312  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"code section ended without end marker");
5314  return retval;
5315 }
5316 
5318 {
5319  if (m_parser.context.memberDef) // inheriting docs from a member
5320  {
5321  const MemberDef *reMd = m_parser.context.memberDef->reimplements();
5322  if (reMd) // member from which was inherited.
5323  {
5324  const MemberDef *thisMd = m_parser.context.memberDef;
5325  //printf("{InheritDocs:%s=>%s}\n",qPrint(m_parser.context.memberDef->qualifiedName()),qPrint(reMd->qualifiedName()));
5329  {
5331  }
5332  m_parser.context.memberDef=reMd;
5333  while (!m_parser.context.styleStack.empty()) m_parser.context.styleStack.pop();
5334  while (!m_parser.context.nodeStack.empty()) m_parser.context.nodeStack.pop();
5335  m_parser.context.copyStack.push_back(reMd);
5338  m_parser.context.copyStack.pop_back();
5339  auto hasParamCommand = m_parser.context.hasParamCommand;
5340  auto hasReturnCommand = m_parser.context.hasReturnCommand;
5341  auto retvalsFound = m_parser.context.retvalsFound;
5342  auto paramsFound = m_parser.context.paramsFound;
5343  m_parser.popContext();
5344  m_parser.context.hasParamCommand = hasParamCommand;
5345  m_parser.context.hasReturnCommand = hasReturnCommand;
5346  m_parser.context.retvalsFound = retvalsFound;
5347  m_parser.context.paramsFound = paramsFound;
5348  m_parser.context.memberDef = thisMd;
5349  }
5350  }
5351 }
5352 
5353 
5354 int DocPara::handleCommand(const QCString &cmdName, const int tok)
5355 {
5356  DBG(("handleCommand(%s)\n",qPrint(cmdName)));
5357  int retval = RetVal_OK;
5358  int cmdId = Mappers::cmdMapper->map(cmdName);
5359  switch (cmdId)
5360  {
5361  case CMD_UNKNOWN:
5362  m_children.push_back(std::make_unique<DocWord>(m_parser,this,TK_COMMAND_CHAR(tok) + cmdName));
5363  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Found unknown command '%s%s'",TK_COMMAND_CHAR(tok),qPrint(cmdName));
5364  break;
5365  case CMD_EMPHASIS:
5366  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Italic,cmdName,TRUE));
5367  retval=m_parser.handleStyleArgument(this,m_children,cmdName);
5368  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Italic,cmdName,FALSE));
5369  if (retval!=TK_WORD) m_children.push_back(std::make_unique<DocWhiteSpace>(m_parser,this," "));
5370  break;
5371  case CMD_BOLD:
5372  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Bold,cmdName,TRUE));
5373  retval=m_parser.handleStyleArgument(this,m_children,cmdName);
5374  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Bold,cmdName,FALSE));
5375  if (retval!=TK_WORD) m_children.push_back(std::make_unique<DocWhiteSpace>(m_parser,this," "));
5376  break;
5377  case CMD_CODE:
5378  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,cmdName,TRUE));
5379  retval=m_parser.handleStyleArgument(this,m_children,cmdName);
5380  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,cmdName,FALSE));
5381  if (retval!=TK_WORD) m_children.push_back(std::make_unique<DocWhiteSpace>(m_parser,this," "));
5382  break;
5383  case CMD_BSLASH:
5384  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_BSlash));
5385  break;
5386  case CMD_AT:
5387  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_At));
5388  break;
5389  case CMD_LESS:
5390  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Less));
5391  break;
5392  case CMD_GREATER:
5393  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Greater));
5394  break;
5395  case CMD_AMP:
5396  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Amp));
5397  break;
5398  case CMD_DOLLAR:
5399  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Dollar));
5400  break;
5401  case CMD_HASH:
5402  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Hash));
5403  break;
5404  case CMD_PIPE:
5405  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Pipe));
5406  break;
5407  case CMD_DCOLON:
5408  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_DoubleColon));
5409  break;
5410  case CMD_PERCENT:
5411  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Percent));
5412  break;
5413  case CMD_NDASH:
5414  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
5415  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
5416  break;
5417  case CMD_MDASH:
5418  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
5419  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
5420  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
5421  break;
5422  case CMD_QUOTE:
5423  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Quot));
5424  break;
5425  case CMD_PUNT:
5426  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Dot));
5427  break;
5428  case CMD_PLUS:
5429  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Plus));
5430  break;
5431  case CMD_MINUS:
5432  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
5433  break;
5434  case CMD_EQUAL:
5435  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Equal));
5436  break;
5437  case CMD_SA:
5441  break;
5442  case CMD_RETURN:
5445  break;
5446  case CMD_AUTHOR:
5448  break;
5449  case CMD_AUTHORS:
5451  break;
5452  case CMD_VERSION:
5454  break;
5455  case CMD_SINCE:
5457  break;
5458  case CMD_DATE:
5460  break;
5461  case CMD_NOTE:
5463  break;
5464  case CMD_WARNING:
5466  break;
5467  case CMD_PRE:
5469  break;
5470  case CMD_POST:
5472  break;
5473  case CMD_COPYRIGHT:
5475  break;
5476  case CMD_INVARIANT:
5478  break;
5479  case CMD_REMARK:
5481  break;
5482  case CMD_ATTENTION:
5484  break;
5485  case CMD_PAR:
5487  break;
5488  case CMD_LI:
5489  {
5490  DocSimpleList *sl=new DocSimpleList(m_parser,this);
5491  m_children.push_back(std::unique_ptr<DocSimpleList>(sl));
5492  retval = sl->parse();
5493  }
5494  break;
5495  case CMD_SECTION:
5496  {
5497  handleSection(cmdName);
5498  retval = RetVal_Section;
5499  }
5500  break;
5501  case CMD_SUBSECTION:
5502  {
5503  handleSection(cmdName);
5504  retval = RetVal_Subsection;
5505  }
5506  break;
5507  case CMD_SUBSUBSECTION:
5508  {
5509  handleSection(cmdName);
5510  retval = RetVal_Subsubsection;
5511  }
5512  break;
5513  case CMD_PARAGRAPH:
5514  {
5515  handleSection(cmdName);
5516  retval = RetVal_Paragraph;
5517  }
5518  break;
5519  case CMD_STARTCODE:
5520  {
5522  retval = handleStartCode();
5523  }
5524  break;
5525  case CMD_HTMLONLY:
5526  {
5528  retval = m_parser.tokenizer.lex();
5530  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"htmlonly section ended without end marker");
5532  }
5533  break;
5534  case CMD_MANONLY:
5535  {
5537  retval = m_parser.tokenizer.lex();
5539  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"manonly section ended without end marker");
5541  }
5542  break;
5543  case CMD_RTFONLY:
5544  {
5546  retval = m_parser.tokenizer.lex();
5548  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"rtfonly section ended without end marker");
5550  }
5551  break;
5552  case CMD_LATEXONLY:
5553  {
5555  retval = m_parser.tokenizer.lex();
5557  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"latexonly section ended without end marker");
5559  }
5560  break;
5561  case CMD_XMLONLY:
5562  {
5564  retval = m_parser.tokenizer.lex();
5566  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"xmlonly section ended without end marker");
5568  }
5569  break;
5570  case CMD_DBONLY:
5571  {
5573  retval = m_parser.tokenizer.lex();
5575  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"docbookonly section ended without end marker");
5577  }
5578  break;
5579  case CMD_VERBATIM:
5580  {
5582  retval = m_parser.tokenizer.lex();
5584  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"verbatim section ended without end marker");
5586  }
5587  break;
5588  case CMD_DOT:
5589  {
5592  QCString width,height;
5593  m_parser.defaultHandleTitleAndSize(CMD_DOT,dv.get(),dv->children(),width,height);
5595  retval = m_parser.tokenizer.lex();
5596  dv->setText(m_parser.context.token->verb);
5597  dv->setWidth(width);
5598  dv->setHeight(height);
5599  dv->setLocation(m_parser.context.fileName,m_parser.tokenizer.getLineNr());
5600  if (!Config_getBool(HAVE_DOT))
5601  {
5602  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"ignoring \\dot command because HAVE_DOT is not set");
5603  }
5604  else
5605  {
5606  m_children.push_back(std::move(dv));
5607  }
5608  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"dot section ended without end marker");
5610  }
5611  break;
5612  case CMD_MSC:
5613  {
5616  QCString width,height;
5617  m_parser.defaultHandleTitleAndSize(CMD_MSC,dv.get(),dv->children(),width,height);
5619  retval = m_parser.tokenizer.lex();
5620  dv->setText(m_parser.context.token->verb);
5621  dv->setWidth(width);
5622  dv->setHeight(height);
5623  dv->setLocation(m_parser.context.fileName,m_parser.tokenizer.getLineNr());
5624  m_children.push_back(std::move(dv));
5625  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"msc section ended without end marker");
5627  }
5628  break;
5629  case CMD_STARTUML:
5630  {
5631  static QCString jarPath = Config_getString(PLANTUML_JAR_PATH);
5633  retval = m_parser.tokenizer.lex();
5634 
5635  QCString fullMatch = m_parser.context.token->sectionId;
5636  QCString sectionId = "";
5637  int idx = fullMatch.find('{');
5638  int idxEnd = fullMatch.find("}",idx+1);
5639  StringVector optList;
5640  QCString engine;
5641  if (idx != -1) // options present
5642  {
5643  QCString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace();
5644  optList = split(optStr.str(),",");
5645  for (const auto &opt : optList)
5646  {
5647  if (opt.empty()) continue;
5648  bool found = false;
5649  QCString locOpt(opt);
5650  locOpt = locOpt.stripWhiteSpace().lower();
5651  if (g_plantumlEngine.find(locOpt.str())!=g_plantumlEngine.end())
5652  {
5653  if (!engine.isEmpty())
5654  {
5655  warn(m_parser.context.fileName,m_parser.tokenizer.getLineNr(), "Multiple definition of engine for '\\startuml'");
5656  }
5657  engine = locOpt;
5658  found = true;
5659  }
5660  if (!found)
5661  {
5662  if (sectionId.isEmpty())
5663  {
5664  sectionId = opt;
5665  }
5666  else
5667  {
5668  warn(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Multiple use of of filename for '\\startuml'");
5669  }
5670  }
5671  }
5672  }
5673  else
5674  {
5675  sectionId = m_parser.context.token->sectionId;
5676  }
5677  if (engine.isEmpty()) engine = "uml";
5678 
5679  if (sectionId.isEmpty())
5680  {
5682  retval = m_parser.tokenizer.lex();
5683  assert(retval==RetVal_OK);
5684 
5685  sectionId = m_parser.context.token->sectionId;
5686  sectionId = sectionId.stripWhiteSpace();
5687  }
5688 
5689  QCString plantFile(sectionId);
5691  dv->setEngine(engine);
5693  QCString width,height;
5696  retval = m_parser.tokenizer.lex();
5697  int line = 0;
5699  if (engine == "ditaa")
5700  {
5701  dv->setUseBitmap(true);
5702  }
5703  else if (engine == "uml")
5704  {
5705  int i = trimmedVerb.find('\n');
5706  QCString firstLine = i==-1 ? trimmedVerb : trimmedVerb.left(i);
5707  if (firstLine.stripWhiteSpace() == "ditaa") dv->setUseBitmap(true);
5708  }
5709  dv->setText(trimmedVerb);
5710  dv->setWidth(width);
5711  dv->setHeight(height);
5713  if (jarPath.isEmpty())
5714  {
5715  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"ignoring \\startuml command because PLANTUML_JAR_PATH is not set");
5716  delete dv;
5717  }
5718  else
5719  {
5720  m_children.push_back(std::unique_ptr<DocVerbatim>(dv));
5721  }
5722  if (retval==0) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"startuml section ended without end marker");
5724  }
5725  break;
5726  case CMD_ENDPARBLOCK:
5727  retval=RetVal_EndParBlock;
5728  break;
5729  case CMD_ENDCODE:
5730  case CMD_ENDHTMLONLY:
5731  case CMD_ENDMANONLY:
5732  case CMD_ENDRTFONLY:
5733  case CMD_ENDLATEXONLY:
5734  case CMD_ENDXMLONLY:
5735  case CMD_ENDDBONLY:
5736  case CMD_ENDLINK:
5737  case CMD_ENDVERBATIM:
5738  case CMD_ENDDOT:
5739  case CMD_ENDMSC:
5740  case CMD_ENDUML:
5742  break;
5743  case CMD_PARAM:
5745  break;
5746  case CMD_TPARAM:
5748  break;
5749  case CMD_RETVAL:
5750  retval = handleParamSection(cmdName,DocParamSect::RetVal);
5751  break;
5752  case CMD_EXCEPTION:
5753  retval = handleParamSection(cmdName,DocParamSect::Exception);
5754  break;
5755  case CMD_XREFITEM:
5756  retval = handleXRefItem();
5757  break;
5758  case CMD_LINEBREAK:
5759  {
5760  m_children.push_back(std::make_unique<DocLineBreak>(m_parser,this));
5761  }
5762  break;
5763  case CMD_ANCHOR:
5764  {
5765  DocAnchor *anchor = m_parser.handleAnchor(this);
5766  if (anchor)
5767  {
5768  m_children.push_back(std::unique_ptr<DocAnchor>(anchor));
5769  }
5770  }
5771  break;
5772  case CMD_ADDINDEX:
5773  {
5774  DocIndexEntry *ie = new DocIndexEntry(m_parser,this,
5777  m_children.push_back(std::unique_ptr<DocIndexEntry>(ie));
5778  retval = ie->parse();
5779  }
5780  break;
5781  case CMD_INTERNAL:
5782  retval = RetVal_Internal;
5783  break;
5784  case CMD_ENDINTERNAL:
5785  retval = RetVal_EndInternal;
5786  break;
5787  case CMD_PARBLOCK:
5788  {
5789  DocParBlock *block = new DocParBlock(m_parser,this);
5790  m_children.push_back(std::unique_ptr<DocParBlock>(block));
5791  retval = block->parse();
5792  }
5793  break;
5794  case CMD_COPYDOC: // fall through
5795  case CMD_COPYBRIEF: // fall through
5796  case CMD_COPYDETAILS:
5797  //retval = RetVal_CopyDoc;
5798  // these commands should already be resolved by processCopyDoc()
5799  break;
5800  case CMD_INCLUDE:
5802  break;
5803  case CMD_INCWITHLINES:
5805  break;
5806  case CMD_DONTINCLUDE:
5808  break;
5809  case CMD_HTMLINCLUDE:
5811  break;
5812  case CMD_LATEXINCLUDE:
5814  break;
5815  case CMD_RTFINCLUDE:
5817  break;
5818  case CMD_MANINCLUDE:
5820  break;
5821  case CMD_XMLINCLUDE:
5823  break;
5824  case CMD_DOCBOOKINCLUDE:
5826  break;
5827  case CMD_VERBINCLUDE:
5829  break;
5830  case CMD_SNIPPET:
5832  break;
5833  case CMD_SNIPWITHLINES:
5835  break;
5836  case CMD_INCLUDEDOC:
5838  break;
5839  case CMD_SNIPPETDOC:
5841  break;
5842  case CMD_SKIP:
5844  break;
5845  case CMD_UNTIL:
5847  break;
5848  case CMD_SKIPLINE:
5850  break;
5851  case CMD_LINE:
5853  break;
5854  case CMD_IMAGE:
5855  handleImage(cmdName);
5856  break;
5857  case CMD_DOTFILE:
5858  if (!Config_getBool(HAVE_DOT))
5859  {
5861  "ignoring \\dotfile command because HAVE_DOT is not set");
5862  }
5863  else
5864  {
5865  handleFile<DocDotFile>(cmdName);
5866  }
5867  break;
5868  case CMD_VHDLFLOW:
5869  handleVhdlFlow();
5870  break;
5871  case CMD_MSCFILE:
5872  handleFile<DocMscFile>(cmdName);
5873  break;
5874  case CMD_DIAFILE:
5875  handleFile<DocDiaFile>(cmdName);
5876  break;
5877  case CMD_LINK:
5878  handleLink(cmdName,FALSE);
5879  break;
5880  case CMD_JAVALINK:
5881  handleLink(cmdName,TRUE);
5882  break;
5883  case CMD_CITE:
5884  handleCite();
5885  break;
5886  case CMD_EMOJI:
5887  handleEmoji();
5888  break;
5889  case CMD_REF: // fall through
5890  case CMD_SUBPAGE:
5891  handleRef(cmdName);
5892  break;
5893  case CMD_SECREFLIST:
5894  {
5895  DocSecRefList *list = new DocSecRefList(m_parser,this);
5896  m_children.push_back(std::unique_ptr<DocSecRefList>(list));
5897  list->parse();
5898  }
5899  break;
5900  case CMD_SECREFITEM:
5902  break;
5903  case CMD_ENDSECREFLIST:
5905  break;
5906  case CMD_FORMULA:
5907  {
5908  m_children.push_back(
5909  std::make_unique<DocFormula>(
5910  m_parser,this,m_parser.context.token->id));
5911  }
5912  break;
5913  //case CMD_LANGSWITCH:
5914  // retval = handleLanguageSwitch();
5915  // break;
5916  case CMD_INTERNALREF:
5917  //warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected command %s",qPrint(m_parser.context.token->name));
5918  {
5920  if (ref)
5921  {
5922  m_children.push_back(std::unique_ptr<DocInternalRef>(ref));
5923  ref->parse();
5924  }
5926  }
5927  break;
5928  case CMD_INHERITDOC:
5929  handleInheritDoc();
5930  break;
5931  case CMD_ILINE:
5932  handleIline();
5933  break;
5934  default:
5935  // we should not get here!
5936  ASSERT(0);
5937  break;
5938  }
5939  INTERNAL_ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec ||
5940  retval==TK_LISTITEM || retval==TK_ENDLIST || retval==TK_NEWPARA ||
5941  retval==RetVal_Section || retval==RetVal_EndList ||
5942  retval==RetVal_Internal || retval==RetVal_SwitchLang ||
5943  retval==RetVal_EndInternal
5944  );
5945  DBG(("handleCommand(%s) end retval=%s\n",qPrint(cmdName),DocTokenizer::retvalToString(retval)));
5946  return retval;
5947 }
5948 
5949 static bool findAttribute(const HtmlAttribList &tagHtmlAttribs,
5950  const char *attrName,
5951  QCString *result)
5952 {
5953 
5954  for (const auto &opt : tagHtmlAttribs)
5955  {
5956  if (opt.name==attrName)
5957  {
5958  *result = opt.value;
5959  return TRUE;
5960  }
5961  }
5962  return FALSE;
5963 }
5964 
5965 int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &tagHtmlAttribs)
5966 {
5967  DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.size()));
5968  int retval=RetVal_OK;
5969  int tagId = Mappers::htmlTagMapper->map(tagName);
5970  if (m_parser.context.token->emptyTag && !(tagId&XML_CmdMask) &&
5971  tagId!=HTML_UNKNOWN && tagId!=HTML_IMG && tagId!=HTML_BR && tagId!=HTML_HR && tagId!=HTML_P)
5972  {
5973  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"HTML tag ('<%s/>') may not use the 'empty tag' XHTML syntax.",
5974  qPrint(tagName));
5975  }
5976  switch (tagId)
5977  {
5978  case HTML_UL:
5980  {
5981  DocHtmlList *list = new DocHtmlList(m_parser,this,tagHtmlAttribs,DocHtmlList::Unordered);
5982  m_children.push_back(std::unique_ptr<DocHtmlList>(list));
5983  retval=list->parse();
5984  }
5985  break;
5986  case HTML_OL:
5988  {
5989  DocHtmlList *list = new DocHtmlList(m_parser,this,tagHtmlAttribs,DocHtmlList::Ordered);
5990  m_children.push_back(std::unique_ptr<DocHtmlList>(list));
5991  retval=list->parse();
5992  }
5993  break;
5994  case HTML_LI:
5995  if (m_parser.context.token->emptyTag) break;
5996  if (!insideUL(this) && !insideOL(this))
5997  {
5998  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"lonely <li> tag found");
5999  }
6000  else
6001  {
6002  retval=RetVal_ListItem;
6003  }
6004  break;
6005  case HTML_BOLD:
6007  break;
6008  case HTML_S:
6010  break;
6011  case HTML_STRIKE:
6013  break;
6014  case HTML_DEL:
6016  break;
6017  case HTML_UNDERLINE:
6019  break;
6020  case HTML_INS:
6022  break;
6023  case HTML_CODE:
6024  if (m_parser.context.token->emptyTag) break;
6025  if (/*getLanguageFromFileName(m_parser.context.fileName)==SrcLangExt_CSharp ||*/ m_parser.context.xmlComment)
6026  // for C# source or inside a <summary> or <remark> section we
6027  // treat <code> as an XML tag (so similar to @code)
6028  {
6030  retval = handleStartCode();
6031  }
6032  else // normal HTML markup
6033  {
6035  }
6036  break;
6037  case HTML_EMPHASIS:
6039  break;
6040  case HTML_DIV:
6042  break;
6043  case HTML_SPAN:
6045  break;
6046  case HTML_SUB:
6048  break;
6049  case HTML_SUP:
6051  break;
6052  case HTML_CENTER:
6054  break;
6055  case HTML_SMALL:
6057  break;
6058  case HTML_PRE:
6059  if (m_parser.context.token->emptyTag) break;
6063  break;
6064  case HTML_P:
6065  retval=TK_NEWPARA;
6066  break;
6067  case HTML_DL:
6069  {
6070  DocHtmlDescList *list = new DocHtmlDescList(m_parser,this,tagHtmlAttribs);
6071  m_children.push_back(std::unique_ptr<DocHtmlDescList>(list));
6072  retval=list->parse();
6073  }
6074  break;
6075  case HTML_DT:
6076  retval = RetVal_DescTitle;
6077  break;
6078  case HTML_DD:
6079  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag <dd> found");
6080  break;
6081  case HTML_TABLE:
6083  {
6084  DocHtmlTable *table = new DocHtmlTable(m_parser,this,tagHtmlAttribs);
6085  m_children.push_back(std::unique_ptr<DocHtmlTable>(table));
6086  retval=table->parse();
6087  }
6088  break;
6089  case HTML_TR:
6090  retval = RetVal_TableRow;
6091  break;
6092  case HTML_TD:
6093  retval = RetVal_TableCell;
6094  break;
6095  case HTML_TH:
6096  retval = RetVal_TableHCell;
6097  break;
6098  case HTML_CAPTION:
6099  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag <caption> found");
6100  break;
6101  case HTML_BR:
6102  {
6103  m_children.push_back(std::make_unique<DocLineBreak>(m_parser,this,tagHtmlAttribs));
6104  }
6105  break;
6106  case HTML_HR:
6107  {
6108  m_children.push_back(std::make_unique<DocHorRuler>(m_parser,this,tagHtmlAttribs));
6109  }
6110  break;
6111  case HTML_A:
6112  retval = m_parser.handleAHref(this,m_children,tagHtmlAttribs);
6113  break;
6114  case HTML_H1:
6115  if (!m_parser.context.token->emptyTag) retval=handleHtmlHeader(tagHtmlAttribs,1);
6116  break;
6117  case HTML_H2:
6118  if (!m_parser.context.token->emptyTag) retval=handleHtmlHeader(tagHtmlAttribs,2);
6119  break;
6120  case HTML_H3:
6121  if (!m_parser.context.token->emptyTag) retval=handleHtmlHeader(tagHtmlAttribs,3);
6122  break;
6123  case HTML_H4:
6124  if (!m_parser.context.token->emptyTag) retval=handleHtmlHeader(tagHtmlAttribs,4);
6125  break;
6126  case HTML_H5:
6127  if (!m_parser.context.token->emptyTag) retval=handleHtmlHeader(tagHtmlAttribs,5);
6128  break;
6129  case HTML_H6:
6130  if (!m_parser.context.token->emptyTag) retval=handleHtmlHeader(tagHtmlAttribs,6);
6131  break;
6132  case HTML_IMG:
6133  {
6134  m_parser.handleImg(this,m_children,tagHtmlAttribs);
6135  }
6136  break;
6137  case HTML_BLOCKQUOTE:
6139  {
6140  DocHtmlBlockQuote *block = new DocHtmlBlockQuote(m_parser,this,tagHtmlAttribs);
6141  m_children.push_back(std::unique_ptr<DocHtmlBlockQuote>(block));
6142  retval = block->parse();
6143  }
6144  break;
6145 
6146  case XML_SUMMARY:
6147  case XML_REMARKS:
6148  case XML_EXAMPLE:
6150  // fall through
6151  case XML_VALUE:
6152  case XML_PARA:
6153  if (!m_children.empty())
6154  {
6155  retval = TK_NEWPARA;
6156  }
6157  break;
6158  case XML_DESCRIPTION:
6159  if (insideTable(this))
6160  {
6161  retval=RetVal_TableCell;
6162  }
6163  break;
6164  case XML_C:
6166  break;
6167  case XML_PARAM:
6168  case XML_TYPEPARAM:
6169  {
6171  QCString paramName;
6172  if (findAttribute(tagHtmlAttribs,"name",&paramName))
6173  {
6174  if (paramName.isEmpty())
6175  {
6176  if (Config_getBool(WARN_NO_PARAMDOC))
6177  {
6178  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"empty 'name' attribute for <param%s> tag.",tagId==XML_PARAM?"":"type");
6179  }
6180  }
6181  else
6182  {
6183  retval = handleParamSection(paramName,
6185  TRUE);
6186  }
6187  }
6188  else
6189  {
6190  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing 'name' attribute from <param%s> tag.",tagId==XML_PARAM?"":"type");
6191  }
6192  }
6193  break;
6194  case XML_PARAMREF:
6195  case XML_TYPEPARAMREF:
6196  {
6197  QCString paramName;
6198  if (findAttribute(tagHtmlAttribs,"name",&paramName))
6199  {
6200  //printf("paramName=%s\n",qPrint(paramName));
6201  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Italic,tagName,TRUE));
6202  m_children.push_back(std::make_unique<DocWord>(m_parser,this,paramName));
6203  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Italic,tagName,FALSE));
6204  if (retval!=TK_WORD) m_children.push_back(std::make_unique<DocWhiteSpace>(m_parser,this," "));
6205  }
6206  else
6207  {
6208  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type");
6209  }
6210  }
6211  break;
6212  case XML_EXCEPTION:
6213  {
6215  QCString exceptName;
6216  if (findAttribute(tagHtmlAttribs,"cref",&exceptName))
6217  {
6218  unescapeCRef(exceptName);
6219  retval = handleParamSection(exceptName,DocParamSect::Exception,TRUE);
6220  }
6221  else
6222  {
6223  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing 'cref' attribute from <exception> tag.");
6224  }
6225  }
6226  break;
6227  case XML_ITEM:
6228  case XML_LISTHEADER:
6229  if (insideTable(this))
6230  {
6231  retval=RetVal_TableRow;
6232  }
6233  else if (insideUL(this) || insideOL(this))
6234  {
6235  retval=RetVal_ListItem;
6236  }
6237  else
6238  {
6239  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"lonely <item> tag found");
6240  }
6241  break;
6242  case XML_RETURNS:
6246  break;
6247  case XML_TERM:
6248  //m_children.push_back(std::make_unique<DocStyleChange>(this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Bold,TRUE));
6249  if (insideTable(this))
6250  {
6251  retval=RetVal_TableCell;
6252  }
6253  break;
6254  case XML_SEE:
6255  // I'm not sure if <see> is the same as <seealso> or if it
6256  // should you link a member without producing a section. The
6257  // C# specification is extremely vague about this (but what else
6258  // can we expect from Microsoft...)
6259  {
6260  QCString cref;
6261  //printf("XML_SEE: empty tag=%d\n",m_parser.context.token->emptyTag);
6262  if (findAttribute(tagHtmlAttribs,"cref",&cref))
6263  {
6264  unescapeCRef(cref);
6265  if (m_parser.context.token->emptyTag) // <see cref="..."/> style
6266  {
6267  bool inSeeBlock = m_parser.context.inSeeBlock;
6268  m_parser.context.token->name = cref;
6271  m_parser.context.inSeeBlock = inSeeBlock;
6272  }
6273  else // <see cref="...">...</see> style
6274  {
6275  //DocRef *ref = new DocRef(this,cref);
6276  //m_children.append(ref);
6277  //ref->parse();
6279  DocLink *lnk = new DocLink(m_parser,this,cref);
6280  m_children.push_back(std::unique_ptr<DocLink>(lnk));
6281  QCString leftOver = lnk->parse(FALSE,TRUE);
6282  if (!leftOver.isEmpty())
6283  {
6284  m_children.push_back(std::make_unique<DocWord>(m_parser,this,leftOver));
6285  }
6286  }
6287  }
6288  else if (findAttribute(tagHtmlAttribs,"langword",&cref)) // <see langword="..."/> or <see langword="..."></see>
6289  {
6290  bool inSeeBlock = m_parser.context.inSeeBlock;
6291  m_parser.context.token->name = cref;
6293  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,tagName,TRUE));
6295  m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,tagName,FALSE));
6296  m_parser.context.inSeeBlock = inSeeBlock;
6297  }
6298  else
6299  {
6300  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing 'cref' or 'langword' attribute from <see> tag.");
6301  }
6302  }
6303  break;
6304  case XML_SEEALSO:
6305  {
6307  QCString cref;
6308  if (findAttribute(tagHtmlAttribs,"cref",&cref))
6309  {
6310  unescapeCRef(cref);
6311  // Look for an existing "see" section
6312  DocSimpleSect *ss=0;
6313  for (const auto &n : m_children)
6314  {
6315  if (n->kind()==Kind_SimpleSect && ((DocSimpleSect *)n.get())->type()==DocSimpleSect::See)
6316  {
6317  ss = (DocSimpleSect *)n.get();
6318  }
6319  }
6320 
6321  if (!ss) // start new section
6322  {
6324  m_children.push_back(std::unique_ptr<DocSimpleSect>(ss));
6325  }
6326 
6327  ss->appendLinkWord(cref);
6328  retval = RetVal_OK;
6329  }
6330  else
6331  {
6332  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing 'cref' attribute from <seealso> tag.");
6333  }
6334  }
6335  break;
6336  case XML_LIST:
6337  {
6338  QCString type;
6339  findAttribute(tagHtmlAttribs,"type",&type);
6341  HtmlAttribList emptyList;
6342  if (type=="number")
6343  {
6344  listType=DocHtmlList::Ordered;
6345  }
6346  if (type=="table")
6347  {
6348  DocHtmlTable *table = new DocHtmlTable(m_parser,this,emptyList);
6349  m_children.push_back(std::unique_ptr<DocHtmlTable>(table));
6350  retval=table->parseXml();
6351  }
6352  else
6353  {
6354  DocHtmlList *list = new DocHtmlList(m_parser,this,emptyList,listType);
6355  m_children.push_back(std::unique_ptr<DocHtmlList>(list));
6356  retval=list->parseXml();
6357  }
6358  }
6359  break;
6360  case XML_INCLUDE:
6361  case XML_PERMISSION:
6362  // These tags are defined in .Net but are currently unsupported
6364  break;
6365  case HTML_UNKNOWN:
6366  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unsupported xml/html tag <%s> found", qPrint(tagName));
6367  m_children.push_back(std::make_unique<DocWord>(m_parser,this, "<"+tagName+m_parser.context.token->attribsStr+">"));
6368  break;
6369  case XML_INHERITDOC:
6370  handleInheritDoc();
6371  break;
6372  default:
6373  // we should not get here!
6374  ASSERT(0);
6375  break;
6376  }
6377  return retval;
6378 }
6379 
6381 {
6382  DBG(("handleHtmlEndTag(%s)\n",qPrint(tagName)));
6383  int tagId = Mappers::htmlTagMapper->map(tagName);
6384  int retval=RetVal_OK;
6385  switch (tagId)
6386  {
6387  case HTML_UL:
6388  if (!insideUL(this))
6389  {
6390  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"found </ul> tag without matching <ul>");
6391  }
6392  else
6393  {
6394  retval=RetVal_EndList;
6395  }
6396  break;
6397  case HTML_OL:
6398  if (!insideOL(this))
6399  {
6400  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"found </ol> tag without matching <ol>");
6401  }
6402  else
6403  {
6404  retval=RetVal_EndList;
6405  }
6406  break;
6407  case HTML_LI:
6408  if (!insideLI(this))
6409  {
6410  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"found </li> tag without matching <li>");
6411  }
6412  else
6413  {
6414  // ignore </li> tags
6415  }
6416  break;
6417  case HTML_BLOCKQUOTE:
6418  retval=RetVal_EndBlockQuote;
6419  break;
6420  //case HTML_PRE:
6421  // if (!insidePRE(this))
6422  // {
6423  // warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"found </pre> tag without matching <pre>");
6424  // }
6425  // else
6426  // {
6427  // retval=RetVal_EndPre;
6428  // }
6429  // break;
6430  case HTML_BOLD:
6432  break;
6433  case HTML_S:
6435  break;
6436  case HTML_STRIKE:
6438  break;
6439  case HTML_DEL:
6441  break;
6442  case HTML_UNDERLINE:
6444  break;
6445  case HTML_INS:
6447  break;
6448  case HTML_CODE:
6450  break;
6451  case HTML_EMPHASIS:
6453  break;
6454  case HTML_DIV:
6456  break;
6457  case HTML_SPAN:
6459  break;
6460  case HTML_SUB:
6462  break;
6463  case HTML_SUP:
6465  break;
6466  case HTML_CENTER:
6468  break;
6469  case HTML_SMALL:
6471  break;
6472  case HTML_PRE:
6476  break;
6477  case HTML_P:
6478  retval=TK_NEWPARA;
6479  break;
6480  case HTML_DL:
6481  retval=RetVal_EndDesc;
6482  break;
6483  case HTML_DT:
6484  // ignore </dt> tag
6485  break;
6486  case HTML_DD:
6487  // ignore </dd> tag
6488  break;
6489  case HTML_TABLE:
6490  retval=RetVal_EndTable;
6491  break;
6492  case HTML_TR:
6493  // ignore </tr> tag
6494  break;
6495  case HTML_TD:
6496  // ignore </td> tag
6497  break;
6498  case HTML_TH:
6499  // ignore </th> tag
6500  break;
6501  case HTML_CAPTION:
6502  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </caption> found");
6503  break;
6504  case HTML_BR:
6505  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Illegal </br> tag found\n");
6506  break;
6507  case HTML_H1:
6508  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </h1> found");
6509  break;
6510  case HTML_H2:
6511  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </h2> found");
6512  break;
6513  case HTML_H3:
6514  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </h3> found");
6515  break;
6516  case HTML_H4:
6517  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </h4> found");
6518  break;
6519  case HTML_H5:
6520  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </h5> found");
6521  break;
6522  case HTML_H6:
6523  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </h6> found");
6524  break;
6525  case HTML_IMG:
6526  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </img> found");
6527  break;
6528  case HTML_HR:
6529  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Illegal </hr> tag found\n");
6530  break;
6531  case HTML_A:
6532  //warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected tag </a> found");
6533  // ignore </a> tag (can be part of <a name=...></a>
6534  break;
6535 
6536  case XML_TERM:
6537  //m_children.push_back(std::make_unique<DocStyleChange>(this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Bold,FALSE));
6538  break;
6539  case XML_SUMMARY:
6540  case XML_REMARKS:
6541  case XML_PARA:
6542  case XML_VALUE:
6543  case XML_EXAMPLE:
6544  case XML_PARAM:
6545  case XML_LIST:
6546  case XML_TYPEPARAM:
6547  case XML_RETURNS:
6548  case XML_SEE:
6549  case XML_SEEALSO:
6550  case XML_EXCEPTION:
6551  case XML_INHERITDOC:
6552  retval = RetVal_CloseXml;
6553  break;
6554  case XML_C:
6556  break;
6557  case XML_ITEM:
6558  case XML_LISTHEADER:
6559  case XML_INCLUDE:
6560  case XML_PERMISSION:
6561  case XML_DESCRIPTION:
6562  case XML_PARAMREF:
6563  case XML_TYPEPARAMREF:
6564  // These tags are defined in .Net but are currently unsupported
6565  break;
6566  case HTML_UNKNOWN:
6567  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unsupported xml/html tag </%s> found", qPrint(tagName));
6568  m_children.push_back(std::make_unique<DocWord>(m_parser,this,"</"+tagName+">"));
6569  break;
6570  default:
6571  // we should not get here!
6572  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected end tag %s\n",qPrint(tagName));
6573  ASSERT(0);
6574  break;
6575  }
6576  return retval;
6577 }
6578 
6580 {
6581  DBG(("DocPara::parse() start\n"));
6582  auto ns = AutoNodeStack(m_parser,this);
6583  // handle style commands "inherited" from the previous paragraph
6585  int tok;
6586  int retval=0;
6587  while ((tok=m_parser.tokenizer.lex())) // get the next token
6588  {
6589 reparsetoken:
6590  DBG(("token %s at %d",DocTokenizer::tokToString(tok),m_parser.tokenizer.getLineNr()));
6591  if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
6592  tok==TK_COMMAND_AT || tok == TK_COMMAND_BS || tok==TK_HTMLTAG
6593  )
6594  {
6595  DBG((" name=%s",qPrint(m_parser.context.token->name)));
6596  }
6597  DBG(("\n"));
6598  switch(tok)
6599  {
6600  case TK_WORD:
6601  m_children.push_back(std::make_unique<DocWord>(m_parser,this,m_parser.context.token->name));
6602  break;
6603  case TK_LNKWORD:
6605  break;
6606  case TK_URL:
6607  m_children.push_back(std::make_unique<DocURL>(m_parser,this,m_parser.context.token->name,m_parser.context.token->isEMailAddr));
6608  break;
6609  case TK_WHITESPACE:
6610  {
6611  // prevent leading whitespace and collapse multiple whitespace areas
6612  DocNode::Kind k;
6613  if (insidePRE(this) || // all whitespace is relevant
6614  (
6615  // remove leading whitespace
6616  !m_children.empty() &&
6617  // and whitespace after certain constructs
6618  (k=m_children.back()->kind())!=DocNode::Kind_HtmlDescList &&
6624  /*k!=DocNode::Kind_Verbatim &&*/
6629  )
6630  )
6631  {
6632  m_children.push_back(std::make_unique<DocWhiteSpace>(m_parser,this,m_parser.context.token->chars));
6633  }
6634  }
6635  break;
6636  case TK_LISTITEM:
6637  {
6638  DBG(("found list item at %d parent=%d\n",m_parser.context.token->indent,parent()->kind()));
6639  DocNode *n=parent();
6640  while (n && n->kind()!=DocNode::Kind_AutoList) n=n->parent();
6641  if (n) // we found an auto list up in the hierarchy
6642  {
6643  DocAutoList *al = (DocAutoList *)n;
6644  DBG(("previous list item at %d\n",al->indent()));
6645  if (al->indent()>=m_parser.context.token->indent)
6646  // new item at the same or lower indent level
6647  {
6648  retval=TK_LISTITEM;
6649  goto endparagraph;
6650  }
6651  }
6652 
6653  // determine list depth
6654  int depth = 0;
6655  n=parent();
6656  while(n)
6657  {
6658  if (n->kind() == DocNode::Kind_AutoList &&
6659  ((DocAutoList*)n)->isEnumList()) depth++;
6660  n=n->parent();
6661  }
6662 
6663  // first item or sub list => create new list
6664  DocAutoList *al=0;
6665  do
6666  {
6668  m_parser.context.token->isEnumList,depth);
6669  m_children.push_back(std::unique_ptr<DocAutoList>(al));
6670  retval = al->parse();
6671  } while (retval==TK_LISTITEM && // new list
6672  al->indent()==m_parser.context.token->indent // at same indent level
6673  );
6674 
6675  // check the return value
6676  if (retval==RetVal_SimpleSec) // auto list ended due to simple section command
6677  {
6678  // Reparse the token that ended the section at this level,
6679  // so a new simple section will be started at this level.
6680  // This is the same as unputting the last read token and continuing.
6682  if (m_parser.context.token->name.left(4)=="rcs:") // RCS section
6683  {
6686  tok = TK_RCSTAG;
6687  }
6688  else // other section
6689  {
6690  tok = TK_COMMAND_BS;
6691  }
6692  DBG(("reparsing command %s\n",qPrint(m_parser.context.token->name)));
6693  goto reparsetoken;
6694  }
6695  else if (retval==TK_ENDLIST)
6696  {
6697  if (al->indent()>m_parser.context.token->indent) // end list
6698  {
6699  goto endparagraph;
6700  }
6701  else // continue with current paragraph
6702  {
6703  }
6704  }
6705  else // paragraph ended due to TK_NEWPARA, TK_LISTITEM, or EOF
6706  {
6707  goto endparagraph;
6708  }
6709  }
6710  break;
6711  case TK_ENDLIST:
6712  DBG(("Found end of list inside of paragraph at line %d\n",m_parser.tokenizer.getLineNr()));
6714  {
6716  DocAutoList *al = (DocAutoList *)parent()->parent();
6717  if (al->indent()>=m_parser.context.token->indent)
6718  {
6719  // end of list marker ends this paragraph
6720  retval=TK_ENDLIST;
6721  goto endparagraph;
6722  }
6723  else
6724  {
6725  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"End of list marker found "
6726  "has invalid indent level");
6727  }
6728  }
6729  else
6730  {
6731  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"End of list marker found without any preceding "
6732  "list items");
6733  }
6734  break;
6735  case TK_COMMAND_AT:
6736  // fall through
6737  case TK_COMMAND_BS:
6738  {
6739  // see if we have to start a simple section
6741  DocNode *n=parent();
6742  while (n &&
6745  )
6746  {
6747  n=n->parent();
6748  }
6749  if (cmd&SIMPLESECT_BIT)
6750  {
6751  if (n) // already in a simple section
6752  {
6753  // simple section cannot start in this paragraph, need
6754  // to unwind the stack and remember the command.
6756  retval=RetVal_SimpleSec;
6757  goto endparagraph;
6758  }
6759  }
6760  // see if we are in a simple list
6761  n=parent();
6762  while (n && n->kind()!=DocNode::Kind_SimpleListItem) n=n->parent();
6763  if (n)
6764  {
6765  if (cmd==CMD_LI)
6766  {
6767  retval=RetVal_ListItem;
6768  goto endparagraph;
6769  }
6770  }
6771 
6772  // handle the command
6773  retval=handleCommand(m_parser.context.token->name,tok);
6774  DBG(("handleCommand returns %s\n",DocTokenizer::retvalToString(retval)));
6775 
6776  // check the return value
6777  if (retval==RetVal_SimpleSec)
6778  {
6779  // Reparse the token that ended the section at this level,
6780  // so a new simple section will be started at this level.
6781  // This is the same as unputting the last read token and continuing.
6783  if (m_parser.context.token->name.left(4)=="rcs:") // RCS section
6784  {
6787  tok = TK_RCSTAG;
6788  }
6789  else // other section
6790  {
6791  tok = TK_COMMAND_BS;
6792  }
6793  DBG(("reparsing command %s\n",qPrint(m_parser.context.token->name)));
6794  goto reparsetoken;
6795  }
6796  else if (retval==RetVal_OK)
6797  {
6798  // the command ended normally, keep scanning for new tokens.
6799  retval = 0;
6800  }
6801  else if (retval>0 && retval<RetVal_OK)
6802  {
6803  // the command ended with a new command, reparse this token
6804  tok = retval;
6805  goto reparsetoken;
6806  }
6807  else // end of file, end of paragraph, start or end of section
6808  // or some auto list marker
6809  {
6810  goto endparagraph;
6811  }
6812  }
6813  break;
6814  case TK_HTMLTAG:
6815  {
6816  if (!m_parser.context.token->endTag) // found a start tag
6817  {
6819  }
6820  else // found an end tag
6821  {
6823  }
6824  if (retval==RetVal_OK)
6825  {
6826  // the command ended normally, keep scanner for new tokens.
6827  retval = 0;
6828  }
6829  else
6830  {
6831  goto endparagraph;
6832  }
6833  }
6834  break;
6835  case TK_SYMBOL:
6836  {
6838  if (s!=DocSymbol::Sym_Unknown)
6839  {
6840  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,s));
6841  }
6842  else
6843  {
6844  m_children.push_back(std::make_unique<DocWord>(m_parser,this,m_parser.context.token->name));
6845  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unsupported symbol %s found",
6847  }
6848  break;
6849  }
6850  case TK_NEWPARA:
6851  retval=TK_NEWPARA;
6852  goto endparagraph;
6853  case TK_RCSTAG:
6854  {
6855  DocNode *n=parent();
6856  while (n &&
6859  )
6860  {
6861  n=n->parent();
6862  }
6863  if (n) // already in a simple section
6864  {
6865  // simple section cannot start in this paragraph, need
6866  // to unwind the stack and remember the command.
6869  retval=RetVal_SimpleSec;
6870  goto endparagraph;
6871  }
6872 
6873  // see if we are in a simple list
6875  m_children.push_back(std::unique_ptr<DocSimpleSect>(ss));
6876  ss->parseRcs();
6877  }
6878  break;
6879  default:
6881  "Found unexpected token (id=%s)\n",DocTokenizer::tokToString(tok));
6882  break;
6883  }
6884  }
6885  retval=0;
6886 endparagraph:
6888  DBG(("DocPara::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
6889  const DocNode *n = m_parser.context.nodeStack.top();
6891  retval==TK_NEWPARA && m_parser.context.token->name.lower() == "p")
6892  {
6893  ((DocPara *)n)->setAttribs(m_parser.context.token->attribs);
6894  }
6895  INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM ||
6896  retval==TK_ENDLIST || retval>RetVal_OK
6897  );
6898 
6899  return retval;
6900 }
6901 
6902 //--------------------------------------------------------------------------
6903 
6905 {
6906  DBG(("DocSection::parse() start %s level=%d\n",qPrint(m_parser.context.token->sectionId),m_level));
6907  int retval=RetVal_OK;
6908  auto ns = AutoNodeStack(m_parser,this);
6909 
6910  if (!m_id.isEmpty())
6911  {
6913  if (sec)
6914  {
6915  m_file = sec->fileName();
6916  m_anchor = sec->label();
6917  m_title = sec->title();
6918  if (m_title.isEmpty()) m_title = sec->label();
6919  }
6920  }
6921 
6922  // first parse any number of paragraphs
6923  bool isFirst=TRUE;
6924  DocPara *lastPar=0;
6925  do
6926  {
6927  DocPara *par = new DocPara(m_parser,this);
6928  if (isFirst) { par->markFirst(); isFirst=FALSE; }
6929  retval=par->parse();
6930  if (!par->isEmpty())
6931  {
6932  m_children.push_back(std::unique_ptr<DocPara>(par));
6933  lastPar=par;
6934  }
6935  else
6936  {
6937  delete par;
6938  }
6939  if (retval==TK_LISTITEM)
6940  {
6941  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Invalid list item found");
6942  }
6943  if (retval==RetVal_Internal)
6944  {
6945  DocInternal *in = new DocInternal(m_parser,this);
6946  m_children.push_back(std::unique_ptr<DocInternal>(in));
6947  retval = in->parse(m_level+1);
6948  if (retval==RetVal_EndInternal)
6949  {
6950  retval=RetVal_OK;
6951  }
6952  }
6953  } while (retval!=0 &&
6954  retval!=RetVal_Section &&
6955  retval!=RetVal_Subsection &&
6956  retval!=RetVal_Subsubsection &&
6957  retval!=RetVal_Paragraph &&
6958  retval!=RetVal_EndInternal
6959  );
6960 
6961  if (lastPar) lastPar->markLast();
6962 
6963  //printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel);
6964 
6965  while (true)
6966  {
6968  {
6969  // then parse any number of nested sections
6970  while (retval==RetVal_Subsection) // more sections follow
6971  {
6972  DocSection *s=new DocSection(m_parser,this,
6974  m_children.push_back(std::unique_ptr<DocSection>(s));
6975  retval = s->parse();
6976  }
6977  break;
6978  }
6980  {
6982  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected subsubsection command found inside %s!",g_sectionLevelToName[m_level]);
6983  // then parse any number of nested sections
6984  while (retval==RetVal_Subsubsection) // more sections follow
6985  {
6986  DocSection *s=new DocSection(m_parser,this,
6988  m_children.push_back(std::unique_ptr<DocSection>(s));
6989  retval = s->parse();
6990  }
6991  if (!(m_level<Doxygen::subpageNestingLevel+2 && retval == RetVal_Subsection)) break;
6992  }
6993  else if (retval==RetVal_Paragraph && m_level<=std::min(5,Doxygen::subpageNestingLevel+3))
6994  {
6996  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected paragraph command found inside %s!",g_sectionLevelToName[m_level]);
6997  // then parse any number of nested sections
6998  while (retval==RetVal_Paragraph) // more sections follow
6999  {
7000  DocSection *s=new DocSection(m_parser,this,
7002  m_children.push_back(std::unique_ptr<DocSection>(s));
7003  retval = s->parse();
7004  }
7005  if (!(m_level<Doxygen::subpageNestingLevel+3 && (retval == RetVal_Subsection || retval == RetVal_Subsubsection))) break;
7006  }
7007  else
7008  {
7009  break;
7010  }
7011  }
7012 
7013  INTERNAL_ASSERT(retval==0 ||
7014  retval==RetVal_Section ||
7015  retval==RetVal_Subsection ||
7016  retval==RetVal_Subsubsection ||
7017  retval==RetVal_Paragraph ||
7018  retval==RetVal_Internal ||
7019  retval==RetVal_EndInternal
7020  );
7021 
7022  DBG(("DocSection::parse() end: retval=%s\n",DocTokenizer::retvalToString(retval)));
7023  return retval;
7024 }
7025 
7026 //--------------------------------------------------------------------------
7027 
7029 {
7030  DBG(("DocText::parse() start\n"));
7031  auto ns = AutoNodeStack(m_parser,this);
7033 
7034  int tok;
7035  while ((tok=m_parser.tokenizer.lex())) // get the next token
7036  {
7037  switch(tok)
7038  {
7039  case TK_WORD:
7040  m_children.push_back(std::make_unique<DocWord>(m_parser,this,m_parser.context.token->name));
7041  break;
7042  case TK_WHITESPACE:
7043  m_children.push_back(std::make_unique<DocWhiteSpace>(m_parser,this,m_parser.context.token->chars));
7044  break;
7045  case TK_SYMBOL:
7046  {
7048  if (s!=DocSymbol::Sym_Unknown)
7049  {
7050  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,s));
7051  }
7052  else
7053  {
7054  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unsupported symbol %s found",
7056  }
7057  }
7058  break;
7059  case TK_COMMAND_AT:
7060  // fall through
7061  case TK_COMMAND_BS:
7062  switch (Mappers::cmdMapper->map(m_parser.context.token->name))
7063  {
7064  case CMD_BSLASH:
7065  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_BSlash));
7066  break;
7067  case CMD_AT:
7068  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_At));
7069  break;
7070  case CMD_LESS:
7071  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Less));
7072  break;
7073  case CMD_GREATER:
7074  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Greater));
7075  break;
7076  case CMD_AMP:
7077  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Amp));
7078  break;
7079  case CMD_DOLLAR:
7080  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Dollar));
7081  break;
7082  case CMD_HASH:
7083  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Hash));
7084  break;
7085  case CMD_DCOLON:
7086  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_DoubleColon));
7087  break;
7088  case CMD_PERCENT:
7089  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Percent));
7090  break;
7091  case CMD_NDASH:
7092  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
7093  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
7094  break;
7095  case CMD_MDASH:
7096  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
7097  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
7098  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
7099  break;
7100  case CMD_QUOTE:
7101  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Quot));
7102  break;
7103  case CMD_PUNT:
7104  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Dot));
7105  break;
7106  case CMD_PLUS:
7107  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Plus));
7108  break;
7109  case CMD_MINUS:
7110  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Minus));
7111  break;
7112  case CMD_EQUAL:
7113  m_children.push_back(std::make_unique<DocSymbol>(m_parser,this,DocSymbol::Sym_Equal));
7114  break;
7115  default:
7116  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Unexpected command '%s' found",
7118  break;
7119  }
7120  break;
7121  default:
7124  break;
7125  }
7126  }
7127 
7129 
7130  DBG(("DocText::parse() end\n"));
7131 }
7132 
7133 
7134 //--------------------------------------------------------------------------
7135 
7137 {
7138  DBG(("DocRoot::parse() start\n"));
7139  auto ns = AutoNodeStack(m_parser,this);
7141  int retval=0;
7142 
7143  // first parse any number of paragraphs
7144  bool isFirst=TRUE;
7145  DocPara *lastPar=0;
7146  do
7147  {
7148  DocPara *par = new DocPara(m_parser,this);
7149  if (isFirst) { par->markFirst(); isFirst=FALSE; }
7150  retval=par->parse();
7151  if (!par->isEmpty() || !par->attribs().empty())
7152  {
7153  m_children.push_back(std::unique_ptr<DocPara>(par));
7154  lastPar=par;
7155  }
7156  else
7157  {
7158  delete par;
7159  }
7160  if (retval==RetVal_Paragraph)
7161  {
7162  if (!m_parser.context.token->sectionId.startsWith("autotoc_md"))
7163  {
7164  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"found paragraph command (id: '%s') outside of subsubsection context!",qPrint(m_parser.context.token->sectionId));
7165  }
7166  while (retval==RetVal_Paragraph)
7167  {
7169  {
7171  if (sec)
7172  {
7173  DocSection *s=new DocSection(m_parser,this,
7175  m_children.push_back(std::unique_ptr<DocSection>(s));
7176  retval = s->parse();
7177  }
7178  else
7179  {
7180  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Invalid paragraph id '%s'; ignoring paragraph",qPrint(m_parser.context.token->sectionId));
7181  retval = 0;
7182  }
7183  }
7184  else
7185  {
7186  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing id for paragraph; ignoring paragraph");
7187  retval = 0;
7188  }
7189  }
7190  }
7191  if (retval==RetVal_Subsubsection)
7192  {
7193  if (!(m_parser.context.token->sectionId.startsWith("autotoc_md")))
7194  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"found subsubsection command (id: '%s') outside of subsection context!",qPrint(m_parser.context.token->sectionId));
7195  while (retval==RetVal_Subsubsection)
7196  {
7198  {
7200  if (sec)
7201  {
7202  DocSection *s=new DocSection(m_parser,this,
7204  m_children.push_back(std::unique_ptr<DocSection>(s));
7205  retval = s->parse();
7206  }
7207  else
7208  {
7209  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Invalid subsubsection id '%s'; ignoring subsubsection",qPrint(m_parser.context.token->sectionId));
7210  retval = 0;
7211  }
7212  }
7213  else
7214  {
7215  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing id for subsubsection; ignoring subsubsection");
7216  retval = 0;
7217  }
7218  }
7219  }
7220  if (retval==RetVal_Subsection)
7221  {
7222  if (!m_parser.context.token->sectionId.startsWith("autotoc_md"))
7223  {
7224  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"found subsection command (id: '%s') outside of section context!",qPrint(m_parser.context.token->sectionId));
7225  }
7226  while (retval==RetVal_Subsection)
7227  {
7229  {
7231  if (sec)
7232  {
7233  DocSection *s=new DocSection(m_parser,this,
7235  m_children.push_back(std::unique_ptr<DocSection>(s));
7236  retval = s->parse();
7237  }
7238  else
7239  {
7240  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Invalid subsection id '%s'; ignoring subsection",qPrint(m_parser.context.token->sectionId));
7241  retval = 0;
7242  }
7243  }
7244  else
7245  {
7246  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing id for subsection; ignoring subsection");
7247  retval = 0;
7248  }
7249  }
7250  }
7251  if (retval==TK_LISTITEM)
7252  {
7253  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Invalid list item found");
7254  }
7255  if (retval==RetVal_Internal)
7256  {
7257  DocInternal *in = new DocInternal(m_parser,this);
7258  m_children.push_back(std::unique_ptr<DocInternal>(in));
7259  retval = in->parse(1);
7260  }
7261  } while (retval!=0 && retval!=RetVal_Section);
7262  if (lastPar) lastPar->markLast();
7263 
7264  //printf("DocRoot::parse() retval=%d %d\n",retval,RetVal_Section);
7265  // then parse any number of level1 sections
7266  while (retval==RetVal_Section)
7267  {
7269  {
7271  if (sec)
7272  {
7273  DocSection *s=new DocSection(m_parser,this,
7275  m_children.push_back(std::unique_ptr<DocSection>(s));
7276  retval = s->parse();
7277  }
7278  else
7279  {
7280  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Invalid section id '%s'; ignoring section",qPrint(m_parser.context.token->sectionId));
7281  retval = 0;
7282  }
7283  }
7284  else
7285  {
7286  warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"Missing id for section; ignoring section");
7287  retval = 0;
7288  }
7289  }
7290 
7292 
7293  DBG(("DocRoot::parse() end\n"));
7294 }
7295 
7296 static QCString extractCopyDocId(const char *data, uint &j, uint len)
7297 {
7298  uint s=j;
7299  uint e=j;
7300  int round=0;
7301  bool insideDQuote=FALSE;
7302  bool insideSQuote=FALSE;
7303  bool found=FALSE;
7304  while (j<len && !found)
7305  {
7306  if (!insideSQuote && !insideDQuote)
7307  {
7308  switch (data[j])
7309  {
7310  case '(': round++; break;
7311  case ')': round--; break;
7312  case '"': insideDQuote=TRUE; break;
7313  case '\'': insideSQuote=TRUE; break;
7314  case ' ': // fall through
7315  case '\t': // fall through
7316  case '\n':
7317  found=(round==0);
7318  break;
7319  }
7320  }
7321  else if (insideSQuote) // look for single quote end
7322  {
7323  if (data[j]=='\'' && (j==0 || data[j]!='\\'))
7324  {
7325  insideSQuote=FALSE;
7326  }
7327  }
7328  else if (insideDQuote) // look for double quote end
7329  {
7330  if (data[j]=='"' && (j==0 || data[j]!='\\'))
7331  {
7332  insideDQuote=FALSE;
7333  }
7334  }
7335  if (!found) j++;
7336  }
7337  if (qstrncmp(data+j," const",6)==0)
7338  {
7339  j+=6;
7340  }
7341  else if (qstrncmp(data+j," volatile",9)==0)
7342  {
7343  j+=9;
7344  }
7345  e=j;
7346  QCString id(data+s,e-s);
7347  //printf("extractCopyDocId='%s' input='%s'\n",qPrint(id),&data[s]);
7348  return id;
7349 }
7350 
7351 // macro to check if the input starts with a specific command.
7352 // note that data[i] should point to the start of the command (\ or @ character)
7353 // and the sizeof(str) returns the size of str including the '\0' terminator;
7354 // a fact we abuse to skip over the start of the command character.
7355 #define CHECK_FOR_COMMAND(str,action) \
7356  do if ((i+sizeof(str)<len) && qstrncmp(data+i+1,str,sizeof(str)-1)==0) \
7357  { j=i+sizeof(str); action; } while(0)
7358 
7359 static uint isCopyBriefOrDetailsCmd(const char *data, uint i,uint len,bool &brief)
7360 {
7361  int j=0;
7362  if (i==0 || (data[i-1]!='@' && data[i-1]!='\\')) // not an escaped command
7363  {
7364  CHECK_FOR_COMMAND("copybrief",brief=TRUE); // @copybrief or \copybrief
7365  CHECK_FOR_COMMAND("copydetails",brief=FALSE); // @copydetails or \copydetails
7366  }
7367  return j;
7368 }
7369 
7370 static uint isVerbatimSection(const char *data,uint i,uint len,QCString &endMarker)
7371 {
7372  int j=0;
7373  if (i==0 || (data[i-1]!='@' && data[i-1]!='\\')) // not an escaped command
7374  {
7375  CHECK_FOR_COMMAND("dot",endMarker="enddot");
7376  CHECK_FOR_COMMAND("code",endMarker="endcode");
7377  CHECK_FOR_COMMAND("msc",endMarker="endmsc");
7378  CHECK_FOR_COMMAND("verbatim",endMarker="endverbatim");
7379  CHECK_FOR_COMMAND("latexonly",endMarker="endlatexonly");
7380  CHECK_FOR_COMMAND("htmlonly",endMarker="endhtmlonly");
7381  CHECK_FOR_COMMAND("xmlonly",endMarker="endxmlonly");
7382  CHECK_FOR_COMMAND("rtfonly",endMarker="endrtfonly");
7383  CHECK_FOR_COMMAND("manonly",endMarker="endmanonly");
7384  CHECK_FOR_COMMAND("docbookonly",endMarker="enddocbookonly");
7385  CHECK_FOR_COMMAND("startuml",endMarker="enduml");
7386  }
7387  //printf("isVerbatimSection(%s)=%d)\n",qPrint(QCString(&data[i]).left(10)),j);
7388  return j;
7389 }
7390 
7391 static uint skipToEndMarker(const char *data,uint i,uint len,const QCString &endMarker)
7392 {
7393  while (i<len)
7394  {
7395  if ((data[i]=='@' || data[i]=='\\') && // start of command character
7396  (i==0 || (data[i-1]!='@' && data[i-1]!='\\'))) // that is not escaped
7397  {
7398  if (i+endMarker.length()+1<=len && qstrncmp(data+i+1,endMarker.data(),endMarker.length())==0)
7399  {
7400  return i+endMarker.length()+1;
7401  }
7402  }
7403  i++;
7404  }
7405  // oops no endmarker found...
7406  return i<len ? i+1 : len;
7407 }
7408 
7410 {
7411  //printf("processCopyDoc start '%s'\n",data);
7412  GrowBuf buf;
7413  uint i=0;
7414  while (i<len)
7415  {
7416  char c = data[i];
7417  if (c=='@' || c=='\\') // look for a command
7418  {
7419  bool isBrief=TRUE;
7420  uint j=isCopyBriefOrDetailsCmd(data,i,len,isBrief);
7421  if (j>0)
7422  {
7423  // skip whitespace
7424  while (j<len && (data[j]==' ' || data[j]=='\t')) j++;
7425  // extract the argument
7426  QCString id = extractCopyDocId(data,j,len);
7427  const Definition *def = 0;
7428  QCString doc,brief;
7429  //printf("resolving docs='%s'\n",qPrint(id));
7430  if (findDocsForMemberOrCompound(id,&doc,&brief,&def))
7431  {
7432  //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,qPrint(brief),qPrint(doc),isBrief);
7433  auto it = std::find(context.copyStack.begin(),context.copyStack.end(),def);
7434  if (it==context.copyStack.end()) // definition not parsed earlier
7435  {
7436  context.copyStack.push_back(def);
7437  if (isBrief)
7438  {
7439  uint l=brief.length();
7440  buf.addStr(processCopyDoc(brief.data(),l));
7441  }
7442  else
7443  {
7444  uint l=doc.length();
7445  buf.addStr(processCopyDoc(doc.data(),l));
7446  }
7447  context.copyStack.pop_back();
7448  }
7449  else
7450  {
7452  "Found recursive @copy%s or @copydoc relation for argument '%s'.\n",
7453  isBrief?"brief":"details",qPrint(id));
7454  }
7455  }
7456  else
7457  {
7459  "@copy%s or @copydoc target '%s' not found", isBrief?"brief":"details",
7460  qPrint(id));
7461  }
7462  // skip over command
7463  i=j;
7464  }
7465  else
7466  {
7467  QCString endMarker;
7468  uint k = isVerbatimSection(data,i,len,endMarker);
7469  if (k>0)
7470  {
7471  int orgPos = i;
7472  i=skipToEndMarker(data,k,len,endMarker);
7473  buf.addStr(data+orgPos,i-orgPos);
7474  }
7475  else
7476  {
7477  buf.addChar(c);
7478  i++;
7479  }
7480  }
7481  }
7482  else // not a command, just copy
7483  {
7484  buf.addChar(c);
7485  i++;
7486  }
7487  }
7488  len = buf.getPos();
7489  buf.addChar(0);
7490  return buf.get();
7491 }
7492 
7493 //---------------------------------------------------------------------------
7494 
7496  const QCString &fileName,int startLine,
7497  const Definition *ctx,const MemberDef *md,
7498  const QCString &input,bool indexWords,
7499  bool isExample, const QCString &exampleName,
7500  bool singleLine, bool linkFromIndex,
7501  bool markdownSupport)
7502 {
7503  DocParser &parser = dynamic_cast<DocParser&>(parserIntf);
7504  //printf("validatingParseDoc(%s,%s)=[%s]\n",ctx?qPrint(ctx->name()):"<none>",
7505  // md?qPrint(md->name()):"<none>",
7506  // input);
7507  //printf("========== validating %s at line %d\n",qPrint(fileName),startLine);
7508  //printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",qPrint(input));
7509  //parser.context.token = new TokenInfo;
7510 
7511  // store parser state so we can re-enter this function if needed
7512  //bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
7513  parser.pushContext();
7514 
7515  if (ctx && ctx!=Doxygen::globalScope &&
7518  )
7519  )
7520  {
7521  parser.context.context = ctx->name();
7522  }
7523  else if (ctx && ctx->definitionType()==Definition::TypePage)
7524  {
7525  const Definition *scope = (toPageDef(ctx))->getPageScope();
7526  if (scope && scope!=Doxygen::globalScope) parser.context.context = scope->name();
7527  }
7528  else if (ctx && ctx->definitionType()==Definition::TypeGroup)
7529  {
7530  const Definition *scope = (toGroupDef(ctx))->getGroupScope();
7531  if (scope && scope!=Doxygen::globalScope) parser.context.context = scope->name();
7532  }
7533  else
7534  {
7535  parser.context.context = "";
7536  }
7537  parser.context.scope = ctx;
7538 
7539  if (indexWords && Doxygen::searchIndex)
7540  {
7541  if (md)
7542  {
7543  parser.context.searchUrl=md->getOutputFileBase();
7545  }
7546  else if (ctx)
7547  {
7548  parser.context.searchUrl=ctx->getOutputFileBase();
7550  }
7551  }
7552  else
7553  {
7554  parser.context.searchUrl="";
7555  }
7556 
7557  parser.context.fileName = fileName;
7558  parser.context.relPath = (!linkFromIndex && ctx) ?
7560  QCString("");
7561  //printf("ctx->name=%s relPath=%s\n",qPrint(ctx->name()),qPrint(parser.context.relPath));
7562  parser.context.memberDef = md;
7563  while (!parser.context.nodeStack.empty()) parser.context.nodeStack.pop();
7564  while (!parser.context.styleStack.empty()) parser.context.styleStack.pop();
7565  while (!parser.context.initialStyleStack.empty()) parser.context.initialStyleStack.pop();
7566  parser.context.inSeeBlock = FALSE;
7567  parser.context.xmlComment = FALSE;
7568  parser.context.insideHtmlLink = FALSE;
7569  parser.context.includeFileText = "";
7570  parser.context.includeFileOffset = 0;
7571  parser.context.includeFileLength = 0;
7572  parser.context.isExample = isExample;
7573  parser.context.exampleName = exampleName;
7574  parser.context.hasParamCommand = FALSE;
7575  parser.context.hasReturnCommand = FALSE;
7576  parser.context.retvalsFound.clear();
7577  parser.context.paramsFound.clear();
7578  parser.context.markdownSupport = markdownSupport;
7579 
7580  //printf("Starting comment block at %s:%d\n",qPrint(parser.context.fileName),startLine);
7581  parser.tokenizer.setLineNr(startLine);
7582  uint ioLen = input.length();
7583  QCString inpStr = parser.processCopyDoc(input.data(),ioLen);
7584  if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n')
7585  {
7586  inpStr+='\n';
7587  }
7588  //printf("processCopyDoc(in='%s' out='%s')\n",input,qPrint(inpStr));
7589  parser.tokenizer.init(inpStr.data(),parser.context.fileName,markdownSupport);
7590 
7591  // build abstract syntax tree
7592  DocRoot *root = new DocRoot(parser,md!=0,singleLine);
7593  root->parse();
7594 
7595 
7597  {
7598  // pretty print the result
7600  root->accept(v);
7601  delete v;
7602  }
7603 
7606 
7607  // TODO: These should be called at the end of the program.
7608  //parser.tokenizer.cleanup();
7609  //Mappers::cmdMapper->freeInstance();
7610  //Mappers::htmlTagMapper->freeInstance();
7611 
7612  // restore original parser state
7613  parser.popContext();
7614 
7615  //printf(">>>>>> end validatingParseDoc(%s,%s)\n",ctx?qPrint(ctx->name()):"<none>",
7616  // md?qPrint(md->name()):"<none>");
7617 
7618  return root;
7619 }
7620 
7622 {
7623  DocParser &parser = dynamic_cast<DocParser&>(parserIntf);
7624  // store parser state so we can re-enter this function if needed
7625  parser.pushContext();
7626 
7627  //printf("------------ input ---------\n%s\n"
7628  // "------------ end input -----\n",input);
7629  //parser.context.token = new TokenInfo;
7630  parser.context.context = "";
7631  parser.context.fileName = "<parseText>";
7632  parser.context.relPath = "";
7633  parser.context.memberDef = 0;
7634  while (!parser.context.nodeStack.empty()) parser.context.nodeStack.pop();
7635  while (!parser.context.styleStack.empty()) parser.context.styleStack.pop();
7636  while (!parser.context.initialStyleStack.empty()) parser.context.initialStyleStack.pop();
7637  parser.context.inSeeBlock = FALSE;
7638  parser.context.xmlComment = FALSE;
7639  parser.context.insideHtmlLink = FALSE;
7640  parser.context.includeFileText = "";
7641  parser.context.includeFileOffset = 0;
7642  parser.context.includeFileLength = 0;
7643  parser.context.isExample = FALSE;
7644  parser.context.exampleName = "";
7645  parser.context.hasParamCommand = FALSE;
7646  parser.context.hasReturnCommand = FALSE;
7647  parser.context.retvalsFound.clear();
7648  parser.context.paramsFound.clear();
7649  parser.context.searchUrl="";
7650 
7651  DocText *txt = new DocText(parser);
7652 
7653  if (!input.isEmpty())
7654  {
7655  parser.tokenizer.setLineNr(1);
7656  parser.tokenizer.init(input.data(),parser.context.fileName,Config_getBool(MARKDOWN_SUPPORT));
7657 
7658  // build abstract syntax tree
7659  txt->parse();
7660 
7662  {
7663  // pretty print the result
7665  txt->accept(v);
7666  delete v;
7667  }
7668  }
7669 
7670  // restore original parser state
7671  parser.popContext();
7672  return txt;
7673 }
7674 
7675 DocRef *createRef(IDocParser &parserIntf,const QCString &target,const QCString &context)
7676 {
7677  DocParser &parser = dynamic_cast<DocParser&>(parserIntf);
7678  return new DocRef(parser,0,target,context);
7679 }
7680 
7681 void docFindSections(const QCString &input,
7682  const Definition *d,
7683  const QCString &fileName)
7684 {
7685  DocParser parser;
7686  parser.tokenizer.findSections(input,d,fileName);
7687 }
7688 
DocHtmlBlockQuote
Node representing an HTML blockquote
Definition: docparser.h:1433
CMD_DOLLAR
@ CMD_DOLLAR
Definition: cmdmapper.h:42
DocIndexEntry::m_entry
QCString m_entry
Definition: docparser.h:695
formula.h
DocAutoListItem
Node representing an item of a auto list
Definition: docparser.h:720
Definition::getSourceFileBase
virtual QCString getSourceFileBase() const =0
DocHRef
Node representing a Hypertext reference
Definition: docparser.h:936
CMD_ENDRTFONLY
@ CMD_ENDRTFONLY
Definition: cmdmapper.h:118
DocStyleChange
Node representing a style change
Definition: docparser.h:343
StringVector
std::vector< std::string > StringVector
Definition: containers.h:32
DocInternalRef::DocInternalRef
DocInternalRef(DocParser &parser, DocNode *parent, const QCString &target)
Definition: docparser.cpp:2350
DocTokenizer::setStateAnchor
void setStateAnchor()
DocPara::handleLink
void handleLink(const QCString &cmdName, bool isJavaLink)
Definition: docparser.cpp:5063
SrcLangExt_Unknown
@ SrcLangExt_Unknown
Definition: types.h:43
DocVerbatim
Node representing a verbatim, unparsed text fragment
Definition: docparser.h:510
TokenInfo::emptyTag
bool emptyTag
Definition: doctokenizer.h:101
HtmlEntityMapper::name2sym
DocSymbol::SymType name2sym(const QCString &symName) const
Give code of the requested HTML entity name
Definition: htmlentity.cpp:471
DocPara::handleCommand
int handleCommand(const QCString &cmdName, const int tok)
Definition: docparser.cpp:5354
DocParserContext::searchUrl
QCString searchUrl
Definition: docparser.cpp:120
insideUL
static bool insideUL(DocNode *n)
Definition: docparser.cpp:584
DocSimpleSect::appendLinkWord
void appendLinkWord(const QCString &word)
Definition: docparser.cpp:4478
DocParserContext
Parser's context to store all global variables.
Definition: docparser.cpp:99
DocStyleChangeStack
std::stack< const DocStyleChange * > DocStyleChangeStack
Definition: docparser.cpp:95
DocSymbol::Sym_Amp
@ Sym_Amp
Definition: docparser.h:445
RefItem::text
QCString text() const
Definition: reflist.h:44
TokenInfo::endTag
bool endTag
Definition: doctokenizer.h:100
RetVal_Subsubsection
@ RetVal_Subsubsection
Definition: doctokenizer.h:64
DocStyleChange::position
uint position() const
Definition: docparser.h:371
DocTitle
Node representing a simple section title
Definition: docparser.h:736
DocHtmlRow::parse
int parse()
Definition: docparser.cpp:3425
RetVal_TableCell
@ RetVal_TableCell
Definition: doctokenizer.h:73
DocParser::popContext
void popContext()
Definition: docparser.cpp:222
DocHtmlList::parse
int parse()
Definition: docparser.cpp:4048
DocImage::m_name
QCString m_name
Definition: docparser.h:792
TokenInfo::attribsStr
QCString attribsStr
Definition: doctokenizer.h:102
DocCite::m_text
QCString m_text
Definition: docparser.h:338
CMD_SUBSECTION
@ CMD_SUBSECTION
Definition: cmdmapper.h:85
DocPara
Node representing a paragraph in the documentation tree
Definition: docparser.h:1178
fileinfo.h
findFileDef
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition: util.cpp:3222
DocInclude::HtmlInclude
@ HtmlInclude
Definition: docparser.h:566
HTML_UNDERLINE
@ HTML_UNDERLINE
Definition: cmdmapper.h:185
CMD_ENDMANONLY
@ CMD_ENDMANONLY
Definition: cmdmapper.h:105
AutoNodeStack::~AutoNodeStack
~AutoNodeStack()
Definition: docparser.cpp:191
warn_incomplete_doc
void warn_incomplete_doc(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:178
CMD_ENDVERBATIM
@ CMD_ENDVERBATIM
Definition: cmdmapper.h:51
toGroupDef
GroupDef * toGroupDef(Definition *d)
Definition: groupdef.cpp:1766
DocHtmlCell::rowSpan
uint rowSpan() const
Definition: docparser.cpp:3341
markdownFileNameToId
QCString markdownFileNameToId(const QCString &fileName)
processes string s and converts markdown into doxygen/html commands.
Definition: markdown.cpp:3053
CMD_BSLASH
@ CMD_BSLASH
Definition: cmdmapper.h:38
Definition::docLine
virtual int docLine() const =0
DocSymbol::SymType
SymType
Definition: docparser.h:388
DocHRef::parse
int parse()
Definition: docparser.cpp:2993
DocSymbol::Sym_rdquo
@ Sym_rdquo
Definition: docparser.h:437
RefListManager::instance
static RefListManager & instance()
Definition: reflist.h:120
cite.h
DocSimpleSect::Return
@ Return
Definition: docparser.h:1116
HTML_H5
@ HTML_H5
Definition: cmdmapper.h:179
DocHtmlCell::alignment
Alignment alignment() const
Definition: docparser.cpp:3365
getDefs
bool getDefs(const QCString &scName, const QCString &mbName, const QCString &args, const MemberDef *&md, const ClassDef *&cd, const FileDef *&fd, const NamespaceDef *&nd, const GroupDef *&gd, bool forceEmptyScope, const FileDef *currentFile, bool checkCV)
Definition: util.cpp:2208
resolveLink
bool resolveLink(const QCString &scName, const QCString &lr, bool, const Definition **resContext, QCString &resAnchor)
Definition: util.cpp:3037
CMD_ENDXMLONLY
@ CMD_ENDXMLONLY
Definition: cmdmapper.h:52
DocNode::isPreformatted
bool isPreformatted() const
Definition: docparser.h:177
DocParserContext::token
TokenInfo * token
Definition: docparser.cpp:129
CMD_FORMULA
@ CMD_FORMULA
Definition: cmdmapper.h:54
DocHtmlCell::colSpan
uint colSpan() const
Definition: docparser.cpp:3353
DocParser::context
DocParserContext context
Definition: docparser.cpp:175
DocTokenizer::tokToString
static const char * tokToString(int token)
CMD_EMPHASIS
@ CMD_EMPHASIS
Definition: cmdmapper.h:45
CMD_LESS
@ CMD_LESS
Definition: cmdmapper.h:65
CMD_STARTCODE
@ CMD_STARTCODE
Definition: cmdmapper.h:91
insideOL
static bool insideOL(DocNode *n)
Definition: docparser.cpp:598
ArgumentList::push_back
void push_back(const Argument &a)
Definition: arguments.h:95
DocHtmlDescData::m_attribs
HtmlAttribList m_attribs
Definition: docparser.h:1312
DocHtmlCaption::m_hasCaptionId
bool m_hasCaptionId
Definition: docparser.h:1365
DocTokenizer::setStateBlock
void setStateBlock()
DocParserContext::scope
const Definition * scope
Definition: docparser.cpp:101
CMD_POST
@ CMD_POST
Definition: cmdmapper.h:74
CMD_ENDCODE
@ CMD_ENDCODE
Definition: cmdmapper.h:46
DocHtmlTable
Node representing a HTML table
Definition: docparser.h:1405
DocTokenizer::setStateInternalRef
void setStateInternalRef()
TK_WORD
@ TK_WORD
Definition: doctokenizer.h:46
DocHtmlCaption::m_attribs
HtmlAttribList m_attribs
Definition: docparser.h:1364
Definition::TypeMember
@ TypeMember
Definition: definition.h:90
Portable::pathSeparator
QCString pathSeparator()
Definition: portable.cpp:347
XML_SEE
@ XML_SEE
Definition: cmdmapper.h:207
DocSecRefItem::m_file
QCString m_file
Definition: docparser.h:1041
DocPara::handleInclude
void handleInclude(const QCString &cmdName, DocInclude::Type t)
Definition: docparser.cpp:5118
DocParserContext::relPath
QCString relPath
Definition: docparser.cpp:111
MemberDef::briefDescription
virtual QCString briefDescription(bool abbr=FALSE) const =0
DocNodeStack
std::stack< const DocNode * > DocNodeStack
Definition: docparser.cpp:94
DocNode::Kind_AutoListItem
@ Kind_AutoListItem
Definition: docparser.h:105
DocInclude::Type
Type
Definition: docparser.h:566
CMD_AT
@ CMD_AT
Definition: cmdmapper.h:33
DocTokenizer::setStatePlantUML
void setStatePlantUML()
XML_PARA
@ XML_PARA
Definition: cmdmapper.h:201
DocCite::DocCite
DocCite(DocParser &parser, DocNode *parent, const QCString &target, const QCString &context)
Definition: docparser.cpp:2540
CMD_SECTION
@ CMD_SECTION
Definition: cmdmapper.h:83
Definition
The common base class of all entity definitions found in the sources.
Definition: definition.h:76
DocInternalRef::m_anchor
QCString m_anchor
Definition: docparser.h:932
DocHtmlCaption::attribs
const HtmlAttribList & attribs() const
Definition: docparser.h:1357
VhdlDocGen::createFlowChart
static void createFlowChart(const MemberDef *)
Definition: vhdldocgen.cpp:2742
DocSymbol::Sym_Dot
@ Sym_Dot
Definition: docparser.h:447
MemberDef::documentation
virtual QCString documentation() const =0
Markdown::process
QCString process(const QCString &input, int &startNewlines, bool fromParseInput=false)
Definition: markdown.cpp:3002
CitationManager::find
const CiteInfo * find(const QCString &label) const
Return the citation info for a given label.
Definition: cite.cpp:75
CompAccept
Default accept implementation for compound nodes in the abstract syntax tree.
Definition: docparser.h:196
CMD_SETSCOPE
@ CMD_SETSCOPE
Definition: cmdmapper.h:132
XML_SUMMARY
@ XML_SUMMARY
Definition: cmdmapper.h:209
DocParser::handleParameterType
void handleParameterType(DocNode *parent, DocNodeList &children, const QCString &paramTypes)
Definition: docparser.cpp:1127
Doxygen::imageNameLinkedMap
static FileNameLinkedMap * imageNameLinkedMap
Definition: doxygen.h:89
DocSimpleSect::Warning
@ Warning
Definition: docparser.h:1117
DocImage::isSVG
bool isSVG() const
Definition: docparser.cpp:2868
RetVal_EndDesc
@ RetVal_EndDesc
Definition: doctokenizer.h:71
CMD_BOLD
@ CMD_BOLD
Definition: cmdmapper.h:37
Dir::remove
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition: dir.cpp:256
relativePathToRoot
QCString relativePathToRoot(const QCString &name)
Definition: util.cpp:3656
TokenInfo::isEnumList
bool isEnumList
Definition: doctokenizer.h:82
DocHtmlCell::isFirst
bool isFirst() const
Definition: docparser.h:1325
CMD_COPYDOC
@ CMD_COPYDOC
Definition: cmdmapper.h:40
DocAutoList::DocAutoList
DocAutoList(DocParser &parser, DocNode *parent, int indent, bool isEnumList, int depth)
Definition: docparser.cpp:4304
NamespaceDef
An abstract interface of a namespace symbol.
Definition: namespacedef.h:54
Dir
Class representing a directory in the file system
Definition: dir.h:68
DocImage::Xml
@ Xml
Definition: docparser.h:774
DocParserContext::retvalsFound
StringMultiSet retvalsFound
Definition: docparser.cpp:115
DocParser::contextStack
std::stack< DocParserContext > contextStack
Definition: docparser.cpp:174
DocHtmlTable::parse
int parse()
Definition: docparser.cpp:3551
ActiveRowSpan
Helper class to compute the grid for an HTML style table
Definition: docparser.cpp:3663
DocPara::handleIncludeOperator
void handleIncludeOperator(const QCString &cmdName, DocIncOperator::Type t)
Definition: docparser.cpp:4863
Definition::isLinkable
virtual bool isLinkable() const =0
DocSection::DocSection
DocSection(DocParser &parser, DocNode *parent, int level, const QCString &id)
Definition: docparser.h:1004
DocPara::attribs
const HtmlAttribList & attribs() const
Definition: docparser.h:1215
HTML_LI
@ HTML_LI
Definition: cmdmapper.h:165
DocRoot
Root node of documentation tree
Definition: docparser.h:1457
DocFormula::DocFormula
DocFormula(DocParser &parser, DocNode *parent, int id)
Definition: docparser.cpp:2161
Doxygen::diaFileNameLinkedMap
static FileNameLinkedMap * diaFileNameLinkedMap
Definition: doxygen.h:92
DocVerbatim::HtmlOnly
@ HtmlOnly
Definition: docparser.h:513
pagedef.h
cmdmapper.h
DocSymbol::Sym_Pipe
@ Sym_Pipe
Definition: docparser.h:446
QCString::length
uint length() const
Returns the length of the string, not counting the 0-terminator.
Definition: qcstring.h:147
DocStyleChange::Center
@ Center
Definition: docparser.h:349
CMD_INTERNAL
@ CMD_INTERNAL
Definition: cmdmapper.h:61
HtmlAttribList
Class representing a list of HTML attributes.
Definition: htmlattrib.h:30
RowSpanList
std::vector< ActiveRowSpan > RowSpanList
List of ActiveRowSpan classes.
Definition: docparser.cpp:3671
DocNode::Kind_HtmlHeader
@ Kind_HtmlHeader
Definition: docparser.h:133
DocHtmlListItem::parseXml
int parseXml()
Definition: docparser.cpp:4014
CMD_ENDDOT
@ CMD_ENDDOT
Definition: cmdmapper.h:101
DocSecRefItem::m_anchor
QCString m_anchor
Definition: docparser.h:1044
GrowBuf::get
char * get()
Definition: growbuf.h:94
DocHtmlHeader
Node Html heading
Definition: docparser.h:957
DocSymbol::Sym_Equal
@ Sym_Equal
Definition: docparser.h:447
ArgumentList
This class represents an function or template argument list.
Definition: arguments.h:59
DocIncOperator::m_includeFileName
QCString m_includeFileName
Definition: docparser.h:654
DocSimpleSect::Unknown
@ Unknown
Definition: docparser.h:1116
TokenInfo::name
QCString name
Definition: doctokenizer.h:74
DocTokenizer::findSections
void findSections(const QCString &input, const Definition *d, const QCString &fileName)
DocStyleChange::Strike
@ Strike
Definition: docparser.h:356
RetVal_OK
@ RetVal_OK
Command starting with \
Definition: doctokenizer.h:59
DocParamList::markLast
void markLast(bool b=TRUE)
Definition: docparser.h:1243
memberdef.h
RetVal_CloseXml
@ RetVal_CloseXml
Definition: doctokenizer.h:78
DocParser::internalValidatingParseDoc
int internalValidatingParseDoc(DocNode *parent, DocNodeList &children, const QCString &doc)
Definition: docparser.cpp:1742
DocPara::markFirst
void markFirst(bool v=TRUE)
Definition: docparser.h:1186
Definition::getDefLine
virtual int getDefLine() const =0
QCString::findRev
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition: qcstring.cpp:86
DocParserContext::nodeStack
DocNodeStack nodeStack
Definition: docparser.cpp:106
DocHtmlCaption::m_file
QCString m_file
Definition: docparser.h:1366
DocParser::handleInitialStyleCommands
void handleInitialStyleCommands(DocPara *parent, DocNodeList &children)
Definition: docparser.cpp:927
DocTokenizer::setStateManOnly
void setStateManOnly()
DocInclude::Snippet
@ Snippet
Definition: docparser.h:567
DocHtmlListItem
Node representing a HTML list item
Definition: docparser.h:1286
Doxygen::dotFileNameLinkedMap
static FileNameLinkedMap * dotFileNameLinkedMap
Definition: doxygen.h:90
QCString::isEmpty
bool isEmpty() const
Returns TRUE iff the string is empty
Definition: qcstring.h:144
DocStyleChange::Del
@ Del
Definition: docparser.h:358
TokenInfo::chars
QCString chars
Definition: doctokenizer.h:105
CMD_LINK
@ CMD_LINK
Definition: cmdmapper.h:69
reg::match
bool match(const std::string &str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition: regex.cpp:729
DocParser::handlePendingStyleCommands
void handlePendingStyleCommands(DocNode *parent, DocNodeList &children)
Definition: docparser.cpp:912
DocSymbol::Sym_Percent
@ Sym_Percent
Definition: docparser.h:446
DocVhdlFlow
Node representing a VHDL flow chart
Definition: docparser.h:860
DocNode
Abstract node interface with type information.
Definition: docparser.h:96
section.h
DocSymbol::Sym_Dollar
@ Sym_Dollar
Definition: docparser.h:446
DocParamList::parse
int parse(const QCString &cmdName)
Definition: docparser.cpp:4528
Doxygen::pageLinkedMap
static PageLinkedMap * pageLinkedMap
Definition: doxygen.h:82
DocParser::findAndCopyImage
QCString findAndCopyImage(const QCString &fileName, DocImage::Type type, bool doWarn=true)
Definition: docparser.cpp:266
namespacedef.h
Doxygen::indexList
static IndexList * indexList
Definition: doxygen.h:114
DocVerbatim::Msc
@ Msc
Definition: docparser.h:513
GroupDef::groupTitle
virtual QCString groupTitle() const =0
Definition::TypePage
@ TypePage
Definition: definition.h:93
CMD_VERSION
@ CMD_VERSION
Definition: cmdmapper.h:96
MemberDef::inheritsDocsFrom
virtual const MemberDef * inheritsDocsFrom() const =0
DocSimpleSect::parse
int parse(bool userTitle, bool needsSeparator)
Definition: docparser.cpp:4391
DocHtmlDescData
Node representing a HTML description data
Definition: docparser.h:1303
DocXRefItem::m_key
QCString m_key
Definition: docparser.h:763
CMD_AUTHORS
@ CMD_AUTHORS
Definition: cmdmapper.h:36
DocPara::handleSection
void handleSection(const QCString &cmdName)
Definition: docparser.cpp:5245
XML_VALUE
@ XML_VALUE
Definition: cmdmapper.h:213
DocSymbol::Sym_Hash
@ Sym_Hash
Definition: docparser.h:446
DocParser::handleLinkedWord
void handleLinkedWord(DocNode *parent, DocNodeList &children, bool ignoreAutoLinkFlag=FALSE)
Definition: docparser.cpp:1015
copyFile
bool copyFile(const QCString &src, const QCString &dest)
Copies the contents of file with name src to the newly created file with name dest.
Definition: util.cpp:6439
RetVal_EndTable
@ RetVal_EndTable
Definition: doctokenizer.h:75
QCString::size
uint size() const
Returns the length of the string, not counting the 0-terminator.
Definition: qcstring.h:150
DocTokenizer::setStateXmlOnly
void setStateXmlOnly()
RefItem
This struct represents an item in the list of references.
Definition: reflist.h:30
DocHtmlDescTitle
Node representing a Html description item
Definition: docparser.h:973
DocInclude::XmlInclude
@ XmlInclude
Definition: docparser.h:568
DocVerbatim::PlantUML
@ PlantUML
Definition: docparser.h:513
DocParser::handleStyleEnter
void handleStyleEnter(DocNode *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName, const HtmlAttribList *attribs)
Definition: docparser.cpp:855
HTML_CODE
@ HTML_CODE
Definition: cmdmapper.h:155
split
static std::vector< QCString > split(const QCString &str, const QCString &sep, bool allowEmptyEntries=FALSE, bool cleanup=TRUE)
Definition: template.cpp:47
RetVal_Subsection
@ RetVal_Subsection
Definition: doctokenizer.h:63
DocImage::DocBook
@ DocBook
Definition: docparser.h:774
toMemberDef
MemberDef * toMemberDef(Definition *d)
Definition: memberdef.cpp:6088
HTML_SMALL
@ HTML_SMALL
Definition: cmdmapper.h:154
XML_REMARKS
@ XML_REMARKS
Definition: cmdmapper.h:205
CMD_CITE
@ CMD_CITE
Definition: cmdmapper.h:115
DocStyleChange::Italic
@ Italic
Definition: docparser.h:347
DocTokenizer::setStateParam
void setStateParam()
SrcLangExt
SrcLangExt
Language as given by extension
Definition: types.h:41
RetVal_TableRow
@ RetVal_TableRow
Definition: doctokenizer.h:72
DocHtmlRow::isHeading
bool isHeading() const
Definition: docparser.h:1382
DocNode::Kind_HtmlDescList
@ Kind_HtmlDescList
Definition: docparser.h:118
FormulaManager::instance
static FormulaManager & instance()
Definition: formula.cpp:65
DocHtmlCaption::m_anchor
QCString m_anchor
Definition: docparser.h:1367
TokenInfo::attribs
HtmlAttribList attribs
Definition: doctokenizer.h:99
DocTokenizer::setStateDot
void setStateDot()
DocTokenizer::init
void init(const char *input, const QCString &fileName, bool markdownSupport)
HTML_PRE
@ HTML_PRE
Definition: cmdmapper.h:157
CMD_PRE
@ CMD_PRE
Definition: cmdmapper.h:75
DocVerbatim::Code
@ Code
Definition: docparser.h:513
DocParserContext::includeFileShowLineNo
bool includeFileShowLineNo
Definition: docparser.cpp:127
Doxygen::globalScope
static NamespaceDefMutable * globalScope
Definition: doxygen.h:102
DocParamSect::m_hasInOutSpecifier
bool m_hasInOutSpecifier
Definition: docparser.h:1173
DocStyleChange::Bold
@ Bold
Definition: docparser.h:346
DocParser::tokenizer
DocTokenizer tokenizer
Definition: docparser.cpp:176
CMD_LI
@ CMD_LI
Definition: cmdmapper.h:66
growbuf.h
HTML_H4
@ HTML_H4
Definition: cmdmapper.h:178
DocSymbol::Sym_rsquo
@ Sym_rsquo
Definition: docparser.h:437
DocSymbol::decodeSymbol
static SymType decodeSymbol(const QCString &symName)
Definition: docparser.cpp:1713
DocInclude::IncludeDoc
@ IncludeDoc
Definition: docparser.h:567
DocRef::anchor
QCString anchor() const
Definition: docparser.h:900
markdown.h
DocHtmlCaption::parse
int parse()
Definition: docparser.cpp:3225
DocVerbatim::RtfOnly
@ RtfOnly
Definition: docparser.h:513
QCString::str
std::string str() const
Definition: qcstring.h:442
CMD_ENDDBONLY
@ CMD_ENDDBONLY
Definition: cmdmapper.h:122
CMD_LATEXONLY
@ CMD_LATEXONLY
Definition: cmdmapper.h:64
DocParamSect::TemplateParam
@ TemplateParam
Definition: docparser.h:1156
CMD_UNKNOWN
@ CMD_UNKNOWN
Definition: cmdmapper.h:29
CMD_ENDMSC
@ CMD_ENDMSC
Definition: cmdmapper.h:103
DocSecRefItem
Node representing a reference to a section
Definition: docparser.h:1023
DocFormula::m_name
QCString m_name
Definition: docparser.h:675
XML_RETURNS
@ XML_RETURNS
Definition: cmdmapper.h:206
TK_RCSTAG
@ TK_RCSTAG
Definition: doctokenizer.h:55
CMD_COPYRIGHT
@ CMD_COPYRIGHT
Definition: cmdmapper.h:114
DocHtmlTable::m_numCols
size_t m_numCols
Definition: docparser.h:1429
CMD_SNIPPET
@ CMD_SNIPPET
Definition: cmdmapper.h:116
Definition::TypeGroup
@ TypeGroup
Definition: definition.h:91
DocStyleChange::Span
@ Span
Definition: docparser.h:354
DocNode::Kind_HtmlCell
@ Kind_HtmlCell
Definition: docparser.h:123
warn_doc_error
void warn_doc_error(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:186
DocAnchor
Node representing an anchor
Definition: docparser.h:303
CMD_SNIPPETDOC
@ CMD_SNIPPETDOC
Definition: cmdmapper.h:137
XML_EXAMPLE
@ XML_EXAMPLE
Definition: cmdmapper.h:195
DocFormula::text
QCString text() const
Definition: docparser.h:664
DocSimpleSect::parseXml
int parseXml()
Definition: docparser.cpp:4442
DocPara::handleStartCode
int handleStartCode()
Definition: docparser.cpp:5292
DocInclude::m_file
QCString m_file
Definition: docparser.h:595
DocParser
Definition: docparser.cpp:134
DocNode::Kind_HtmlRow
@ Kind_HtmlRow
Definition: docparser.h:122
DefinitionStack
std::vector< const Definition * > DefinitionStack
Definition: docparser.cpp:93
DocTokenizer::setStateMsc
void setStateMsc()
DocHtmlCell::parseXml
int parseXml()
Definition: docparser.cpp:3306
DocStyleChange::Superscript
@ Superscript
Definition: docparser.h:352
TokenInfo::simpleSectText
QCString simpleSectText
Definition: doctokenizer.h:90
CMD_ANCHOR
@ CMD_ANCHOR
Definition: cmdmapper.h:32
CMD_PAR
@ CMD_PAR
Definition: cmdmapper.h:71
err
void err(const char *fmt,...)
Definition: message.cpp:203
CMD_INCWITHLINES
@ CMD_INCWITHLINES
Definition: cmdmapper.h:106
g_sectionLevelToName
static const char * g_sectionLevelToName[]
Definition: docparser.cpp:72
DocSecRefItem::m_target
QCString m_target
Definition: docparser.h:1038
QCString::at
char & at(size_t i)
Returns a reference to the character at index i.
Definition: qcstring.h:477
DocPara::handleHtmlEndTag
int handleHtmlEndTag(const QCString &tagName)
Definition: docparser.cpp:6380
CompAccept::accept
void accept(DocVisitor *v) override
Definition: docparser.h:200
HTML_H6
@ HTML_H6
Definition: cmdmapper.h:180
GrowBuf::addStr
void addStr(const QCString &s)
Definition: growbuf.h:57
QCString::find
int find(char c, int index=0, bool cs=TRUE) const
Definition: qcstring.cpp:38
DocText
Root node of a text fragment
Definition: docparser.h:1447
DocHtmlTable::parseXml
int parseXml()
Definition: docparser.cpp:3619
DocTokenizer::setStateXmlCode
void setStateXmlCode()
DocSection::m_title
QCString m_title
Definition: docparser.h:1017
DocParser::handleAHref
int handleAHref(DocNode *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
Definition: docparser.cpp:937
DocStyleChange::styleString
const char * styleString() const
Definition: docparser.cpp:979
CitationManager::instance
static CitationManager & instance()
Definition: cite.cpp:56
DocParser::defaultHandleTitleAndSize
void defaultHandleTitleAndSize(const int cmd, DocNode *parent, DocNodeList &children, QCString &width, QCString &height)
Definition: docparser.cpp:1209
SectionType::Table
@ Table
TokenInfo::indent
int indent
Definition: doctokenizer.h:83
DocParamSect::parse
int parse(const QCString &cmdName, bool xmlContext, Direction d)
Definition: docparser.cpp:4672
DocVisitor
Abstract visitor that participates in the visitor pattern.
Definition: docvisitor.h:92
qcstring.h
CMD_LINE
@ CMD_LINE
Definition: cmdmapper.h:67
DocSimpleSect::Author
@ Author
Definition: docparser.h:1116
DocHtmlCell::Middle
@ Middle
Definition: docparser.h:1321
getClass
ClassDef * getClass(const QCString &n)
Definition: classdef.cpp:4974
DocXRefItem::m_id
int m_id
Definition: docparser.h:762
CMD_MSC
@ CMD_MSC
Definition: cmdmapper.h:102
DocPara::handleIline
void handleIline()
Definition: docparser.cpp:4851
DocParserContext::hasReturnCommand
bool hasReturnCommand
Definition: docparser.cpp:114
qstrncmp
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition: qcstring.h:91
DocSimpleSect::Note
@ Note
Definition: docparser.h:1117
DocMscFile::parse
bool parse()
Definition: docparser.cpp:2754
TK_WHITESPACE
@ TK_WHITESPACE
Definition: doctokenizer.h:48
CMD_INVARIANT
@ CMD_INVARIANT
Definition: cmdmapper.h:63
DocSymbol::Sym_Minus
@ Sym_Minus
Definition: docparser.h:447
DocInclude::DocbookInclude
@ DocbookInclude
Definition: docparser.h:568
HTML_SUP
@ HTML_SUP
Definition: cmdmapper.h:159
DocParser::processCopyDoc
QCString processCopyDoc(const char *data, uint &len)
Definition: docparser.cpp:7409
DocRef::m_refType
RefType m_refType
Definition: docparser.h:909
DocIncOperator::parse
void parse()
Definition: docparser.cpp:1978
DocTokenizer::replaceToken
void replaceToken(TokenInfo *newToken)
DocInclude::DontInclude
@ DontInclude
Definition: docparser.h:566
DocSection::m_anchor
QCString m_anchor
Definition: docparser.h:1018
DocRef::parse
void parse()
Definition: docparser.cpp:2504
Doxygen::exampleNameLinkedMap
static FileNameLinkedMap * exampleNameLinkedMap
Definition: doxygen.h:86
DocParserContext::exampleName
QCString exampleName
Definition: docparser.cpp:119
HTML_CAPTION
@ HTML_CAPTION
Definition: cmdmapper.h:153
HtmlEntityMapper::instance
static HtmlEntityMapper * instance()
Returns the one and only instance of the HTML entity mapper
Definition: htmlentity.cpp:341
CMD_ENDSECREFLIST
@ CMD_ENDSECREFLIST
Definition: cmdmapper.h:50
DocNode::Kind_IncOperator
@ Kind_IncOperator
Definition: docparser.h:132
Definition::docFile
virtual QCString docFile() const =0
MemberDef::getReference
virtual QCString getReference() const =0
DocEmoji::m_symName
QCString m_symName
Definition: docparser.h:479
DocSimpleList::parse
int parse()
Definition: docparser.cpp:4249
DocPara::handleInheritDoc
void handleInheritDoc()
Definition: docparser.cpp:5317
DocInclude::VerbInclude
@ VerbInclude
Definition: docparser.h:566
DocRef::DocRef
DocRef(DocParser &parser, DocNode *parent, const QCString &target, const QCString &context)
Definition: docparser.cpp:2386
DocHtmlCell::Top
@ Top
Definition: docparser.h:1321
SectionInfo::label
QCString label() const
Definition: section.h:65
DocSimpleSect::parseRcs
int parseRcs()
Definition: docparser.cpp:4425
DocSymbol::Sym_ldquo
@ Sym_ldquo
Definition: docparser.h:437
DocHtmlCell::setRowIndex
void setRowIndex(uint idx)
Definition: docparser.h:1341
warn
void warn(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:151
SectionInfo::ref
QCString ref() const
Definition: section.h:68
TK_SYMBOL
@ TK_SYMBOL
Definition: doctokenizer.h:53
Definition::getLanguage
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
CMD_DIAFILE
@ CMD_DIAFILE
Definition: cmdmapper.h:126
DocParser::handleInternalRef
DocInternalRef * handleInternalRef(DocNode *parent)
Definition: docparser.cpp:1150
DocImage::Html
@ Html
Definition: docparser.h:774
TK_LISTITEM
@ TK_LISTITEM
Definition: doctokenizer.h:49
XML_TERM
@ XML_TERM
Definition: cmdmapper.h:210
DocDiagramFileBase< DocDotFile >::m_name
QCString m_name
Definition: docparser.h:819
HTML_SUB
@ HTML_SUB
Definition: cmdmapper.h:158
DocVerbatim::DocbookOnly
@ DocbookOnly
Definition: docparser.h:513
Debug::isFlagSet
static bool isFlagSet(DebugMask mask)
Definition: debug.cpp:99
CMD_SA
@ CMD_SA
Definition: cmdmapper.h:81
DocNode::Kind_WhiteSpace
@ Kind_WhiteSpace
Definition: docparser.h:102
reg::Iterator
Iterator class to iterator through matches.
Definition: regex.h:242
MemberDef::isObjCMethod
virtual bool isObjCMethod() const =0
DocLinkedWord::word
QCString word() const
Definition: docparser.h:237
DocHtmlDescList
Node representing a Html description list
Definition: docparser.h:987
DocSimpleSect::Type
Type
Definition: docparser.h:1114
DocPara::handleParamSection
int handleParamSection(const QCString &cmdName, DocParamSect::Type t, bool xmlContext, int direction)
Definition: docparser.cpp:4745
GrowBuf::addChar
void addChar(char c)
Definition: growbuf.h:54
XML_PARAMREF
@ XML_PARAMREF
Definition: cmdmapper.h:203
GrowBuf
Class representing a string buffer optimised for growing.
Definition: growbuf.h:12
end
DirIterator end(const DirIterator &) noexcept
Definition: dir.cpp:128
DocAutoList::m_isEnumList
bool m_isEnumList
Definition: docparser.h:715
CMD_WARNING
@ CMD_WARNING
Definition: cmdmapper.h:97
DocIncOperator
Node representing a include/dontinclude operator block
Definition: docparser.h:606
DocHtmlTable::accept
void accept(DocVisitor *v) override
Definition: docparser.cpp:3729
DocLinkedWord::DocLinkedWord
DocLinkedWord(DocParser &parser, DocNode *parent, const QCString &word, const QCString &ref, const QCString &file, const QCString &anchor, const QCString &tooltip)
Definition: docparser.cpp:1844
DocHtmlDescTitle::parse
int parse()
Definition: docparser.cpp:3744
DocStyleChange::Style
Style
Definition: docparser.h:346
DocVerbatim::Type
Type
Definition: docparser.h:513
QCString::contains
int contains(char c, bool cs=TRUE) const
Definition: qcstring.cpp:138
toPageDef
PageDef * toPageDef(Definition *d)
Definition: pagedef.cpp:408
MemberDef::isLinkable
virtual bool isLinkable() const =0
TK_COMMAND_AT
@ TK_COMMAND_AT
Definition: doctokenizer.h:51
DocCite::m_file
QCString m_file
Definition: docparser.h:334
CMD_COPYDETAILS
@ CMD_COPYDETAILS
Definition: cmdmapper.h:110
DocHtmlCell::Valignment
Valignment
Definition: docparser.h:1321
DocHtmlList::Ordered
@ Ordered
Definition: docparser.h:1096
DocImage::Type
Type
Definition: docparser.h:774
DocIndexEntry
Node representing an entry in the index.
Definition: docparser.h:682
PageDef
A model of a page symbol.
Definition: pagedef.h:25
GroupDef
A model of a group of symbols.
Definition: groupdef.h:49
DocSymbol::Sym_Less
@ Sym_Less
Definition: docparser.h:445
CMD_REMARK
@ CMD_REMARK
Definition: cmdmapper.h:78
DocSimpleSect::User
@ User
Definition: docparser.h:1117
DocParserContext::memberDef
const MemberDef * memberDef
Definition: docparser.cpp:117
DocSecRefList
Node representing a list of section references
Definition: docparser.h:1048
Doxygen::inputNameLinkedMap
static FileNameLinkedMap * inputNameLinkedMap
Definition: doxygen.h:88
DocTokenizer::setStateLink
void setStateLink()
DocDotFile::DocDotFile
DocDotFile(DocParser &parser, DocNode *parent, const QCString &name, const QCString &context, const QCString &srcFile, int srcLine)
Definition: docparser.cpp:2707
DocEmoji::m_index
int m_index
Definition: docparser.h:480
DocVerbatim::DocVerbatim
DocVerbatim(DocParser &parser, DocNode *parent, const QCString &context, const QCString &text, Type t, bool isExample, const QCString &exampleFile, bool isBlock=FALSE, const QCString &lang=QCString())
Definition: docparser.cpp:1912
ActiveRowSpan::ActiveRowSpan
ActiveRowSpan(uint rows, uint col)
Definition: docparser.cpp:3665
DocPara::injectToken
bool injectToken(int tok, const QCString &tokText)
Definition: docparser.cpp:5286
DocParserContext::includeFileLine
int includeFileLine
Definition: docparser.cpp:126
DocTokenizer::setStateVerbatim
void setStateVerbatim()
DocSimpleSect::~DocSimpleSect
virtual ~DocSimpleSect()
Definition: docparser.cpp:4378
DocParserContext::inSeeBlock
bool inSeeBlock
Definition: docparser.cpp:103
uint
unsigned uint
Definition: qcstring.h:40
DocTokenizer::setStatePlantUMLOpt
void setStatePlantUMLOpt()
DocTokenizer::pushBackHtmlTag
void pushBackHtmlTag(const QCString &tag)
DocCite::m_relPath
QCString m_relPath
Definition: docparser.h:335
CMD_SNIPWITHLINES
@ CMD_SNIPWITHLINES
Definition: cmdmapper.h:138
HTML_IMG
@ HTML_IMG
Definition: cmdmapper.h:156
MemberDef::anchor
virtual QCString anchor() const =0
HTML_P
@ HTML_P
Definition: cmdmapper.h:174
DocParser::defaultHandleToken
bool defaultHandleToken(DocNode *parent, int tok, DocNodeList &children, bool handleWord=TRUE)
Definition: docparser.cpp:1277
DocTokenizer::setStateIline
void setStateIline()
DocNode::Section
@ Section
Definition: docparser.h:183
Mappers::htmlTagMapper
static Mapper * htmlTagMapper
Definition: cmdmapper.h:235
DocParserContext::fileName
QCString fileName
Definition: docparser.cpp:110
TokenInfo::verb
QCString verb
Definition: doctokenizer.h:93
DocFormula::m_text
QCString m_text
Definition: docparser.h:676
DocNode::Anchor
@ Anchor
Definition: docparser.h:183
extractBlock
QCString extractBlock(const QCString &text, const QCString &marker)
Returns the section of text, in between a pair of markers.
Definition: util.cpp:6453
DocPara::isFirst
bool isFirst() const
Definition: docparser.h:1188
HTML_DL
@ HTML_DL
Definition: cmdmapper.h:168
CMD_HASH
@ CMD_HASH
Definition: cmdmapper.h:56
CMD_MANONLY
@ CMD_MANONLY
Definition: cmdmapper.h:104
insideLI
static bool insideLI(DocNode *n)
Definition: docparser.cpp:571
MemberDef
A model of a class/file/namespace member symbol.
Definition: memberdef.h:45
XML_TYPEPARAMREF
@ XML_TYPEPARAMREF
Definition: cmdmapper.h:212
DocXRefItem
Node representing an item of a cross-referenced list
Definition: docparser.h:749
DocAnchor::m_file
QCString m_file
Definition: docparser.h:316
XML_CmdMask
@ XML_CmdMask
Definition: cmdmapper.h:190
DocTokenizer::endAutoList
void endAutoList()
skipToEndMarker
static uint skipToEndMarker(const char *data, uint i, uint len, const QCString &endMarker)
Definition: docparser.cpp:7391
insidePRE
static bool insidePRE(DocNode *n)
Definition: docparser.cpp:558
argListToString
QCString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition: util.cpp:1149
DocAutoList::indent
int indent() const
Definition: docparser.h:709
DocImage
Node representing an image
Definition: docparser.h:771
Doxygen::subpageNestingLevel
static int subpageNestingLevel
Definition: doxygen.h:115
Definition::TypeNamespace
@ TypeNamespace
Definition: definition.h:89
ClassDef
A abstract class representing of a compound symbol.
Definition: classdef.h:103
classlist.h
DocHtmlCell::attribs
const HtmlAttribList & attribs() const
Definition: docparser.h:1330
DocInternalRef::m_file
QCString m_file
Definition: docparser.h:930
QCString::stripWhiteSpace
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition: qcstring.h:243
DocNode::kind
virtual Kind kind() const =0
DocIncOperator::m_showLineNo
bool m_showLineNo
Definition: docparser.h:646
reg::isspace
static bool isspace(char c)
Definition: regex.cpp:33
CMD_PIPE
@ CMD_PIPE
Definition: cmdmapper.h:119
CMD_ATTENTION
@ CMD_ATTENTION
Definition: cmdmapper.h:34
DocHtmlList::Unordered
@ Unordered
Definition: docparser.h:1096
uchar
unsigned char uchar
Definition: qcstring.h:38
RefList
List of cross-referenced items
Definition: reflist.h:78
FileInfo::exists
bool exists() const
Definition: fileinfo.cpp:30
DocNodeList
std::vector< std::unique_ptr< DocNode > > DocNodeList
Definition: docparser.h:190
DocPara::handleFile
void handleFile(const QCString &cmdName)
Definition: docparser.cpp:5029
DocTokenizer::setStateSkipTitle
void setStateSkipTitle()
QCString::left
QCString left(size_t len) const
Definition: qcstring.h:212
TokenInfo::text
QCString text
Definition: doctokenizer.h:77
TokenInfo::paramDir
ParamDir paramDir
Definition: doctokenizer.h:112
DocParser::checkArgumentName
void checkArgumentName()
Definition: docparser.cpp:380
HTML_S
@ HTML_S
Definition: cmdmapper.h:188
message.h
DocPara::kind
Kind kind() const override
Definition: docparser.h:1184
CitationManager
Citation manager class.
Definition: cite.h:37
DocPara::isEmpty
bool isEmpty() const
Definition: docparser.h:1185
FileDef::name
virtual QCString name() const =0
MemberDef::isDefine
virtual bool isDefine() const =0
DocParserContext::includeFileOffset
uint includeFileOffset
Definition: docparser.cpp:124
DocParamSect::Unspecified
@ Unspecified
Definition: docparser.h:1160
DocNode::Kind_SimpleList
@ Kind_SimpleList
Definition: docparser.h:111
CMD_PARAM
@ CMD_PARAM
Definition: cmdmapper.h:72
RetVal_EndList
@ RetVal_EndList
Definition: doctokenizer.h:67
Portable::sysTimerStart
void sysTimerStart()
Definition: portable.cpp:470
CMD_INCLUDEDOC
@ CMD_INCLUDEDOC
Definition: cmdmapper.h:136
DocSimpleSect::See
@ See
Definition: docparser.h:1116
DocIncOperator::Until
@ Until
Definition: docparser.h:609
DocAnchor::m_anchor
QCString m_anchor
Definition: docparser.h:315
IndexList::addImageFile
void addImageFile(const QCString &name)
Definition: index.h:105
DocParBlock::parse
int parse()
Definition: docparser.cpp:4213
GrowBuf::getPos
uint getPos() const
Definition: growbuf.h:96
DocSimpleSect::accept
void accept(DocVisitor *v) override
Definition: docparser.cpp:4383
ArgumentList::empty
bool empty() const
Definition: arguments.h:92
RefList::find
RefItem * find(int itemId)
Definition: reflist.cpp:40
DocParser::errorHandleDefaultToken
void errorHandleDefaultToken(DocNode *parent, int tok, DocNodeList &children, const QCString &txt)
Definition: docparser.cpp:775
DocHtmlCaption
Node representing a HTML table caption
Definition: docparser.h:1352
CMD_INHERITDOC
@ CMD_INHERITDOC
Definition: cmdmapper.h:107
ClassDef::getOutputFileBase
virtual QCString getOutputFileBase() const =0
Returns the unique base name (without extension) of the class's file on disk
DocStyleChange::Ins
@ Ins
Definition: docparser.h:359
DocDiagramFileBase< DocDotFile >::m_relPath
QCString m_relPath
Definition: docparser.h:821
CMD_STARTUML
@ CMD_STARTUML
Definition: cmdmapper.h:130
DocHtmlCell::Right
@ Right
Definition: docparser.h:1320
TokenInfo
Data associated with a token used by the comment block parser.
Definition: doctokenizer.h:70
CMD_VERBINCLUDE
@ CMD_VERBINCLUDE
Definition: cmdmapper.h:95
RetVal_DescData
@ RetVal_DescData
Definition: doctokenizer.h:69
HTML_STRIKE
@ HTML_STRIKE
Definition: cmdmapper.h:184
DocHtmlRow::setVisibleCells
void setVisibleCells(uint n)
Definition: docparser.h:1393
DocInclude::SnipWithLines
@ SnipWithLines
Definition: docparser.h:567
XML_INHERITDOC
@ XML_INHERITDOC
Definition: cmdmapper.h:214
Definition::TypeFile
@ TypeFile
Definition: definition.h:88
DocRef::m_isSubPage
bool m_isSubPage
Definition: docparser.h:910
DocSymbol::Sym_At
@ Sym_At
Definition: docparser.h:445
DocHtmlRow::setRowIndex
void setRowIndex(uint idx)
Definition: docparser.h:1398
CMD_GREATER
@ CMD_GREATER
Definition: cmdmapper.h:55
CMD_RETVAL
@ CMD_RETVAL
Definition: cmdmapper.h:80
ActiveRowSpan::rowsLeft
uint rowsLeft
Definition: docparser.cpp:3666
DocInclude::m_type
Type m_type
Definition: docparser.h:598
DocHtmlDescData::parse
int parse()
Definition: docparser.cpp:3896
DocIncOperator::typeAsString
const char * typeAsString() const
Definition: docparser.h:617
DocCite::m_ref
QCString m_ref
Definition: docparser.h:336
DocImage::Latex
@ Latex
Definition: docparser.h:774
CMD_HTMLONLY
@ CMD_HTMLONLY
Definition: cmdmapper.h:58
DocParamList
Node representing a parameter list.
Definition: docparser.h:1228
CiteInfo::label
virtual QCString label() const =0
DocSimpleSect::Rcs
@ Rcs
Definition: docparser.h:1117
DocParser::handleStyleArgument
int handleStyleArgument(DocNode *parent, DocNodeList &children, const QCString &cmdName)
Definition: docparser.cpp:803
removeRedundantWhiteSpace
QCString removeRedundantWhiteSpace(const QCString &s)
Definition: util.cpp:544
DocParserContext::markdownSupport
bool markdownSupport
Definition: docparser.cpp:131
arguments.h
DocNode::Kind_Para
@ Kind_Para
Definition: docparser.h:103
DocImage::m_width
QCString m_width
Definition: docparser.h:794
DocIncOperator::m_line
int m_line
Definition: docparser.h:645
HTML_DD
@ HTML_DD
Definition: cmdmapper.h:170
DocParamList::markFirst
void markFirst(bool b=TRUE)
Definition: docparser.h:1242
SIMPLESECT_BIT
const int SIMPLESECT_BIT
Definition: cmdmapper.h:25
DocXRefItem::m_title
QCString m_title
Definition: docparser.h:766
CMD_XMLINCLUDE
@ CMD_XMLINCLUDE
Definition: cmdmapper.h:144
DocTokenizer::retvalToString
static const char * retvalToString(int retval)
CMD_DATE
@ CMD_DATE
Definition: cmdmapper.h:41
DocAutoListItem::m_indent
int m_indent
Definition: docparser.h:729
DocDiaFile::parse
bool parse()
Definition: docparser.cpp:2795
Definition::name
virtual QCString name() const =0
DocMscFile::DocMscFile
DocMscFile(DocParser &parser, DocNode *parent, const QCString &name, const QCString &context, const QCString &srcFile, int srcLine)
Definition: docparser.cpp:2746
Doxygen::groupLinkedMap
static GroupLinkedMap * groupLinkedMap
Definition: doxygen.h:96
DocNode::setParent
void setParent(DocNode *parent)
Definition: docparser.h:169
CMD_AUTHOR
@ CMD_AUTHOR
Definition: cmdmapper.h:35
DocSimpleSect::m_title
DocTitle * m_title
Definition: docparser.h:1133
doxygen.h
SearchIndexIntf::addWord
virtual void addWord(const QCString &word, bool hiPriority)=0
DocVhdlFlow::DocVhdlFlow
DocVhdlFlow(DocParser &parser, DocNode *parent)
Definition: docparser.cpp:2828
DocHtmlCaption::DocHtmlCaption
DocHtmlCaption(DocParser &parser, DocNode *parent, const HtmlAttribList &attribs)
Definition: docparser.cpp:3196
CMD_IMAGE
@ CMD_IMAGE
Definition: cmdmapper.h:59
DocAutoListItem::DocAutoListItem
DocAutoListItem(DocParser &parser, DocNode *parent, int indent, int num)
Definition: docparser.cpp:4264
DocSymbol::Sym_Unknown
@ Sym_Unknown
Definition: docparser.h:388
DocHtmlCell::markLast
void markLast(bool v=TRUE)
Definition: docparser.h:1329
DocHtmlListItem::parse
int parse()
Definition: docparser.cpp:3991
DocIncOperator::Skip
@ Skip
Definition: docparser.h:609
DocNode::m_parser
DocParser & m_parser
Definition: docparser.h:184
DocInclude::m_blockId
QCString m_blockId
Definition: docparser.h:602
Argument
This class contains the information about the argument of a function or template
Definition: arguments.h:26
HTML_DT
@ HTML_DT
Definition: cmdmapper.h:169
RetVal_Internal
@ RetVal_Internal
Definition: doctokenizer.h:76
CMD_CODE
@ CMD_CODE
Definition: cmdmapper.h:39
DocNode::Kind_HtmlList
@ Kind_HtmlList
Definition: docparser.h:116
DocParBlock
Node representing an block of paragraphs
Definition: docparser.h:1070
MemberDef::getClassDef
virtual const ClassDef * getClassDef() const =0
DocParserContext::context
QCString context
Definition: docparser.cpp:102
DocVerbatim::ManOnly
@ ManOnly
Definition: docparser.h:513
DocParserContext::xmlComment
bool xmlComment
Definition: docparser.cpp:104
DocImage::Rtf
@ Rtf
Definition: docparser.h:774
CMD_SINCE
@ CMD_SINCE
Definition: cmdmapper.h:88
language.h
DocTokenizer::pushContext
void pushContext()
HTML_BLOCKQUOTE
@ HTML_BLOCKQUOTE
Definition: cmdmapper.h:183
SrcLangExt_Python
@ SrcLangExt_Python
Definition: types.h:52
CMD_ILINE
@ CMD_ILINE
Definition: cmdmapper.h:145
DocRef::m_ref
QCString m_ref
Definition: docparser.h:913
DocNode::Kind_SimpleListItem
@ Kind_SimpleListItem
Definition: docparser.h:112
QCString::lower
QCString lower() const
Definition: qcstring.h:232
DocSecRefList::parse
void parse()
Definition: docparser.cpp:2286
CMD_ENDPARBLOCK
@ CMD_ENDPARBLOCK
Definition: cmdmapper.h:125
RetVal_ListItem
@ RetVal_ListItem
Definition: doctokenizer.h:61
HTML_TD
@ HTML_TD
Definition: cmdmapper.h:161
EmojiEntityMapper::symbol2index
int symbol2index(const std::string &symName) const
Returns a code for the requested Emoji entity name
Definition: emoji.cpp:1558
DocStyleChange::m_style
Style m_style
Definition: docparser.h:378
validatingParseDoc
DocRoot * validatingParseDoc(IDocParser &parserIntf, const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &input, bool indexWords, bool isExample, const QCString &exampleName, bool singleLine, bool linkFromIndex, bool markdownSupport)
Definition: docparser.cpp:7495
DocParser::handleUnclosedStyleCommands
void handleUnclosedStyleCommands()
Definition: docparser.cpp:1002
CMD_HTMLINCLUDE
@ CMD_HTMLINCLUDE
Definition: cmdmapper.h:57
CMD_INTERNALREF
@ CMD_INTERNALREF
Definition: cmdmapper.h:62
DocTokenizer::setStateOptions
void setStateOptions()
DocSimpleListItem::parse
int parse()
Definition: docparser.cpp:4238
DocParamList::m_paragraphs
DocParaList m_paragraphs
Definition: docparser.h:1256
DocTokenizer::startAutoList
void startAutoList()
DocInternal::parse
int parse(int)
Definition: docparser.cpp:3043
DocTokenizer::getLineNr
int getLineNr(void)
HTML_OL
@ HTML_OL
Definition: cmdmapper.h:163
DocStyleChange::Small
@ Small
Definition: docparser.h:350
DocDiagramFileBase< DocDotFile >::m_file
QCString m_file
Definition: docparser.h:820
DocSymbol::Sym_DoubleColon
@ Sym_DoubleColon
Definition: docparser.h:446
DocHtmlHeader::parse
int parse()
Definition: docparser.cpp:2885
DocHtmlTable::computeTableGrid
void computeTableGrid()
determines the location of all cells in a grid, resolving row and column spans.
Definition: docparser.cpp:3677
SectionInfo::fileName
QCString fileName() const
Definition: section.h:70
XML_LIST
@ XML_LIST
Definition: cmdmapper.h:199
DocRef
Node representing a reference to some item
Definition: docparser.h:891
fileToString
QCString fileToString(const QCString &name, bool filter, bool isSourceCode)
Definition: util.cpp:1394
DocTokenizer::setStateSnippet
void setStateSnippet()
DocSimpleSect::Date
@ Date
Definition: docparser.h:1116
DocSimpleSect::typeString
QCString typeString() const
Definition: docparser.cpp:4500
docparser.h
getLanguageFromFileName
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition: util.cpp:5574
Definition::briefDescription
virtual QCString briefDescription(bool abbreviate=FALSE) const =0
showFileDefMatches
QCString showFileDefMatches(const FileNameLinkedMap *fnMap, const QCString &n)
Definition: util.cpp:3308
TRUE
#define TRUE
Definition: qcstring.h:36
DocParserContext::styleStack
DocStyleChangeStack styleStack
Definition: docparser.cpp:107
DocSimpleSect::Authors
@ Authors
Definition: docparser.h:1116
Definition::getOutputFileBase
virtual QCString getOutputFileBase() const =0
HTML_CENTER
@ HTML_CENTER
Definition: cmdmapper.h:151
CMD_REF
@ CMD_REF
Definition: cmdmapper.h:76
CMD_MDASH
@ CMD_MDASH
Definition: cmdmapper.h:129
DocPara::handleXRefItem
int handleXRefItem()
Definition: docparser.cpp:4829
DocSymbol::Sym_Greater
@ Sym_Greater
Definition: docparser.h:445
DocParamSect
Node representing a parameter section
Definition: docparser.h:1150
DocInclude::IncWithLines
@ IncWithLines
Definition: docparser.h:567
CMD_MSCFILE
@ CMD_MSCFILE
Definition: cmdmapper.h:112
DocTokenizer::setStateEmoji
void setStateEmoji()
DocHtmlBlockQuote::parse
int parse()
Definition: docparser.cpp:4188
DocStyleChange::tagName
QCString tagName() const
Definition: docparser.h:374
Portable::system
int system(const QCString &command, const QCString &args, bool commandHasConsole=true)
Definition: portable.cpp:42
DocParamList::m_type
DocParamSect::Type m_type
Definition: docparser.h:1259
DocVerbatim::children
const DocNodeList & children() const
Definition: docparser.h:532
regex.h
g_plantumlEngine
static const std::set< std::string > g_plantumlEngine
Definition: docparser.cpp:82
SrcLangExt_Fortran
@ SrcLangExt_Fortran
Definition: types.h:53
DocParamList::parseXml
int parseXml(const QCString &paramName)
Definition: docparser.cpp:4604
DocHtmlList
Node representing a Html list
Definition: docparser.h:1093
filedef.h
DocHtmlList::Type
Type
Definition: docparser.h:1096
HTML_H1
@ HTML_H1
Definition: cmdmapper.h:175
DocSimpleSect::m_type
Type m_type
Definition: docparser.h:1132
CMD_DOTFILE
@ CMD_DOTFILE
Definition: cmdmapper.h:44
CMD_UNTIL
@ CMD_UNTIL
Definition: cmdmapper.h:93
CMD_ENDHTMLONLY
@ CMD_ENDHTMLONLY
Definition: cmdmapper.h:47
MemberDef::detectUndocumentedParams
virtual void detectUndocumentedParams(bool hasParamCommand, bool hasReturnCommand) const =0
lineBlock
int lineBlock(const QCString &text, const QCString &marker)
Returns the line number of the line following the line with the marker.
Definition: util.cpp:6498
MemberDef::reimplements
virtual const MemberDef * reimplements() const =0
TK_LNKWORD
@ TK_LNKWORD
Definition: doctokenizer.h:47
DocParamList::m_params
DocNodeList m_params
Definition: docparser.h:1257
DocNode::Kind_ParamSect
@ Kind_ParamSect
Definition: docparser.h:143
LinkedMap::find
const T * find(const std::string &key) const
Find an object given the key.
Definition: linkedmap.h:60
RetVal_EndInternal
@ RetVal_EndInternal
Definition: doctokenizer.h:81
DocInternalRef::parse
void parse()
Definition: docparser.cpp:2366
CMD_PARBLOCK
@ CMD_PARBLOCK
Definition: cmdmapper.h:124
CMD_ADDINDEX
@ CMD_ADDINDEX
Definition: cmdmapper.h:30
CMD_SECREFLIST
@ CMD_SECREFLIST
Definition: cmdmapper.h:82
SectionType::Page
@ Page
reflist.h
DocNode::Kind_ParamList
@ Kind_ParamList
Definition: docparser.h:144
CMD_XMLONLY
@ CMD_XMLONLY
Definition: cmdmapper.h:99
DocTokenizer::popContext
bool popContext()
DocSimpleSect
Node representing a simple section
Definition: docparser.h:1111
FileInfo::isSymLink
bool isSymLink() const
Definition: fileinfo.cpp:77
DocSymbol::Sym_lsquo
@ Sym_lsquo
Definition: docparser.h:437
SectionInfo::title
QCString title() const
Definition: section.h:66
DocTokenizer::setStateRtfOnly
void setStateRtfOnly()
DocTokenizer::setStateText
void setStateText()
DocVhdlFlow::parse
void parse()
Definition: docparser.cpp:2833
CMD_PERCENT
@ CMD_PERCENT
Definition: cmdmapper.h:73
DocSection
Node representing a normal section
Definition: docparser.h:1001
DocTokenizer::setStateCite
void setStateCite()
validatingParseText
DocText * validatingParseText(IDocParser &parserIntf, const QCString &input)
Definition: docparser.cpp:7621
DocHtmlList::parseXml
int parseXml()
Definition: docparser.cpp:4123
DocSecRefItem::m_isSubPage
bool m_isSubPage
Definition: docparser.h:1040
HTML_DEL
@ HTML_DEL
Definition: cmdmapper.h:187
DocParser::pushContext
void pushContext()
Definition: docparser.cpp:208
CMD_PUNT
@ CMD_PUNT
Definition: cmdmapper.h:133
DocIncOperator::SkipLine
@ SkipLine
Definition: docparser.h:609
Definition::TypeClass
@ TypeClass
Definition: definition.h:87
DocPara::markLast
void markLast(bool v=TRUE)
Definition: docparser.h:1187
CMD_LINEBREAK
@ CMD_LINEBREAK
Definition: cmdmapper.h:68
DocSymbol::Sym_mdash
@ Sym_mdash
Definition: docparser.h:436
AutoNodeStack::m_parser
DocParser & m_parser
Definition: docparser.cpp:201
Definition::definitionType
virtual DefType definitionType() const =0
CMD_JAVALINK
@ CMD_JAVALINK
Definition: cmdmapper.h:92
unescapeCRef
static void unescapeCRef(QCString &s)
Definition: docparser.cpp:241
DocWord::word
QCString word() const
Definition: docparser.h:221
DocInclude
Node representing an included text block from file
Definition: docparser.h:563
DocHtmlCell::markFirst
void markFirst(bool v=TRUE)
Definition: docparser.h:1328
DocSecRefItem::m_refType
RefType m_refType
Definition: docparser.h:1039
DocNode::Kind_HtmlTable
@ Kind_HtmlTable
Definition: docparser.h:121
linkToText
QCString linkToText(SrcLangExt lang, const QCString &link, bool isFileName)
Definition: util.cpp:2943
IDocParser
Definition: docparser.h:38
DocPara::handleRef
void handleRef(const QCString &cmdName)
Definition: docparser.cpp:5091
DocStyleChange::Subscript
@ Subscript
Definition: docparser.h:351
HTML_TABLE
@ HTML_TABLE
Definition: cmdmapper.h:152
DocPara::handleEmoji
void handleEmoji()
Definition: docparser.cpp:4799
DocIndexEntry::parse
int parse()
Definition: docparser.cpp:3103
RetVal_EndBlockQuote
@ RetVal_EndBlockQuote
Definition: doctokenizer.h:79
XML_ITEM
@ XML_ITEM
Definition: cmdmapper.h:198
CMD_QUOTE
@ CMD_QUOTE
Definition: cmdmapper.h:111
RefItem::anchor
QCString anchor() const
Definition: reflist.h:45
DocXRefItem::m_file
QCString m_file
Definition: docparser.h:764
DocImage::DocImage
DocImage(DocParser &parser, DocNode *parent, const HtmlAttribList &attribs, const QCString &name, Type t, const QCString &url=QCString(), bool inlineImage=TRUE)
Definition: docparser.cpp:2859
DocParserContext::includeFileLength
uint includeFileLength
Definition: docparser.cpp:125
DocAutoList
Node representing an auto List
Definition: docparser.h:703
CMD_SUBPAGE
@ CMD_SUBPAGE
Definition: cmdmapper.h:84
DocPara::parse
int parse()
Definition: docparser.cpp:6579
DocDotFile::parse
bool parse()
Definition: docparser.cpp:2715
ArgumentList::size
size_t size() const
Definition: arguments.h:93
docFindSections
void docFindSections(const QCString &input, const Definition *d, const QCString &fileName)
Definition: docparser.cpp:7681
PrintDocVisitor
Definition: printdocvisitor.h:28
DocDiagramFileBase< DocDotFile >::m_height
QCString m_height
Definition: docparser.h:823
CiteInfo
Citation-related data.
Definition: cite.h:25
RetVal_EndParBlock
@ RetVal_EndParBlock
Definition: doctokenizer.h:82
DocSecRefItem::parse
void parse()
Definition: docparser.cpp:2212
DocInternal
Node representing an internal section of documentation
Definition: docparser.h:1059
HTML_EMPHASIS
@ HTML_EMPHASIS
Definition: cmdmapper.h:166
RetVal_SwitchLang
@ RetVal_SwitchLang
Definition: doctokenizer.h:77
DocParamSect::Exception
@ Exception
Definition: docparser.h:1156
DocIncOperator::Type
Type
Definition: docparser.h:609
DocParamSect::DocParamList
friend class DocParamList
Definition: docparser.h:1152
XML_LISTHEADER
@ XML_LISTHEADER
Definition: cmdmapper.h:200
Definition::getReference
virtual QCString getReference() const =0
DocNode::Kind_HtmlBlockQuote
@ Kind_HtmlBlockQuote
Definition: docparser.h:149
TokenInfo::simpleSectName
QCString simpleSectName
Definition: doctokenizer.h:89
DocParamSect::m_type
Type m_type
Definition: docparser.h:1172
DocInclude::RtfInclude
@ RtfInclude
Definition: docparser.h:568
DocNode::setInsidePreformatted
void setInsidePreformatted(bool p)
Definition: docparser.h:181
DocInclude::SnippetDoc
@ SnippetDoc
Definition: docparser.h:567
MemberDef::qualifiedName
virtual QCString qualifiedName() const =0
TokenInfo::id
int id
Definition: doctokenizer.h:96
DocSymbol::Sym_Plus
@ Sym_Plus
Definition: docparser.h:447
DocInclude::parse
void parse()
Definition: docparser.cpp:1925
DocVerbatim::setLocation
void setLocation(const QCString &file, int line)
Definition: docparser.h:541
DocInclude::LatexInclude
@ LatexInclude
Definition: docparser.h:566
stripIndentation
QCString stripIndentation(const QCString &s)
Definition: util.cpp:6597
HTML_UL
@ HTML_UL
Definition: cmdmapper.h:164
DocParserContext::initialStyleStack
DocStyleChangeStack initialStyleStack
Definition: docparser.cpp:108
Doxygen::searchIndex
static SearchIndexIntf * searchIndex
Definition: doxygen.h:105
SectionType::Anchor
@ Anchor
DocSimpleSect::DocSimpleSect
DocSimpleSect(DocParser &parser, DocNode *parent, Type t)
Definition: docparser.cpp:4371
DocDiaFile::DocDiaFile
DocDiaFile(DocParser &parser, DocNode *parent, const QCString &name, const QCString &context, const QCString &srcFile, int srcLine)
Definition: docparser.cpp:2787
createRef
DocRef * createRef(IDocParser &parserIntf, const QCString &target, const QCString &context)
Definition: docparser.cpp:7675
DocHtmlTable::m_caption
DocHtmlCaption * m_caption
Definition: docparser.h:1427
DocParamList::m_paramTypes
DocNodeList m_paramTypes
Definition: docparser.h:1258
HTML_A
@ HTML_A
Definition: cmdmapper.h:172
XML_TYPEPARAM
@ XML_TYPEPARAM
Definition: cmdmapper.h:211
QCString::mid
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition: qcstring.h:224
CMD_PLUS
@ CMD_PLUS
Definition: cmdmapper.h:134
substitute
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition: qcstring.cpp:465
DocTokenizer::setInsidePre
void setInsidePre(bool b)
DocTokenizer::setStateXRefItem
void setStateXRefItem()
stripKnownExtensions
static QCString stripKnownExtensions(const QCString &text)
Definition: docparser.cpp:539
DocStyleChange::style
Style style() const
Definition: docparser.h:368
DocSymbol::Sym_Quot
@ Sym_Quot
Definition: docparser.h:447
DocVisitor::visitPost
virtual void visitPost(DocAutoList *)=0
extractCopyDocId
static QCString extractCopyDocId(const char *data, uint &j, uint len)
Definition: docparser.cpp:7296
DocTokenizer::setStateRef
void setStateRef()
DocStyleChange::Code
@ Code
Definition: docparser.h:348
MemberDef::getOutputFileBase
virtual QCString getOutputFileBase() const =0
DocPara::handleCite
void handleCite()
Definition: docparser.cpp:4767
DocHtmlCell::Left
@ Left
Definition: docparser.h:1320
CMD_MANINCLUDE
@ CMD_MANINCLUDE
Definition: cmdmapper.h:143
CMD_AMP
@ CMD_AMP
Definition: cmdmapper.h:31
DocIncOperator::markFirst
void markFirst(bool v=TRUE)
Definition: docparser.h:636
Definition::anchor
virtual QCString anchor() const =0
DocTitle::parse
void parse()
Definition: docparser.cpp:4346
CMD_SECREFITEM
@ CMD_SECREFITEM
Definition: cmdmapper.h:77
DocInclude::Include
@ Include
Definition: docparser.h:566
DocPara::handleHtmlStartTag
int handleHtmlStartTag(const QCString &tagName, const HtmlAttribList &tagHtmlAttribs)
Definition: docparser.cpp:5965
DocParser::handleAnchor
DocAnchor * handleAnchor(DocNode *parent)
Definition: docparser.cpp:1172
CMD_NOTE
@ CMD_NOTE
Definition: cmdmapper.h:70
Config_getBool
#define Config_getBool(name)
Definition: config.h:33
XML_DESCRIPTION
@ XML_DESCRIPTION
Definition: cmdmapper.h:194
QCString::append
QCString & append(char c)
Definition: qcstring.h:318
HTML_HR
@ HTML_HR
Definition: cmdmapper.h:167
DocNode::Kind
Kind
Definition: docparser.h:100
DocParser::checkUnOrMultipleDocumentedParams
void checkUnOrMultipleDocumentedParams()
Definition: docparser.cpp:468
DocParser::handleImg
void handleImg(DocNode *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
Definition: docparser.cpp:1682
HTML_DIV
@ HTML_DIV
Definition: cmdmapper.h:182
RetVal_SimpleSec
@ RetVal_SimpleSec
Definition: doctokenizer.h:60
DocNode::Kind_XRefItem
@ Kind_XRefItem
Definition: docparser.h:115
CMD_PARAGRAPH
@ CMD_PARAGRAPH
Definition: cmdmapper.h:87
DocRef::m_relPath
QCString m_relPath
Definition: docparser.h:912
CMD_DOT
@ CMD_DOT
Definition: cmdmapper.h:100
DocSymbol::Sym_BSlash
@ Sym_BSlash
Definition: docparser.h:445
DocImage::m_height
QCString m_height
Definition: docparser.h:795
Doxygen::htmlFileExtension
static QCString htmlFileExtension
Definition: doxygen.h:103
MemberDef::objCMethodName
virtual QCString objCMethodName(bool localLink, bool showStatic) const =0
MemberDef::isDocsForDefinition
virtual bool isDocsForDefinition() const =0
DocParserContext::isExample
bool isExample
Definition: docparser.cpp:118
MemberDef::getScopeString
virtual QCString getScopeString() const =0
SectionManager::instance
static SectionManager & instance()
returns a reference to the singleton
Definition: section.h:172
CMD_DBONLY
@ CMD_DBONLY
Definition: cmdmapper.h:121
DocNode::Kind_AutoList
@ Kind_AutoList
Definition: docparser.h:104
DocTokenizer
Definition: doctokenizer.h:117
reg::Ex
Class representing a regular expression.
Definition: regex.h:48
DocIncOperator::type
Type type() const
Definition: docparser.h:616
XML_PARAM
@ XML_PARAM
Definition: cmdmapper.h:202
Markdown
Helper class to process markdown formatted text
Definition: markdown.h:32
ClassDef::getReference
virtual QCString getReference() const =0
If this class originated from a tagfile, this will return the tag file reference
DocEmoji::DocEmoji
DocEmoji(DocParser &parser, DocNode *parent, const QCString &symName)
Definition: docparser.cpp:1721
CMD_DCOLON
@ CMD_DCOLON
Definition: cmdmapper.h:113
CMD_ENDINTERNAL
@ CMD_ENDINTERNAL
Definition: cmdmapper.h:123
TokenInfo::isEMailAddr
bool isEMailAddr
Definition: doctokenizer.h:108
DocCite::m_anchor
QCString m_anchor
Definition: docparser.h:337
insideTable
static bool insideTable(DocNode *n)
Definition: docparser.cpp:611
DocTokenizer::setStateHtmlOnly
void setStateHtmlOnly()
CMD_SKIPLINE
@ CMD_SKIPLINE
Definition: cmdmapper.h:90
DocParamSect::Type
Type
Definition: docparser.h:1154
DocTokenizer::setStateSetScope
void setStateSetScope()
Definition::documentation
virtual QCString documentation() const =0
CitationManager::fileName
QCString fileName() const
Definition: cite.cpp:96
MemberDef::declArgumentList
virtual const ArgumentList & declArgumentList() const =0
DocTokenizer::setLineNr
void setLineNr(int lineno)
DocVerbatim::setUseBitmap
void setUseBitmap(const bool &u)
Definition: docparser.h:540
SearchIndexIntf::setCurrentDoc
virtual void setCurrentDoc(const Definition *ctx, const QCString &anchor, bool isSourceFile)=0
TK_ENDLIST
@ TK_ENDLIST
Definition: doctokenizer.h:50
DocSection::m_file
QCString m_file
Definition: docparser.h:1019
DocParamSect::Param
@ Param
Definition: docparser.h:1156
Definition::getOuterScope
virtual Definition * getOuterScope() const =0
DocAutoListItem::parse
int parse()
Definition: docparser.cpp:4270
TK_HTMLTAG
@ TK_HTMLTAG
Command starting with @
Definition: doctokenizer.h:52
DocVerbatim::setEngine
void setEngine(const QCString &e)
Definition: docparser.h:539
CMD_EMOJI
@ CMD_EMOJI
Definition: cmdmapper.h:139
DocSimpleSect::Copyright
@ Copyright
Definition: docparser.h:1117
DocImage::parse
void parse()
Definition: docparser.cpp:2877
DocVerbatim::LatexOnly
@ LatexOnly
Definition: docparser.h:513
DocHtmlCell::setColumnIndex
void setColumnIndex(uint idx)
Definition: docparser.h:1342
QCString::startsWith
bool startsWith(const char *s) const
Definition: qcstring.h:408
DocIncOperator::Line
@ Line
Definition: docparser.h:609
FileInfo
Minimal replacement for QFileInfo.
Definition: fileinfo.h:22
DocParserContext::includeFileName
QCString includeFileName
Definition: docparser.cpp:122
flattenParagraphs
static void flattenParagraphs(DocNode *root, DocNodeList &children)
Definition: docparser.cpp:2477
RetVal_Section
@ RetVal_Section
Definition: doctokenizer.h:62
DocSecRefItem::DocSecRefItem
DocSecRefItem(DocParser &parser, DocNode *parent, const QCString &target)
Definition: docparser.cpp:2206
HTML_TR
@ HTML_TR
Definition: cmdmapper.h:160
FileDef::absFilePath
virtual QCString absFilePath() const =0
DocSection::m_id
QCString m_id
Definition: docparser.h:1016
qPrint
const char * qPrint(const char *s)
Definition: qcstring.h:589
DocHtmlCell::Bottom
@ Bottom
Definition: docparser.h:1321
INTERNAL_ASSERT
#define INTERNAL_ASSERT(x)
Definition: docparser.cpp:67
stripLeadingAndTrailingEmptyLines
QCString stripLeadingAndTrailingEmptyLines(const QCString &s, int &docLine)
Special version of QCString::stripWhiteSpace() that only strips completely blank lines.
Definition: util.cpp:5394
DocTokenizer::setStatePattern
void setStatePattern()
DocStyleChange::Preformatted
@ Preformatted
Definition: docparser.h:353
DocRef::m_file
QCString m_file
Definition: docparser.h:911
Config_getString
#define Config_getString(name)
Definition: config.h:32
CMD_MINUS
@ CMD_MINUS
Definition: cmdmapper.h:135
DocParserContext::paramsFound
StringMultiSet paramsFound
Definition: docparser.cpp:116
DocTokenizer::setStateCode
void setStateCode()
RetVal_DescTitle
@ RetVal_DescTitle
Definition: doctokenizer.h:70
StringMultiSet
std::multiset< std::string > StringMultiSet
Definition: containers.h:31
DocAutoList::m_indent
int m_indent
Definition: docparser.h:714
Definition::getDefFileName
virtual QCString getDefFileName() const =0
RetVal_Paragraph
@ RetVal_Paragraph
Definition: doctokenizer.h:65
SectionInfo
class that provide information about a section.
Definition: section.h:49
DocHtmlList::m_type
Type m_type
Definition: docparser.h:1106
DocPara::handleHtmlHeader
int handleHtmlHeader(const HtmlAttribList &tagHtmlAttribs, int level)
Definition: docparser.cpp:5275
Mappers::cmdMapper
static Mapper * cmdMapper
Definition: cmdmapper.h:234
DocText::parse
void parse()
Definition: docparser.cpp:7028
RefList::isEnabled
bool isEnabled() const
Definition: reflist.cpp:46
DocHtmlRow::parseXml
int parseXml(bool header)
Definition: docparser.cpp:3489
CMD_ENDLATEXONLY
@ CMD_ENDLATEXONLY
Definition: cmdmapper.h:48
DocXRefItem::m_anchor
QCString m_anchor
Definition: docparser.h:765
DocHtmlCell::parse
int parse()
Definition: docparser.cpp:3271
MemberDef::argumentList
virtual const ArgumentList & argumentList() const =0
DocSimpleListItem::m_paragraph
DocPara * m_paragraph
Definition: docparser.h:1282
CMD_ENDUML
@ CMD_ENDUML
Definition: cmdmapper.h:131
resolveRef
bool resolveRef(const QCString &scName, const QCString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
Definition: util.cpp:2757
convertNameToFile
QCString convertNameToFile(const QCString &name, bool allowDots, bool allowUnderscore)
Definition: util.cpp:3604
config.h
DocParser::checkRetvalName
void checkRetvalName()
Definition: docparser.cpp:445
DocSimpleSect::Post
@ Post
Definition: docparser.h:1117
Portable::sysTimerStop
void sysTimerStop()
Definition: portable.cpp:475
DocParserContext::hasParamCommand
bool hasParamCommand
Definition: docparser.cpp:113
findAttribute
static bool findAttribute(const HtmlAttribList &tagHtmlAttribs, const char *attrName, QCString *result)
Definition: docparser.cpp:5949
DocSimpleSect::Pre
@ Pre
Definition: docparser.h:1117
Doxygen::namespaceLinkedMap
static NamespaceLinkedMap * namespaceLinkedMap
Definition: doxygen.h:97
DocPara::handleSimpleSection
int handleSimpleSection(DocSimpleSect::Type t, bool xmlContext=FALSE)
Definition: docparser.cpp:4715
TokenInfo::sectionId
QCString sectionId
Definition: doctokenizer.h:86
DocSimpleList
Node representing a simple list
Definition: docparser.h:1082
DocTokenizer::setStateTitle
void setStateTitle()
DocSimpleSect::Remark
@ Remark
Definition: docparser.h:1117
AutoNodeStack
Definition: docparser.cpp:186
ASSERT
#define ASSERT(x)
Definition: qcstring.h:44
SrcLangExt_Markdown
@ SrcLangExt_Markdown
Definition: types.h:57
DocParserContext::copyStack
DefinitionStack copyStack
Definition: docparser.cpp:109
groupdef.h
QCString::data
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string
Definition: qcstring.h:153
CMD_RETURN
@ CMD_RETURN
Definition: cmdmapper.h:79
Doxygen::mscFileNameLinkedMap
static FileNameLinkedMap * mscFileNameLinkedMap
Definition: doxygen.h:91
DocFormula::id
int id() const
Definition: docparser.h:666
DocStyleChange::Underline
@ Underline
Definition: docparser.h:357
Mapper::map
int map(const QCString &n)
Definition: cmdmapper.cpp:237
DocPara::handleVhdlFlow
void handleVhdlFlow()
Definition: docparser.cpp:5056
DocSimpleListItem
Node representing a simple list item
Definition: docparser.h:1266
AutoNodeStack::m_node
const DocNode * m_node
Definition: docparser.cpp:202
emoji.h
DocTokenizer::newToken
TokenInfo * newToken()
FileDef
A model of a file symbol.
Definition: filedef.h:73
CMD_RTFONLY
@ CMD_RTFONLY
Definition: cmdmapper.h:117
CompAccept::children
const DocNodeList & children() const
Definition: docparser.h:207
FormulaManager::findFormula
std::string findFormula(int formulaId) const
Definition: formula.cpp:481
DocVerbatim::XmlOnly
@ XmlOnly
Definition: docparser.h:513
doctokenizer.h
toFileDef
FileDef * toFileDef(Definition *d)
Definition: filedef.cpp:1778
CMD_VHDLFLOW
@ CMD_VHDLFLOW
Definition: cmdmapper.h:120
DocParserContext::includeFileText
QCString includeFileText
Definition: docparser.cpp:123
DocParserContext::insideHtmlLink
bool insideHtmlLink
Definition: docparser.cpp:105
DocTokenizer::lex
int lex()
DocParamSect::RetVal
@ RetVal
Definition: docparser.h:1156
DocInclude::DontIncWithLines
@ DontIncWithLines
Definition: docparser.h:568
DocTokenizer::setStateFile
void setStateFile()
DocAutoList::parse
int parse()
Definition: docparser.cpp:4312
DocRef::m_text
QCString m_text
Definition: docparser.h:915
HTML_H3
@ HTML_H3
Definition: cmdmapper.h:177
CiteInfo::text
virtual QCString text() const =0
HTML_BOLD
@ HTML_BOLD
Definition: cmdmapper.h:173
XML_C
@ XML_C
Definition: cmdmapper.h:192
DocStyleChange::Div
@ Div
Definition: docparser.h:355
TK_NEWPARA
@ TK_NEWPARA
Definition: doctokenizer.h:54
XML_INCLUDE
@ XML_INCLUDE
Definition: cmdmapper.h:197
CMD_EXCEPTION
@ CMD_EXCEPTION
Definition: cmdmapper.h:53
DocStyleChange::attribs
const HtmlAttribList & attribs() const
Definition: docparser.h:373
Portable::isAbsolutePath
bool isAbsolutePath(const QCString &fileName)
Definition: portable.cpp:496
DocAnchor::DocAnchor
DocAnchor(DocParser &parser, DocNode *parent, const QCString &id, bool newAnchor)
Definition: docparser.cpp:1862
EmojiEntityMapper::instance
static EmojiEntityMapper * instance()
Returns the one and only instance of the Emoji entity mapper
Definition: emoji.cpp:1536
DocParser::readTextFileByName
void readTextFileByName(const QCString &file, QCString &text)
Definition: docparser.cpp:1785
DocParserContext::lineNo
int lineNo
Definition: docparser.cpp:130
HTML_INS
@ HTML_INS
Definition: cmdmapper.h:186
CMD_COPYBRIEF
@ CMD_COPYBRIEF
Definition: cmdmapper.h:109
DocImage::m_url
QCString m_url
Definition: docparser.h:797
CMD_LATEXINCLUDE
@ CMD_LATEXINCLUDE
Definition: cmdmapper.h:127
DocNode::parent
DocNode * parent() const
Definition: docparser.h:166
TK_COMMAND_CHAR
#define TK_COMMAND_CHAR(token)
Definition: docparser.cpp:55
CMD_NDASH
@ CMD_NDASH
Definition: cmdmapper.h:128
DocHtmlCell
Node representing a HTML table cell
Definition: docparser.h:1316
printdocvisitor.h
DocIncOperator::m_pattern
QCString m_pattern
Definition: docparser.h:648
DocDiagramFileBase
Definition: docparser.h:802
portable.h
Portable versions of functions that are platform dependent.
CMD_VERBATIM
@ CMD_VERBATIM
Definition: cmdmapper.h:94
DocIncOperator::markLast
void markLast(bool v=TRUE)
Definition: docparser.h:637
DocRoot::parse
void parse()
Definition: docparser.cpp:7136
DocHtmlDescList::parse
int parse()
Definition: docparser.cpp:3921
DocDiagramFileBase< DocDotFile >::m_width
QCString m_width
Definition: docparser.h:822
searchindex.h
RefList::sectionTitle
QCString sectionTitle() const
Definition: reflist.h:103
DocHtmlHeader::m_level
int m_level
Definition: docparser.h:968
DocTokenizer::setStatePara
void setStatePara()
DocParamSect::Direction
Direction
Definition: docparser.h:1158
htmlentity.h
Definition::briefDescriptionAsTooltip
virtual QCString briefDescriptionAsTooltip() const =0
CMD_SKIP
@ CMD_SKIP
Definition: cmdmapper.h:89
DocTokenizer::setStateTitleAttrValue
void setStateTitleAttrValue()
DocRef::m_anchor
QCString m_anchor
Definition: docparser.h:914
HTML_UNKNOWN
@ HTML_UNKNOWN
Definition: cmdmapper.h:150
CMD_SUBSUBSECTION
@ CMD_SUBSUBSECTION
Definition: cmdmapper.h:86
DocInternalRef
Node representing an internal reference to some item
Definition: docparser.h:919
DocNode::Kind_SimpleSect
@ Kind_SimpleSect
Definition: docparser.h:109
DBG
#define DBG(x)
Definition: docparser.cpp:58
AutoNodeStack::AutoNodeStack
AutoNodeStack(DocParser &parser, const DocNode *node)
Definition: docparser.cpp:189
DocTokenizer::setStateDbOnly
void setStateDbOnly()
DocIncOperator::m_text
QCString m_text
Definition: docparser.h:647
CMD_RTFINCLUDE
@ CMD_RTFINCLUDE
Definition: cmdmapper.h:141
XML_EXCEPTION
@ XML_EXCEPTION
Definition: cmdmapper.h:196
dir.h
DocVerbatim::setText
void setText(const QCString &t)
Definition: docparser.h:536
Doxygen::classLinkedMap
static ClassLinkedMap * classLinkedMap
Definition: doxygen.h:78
DocXRefItem::DocXRefItem
DocXRefItem(DocParser &parser, DocNode *parent, int id, const QCString &key)
Definition: docparser.cpp:2118
DocStyleChange::S
@ S
Definition: docparser.h:360
DocNode::Table
@ Table
Definition: docparser.h:183
SectionInfo::type
SectionType type() const
Definition: section.h:67
HTML_H2
@ HTML_H2
Definition: cmdmapper.h:176
DocVerbatim::Verbatim
@ Verbatim
Definition: docparser.h:513
util.h
A bunch of utility functions.
DocHtmlCell::Center
@ Center
Definition: docparser.h:1320
ActiveRowSpan::column
uint column
Definition: docparser.cpp:3667
DocFormula::m_id
int m_id
Definition: docparser.h:678
DocHtmlCell::valignment
Valignment valignment() const
Definition: docparser.cpp:3403
DocVerbatim::setHeight
void setHeight(const QCString &h)
Definition: docparser.h:538
HTML_SPAN
@ HTML_SPAN
Definition: cmdmapper.h:181
CompAccept< DocXRefItem >::m_children
DocNodeList m_children
Definition: docparser.h:211
CHECK_FOR_COMMAND
#define CHECK_FOR_COMMAND(str, action)
Definition: docparser.cpp:7355
XML_SEEALSO
@ XML_SEEALSO
Definition: cmdmapper.h:208
DocHtmlRow
Node representing a HTML table row
Definition: docparser.h:1371
CMD_DOCBOOKINCLUDE
@ CMD_DOCBOOKINCLUDE
Definition: cmdmapper.h:142
TK_COMMAND_BS
@ TK_COMMAND_BS
Definition: doctokenizer.h:57
DocVerbatim::setWidth
void setWidth(const QCString &w)
Definition: docparser.h:537
RetVal_TableHCell
@ RetVal_TableHCell
Definition: doctokenizer.h:74
DocParser::handleStyleLeave
void handleStyleLeave(DocNode *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName)
Definition: docparser.cpp:867
DocWord::DocWord
DocWord(DocParser &parser, DocNode *parent, const QCString &word)
Definition: docparser.cpp:1831
DocHtmlCell::Alignment
Alignment
Definition: docparser.h:1320
DocInclude::ManInclude
@ ManInclude
Definition: docparser.h:568
DocPara::handleImage
void handleImage(const QCString &cmdName)
Definition: docparser.cpp:4915
DocSection::m_level
int m_level
Definition: docparser.h:1015
CMD_ENDLINK
@ CMD_ENDLINK
Definition: cmdmapper.h:49
isCopyBriefOrDetailsCmd
static uint isCopyBriefOrDetailsCmd(const char *data, uint i, uint len, bool &brief)
Definition: docparser.cpp:7359
QCString::right
QCString right(size_t len) const
Definition: qcstring.h:217
DocSecRefItem::m_ref
QCString m_ref
Definition: docparser.h:1043
HTML_TH
@ HTML_TH
Definition: cmdmapper.h:162
QCString::prepend
QCString & prepend(const char *s)
Definition: qcstring.h:339
DocVisitor::visitPre
virtual void visitPre(DocAutoList *)=0
DocParser::findDocsForMemberOrCompound
bool findDocsForMemberOrCompound(const QCString &commandName, QCString *pDoc, QCString *pBrief, const Definition **pDef)
Definition: docparser.cpp:629
qstrlen
uint qstrlen(const char *str)
Definition: qcstring.h:65
DocSimpleSect::Invar
@ Invar
Definition: docparser.h:1117
QCString::sprintf
QCString & sprintf(const char *format,...)
Definition: qcstring.cpp:24
debug.h
DocSymbol::Sym_apos
@ Sym_apos
Definition: docparser.h:442
CMD_TPARAM
@ CMD_TPARAM
Definition: cmdmapper.h:108
CMD_XREFITEM
@ CMD_XREFITEM
Definition: cmdmapper.h:98
HTML_BR
@ HTML_BR
Definition: cmdmapper.h:171
DocSimpleSect::Version
@ Version
Definition: docparser.h:1116
vhdldocgen.h
DocTitle::parseFromString
void parseFromString(const QCString &title)
Definition: docparser.cpp:4364
XML_PERMISSION
@ XML_PERMISSION
Definition: cmdmapper.h:204
CitationManager::anchorPrefix
QCString anchorPrefix() const
Definition: cite.cpp:101
Debug::PrintTree
@ PrintTree
Definition: debug.h:34
DocNode::m_parent
DocNode * m_parent
Definition: docparser.h:182
createDocParser
std::unique_ptr< IDocParser > createDocParser()
Definition: docparser.cpp:179
TK_URL
@ TK_URL
Definition: doctokenizer.h:56
Config_getList
#define Config_getList(name)
Definition: config.h:37
PageDef::hasParentPage
virtual bool hasParentPage() const =0
DocSymbol::Sym_ndash
@ Sym_ndash
Definition: docparser.h:436
DocSection::parse
int parse()
Definition: docparser.cpp:6904
DocTokenizer::setStateLatexOnly
void setStateLatexOnly()
DocInclude::m_text
QCString m_text
Definition: docparser.h:597
FALSE
#define FALSE
Definition: qcstring.h:33
DocSimpleSect::Since
@ Since
Definition: docparser.h:1116
CMD_DONTINCLUDE
@ CMD_DONTINCLUDE
Definition: cmdmapper.h:43
DocXRefItem::parse
bool parse()
Definition: docparser.cpp:2124
CMD_INCLUDE
@ CMD_INCLUDE
Definition: cmdmapper.h:60
RefList::fileName
QCString fileName() const
Definition: reflist.h:101
ClassDef::anchor
virtual QCString anchor() const =0
DocNode::Kind_HtmlListItem
@ Kind_HtmlListItem
Definition: docparser.h:117
DocSimpleSect::Attention
@ Attention
Definition: docparser.h:1117
isVerbatimSection
static uint isVerbatimSection(const char *data, uint i, uint len, QCString &endMarker)
Definition: docparser.cpp:7370
CMD_EQUAL
@ CMD_EQUAL
Definition: cmdmapper.h:140
DocVerbatim::Dot
@ Dot
Definition: docparser.h:513
QCString
This is an alternative implementation of QCString.
Definition: qcstring.h:108