1 /******************************************************************************
6 * Copyright (C) 1997-2014 by Dimitri van Heesch.
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.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
23 #include <qfileinfo.h>
34 #include "docparser.h"
35 #include "doctokenizer.h"
36 #include "cmdmapper.h"
37 #include "printdocvisitor.h"
40 #include "searchindex.h"
44 #include "arguments.h"
45 #include "vhdldocgen.h"
47 #include "classlist.h"
49 #include "memberdef.h"
50 #include "namespacedef.h"
56 #include "htmlentity.h"
59 #define DBG(x) do {} while(0)
62 //#define DBG(x) printf x
65 //#define myprintf(x...) fprintf(stderr,x)
66 //#define DBG(x) myprintf x
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__));
71 //---------------------------------------------------------------------------
73 static const char *sectionLevelToName[] =
82 //---------------------------------------------------------------------------
84 // Parser state: global variables during a call to validatingParseDoc
85 static Definition * g_scope;
86 static QCString g_context;
87 static bool g_inSeeBlock;
88 static bool g_xmlComment;
89 static bool g_insideHtmlLink;
90 static QStack<DocNode> g_nodeStack;
91 static QStack<DocStyleChange> g_styleStack;
92 static QStack<DocStyleChange> g_initialStyleStack;
93 static QList<Definition> g_copyStack;
94 static QCString g_fileName;
95 static QCString g_relPath;
97 static bool g_hasParamCommand;
98 static bool g_hasReturnCommand;
99 static QDict<void> g_paramsFound;
100 static MemberDef * g_memberDef;
101 static bool g_isExample;
102 static QCString g_exampleName;
103 static SectionDict * g_sectionDict;
104 static QCString g_searchUrl;
106 static QCString g_includeFileText;
107 static uint g_includeFileOffset;
108 static uint g_includeFileLength;
111 /** Parser's context to store all global variables.
113 struct DocParserContext
120 QStack<DocNode> nodeStack;
121 QStack<DocStyleChange> styleStack;
122 QStack<DocStyleChange> initialStyleStack;
123 QList<Definition> copyStack;
127 bool hasParamCommand;
128 bool hasReturnCommand;
129 MemberDef * memberDef;
130 QDict<void> paramsFound;
132 QCString exampleName;
133 SectionDict *sectionDict;
136 QCString includeFileText;
137 uint includeFileOffset;
138 uint includeFileLength;
143 static QStack<DocParserContext> g_parserStack;
145 //---------------------------------------------------------------------------
147 static void docParserPushContext(bool saveParamInfo=TRUE)
150 //indent.fill(' ',g_parserStack.count()*2+2);
151 //printf("%sdocParserPushContext() count=%d\n",indent.data(),g_nodeStack.count());
153 doctokenizerYYpushContext();
154 DocParserContext *ctx = new DocParserContext;
155 ctx->scope = g_scope;
156 ctx->context = g_context;
157 ctx->inSeeBlock = g_inSeeBlock;
158 ctx->xmlComment = g_xmlComment;
159 ctx->insideHtmlLink = g_insideHtmlLink;
160 ctx->nodeStack = g_nodeStack;
161 ctx->styleStack = g_styleStack;
162 ctx->initialStyleStack = g_initialStyleStack;
163 ctx->copyStack = g_copyStack;
164 ctx->fileName = g_fileName;
165 ctx->relPath = g_relPath;
169 ctx->hasParamCommand = g_hasParamCommand;
170 ctx->hasReturnCommand = g_hasReturnCommand;
171 ctx->paramsFound = g_paramsFound;
174 ctx->memberDef = g_memberDef;
175 ctx->isExample = g_isExample;
176 ctx->exampleName = g_exampleName;
177 ctx->sectionDict = g_sectionDict;
178 ctx->searchUrl = g_searchUrl;
180 ctx->includeFileText = g_includeFileText;
181 ctx->includeFileOffset = g_includeFileOffset;
182 ctx->includeFileLength = g_includeFileLength;
184 ctx->token = g_token;
185 g_token = new TokenInfo;
187 g_parserStack.push(ctx);
190 static void docParserPopContext(bool keepParamInfo=FALSE)
192 DocParserContext *ctx = g_parserStack.pop();
193 g_scope = ctx->scope;
194 g_context = ctx->context;
195 g_inSeeBlock = ctx->inSeeBlock;
196 g_xmlComment = ctx->xmlComment;
197 g_insideHtmlLink = ctx->insideHtmlLink;
198 g_nodeStack = ctx->nodeStack;
199 g_styleStack = ctx->styleStack;
200 g_initialStyleStack = ctx->initialStyleStack;
201 g_copyStack = ctx->copyStack;
202 g_fileName = ctx->fileName;
203 g_relPath = ctx->relPath;
207 g_hasParamCommand = ctx->hasParamCommand;
208 g_hasReturnCommand = ctx->hasReturnCommand;
209 g_paramsFound = ctx->paramsFound;
211 g_memberDef = ctx->memberDef;
212 g_isExample = ctx->isExample;
213 g_exampleName = ctx->exampleName;
214 g_sectionDict = ctx->sectionDict;
215 g_searchUrl = ctx->searchUrl;
217 g_includeFileText = ctx->includeFileText;
218 g_includeFileOffset = ctx->includeFileOffset;
219 g_includeFileLength = ctx->includeFileLength;
222 g_token = ctx->token;
225 doctokenizerYYpopContext();
228 //indent.fill(' ',g_parserStack.count()*2+2);
229 //printf("%sdocParserPopContext() count=%d\n",indent.data(),g_nodeStack.count());
232 //---------------------------------------------------------------------------
234 /*! search for an image in the imageNameDict and if found
235 * copies the image to the output directory (which depends on the \a type
238 static QCString findAndCopyImage(const char *fileName,DocImage::Type type)
243 //printf("Search for %s\n",fileName);
244 if ((fd=findFileDef(Doxygen::imageNameDict,fileName,ambig)))
246 QCString inputFile = fd->absFilePath();
247 QFile inImage(inputFile);
248 if (inImage.open(IO_ReadOnly))
252 if ((i=result.findRev('/'))!=-1 || (i=result.findRev('\\'))!=-1)
254 result = result.right(result.length()-i-1);
256 //printf("fileName=%s result=%s\n",fileName,result.data());
261 if (!Config_getBool("GENERATE_HTML")) return result;
262 outputDir = Config_getString("HTML_OUTPUT");
264 case DocImage::Latex:
265 if (!Config_getBool("GENERATE_LATEX")) return result;
266 outputDir = Config_getString("LATEX_OUTPUT");
269 if (!Config_getBool("GENERATE_RTF")) return result;
270 outputDir = Config_getString("RTF_OUTPUT");
273 QCString outputFile = outputDir+"/"+result;
274 QFileInfo outfi(outputFile);
275 if (outfi.isSymLink())
277 QFile::remove(outputFile);
278 warn_doc_error(g_fileName,doctokenizerYYlineno,
279 "destination of image %s is a symlink, replacing with image",
282 if (outputFile!=inputFile) // prevent copying to ourself
284 QFile outImage(outputFile.data());
285 if (outImage.open(IO_WriteOnly)) // copy the image
287 char *buffer = new char[inImage.size()];
288 inImage.readBlock(buffer,inImage.size());
289 outImage.writeBlock(buffer,inImage.size());
292 if (type==DocImage::Html) Doxygen::indexList->addImageFile(result);
296 warn_doc_error(g_fileName,doctokenizerYYlineno,
297 "could not write output image %s",qPrint(outputFile));
302 printf("Source & Destination are the same!\n");
307 warn_doc_error(g_fileName,doctokenizerYYlineno,
308 "could not open image %s",qPrint(fileName));
311 if (type==DocImage::Latex && Config_getBool("USE_PDFLATEX") &&
312 fd->name().right(4)==".eps"
314 { // we have an .eps image in pdflatex mode => convert it to a pdf.
315 QCString outputDir = Config_getString("LATEX_OUTPUT");
316 QCString baseName = fd->name().left(fd->name().length()-4);
317 QCString epstopdfArgs(4096);
318 epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"",
319 outputDir.data(), baseName.data(),
320 outputDir.data(), baseName.data());
321 portable_sysTimerStart();
322 if (portable_system("epstopdf",epstopdfArgs)!=0)
324 err("Problems running epstopdf. Check your TeX installation!\n");
326 portable_sysTimerStop();
333 text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName));
334 text+="Possible candidates:\n";
335 text+=showFileDefMatches(Doxygen::imageNameDict,fileName);
336 warn_doc_error(g_fileName,doctokenizerYYlineno,text);
341 if (result.left(5)!="http:" && result.left(6)!="https:")
343 warn_doc_error(g_fileName,doctokenizerYYlineno,
344 "image file %s is not found in IMAGE_PATH: "
345 "assuming external image.",qPrint(fileName)
352 /*! Collects the parameters found with \@param or \@retval commands
353 * in a global list g_paramsFound. If \a isParam is set to TRUE
354 * and the parameter is not an actual parameter of the current
355 * member g_memberDef, then a warning is raised (unless warnings
356 * are disabled altogether).
358 static void checkArgumentName(const QCString &name,bool isParam)
360 if (!Config_getBool("WARN_IF_DOC_ERROR")) return;
361 if (g_memberDef==0) return; // not a member
362 ArgumentList *al=g_memberDef->isDocsForDefinition() ?
363 g_memberDef->argumentList() :
364 g_memberDef->declArgumentList();
365 SrcLangExt lang = g_memberDef->getLanguage();
366 //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition());
367 if (al==0) return; // no argument list
369 static QRegExp re("$?[a-zA-Z0-9_\\x80-\\xFF]+\\.*");
371 while ((i=re.match(name,p,&l))!=-1) // to handle @param x,y
373 QCString aName=name.mid(i,l);
374 if (lang==SrcLangExt_Fortran) aName=aName.lower();
375 //printf("aName=`%s'\n",aName.data());
376 ArgumentListIterator ali(*al);
379 for (ali.toFirst();(a=ali.current());++ali)
381 QCString argName = g_memberDef->isDefine() ? a->type : a->name;
382 if (lang==SrcLangExt_Fortran) argName=argName.lower();
383 argName=argName.stripWhiteSpace();
384 //printf("argName=`%s' aName=%s\n",argName.data(),aName.data());
385 if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
388 g_paramsFound.insert(aName,(void *)(0x8));
393 if (!found && isParam)
395 //printf("member type=%d\n",memberDef->memberType());
396 QCString scope=g_memberDef->getScopeString();
397 if (!scope.isEmpty()) scope+="::"; else scope="";
398 QCString inheritedFrom = "";
399 QCString docFile = g_memberDef->docFile();
400 int docLine = g_memberDef->docLine();
401 MemberDef *inheritedMd = g_memberDef->inheritsDocsFrom();
402 if (inheritedMd) // documentation was inherited
404 inheritedFrom.sprintf(" inherited from member %s at line "
405 "%d in file %s",qPrint(inheritedMd->name()),
406 inheritedMd->docLine(),qPrint(inheritedMd->docFile()));
407 docFile = g_memberDef->getDefFileName();
408 docLine = g_memberDef->getDefLine();
411 QCString alStr = argListToString(al);
412 warn_doc_error(docFile,docLine,
413 "argument '%s' of command @param "
414 "is not found in the argument list of %s%s%s%s",
415 qPrint(aName), qPrint(scope), qPrint(g_memberDef->name()),
416 qPrint(alStr), qPrint(inheritedFrom));
422 /*! Checks if the parameters that have been specified using \@param are
423 * indeed all parameters.
424 * Must be called after checkArgumentName() has been called for each
427 static void checkUndocumentedParams()
429 if (g_memberDef && g_hasParamCommand && Config_getBool("WARN_IF_DOC_ERROR"))
431 ArgumentList *al=g_memberDef->isDocsForDefinition() ?
432 g_memberDef->argumentList() :
433 g_memberDef->declArgumentList();
434 SrcLangExt lang = g_memberDef->getLanguage();
437 ArgumentListIterator ali(*al);
440 for (ali.toFirst();(a=ali.current());++ali)
442 QCString argName = g_memberDef->isDefine() ? a->type : a->name;
443 if (lang==SrcLangExt_Fortran) argName = argName.lower();
444 argName=argName.stripWhiteSpace();
445 if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
446 if (g_memberDef->getLanguage()==SrcLangExt_Python && argName=="self")
448 // allow undocumented self parameter for Python
450 else if (!argName.isEmpty() && g_paramsFound.find(argName)==0 && a->docs.isEmpty())
460 "The following parameters of "+
461 QCString(g_memberDef->qualifiedName()) +
462 QCString(argListToString(al)) +
463 " are not documented:\n";
464 for (ali.toFirst();(a=ali.current());++ali)
466 QCString argName = g_memberDef->isDefine() ? a->type : a->name;
467 if (lang==SrcLangExt_Fortran) argName = argName.lower();
468 argName=argName.stripWhiteSpace();
469 if (g_memberDef->getLanguage()==SrcLangExt_Python && argName=="self")
471 // allow undocumented self parameter for Python
473 else if (!argName.isEmpty() && g_paramsFound.find(argName)==0)
483 errMsg+=" parameter '"+argName+"'";
486 if (g_memberDef->inheritsDocsFrom())
488 warn_doc_error(g_memberDef->getDefFileName(),
489 g_memberDef->getDefLine(),
490 substitute(errMsg,"%","%%"));
494 warn_doc_error(g_memberDef->docFile(),
495 g_memberDef->docLine(),
496 substitute(errMsg,"%","%%"));
503 /*! Check if a member has documentation for its parameter and or return
504 * type, if applicable. If found this will be stored in the member, this
505 * is needed as a member can have brief and detailed documentation, while
506 * only one of these needs to document the parameters.
508 static void detectNoDocumentedParams()
510 if (g_memberDef && Config_getBool("WARN_NO_PARAMDOC"))
512 ArgumentList *al = g_memberDef->argumentList();
513 ArgumentList *declAl = g_memberDef->declArgumentList();
514 QCString returnType = g_memberDef->typeString();
515 bool isPython = g_memberDef->getLanguage()==SrcLangExt_Python;
517 if (!g_memberDef->hasDocumentedParams() &&
520 //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
521 g_memberDef->setHasDocumentedParams(TRUE);
523 else if (!g_memberDef->hasDocumentedParams())
525 bool allDoc=TRUE; // no paramater => all parameters are documented
526 if ( // member has parameters
527 al!=0 && // but the member has a parameter list
528 al->count()>0 // with at least one parameter (that is not void)
531 ArgumentListIterator ali(*al);
534 // see if all parameters have documentation
535 for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
537 if (!a->name.isEmpty() && a->type!="void" &&
538 !(isPython && a->name=="self")
541 allDoc = !a->docs.isEmpty();
543 //printf("a->type=%s a->name=%s doc=%s\n",
544 // a->type.data(),a->name.data(),a->docs.data());
546 if (!allDoc && declAl!=0) // try declaration arguments as well
549 ArgumentListIterator ali(*declAl);
551 for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
553 if (!a->name.isEmpty() && a->type!="void" &&
554 !(isPython && a->name=="self")
557 allDoc = !a->docs.isEmpty();
559 //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data());
565 //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
566 g_memberDef->setHasDocumentedParams(TRUE);
569 //printf("Member %s hasReturnCommand=%d\n",g_memberDef->name().data(),g_hasReturnCommand);
570 if (!g_memberDef->hasDocumentedReturnType() && // docs not yet found
573 g_memberDef->setHasDocumentedReturnType(TRUE);
575 else if ( // see if return needs to documented
576 g_memberDef->hasDocumentedReturnType() ||
577 returnType.isEmpty() || // empty return type
578 returnType.find("void")!=-1 || // void return type
579 returnType.find("subroutine")!=-1 || // fortran subroutine
580 g_memberDef->isConstructor() || // a constructor
581 g_memberDef->isDestructor() // or destructor
584 g_memberDef->setHasDocumentedReturnType(TRUE);
591 //---------------------------------------------------------------------------
593 /*! Strips known html and tex extensions from \a text. */
594 static QCString stripKnownExtensions(const char *text)
596 QCString result=text;
597 if (result.right(4)==".tex")
599 result=result.left(result.length()-4);
601 else if (result.right(Doxygen::htmlFileExtension.length())==
602 QCString(Doxygen::htmlFileExtension))
604 result=result.left(result.length()-Doxygen::htmlFileExtension.length());
610 //---------------------------------------------------------------------------
612 /*! Returns TRUE iff node n is a child of a preformatted node */
613 static bool insidePRE(DocNode *n)
617 if (n->isPreformatted()) return TRUE;
623 //---------------------------------------------------------------------------
625 /*! Returns TRUE iff node n is a child of a html list item node */
626 static bool insideLI(DocNode *n)
630 if (n->kind()==DocNode::Kind_HtmlListItem) return TRUE;
636 //---------------------------------------------------------------------------
638 /*! Returns TRUE iff node n is a child of a unordered html list node */
639 static bool insideUL(DocNode *n)
643 if (n->kind()==DocNode::Kind_HtmlList &&
644 ((DocHtmlList *)n)->type()==DocHtmlList::Unordered) return TRUE;
650 //---------------------------------------------------------------------------
652 /*! Returns TRUE iff node n is a child of a ordered html list node */
653 static bool insideOL(DocNode *n)
657 if (n->kind()==DocNode::Kind_HtmlList &&
658 ((DocHtmlList *)n)->type()==DocHtmlList::Ordered) return TRUE;
664 //---------------------------------------------------------------------------
666 static bool insideTable(DocNode *n)
670 if (n->kind()==DocNode::Kind_HtmlTable) return TRUE;
676 //---------------------------------------------------------------------------
678 /*! Looks for a documentation block with name commandName in the current
679 * context (g_context). The resulting documentation string is
680 * put in pDoc, the definition in which the documentation was found is
682 * @retval TRUE if name was found.
683 * @retval FALSE if name was not found.
685 static bool findDocsForMemberOrCompound(const char *commandName,
690 //printf("findDocsForMemberOrCompound(%s)\n",commandName);
694 QCString cmdArg=substitute(commandName,"#","::");
695 int l=cmdArg.length();
696 if (l==0) return FALSE;
698 int funcStart=cmdArg.find('(');
705 // Check for the case of operator() and the like.
706 // beware of scenarios like operator()((foo)bar)
707 int secondParen = cmdArg.find('(', funcStart+1);
708 int leftParen = cmdArg.find(')', funcStart+1);
709 if (leftParen!=-1 && secondParen!=-1)
711 if (leftParen<secondParen)
713 funcStart=secondParen;
718 QCString name=removeRedundantWhiteSpace(cmdArg.left(funcStart));
719 QCString args=cmdArg.right(l-funcStart);
721 // try if the link is to a member
728 bool found = getDefs(
729 g_context.find('.')==-1?g_context.data():"", // `find('.') is a hack to detect files
731 args.isEmpty()?0:args.data(),
732 md,cd,fd,nd,gd,FALSE,0,TRUE);
733 //printf("found=%d context=%s name=%s\n",found,g_context.data(),name.data());
736 *pDoc=md->documentation();
737 *pBrief=md->briefDescription();
743 int scopeOffset=g_context.length();
746 QCString fullName=cmdArg;
749 fullName.prepend(g_context.left(scopeOffset)+"::");
751 //printf("Trying fullName=`%s'\n",fullName.data());
753 // try class, namespace, group, page, file reference
754 cd = Doxygen::classSDict->find(fullName);
757 *pDoc=cd->documentation();
758 *pBrief=cd->briefDescription();
762 nd = Doxygen::namespaceSDict->find(fullName);
765 *pDoc=nd->documentation();
766 *pBrief=nd->briefDescription();
770 gd = Doxygen::groupSDict->find(cmdArg);
773 *pDoc=gd->documentation();
774 *pBrief=gd->briefDescription();
778 pd = Doxygen::pageSDict->find(cmdArg);
781 *pDoc=pd->documentation();
782 *pBrief=pd->briefDescription();
787 fd = findFileDef(Doxygen::inputNameDict,cmdArg,ambig);
788 if (fd && !ambig) // file
790 *pDoc=fd->documentation();
791 *pBrief=fd->briefDescription();
802 scopeOffset = g_context.findRev("::",scopeOffset-1);
803 if (scopeOffset==-1) scopeOffset=0;
805 } while (scopeOffset>=0);
810 //---------------------------------------------------------------------------
812 // forward declaration
813 static bool defaultHandleToken(DocNode *parent,int tok,
814 QList<DocNode> &children,bool
818 static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
819 const QCString &cmdName)
821 DBG(("handleStyleArgument(%s)\n",qPrint(cmdName)));
822 QCString tokenName = g_token->name;
823 int tok=doctokenizerYYlex();
824 if (tok!=TK_WHITESPACE)
826 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
830 while ((tok=doctokenizerYYlex()) &&
831 tok!=TK_WHITESPACE &&
837 static QRegExp specialChar("[.,|()\\[\\]:;\\?]");
838 if (tok==TK_WORD && g_token->name.length()==1 &&
839 g_token->name.find(specialChar)!=-1)
841 // special character that ends the markup command
844 if (!defaultHandleToken(parent,tok,children))
849 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command \\%s as the argument of a \\%s command",
850 qPrint(g_token->name),qPrint(cmdName));
853 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found while handling command %s",
854 qPrint(g_token->name),qPrint(cmdName));
857 if (insideLI(parent) && Mappers::htmlTagMapper->map(g_token->name) && g_token->endTag)
858 { // ignore </li> as the end of a style command
864 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s while handling command %s",
865 tokToString(tok),qPrint(cmdName));
871 DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(cmdName),tok));
872 return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST
876 /*! Called when a style change starts. For instance a \<b\> command is
879 static void handleStyleEnter(DocNode *parent,QList<DocNode> &children,
880 DocStyleChange::Style s,const HtmlAttribList *attribs)
882 DBG(("HandleStyleEnter\n"));
883 DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,TRUE,attribs);
885 g_styleStack.push(sc);
888 /*! Called when a style change ends. For instance a \</b\> command is
891 static void handleStyleLeave(DocNode *parent,QList<DocNode> &children,
892 DocStyleChange::Style s,const char *tagName)
894 DBG(("HandleStyleLeave\n"));
895 if (g_styleStack.isEmpty() || // no style change
896 g_styleStack.top()->style()!=s || // wrong style change
897 g_styleStack.top()->position()!=g_nodeStack.count() // wrong position
900 if (g_styleStack.isEmpty())
902 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag without matching <%s>",
903 qPrint(tagName),qPrint(tagName));
905 else if (g_styleStack.top()->style()!=s)
907 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag while expecting </%s>",
908 qPrint(tagName),qPrint(g_styleStack.top()->styleString()));
912 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> at different nesting level (%d) than expected (%d)",
913 qPrint(tagName),g_nodeStack.count(),g_styleStack.top()->position());
916 else // end the section
918 DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,FALSE);
924 /*! Called at the end of a paragraph to close all open style changes
925 * (e.g. a <b> without a </b>). The closed styles are pushed onto a stack
926 * and entered again at the start of a new paragraph.
928 static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children)
930 if (!g_styleStack.isEmpty())
932 DocStyleChange *sc = g_styleStack.top();
933 while (sc && sc->position()>=g_nodeStack.count())
934 { // there are unclosed style modifiers in the paragraph
935 children.append(new DocStyleChange(parent,g_nodeStack.count(),sc->style(),FALSE));
936 g_initialStyleStack.push(sc);
938 sc = g_styleStack.top();
943 static void handleInitialStyleCommands(DocPara *parent,QList<DocNode> &children)
946 while ((sc=g_initialStyleStack.pop()))
948 handleStyleEnter(parent,children,sc->style(),&sc->attribs());
952 static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs)
954 HtmlAttribListIterator li(tagHtmlAttribs);
957 int retval = RetVal_OK;
958 for (li.toFirst();(opt=li.current());++li,++index)
960 if (opt->name=="name") // <a name=label> tag
962 if (!opt->value.isEmpty())
964 DocAnchor *anc = new DocAnchor(parent,opt->value,TRUE);
965 children.append(anc);
966 break; // stop looking for other tag attribs
970 warn_doc_error(g_fileName,doctokenizerYYlineno,"found <a> tag with name option but without value!");
973 else if (opt->name=="href") // <a href=url>..</a> tag
976 HtmlAttribList attrList = tagHtmlAttribs;
977 // and remove the href attribute
978 bool result = attrList.remove(index);
980 DocHRef *href = new DocHRef(parent,attrList,opt->value,g_relPath);
981 children.append(href);
982 g_insideHtmlLink=TRUE;
983 retval = href->parse();
984 g_insideHtmlLink=FALSE;
987 else // unsupported option for tag a
994 const char *DocStyleChange::styleString() const
998 case DocStyleChange::Bold: return "b";
999 case DocStyleChange::Italic: return "em";
1000 case DocStyleChange::Code: return "code";
1001 case DocStyleChange::Center: return "center";
1002 case DocStyleChange::Small: return "small";
1003 case DocStyleChange::Subscript: return "subscript";
1004 case DocStyleChange::Superscript: return "superscript";
1005 case DocStyleChange::Preformatted: return "pre";
1006 case DocStyleChange::Div: return "div";
1007 case DocStyleChange::Span: return "span";
1012 static void handleUnclosedStyleCommands()
1014 if (!g_initialStyleStack.isEmpty())
1016 DocStyleChange *sc = g_initialStyleStack.top();
1017 g_initialStyleStack.pop();
1018 handleUnclosedStyleCommands();
1019 warn_doc_error(g_fileName,doctokenizerYYlineno,
1020 "end of comment block while expecting "
1021 "command </%s>",qPrint(sc->styleString()));
1025 static void handleLinkedWord(DocNode *parent,QList<DocNode> &children)
1027 QCString name = linkToText(SrcLangExt_Unknown,g_token->name,TRUE);
1028 static bool autolinkSupport = Config_getBool("AUTOLINK_SUPPORT");
1029 if (!autolinkSupport) // no autolinking -> add as normal word
1031 children.append(new DocWord(parent,name));
1035 // ------- try to turn the word 'name' into a link
1037 Definition *compound=0;
1038 MemberDef *member=0;
1039 int len = g_token->name.length();
1042 FileDef *fd = findFileDef(Doxygen::inputNameDict,g_fileName,ambig);
1043 //printf("handleLinkedWord(%s) g_context=%s\n",g_token->name.data(),g_context.data());
1044 if (!g_insideHtmlLink &&
1045 (resolveRef(g_context,g_token->name,g_inSeeBlock,&compound,&member,TRUE,fd,TRUE)
1046 || (!g_context.isEmpty() && // also try with global scope
1047 resolveRef("",g_token->name,g_inSeeBlock,&compound,&member,FALSE,0,TRUE))
1051 //printf("resolveRef %s = %p (linkable?=%d)\n",qPrint(g_token->name),member,member ? member->isLinkable() : FALSE);
1052 if (member && member->isLinkable()) // member link
1054 if (member->isObjCMethod())
1056 bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE;
1057 name = member->objCMethodName(localLink,g_inSeeBlock);
1060 DocLinkedWord(parent,name,
1061 member->getReference(),
1062 member->getOutputFileBase(),
1064 member->briefDescriptionAsTooltip()
1068 else if (compound->isLinkable()) // compound link
1070 QCString anchor = compound->anchor();
1071 if (compound->definitionType()==Definition::TypeFile)
1075 else if (compound->definitionType()==Definition::TypeGroup)
1077 name=((GroupDef*)compound)->groupTitle();
1080 DocLinkedWord(parent,name,
1081 compound->getReference(),
1082 compound->getOutputFileBase(),
1084 compound->briefDescriptionAsTooltip()
1088 else if (compound->definitionType()==Definition::TypeFile &&
1089 ((FileDef*)compound)->generateSourceFile()
1090 ) // undocumented file that has source code we can link to
1093 DocLinkedWord(parent,g_token->name,
1094 compound->getReference(),
1095 compound->getSourceFileBase(),
1097 compound->briefDescriptionAsTooltip()
1101 else // not linkable
1103 children.append(new DocWord(parent,name));
1106 else if (!g_insideHtmlLink && len>1 && g_token->name.at(len-1)==':')
1108 // special case, where matching Foo: fails to be an Obj-C reference,
1109 // but Foo itself might be linkable.
1110 g_token->name=g_token->name.left(len-1);
1111 handleLinkedWord(parent,children);
1112 children.append(new DocWord(parent,":"));
1114 else if (!g_insideHtmlLink && (cd=getClass(g_token->name+"-p")))
1116 // special case 2, where the token name is not a class, but could
1117 // be a Obj-C protocol
1119 DocLinkedWord(parent,name,
1121 cd->getOutputFileBase(),
1123 cd->briefDescriptionAsTooltip()
1126 // else if (!g_insideHtmlLink && (cd=getClass(g_token->name+"-g")))
1128 // // special case 3, where the token name is not a class, but could
1129 // // be a C# generic
1130 // children.append(new
1131 // DocLinkedWord(parent,name,
1132 // cd->getReference(),
1133 // cd->getOutputFileBase(),
1135 // cd->briefDescriptionAsTooltip()
1138 else // normal non-linkable word
1140 if (g_token->name.left(1)=="#" || g_token->name.left(2)=="::")
1142 warn_doc_error(g_fileName,doctokenizerYYlineno,"explicit link request to '%s' could not be resolved",qPrint(name));
1143 children.append(new DocWord(parent,g_token->name));
1147 children.append(new DocWord(parent,name));
1152 static void handleParameterType(DocNode *parent,QList<DocNode> &children,const QCString ¶mTypes)
1154 QCString name = g_token->name;
1157 while ((i=paramTypes.find('|',p))!=-1)
1159 g_token->name = paramTypes.mid(p,i-p);
1160 handleLinkedWord(parent,children);
1163 g_token->name = paramTypes.mid(p);
1164 handleLinkedWord(parent,children);
1165 g_token->name = name;
1168 static DocInternalRef *handleInternalRef(DocNode *parent)
1170 //printf("CMD_INTERNALREF\n");
1171 int tok=doctokenizerYYlex();
1172 QCString tokenName = g_token->name;
1173 if (tok!=TK_WHITESPACE)
1175 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
1179 doctokenizerYYsetStateInternalRef();
1180 tok=doctokenizerYYlex(); // get the reference id
1181 if (tok!=TK_WORD && tok!=TK_LNKWORD)
1183 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
1184 tokToString(tok),qPrint(tokenName));
1187 return new DocInternalRef(parent,g_token->name);
1190 static DocAnchor *handleAnchor(DocNode *parent)
1192 int tok=doctokenizerYYlex();
1193 if (tok!=TK_WHITESPACE)
1195 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
1196 qPrint(g_token->name));
1199 doctokenizerYYsetStateAnchor();
1200 tok=doctokenizerYYlex();
1203 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
1204 "argument of command %s",qPrint(g_token->name));
1207 else if (tok!=TK_WORD && tok!=TK_LNKWORD)
1209 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
1210 tokToString(tok),qPrint(g_token->name));
1213 doctokenizerYYsetStatePara();
1214 return new DocAnchor(parent,g_token->name,FALSE);
1218 /* Helper function that deals with the most common tokens allowed in
1219 * title like sections.
1220 * @param parent Parent node, owner of the children list passed as
1221 * the third argument.
1222 * @param tok The token to process.
1223 * @param children The list of child nodes to which the node representing
1224 * the token can be added.
1225 * @param handleWord Indicates if word token should be processed
1226 * @retval TRUE The token was handled.
1227 * @retval FALSE The token was not handled.
1229 static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool
1232 DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
1233 if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
1234 tok==TK_COMMAND || tok==TK_HTMLTAG
1237 DBG((" name=%s",qPrint(g_token->name)));
1241 QCString tokenName = g_token->name;
1245 switch (Mappers::cmdMapper->map(tokenName))
1248 children.append(new DocSymbol(parent,DocSymbol::Sym_BSlash));
1251 children.append(new DocSymbol(parent,DocSymbol::Sym_At));
1254 children.append(new DocSymbol(parent,DocSymbol::Sym_Less));
1257 children.append(new DocSymbol(parent,DocSymbol::Sym_Greater));
1260 children.append(new DocSymbol(parent,DocSymbol::Sym_Amp));
1263 children.append(new DocSymbol(parent,DocSymbol::Sym_Dollar));
1266 children.append(new DocSymbol(parent,DocSymbol::Sym_Hash));
1269 children.append(new DocSymbol(parent,DocSymbol::Sym_DoubleColon));
1272 children.append(new DocSymbol(parent,DocSymbol::Sym_Percent));
1275 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1276 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1279 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1280 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1281 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1284 children.append(new DocSymbol(parent,DocSymbol::Sym_Quot));
1288 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
1289 tok=handleStyleArgument(parent,children,tokenName);
1290 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
1291 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
1292 if (tok==TK_NEWPARA) goto handlepara;
1293 else if (tok==TK_WORD || tok==TK_HTMLTAG)
1295 DBG(("CMD_EMPHASIS: reparsing command %s\n",qPrint(g_token->name)));
1302 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
1303 tok=handleStyleArgument(parent,children,tokenName);
1304 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
1305 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
1306 if (tok==TK_NEWPARA) goto handlepara;
1307 else if (tok==TK_WORD || tok==TK_HTMLTAG)
1309 DBG(("CMD_BOLD: reparsing command %s\n",qPrint(g_token->name)));
1316 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,TRUE));
1317 tok=handleStyleArgument(parent,children,tokenName);
1318 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,FALSE));
1319 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
1320 if (tok==TK_NEWPARA) goto handlepara;
1321 else if (tok==TK_WORD || tok==TK_HTMLTAG)
1323 DBG(("CMD_CODE: reparsing command %s\n",qPrint(g_token->name)));
1330 doctokenizerYYsetStateHtmlOnly();
1331 tok = doctokenizerYYlex();
1332 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block"));
1333 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker");
1334 doctokenizerYYsetStatePara();
1339 doctokenizerYYsetStateManOnly();
1340 tok = doctokenizerYYlex();
1341 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName));
1342 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker");
1343 doctokenizerYYsetStatePara();
1348 doctokenizerYYsetStateRtfOnly();
1349 tok = doctokenizerYYlex();
1350 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName));
1351 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker");
1352 doctokenizerYYsetStatePara();
1357 doctokenizerYYsetStateLatexOnly();
1358 tok = doctokenizerYYlex();
1359 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName));
1360 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker",doctokenizerYYlineno);
1361 doctokenizerYYsetStatePara();
1366 doctokenizerYYsetStateXmlOnly();
1367 tok = doctokenizerYYlex();
1368 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName));
1369 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker",doctokenizerYYlineno);
1370 doctokenizerYYsetStatePara();
1375 doctokenizerYYsetStateDbOnly();
1376 tok = doctokenizerYYlex();
1377 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName));
1378 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker",doctokenizerYYlineno);
1379 doctokenizerYYsetStatePara();
1384 DocFormula *form=new DocFormula(parent,g_token->id);
1385 children.append(form);
1390 DocAnchor *anchor = handleAnchor(parent);
1393 children.append(anchor);
1397 case CMD_INTERNALREF:
1399 DocInternalRef *ref = handleInternalRef(parent);
1402 children.append(ref);
1405 doctokenizerYYsetStatePara();
1414 switch (Mappers::htmlTagMapper->map(tokenName))
1417 warn_doc_error(g_fileName,doctokenizerYYlineno,"found <div> tag in heading\n");
1420 warn_doc_error(g_fileName,doctokenizerYYlineno,"found <pre> tag in heading\n");
1423 if (!g_token->endTag)
1425 handleStyleEnter(parent,children,DocStyleChange::Bold,&g_token->attribs);
1429 handleStyleLeave(parent,children,DocStyleChange::Bold,tokenName);
1434 if (!g_token->endTag)
1436 handleStyleEnter(parent,children,DocStyleChange::Code,&g_token->attribs);
1440 handleStyleLeave(parent,children,DocStyleChange::Code,tokenName);
1444 if (!g_token->endTag)
1446 handleStyleEnter(parent,children,DocStyleChange::Italic,&g_token->attribs);
1450 handleStyleLeave(parent,children,DocStyleChange::Italic,tokenName);
1454 if (!g_token->endTag)
1456 handleStyleEnter(parent,children,DocStyleChange::Subscript,&g_token->attribs);
1460 handleStyleLeave(parent,children,DocStyleChange::Subscript,tokenName);
1464 if (!g_token->endTag)
1466 handleStyleEnter(parent,children,DocStyleChange::Superscript,&g_token->attribs);
1470 handleStyleLeave(parent,children,DocStyleChange::Superscript,tokenName);
1474 if (!g_token->endTag)
1476 handleStyleEnter(parent,children,DocStyleChange::Center,&g_token->attribs);
1480 handleStyleLeave(parent,children,DocStyleChange::Center,tokenName);
1484 if (!g_token->endTag)
1486 handleStyleEnter(parent,children,DocStyleChange::Small,&g_token->attribs);
1490 handleStyleLeave(parent,children,DocStyleChange::Small,tokenName);
1501 DocSymbol::SymType s = DocSymbol::decodeSymbol(tokenName);
1502 if (s!=DocSymbol::Sym_Unknown)
1504 children.append(new DocSymbol(parent,s));
1515 if (insidePRE(parent) || !children.isEmpty())
1517 children.append(new DocWhiteSpace(parent,g_token->chars));
1523 handleLinkedWord(parent,children);
1531 children.append(new DocWord(parent,g_token->name));
1537 if (g_insideHtmlLink)
1539 children.append(new DocWord(parent,g_token->name));
1543 children.append(new DocURL(parent,g_token->name,g_token->isEMailAddr));
1552 //---------------------------------------------------------------------------
1554 static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs)
1556 HtmlAttribListIterator li(tagHtmlAttribs);
1560 for (li.toFirst();(opt=li.current());++li,++index)
1562 //printf("option name=%s value=%s\n",opt->name.data(),opt->value.data());
1563 if (opt->name=="src" && !opt->value.isEmpty())
1566 HtmlAttribList attrList = tagHtmlAttribs;
1567 // and remove the src attribute
1568 bool result = attrList.remove(index);
1570 DocImage *img = new DocImage(parent,attrList,opt->value,DocImage::Html,opt->value);
1571 children.append(img);
1577 warn_doc_error(g_fileName,doctokenizerYYlineno,"IMG tag does not have a SRC attribute!\n");
1581 //---------------------------------------------------------------------------
1583 DocSymbol::SymType DocSymbol::decodeSymbol(const QCString &symName)
1585 DBG(("decodeSymbol(%s)\n",qPrint(symName)));
1586 return HtmlEntityMapper::instance()->name2sym(symName);
1589 //---------------------------------------------------------------------------
1591 static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children,
1592 const QCString &doc)
1594 int retval = RetVal_OK;
1596 if (doc.isEmpty()) return retval;
1598 doctokenizerYYinit(doc,g_fileName);
1600 // first parse any number of paragraphs
1603 if (!children.isEmpty() && children.getLast()->kind()==DocNode::Kind_Para)
1604 { // last child item was a paragraph
1605 lastPar = (DocPara*)children.getLast();
1610 DocPara *par = new DocPara(parent);
1611 if (isFirst) { par->markFirst(); isFirst=FALSE; }
1612 retval=par->parse();
1613 if (!par->isEmpty())
1615 children.append(par);
1616 if (lastPar) lastPar->markLast(FALSE);
1623 } while (retval==TK_NEWPARA);
1624 if (lastPar) lastPar->markLast();
1626 //printf("internalValidateParsingDoc: %p: isFirst=%d isLast=%d\n",
1627 // lastPar,lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
1632 //---------------------------------------------------------------------------
1634 static void readTextFileByName(const QCString &file,QCString &text)
1636 QStrList &examplePathList = Config_getList("EXAMPLE_PATH");
1637 char *s=examplePathList.first();
1640 QCString absFileName = QCString(s)+portable_pathSeparator()+file;
1641 QFileInfo fi(absFileName);
1644 text = fileToString(absFileName,Config_getBool("FILTER_SOURCE_FILES"));
1647 s=examplePathList.next();
1650 // as a fallback we also look in the exampleNameDict
1653 if ((fd=findFileDef(Doxygen::exampleNameDict,file,ambig)))
1655 text = fileToString(fd->absFilePath(),Config_getBool("FILTER_SOURCE_FILES"));
1659 warn_doc_error(g_fileName,doctokenizerYYlineno,"included file name %s is ambiguous"
1660 "Possible candidates:\n%s",qPrint(file),
1661 qPrint(showFileDefMatches(Doxygen::exampleNameDict,file))
1666 warn_doc_error(g_fileName,doctokenizerYYlineno,"included file %s is not found. "
1667 "Check your EXAMPLE_PATH",qPrint(file));
1671 //---------------------------------------------------------------------------
1673 DocWord::DocWord(DocNode *parent,const QCString &word) :
1677 //printf("new word %s url=%s\n",word.data(),g_searchUrl.data());
1678 if (Doxygen::searchIndex && !g_searchUrl.isEmpty())
1680 Doxygen::searchIndex->addWord(word,FALSE);
1684 //---------------------------------------------------------------------------
1686 DocLinkedWord::DocLinkedWord(DocNode *parent,const QCString &word,
1687 const QCString &ref,const QCString &file,
1688 const QCString &anchor,const QCString &tooltip) :
1689 m_word(word), m_ref(ref),
1690 m_file(file), m_relPath(g_relPath), m_anchor(anchor),
1694 //printf("DocLinkedWord: new word %s url=%s tooltip='%s'\n",
1695 // word.data(),g_searchUrl.data(),tooltip.data());
1696 if (Doxygen::searchIndex && !g_searchUrl.isEmpty())
1698 Doxygen::searchIndex->addWord(word,FALSE);
1702 //---------------------------------------------------------------------------
1704 DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor)
1709 warn_doc_error(g_fileName,doctokenizerYYlineno,"Empty anchor label");
1711 if (newAnchor) // found <a name="label">
1715 else if (id.left(CiteConsts::anchorPrefix.length()) == CiteConsts::anchorPrefix)
1717 CiteInfo *cite = Doxygen::citeDict->find(id.mid(CiteConsts::anchorPrefix.length()));
1720 m_file = convertNameToFile(CiteConsts::fileName,FALSE,TRUE);
1725 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid cite anchor id `%s'",qPrint(id));
1726 m_anchor = "invalid";
1730 else // found \anchor label
1732 SectionInfo *sec = Doxygen::sectionDict->find(id);
1735 //printf("Found anchor %s\n",id.data());
1736 m_file = sec->fileName;
1737 m_anchor = sec->label;
1738 if (g_sectionDict && g_sectionDict->find(id)==0)
1740 //printf("Inserting in dictionary!\n");
1741 g_sectionDict->append(id,sec);
1746 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid anchor id `%s'",qPrint(id));
1747 m_anchor = "invalid";
1753 //---------------------------------------------------------------------------
1755 DocVerbatim::DocVerbatim(DocNode *parent,const QCString &context,
1756 const QCString &text, Type t,bool isExample,
1757 const QCString &exampleFile,bool isBlock,const QCString &lang)
1758 : m_context(context), m_text(text), m_type(t),
1759 m_isExample(isExample), m_exampleFile(exampleFile),
1760 m_relPath(g_relPath), m_lang(lang), m_isBlock(isBlock)
1766 //---------------------------------------------------------------------------
1768 void DocInclude::parse()
1770 DBG(("DocInclude::parse(file=%s,text=%s)\n",qPrint(m_file),qPrint(m_text)));
1778 readTextFileByName(m_file,m_text);
1779 g_includeFileText = m_text;
1780 g_includeFileOffset = 0;
1781 g_includeFileLength = m_text.length();
1782 //printf("g_includeFile=<<%s>>\n",g_includeFileText.data());
1787 readTextFileByName(m_file,m_text);
1790 readTextFileByName(m_file,m_text);
1793 readTextFileByName(m_file,m_text);
1794 // check here for the existence of the blockId inside the file, so we
1795 // only generate the warning once.
1797 if (!m_blockId.isEmpty() && (count=m_text.contains(m_blockId.data()))!=2)
1799 warn_doc_error(g_fileName,doctokenizerYYlineno,"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n",
1800 m_blockId.data(),m_file.data(),count);
1806 //---------------------------------------------------------------------------
1808 void DocIncOperator::parse()
1810 const char *p = g_includeFileText;
1811 uint l = g_includeFileLength;
1812 uint o = g_includeFileOffset;
1813 DBG(("DocIncOperator::parse() text=%s off=%d len=%d\n",qPrint(p),o,l));
1815 bool nonEmpty = FALSE;
1824 if (nonEmpty) break; // we have a pattern to match
1825 so=o+1; // no pattern, skip empty line
1827 else if (!isspace((uchar)c)) // no white space char
1833 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1835 m_text = g_includeFileText.mid(so,o-so);
1836 DBG(("DocIncOperator::parse() Line: %s\n",qPrint(m_text)));
1838 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
1849 if (nonEmpty) break; // we have a pattern to match
1850 so=o+1; // no pattern, skip empty line
1852 else if (!isspace((uchar)c)) // no white space char
1858 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1860 m_text = g_includeFileText.mid(so,o-so);
1861 DBG(("DocIncOperator::parse() SkipLine: %s\n",qPrint(m_text)));
1864 o++; // skip new line
1866 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
1877 if (nonEmpty) break; // we have a pattern to match
1878 so=o+1; // no pattern, skip empty line
1880 else if (!isspace((uchar)c)) // no white space char
1886 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1890 o++; // skip new line
1892 g_includeFileOffset = so; // set pointer to start of new line
1904 if (nonEmpty) break; // we have a pattern to match
1905 so=o+1; // no pattern, skip empty line
1907 else if (!isspace((uchar)c)) // no white space char
1913 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1915 m_text = g_includeFileText.mid(bo,o-bo);
1916 DBG(("DocIncOperator::parse() Until: %s\n",qPrint(m_text)));
1919 o++; // skip new line
1921 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
1926 //---------------------------------------------------------------------------
1928 void DocCopy::parse(QList<DocNode> &children)
1932 if (findDocsForMemberOrCompound(m_link,&doc,&brief,&def))
1934 if (g_copyStack.findRef(def)==-1) // definition not parsed earlier
1936 bool hasParamCommand = g_hasParamCommand;
1937 bool hasReturnCommand = g_hasReturnCommand;
1938 QDict<void> paramsFound = g_paramsFound;
1939 //printf("..1 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
1940 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
1942 docParserPushContext(FALSE);
1944 if (def->definitionType()==Definition::TypeMember && def->getOuterScope())
1946 if (def->getOuterScope()!=Doxygen::globalScope)
1948 g_context=def->getOuterScope()->name();
1951 else if (def!=Doxygen::globalScope)
1953 g_context=def->name();
1955 g_styleStack.clear();
1956 g_nodeStack.clear();
1957 g_paramsFound.clear();
1958 g_copyStack.append(def);
1959 // make sure the descriptions end with a newline, so the parser will correctly
1960 // handle them in all cases.
1961 //printf("doc='%s'\n",doc.data());
1962 //printf("brief='%s'\n",brief.data());
1966 internalValidatingParseDoc(m_parent,children,brief);
1968 //printf("..2 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
1969 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
1970 hasParamCommand = hasParamCommand || g_hasParamCommand;
1971 hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
1972 QDictIterator<void> it(g_paramsFound);
1974 for (;(item=it.current());++it)
1976 paramsFound.insert(it.currentKey(),it.current());
1982 internalValidatingParseDoc(m_parent,children,doc);
1984 //printf("..3 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
1985 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
1986 hasParamCommand = hasParamCommand || g_hasParamCommand;
1987 hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
1988 QDictIterator<void> it(g_paramsFound);
1990 for (;(item=it.current());++it)
1992 paramsFound.insert(it.currentKey(),it.current());
1995 g_copyStack.remove(def);
1996 ASSERT(g_styleStack.isEmpty());
1997 ASSERT(g_nodeStack.isEmpty());
1998 docParserPopContext(TRUE);
2000 g_hasParamCommand = hasParamCommand;
2001 g_hasReturnCommand = hasReturnCommand;
2002 g_paramsFound = paramsFound;
2004 //printf("..4 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
2005 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
2007 else // oops, recursion
2009 warn_doc_error(g_fileName,doctokenizerYYlineno,"recursive call chain of \\copydoc commands detected at %d\n",
2010 doctokenizerYYlineno);
2015 warn_doc_error(g_fileName,doctokenizerYYlineno,"target %s of \\copydoc command not found",
2020 //---------------------------------------------------------------------------
2022 DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) :
2023 m_id(id), m_key(key), m_relPath(g_relPath)
2028 bool DocXRefItem::parse()
2031 RefList *refList = Doxygen::xrefLists->find(m_key);
2034 // either not a built-in list or the list is enabled
2035 (m_key!="todo" || Config_getBool("GENERATE_TODOLIST")) &&
2036 (m_key!="test" || Config_getBool("GENERATE_TESTLIST")) &&
2037 (m_key!="bug" || Config_getBool("GENERATE_BUGLIST")) &&
2038 (m_key!="deprecated" || Config_getBool("GENERATE_DEPRECATEDLIST"))
2042 RefItem *item = refList->getRefItem(m_id);
2046 if (g_memberDef && g_memberDef->name().at(0)=='@')
2048 m_file = "@"; // can't cross reference anonymous enum
2053 m_file = convertNameToFile(refList->listName(),FALSE,TRUE);
2054 m_anchor = item->listAnchor;
2056 m_title = refList->sectionTitle();
2057 //printf("DocXRefItem: file=%s anchor=%s title=%s\n",
2058 // m_file.data(),m_anchor.data(),m_title.data());
2060 if (!item->text.isEmpty())
2062 docParserPushContext();
2063 internalValidatingParseDoc(this,m_children,item->text);
2064 docParserPopContext();
2072 //---------------------------------------------------------------------------
2074 DocFormula::DocFormula(DocNode *parent,int id) :
2075 m_relPath(g_relPath)
2079 formCmd.sprintf("\\form#%d",id);
2080 Formula *formula=Doxygen::formulaNameDict->find(formCmd);
2083 m_id = formula->getId();
2084 m_name.sprintf("form_%d",m_id);
2085 m_text = formula->getFormulaText();
2089 //---------------------------------------------------------------------------
2091 //int DocLanguage::parse()
2094 // DBG(("DocLanguage::parse() start\n"));
2095 // g_nodeStack.push(this);
2097 // // parse one or more paragraphs
2098 // bool isFirst=TRUE;
2102 // par = new DocPara(this);
2103 // if (isFirst) { par->markFirst(); isFirst=FALSE; }
2104 // m_children.append(par);
2105 // retval=par->parse();
2107 // while (retval==TK_NEWPARA);
2108 // if (par) par->markLast();
2110 // DBG(("DocLanguage::parse() end\n"));
2111 // DocNode *n = g_nodeStack.pop();
2116 //---------------------------------------------------------------------------
2118 void DocSecRefItem::parse()
2120 DBG(("DocSecRefItem::parse() start\n"));
2121 g_nodeStack.push(this);
2123 doctokenizerYYsetStateTitle();
2125 while ((tok=doctokenizerYYlex()))
2127 if (!defaultHandleToken(this,tok,m_children))
2132 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\refitem",
2133 qPrint(g_token->name));
2136 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2137 qPrint(g_token->name));
2140 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2146 doctokenizerYYsetStatePara();
2147 handlePendingStyleCommands(this,m_children);
2150 if (!m_target.isEmpty())
2152 sec=Doxygen::sectionDict->find(m_target);
2155 m_file = sec->fileName;
2156 m_anchor = sec->label;
2157 if (g_sectionDict && g_sectionDict->find(m_target)==0)
2159 g_sectionDict->append(m_target,sec);
2164 warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to unknown section %s",
2170 warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to empty target");
2173 DBG(("DocSecRefItem::parse() end\n"));
2174 DocNode *n = g_nodeStack.pop();
2178 //---------------------------------------------------------------------------
2180 void DocSecRefList::parse()
2182 DBG(("DocSecRefList::parse() start\n"));
2183 g_nodeStack.push(this);
2185 int tok=doctokenizerYYlex();
2187 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
2191 if (tok==TK_COMMAND)
2193 switch (Mappers::cmdMapper->map(g_token->name))
2195 case CMD_SECREFITEM:
2197 int tok=doctokenizerYYlex();
2198 if (tok!=TK_WHITESPACE)
2200 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\refitem command");
2203 tok=doctokenizerYYlex();
2204 if (tok!=TK_WORD && tok!=TK_LNKWORD)
2206 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\refitem",
2211 DocSecRefItem *item = new DocSecRefItem(this,g_token->name);
2212 m_children.append(item);
2216 case CMD_ENDSECREFLIST:
2219 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\secreflist",
2220 qPrint(g_token->name));
2224 else if (tok==TK_WHITESPACE)
2226 // ignore whitespace
2230 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s inside section reference list",
2234 tok=doctokenizerYYlex();
2238 DBG(("DocSecRefList::parse() end\n"));
2239 DocNode *n = g_nodeStack.pop();
2243 //---------------------------------------------------------------------------
2245 DocInternalRef::DocInternalRef(DocNode *parent,const QCString &ref)
2246 : m_relPath(g_relPath)
2249 int i=ref.find('#');
2252 m_anchor = ref.right(ref.length()-i-1);
2253 m_file = ref.left(i);
2261 void DocInternalRef::parse()
2263 g_nodeStack.push(this);
2264 DBG(("DocInternalRef::parse() start\n"));
2267 while ((tok=doctokenizerYYlex()))
2269 if (!defaultHandleToken(this,tok,m_children))
2274 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\ref",
2275 qPrint(g_token->name));
2278 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2279 qPrint(g_token->name));
2282 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2289 handlePendingStyleCommands(this,m_children);
2290 DBG(("DocInternalRef::parse() end\n"));
2291 DocNode *n=g_nodeStack.pop();
2295 //---------------------------------------------------------------------------
2297 DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
2298 m_refToSection(FALSE), m_refToAnchor(FALSE), m_isSubPage(FALSE)
2301 Definition *compound = 0;
2303 //printf("DocRef::DocRef(target=%s,context=%s)\n",target.data(),context.data());
2304 ASSERT(!target.isEmpty());
2305 SrcLangExt lang = getLanguageFromFileName(target);
2306 m_relPath = g_relPath;
2307 SectionInfo *sec = Doxygen::sectionDict->find(target);
2308 if (sec==0 && lang==SrcLangExt_Markdown) // lookup as markdown file
2310 sec = Doxygen::sectionDict->find(markdownFileNameToId(target));
2312 if (sec) // ref to section or anchor
2315 if (sec->type==SectionInfo::Page)
2317 pd = Doxygen::pageSDict->find(target);
2319 m_text = sec->title;
2320 if (m_text.isEmpty()) m_text = sec->label;
2323 m_file = stripKnownExtensions(sec->fileName);
2324 m_refToAnchor = sec->type==SectionInfo::Anchor;
2325 m_refToSection = sec->type!=SectionInfo::Anchor;
2326 m_isSubPage = pd && pd->hasParentPage();
2327 if (sec->type!=SectionInfo::Page || m_isSubPage) m_anchor = sec->label;
2328 //printf("m_text=%s,m_ref=%s,m_file=%s,m_refToAnchor=%d type=%d\n",
2329 // m_text.data(),m_ref.data(),m_file.data(),m_refToAnchor,sec->type);
2332 else if (resolveLink(context,target,TRUE,&compound,anchor))
2334 bool isFile = compound ?
2335 (compound->definitionType()==Definition::TypeFile ||
2336 compound->definitionType()==Definition::TypePage ? TRUE : FALSE) :
2338 m_text = linkToText(compound?compound->getLanguage():SrcLangExt_Unknown,target,isFile);
2340 if (compound && compound->isLinkable()) // ref to compound
2342 if (anchor.isEmpty() && /* compound link */
2343 compound->definitionType()==Definition::TypeGroup && /* is group */
2344 ((GroupDef *)compound)->groupTitle() /* with title */
2347 m_text=((GroupDef *)compound)->groupTitle(); // use group's title as link
2349 else if (compound->definitionType()==Definition::TypeMember &&
2350 ((MemberDef*)compound)->isObjCMethod())
2352 // Objective C Method
2353 MemberDef *member = (MemberDef*)compound;
2354 bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE;
2355 m_text = member->objCMethodName(localLink,g_inSeeBlock);
2358 m_file = compound->getOutputFileBase();
2359 m_ref = compound->getReference();
2360 //printf("isFile=%d compound=%s (%d)\n",isFile,compound->name().data(),
2361 // compound->definitionType());
2364 else if (compound->definitionType()==Definition::TypeFile &&
2365 ((FileDef*)compound)->generateSourceFile()
2366 ) // undocumented file that has source code we can link to
2368 m_file = compound->getSourceFileBase();
2369 m_ref = compound->getReference();
2374 warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to `%s' for \\ref command",
2378 static void flattenParagraphs(DocNode *root,QList<DocNode> &children)
2380 QListIterator<DocNode> li(children);
2381 QList<DocNode> newChildren;
2383 for (li.toFirst();(dn=li.current());++li)
2385 if (dn->kind()==DocNode::Kind_Para)
2387 DocPara *para = (DocPara*)dn;
2388 QList<DocNode> ¶Children = para->children();
2389 paraChildren.setAutoDelete(FALSE); // unlink children from paragraph node
2390 QListIterator<DocNode> li2(paraChildren);
2392 for (li2.toFirst();(dn2=li2.current());++li2)
2394 newChildren.append(dn2); // add them to new node
2399 QListIterator<DocNode> li3(newChildren);
2400 for (li3.toFirst();(dn=li3.current());++li3)
2402 children.append(dn);
2403 dn->setParent(root);
2407 void DocRef::parse()
2409 g_nodeStack.push(this);
2410 DBG(("DocRef::parse() start\n"));
2413 while ((tok=doctokenizerYYlex()))
2415 if (!defaultHandleToken(this,tok,m_children))
2420 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\ref",
2421 qPrint(g_token->name));
2424 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2425 qPrint(g_token->name));
2430 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2437 if (m_children.isEmpty() && !m_text.isEmpty())
2439 g_insideHtmlLink=TRUE;
2440 docParserPushContext();
2441 internalValidatingParseDoc(this,m_children,m_text);
2442 docParserPopContext();
2443 g_insideHtmlLink=FALSE;
2444 flattenParagraphs(this,m_children);
2447 handlePendingStyleCommands(this,m_children);
2449 DocNode *n=g_nodeStack.pop();
2453 //---------------------------------------------------------------------------
2455 DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //context)
2457 static uint numBibFiles = Config_getList("CITE_BIB_FILES").count();
2460 //printf("DocCite::DocCite(target=%s)\n",target.data());
2461 ASSERT(!target.isEmpty());
2462 m_relPath = g_relPath;
2463 CiteInfo *cite = Doxygen::citeDict->find(target);
2464 if (numBibFiles>0 && cite) // ref to citation
2466 m_text = cite->text;
2467 if (m_text.isEmpty()) m_text = cite->label;
2469 m_anchor = CiteConsts::anchorPrefix+cite->label;
2470 m_file = convertNameToFile(CiteConsts::fileName,FALSE,TRUE);
2471 //printf("CITE ==> m_text=%s,m_ref=%s,m_file=%s,m_anchor=%s\n",
2472 // m_text.data(),m_ref.data(),m_file.data(),m_anchor.data());
2475 m_text = linkToText(SrcLangExt_Unknown,target,FALSE);
2476 warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to `%s' for \\cite command",
2480 //---------------------------------------------------------------------------
2482 DocLink::DocLink(DocNode *parent,const QCString &target)
2485 Definition *compound;
2489 m_relPath = g_relPath;
2490 if (!m_refText.isEmpty() && m_refText.at(0)=='#')
2492 m_refText = m_refText.right(m_refText.length()-1);
2494 if (resolveLink(g_context,stripKnownExtensions(target),g_inSeeBlock,
2498 if (compound && compound->isLinkable())
2500 m_file = compound->getOutputFileBase();
2501 m_ref = compound->getReference();
2503 else if (compound->definitionType()==Definition::TypeFile &&
2504 ((FileDef*)compound)->generateSourceFile()
2505 ) // undocumented file that has source code we can link to
2507 m_file = compound->getSourceFileBase();
2508 m_ref = compound->getReference();
2513 // bogus link target
2514 warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve link to `%s' for \\link command",
2519 QCString DocLink::parse(bool isJavaLink,bool isXmlLink)
2522 g_nodeStack.push(this);
2523 DBG(("DocLink::parse() start\n"));
2526 while ((tok=doctokenizerYYlex()))
2528 if (!defaultHandleToken(this,tok,m_children,FALSE))
2533 switch (Mappers::cmdMapper->map(g_token->name))
2538 warn_doc_error(g_fileName,doctokenizerYYlineno,"{@link.. ended with @endlink command");
2542 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\link",
2543 qPrint(g_token->name));
2548 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2549 qPrint(g_token->name));
2552 if (g_token->name!="see" || !isXmlLink)
2554 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected xml/html command %s found",
2555 qPrint(g_token->name));
2560 if (isJavaLink) // special case to detect closing }
2562 QCString w = g_token->name;
2568 else if ((p=w.find('}'))!=-1)
2571 m_children.append(new DocWord(this,w.left(p)));
2572 if ((uint)p<l-1) // something left after the } (for instance a .)
2574 result=w.right(l-p-1);
2579 m_children.append(new DocWord(this,g_token->name));
2582 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2590 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
2595 if (m_children.isEmpty()) // no link text
2597 m_children.append(new DocWord(this,m_refText));
2600 handlePendingStyleCommands(this,m_children);
2601 DBG(("DocLink::parse() end\n"));
2602 DocNode *n=g_nodeStack.pop();
2608 //---------------------------------------------------------------------------
2610 DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &context) :
2611 m_name(name), m_relPath(g_relPath), m_context(context)
2616 void DocDotFile::parse()
2618 g_nodeStack.push(this);
2619 DBG(("DocDotFile::parse() start\n"));
2621 doctokenizerYYsetStateTitle();
2623 while ((tok=doctokenizerYYlex()))
2625 if (!defaultHandleToken(this,tok,m_children))
2630 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\dotfile",
2631 qPrint(g_token->name));
2634 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2635 qPrint(g_token->name));
2638 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2644 tok=doctokenizerYYlex();
2645 while (tok==TK_WORD) // there are values following the title
2647 if (g_token->name=="width")
2649 m_width=g_token->chars;
2651 else if (g_token->name=="height")
2653 m_height=g_token->chars;
2657 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2658 qPrint(g_token->name));
2660 tok=doctokenizerYYlex();
2663 doctokenizerYYsetStatePara();
2664 handlePendingStyleCommands(this,m_children);
2667 FileDef *fd = findFileDef(Doxygen::dotFileNameDict,m_name,ambig);
2668 if (fd==0 && m_name.right(4)!=".dot") // try with .dot extension as well
2670 fd = findFileDef(Doxygen::dotFileNameDict,m_name+".dot",ambig);
2674 m_file = fd->absFilePath();
2678 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file name %s is ambiguous.\n"
2679 "Possible candidates:\n%s",qPrint(m_name),
2680 qPrint(showFileDefMatches(Doxygen::exampleNameDict,m_name))
2685 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found "
2686 "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name));
2689 DBG(("DocDotFile::parse() end\n"));
2690 DocNode *n=g_nodeStack.pop();
2694 DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) :
2695 m_name(name), m_relPath(g_relPath), m_context(context)
2700 void DocMscFile::parse()
2702 g_nodeStack.push(this);
2703 DBG(("DocMscFile::parse() start\n"));
2705 doctokenizerYYsetStateTitle();
2707 while ((tok=doctokenizerYYlex()))
2709 if (!defaultHandleToken(this,tok,m_children))
2714 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\mscfile",
2715 qPrint(g_token->name));
2718 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2719 qPrint(g_token->name));
2722 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2728 tok=doctokenizerYYlex();
2729 while (tok==TK_WORD) // there are values following the title
2731 if (g_token->name=="width")
2733 m_width=g_token->chars;
2735 else if (g_token->name=="height")
2737 m_height=g_token->chars;
2741 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2742 qPrint(g_token->name));
2744 tok=doctokenizerYYlex();
2747 doctokenizerYYsetStatePara();
2748 handlePendingStyleCommands(this,m_children);
2751 FileDef *fd = findFileDef(Doxygen::mscFileNameDict,m_name,ambig);
2752 if (fd==0 && m_name.right(4)!=".msc") // try with .msc extension as well
2754 fd = findFileDef(Doxygen::mscFileNameDict,m_name+".msc",ambig);
2758 m_file = fd->absFilePath();
2762 warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file name %s is ambiguous.\n"
2763 "Possible candidates:\n%s",qPrint(m_name),
2764 qPrint(showFileDefMatches(Doxygen::exampleNameDict,m_name))
2769 warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found "
2770 "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name));
2773 DBG(("DocMscFile::parse() end\n"));
2774 DocNode *n=g_nodeStack.pop();
2778 //---------------------------------------------------------------------------
2780 DocDiaFile::DocDiaFile(DocNode *parent,const QCString &name,const QCString &context) :
2781 m_name(name), m_relPath(g_relPath), m_context(context)
2786 void DocDiaFile::parse()
2788 g_nodeStack.push(this);
2789 DBG(("DocDiaFile::parse() start\n"));
2791 doctokenizerYYsetStateTitle();
2793 while ((tok=doctokenizerYYlex()))
2795 if (!defaultHandleToken(this,tok,m_children))
2800 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\diafile",
2801 qPrint(g_token->name));
2804 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2805 qPrint(g_token->name));
2808 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2814 tok=doctokenizerYYlex();
2815 while (tok==TK_WORD) // there are values following the title
2817 if (g_token->name=="width")
2819 m_width=g_token->chars;
2821 else if (g_token->name=="height")
2823 m_height=g_token->chars;
2827 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2828 qPrint(g_token->name));
2830 tok=doctokenizerYYlex();
2833 doctokenizerYYsetStatePara();
2834 handlePendingStyleCommands(this,m_children);
2837 FileDef *fd = findFileDef(Doxygen::diaFileNameDict,m_name,ambig);
2838 if (fd==0 && m_name.right(4)!=".dia") // try with .dia extension as well
2840 fd = findFileDef(Doxygen::diaFileNameDict,m_name+".dia",ambig);
2844 m_file = fd->absFilePath();
2848 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file name %s is ambiguous.\n"
2849 "Possible candidates:\n%s",qPrint(m_name),
2850 qPrint(showFileDefMatches(Doxygen::exampleNameDict,m_name))
2855 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found "
2856 "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name));
2859 DBG(("DocDiaFile::parse() end\n"));
2860 DocNode *n=g_nodeStack.pop();
2864 //---------------------------------------------------------------------------
2866 DocVhdlFlow::DocVhdlFlow(DocNode *parent)
2871 void DocVhdlFlow::parse()
2873 g_nodeStack.push(this);
2874 DBG(("DocVhdlFlow::parse() start\n"));
2876 doctokenizerYYsetStateTitle();
2878 while ((tok=doctokenizerYYlex()))
2880 if (!defaultHandleToken(this,tok,m_children))
2885 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\mscfile",
2886 qPrint(g_token->name));
2889 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2890 qPrint(g_token->name));
2893 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2899 tok=doctokenizerYYlex();
2901 doctokenizerYYsetStatePara();
2902 handlePendingStyleCommands(this,m_children);
2904 DBG(("DocVhdlFlow::parse() end\n"));
2905 DocNode *n=g_nodeStack.pop();
2908 VhdlDocGen::createFlowChart(g_memberDef);
2912 //---------------------------------------------------------------------------
2914 DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString &name,
2915 Type t,const QCString &url) :
2916 m_attribs(attribs), m_name(name),
2917 m_type(t), m_relPath(g_relPath),
2923 void DocImage::parse()
2925 g_nodeStack.push(this);
2926 DBG(("DocImage::parse() start\n"));
2929 doctokenizerYYsetStateTitle();
2931 while ((tok=doctokenizerYYlex()))
2933 if (tok==TK_WORD && (g_token->name=="width=" || g_token->name=="height="))
2935 // special case: no title, but we do have a size indicator
2936 doctokenizerYYsetStateTitleAttrValue();
2938 g_token->name=g_token->name.left(g_token->name.length()-1);
2941 if (!defaultHandleToken(this,tok,m_children))
2946 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\image",
2947 qPrint(g_token->name));
2950 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2951 qPrint(g_token->name));
2954 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2960 // parse size attributes
2961 tok=doctokenizerYYlex();
2962 while (tok==TK_WORD) // there are values following the title
2964 if (g_token->name=="width")
2966 m_width=g_token->chars;
2968 else if (g_token->name=="height")
2970 m_height=g_token->chars;
2974 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2975 qPrint(g_token->name));
2977 tok=doctokenizerYYlex();
2979 doctokenizerYYsetStatePara();
2981 handlePendingStyleCommands(this,m_children);
2982 DBG(("DocImage::parse() end\n"));
2983 DocNode *n=g_nodeStack.pop();
2988 //---------------------------------------------------------------------------
2990 int DocHtmlHeader::parse()
2992 int retval=RetVal_OK;
2993 g_nodeStack.push(this);
2994 DBG(("DocHtmlHeader::parse() start\n"));
2997 while ((tok=doctokenizerYYlex()))
2999 if (!defaultHandleToken(this,tok,m_children))
3004 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <h%d> tag",
3005 qPrint(g_token->name),m_level);
3009 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3010 if (tagId==HTML_H1 && g_token->endTag) // found </h1> tag
3014 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h1>",
3019 else if (tagId==HTML_H2 && g_token->endTag) // found </h2> tag
3023 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h2>",
3028 else if (tagId==HTML_H3 && g_token->endTag) // found </h3> tag
3032 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h3>",
3037 else if (tagId==HTML_H4 && g_token->endTag) // found </h4> tag
3041 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h4>",
3046 else if (tagId==HTML_H5 && g_token->endTag) // found </h5> tag
3050 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h5>",
3055 else if (tagId==HTML_H6 && g_token->endTag) // found </h6> tag
3059 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h6>",
3064 else if (tagId==HTML_A)
3066 if (!g_token->endTag)
3068 handleAHref(this,m_children,g_token->attribs);
3071 else if (tagId==HTML_BR)
3073 DocLineBreak *lb = new DocLineBreak(this);
3074 m_children.append(lb);
3078 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <h%d> context",
3079 g_token->endTag?"/":"",qPrint(g_token->name),m_level);
3085 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3086 qPrint(g_token->name));
3089 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3097 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3098 " <h%d> tag\n",m_level);
3101 handlePendingStyleCommands(this,m_children);
3102 DBG(("DocHtmlHeader::parse() end\n"));
3103 DocNode *n=g_nodeStack.pop();
3108 //---------------------------------------------------------------------------
3110 int DocHRef::parse()
3112 int retval=RetVal_OK;
3113 g_nodeStack.push(this);
3114 DBG(("DocHRef::parse() start\n"));
3117 while ((tok=doctokenizerYYlex()))
3119 if (!defaultHandleToken(this,tok,m_children))
3124 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <a>..</a> block",
3125 qPrint(g_token->name));
3128 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3129 qPrint(g_token->name));
3134 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3135 if (tagId==HTML_A && g_token->endTag) // found </a> tag
3141 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <a href=...> context",
3142 g_token->endTag?"/":"",qPrint(g_token->name),doctokenizerYYlineno);
3147 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3148 tokToString(tok),doctokenizerYYlineno);
3155 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3156 " <a href=...> tag",doctokenizerYYlineno);
3159 handlePendingStyleCommands(this,m_children);
3160 DBG(("DocHRef::parse() end\n"));
3161 DocNode *n=g_nodeStack.pop();
3166 //---------------------------------------------------------------------------
3168 int DocInternal::parse(int level)
3170 int retval=RetVal_OK;
3171 g_nodeStack.push(this);
3172 DBG(("DocInternal::parse() start\n"));
3174 // first parse any number of paragraphs
3179 DocPara *par = new DocPara(this);
3180 if (isFirst) { par->markFirst(); isFirst=FALSE; }
3181 retval=par->parse();
3182 if (!par->isEmpty())
3184 m_children.append(par);
3191 if (retval==TK_LISTITEM)
3193 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found",doctokenizerYYlineno);
3195 } while (retval!=0 &&
3196 retval!=RetVal_Section &&
3197 retval!=RetVal_Subsection &&
3198 retval!=RetVal_Subsubsection &&
3199 retval!=RetVal_Paragraph &&
3200 retval!=RetVal_EndInternal
3202 if (lastPar) lastPar->markLast();
3204 // then parse any number of level-n sections
3205 while ((level==1 && retval==RetVal_Section) ||
3206 (level==2 && retval==RetVal_Subsection) ||
3207 (level==3 && retval==RetVal_Subsubsection) ||
3208 (level==4 && retval==RetVal_Paragraph)
3211 DocSection *s=new DocSection(this,
3212 QMIN(level+Doxygen::subpageNestingLevel,5),g_token->sectionId);
3213 m_children.append(s);
3214 retval = s->parse();
3217 if (retval==RetVal_Internal)
3219 warn_doc_error(g_fileName,doctokenizerYYlineno,"\\internal command found inside internal section");
3222 DBG(("DocInternal::parse() end: retval=%x\n",retval));
3223 DocNode *n=g_nodeStack.pop();
3228 //---------------------------------------------------------------------------
3230 int DocIndexEntry::parse()
3232 int retval=RetVal_OK;
3233 g_nodeStack.push(this);
3234 DBG(("DocIndexEntry::parse() start\n"));
3235 int tok=doctokenizerYYlex();
3236 if (tok!=TK_WHITESPACE)
3238 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\addindex command");
3241 doctokenizerYYsetStateTitle();
3243 while ((tok=doctokenizerYYlex()))
3252 m_entry+=g_token->name;
3256 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name);
3259 case DocSymbol::Sym_BSlash: m_entry+='\\'; break;
3260 case DocSymbol::Sym_At: m_entry+='@'; break;
3261 case DocSymbol::Sym_Less: m_entry+='<'; break;
3262 case DocSymbol::Sym_Greater: m_entry+='>'; break;
3263 case DocSymbol::Sym_Amp: m_entry+='&'; break;
3264 case DocSymbol::Sym_Dollar: m_entry+='$'; break;
3265 case DocSymbol::Sym_Hash: m_entry+='#'; break;
3266 case DocSymbol::Sym_Percent: m_entry+='%'; break;
3267 case DocSymbol::Sym_apos: m_entry+='\''; break;
3268 case DocSymbol::Sym_Quot: m_entry+='"'; break;
3269 case DocSymbol::Sym_lsquo: m_entry+='`'; break;
3270 case DocSymbol::Sym_rsquo: m_entry+='\''; break;
3271 case DocSymbol::Sym_ldquo: m_entry+="``"; break;
3272 case DocSymbol::Sym_rdquo: m_entry+="''"; break;
3273 case DocSymbol::Sym_ndash: m_entry+="--"; break;
3274 case DocSymbol::Sym_mdash: m_entry+="---"; break;
3276 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected symbol found as argument of \\addindex");
3282 switch (Mappers::cmdMapper->map(g_token->name))
3284 case CMD_BSLASH: m_entry+='\\'; break;
3285 case CMD_AT: m_entry+='@'; break;
3286 case CMD_LESS: m_entry+='<'; break;
3287 case CMD_GREATER: m_entry+='>'; break;
3288 case CMD_AMP: m_entry+='&'; break;
3289 case CMD_DOLLAR: m_entry+='$'; break;
3290 case CMD_HASH: m_entry+='#'; break;
3291 case CMD_DCOLON: m_entry+="::"; break;
3292 case CMD_PERCENT: m_entry+='%'; break;
3293 case CMD_NDASH: m_entry+="--"; break;
3294 case CMD_MDASH: m_entry+="---"; break;
3295 case CMD_QUOTE: m_entry+='"'; break;
3297 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command %s found as argument of \\addindex",
3298 qPrint(g_token->name));
3303 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3308 if (tok!=0) retval=tok;
3309 doctokenizerYYsetStatePara();
3310 m_entry = m_entry.stripWhiteSpace();
3312 DBG(("DocIndexEntry::parse() end retval=%x\n",retval));
3313 DocNode *n=g_nodeStack.pop();
3318 //---------------------------------------------------------------------------
3320 int DocHtmlCaption::parse()
3323 g_nodeStack.push(this);
3324 DBG(("DocHtmlCaption::parse() start\n"));
3326 while ((tok=doctokenizerYYlex()))
3328 if (!defaultHandleToken(this,tok,m_children))
3333 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <caption> tag",
3334 qPrint(g_token->name));
3337 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3338 qPrint(g_token->name));
3342 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3343 if (tagId==HTML_CAPTION && g_token->endTag) // found </caption> tag
3350 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <caption> context",
3351 g_token->endTag?"/":"",qPrint(g_token->name));
3356 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3364 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3365 " <caption> tag",doctokenizerYYlineno);
3368 handlePendingStyleCommands(this,m_children);
3369 DBG(("DocHtmlCaption::parse() end\n"));
3370 DocNode *n=g_nodeStack.pop();
3375 //---------------------------------------------------------------------------
3377 int DocHtmlCell::parse()
3379 int retval=RetVal_OK;
3380 g_nodeStack.push(this);
3381 DBG(("DocHtmlCell::parse() start\n"));
3383 // parse one or more paragraphs
3388 par = new DocPara(this);
3389 if (isFirst) { par->markFirst(); isFirst=FALSE; }
3390 m_children.append(par);
3391 retval=par->parse();
3392 if (retval==TK_HTMLTAG)
3394 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3395 if (tagId==HTML_TD && g_token->endTag) // found </dt> tag
3397 retval=TK_NEWPARA; // ignore the tag
3399 else if (tagId==HTML_TH && g_token->endTag) // found </th> tag
3401 retval=TK_NEWPARA; // ignore the tag
3405 while (retval==TK_NEWPARA);
3406 if (par) par->markLast();
3408 DBG(("DocHtmlCell::parse() end\n"));
3409 DocNode *n=g_nodeStack.pop();
3414 int DocHtmlCell::parseXml()
3416 int retval=RetVal_OK;
3417 g_nodeStack.push(this);
3418 DBG(("DocHtmlCell::parseXml() start\n"));
3420 // parse one or more paragraphs
3425 par = new DocPara(this);
3426 if (isFirst) { par->markFirst(); isFirst=FALSE; }
3427 m_children.append(par);
3428 retval=par->parse();
3429 if (retval==TK_HTMLTAG)
3431 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3432 if (tagId==XML_ITEM && g_token->endTag) // found </item> tag
3434 retval=TK_NEWPARA; // ignore the tag
3436 else if (tagId==XML_DESCRIPTION && g_token->endTag) // found </description> tag
3438 retval=TK_NEWPARA; // ignore the tag
3442 while (retval==TK_NEWPARA);
3443 if (par) par->markLast();
3445 DBG(("DocHtmlCell::parseXml() end\n"));
3446 DocNode *n=g_nodeStack.pop();
3451 int DocHtmlCell::rowSpan() const
3454 HtmlAttribList attrs = attribs();
3456 for (i=0; i<attrs.count(); ++i)
3458 if (attrs.at(i)->name.lower()=="rowspan")
3460 retval = attrs.at(i)->value.toInt();
3467 int DocHtmlCell::colSpan() const
3470 HtmlAttribList attrs = attribs();
3472 for (i=0; i<attrs.count(); ++i)
3474 if (attrs.at(i)->name.lower()=="colspan")
3476 retval = QMAX(1,attrs.at(i)->value.toInt());
3483 DocHtmlCell::Alignment DocHtmlCell::alignment() const
3485 HtmlAttribList attrs = attribs();
3487 for (i=0; i<attrs.count(); ++i)
3489 if (attrs.at(i)->name.lower()=="align")
3491 if (attrs.at(i)->value.lower()=="center")
3493 else if (attrs.at(i)->value.lower()=="right")
3502 //---------------------------------------------------------------------------
3504 int DocHtmlRow::parse()
3506 int retval=RetVal_OK;
3507 g_nodeStack.push(this);
3508 DBG(("DocHtmlRow::parse() start\n"));
3510 bool isHeading=FALSE;
3512 DocHtmlCell *cell=0;
3515 int tok=doctokenizerYYlex();
3517 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3518 // should find a html tag now
3519 if (tok==TK_HTMLTAG)
3521 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3522 if (tagId==HTML_TD && !g_token->endTag) // found <td> tag
3525 else if (tagId==HTML_TH && !g_token->endTag) // found <th> tag
3529 else // found some other tag
3531 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but "
3532 "found <%s> instead!",qPrint(g_token->name));
3533 doctokenizerYYpushBackHtmlTag(g_token->name);
3537 else if (tok==0) // premature end of comment
3539 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
3540 " for a html description title");
3543 else // token other than html token
3545 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!",
3550 // parse one or more cells
3553 cell=new DocHtmlCell(this,g_token->attribs,isHeading);
3554 cell->markFirst(isFirst);
3556 m_children.append(cell);
3557 retval=cell->parse();
3558 isHeading = retval==RetVal_TableHCell;
3560 while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
3561 if (cell) cell->markLast(TRUE);
3564 DBG(("DocHtmlRow::parse() end\n"));
3565 DocNode *n=g_nodeStack.pop();
3570 int DocHtmlRow::parseXml(bool isHeading)
3572 int retval=RetVal_OK;
3573 g_nodeStack.push(this);
3574 DBG(("DocHtmlRow::parseXml() start\n"));
3577 DocHtmlCell *cell=0;
3580 int tok=doctokenizerYYlex();
3582 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3583 // should find a html tag now
3584 if (tok==TK_HTMLTAG)
3586 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3587 if (tagId==XML_TERM && !g_token->endTag) // found <term> tag
3590 else if (tagId==XML_DESCRIPTION && !g_token->endTag) // found <description> tag
3593 else // found some other tag
3595 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <term> or <description> tag but "
3596 "found <%s> instead!",qPrint(g_token->name));
3597 doctokenizerYYpushBackHtmlTag(g_token->name);
3601 else if (tok==0) // premature end of comment
3603 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
3604 " for a html description title");
3607 else // token other than html token
3609 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!",
3616 cell=new DocHtmlCell(this,g_token->attribs,isHeading);
3617 cell->markFirst(isFirst);
3619 m_children.append(cell);
3620 retval=cell->parseXml();
3622 while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
3623 if (cell) cell->markLast(TRUE);
3626 DBG(("DocHtmlRow::parseXml() end\n"));
3627 DocNode *n=g_nodeStack.pop();
3632 //---------------------------------------------------------------------------
3634 int DocHtmlTable::parse()
3636 int retval=RetVal_OK;
3637 g_nodeStack.push(this);
3638 DBG(("DocHtmlTable::parse() start\n"));
3642 int tok=doctokenizerYYlex();
3644 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3645 // should find a html tag now
3646 if (tok==TK_HTMLTAG)
3648 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3649 if (tagId==HTML_TR && !g_token->endTag) // found <tr> tag
3651 // no caption, just rows
3652 retval=RetVal_TableRow;
3654 else if (tagId==HTML_CAPTION && !g_token->endTag) // found <caption> tag
3658 warn_doc_error(g_fileName,doctokenizerYYlineno,"table already has a caption, found another one");
3662 m_caption = new DocHtmlCaption(this,g_token->attribs);
3663 retval=m_caption->parse();
3665 if (retval==RetVal_OK) // caption was parsed ok
3671 else // found wrong token
3673 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> or <caption> tag but "
3674 "found <%s%s> instead!", g_token->endTag ? "/" : "", qPrint(g_token->name));
3677 else if (tok==0) // premature end of comment
3679 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
3680 " for a <tr> or <caption> tag");
3682 else // token other than html token
3684 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> tag but found %s token instead!",
3688 // parse one or more rows
3689 while (retval==RetVal_TableRow)
3691 DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs);
3692 m_children.append(tr);
3698 DBG(("DocHtmlTable::parse() end\n"));
3699 DocNode *n=g_nodeStack.pop();
3701 return retval==RetVal_EndTable ? RetVal_OK : retval;
3704 int DocHtmlTable::parseXml()
3706 int retval=RetVal_OK;
3707 g_nodeStack.push(this);
3708 DBG(("DocHtmlTable::parseXml() start\n"));
3711 int tok=doctokenizerYYlex();
3713 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3714 // should find a html tag now
3716 bool isHeader=FALSE;
3717 if (tok==TK_HTMLTAG)
3719 tagId=Mappers::htmlTagMapper->map(g_token->name);
3720 if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag
3722 retval=RetVal_TableRow;
3724 if (tagId==XML_LISTHEADER && !g_token->endTag) // found <listheader> tag
3726 retval=RetVal_TableRow;
3731 // parse one or more rows
3732 while (retval==RetVal_TableRow)
3734 DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs);
3735 m_children.append(tr);
3736 retval=tr->parseXml(isHeader);
3742 DBG(("DocHtmlTable::parseXml() end\n"));
3743 DocNode *n=g_nodeStack.pop();
3745 return retval==RetVal_EndTable ? RetVal_OK : retval;
3748 /** Helper class to compute the grid for an HTML style table */
3749 struct ActiveRowSpan
3751 ActiveRowSpan(int rows,int col) : rowsLeft(rows), column(col) {}
3756 /** List of ActiveRowSpan classes. */
3757 typedef QList<ActiveRowSpan> RowSpanList;
3759 /** determines the location of all cells in a grid, resolving row and
3760 column spans. For each the total number of visible cells is computed,
3761 and the total number of visible columns over all rows is stored.
3763 void DocHtmlTable::computeTableGrid()
3765 //printf("computeTableGrid()\n");
3766 RowSpanList rowSpans;
3767 rowSpans.setAutoDelete(TRUE);
3770 QListIterator<DocNode> li(children());
3772 for (li.toFirst();(rowNode=li.current());++li)
3776 if (rowNode->kind()==DocNode::Kind_HtmlRow)
3779 DocHtmlRow *row = (DocHtmlRow*)rowNode;
3780 QListIterator<DocNode> rli(row->children());
3782 for (rli.toFirst();(cellNode=rli.current());++rli)
3784 if (cellNode->kind()==DocNode::Kind_HtmlCell)
3786 DocHtmlCell *cell = (DocHtmlCell*)cellNode;
3787 int rs = cell->rowSpan();
3788 int cs = cell->colSpan();
3790 for (i=0;i<rowSpans.count();i++)
3792 if (rowSpans.at(i)->rowsLeft>0 &&
3793 rowSpans.at(i)->column==colIdx)
3795 colIdx=rowSpans.at(i)->column+1;
3799 if (rs>0) rowSpans.append(new ActiveRowSpan(rs,colIdx));
3800 //printf("found cell at (%d,%d)\n",rowIdx,colIdx);
3801 cell->setRowIndex(rowIdx);
3802 cell->setColumnIndex(colIdx);
3807 for (i=0;i<rowSpans.count();i++)
3809 if (rowSpans.at(i)->rowsLeft>0) rowSpans.at(i)->rowsLeft--;
3811 row->setVisibleCells(cells);
3812 row->setRowIndex(rowIdx);
3815 if (colIdx-1>maxCols) maxCols=colIdx-1;
3817 m_numCols = maxCols;
3820 void DocHtmlTable::accept(DocVisitor *v)
3823 // for HTML output we put the caption first
3824 if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v);
3825 QListIterator<DocNode> cli(m_children);
3827 for (cli.toFirst();(n=cli.current());++cli) n->accept(v);
3828 // for other output formats we put the caption last
3829 if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v);
3833 //---------------------------------------------------------------------------
3835 int DocHtmlDescTitle::parse()
3838 g_nodeStack.push(this);
3839 DBG(("DocHtmlDescTitle::parse() start\n"));
3842 while ((tok=doctokenizerYYlex()))
3844 if (!defaultHandleToken(this,tok,m_children))
3850 QCString cmdName=g_token->name;
3851 bool isJavaLink=FALSE;
3852 switch (Mappers::cmdMapper->map(cmdName))
3856 int tok=doctokenizerYYlex();
3857 if (tok!=TK_WHITESPACE)
3859 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
3860 qPrint(g_token->name));
3864 doctokenizerYYsetStateRef();
3865 tok=doctokenizerYYlex(); // get the reference id
3868 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
3869 tokToString(tok),qPrint(cmdName));
3873 DocRef *ref = new DocRef(this,g_token->name,g_context);
3874 m_children.append(ref);
3877 doctokenizerYYsetStatePara();
3886 int tok=doctokenizerYYlex();
3887 if (tok!=TK_WHITESPACE)
3889 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
3894 doctokenizerYYsetStateLink();
3895 tok=doctokenizerYYlex();
3898 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
3899 tokToString(tok),qPrint(cmdName));
3903 doctokenizerYYsetStatePara();
3904 DocLink *lnk = new DocLink(this,g_token->name);
3905 m_children.append(lnk);
3906 QCString leftOver = lnk->parse(isJavaLink);
3907 if (!leftOver.isEmpty())
3909 m_children.append(new DocWord(this,leftOver));
3917 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <dt> tag",
3918 qPrint(g_token->name));
3923 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3924 qPrint(g_token->name));
3928 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3929 if (tagId==HTML_DD && !g_token->endTag) // found <dd> tag
3931 retval = RetVal_DescData;
3934 else if (tagId==HTML_DT && g_token->endTag)
3936 // ignore </dt> tag.
3938 else if (tagId==HTML_DT)
3940 // missing <dt> tag.
3941 retval = RetVal_DescTitle;
3944 else if (tagId==HTML_DL && g_token->endTag)
3946 retval=RetVal_EndDesc;
3949 else if (tagId==HTML_A)
3951 if (!g_token->endTag)
3953 handleAHref(this,m_children,g_token->attribs);
3958 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <dt> context",
3959 g_token->endTag?"/":"",qPrint(g_token->name));
3964 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3972 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3976 handlePendingStyleCommands(this,m_children);
3977 DBG(("DocHtmlDescTitle::parse() end\n"));
3978 DocNode *n=g_nodeStack.pop();
3983 //---------------------------------------------------------------------------
3985 int DocHtmlDescData::parse()
3987 m_attribs = g_token->attribs;
3989 g_nodeStack.push(this);
3990 DBG(("DocHtmlDescData::parse() start\n"));
3996 par = new DocPara(this);
3997 if (isFirst) { par->markFirst(); isFirst=FALSE; }
3998 m_children.append(par);
3999 retval=par->parse();
4001 while (retval==TK_NEWPARA);
4002 if (par) par->markLast();
4004 DBG(("DocHtmlDescData::parse() end\n"));
4005 DocNode *n=g_nodeStack.pop();
4010 //---------------------------------------------------------------------------
4012 int DocHtmlDescList::parse()
4014 int retval=RetVal_OK;
4015 g_nodeStack.push(this);
4016 DBG(("DocHtmlDescList::parse() start\n"));
4019 int tok=doctokenizerYYlex();
4021 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
4022 // should find a html tag now
4023 if (tok==TK_HTMLTAG)
4025 int tagId=Mappers::htmlTagMapper->map(g_token->name);
4026 if (tagId==HTML_DT && !g_token->endTag) // found <dt> tag
4030 else // found some other tag
4032 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but "
4033 "found <%s> instead!",qPrint(g_token->name));
4034 doctokenizerYYpushBackHtmlTag(g_token->name);
4038 else if (tok==0) // premature end of comment
4040 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
4041 " for a html description title");
4044 else // token other than html token
4046 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but found %s token instead!",
4053 DocHtmlDescTitle *dt=new DocHtmlDescTitle(this,g_token->attribs);
4054 m_children.append(dt);
4055 DocHtmlDescData *dd=new DocHtmlDescData(this);
4056 m_children.append(dd);
4058 if (retval==RetVal_DescData)
4062 else if (retval!=RetVal_DescTitle)
4067 } while (retval==RetVal_DescTitle);
4071 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <dl> block");
4076 DocNode *n=g_nodeStack.pop();
4078 DBG(("DocHtmlDescList::parse() end\n"));
4079 return retval==RetVal_EndDesc ? RetVal_OK : retval;
4082 //---------------------------------------------------------------------------
4084 int DocHtmlListItem::parse()
4086 DBG(("DocHtmlListItem::parse() start\n"));
4088 g_nodeStack.push(this);
4090 // parse one or more paragraphs
4095 par = new DocPara(this);
4096 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4097 m_children.append(par);
4098 retval=par->parse();
4100 while (retval==TK_NEWPARA);
4101 if (par) par->markLast();
4103 DocNode *n=g_nodeStack.pop();
4105 DBG(("DocHtmlListItem::parse() end retval=%x\n",retval));
4109 int DocHtmlListItem::parseXml()
4111 DBG(("DocHtmlListItem::parseXml() start\n"));
4113 g_nodeStack.push(this);
4115 // parse one or more paragraphs
4120 par = new DocPara(this);
4121 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4122 m_children.append(par);
4123 retval=par->parse();
4124 if (retval==0) break;
4126 //printf("new item: retval=%x g_token->name=%s g_token->endTag=%d\n",
4127 // retval,qPrint(g_token->name),g_token->endTag);
4128 if (retval==RetVal_ListItem)
4133 while (retval!=RetVal_CloseXml);
4135 if (par) par->markLast();
4137 DocNode *n=g_nodeStack.pop();
4139 DBG(("DocHtmlListItem::parseXml() end retval=%x\n",retval));
4143 //---------------------------------------------------------------------------
4145 int DocHtmlList::parse()
4147 DBG(("DocHtmlList::parse() start\n"));
4148 int retval=RetVal_OK;
4150 g_nodeStack.push(this);
4153 int tok=doctokenizerYYlex();
4154 // skip whitespace and paragraph breaks
4155 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
4156 // should find a html tag now
4157 if (tok==TK_HTMLTAG)
4159 int tagId=Mappers::htmlTagMapper->map(g_token->name);
4160 if (tagId==HTML_LI && !g_token->endTag) // found <li> tag
4162 // ok, we can go on.
4164 else if (((m_type==Unordered && tagId==HTML_UL) ||
4165 (m_type==Ordered && tagId==HTML_OL)
4166 ) && g_token->endTag
4167 ) // found empty list
4169 // add dummy item to obtain valid HTML
4170 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4171 warn_doc_error(g_fileName,doctokenizerYYlineno,"empty list!");
4172 retval = RetVal_EndList;
4175 else // found some other tag
4177 // add dummy item to obtain valid HTML
4178 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4179 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but "
4180 "found <%s%s> instead!",g_token->endTag?"/":"",qPrint(g_token->name));
4181 doctokenizerYYpushBackHtmlTag(g_token->name);
4185 else if (tok==0) // premature end of comment
4187 // add dummy item to obtain valid HTML
4188 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4189 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
4190 " for a html list item");
4193 else // token other than html token
4195 // add dummy item to obtain valid HTML
4196 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4197 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but found %s token instead!",
4204 DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++);
4205 m_children.append(li);
4207 } while (retval==RetVal_ListItem);
4211 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <%cl> block",
4212 m_type==Unordered ? 'u' : 'o');
4216 DBG(("DocHtmlList::parse() end retval=%x\n",retval));
4217 DocNode *n=g_nodeStack.pop();
4219 return retval==RetVal_EndList ? RetVal_OK : retval;
4222 int DocHtmlList::parseXml()
4224 DBG(("DocHtmlList::parseXml() start\n"));
4225 int retval=RetVal_OK;
4227 g_nodeStack.push(this);
4230 int tok=doctokenizerYYlex();
4231 // skip whitespace and paragraph breaks
4232 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
4233 // should find a html tag now
4234 if (tok==TK_HTMLTAG)
4236 int tagId=Mappers::htmlTagMapper->map(g_token->name);
4237 //printf("g_token->name=%s g_token->endTag=%d\n",qPrint(g_token->name),g_token->endTag);
4238 if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag
4240 // ok, we can go on.
4242 else // found some other tag
4244 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but "
4245 "found <%s> instead!",qPrint(g_token->name));
4246 doctokenizerYYpushBackHtmlTag(g_token->name);
4250 else if (tok==0) // premature end of comment
4252 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
4253 " for a html list item");
4256 else // token other than html token
4258 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but found %s token instead!",
4265 DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++);
4266 m_children.append(li);
4267 retval=li->parseXml();
4268 if (retval==0) break;
4269 //printf("retval=%x g_token->name=%s\n",retval,qPrint(g_token->name));
4270 } while (retval==RetVal_ListItem);
4274 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <list type=\"%s\"> block",
4275 m_type==Unordered ? "bullet" : "number");
4279 DBG(("DocHtmlList::parseXml() end retval=%x\n",retval));
4280 DocNode *n=g_nodeStack.pop();
4282 return retval==RetVal_EndList ||
4283 (retval==RetVal_CloseXml || g_token->name=="list") ?
4287 //--------------------------------------------------------------------------
4289 int DocHtmlBlockQuote::parse()
4291 DBG(("DocHtmlBlockQuote::parse() start\n"));
4293 g_nodeStack.push(this);
4295 // parse one or more paragraphs
4300 par = new DocPara(this);
4301 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4302 m_children.append(par);
4303 retval=par->parse();
4305 while (retval==TK_NEWPARA);
4306 if (par) par->markLast();
4308 DocNode *n=g_nodeStack.pop();
4310 DBG(("DocHtmlBlockQuote::parse() end retval=%x\n",retval));
4311 return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
4314 //---------------------------------------------------------------------------
4316 int DocParBlock::parse()
4318 DBG(("DocParBlock::parse() start\n"));
4320 g_nodeStack.push(this);
4322 // parse one or more paragraphs
4327 par = new DocPara(this);
4328 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4329 m_children.append(par);
4330 retval=par->parse();
4332 while (retval==TK_NEWPARA);
4333 if (par) par->markLast();
4335 DocNode *n=g_nodeStack.pop();
4337 DBG(("DocParBlock::parse() end retval=%x\n",retval));
4338 return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
4341 //---------------------------------------------------------------------------
4343 int DocSimpleListItem::parse()
4345 g_nodeStack.push(this);
4346 int rv=m_paragraph->parse();
4347 m_paragraph->markFirst();
4348 m_paragraph->markLast();
4349 DocNode *n=g_nodeStack.pop();
4354 //--------------------------------------------------------------------------
4356 int DocSimpleList::parse()
4358 g_nodeStack.push(this);
4362 DocSimpleListItem *li=new DocSimpleListItem(this);
4363 m_children.append(li);
4365 } while (rv==RetVal_ListItem);
4366 DocNode *n=g_nodeStack.pop();
4368 return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4371 //--------------------------------------------------------------------------
4373 DocAutoListItem::DocAutoListItem(DocNode *parent,int indent,int num)
4374 : m_indent(indent), m_itemNum(num)
4379 int DocAutoListItem::parse()
4381 int retval = RetVal_OK;
4382 g_nodeStack.push(this);
4384 // first parse any number of paragraphs
4389 DocPara *par = new DocPara(this);
4390 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4391 retval=par->parse();
4392 if (!par->isEmpty())
4394 m_children.append(par);
4395 if (lastPar) lastPar->markLast(FALSE);
4402 // next paragraph should be more indented than the - marker to belong
4404 } while (retval==TK_NEWPARA && g_token->indent>m_indent);
4405 if (lastPar) lastPar->markLast();
4407 DocNode *n=g_nodeStack.pop();
4409 //printf("DocAutoListItem: retval=%d indent=%d\n",retval,g_token->indent);
4413 //--------------------------------------------------------------------------
4415 DocAutoList::DocAutoList(DocNode *parent,int indent,bool isEnumList,
4417 m_indent(indent), m_isEnumList(isEnumList),
4423 int DocAutoList::parse()
4425 int retval = RetVal_OK;
4427 g_nodeStack.push(this);
4428 doctokenizerYYstartAutoList();
4429 // first item or sub list => create new list
4432 if (g_token->id!=-1) // explicitly numbered list
4434 num=g_token->id; // override num with real number given
4436 DocAutoListItem *li = new DocAutoListItem(this,m_indent,num++);
4437 m_children.append(li);
4439 //printf("DocAutoList::parse(): retval=0x%x g_token->indent=%d m_indent=%d "
4440 // "m_isEnumList=%d g_token->isEnumList=%d g_token->name=%s\n",
4441 // retval,g_token->indent,m_indent,m_isEnumList,g_token->isEnumList,
4442 // g_token->name.data());
4443 //printf("num=%d g_token->id=%d\n",num,g_token->id);
4445 while (retval==TK_LISTITEM && // new list item
4446 m_indent==g_token->indent && // at same indent level
4447 m_isEnumList==g_token->isEnumList && // of the same kind
4448 (g_token->id==-1 || g_token->id>=num) // increasing number (or no number)
4451 doctokenizerYYendAutoList();
4452 DocNode *n=g_nodeStack.pop();
4457 //--------------------------------------------------------------------------
4459 void DocTitle::parse()
4461 DBG(("DocTitle::parse() start\n"));
4462 g_nodeStack.push(this);
4463 doctokenizerYYsetStateTitle();
4465 while ((tok=doctokenizerYYlex()))
4467 if (!defaultHandleToken(this,tok,m_children))
4472 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a title section",
4473 qPrint(g_token->name));
4476 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
4477 qPrint(g_token->name));
4480 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
4486 doctokenizerYYsetStatePara();
4487 handlePendingStyleCommands(this,m_children);
4488 DBG(("DocTitle::parse() end\n"));
4489 DocNode *n = g_nodeStack.pop();
4493 void DocTitle::parseFromString(const QCString &text)
4495 m_children.append(new DocWord(this,text));
4498 //--------------------------------------------------------------------------
4500 DocSimpleSect::DocSimpleSect(DocNode *parent,Type t) :
4507 DocSimpleSect::~DocSimpleSect()
4512 void DocSimpleSect::accept(DocVisitor *v)
4515 if (m_title) m_title->accept(v);
4516 QListIterator<DocNode> cli(m_children);
4518 for (cli.toFirst();(n=cli.current());++cli) n->accept(v);
4522 int DocSimpleSect::parse(bool userTitle,bool needsSeparator)
4524 DBG(("DocSimpleSect::parse() start\n"));
4525 g_nodeStack.push(this);
4527 // handle case for user defined title
4530 m_title = new DocTitle(this);
4534 // add new paragraph as child
4535 DocPara *par = new DocPara(this);
4536 if (m_children.isEmpty())
4542 ASSERT(m_children.getLast()->kind()==DocNode::Kind_Para);
4543 ((DocPara *)m_children.getLast())->markLast(FALSE);
4546 if (needsSeparator) m_children.append(new DocSimpleSectSep(this));
4547 m_children.append(par);
4549 // parse the contents of the paragraph
4550 int retval = par->parse();
4552 DBG(("DocSimpleSect::parse() end retval=%d\n",retval));
4553 DocNode *n=g_nodeStack.pop();
4555 return retval; // 0==EOF, TK_NEWPARA, TK_LISTITEM, TK_ENDLIST, RetVal_SimpleSec
4558 int DocSimpleSect::parseRcs()
4560 DBG(("DocSimpleSect::parseRcs() start\n"));
4561 g_nodeStack.push(this);
4563 m_title = new DocTitle(this);
4564 m_title->parseFromString(g_token->name);
4566 QCString text = g_token->text;
4567 docParserPushContext(); // this will create a new g_token
4568 internalValidatingParseDoc(this,m_children,text);
4569 docParserPopContext(); // this will restore the old g_token
4571 DBG(("DocSimpleSect::parseRcs()\n"));
4572 DocNode *n=g_nodeStack.pop();
4577 int DocSimpleSect::parseXml()
4579 DBG(("DocSimpleSect::parse() start\n"));
4580 g_nodeStack.push(this);
4582 int retval = RetVal_OK;
4585 // add new paragraph as child
4586 DocPara *par = new DocPara(this);
4587 if (m_children.isEmpty())
4593 ASSERT(m_children.getLast()->kind()==DocNode::Kind_Para);
4594 ((DocPara *)m_children.getLast())->markLast(FALSE);
4597 m_children.append(par);
4599 // parse the contents of the paragraph
4600 retval = par->parse();
4601 if (retval == 0) break;
4602 if (retval == RetVal_CloseXml)
4609 DBG(("DocSimpleSect::parseXml() end retval=%d\n",retval));
4610 DocNode *n=g_nodeStack.pop();
4615 void DocSimpleSect::appendLinkWord(const QCString &word)
4618 if (m_children.isEmpty() || m_children.getLast()->kind()!=DocNode::Kind_Para)
4620 p = new DocPara(this);
4621 m_children.append(p);
4625 p = (DocPara *)m_children.getLast();
4627 // Comma-seperate <seealso> links.
4628 p->injectToken(TK_WORD,",");
4629 p->injectToken(TK_WHITESPACE," ");
4633 p->injectToken(TK_LNKWORD,word);
4637 QCString DocSimpleSect::typeString() const
4641 case Unknown: break;
4642 case See: return "see";
4643 case Return: return "return";
4644 case Author: // fall through
4645 case Authors: return "author";
4646 case Version: return "version";
4647 case Since: return "since";
4648 case Date: return "date";
4649 case Note: return "note";
4650 case Warning: return "warning";
4651 case Pre: return "pre";
4652 case Post: return "post";
4653 case Copyright: return "copyright";
4654 case Invar: return "invariant";
4655 case Remark: return "remark";
4656 case Attention: return "attention";
4657 case User: return "user";
4658 case Rcs: return "rcs";
4663 //--------------------------------------------------------------------------
4665 int DocParamList::parse(const QCString &cmdName)
4667 int retval=RetVal_OK;
4668 DBG(("DocParamList::parse() start\n"));
4669 g_nodeStack.push(this);
4672 int tok=doctokenizerYYlex();
4673 if (tok!=TK_WHITESPACE)
4675 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
4678 doctokenizerYYsetStateParam();
4679 tok=doctokenizerYYlex();
4680 while (tok==TK_WORD) /* there is a parameter name */
4682 if (m_type==DocParamSect::Param)
4684 int typeSeparator = g_token->name.find('#'); // explicit type position
4685 if (typeSeparator!=-1)
4687 handleParameterType(this,m_paramTypes,g_token->name.left(typeSeparator));
4688 g_token->name = g_token->name.mid(typeSeparator+1);
4689 g_hasParamCommand=TRUE;
4690 checkArgumentName(g_token->name,TRUE);
4691 ((DocParamSect*)parent())->m_hasTypeSpecifier=TRUE;
4695 g_hasParamCommand=TRUE;
4696 checkArgumentName(g_token->name,TRUE);
4699 else if (m_type==DocParamSect::RetVal)
4701 g_hasReturnCommand=TRUE;
4702 checkArgumentName(g_token->name,FALSE);
4704 //m_params.append(g_token->name);
4705 handleLinkedWord(this,m_params);
4706 tok=doctokenizerYYlex();
4708 doctokenizerYYsetStatePara();
4709 if (tok==0) /* premature end of comment block */
4711 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
4712 "argument of command %s",qPrint(cmdName));
4716 ASSERT(tok==TK_WHITESPACE);
4718 par = new DocPara(this);
4719 m_paragraphs.append(par);
4720 retval = par->parse();
4725 DBG(("DocParamList::parse() end retval=%d\n",retval));
4726 DocNode *n=g_nodeStack.pop();
4731 int DocParamList::parseXml(const QCString ¶mName)
4733 int retval=RetVal_OK;
4734 DBG(("DocParamList::parseXml() start\n"));
4735 g_nodeStack.push(this);
4737 g_token->name = paramName;
4738 if (m_type==DocParamSect::Param)
4740 g_hasParamCommand=TRUE;
4741 checkArgumentName(g_token->name,TRUE);
4743 else if (m_type==DocParamSect::RetVal)
4745 g_hasReturnCommand=TRUE;
4746 checkArgumentName(g_token->name,FALSE);
4749 handleLinkedWord(this,m_params);
4753 DocPara *par = new DocPara(this);
4754 retval = par->parse();
4755 if (par->isEmpty()) // avoid adding an empty paragraph for the whitespace
4756 // after </para> and before </param>
4761 else // append the paragraph to the list
4763 if (m_paragraphs.isEmpty())
4769 m_paragraphs.getLast()->markLast(FALSE);
4772 m_paragraphs.append(par);
4775 if (retval == 0) break;
4777 } while (retval==RetVal_CloseXml &&
4778 Mappers::htmlTagMapper->map(g_token->name)!=XML_PARAM &&
4779 Mappers::htmlTagMapper->map(g_token->name)!=XML_TYPEPARAM &&
4780 Mappers::htmlTagMapper->map(g_token->name)!=XML_EXCEPTION);
4783 if (retval==0) /* premature end of comment block */
4785 warn_doc_error(g_fileName,doctokenizerYYlineno,"unterminated param or exception tag");
4793 DBG(("DocParamList::parse() end retval=%d\n",retval));
4794 DocNode *n=g_nodeStack.pop();
4799 //--------------------------------------------------------------------------
4801 int DocParamSect::parse(const QCString &cmdName,bool xmlContext, Direction d)
4803 int retval=RetVal_OK;
4804 DBG(("DocParamSect::parse() start\n"));
4805 g_nodeStack.push(this);
4809 m_hasInOutSpecifier=TRUE;
4812 DocParamList *pl = new DocParamList(this,m_type,d);
4813 if (m_children.isEmpty())
4820 ASSERT(m_children.getLast()->kind()==DocNode::Kind_ParamList);
4821 ((DocParamList *)m_children.getLast())->markLast(FALSE);
4824 m_children.append(pl);
4827 retval = pl->parseXml(cmdName);
4831 retval = pl->parse(cmdName);
4833 if (retval==RetVal_EndParBlock)
4838 DBG(("DocParamSect::parse() end retval=%d\n",retval));
4839 DocNode *n=g_nodeStack.pop();
4844 //--------------------------------------------------------------------------
4846 int DocPara::handleSimpleSection(DocSimpleSect::Type t, bool xmlContext)
4848 DocSimpleSect *ss=0;
4849 bool needsSeparator = FALSE;
4850 if (!m_children.isEmpty() && // previous element
4851 m_children.getLast()->kind()==Kind_SimpleSect && // was a simple sect
4852 ((DocSimpleSect *)m_children.getLast())->type()==t && // of same type
4853 t!=DocSimpleSect::User) // but not user defined
4855 // append to previous section
4856 ss=(DocSimpleSect *)m_children.getLast();
4857 needsSeparator = TRUE;
4859 else // start new section
4861 ss=new DocSimpleSect(this,t);
4862 m_children.append(ss);
4867 return ss->parseXml();
4871 rv = ss->parse(t==DocSimpleSect::User,needsSeparator);
4873 return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4876 int DocPara::handleParamSection(const QCString &cmdName,
4877 DocParamSect::Type t,
4878 bool xmlContext=FALSE,
4879 int direction=DocParamSect::Unspecified)
4882 if (!m_children.isEmpty() && // previous element
4883 m_children.getLast()->kind()==Kind_ParamSect && // was a param sect
4884 ((DocParamSect *)m_children.getLast())->type()==t) // of same type
4886 // append to previous section
4887 ps=(DocParamSect *)m_children.getLast();
4889 else // start new section
4891 ps=new DocParamSect(this,t);
4892 m_children.append(ps);
4894 int rv=ps->parse(cmdName,xmlContext,(DocParamSect::Direction)direction);
4895 return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4898 void DocPara::handleCite()
4900 // get the argument of the cite command.
4901 int tok=doctokenizerYYlex();
4902 if (tok!=TK_WHITESPACE)
4904 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
4908 doctokenizerYYsetStateCite();
4909 tok=doctokenizerYYlex();
4912 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
4913 "argument of command %s\n", qPrint("cite"));
4916 else if (tok!=TK_WORD && tok!=TK_LNKWORD)
4918 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
4919 tokToString(tok),qPrint("cite"));
4922 g_token->sectionId = g_token->name;
4923 DocCite *cite = new DocCite(this,g_token->name,g_context);
4924 m_children.append(cite);
4927 doctokenizerYYsetStatePara();
4930 int DocPara::handleXRefItem()
4932 int retval=doctokenizerYYlex();
4933 ASSERT(retval==TK_WHITESPACE);
4934 doctokenizerYYsetStateXRefItem();
4935 retval=doctokenizerYYlex();
4936 if (retval==RetVal_OK)
4938 DocXRefItem *ref = new DocXRefItem(this,g_token->id,g_token->name);
4941 m_children.append(ref);
4948 doctokenizerYYsetStatePara();
4952 void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type t)
4954 DBG(("handleIncludeOperator(%s)\n",qPrint(cmdName)));
4955 int tok=doctokenizerYYlex();
4956 if (tok!=TK_WHITESPACE)
4958 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
4962 doctokenizerYYsetStatePattern();
4963 tok=doctokenizerYYlex();
4964 doctokenizerYYsetStatePara();
4967 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
4968 "argument of command %s", qPrint(cmdName));
4971 else if (tok!=TK_WORD)
4973 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
4974 tokToString(tok),qPrint(cmdName));
4977 DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName);
4978 QListIterator<DocNode> it(m_children);
4979 DocNode *n1 = it.toLast();
4981 DocNode *n2 = n1!=0 ? it.current() : 0;
4982 bool isFirst = n1==0 || // no last node
4983 (n1->kind()!=DocNode::Kind_IncOperator &&
4984 n1->kind()!=DocNode::Kind_WhiteSpace
4985 ) || // last node is not operator or whitespace
4986 (n1->kind()==DocNode::Kind_WhiteSpace &&
4987 n2!=0 && n2->kind()!=DocNode::Kind_IncOperator
4988 ); // previous not is not operator
4989 op->markFirst(isFirst);
4991 if (n1!=0 && n1->kind()==DocNode::Kind_IncOperator)
4993 ((DocIncOperator *)n1)->markLast(FALSE);
4995 else if (n1!=0 && n1->kind()==DocNode::Kind_WhiteSpace &&
4996 n2!=0 && n2->kind()==DocNode::Kind_IncOperator
4999 ((DocIncOperator *)n2)->markLast(FALSE);
5001 m_children.append(op);
5005 void DocPara::handleImage(const QCString &cmdName)
5007 int tok=doctokenizerYYlex();
5008 if (tok!=TK_WHITESPACE)
5010 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5014 tok=doctokenizerYYlex();
5015 if (tok!=TK_WORD && tok!=TK_LNKWORD)
5017 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5018 tokToString(tok),qPrint(cmdName));
5021 tok=doctokenizerYYlex();
5022 if (tok!=TK_WHITESPACE)
5024 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5029 QCString imgType = g_token->name.lower();
5030 if (imgType=="html") t=DocImage::Html;
5031 else if (imgType=="latex") t=DocImage::Latex;
5032 else if (imgType=="rtf") t=DocImage::Rtf;
5035 warn_doc_error(g_fileName,doctokenizerYYlineno,"image type %s specified as the first argument of "
5037 qPrint(imgType),qPrint(cmdName));
5040 doctokenizerYYsetStateFile();
5041 tok=doctokenizerYYlex();
5042 doctokenizerYYsetStatePara();
5045 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5046 tokToString(tok),qPrint(cmdName));
5049 HtmlAttribList attrList;
5050 DocImage *img = new DocImage(this,attrList,findAndCopyImage(g_token->name,t),t);
5051 m_children.append(img);
5055 void DocPara::handleDotFile(const QCString &cmdName)
5057 int tok=doctokenizerYYlex();
5058 if (tok!=TK_WHITESPACE)
5060 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5064 doctokenizerYYsetStateFile();
5065 tok=doctokenizerYYlex();
5066 doctokenizerYYsetStatePara();
5069 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5070 tokToString(tok),qPrint(cmdName));
5073 QCString name = g_token->name;
5074 DocDotFile *df = new DocDotFile(this,name,g_context);
5075 m_children.append(df);
5079 void DocPara::handleMscFile(const QCString &cmdName)
5081 int tok=doctokenizerYYlex();
5082 if (tok!=TK_WHITESPACE)
5084 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5088 doctokenizerYYsetStateFile();
5089 tok=doctokenizerYYlex();
5090 doctokenizerYYsetStatePara();
5093 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5094 tokToString(tok),qPrint(cmdName));
5097 QCString name = g_token->name;
5098 DocMscFile *df = new DocMscFile(this,name,g_context);
5099 m_children.append(df);
5103 void DocPara::handleDiaFile(const QCString &cmdName)
5105 int tok=doctokenizerYYlex();
5106 if (tok!=TK_WHITESPACE)
5108 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5112 doctokenizerYYsetStateFile();
5113 tok=doctokenizerYYlex();
5114 doctokenizerYYsetStatePara();
5117 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5118 tokToString(tok),qPrint(cmdName));
5121 QCString name = g_token->name;
5122 DocDiaFile *df = new DocDiaFile(this,name,g_context);
5123 m_children.append(df);
5127 void DocPara::handleVhdlFlow()
5129 DocVhdlFlow *vf = new DocVhdlFlow(this);
5130 m_children.append(vf);
5134 void DocPara::handleLink(const QCString &cmdName,bool isJavaLink)
5136 int tok=doctokenizerYYlex();
5137 if (tok!=TK_WHITESPACE)
5139 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5143 doctokenizerYYsetStateLink();
5144 tok=doctokenizerYYlex();
5147 warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s",
5148 tokToString(tok),qPrint(cmdName));
5151 doctokenizerYYsetStatePara();
5152 DocLink *lnk = new DocLink(this,g_token->name);
5153 m_children.append(lnk);
5154 QCString leftOver = lnk->parse(isJavaLink);
5155 if (!leftOver.isEmpty())
5157 m_children.append(new DocWord(this,leftOver));
5161 void DocPara::handleRef(const QCString &cmdName)
5163 DBG(("handleRef(%s)\n",qPrint(cmdName)));
5164 int tok=doctokenizerYYlex();
5165 if (tok!=TK_WHITESPACE)
5167 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5171 doctokenizerYYsetStateRef();
5172 tok=doctokenizerYYlex(); // get the reference id
5176 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5177 tokToString(tok),qPrint(cmdName));
5180 ref = new DocRef(this,g_token->name,g_context);
5181 m_children.append(ref);
5184 doctokenizerYYsetStatePara();
5188 void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t)
5190 DBG(("handleInclude(%s)\n",qPrint(cmdName)));
5191 int tok=doctokenizerYYlex();
5192 if (tok!=TK_WHITESPACE)
5194 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5198 doctokenizerYYsetStateFile();
5199 tok=doctokenizerYYlex();
5200 doctokenizerYYsetStatePara();
5203 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
5204 "argument of command %s",qPrint(cmdName));
5207 else if (tok!=TK_WORD)
5209 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5210 tokToString(tok),qPrint(cmdName));
5213 QCString fileName = g_token->name;
5215 if (t==DocInclude::Snippet)
5217 doctokenizerYYsetStateSnippet();
5218 tok=doctokenizerYYlex();
5219 doctokenizerYYsetStatePara();
5222 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command",
5223 tokToString(tok),qPrint(cmdName));
5226 blockId = "["+g_token->name+"]";
5228 DocInclude *inc = new DocInclude(this,fileName,g_context,t,g_isExample,g_exampleName,blockId);
5229 m_children.append(inc);
5233 void DocPara::handleSection(const QCString &cmdName)
5235 // get the argument of the section command.
5236 int tok=doctokenizerYYlex();
5237 if (tok!=TK_WHITESPACE)
5239 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5243 tok=doctokenizerYYlex();
5246 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
5247 "argument of command %s\n", qPrint(cmdName));
5250 else if (tok!=TK_WORD && tok!=TK_LNKWORD)
5252 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5253 tokToString(tok),qPrint(cmdName));
5256 g_token->sectionId = g_token->name;
5257 doctokenizerYYsetStateSkipTitle();
5258 doctokenizerYYlex();
5259 doctokenizerYYsetStatePara();
5262 int DocPara::handleHtmlHeader(const HtmlAttribList &tagHtmlAttribs,int level)
5264 DocHtmlHeader *header = new DocHtmlHeader(this,tagHtmlAttribs,level);
5265 m_children.append(header);
5266 int retval = header->parse();
5267 return (retval==RetVal_OK) ? TK_NEWPARA : retval;
5270 // For XML tags whose content is stored in attributes rather than
5271 // contained within the element, we need a way to inject the attribute
5272 // text into the current paragraph.
5273 bool DocPara::injectToken(int tok,const QCString &tokText)
5275 g_token->name = tokText;
5276 return defaultHandleToken(this,tok,m_children);
5279 int DocPara::handleStartCode()
5281 int retval = doctokenizerYYlex();
5282 QCString lang = g_token->name;
5283 if (!lang.isEmpty() && lang.at(0)!='.')
5287 // search for the first non-whitespace line, index is stored in li
5288 int i=0,li=0,l=g_token->verb.length();
5289 while (i<l && (g_token->verb.at(i)==' ' || g_token->verb.at(i)=='\n'))
5291 if (g_token->verb.at(i)=='\n') li=i+1;
5294 m_children.append(new DocVerbatim(this,g_context,stripIndentation(g_token->verb.mid(li)),DocVerbatim::Code,g_isExample,g_exampleName,FALSE,lang));
5295 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"code section ended without end marker");
5296 doctokenizerYYsetStatePara();
5300 void DocPara::handleInheritDoc()
5302 if (g_memberDef) // inheriting docs from a member
5304 MemberDef *reMd = g_memberDef->reimplements();
5305 if (reMd) // member from which was inherited.
5307 MemberDef *thisMd = g_memberDef;
5308 //printf("{InheritDocs:%s=>%s}\n",g_memberDef->qualifiedName().data(),reMd->qualifiedName().data());
5309 docParserPushContext();
5310 g_scope=reMd->getOuterScope();
5311 if (g_scope!=Doxygen::globalScope)
5313 g_context=g_scope->name();
5316 g_styleStack.clear();
5317 g_nodeStack.clear();
5318 g_copyStack.append(reMd);
5319 internalValidatingParseDoc(this,m_children,reMd->briefDescription());
5320 internalValidatingParseDoc(this,m_children,reMd->documentation());
5321 g_copyStack.remove(reMd);
5322 docParserPopContext(TRUE);
5323 g_memberDef = thisMd;
5329 int DocPara::handleCommand(const QCString &cmdName)
5331 DBG(("handleCommand(%s)\n",qPrint(cmdName)));
5332 int retval = RetVal_OK;
5333 int cmdId = Mappers::cmdMapper->map(cmdName);
5337 warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unknown command `\\%s'",qPrint(cmdName));
5340 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
5341 retval=handleStyleArgument(this,m_children,cmdName);
5342 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
5343 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
5346 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
5347 retval=handleStyleArgument(this,m_children,cmdName);
5348 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
5349 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
5352 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,TRUE));
5353 retval=handleStyleArgument(this,m_children,cmdName);
5354 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,FALSE));
5355 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
5358 m_children.append(new DocSymbol(this,DocSymbol::Sym_BSlash));
5361 m_children.append(new DocSymbol(this,DocSymbol::Sym_At));
5364 m_children.append(new DocSymbol(this,DocSymbol::Sym_Less));
5367 m_children.append(new DocSymbol(this,DocSymbol::Sym_Greater));
5370 m_children.append(new DocSymbol(this,DocSymbol::Sym_Amp));
5373 m_children.append(new DocSymbol(this,DocSymbol::Sym_Dollar));
5376 m_children.append(new DocSymbol(this,DocSymbol::Sym_Hash));
5379 m_children.append(new DocSymbol(this,DocSymbol::Sym_Pipe));
5382 m_children.append(new DocSymbol(this,DocSymbol::Sym_DoubleColon));
5385 m_children.append(new DocSymbol(this,DocSymbol::Sym_Percent));
5388 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5389 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5392 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5393 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5394 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5397 m_children.append(new DocSymbol(this,DocSymbol::Sym_Quot));
5401 retval = handleSimpleSection(DocSimpleSect::See);
5405 retval = handleSimpleSection(DocSimpleSect::Return);
5406 g_hasReturnCommand=TRUE;
5409 retval = handleSimpleSection(DocSimpleSect::Author);
5412 retval = handleSimpleSection(DocSimpleSect::Authors);
5415 retval = handleSimpleSection(DocSimpleSect::Version);
5418 retval = handleSimpleSection(DocSimpleSect::Since);
5421 retval = handleSimpleSection(DocSimpleSect::Date);
5424 retval = handleSimpleSection(DocSimpleSect::Note);
5427 retval = handleSimpleSection(DocSimpleSect::Warning);
5430 retval = handleSimpleSection(DocSimpleSect::Pre);
5433 retval = handleSimpleSection(DocSimpleSect::Post);
5436 retval = handleSimpleSection(DocSimpleSect::Copyright);
5439 retval = handleSimpleSection(DocSimpleSect::Invar);
5442 retval = handleSimpleSection(DocSimpleSect::Remark);
5445 retval = handleSimpleSection(DocSimpleSect::Attention);
5448 retval = handleSimpleSection(DocSimpleSect::User);
5452 DocSimpleList *sl=new DocSimpleList(this);
5453 m_children.append(sl);
5454 retval = sl->parse();
5459 handleSection(cmdName);
5460 retval = RetVal_Section;
5463 case CMD_SUBSECTION:
5465 handleSection(cmdName);
5466 retval = RetVal_Subsection;
5469 case CMD_SUBSUBSECTION:
5471 handleSection(cmdName);
5472 retval = RetVal_Subsubsection;
5477 handleSection(cmdName);
5478 retval = RetVal_Paragraph;
5483 doctokenizerYYsetStateCode();
5484 retval = handleStartCode();
5489 doctokenizerYYsetStateHtmlOnly();
5490 retval = doctokenizerYYlex();
5491 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block"));
5492 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker");
5493 doctokenizerYYsetStatePara();
5498 doctokenizerYYsetStateManOnly();
5499 retval = doctokenizerYYlex();
5500 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName));
5501 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker");
5502 doctokenizerYYsetStatePara();
5507 doctokenizerYYsetStateRtfOnly();
5508 retval = doctokenizerYYlex();
5509 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName));
5510 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker");
5511 doctokenizerYYsetStatePara();
5516 doctokenizerYYsetStateLatexOnly();
5517 retval = doctokenizerYYlex();
5518 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName));
5519 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker");
5520 doctokenizerYYsetStatePara();
5525 doctokenizerYYsetStateXmlOnly();
5526 retval = doctokenizerYYlex();
5527 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName));
5528 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker");
5529 doctokenizerYYsetStatePara();
5534 doctokenizerYYsetStateDbOnly();
5535 retval = doctokenizerYYlex();
5536 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName));
5537 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker",doctokenizerYYlineno);
5538 doctokenizerYYsetStatePara();
5543 doctokenizerYYsetStateVerbatim();
5544 retval = doctokenizerYYlex();
5545 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Verbatim,g_isExample,g_exampleName));
5546 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"verbatim section ended without end marker");
5547 doctokenizerYYsetStatePara();
5552 doctokenizerYYsetStateDot();
5553 retval = doctokenizerYYlex();
5554 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Dot,g_isExample,g_exampleName));
5555 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"dot section ended without end marker");
5556 doctokenizerYYsetStatePara();
5561 doctokenizerYYsetStateMsc();
5562 retval = doctokenizerYYlex();
5563 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName));
5564 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"msc section ended without end marker");
5565 doctokenizerYYsetStatePara();
5568 case CMD_ENDPARBLOCK:
5569 retval=RetVal_EndParBlock;
5572 case CMD_ENDHTMLONLY:
5573 case CMD_ENDMANONLY:
5574 case CMD_ENDRTFONLY:
5575 case CMD_ENDLATEXONLY:
5576 case CMD_ENDXMLONLY:
5579 case CMD_ENDVERBATIM:
5582 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5585 retval = handleParamSection(cmdName,DocParamSect::Param,FALSE,g_token->paramDir);
5588 retval = handleParamSection(cmdName,DocParamSect::TemplateParam,FALSE,g_token->paramDir);
5591 retval = handleParamSection(cmdName,DocParamSect::RetVal);
5594 retval = handleParamSection(cmdName,DocParamSect::Exception);
5597 retval = handleXRefItem();
5601 DocLineBreak *lb = new DocLineBreak(this);
5602 m_children.append(lb);
5607 DocAnchor *anchor = handleAnchor(this);
5610 m_children.append(anchor);
5616 DocIndexEntry *ie = new DocIndexEntry(this,
5617 g_scope!=Doxygen::globalScope?g_scope:0,
5619 m_children.append(ie);
5620 retval = ie->parse();
5624 retval = RetVal_Internal;
5626 case CMD_ENDINTERNAL:
5627 retval = RetVal_EndInternal;
5631 DocParBlock *block = new DocParBlock(this);
5632 m_children.append(block);
5633 retval = block->parse();
5636 case CMD_COPYDOC: // fall through
5637 case CMD_COPYBRIEF: // fall through
5638 case CMD_COPYDETAILS:
5639 //retval = RetVal_CopyDoc;
5640 // these commands should already be resolved by processCopyDoc()
5643 handleInclude(cmdName,DocInclude::Include);
5645 case CMD_INCWITHLINES:
5646 handleInclude(cmdName,DocInclude::IncWithLines);
5648 case CMD_DONTINCLUDE:
5649 handleInclude(cmdName,DocInclude::DontInclude);
5651 case CMD_HTMLINCLUDE:
5652 handleInclude(cmdName,DocInclude::HtmlInclude);
5654 case CMD_LATEXINCLUDE:
5655 handleInclude(cmdName,DocInclude::LatexInclude);
5657 case CMD_VERBINCLUDE:
5658 handleInclude(cmdName,DocInclude::VerbInclude);
5661 handleInclude(cmdName,DocInclude::Snippet);
5664 handleIncludeOperator(cmdName,DocIncOperator::Skip);
5667 handleIncludeOperator(cmdName,DocIncOperator::Until);
5670 handleIncludeOperator(cmdName,DocIncOperator::SkipLine);
5673 handleIncludeOperator(cmdName,DocIncOperator::Line);
5676 handleImage(cmdName);
5679 handleDotFile(cmdName);
5685 handleMscFile(cmdName);
5688 handleDiaFile(cmdName);
5691 handleLink(cmdName,FALSE);
5694 handleLink(cmdName,TRUE);
5699 case CMD_REF: // fall through
5703 case CMD_SECREFLIST:
5705 DocSecRefList *list = new DocSecRefList(this);
5706 m_children.append(list);
5710 case CMD_SECREFITEM:
5711 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5713 case CMD_ENDSECREFLIST:
5714 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5718 DocFormula *form=new DocFormula(this,g_token->id);
5719 m_children.append(form);
5722 //case CMD_LANGSWITCH:
5723 // retval = handleLanguageSwitch();
5725 case CMD_INTERNALREF:
5726 //warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5728 DocInternalRef *ref = handleInternalRef(this);
5731 m_children.append(ref);
5734 doctokenizerYYsetStatePara();
5737 case CMD_INHERITDOC:
5741 // we should not get here!
5745 INTERNAL_ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec ||
5746 retval==TK_LISTITEM || retval==TK_ENDLIST || retval==TK_NEWPARA ||
5747 retval==RetVal_Section || retval==RetVal_EndList ||
5748 retval==RetVal_Internal || retval==RetVal_SwitchLang ||
5749 retval==RetVal_EndInternal
5751 DBG(("handleCommand(%s) end retval=%x\n",qPrint(cmdName),retval));
5755 static bool findAttribute(const HtmlAttribList &tagHtmlAttribs,
5756 const char *attrName,
5760 HtmlAttribListIterator li(tagHtmlAttribs);
5762 for (li.toFirst();(opt=li.current());++li)
5764 if (opt->name==attrName)
5766 *result = opt->value;
5773 int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &tagHtmlAttribs)
5775 DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.count()));
5776 int retval=RetVal_OK;
5777 int tagId = Mappers::htmlTagMapper->map(tagName);
5778 if (g_token->emptyTag && !(tagId&XML_CmdMask) &&
5779 tagId!=HTML_UNKNOWN && tagId!=HTML_IMG && tagId!=HTML_BR)
5781 warn_doc_error(g_fileName,doctokenizerYYlineno,"HTML tags may not use the 'empty tag' XHTML syntax.");
5787 DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Unordered);
5788 m_children.append(list);
5789 retval=list->parse();
5794 DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Ordered);
5795 m_children.append(list);
5796 retval=list->parse();
5800 if (!insideUL(this) && !insideOL(this))
5802 warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <li> tag found");
5806 retval=RetVal_ListItem;
5810 handleStyleEnter(this,m_children,DocStyleChange::Bold,&g_token->attribs);
5813 if (/*getLanguageFromFileName(g_fileName)==SrcLangExt_CSharp ||*/ g_xmlComment)
5814 // for C# source or inside a <summary> or <remark> section we
5815 // treat <code> as an XML tag (so similar to @code)
5817 doctokenizerYYsetStateXmlCode();
5818 retval = handleStartCode();
5820 else // normal HTML markup
5822 handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs);
5826 handleStyleEnter(this,m_children,DocStyleChange::Italic,&g_token->attribs);
5829 handleStyleEnter(this,m_children,DocStyleChange::Div,&g_token->attribs);
5832 handleStyleEnter(this,m_children,DocStyleChange::Span,&g_token->attribs);
5835 handleStyleEnter(this,m_children,DocStyleChange::Subscript,&g_token->attribs);
5838 handleStyleEnter(this,m_children,DocStyleChange::Superscript,&g_token->attribs);
5841 handleStyleEnter(this,m_children,DocStyleChange::Center,&g_token->attribs);
5844 handleStyleEnter(this,m_children,DocStyleChange::Small,&g_token->attribs);
5847 handleStyleEnter(this,m_children,DocStyleChange::Preformatted,&g_token->attribs);
5848 setInsidePreformatted(TRUE);
5849 doctokenizerYYsetInsidePre(TRUE);
5856 DocHtmlDescList *list = new DocHtmlDescList(this,tagHtmlAttribs);
5857 m_children.append(list);
5858 retval=list->parse();
5862 retval = RetVal_DescTitle;
5865 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <dd> found");
5869 DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs);
5870 m_children.append(table);
5871 retval=table->parse();
5875 retval = RetVal_TableRow;
5878 retval = RetVal_TableCell;
5881 retval = RetVal_TableHCell;
5884 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <caption> found");
5888 DocLineBreak *lb = new DocLineBreak(this);
5889 m_children.append(lb);
5894 DocHorRuler *hr = new DocHorRuler(this);
5895 m_children.append(hr);
5899 retval=handleAHref(this,m_children,tagHtmlAttribs);
5902 retval=handleHtmlHeader(tagHtmlAttribs,1);
5905 retval=handleHtmlHeader(tagHtmlAttribs,2);
5908 retval=handleHtmlHeader(tagHtmlAttribs,3);
5911 retval=handleHtmlHeader(tagHtmlAttribs,4);
5914 retval=handleHtmlHeader(tagHtmlAttribs,5);
5917 retval=handleHtmlHeader(tagHtmlAttribs,6);
5921 handleImg(this,m_children,tagHtmlAttribs);
5924 case HTML_BLOCKQUOTE:
5926 DocHtmlBlockQuote *block = new DocHtmlBlockQuote(this,tagHtmlAttribs);
5927 m_children.append(block);
5928 retval = block->parse();
5938 if (!m_children.isEmpty())
5940 retval = TK_NEWPARA;
5944 case XML_DESCRIPTION:
5945 if (insideTable(this))
5947 retval=RetVal_TableCell;
5951 handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs);
5957 if (findAttribute(tagHtmlAttribs,"name",¶mName))
5959 if (paramName.isEmpty())
5961 if (Config_getBool("WARN_NO_PARAMDOC"))
5963 warn_doc_error(g_fileName,doctokenizerYYlineno,"empty 'name' attribute for <param> tag.");
5968 retval = handleParamSection(paramName,
5969 tagId==XML_PARAM ? DocParamSect::Param : DocParamSect::TemplateParam,
5975 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param> tag.");
5980 case XML_TYPEPARAMREF:
5983 if (findAttribute(tagHtmlAttribs,"name",¶mName))
5985 //printf("paramName=%s\n",paramName.data());
5986 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
5987 m_children.append(new DocWord(this,paramName));
5988 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
5989 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
5993 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type");
5999 QCString exceptName;
6000 if (findAttribute(tagHtmlAttribs,"cref",&exceptName))
6002 retval = handleParamSection(exceptName,DocParamSect::Exception,TRUE);
6006 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <exception> tag.");
6011 case XML_LISTHEADER:
6012 if (insideTable(this))
6014 retval=RetVal_TableRow;
6016 else if (insideUL(this) || insideOL(this))
6018 retval=RetVal_ListItem;
6022 warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <item> tag found");
6026 retval = handleSimpleSection(DocSimpleSect::Return,TRUE);
6027 g_hasReturnCommand=TRUE;
6030 //m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
6031 if (insideTable(this))
6033 retval=RetVal_TableCell;
6037 // I'm not sure if <see> is the same as <seealso> or if it
6038 // should you link a member without producing a section. The
6039 // C# specification is extremely vague about this (but what else
6040 // can we expect from Microsoft...)
6043 //printf("XML_SEE: empty tag=%d\n",g_token->emptyTag);
6044 if (findAttribute(tagHtmlAttribs,"cref",&cref))
6046 if (g_token->emptyTag) // <see cref="..."/> style
6048 bool inSeeBlock = g_inSeeBlock;
6049 g_token->name = cref;
6050 g_inSeeBlock = TRUE;
6051 handleLinkedWord(this,m_children);
6052 g_inSeeBlock = inSeeBlock;
6054 else // <see cref="...">...</see> style
6056 //DocRef *ref = new DocRef(this,cref);
6057 //m_children.append(ref);
6059 doctokenizerYYsetStatePara();
6060 DocLink *lnk = new DocLink(this,cref);
6061 m_children.append(lnk);
6062 QCString leftOver = lnk->parse(FALSE,TRUE);
6063 if (!leftOver.isEmpty())
6065 m_children.append(new DocWord(this,leftOver));
6071 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <see> tag.");
6078 if (findAttribute(tagHtmlAttribs,"cref",&cref))
6080 // Look for an existing "see" section
6081 DocSimpleSect *ss=0;
6082 QListIterator<DocNode> cli(m_children);
6084 for (cli.toFirst();(n=cli.current());++cli)
6086 if (n->kind()==Kind_SimpleSect && ((DocSimpleSect *)n)->type()==DocSimpleSect::See)
6088 ss = (DocSimpleSect *)n;
6092 if (!ss) // start new section
6094 ss=new DocSimpleSect(this,DocSimpleSect::See);
6095 m_children.append(ss);
6098 ss->appendLinkWord(cref);
6103 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <seealso> tag.");
6110 findAttribute(tagHtmlAttribs,"type",&type);
6111 DocHtmlList::Type listType = DocHtmlList::Unordered;
6112 HtmlAttribList emptyList;
6115 listType=DocHtmlList::Ordered;
6119 DocHtmlTable *table = new DocHtmlTable(this,emptyList);
6120 m_children.append(table);
6121 retval=table->parseXml();
6125 DocHtmlList *list = new DocHtmlList(this,emptyList,listType);
6126 m_children.append(list);
6127 retval=list->parseXml();
6132 case XML_PERMISSION:
6133 // These tags are defined in .Net but are currently unsupported
6136 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag <%s> found", qPrint(tagName));
6137 m_children.append(new DocWord(this, "<"+tagName+tagHtmlAttribs.toString()+">"));
6139 case XML_INHERITDOC:
6144 // we should not get here!
6151 int DocPara::handleHtmlEndTag(const QCString &tagName)
6153 DBG(("handleHtmlEndTag(%s)\n",qPrint(tagName)));
6154 int tagId = Mappers::htmlTagMapper->map(tagName);
6155 int retval=RetVal_OK;
6159 if (!insideUL(this))
6161 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ul> tag without matching <ul>");
6165 retval=RetVal_EndList;
6169 if (!insideOL(this))
6171 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ol> tag without matching <ol>");
6175 retval=RetVal_EndList;
6179 if (!insideLI(this))
6181 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </li> tag without matching <li>");
6185 // ignore </li> tags
6188 case HTML_BLOCKQUOTE:
6189 retval=RetVal_EndBlockQuote;
6192 // if (!insidePRE(this))
6194 // warn_doc_error(g_fileName,doctokenizerYYlineno,"found </pre> tag without matching <pre>");
6198 // retval=RetVal_EndPre;
6202 handleStyleLeave(this,m_children,DocStyleChange::Bold,"b");
6205 handleStyleLeave(this,m_children,DocStyleChange::Code,"code");
6208 handleStyleLeave(this,m_children,DocStyleChange::Italic,"em");
6211 handleStyleLeave(this,m_children,DocStyleChange::Div,"div");
6214 handleStyleLeave(this,m_children,DocStyleChange::Span,"span");
6217 handleStyleLeave(this,m_children,DocStyleChange::Subscript,"sub");
6220 handleStyleLeave(this,m_children,DocStyleChange::Superscript,"sup");
6223 handleStyleLeave(this,m_children,DocStyleChange::Center,"center");
6226 handleStyleLeave(this,m_children,DocStyleChange::Small,"small");
6229 handleStyleLeave(this,m_children,DocStyleChange::Preformatted,"pre");
6230 setInsidePreformatted(FALSE);
6231 doctokenizerYYsetInsidePre(FALSE);
6237 retval=RetVal_EndDesc;
6246 retval=RetVal_EndTable;
6258 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </caption> found");
6261 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal </br> tag found\n");
6264 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h1> found");
6267 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h2> found");
6270 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h3> found");
6273 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h4> found");
6276 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h5> found");
6279 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h6> found");
6282 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </img> found");
6285 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </hr> found");
6288 //warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </a> found");
6289 // ignore </a> tag (can be part of <a name=...></a>
6293 //m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
6307 case XML_INHERITDOC:
6308 retval = RetVal_CloseXml;
6311 handleStyleLeave(this,m_children,DocStyleChange::Code,"c");
6314 case XML_LISTHEADER:
6316 case XML_PERMISSION:
6317 case XML_DESCRIPTION:
6319 case XML_TYPEPARAMREF:
6320 // These tags are defined in .Net but are currently unsupported
6323 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag </%s> found", qPrint(tagName));
6324 m_children.append(new DocWord(this,"</"+tagName+">"));
6327 // we should not get here!
6328 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end tag %s\n",qPrint(tagName));
6335 int DocPara::parse()
6337 DBG(("DocPara::parse() start\n"));
6338 g_nodeStack.push(this);
6339 // handle style commands "inherited" from the previous paragraph
6340 handleInitialStyleCommands(this,m_children);
6343 while ((tok=doctokenizerYYlex())) // get the next token
6346 DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
6347 if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
6348 tok==TK_COMMAND || tok==TK_HTMLTAG
6351 DBG((" name=%s",qPrint(g_token->name)));
6357 m_children.append(new DocWord(this,g_token->name));
6360 handleLinkedWord(this,m_children);
6363 m_children.append(new DocURL(this,g_token->name,g_token->isEMailAddr));
6367 // prevent leading whitespace and collapse multiple whitespace areas
6369 if (insidePRE(this) || // all whitespace is relevant
6371 // remove leading whitespace
6372 !m_children.isEmpty() &&
6373 // and whitespace after certain constructs
6374 (k=m_children.getLast()->kind())!=DocNode::Kind_HtmlDescList &&
6375 k!=DocNode::Kind_HtmlTable &&
6376 k!=DocNode::Kind_HtmlList &&
6377 k!=DocNode::Kind_SimpleSect &&
6378 k!=DocNode::Kind_AutoList &&
6379 k!=DocNode::Kind_SimpleList &&
6380 /*k!=DocNode::Kind_Verbatim &&*/
6381 k!=DocNode::Kind_HtmlHeader &&
6382 k!=DocNode::Kind_HtmlBlockQuote &&
6383 k!=DocNode::Kind_ParamSect &&
6384 k!=DocNode::Kind_XRefItem
6388 m_children.append(new DocWhiteSpace(this,g_token->chars));
6394 DBG(("found list item at %d parent=%d\n",g_token->indent,parent()->kind()));
6395 DocNode *n=parent();
6396 while (n && n->kind()!=DocNode::Kind_AutoList) n=n->parent();
6397 if (n) // we found an auto list up in the hierarchy
6399 DocAutoList *al = (DocAutoList *)n;
6400 DBG(("previous list item at %d\n",al->indent()));
6401 if (al->indent()>=g_token->indent)
6402 // new item at the same or lower indent level
6409 // determine list depth
6414 if (n->kind() == DocNode::Kind_AutoList &&
6415 ((DocAutoList*)n)->isEnumList()) depth++;
6419 // first item or sub list => create new list
6423 al = new DocAutoList(this,g_token->indent,
6424 g_token->isEnumList,depth);
6425 m_children.append(al);
6426 retval = al->parse();
6427 } while (retval==TK_LISTITEM && // new list
6428 al->indent()==g_token->indent // at same indent level
6431 // check the return value
6432 if (retval==RetVal_SimpleSec) // auto list ended due to simple section command
6434 // Reparse the token that ended the section at this level,
6435 // so a new simple section will be started at this level.
6436 // This is the same as unputting the last read token and continuing.
6437 g_token->name = g_token->simpleSectName;
6438 if (g_token->name.left(4)=="rcs:") // RCS section
6440 g_token->name = g_token->name.mid(4);
6441 g_token->text = g_token->simpleSectText;
6444 else // other section
6448 DBG(("reparsing command %s\n",qPrint(g_token->name)));
6451 else if (retval==TK_ENDLIST)
6453 if (al->indent()>g_token->indent) // end list
6457 else // continue with current paragraph
6461 else // paragraph ended due to TK_NEWPARA, TK_LISTITEM, or EOF
6468 DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno));
6469 if (parent()->kind()==DocNode::Kind_AutoListItem)
6471 ASSERT(parent()->parent()->kind()==DocNode::Kind_AutoList);
6472 DocAutoList *al = (DocAutoList *)parent()->parent();
6473 if (al->indent()>=g_token->indent)
6475 // end of list marker ends this paragraph
6481 warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found "
6482 "has invalid indent level");
6487 warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found without any preceding "
6493 // see if we have to start a simple section
6494 int cmd = Mappers::cmdMapper->map(g_token->name);
6495 DocNode *n=parent();
6497 n->kind()!=DocNode::Kind_SimpleSect &&
6498 n->kind()!=DocNode::Kind_ParamSect
6503 if (cmd&SIMPLESECT_BIT)
6505 if (n) // already in a simple section
6507 // simple section cannot start in this paragraph, need
6508 // to unwind the stack and remember the command.
6509 g_token->simpleSectName = g_token->name.copy();
6510 retval=RetVal_SimpleSec;
6514 // see if we are in a simple list
6516 while (n && n->kind()!=DocNode::Kind_SimpleListItem) n=n->parent();
6521 retval=RetVal_ListItem;
6526 // handle the command
6527 retval=handleCommand(g_token->name);
6528 DBG(("handleCommand returns %x\n",retval));
6530 // check the return value
6531 if (retval==RetVal_SimpleSec)
6533 // Reparse the token that ended the section at this level,
6534 // so a new simple section will be started at this level.
6535 // This is the same as unputting the last read token and continuing.
6536 g_token->name = g_token->simpleSectName;
6537 if (g_token->name.left(4)=="rcs:") // RCS section
6539 g_token->name = g_token->name.mid(4);
6540 g_token->text = g_token->simpleSectText;
6543 else // other section
6547 DBG(("reparsing command %s\n",qPrint(g_token->name)));
6550 else if (retval==RetVal_OK)
6552 // the command ended normally, keep scanning for new tokens.
6555 else if (retval>0 && retval<RetVal_OK)
6557 // the command ended with a new command, reparse this token
6561 else // end of file, end of paragraph, start or end of section
6562 // or some auto list marker
6570 if (!g_token->endTag) // found a start tag
6572 retval = handleHtmlStartTag(g_token->name,g_token->attribs);
6574 else // found an end tag
6576 retval = handleHtmlEndTag(g_token->name);
6578 if (retval==RetVal_OK)
6580 // the command ended normally, keep scanner for new tokens.
6591 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name);
6592 if (s!=DocSymbol::Sym_Unknown)
6594 m_children.append(new DocSymbol(this,s));
6598 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
6599 qPrint(g_token->name));
6608 DocNode *n=parent();
6610 n->kind()!=DocNode::Kind_SimpleSect &&
6611 n->kind()!=DocNode::Kind_ParamSect
6616 if (n) // already in a simple section
6618 // simple section cannot start in this paragraph, need
6619 // to unwind the stack and remember the command.
6620 g_token->simpleSectName = "rcs:"+g_token->name;
6621 g_token->simpleSectText = g_token->text;
6622 retval=RetVal_SimpleSec;
6626 // see if we are in a simple list
6627 DocSimpleSect *ss=new DocSimpleSect(this,DocSimpleSect::Rcs);
6628 m_children.append(ss);
6633 warn_doc_error(g_fileName,doctokenizerYYlineno,
6634 "Found unexpected token (id=%x)\n",tok);
6640 handlePendingStyleCommands(this,m_children);
6641 DocNode *n = g_nodeStack.pop();
6643 DBG(("DocPara::parse() end retval=%x\n",retval));
6644 INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM ||
6645 retval==TK_ENDLIST || retval>RetVal_OK
6651 //--------------------------------------------------------------------------
6653 int DocSection::parse()
6655 DBG(("DocSection::parse() start %s level=%d\n",qPrint(g_token->sectionId),m_level));
6656 int retval=RetVal_OK;
6657 g_nodeStack.push(this);
6660 if (!m_id.isEmpty())
6662 sec=Doxygen::sectionDict->find(m_id);
6665 m_file = sec->fileName;
6666 m_anchor = sec->label;
6667 m_title = sec->title;
6668 if (m_title.isEmpty()) m_title = sec->label;
6669 if (g_sectionDict && g_sectionDict->find(m_id)==0)
6671 g_sectionDict->append(m_id,sec);
6676 // first parse any number of paragraphs
6681 DocPara *par = new DocPara(this);
6682 if (isFirst) { par->markFirst(); isFirst=FALSE; }
6683 retval=par->parse();
6684 if (!par->isEmpty())
6686 m_children.append(par);
6693 if (retval==TK_LISTITEM)
6695 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found");
6697 if (retval==RetVal_Internal)
6699 DocInternal *in = new DocInternal(this);
6700 m_children.append(in);
6701 retval = in->parse(m_level+1);
6702 if (retval==RetVal_EndInternal)
6707 } while (retval!=0 &&
6708 retval!=RetVal_Section &&
6709 retval!=RetVal_Subsection &&
6710 retval!=RetVal_Subsubsection &&
6711 retval!=RetVal_Paragraph &&
6712 retval!=RetVal_EndInternal
6715 if (lastPar) lastPar->markLast();
6717 //printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel);
6719 if (retval==RetVal_Subsection && m_level==Doxygen::subpageNestingLevel+1)
6721 // then parse any number of nested sections
6722 while (retval==RetVal_Subsection) // more sections follow
6724 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
6725 DocSection *s=new DocSection(this,
6726 QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6727 m_children.append(s);
6728 retval = s->parse();
6731 else if (retval==RetVal_Subsubsection && m_level==Doxygen::subpageNestingLevel+2)
6733 // then parse any number of nested sections
6734 while (retval==RetVal_Subsubsection) // more sections follow
6736 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
6737 DocSection *s=new DocSection(this,
6738 QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6739 m_children.append(s);
6740 retval = s->parse();
6743 else if (retval==RetVal_Paragraph && m_level==QMIN(5,Doxygen::subpageNestingLevel+3))
6745 // then parse any number of nested sections
6746 while (retval==RetVal_Paragraph) // more sections follow
6748 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
6749 DocSection *s=new DocSection(this,
6750 QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6751 m_children.append(s);
6752 retval = s->parse();
6755 else if ((m_level<=1+Doxygen::subpageNestingLevel && retval==RetVal_Subsubsection) ||
6756 (m_level<=2+Doxygen::subpageNestingLevel && retval==RetVal_Paragraph)
6760 if (retval==RetVal_Subsection) level=2;
6761 else if (retval==RetVal_Subsubsection) level=3;
6763 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected %s "
6764 "command found inside %s!",
6765 sectionLevelToName[level],sectionLevelToName[m_level]);
6766 retval=0; // stop parsing
6773 INTERNAL_ASSERT(retval==0 ||
6774 retval==RetVal_Section ||
6775 retval==RetVal_Subsection ||
6776 retval==RetVal_Subsubsection ||
6777 retval==RetVal_Paragraph ||
6778 retval==RetVal_Internal ||
6779 retval==RetVal_EndInternal
6782 DBG(("DocSection::parse() end: retval=%x\n",retval));
6783 DocNode *n = g_nodeStack.pop();
6788 //--------------------------------------------------------------------------
6790 void DocText::parse()
6792 DBG(("DocText::parse() start\n"));
6793 g_nodeStack.push(this);
6794 doctokenizerYYsetStateText();
6797 while ((tok=doctokenizerYYlex())) // get the next token
6802 m_children.append(new DocWord(this,g_token->name));
6805 m_children.append(new DocWhiteSpace(this,g_token->chars));
6809 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name);
6810 if (s!=DocSymbol::Sym_Unknown)
6812 m_children.append(new DocSymbol(this,s));
6816 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
6817 qPrint(g_token->name));
6822 switch (Mappers::cmdMapper->map(g_token->name))
6825 m_children.append(new DocSymbol(this,DocSymbol::Sym_BSlash));
6828 m_children.append(new DocSymbol(this,DocSymbol::Sym_At));
6831 m_children.append(new DocSymbol(this,DocSymbol::Sym_Less));
6834 m_children.append(new DocSymbol(this,DocSymbol::Sym_Greater));
6837 m_children.append(new DocSymbol(this,DocSymbol::Sym_Amp));
6840 m_children.append(new DocSymbol(this,DocSymbol::Sym_Dollar));
6843 m_children.append(new DocSymbol(this,DocSymbol::Sym_Hash));
6846 m_children.append(new DocSymbol(this,DocSymbol::Sym_DoubleColon));
6849 m_children.append(new DocSymbol(this,DocSymbol::Sym_Percent));
6852 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6853 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6856 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6857 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6858 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6861 m_children.append(new DocSymbol(this,DocSymbol::Sym_Quot));
6864 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command `%s' found",
6865 qPrint(g_token->name));
6870 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
6876 handleUnclosedStyleCommands();
6878 DocNode *n = g_nodeStack.pop();
6880 DBG(("DocText::parse() end\n"));
6884 //--------------------------------------------------------------------------
6886 void DocRoot::parse()
6888 DBG(("DocRoot::parse() start\n"));
6889 g_nodeStack.push(this);
6890 doctokenizerYYsetStatePara();
6893 // first parse any number of paragraphs
6898 DocPara *par = new DocPara(this);
6899 if (isFirst) { par->markFirst(); isFirst=FALSE; }
6900 retval=par->parse();
6901 if (!par->isEmpty())
6903 m_children.append(par);
6910 if (retval==TK_LISTITEM)
6912 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found");
6914 else if (retval==RetVal_Subsection)
6916 warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!");
6918 else if (retval==RetVal_Subsubsection)
6920 warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!");
6922 else if (retval==RetVal_Paragraph)
6924 warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!");
6926 if (retval==RetVal_Internal)
6928 DocInternal *in = new DocInternal(this);
6929 m_children.append(in);
6930 retval = in->parse(1);
6932 } while (retval!=0 && retval!=RetVal_Section);
6933 if (lastPar) lastPar->markLast();
6935 //printf("DocRoot::parse() retval=%d %d\n",retval,RetVal_Section);
6936 // then parse any number of level1 sections
6937 while (retval==RetVal_Section)
6939 SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId);
6942 DocSection *s=new DocSection(this,
6943 QMIN(1+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6944 m_children.append(s);
6945 retval = s->parse();
6949 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid section id `%s'; ignoring section",qPrint(g_token->sectionId));
6954 handleUnclosedStyleCommands();
6956 DocNode *n = g_nodeStack.pop();
6958 DBG(("DocRoot::parse() end\n"));
6961 static QCString extractCopyDocId(const char *data, uint &j, uint len)
6966 bool insideDQuote=FALSE;
6967 bool insideSQuote=FALSE;
6969 while (j<len && !found)
6971 if (!insideSQuote && !insideDQuote)
6975 case '(': round++; break;
6976 case ')': round--; break;
6977 case '"': insideDQuote=TRUE; break;
6978 case '\'': insideSQuote=TRUE; break;
6979 case ' ': // fall through
6980 case '\t': // fall through
6986 else if (insideSQuote) // look for single quote end
6988 if (data[j]=='\'' && (j==0 || data[j]!='\\'))
6993 else if (insideDQuote) // look for double quote end
6995 if (data[j]=='"' && (j==0 || data[j]!='\\'))
7002 if (qstrncmp(data+j," const",6)==0)
7006 else if (qstrncmp(data+j," volatile",9)==0)
7012 if (e>s) memcpy(id.data(),data+s,e-s);
7014 //printf("extractCopyDocId='%s' input='%s'\n",id.data(),&data[s]);
7018 static uint isCopyBriefOrDetailsCmd(const char *data, uint i,uint len,bool &brief)
7021 if (i==0 || (data[i-1]!='@' && data[i-1]!='\\')) // not an escaped command
7023 if (i+10<len && qstrncmp(data+i+1,"copybrief",9)==0) // @copybrief or \copybrief
7028 else if (i+12<len && qstrncmp(data+i+1,"copydetails",11)==0) // @copydetails or \copydetails
7037 static QCString processCopyDoc(const char *data,uint &len)
7039 //printf("processCopyDoc start '%s'\n",data);
7045 if (c=='@' || c=='\\') // look for a command
7048 uint j=isCopyBriefOrDetailsCmd(data,i,len,isBrief);
7052 while (j<len && (data[j]==' ' || data[j]=='\t')) j++;
7053 // extract the argument
7054 QCString id = extractCopyDocId(data,j,len);
7057 //printf("resolving docs='%s'\n",id.data());
7058 if (findDocsForMemberOrCompound(id,&doc,&brief,&def))
7060 //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,brief.data(),doc.data(),isBrief);
7061 if (g_copyStack.findRef(def)==-1) // definition not parsed earlier
7063 g_copyStack.append(def);
7066 uint l=brief.length();
7067 buf.addStr(processCopyDoc(brief,l));
7071 uint l=doc.length();
7072 buf.addStr(processCopyDoc(doc,l));
7074 g_copyStack.remove(def);
7078 warn_doc_error(g_fileName,doctokenizerYYlineno,
7079 "Found recursive @copy%s or @copydoc relation for argument '%s'.\n",
7080 isBrief?"brief":"details",id.data());
7083 // skip over command
7092 else // not a command, just copy
7103 //--------------------------------------------------------------------------
7105 DocRoot *validatingParseDoc(const char *fileName,int startLine,
7106 Definition *ctx,MemberDef *md,
7107 const char *input,bool indexWords,
7108 bool isExample, const char *exampleName,
7109 bool singleLine, bool linkFromIndex)
7111 //printf("validatingParseDoc(%s,%s)=[%s]\n",ctx?ctx->name().data():"<none>",
7112 // md?md->name().data():"<none>",
7114 //printf("========== validating %s at line %d\n",fileName,startLine);
7115 //printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",input);
7116 //g_token = new TokenInfo;
7118 // store parser state so we can re-enter this function if needed
7119 //bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
7120 docParserPushContext();
7122 if (ctx && ctx!=Doxygen::globalScope &&
7123 (ctx->definitionType()==Definition::TypeClass ||
7124 ctx->definitionType()==Definition::TypeNamespace
7128 g_context = ctx->name();
7130 else if (ctx && ctx->definitionType()==Definition::TypePage)
7132 Definition *scope = ((PageDef*)ctx)->getPageScope();
7133 if (scope && scope!=Doxygen::globalScope) g_context = scope->name();
7135 else if (ctx && ctx->definitionType()==Definition::TypeGroup)
7137 Definition *scope = ((GroupDef*)ctx)->getGroupScope();
7138 if (scope && scope!=Doxygen::globalScope) g_context = scope->name();
7146 if (indexWords && Doxygen::searchIndex)
7150 g_searchUrl=md->getOutputFileBase();
7151 Doxygen::searchIndex->setCurrentDoc(md,md->anchor(),FALSE);
7155 g_searchUrl=ctx->getOutputFileBase();
7156 Doxygen::searchIndex->setCurrentDoc(ctx,ctx->anchor(),FALSE);
7160 if (indexWords && md && Doxygen::searchIndex)
7162 g_searchUrl=md->getOutputFileBase();
7163 Doxygen::searchIndex->setCurrentDoc(
7164 (md->getLanguage()==SrcLangExt_Fortran ?
7165 theTranslator->trSubprogram(TRUE,TRUE):
7166 theTranslator->trMember(TRUE,TRUE))+" "+md->qualifiedName(),
7170 else if (indexWords && ctx && Doxygen::searchIndex)
7172 g_searchUrl=ctx->getOutputFileBase();
7173 QCString name = ctx->qualifiedName();
7175 SrcLangExt lang = ctx->getLanguage();
7176 QCString sep = getLanguageSpecificSeparator(lang);
7179 name = substitute(name,"::",sep);
7182 switch (ctx->definitionType())
7184 case Definition::TypePage:
7186 PageDef *pd = (PageDef *)ctx;
7187 if (!pd->title().isEmpty())
7189 name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title();
7193 name = theTranslator->trPage(TRUE,TRUE)+" "+pd->name();
7197 case Definition::TypeClass:
7199 ClassDef *cd = (ClassDef *)ctx;
7200 name.prepend(cd->compoundTypeString()+" ");
7203 case Definition::TypeNamespace:
7205 if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
7207 name = theTranslator->trPackage(name);
7209 else if (lang==SrcLangExt_Fortran)
7211 name.prepend(theTranslator->trModule(TRUE,TRUE)+" ");
7215 name.prepend(theTranslator->trNamespace(TRUE,TRUE)+" ");
7219 case Definition::TypeGroup:
7221 GroupDef *gd = (GroupDef *)ctx;
7222 if (gd->groupTitle())
7224 name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle();
7228 name.prepend(theTranslator->trGroup(TRUE,TRUE)+" ");
7235 Doxygen::searchIndex->setCurrentDoc(name,g_searchUrl);
7243 g_fileName = fileName;
7244 g_relPath = (!linkFromIndex && ctx) ?
7245 QCString(relativePathToRoot(ctx->getOutputFileBase())) :
7247 //printf("ctx->name=%s relPath=%s\n",ctx->name().data(),g_relPath.data());
7249 g_nodeStack.clear();
7250 g_styleStack.clear();
7251 g_initialStyleStack.clear();
7252 g_inSeeBlock = FALSE;
7253 g_xmlComment = FALSE;
7254 g_insideHtmlLink = FALSE;
7255 g_includeFileText = "";
7256 g_includeFileOffset = 0;
7257 g_includeFileLength = 0;
7258 g_isExample = isExample;
7259 g_exampleName = exampleName;
7260 g_hasParamCommand = FALSE;
7261 g_hasReturnCommand = FALSE;
7262 g_paramsFound.setAutoDelete(FALSE);
7263 g_paramsFound.clear();
7264 g_sectionDict = 0; //sections;
7266 //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine);
7267 doctokenizerYYlineno=startLine;
7268 uint inpLen=qstrlen(input);
7269 QCString inpStr = processCopyDoc(input,inpLen);
7270 if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n')
7274 //printf("processCopyDoc(in='%s' out='%s')\n",input,inpStr.data());
7275 doctokenizerYYinit(inpStr,g_fileName);
7277 // build abstract syntax tree
7278 DocRoot *root = new DocRoot(md!=0,singleLine);
7282 if (Debug::isFlagSet(Debug::PrintTree))
7284 // pretty print the result
7285 PrintDocVisitor *v = new PrintDocVisitor;
7290 checkUndocumentedParams();
7291 detectNoDocumentedParams();
7293 // TODO: These should be called at the end of the program.
7294 //doctokenizerYYcleanup();
7295 //Mappers::cmdMapper->freeInstance();
7296 //Mappers::htmlTagMapper->freeInstance();
7298 // restore original parser state
7299 docParserPopContext();
7301 //printf(">>>>>> end validatingParseDoc(%s,%s)\n",ctx?ctx->name().data():"<none>",
7302 // md?md->name().data():"<none>");
7307 DocText *validatingParseText(const char *input)
7309 // store parser state so we can re-enter this function if needed
7310 docParserPushContext();
7312 //printf("------------ input ---------\n%s\n"
7313 // "------------ end input -----\n",input);
7314 //g_token = new TokenInfo;
7316 g_fileName = "<parseText>";
7319 g_nodeStack.clear();
7320 g_styleStack.clear();
7321 g_initialStyleStack.clear();
7322 g_inSeeBlock = FALSE;
7323 g_xmlComment = FALSE;
7324 g_insideHtmlLink = FALSE;
7325 g_includeFileText = "";
7326 g_includeFileOffset = 0;
7327 g_includeFileLength = 0;
7328 g_isExample = FALSE;
7330 g_hasParamCommand = FALSE;
7331 g_hasReturnCommand = FALSE;
7332 g_paramsFound.setAutoDelete(FALSE);
7333 g_paramsFound.clear();
7336 DocText *txt = new DocText;
7340 doctokenizerYYlineno=1;
7341 doctokenizerYYinit(input,g_fileName);
7343 // build abstract syntax tree
7346 if (Debug::isFlagSet(Debug::PrintTree))
7348 // pretty print the result
7349 PrintDocVisitor *v = new PrintDocVisitor;
7355 // restore original parser state
7356 docParserPopContext();
7360 void docFindSections(const char *input,
7363 const char *fileName)
7365 doctokenizerYYFindSections(input,d,mg,fileName);