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