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");
268 case DocImage::DocBook:
269 if (!Config_getBool("GENERATE_DOCBOOK")) return result;
270 outputDir = Config_getString("DOCBOOK_OUTPUT");
273 if (!Config_getBool("GENERATE_RTF")) return result;
274 outputDir = Config_getString("RTF_OUTPUT");
277 QCString outputFile = outputDir+"/"+result;
278 QFileInfo outfi(outputFile);
279 if (outfi.isSymLink())
281 QFile::remove(outputFile);
282 warn_doc_error(g_fileName,doctokenizerYYlineno,
283 "destination of image %s is a symlink, replacing with image",
286 if (outputFile!=inputFile) // prevent copying to ourself
288 QFile outImage(outputFile.data());
289 if (outImage.open(IO_WriteOnly)) // copy the image
291 char *buffer = new char[inImage.size()];
292 inImage.readBlock(buffer,inImage.size());
293 outImage.writeBlock(buffer,inImage.size());
296 if (type==DocImage::Html) Doxygen::indexList->addImageFile(result);
300 warn_doc_error(g_fileName,doctokenizerYYlineno,
301 "could not write output image %s",qPrint(outputFile));
306 printf("Source & Destination are the same!\n");
311 warn_doc_error(g_fileName,doctokenizerYYlineno,
312 "could not open image %s",qPrint(fileName));
315 if (type==DocImage::Latex && Config_getBool("USE_PDFLATEX") &&
316 fd->name().right(4)==".eps"
318 { // we have an .eps image in pdflatex mode => convert it to a pdf.
319 QCString outputDir = Config_getString("LATEX_OUTPUT");
320 QCString baseName = fd->name().left(fd->name().length()-4);
321 QCString epstopdfArgs(4096);
322 epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"",
323 outputDir.data(), baseName.data(),
324 outputDir.data(), baseName.data());
325 portable_sysTimerStart();
326 if (portable_system("epstopdf",epstopdfArgs)!=0)
328 err("Problems running epstopdf. Check your TeX installation!\n");
330 portable_sysTimerStop();
337 text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName));
338 text+="Possible candidates:\n";
339 text+=showFileDefMatches(Doxygen::imageNameDict,fileName);
340 warn_doc_error(g_fileName,doctokenizerYYlineno,text);
345 if (result.left(5)!="http:" && result.left(6)!="https:")
347 warn_doc_error(g_fileName,doctokenizerYYlineno,
348 "image file %s is not found in IMAGE_PATH: "
349 "assuming external image.",qPrint(fileName)
356 /*! Collects the parameters found with \@param or \@retval commands
357 * in a global list g_paramsFound. If \a isParam is set to TRUE
358 * and the parameter is not an actual parameter of the current
359 * member g_memberDef, then a warning is raised (unless warnings
360 * are disabled altogether).
362 static void checkArgumentName(const QCString &name,bool isParam)
364 if (!Config_getBool("WARN_IF_DOC_ERROR")) return;
365 if (g_memberDef==0) return; // not a member
366 ArgumentList *al=g_memberDef->isDocsForDefinition() ?
367 g_memberDef->argumentList() :
368 g_memberDef->declArgumentList();
369 SrcLangExt lang = g_memberDef->getLanguage();
370 //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition());
371 if (al==0) return; // no argument list
373 static QRegExp re("$?[a-zA-Z0-9_\\x80-\\xFF]+\\.*");
375 while ((i=re.match(name,p,&l))!=-1) // to handle @param x,y
377 QCString aName=name.mid(i,l);
378 if (lang==SrcLangExt_Fortran) aName=aName.lower();
379 //printf("aName=`%s'\n",aName.data());
380 ArgumentListIterator ali(*al);
383 for (ali.toFirst();(a=ali.current());++ali)
385 QCString argName = g_memberDef->isDefine() ? a->type : a->name;
386 if (lang==SrcLangExt_Fortran) argName=argName.lower();
387 argName=argName.stripWhiteSpace();
388 //printf("argName=`%s' aName=%s\n",argName.data(),aName.data());
389 if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
392 g_paramsFound.insert(aName,(void *)(0x8));
397 if (!found && isParam)
399 //printf("member type=%d\n",memberDef->memberType());
400 QCString scope=g_memberDef->getScopeString();
401 if (!scope.isEmpty()) scope+="::"; else scope="";
402 QCString inheritedFrom = "";
403 QCString docFile = g_memberDef->docFile();
404 int docLine = g_memberDef->docLine();
405 MemberDef *inheritedMd = g_memberDef->inheritsDocsFrom();
406 if (inheritedMd) // documentation was inherited
408 inheritedFrom.sprintf(" inherited from member %s at line "
409 "%d in file %s",qPrint(inheritedMd->name()),
410 inheritedMd->docLine(),qPrint(inheritedMd->docFile()));
411 docFile = g_memberDef->getDefFileName();
412 docLine = g_memberDef->getDefLine();
415 QCString alStr = argListToString(al);
416 warn_doc_error(docFile,docLine,
417 "argument '%s' of command @param "
418 "is not found in the argument list of %s%s%s%s",
419 qPrint(aName), qPrint(scope), qPrint(g_memberDef->name()),
420 qPrint(alStr), qPrint(inheritedFrom));
426 /*! Checks if the parameters that have been specified using \@param are
427 * indeed all parameters.
428 * Must be called after checkArgumentName() has been called for each
431 static void checkUndocumentedParams()
433 if (g_memberDef && g_hasParamCommand && Config_getBool("WARN_IF_DOC_ERROR"))
435 ArgumentList *al=g_memberDef->isDocsForDefinition() ?
436 g_memberDef->argumentList() :
437 g_memberDef->declArgumentList();
438 SrcLangExt lang = g_memberDef->getLanguage();
441 ArgumentListIterator ali(*al);
444 for (ali.toFirst();(a=ali.current());++ali)
446 QCString argName = g_memberDef->isDefine() ? a->type : a->name;
447 if (lang==SrcLangExt_Fortran) argName = argName.lower();
448 argName=argName.stripWhiteSpace();
449 if (argName.right(3)=="...") argName=argName.left(argName.length()-3);
450 if (g_memberDef->getLanguage()==SrcLangExt_Python && argName=="self")
452 // allow undocumented self parameter for Python
454 else if (!argName.isEmpty() && g_paramsFound.find(argName)==0 && a->docs.isEmpty())
464 "The following parameters of "+
465 QCString(g_memberDef->qualifiedName()) +
466 QCString(argListToString(al)) +
467 " are not documented:\n";
468 for (ali.toFirst();(a=ali.current());++ali)
470 QCString argName = g_memberDef->isDefine() ? a->type : a->name;
471 if (lang==SrcLangExt_Fortran) argName = argName.lower();
472 argName=argName.stripWhiteSpace();
473 if (g_memberDef->getLanguage()==SrcLangExt_Python && argName=="self")
475 // allow undocumented self parameter for Python
477 else if (!argName.isEmpty() && g_paramsFound.find(argName)==0)
487 errMsg+=" parameter '"+argName+"'";
490 if (g_memberDef->inheritsDocsFrom())
492 warn_doc_error(g_memberDef->getDefFileName(),
493 g_memberDef->getDefLine(),
494 substitute(errMsg,"%","%%"));
498 warn_doc_error(g_memberDef->docFile(),
499 g_memberDef->docLine(),
500 substitute(errMsg,"%","%%"));
507 /*! Check if a member has documentation for its parameter and or return
508 * type, if applicable. If found this will be stored in the member, this
509 * is needed as a member can have brief and detailed documentation, while
510 * only one of these needs to document the parameters.
512 static void detectNoDocumentedParams()
514 if (g_memberDef && Config_getBool("WARN_NO_PARAMDOC"))
516 ArgumentList *al = g_memberDef->argumentList();
517 ArgumentList *declAl = g_memberDef->declArgumentList();
518 QCString returnType = g_memberDef->typeString();
519 bool isPython = g_memberDef->getLanguage()==SrcLangExt_Python;
521 if (!g_memberDef->hasDocumentedParams() &&
524 //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
525 g_memberDef->setHasDocumentedParams(TRUE);
527 else if (!g_memberDef->hasDocumentedParams())
529 bool allDoc=TRUE; // no paramater => all parameters are documented
530 if ( // member has parameters
531 al!=0 && // but the member has a parameter list
532 al->count()>0 // with at least one parameter (that is not void)
535 ArgumentListIterator ali(*al);
538 // see if all parameters have documentation
539 for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
541 if (!a->name.isEmpty() && a->type!="void" &&
542 !(isPython && a->name=="self")
545 allDoc = !a->docs.isEmpty();
547 //printf("a->type=%s a->name=%s doc=%s\n",
548 // a->type.data(),a->name.data(),a->docs.data());
550 if (!allDoc && declAl!=0) // try declaration arguments as well
553 ArgumentListIterator ali(*declAl);
555 for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
557 if (!a->name.isEmpty() && a->type!="void" &&
558 !(isPython && a->name=="self")
561 allDoc = !a->docs.isEmpty();
563 //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data());
569 //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
570 g_memberDef->setHasDocumentedParams(TRUE);
573 //printf("Member %s hasReturnCommand=%d\n",g_memberDef->name().data(),g_hasReturnCommand);
574 if (!g_memberDef->hasDocumentedReturnType() && // docs not yet found
577 g_memberDef->setHasDocumentedReturnType(TRUE);
579 else if ( // see if return needs to documented
580 g_memberDef->hasDocumentedReturnType() ||
581 returnType.isEmpty() || // empty return type
582 returnType.find("void")!=-1 || // void return type
583 returnType.find("subroutine")!=-1 || // fortran subroutine
584 g_memberDef->isConstructor() || // a constructor
585 g_memberDef->isDestructor() // or destructor
588 g_memberDef->setHasDocumentedReturnType(TRUE);
595 //---------------------------------------------------------------------------
597 /*! Strips known html and tex extensions from \a text. */
598 static QCString stripKnownExtensions(const char *text)
600 QCString result=text;
601 if (result.right(4)==".tex")
603 result=result.left(result.length()-4);
605 else if (result.right(Doxygen::htmlFileExtension.length())==
606 QCString(Doxygen::htmlFileExtension))
608 result=result.left(result.length()-Doxygen::htmlFileExtension.length());
614 //---------------------------------------------------------------------------
616 /*! Returns TRUE iff node n is a child of a preformatted node */
617 static bool insidePRE(DocNode *n)
621 if (n->isPreformatted()) return TRUE;
627 //---------------------------------------------------------------------------
629 /*! Returns TRUE iff node n is a child of a html list item node */
630 static bool insideLI(DocNode *n)
634 if (n->kind()==DocNode::Kind_HtmlListItem) return TRUE;
640 //---------------------------------------------------------------------------
642 /*! Returns TRUE iff node n is a child of a unordered html list node */
643 static bool insideUL(DocNode *n)
647 if (n->kind()==DocNode::Kind_HtmlList &&
648 ((DocHtmlList *)n)->type()==DocHtmlList::Unordered) return TRUE;
654 //---------------------------------------------------------------------------
656 /*! Returns TRUE iff node n is a child of a ordered html list node */
657 static bool insideOL(DocNode *n)
661 if (n->kind()==DocNode::Kind_HtmlList &&
662 ((DocHtmlList *)n)->type()==DocHtmlList::Ordered) return TRUE;
668 //---------------------------------------------------------------------------
670 static bool insideTable(DocNode *n)
674 if (n->kind()==DocNode::Kind_HtmlTable) return TRUE;
680 //---------------------------------------------------------------------------
682 /*! Looks for a documentation block with name commandName in the current
683 * context (g_context). The resulting documentation string is
684 * put in pDoc, the definition in which the documentation was found is
686 * @retval TRUE if name was found.
687 * @retval FALSE if name was not found.
689 static bool findDocsForMemberOrCompound(const char *commandName,
694 //printf("findDocsForMemberOrCompound(%s)\n",commandName);
698 QCString cmdArg=substitute(commandName,"#","::");
699 int l=cmdArg.length();
700 if (l==0) return FALSE;
702 int funcStart=cmdArg.find('(');
709 // Check for the case of operator() and the like.
710 // beware of scenarios like operator()((foo)bar)
711 int secondParen = cmdArg.find('(', funcStart+1);
712 int leftParen = cmdArg.find(')', funcStart+1);
713 if (leftParen!=-1 && secondParen!=-1)
715 if (leftParen<secondParen)
717 funcStart=secondParen;
722 QCString name=removeRedundantWhiteSpace(cmdArg.left(funcStart));
723 QCString args=cmdArg.right(l-funcStart);
725 // try if the link is to a member
732 bool found = getDefs(
733 g_context.find('.')==-1?g_context.data():"", // `find('.') is a hack to detect files
735 args.isEmpty()?0:args.data(),
736 md,cd,fd,nd,gd,FALSE,0,TRUE);
737 //printf("found=%d context=%s name=%s\n",found,g_context.data(),name.data());
740 *pDoc=md->documentation();
741 *pBrief=md->briefDescription();
747 int scopeOffset=g_context.length();
750 QCString fullName=cmdArg;
753 fullName.prepend(g_context.left(scopeOffset)+"::");
755 //printf("Trying fullName=`%s'\n",fullName.data());
757 // try class, namespace, group, page, file reference
758 cd = Doxygen::classSDict->find(fullName);
761 *pDoc=cd->documentation();
762 *pBrief=cd->briefDescription();
766 nd = Doxygen::namespaceSDict->find(fullName);
769 *pDoc=nd->documentation();
770 *pBrief=nd->briefDescription();
774 gd = Doxygen::groupSDict->find(cmdArg);
777 *pDoc=gd->documentation();
778 *pBrief=gd->briefDescription();
782 pd = Doxygen::pageSDict->find(cmdArg);
785 *pDoc=pd->documentation();
786 *pBrief=pd->briefDescription();
791 fd = findFileDef(Doxygen::inputNameDict,cmdArg,ambig);
792 if (fd && !ambig) // file
794 *pDoc=fd->documentation();
795 *pBrief=fd->briefDescription();
806 scopeOffset = g_context.findRev("::",scopeOffset-1);
807 if (scopeOffset==-1) scopeOffset=0;
809 } while (scopeOffset>=0);
814 //---------------------------------------------------------------------------
816 // forward declaration
817 static bool defaultHandleToken(DocNode *parent,int tok,
818 QList<DocNode> &children,bool
822 static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
823 const QCString &cmdName)
825 DBG(("handleStyleArgument(%s)\n",qPrint(cmdName)));
826 QCString tokenName = g_token->name;
827 int tok=doctokenizerYYlex();
828 if (tok!=TK_WHITESPACE)
830 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
834 while ((tok=doctokenizerYYlex()) &&
835 tok!=TK_WHITESPACE &&
841 static QRegExp specialChar("[.,|()\\[\\]:;\\?]");
842 if (tok==TK_WORD && g_token->name.length()==1 &&
843 g_token->name.find(specialChar)!=-1)
845 // special character that ends the markup command
848 if (!defaultHandleToken(parent,tok,children))
853 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command \\%s as the argument of a \\%s command",
854 qPrint(g_token->name),qPrint(cmdName));
857 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found while handling command %s",
858 qPrint(g_token->name),qPrint(cmdName));
861 if (insideLI(parent) && Mappers::htmlTagMapper->map(g_token->name) && g_token->endTag)
862 { // ignore </li> as the end of a style command
868 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s while handling command %s",
869 tokToString(tok),qPrint(cmdName));
875 DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(cmdName),tok));
876 return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST
880 /*! Called when a style change starts. For instance a \<b\> command is
883 static void handleStyleEnter(DocNode *parent,QList<DocNode> &children,
884 DocStyleChange::Style s,const HtmlAttribList *attribs)
886 DBG(("HandleStyleEnter\n"));
887 DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,TRUE,attribs);
889 g_styleStack.push(sc);
892 /*! Called when a style change ends. For instance a \</b\> command is
895 static void handleStyleLeave(DocNode *parent,QList<DocNode> &children,
896 DocStyleChange::Style s,const char *tagName)
898 DBG(("HandleStyleLeave\n"));
899 if (g_styleStack.isEmpty() || // no style change
900 g_styleStack.top()->style()!=s || // wrong style change
901 g_styleStack.top()->position()!=g_nodeStack.count() // wrong position
904 if (g_styleStack.isEmpty())
906 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag without matching <%s>",
907 qPrint(tagName),qPrint(tagName));
909 else if (g_styleStack.top()->style()!=s)
911 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag while expecting </%s>",
912 qPrint(tagName),qPrint(g_styleStack.top()->styleString()));
916 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> at different nesting level (%d) than expected (%d)",
917 qPrint(tagName),g_nodeStack.count(),g_styleStack.top()->position());
920 else // end the section
922 DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,FALSE);
928 /*! Called at the end of a paragraph to close all open style changes
929 * (e.g. a <b> without a </b>). The closed styles are pushed onto a stack
930 * and entered again at the start of a new paragraph.
932 static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children)
934 if (!g_styleStack.isEmpty())
936 DocStyleChange *sc = g_styleStack.top();
937 while (sc && sc->position()>=g_nodeStack.count())
938 { // there are unclosed style modifiers in the paragraph
939 children.append(new DocStyleChange(parent,g_nodeStack.count(),sc->style(),FALSE));
940 g_initialStyleStack.push(sc);
942 sc = g_styleStack.top();
947 static void handleInitialStyleCommands(DocPara *parent,QList<DocNode> &children)
950 while ((sc=g_initialStyleStack.pop()))
952 handleStyleEnter(parent,children,sc->style(),&sc->attribs());
956 static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs)
958 HtmlAttribListIterator li(tagHtmlAttribs);
961 int retval = RetVal_OK;
962 for (li.toFirst();(opt=li.current());++li,++index)
964 if (opt->name=="name") // <a name=label> tag
966 if (!opt->value.isEmpty())
968 DocAnchor *anc = new DocAnchor(parent,opt->value,TRUE);
969 children.append(anc);
970 break; // stop looking for other tag attribs
974 warn_doc_error(g_fileName,doctokenizerYYlineno,"found <a> tag with name option but without value!");
977 else if (opt->name=="href") // <a href=url>..</a> tag
980 HtmlAttribList attrList = tagHtmlAttribs;
981 // and remove the href attribute
982 bool result = attrList.remove(index);
984 DocHRef *href = new DocHRef(parent,attrList,opt->value,g_relPath);
985 children.append(href);
986 g_insideHtmlLink=TRUE;
987 retval = href->parse();
988 g_insideHtmlLink=FALSE;
991 else // unsupported option for tag a
998 const char *DocStyleChange::styleString() const
1002 case DocStyleChange::Bold: return "b";
1003 case DocStyleChange::Italic: return "em";
1004 case DocStyleChange::Code: return "code";
1005 case DocStyleChange::Center: return "center";
1006 case DocStyleChange::Small: return "small";
1007 case DocStyleChange::Subscript: return "subscript";
1008 case DocStyleChange::Superscript: return "superscript";
1009 case DocStyleChange::Preformatted: return "pre";
1010 case DocStyleChange::Div: return "div";
1011 case DocStyleChange::Span: return "span";
1016 static void handleUnclosedStyleCommands()
1018 if (!g_initialStyleStack.isEmpty())
1020 DocStyleChange *sc = g_initialStyleStack.top();
1021 g_initialStyleStack.pop();
1022 handleUnclosedStyleCommands();
1023 warn_doc_error(g_fileName,doctokenizerYYlineno,
1024 "end of comment block while expecting "
1025 "command </%s>",qPrint(sc->styleString()));
1029 static void handleLinkedWord(DocNode *parent,QList<DocNode> &children)
1031 QCString name = linkToText(SrcLangExt_Unknown,g_token->name,TRUE);
1032 static bool autolinkSupport = Config_getBool("AUTOLINK_SUPPORT");
1033 if (!autolinkSupport) // no autolinking -> add as normal word
1035 children.append(new DocWord(parent,name));
1039 // ------- try to turn the word 'name' into a link
1041 Definition *compound=0;
1042 MemberDef *member=0;
1043 int len = g_token->name.length();
1046 FileDef *fd = findFileDef(Doxygen::inputNameDict,g_fileName,ambig);
1047 //printf("handleLinkedWord(%s) g_context=%s\n",g_token->name.data(),g_context.data());
1048 if (!g_insideHtmlLink &&
1049 (resolveRef(g_context,g_token->name,g_inSeeBlock,&compound,&member,TRUE,fd,TRUE)
1050 || (!g_context.isEmpty() && // also try with global scope
1051 resolveRef("",g_token->name,g_inSeeBlock,&compound,&member,FALSE,0,TRUE))
1055 //printf("resolveRef %s = %p (linkable?=%d)\n",qPrint(g_token->name),member,member ? member->isLinkable() : FALSE);
1056 if (member && member->isLinkable()) // member link
1058 if (member->isObjCMethod())
1060 bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE;
1061 name = member->objCMethodName(localLink,g_inSeeBlock);
1064 DocLinkedWord(parent,name,
1065 member->getReference(),
1066 member->getOutputFileBase(),
1068 member->briefDescriptionAsTooltip()
1072 else if (compound->isLinkable()) // compound link
1074 QCString anchor = compound->anchor();
1075 if (compound->definitionType()==Definition::TypeFile)
1079 else if (compound->definitionType()==Definition::TypeGroup)
1081 name=((GroupDef*)compound)->groupTitle();
1084 DocLinkedWord(parent,name,
1085 compound->getReference(),
1086 compound->getOutputFileBase(),
1088 compound->briefDescriptionAsTooltip()
1092 else if (compound->definitionType()==Definition::TypeFile &&
1093 ((FileDef*)compound)->generateSourceFile()
1094 ) // undocumented file that has source code we can link to
1097 DocLinkedWord(parent,g_token->name,
1098 compound->getReference(),
1099 compound->getSourceFileBase(),
1101 compound->briefDescriptionAsTooltip()
1105 else // not linkable
1107 children.append(new DocWord(parent,name));
1110 else if (!g_insideHtmlLink && len>1 && g_token->name.at(len-1)==':')
1112 // special case, where matching Foo: fails to be an Obj-C reference,
1113 // but Foo itself might be linkable.
1114 g_token->name=g_token->name.left(len-1);
1115 handleLinkedWord(parent,children);
1116 children.append(new DocWord(parent,":"));
1118 else if (!g_insideHtmlLink && (cd=getClass(g_token->name+"-p")))
1120 // special case 2, where the token name is not a class, but could
1121 // be a Obj-C protocol
1123 DocLinkedWord(parent,name,
1125 cd->getOutputFileBase(),
1127 cd->briefDescriptionAsTooltip()
1130 // else if (!g_insideHtmlLink && (cd=getClass(g_token->name+"-g")))
1132 // // special case 3, where the token name is not a class, but could
1133 // // be a C# generic
1134 // children.append(new
1135 // DocLinkedWord(parent,name,
1136 // cd->getReference(),
1137 // cd->getOutputFileBase(),
1139 // cd->briefDescriptionAsTooltip()
1142 else // normal non-linkable word
1144 if (g_token->name.left(1)=="#" || g_token->name.left(2)=="::")
1146 warn_doc_error(g_fileName,doctokenizerYYlineno,"explicit link request to '%s' could not be resolved",qPrint(name));
1147 children.append(new DocWord(parent,g_token->name));
1151 children.append(new DocWord(parent,name));
1156 static void handleParameterType(DocNode *parent,QList<DocNode> &children,const QCString ¶mTypes)
1158 QCString name = g_token->name;
1161 while ((i=paramTypes.find('|',p))!=-1)
1163 g_token->name = paramTypes.mid(p,i-p);
1164 handleLinkedWord(parent,children);
1167 g_token->name = paramTypes.mid(p);
1168 handleLinkedWord(parent,children);
1169 g_token->name = name;
1172 static DocInternalRef *handleInternalRef(DocNode *parent)
1174 //printf("CMD_INTERNALREF\n");
1175 int tok=doctokenizerYYlex();
1176 QCString tokenName = g_token->name;
1177 if (tok!=TK_WHITESPACE)
1179 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
1183 doctokenizerYYsetStateInternalRef();
1184 tok=doctokenizerYYlex(); // get the reference id
1185 if (tok!=TK_WORD && tok!=TK_LNKWORD)
1187 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
1188 tokToString(tok),qPrint(tokenName));
1191 return new DocInternalRef(parent,g_token->name);
1194 static DocAnchor *handleAnchor(DocNode *parent)
1196 int tok=doctokenizerYYlex();
1197 if (tok!=TK_WHITESPACE)
1199 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
1200 qPrint(g_token->name));
1203 doctokenizerYYsetStateAnchor();
1204 tok=doctokenizerYYlex();
1207 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
1208 "argument of command %s",qPrint(g_token->name));
1211 else if (tok!=TK_WORD && tok!=TK_LNKWORD)
1213 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
1214 tokToString(tok),qPrint(g_token->name));
1217 doctokenizerYYsetStatePara();
1218 return new DocAnchor(parent,g_token->name,FALSE);
1222 /* Helper function that deals with the most common tokens allowed in
1223 * title like sections.
1224 * @param parent Parent node, owner of the children list passed as
1225 * the third argument.
1226 * @param tok The token to process.
1227 * @param children The list of child nodes to which the node representing
1228 * the token can be added.
1229 * @param handleWord Indicates if word token should be processed
1230 * @retval TRUE The token was handled.
1231 * @retval FALSE The token was not handled.
1233 static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool
1236 DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
1237 if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
1238 tok==TK_COMMAND || tok==TK_HTMLTAG
1241 DBG((" name=%s",qPrint(g_token->name)));
1245 QCString tokenName = g_token->name;
1249 switch (Mappers::cmdMapper->map(tokenName))
1252 children.append(new DocSymbol(parent,DocSymbol::Sym_BSlash));
1255 children.append(new DocSymbol(parent,DocSymbol::Sym_At));
1258 children.append(new DocSymbol(parent,DocSymbol::Sym_Less));
1261 children.append(new DocSymbol(parent,DocSymbol::Sym_Greater));
1264 children.append(new DocSymbol(parent,DocSymbol::Sym_Amp));
1267 children.append(new DocSymbol(parent,DocSymbol::Sym_Dollar));
1270 children.append(new DocSymbol(parent,DocSymbol::Sym_Hash));
1273 children.append(new DocSymbol(parent,DocSymbol::Sym_DoubleColon));
1276 children.append(new DocSymbol(parent,DocSymbol::Sym_Percent));
1279 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1280 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1283 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1284 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1285 children.append(new DocSymbol(parent,DocSymbol::Sym_Minus));
1288 children.append(new DocSymbol(parent,DocSymbol::Sym_Quot));
1292 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
1293 tok=handleStyleArgument(parent,children,tokenName);
1294 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
1295 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
1296 if (tok==TK_NEWPARA) goto handlepara;
1297 else if (tok==TK_WORD || tok==TK_HTMLTAG)
1299 DBG(("CMD_EMPHASIS: reparsing command %s\n",qPrint(g_token->name)));
1306 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
1307 tok=handleStyleArgument(parent,children,tokenName);
1308 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
1309 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
1310 if (tok==TK_NEWPARA) goto handlepara;
1311 else if (tok==TK_WORD || tok==TK_HTMLTAG)
1313 DBG(("CMD_BOLD: reparsing command %s\n",qPrint(g_token->name)));
1320 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,TRUE));
1321 tok=handleStyleArgument(parent,children,tokenName);
1322 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,FALSE));
1323 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," "));
1324 if (tok==TK_NEWPARA) goto handlepara;
1325 else if (tok==TK_WORD || tok==TK_HTMLTAG)
1327 DBG(("CMD_CODE: reparsing command %s\n",qPrint(g_token->name)));
1334 doctokenizerYYsetStateHtmlOnly();
1335 tok = doctokenizerYYlex();
1336 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block"));
1337 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker");
1338 doctokenizerYYsetStatePara();
1343 doctokenizerYYsetStateManOnly();
1344 tok = doctokenizerYYlex();
1345 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName));
1346 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker");
1347 doctokenizerYYsetStatePara();
1352 doctokenizerYYsetStateRtfOnly();
1353 tok = doctokenizerYYlex();
1354 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName));
1355 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker");
1356 doctokenizerYYsetStatePara();
1361 doctokenizerYYsetStateLatexOnly();
1362 tok = doctokenizerYYlex();
1363 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName));
1364 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker",doctokenizerYYlineno);
1365 doctokenizerYYsetStatePara();
1370 doctokenizerYYsetStateXmlOnly();
1371 tok = doctokenizerYYlex();
1372 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName));
1373 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker",doctokenizerYYlineno);
1374 doctokenizerYYsetStatePara();
1379 doctokenizerYYsetStateDbOnly();
1380 tok = doctokenizerYYlex();
1381 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName));
1382 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker",doctokenizerYYlineno);
1383 doctokenizerYYsetStatePara();
1388 DocFormula *form=new DocFormula(parent,g_token->id);
1389 children.append(form);
1394 DocAnchor *anchor = handleAnchor(parent);
1397 children.append(anchor);
1401 case CMD_INTERNALREF:
1403 DocInternalRef *ref = handleInternalRef(parent);
1406 children.append(ref);
1409 doctokenizerYYsetStatePara();
1418 switch (Mappers::htmlTagMapper->map(tokenName))
1421 warn_doc_error(g_fileName,doctokenizerYYlineno,"found <div> tag in heading\n");
1424 warn_doc_error(g_fileName,doctokenizerYYlineno,"found <pre> tag in heading\n");
1427 if (!g_token->endTag)
1429 handleStyleEnter(parent,children,DocStyleChange::Bold,&g_token->attribs);
1433 handleStyleLeave(parent,children,DocStyleChange::Bold,tokenName);
1438 if (!g_token->endTag)
1440 handleStyleEnter(parent,children,DocStyleChange::Code,&g_token->attribs);
1444 handleStyleLeave(parent,children,DocStyleChange::Code,tokenName);
1448 if (!g_token->endTag)
1450 handleStyleEnter(parent,children,DocStyleChange::Italic,&g_token->attribs);
1454 handleStyleLeave(parent,children,DocStyleChange::Italic,tokenName);
1458 if (!g_token->endTag)
1460 handleStyleEnter(parent,children,DocStyleChange::Subscript,&g_token->attribs);
1464 handleStyleLeave(parent,children,DocStyleChange::Subscript,tokenName);
1468 if (!g_token->endTag)
1470 handleStyleEnter(parent,children,DocStyleChange::Superscript,&g_token->attribs);
1474 handleStyleLeave(parent,children,DocStyleChange::Superscript,tokenName);
1478 if (!g_token->endTag)
1480 handleStyleEnter(parent,children,DocStyleChange::Center,&g_token->attribs);
1484 handleStyleLeave(parent,children,DocStyleChange::Center,tokenName);
1488 if (!g_token->endTag)
1490 handleStyleEnter(parent,children,DocStyleChange::Small,&g_token->attribs);
1494 handleStyleLeave(parent,children,DocStyleChange::Small,tokenName);
1505 DocSymbol::SymType s = DocSymbol::decodeSymbol(tokenName);
1506 if (s!=DocSymbol::Sym_Unknown)
1508 children.append(new DocSymbol(parent,s));
1519 if (insidePRE(parent) || !children.isEmpty())
1521 children.append(new DocWhiteSpace(parent,g_token->chars));
1527 handleLinkedWord(parent,children);
1535 children.append(new DocWord(parent,g_token->name));
1541 if (g_insideHtmlLink)
1543 children.append(new DocWord(parent,g_token->name));
1547 children.append(new DocURL(parent,g_token->name,g_token->isEMailAddr));
1556 //---------------------------------------------------------------------------
1558 static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs)
1560 HtmlAttribListIterator li(tagHtmlAttribs);
1564 for (li.toFirst();(opt=li.current());++li,++index)
1566 //printf("option name=%s value=%s\n",opt->name.data(),opt->value.data());
1567 if (opt->name=="src" && !opt->value.isEmpty())
1570 HtmlAttribList attrList = tagHtmlAttribs;
1571 // and remove the src attribute
1572 bool result = attrList.remove(index);
1574 DocImage *img = new DocImage(parent,attrList,opt->value,DocImage::Html,opt->value);
1575 children.append(img);
1581 warn_doc_error(g_fileName,doctokenizerYYlineno,"IMG tag does not have a SRC attribute!\n");
1585 //---------------------------------------------------------------------------
1587 DocSymbol::SymType DocSymbol::decodeSymbol(const QCString &symName)
1589 DBG(("decodeSymbol(%s)\n",qPrint(symName)));
1590 return HtmlEntityMapper::instance()->name2sym(symName);
1593 //---------------------------------------------------------------------------
1595 static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children,
1596 const QCString &doc)
1598 int retval = RetVal_OK;
1600 if (doc.isEmpty()) return retval;
1602 doctokenizerYYinit(doc,g_fileName);
1604 // first parse any number of paragraphs
1607 if (!children.isEmpty() && children.getLast()->kind()==DocNode::Kind_Para)
1608 { // last child item was a paragraph
1609 lastPar = (DocPara*)children.getLast();
1614 DocPara *par = new DocPara(parent);
1615 if (isFirst) { par->markFirst(); isFirst=FALSE; }
1616 retval=par->parse();
1617 if (!par->isEmpty())
1619 children.append(par);
1620 if (lastPar) lastPar->markLast(FALSE);
1627 } while (retval==TK_NEWPARA);
1628 if (lastPar) lastPar->markLast();
1630 //printf("internalValidateParsingDoc: %p: isFirst=%d isLast=%d\n",
1631 // lastPar,lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
1636 //---------------------------------------------------------------------------
1638 static void readTextFileByName(const QCString &file,QCString &text)
1640 QStrList &examplePathList = Config_getList("EXAMPLE_PATH");
1641 char *s=examplePathList.first();
1644 QCString absFileName = QCString(s)+portable_pathSeparator()+file;
1645 QFileInfo fi(absFileName);
1648 text = fileToString(absFileName,Config_getBool("FILTER_SOURCE_FILES"));
1651 s=examplePathList.next();
1654 // as a fallback we also look in the exampleNameDict
1657 if ((fd=findFileDef(Doxygen::exampleNameDict,file,ambig)))
1659 text = fileToString(fd->absFilePath(),Config_getBool("FILTER_SOURCE_FILES"));
1663 warn_doc_error(g_fileName,doctokenizerYYlineno,"included file name %s is ambiguous"
1664 "Possible candidates:\n%s",qPrint(file),
1665 qPrint(showFileDefMatches(Doxygen::exampleNameDict,file))
1670 warn_doc_error(g_fileName,doctokenizerYYlineno,"included file %s is not found. "
1671 "Check your EXAMPLE_PATH",qPrint(file));
1675 //---------------------------------------------------------------------------
1677 DocWord::DocWord(DocNode *parent,const QCString &word) :
1681 //printf("new word %s url=%s\n",word.data(),g_searchUrl.data());
1682 if (Doxygen::searchIndex && !g_searchUrl.isEmpty())
1684 Doxygen::searchIndex->addWord(word,FALSE);
1688 //---------------------------------------------------------------------------
1690 DocLinkedWord::DocLinkedWord(DocNode *parent,const QCString &word,
1691 const QCString &ref,const QCString &file,
1692 const QCString &anchor,const QCString &tooltip) :
1693 m_word(word), m_ref(ref),
1694 m_file(file), m_relPath(g_relPath), m_anchor(anchor),
1698 //printf("DocLinkedWord: new word %s url=%s tooltip='%s'\n",
1699 // word.data(),g_searchUrl.data(),tooltip.data());
1700 if (Doxygen::searchIndex && !g_searchUrl.isEmpty())
1702 Doxygen::searchIndex->addWord(word,FALSE);
1706 //---------------------------------------------------------------------------
1708 DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor)
1713 warn_doc_error(g_fileName,doctokenizerYYlineno,"Empty anchor label");
1715 if (newAnchor) // found <a name="label">
1719 else if (id.left(CiteConsts::anchorPrefix.length()) == CiteConsts::anchorPrefix)
1721 CiteInfo *cite = Doxygen::citeDict->find(id.mid(CiteConsts::anchorPrefix.length()));
1724 m_file = convertNameToFile(CiteConsts::fileName,FALSE,TRUE);
1729 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid cite anchor id `%s'",qPrint(id));
1730 m_anchor = "invalid";
1734 else // found \anchor label
1736 SectionInfo *sec = Doxygen::sectionDict->find(id);
1739 //printf("Found anchor %s\n",id.data());
1740 m_file = sec->fileName;
1741 m_anchor = sec->label;
1742 if (g_sectionDict && g_sectionDict->find(id)==0)
1744 //printf("Inserting in dictionary!\n");
1745 g_sectionDict->append(id,sec);
1750 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid anchor id `%s'",qPrint(id));
1751 m_anchor = "invalid";
1757 //---------------------------------------------------------------------------
1759 DocVerbatim::DocVerbatim(DocNode *parent,const QCString &context,
1760 const QCString &text, Type t,bool isExample,
1761 const QCString &exampleFile,bool isBlock,const QCString &lang)
1762 : m_context(context), m_text(text), m_type(t),
1763 m_isExample(isExample), m_exampleFile(exampleFile),
1764 m_relPath(g_relPath), m_lang(lang), m_isBlock(isBlock)
1770 //---------------------------------------------------------------------------
1772 void DocInclude::parse()
1774 DBG(("DocInclude::parse(file=%s,text=%s)\n",qPrint(m_file),qPrint(m_text)));
1782 readTextFileByName(m_file,m_text);
1783 g_includeFileText = m_text;
1784 g_includeFileOffset = 0;
1785 g_includeFileLength = m_text.length();
1786 //printf("g_includeFile=<<%s>>\n",g_includeFileText.data());
1791 readTextFileByName(m_file,m_text);
1794 readTextFileByName(m_file,m_text);
1797 readTextFileByName(m_file,m_text);
1798 // check here for the existence of the blockId inside the file, so we
1799 // only generate the warning once.
1801 if (!m_blockId.isEmpty() && (count=m_text.contains(m_blockId.data()))!=2)
1803 warn_doc_error(g_fileName,doctokenizerYYlineno,"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n",
1804 m_blockId.data(),m_file.data(),count);
1810 //---------------------------------------------------------------------------
1812 void DocIncOperator::parse()
1814 const char *p = g_includeFileText;
1815 uint l = g_includeFileLength;
1816 uint o = g_includeFileOffset;
1817 DBG(("DocIncOperator::parse() text=%s off=%d len=%d\n",qPrint(p),o,l));
1819 bool nonEmpty = FALSE;
1828 if (nonEmpty) break; // we have a pattern to match
1829 so=o+1; // no pattern, skip empty line
1831 else if (!isspace((uchar)c)) // no white space char
1837 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1839 m_text = g_includeFileText.mid(so,o-so);
1840 DBG(("DocIncOperator::parse() Line: %s\n",qPrint(m_text)));
1842 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
1853 if (nonEmpty) break; // we have a pattern to match
1854 so=o+1; // no pattern, skip empty line
1856 else if (!isspace((uchar)c)) // no white space char
1862 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1864 m_text = g_includeFileText.mid(so,o-so);
1865 DBG(("DocIncOperator::parse() SkipLine: %s\n",qPrint(m_text)));
1868 o++; // skip new line
1870 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
1881 if (nonEmpty) break; // we have a pattern to match
1882 so=o+1; // no pattern, skip empty line
1884 else if (!isspace((uchar)c)) // no white space char
1890 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1894 o++; // skip new line
1896 g_includeFileOffset = so; // set pointer to start of new line
1908 if (nonEmpty) break; // we have a pattern to match
1909 so=o+1; // no pattern, skip empty line
1911 else if (!isspace((uchar)c)) // no white space char
1917 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1)
1919 m_text = g_includeFileText.mid(bo,o-bo);
1920 DBG(("DocIncOperator::parse() Until: %s\n",qPrint(m_text)));
1923 o++; // skip new line
1925 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line
1930 //---------------------------------------------------------------------------
1932 void DocCopy::parse(QList<DocNode> &children)
1936 if (findDocsForMemberOrCompound(m_link,&doc,&brief,&def))
1938 if (g_copyStack.findRef(def)==-1) // definition not parsed earlier
1940 bool hasParamCommand = g_hasParamCommand;
1941 bool hasReturnCommand = g_hasReturnCommand;
1942 QDict<void> paramsFound = g_paramsFound;
1943 //printf("..1 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
1944 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
1946 docParserPushContext(FALSE);
1948 if (def->definitionType()==Definition::TypeMember && def->getOuterScope())
1950 if (def->getOuterScope()!=Doxygen::globalScope)
1952 g_context=def->getOuterScope()->name();
1955 else if (def!=Doxygen::globalScope)
1957 g_context=def->name();
1959 g_styleStack.clear();
1960 g_nodeStack.clear();
1961 g_paramsFound.clear();
1962 g_copyStack.append(def);
1963 // make sure the descriptions end with a newline, so the parser will correctly
1964 // handle them in all cases.
1965 //printf("doc='%s'\n",doc.data());
1966 //printf("brief='%s'\n",brief.data());
1970 internalValidatingParseDoc(m_parent,children,brief);
1972 //printf("..2 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
1973 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
1974 hasParamCommand = hasParamCommand || g_hasParamCommand;
1975 hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
1976 QDictIterator<void> it(g_paramsFound);
1978 for (;(item=it.current());++it)
1980 paramsFound.insert(it.currentKey(),it.current());
1986 internalValidatingParseDoc(m_parent,children,doc);
1988 //printf("..3 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
1989 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
1990 hasParamCommand = hasParamCommand || g_hasParamCommand;
1991 hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
1992 QDictIterator<void> it(g_paramsFound);
1994 for (;(item=it.current());++it)
1996 paramsFound.insert(it.currentKey(),it.current());
1999 g_copyStack.remove(def);
2000 ASSERT(g_styleStack.isEmpty());
2001 ASSERT(g_nodeStack.isEmpty());
2002 docParserPopContext(TRUE);
2004 g_hasParamCommand = hasParamCommand;
2005 g_hasReturnCommand = hasReturnCommand;
2006 g_paramsFound = paramsFound;
2008 //printf("..4 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
2009 // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
2011 else // oops, recursion
2013 warn_doc_error(g_fileName,doctokenizerYYlineno,"recursive call chain of \\copydoc commands detected at %d\n",
2014 doctokenizerYYlineno);
2019 warn_doc_error(g_fileName,doctokenizerYYlineno,"target %s of \\copydoc command not found",
2024 //---------------------------------------------------------------------------
2026 DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) :
2027 m_id(id), m_key(key), m_relPath(g_relPath)
2032 bool DocXRefItem::parse()
2035 RefList *refList = Doxygen::xrefLists->find(m_key);
2038 // either not a built-in list or the list is enabled
2039 (m_key!="todo" || Config_getBool("GENERATE_TODOLIST")) &&
2040 (m_key!="test" || Config_getBool("GENERATE_TESTLIST")) &&
2041 (m_key!="bug" || Config_getBool("GENERATE_BUGLIST")) &&
2042 (m_key!="deprecated" || Config_getBool("GENERATE_DEPRECATEDLIST"))
2046 RefItem *item = refList->getRefItem(m_id);
2050 if (g_memberDef && g_memberDef->name().at(0)=='@')
2052 m_file = "@"; // can't cross reference anonymous enum
2057 m_file = convertNameToFile(refList->listName(),FALSE,TRUE);
2058 m_anchor = item->listAnchor;
2060 m_title = refList->sectionTitle();
2061 //printf("DocXRefItem: file=%s anchor=%s title=%s\n",
2062 // m_file.data(),m_anchor.data(),m_title.data());
2064 if (!item->text.isEmpty())
2066 docParserPushContext();
2067 internalValidatingParseDoc(this,m_children,item->text);
2068 docParserPopContext();
2076 //---------------------------------------------------------------------------
2078 DocFormula::DocFormula(DocNode *parent,int id) :
2079 m_relPath(g_relPath)
2083 formCmd.sprintf("\\form#%d",id);
2084 Formula *formula=Doxygen::formulaNameDict->find(formCmd);
2087 m_id = formula->getId();
2088 m_name.sprintf("form_%d",m_id);
2089 m_text = formula->getFormulaText();
2093 //---------------------------------------------------------------------------
2095 //int DocLanguage::parse()
2098 // DBG(("DocLanguage::parse() start\n"));
2099 // g_nodeStack.push(this);
2101 // // parse one or more paragraphs
2102 // bool isFirst=TRUE;
2106 // par = new DocPara(this);
2107 // if (isFirst) { par->markFirst(); isFirst=FALSE; }
2108 // m_children.append(par);
2109 // retval=par->parse();
2111 // while (retval==TK_NEWPARA);
2112 // if (par) par->markLast();
2114 // DBG(("DocLanguage::parse() end\n"));
2115 // DocNode *n = g_nodeStack.pop();
2120 //---------------------------------------------------------------------------
2122 void DocSecRefItem::parse()
2124 DBG(("DocSecRefItem::parse() start\n"));
2125 g_nodeStack.push(this);
2127 doctokenizerYYsetStateTitle();
2129 while ((tok=doctokenizerYYlex()))
2131 if (!defaultHandleToken(this,tok,m_children))
2136 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\refitem",
2137 qPrint(g_token->name));
2140 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2141 qPrint(g_token->name));
2144 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2150 doctokenizerYYsetStatePara();
2151 handlePendingStyleCommands(this,m_children);
2154 if (!m_target.isEmpty())
2156 sec=Doxygen::sectionDict->find(m_target);
2159 m_file = sec->fileName;
2160 m_anchor = sec->label;
2161 if (g_sectionDict && g_sectionDict->find(m_target)==0)
2163 g_sectionDict->append(m_target,sec);
2168 warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to unknown section %s",
2174 warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to empty target");
2177 DBG(("DocSecRefItem::parse() end\n"));
2178 DocNode *n = g_nodeStack.pop();
2182 //---------------------------------------------------------------------------
2184 void DocSecRefList::parse()
2186 DBG(("DocSecRefList::parse() start\n"));
2187 g_nodeStack.push(this);
2189 int tok=doctokenizerYYlex();
2191 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
2195 if (tok==TK_COMMAND)
2197 switch (Mappers::cmdMapper->map(g_token->name))
2199 case CMD_SECREFITEM:
2201 int tok=doctokenizerYYlex();
2202 if (tok!=TK_WHITESPACE)
2204 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\refitem command");
2207 tok=doctokenizerYYlex();
2208 if (tok!=TK_WORD && tok!=TK_LNKWORD)
2210 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\refitem",
2215 DocSecRefItem *item = new DocSecRefItem(this,g_token->name);
2216 m_children.append(item);
2220 case CMD_ENDSECREFLIST:
2223 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\secreflist",
2224 qPrint(g_token->name));
2228 else if (tok==TK_WHITESPACE)
2230 // ignore whitespace
2234 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s inside section reference list",
2238 tok=doctokenizerYYlex();
2242 DBG(("DocSecRefList::parse() end\n"));
2243 DocNode *n = g_nodeStack.pop();
2247 //---------------------------------------------------------------------------
2249 DocInternalRef::DocInternalRef(DocNode *parent,const QCString &ref)
2250 : m_relPath(g_relPath)
2253 int i=ref.find('#');
2256 m_anchor = ref.right(ref.length()-i-1);
2257 m_file = ref.left(i);
2265 void DocInternalRef::parse()
2267 g_nodeStack.push(this);
2268 DBG(("DocInternalRef::parse() start\n"));
2271 while ((tok=doctokenizerYYlex()))
2273 if (!defaultHandleToken(this,tok,m_children))
2278 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\ref",
2279 qPrint(g_token->name));
2282 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2283 qPrint(g_token->name));
2286 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2293 handlePendingStyleCommands(this,m_children);
2294 DBG(("DocInternalRef::parse() end\n"));
2295 DocNode *n=g_nodeStack.pop();
2299 //---------------------------------------------------------------------------
2301 DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
2302 m_refToSection(FALSE), m_refToAnchor(FALSE), m_isSubPage(FALSE)
2305 Definition *compound = 0;
2307 //printf("DocRef::DocRef(target=%s,context=%s)\n",target.data(),context.data());
2308 ASSERT(!target.isEmpty());
2309 SrcLangExt lang = getLanguageFromFileName(target);
2310 m_relPath = g_relPath;
2311 SectionInfo *sec = Doxygen::sectionDict->find(target);
2312 if (sec==0 && lang==SrcLangExt_Markdown) // lookup as markdown file
2314 sec = Doxygen::sectionDict->find(markdownFileNameToId(target));
2316 if (sec) // ref to section or anchor
2319 if (sec->type==SectionInfo::Page)
2321 pd = Doxygen::pageSDict->find(target);
2323 m_text = sec->title;
2324 if (m_text.isEmpty()) m_text = sec->label;
2327 m_file = stripKnownExtensions(sec->fileName);
2328 m_refToAnchor = sec->type==SectionInfo::Anchor;
2329 m_refToSection = sec->type!=SectionInfo::Anchor;
2330 m_isSubPage = pd && pd->hasParentPage();
2331 if (sec->type!=SectionInfo::Page || m_isSubPage) m_anchor = sec->label;
2332 //printf("m_text=%s,m_ref=%s,m_file=%s,m_refToAnchor=%d type=%d\n",
2333 // m_text.data(),m_ref.data(),m_file.data(),m_refToAnchor,sec->type);
2336 else if (resolveLink(context,target,TRUE,&compound,anchor))
2338 bool isFile = compound ?
2339 (compound->definitionType()==Definition::TypeFile ||
2340 compound->definitionType()==Definition::TypePage ? TRUE : FALSE) :
2342 m_text = linkToText(compound?compound->getLanguage():SrcLangExt_Unknown,target,isFile);
2344 if (compound && compound->isLinkable()) // ref to compound
2346 if (anchor.isEmpty() && /* compound link */
2347 compound->definitionType()==Definition::TypeGroup && /* is group */
2348 ((GroupDef *)compound)->groupTitle() /* with title */
2351 m_text=((GroupDef *)compound)->groupTitle(); // use group's title as link
2353 else if (compound->definitionType()==Definition::TypeMember &&
2354 ((MemberDef*)compound)->isObjCMethod())
2356 // Objective C Method
2357 MemberDef *member = (MemberDef*)compound;
2358 bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE;
2359 m_text = member->objCMethodName(localLink,g_inSeeBlock);
2362 m_file = compound->getOutputFileBase();
2363 m_ref = compound->getReference();
2364 //printf("isFile=%d compound=%s (%d)\n",isFile,compound->name().data(),
2365 // compound->definitionType());
2368 else if (compound->definitionType()==Definition::TypeFile &&
2369 ((FileDef*)compound)->generateSourceFile()
2370 ) // undocumented file that has source code we can link to
2372 m_file = compound->getSourceFileBase();
2373 m_ref = compound->getReference();
2378 warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to `%s' for \\ref command",
2382 static void flattenParagraphs(DocNode *root,QList<DocNode> &children)
2384 QListIterator<DocNode> li(children);
2385 QList<DocNode> newChildren;
2387 for (li.toFirst();(dn=li.current());++li)
2389 if (dn->kind()==DocNode::Kind_Para)
2391 DocPara *para = (DocPara*)dn;
2392 QList<DocNode> ¶Children = para->children();
2393 paraChildren.setAutoDelete(FALSE); // unlink children from paragraph node
2394 QListIterator<DocNode> li2(paraChildren);
2396 for (li2.toFirst();(dn2=li2.current());++li2)
2398 newChildren.append(dn2); // add them to new node
2403 QListIterator<DocNode> li3(newChildren);
2404 for (li3.toFirst();(dn=li3.current());++li3)
2406 children.append(dn);
2407 dn->setParent(root);
2411 void DocRef::parse()
2413 g_nodeStack.push(this);
2414 DBG(("DocRef::parse() start\n"));
2417 while ((tok=doctokenizerYYlex()))
2419 if (!defaultHandleToken(this,tok,m_children))
2424 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\ref",
2425 qPrint(g_token->name));
2428 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2429 qPrint(g_token->name));
2434 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2441 if (m_children.isEmpty() && !m_text.isEmpty())
2443 g_insideHtmlLink=TRUE;
2444 docParserPushContext();
2445 internalValidatingParseDoc(this,m_children,m_text);
2446 docParserPopContext();
2447 g_insideHtmlLink=FALSE;
2448 flattenParagraphs(this,m_children);
2451 handlePendingStyleCommands(this,m_children);
2453 DocNode *n=g_nodeStack.pop();
2457 //---------------------------------------------------------------------------
2459 DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //context)
2461 static uint numBibFiles = Config_getList("CITE_BIB_FILES").count();
2464 //printf("DocCite::DocCite(target=%s)\n",target.data());
2465 ASSERT(!target.isEmpty());
2466 m_relPath = g_relPath;
2467 CiteInfo *cite = Doxygen::citeDict->find(target);
2468 if (numBibFiles>0 && cite && !cite->text.isEmpty()) // ref to citation
2470 m_text = cite->text;
2472 m_anchor = CiteConsts::anchorPrefix+cite->label;
2473 m_file = convertNameToFile(CiteConsts::fileName,FALSE,TRUE);
2474 //printf("CITE ==> m_text=%s,m_ref=%s,m_file=%s,m_anchor=%s\n",
2475 // m_text.data(),m_ref.data(),m_file.data(),m_anchor.data());
2479 warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to `%s' for \\cite command",
2483 //---------------------------------------------------------------------------
2485 DocLink::DocLink(DocNode *parent,const QCString &target)
2488 Definition *compound;
2492 m_relPath = g_relPath;
2493 if (!m_refText.isEmpty() && m_refText.at(0)=='#')
2495 m_refText = m_refText.right(m_refText.length()-1);
2497 if (resolveLink(g_context,stripKnownExtensions(target),g_inSeeBlock,
2501 if (compound && compound->isLinkable())
2503 m_file = compound->getOutputFileBase();
2504 m_ref = compound->getReference();
2506 else if (compound->definitionType()==Definition::TypeFile &&
2507 ((FileDef*)compound)->generateSourceFile()
2508 ) // undocumented file that has source code we can link to
2510 m_file = compound->getSourceFileBase();
2511 m_ref = compound->getReference();
2516 // bogus link target
2517 warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve link to `%s' for \\link command",
2522 QCString DocLink::parse(bool isJavaLink,bool isXmlLink)
2525 g_nodeStack.push(this);
2526 DBG(("DocLink::parse() start\n"));
2529 while ((tok=doctokenizerYYlex()))
2531 if (!defaultHandleToken(this,tok,m_children,FALSE))
2536 switch (Mappers::cmdMapper->map(g_token->name))
2541 warn_doc_error(g_fileName,doctokenizerYYlineno,"{@link.. ended with @endlink command");
2545 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\link",
2546 qPrint(g_token->name));
2551 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2552 qPrint(g_token->name));
2555 if (g_token->name!="see" || !isXmlLink)
2557 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected xml/html command %s found",
2558 qPrint(g_token->name));
2563 if (isJavaLink) // special case to detect closing }
2565 QCString w = g_token->name;
2571 else if ((p=w.find('}'))!=-1)
2574 m_children.append(new DocWord(this,w.left(p)));
2575 if ((uint)p<l-1) // something left after the } (for instance a .)
2577 result=w.right(l-p-1);
2582 m_children.append(new DocWord(this,g_token->name));
2585 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2593 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
2598 if (m_children.isEmpty()) // no link text
2600 m_children.append(new DocWord(this,m_refText));
2603 handlePendingStyleCommands(this,m_children);
2604 DBG(("DocLink::parse() end\n"));
2605 DocNode *n=g_nodeStack.pop();
2611 //---------------------------------------------------------------------------
2613 DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &context) :
2614 m_name(name), m_relPath(g_relPath), m_context(context)
2619 void DocDotFile::parse()
2621 g_nodeStack.push(this);
2622 DBG(("DocDotFile::parse() start\n"));
2624 doctokenizerYYsetStateTitle();
2626 while ((tok=doctokenizerYYlex()))
2628 if (!defaultHandleToken(this,tok,m_children))
2633 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\dotfile",
2634 qPrint(g_token->name));
2637 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2638 qPrint(g_token->name));
2641 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2647 tok=doctokenizerYYlex();
2648 while (tok==TK_WORD) // there are values following the title
2650 if (g_token->name=="width")
2652 m_width=g_token->chars;
2654 else if (g_token->name=="height")
2656 m_height=g_token->chars;
2660 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2661 qPrint(g_token->name));
2663 tok=doctokenizerYYlex();
2666 doctokenizerYYsetStatePara();
2667 handlePendingStyleCommands(this,m_children);
2670 FileDef *fd = findFileDef(Doxygen::dotFileNameDict,m_name,ambig);
2671 if (fd==0 && m_name.right(4)!=".dot") // try with .dot extension as well
2673 fd = findFileDef(Doxygen::dotFileNameDict,m_name+".dot",ambig);
2677 m_file = fd->absFilePath();
2681 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file name %s is ambiguous.\n"
2682 "Possible candidates:\n%s",qPrint(m_name),
2683 qPrint(showFileDefMatches(Doxygen::exampleNameDict,m_name))
2688 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found "
2689 "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name));
2692 DBG(("DocDotFile::parse() end\n"));
2693 DocNode *n=g_nodeStack.pop();
2697 DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) :
2698 m_name(name), m_relPath(g_relPath), m_context(context)
2703 void DocMscFile::parse()
2705 g_nodeStack.push(this);
2706 DBG(("DocMscFile::parse() start\n"));
2708 doctokenizerYYsetStateTitle();
2710 while ((tok=doctokenizerYYlex()))
2712 if (!defaultHandleToken(this,tok,m_children))
2717 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\mscfile",
2718 qPrint(g_token->name));
2721 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2722 qPrint(g_token->name));
2725 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2731 tok=doctokenizerYYlex();
2732 while (tok==TK_WORD) // there are values following the title
2734 if (g_token->name=="width")
2736 m_width=g_token->chars;
2738 else if (g_token->name=="height")
2740 m_height=g_token->chars;
2744 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2745 qPrint(g_token->name));
2747 tok=doctokenizerYYlex();
2750 doctokenizerYYsetStatePara();
2751 handlePendingStyleCommands(this,m_children);
2754 FileDef *fd = findFileDef(Doxygen::mscFileNameDict,m_name,ambig);
2755 if (fd==0 && m_name.right(4)!=".msc") // try with .msc extension as well
2757 fd = findFileDef(Doxygen::mscFileNameDict,m_name+".msc",ambig);
2761 m_file = fd->absFilePath();
2765 warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file name %s is ambiguous.\n"
2766 "Possible candidates:\n%s",qPrint(m_name),
2767 qPrint(showFileDefMatches(Doxygen::exampleNameDict,m_name))
2772 warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found "
2773 "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name));
2776 DBG(("DocMscFile::parse() end\n"));
2777 DocNode *n=g_nodeStack.pop();
2781 //---------------------------------------------------------------------------
2783 DocDiaFile::DocDiaFile(DocNode *parent,const QCString &name,const QCString &context) :
2784 m_name(name), m_relPath(g_relPath), m_context(context)
2789 void DocDiaFile::parse()
2791 g_nodeStack.push(this);
2792 DBG(("DocDiaFile::parse() start\n"));
2794 doctokenizerYYsetStateTitle();
2796 while ((tok=doctokenizerYYlex()))
2798 if (!defaultHandleToken(this,tok,m_children))
2803 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\diafile",
2804 qPrint(g_token->name));
2807 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2808 qPrint(g_token->name));
2811 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2817 tok=doctokenizerYYlex();
2818 while (tok==TK_WORD) // there are values following the title
2820 if (g_token->name=="width")
2822 m_width=g_token->chars;
2824 else if (g_token->name=="height")
2826 m_height=g_token->chars;
2830 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2831 qPrint(g_token->name));
2833 tok=doctokenizerYYlex();
2836 doctokenizerYYsetStatePara();
2837 handlePendingStyleCommands(this,m_children);
2840 FileDef *fd = findFileDef(Doxygen::diaFileNameDict,m_name,ambig);
2841 if (fd==0 && m_name.right(4)!=".dia") // try with .dia extension as well
2843 fd = findFileDef(Doxygen::diaFileNameDict,m_name+".dia",ambig);
2847 m_file = fd->absFilePath();
2851 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file name %s is ambiguous.\n"
2852 "Possible candidates:\n%s",qPrint(m_name),
2853 qPrint(showFileDefMatches(Doxygen::exampleNameDict,m_name))
2858 warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found "
2859 "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name));
2862 DBG(("DocDiaFile::parse() end\n"));
2863 DocNode *n=g_nodeStack.pop();
2867 //---------------------------------------------------------------------------
2869 DocVhdlFlow::DocVhdlFlow(DocNode *parent)
2874 void DocVhdlFlow::parse()
2876 g_nodeStack.push(this);
2877 DBG(("DocVhdlFlow::parse() start\n"));
2879 doctokenizerYYsetStateTitle();
2881 while ((tok=doctokenizerYYlex()))
2883 if (!defaultHandleToken(this,tok,m_children))
2888 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\mscfile",
2889 qPrint(g_token->name));
2892 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2893 qPrint(g_token->name));
2896 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2902 tok=doctokenizerYYlex();
2904 doctokenizerYYsetStatePara();
2905 handlePendingStyleCommands(this,m_children);
2907 DBG(("DocVhdlFlow::parse() end\n"));
2908 DocNode *n=g_nodeStack.pop();
2910 VhdlDocGen::createFlowChart(g_memberDef);
2914 //---------------------------------------------------------------------------
2916 DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString &name,
2917 Type t,const QCString &url) :
2918 m_attribs(attribs), m_name(name),
2919 m_type(t), m_relPath(g_relPath),
2925 void DocImage::parse()
2927 g_nodeStack.push(this);
2928 DBG(("DocImage::parse() start\n"));
2931 doctokenizerYYsetStateTitle();
2933 while ((tok=doctokenizerYYlex()))
2935 if (tok==TK_WORD && (g_token->name=="width=" || g_token->name=="height="))
2937 // special case: no title, but we do have a size indicator
2938 doctokenizerYYsetStateTitleAttrValue();
2940 g_token->name=g_token->name.left(g_token->name.length()-1);
2943 if (!defaultHandleToken(this,tok,m_children))
2948 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\image",
2949 qPrint(g_token->name));
2952 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
2953 qPrint(g_token->name));
2956 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
2962 // parse size attributes
2963 tok=doctokenizerYYlex();
2964 while (tok==TK_WORD) // there are values following the title
2966 if (g_token->name=="width")
2968 m_width=g_token->chars;
2970 else if (g_token->name=="height")
2972 m_height=g_token->chars;
2976 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
2977 qPrint(g_token->name));
2979 tok=doctokenizerYYlex();
2981 doctokenizerYYsetStatePara();
2983 handlePendingStyleCommands(this,m_children);
2984 DBG(("DocImage::parse() end\n"));
2985 DocNode *n=g_nodeStack.pop();
2990 //---------------------------------------------------------------------------
2992 int DocHtmlHeader::parse()
2994 int retval=RetVal_OK;
2995 g_nodeStack.push(this);
2996 DBG(("DocHtmlHeader::parse() start\n"));
2999 while ((tok=doctokenizerYYlex()))
3001 if (!defaultHandleToken(this,tok,m_children))
3006 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <h%d> tag",
3007 qPrint(g_token->name),m_level);
3011 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3012 if (tagId==HTML_H1 && g_token->endTag) // found </h1> tag
3016 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h1>",
3021 else if (tagId==HTML_H2 && g_token->endTag) // found </h2> tag
3025 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h2>",
3030 else if (tagId==HTML_H3 && g_token->endTag) // found </h3> tag
3034 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h3>",
3039 else if (tagId==HTML_H4 && g_token->endTag) // found </h4> tag
3043 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h4>",
3048 else if (tagId==HTML_H5 && g_token->endTag) // found </h5> tag
3052 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h5>",
3057 else if (tagId==HTML_H6 && g_token->endTag) // found </h6> tag
3061 warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h6>",
3066 else if (tagId==HTML_A)
3068 if (!g_token->endTag)
3070 handleAHref(this,m_children,g_token->attribs);
3073 else if (tagId==HTML_BR)
3075 DocLineBreak *lb = new DocLineBreak(this);
3076 m_children.append(lb);
3080 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <h%d> context",
3081 g_token->endTag?"/":"",qPrint(g_token->name),m_level);
3087 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3088 qPrint(g_token->name));
3091 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3099 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3100 " <h%d> tag\n",m_level);
3103 handlePendingStyleCommands(this,m_children);
3104 DBG(("DocHtmlHeader::parse() end\n"));
3105 DocNode *n=g_nodeStack.pop();
3110 //---------------------------------------------------------------------------
3112 int DocHRef::parse()
3114 int retval=RetVal_OK;
3115 g_nodeStack.push(this);
3116 DBG(("DocHRef::parse() start\n"));
3119 while ((tok=doctokenizerYYlex()))
3121 if (!defaultHandleToken(this,tok,m_children))
3126 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <a>..</a> block",
3127 qPrint(g_token->name));
3130 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3131 qPrint(g_token->name));
3136 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3137 if (tagId==HTML_A && g_token->endTag) // found </a> tag
3143 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <a href=...> context",
3144 g_token->endTag?"/":"",qPrint(g_token->name),doctokenizerYYlineno);
3149 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3150 tokToString(tok),doctokenizerYYlineno);
3157 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3158 " <a href=...> tag",doctokenizerYYlineno);
3161 handlePendingStyleCommands(this,m_children);
3162 DBG(("DocHRef::parse() end\n"));
3163 DocNode *n=g_nodeStack.pop();
3168 //---------------------------------------------------------------------------
3170 int DocInternal::parse(int level)
3172 int retval=RetVal_OK;
3173 g_nodeStack.push(this);
3174 DBG(("DocInternal::parse() start\n"));
3176 // first parse any number of paragraphs
3181 DocPara *par = new DocPara(this);
3182 if (isFirst) { par->markFirst(); isFirst=FALSE; }
3183 retval=par->parse();
3184 if (!par->isEmpty())
3186 m_children.append(par);
3193 if (retval==TK_LISTITEM)
3195 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found",doctokenizerYYlineno);
3197 } while (retval!=0 &&
3198 retval!=RetVal_Section &&
3199 retval!=RetVal_Subsection &&
3200 retval!=RetVal_Subsubsection &&
3201 retval!=RetVal_Paragraph &&
3202 retval!=RetVal_EndInternal
3204 if (lastPar) lastPar->markLast();
3206 // then parse any number of level-n sections
3207 while ((level==1 && retval==RetVal_Section) ||
3208 (level==2 && retval==RetVal_Subsection) ||
3209 (level==3 && retval==RetVal_Subsubsection) ||
3210 (level==4 && retval==RetVal_Paragraph)
3213 DocSection *s=new DocSection(this,
3214 QMIN(level+Doxygen::subpageNestingLevel,5),g_token->sectionId);
3215 m_children.append(s);
3216 retval = s->parse();
3219 if (retval==RetVal_Internal)
3221 warn_doc_error(g_fileName,doctokenizerYYlineno,"\\internal command found inside internal section");
3224 DBG(("DocInternal::parse() end: retval=%x\n",retval));
3225 DocNode *n=g_nodeStack.pop();
3230 //---------------------------------------------------------------------------
3232 int DocIndexEntry::parse()
3234 int retval=RetVal_OK;
3235 g_nodeStack.push(this);
3236 DBG(("DocIndexEntry::parse() start\n"));
3237 int tok=doctokenizerYYlex();
3238 if (tok!=TK_WHITESPACE)
3240 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\addindex command");
3243 doctokenizerYYsetStateTitle();
3245 while ((tok=doctokenizerYYlex()))
3254 m_entry+=g_token->name;
3258 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name);
3261 case DocSymbol::Sym_BSlash: m_entry+='\\'; break;
3262 case DocSymbol::Sym_At: m_entry+='@'; break;
3263 case DocSymbol::Sym_Less: m_entry+='<'; break;
3264 case DocSymbol::Sym_Greater: m_entry+='>'; break;
3265 case DocSymbol::Sym_Amp: m_entry+='&'; break;
3266 case DocSymbol::Sym_Dollar: m_entry+='$'; break;
3267 case DocSymbol::Sym_Hash: m_entry+='#'; break;
3268 case DocSymbol::Sym_Percent: m_entry+='%'; break;
3269 case DocSymbol::Sym_apos: m_entry+='\''; break;
3270 case DocSymbol::Sym_Quot: m_entry+='"'; break;
3271 case DocSymbol::Sym_lsquo: m_entry+='`'; break;
3272 case DocSymbol::Sym_rsquo: m_entry+='\''; break;
3273 case DocSymbol::Sym_ldquo: m_entry+="``"; break;
3274 case DocSymbol::Sym_rdquo: m_entry+="''"; break;
3275 case DocSymbol::Sym_ndash: m_entry+="--"; break;
3276 case DocSymbol::Sym_mdash: m_entry+="---"; break;
3278 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected symbol found as argument of \\addindex");
3284 switch (Mappers::cmdMapper->map(g_token->name))
3286 case CMD_BSLASH: m_entry+='\\'; break;
3287 case CMD_AT: m_entry+='@'; break;
3288 case CMD_LESS: m_entry+='<'; break;
3289 case CMD_GREATER: m_entry+='>'; break;
3290 case CMD_AMP: m_entry+='&'; break;
3291 case CMD_DOLLAR: m_entry+='$'; break;
3292 case CMD_HASH: m_entry+='#'; break;
3293 case CMD_DCOLON: m_entry+="::"; break;
3294 case CMD_PERCENT: m_entry+='%'; break;
3295 case CMD_NDASH: m_entry+="--"; break;
3296 case CMD_MDASH: m_entry+="---"; break;
3297 case CMD_QUOTE: m_entry+='"'; break;
3299 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command %s found as argument of \\addindex",
3300 qPrint(g_token->name));
3305 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3310 if (tok!=0) retval=tok;
3311 doctokenizerYYsetStatePara();
3312 m_entry = m_entry.stripWhiteSpace();
3314 DBG(("DocIndexEntry::parse() end retval=%x\n",retval));
3315 DocNode *n=g_nodeStack.pop();
3320 //---------------------------------------------------------------------------
3322 int DocHtmlCaption::parse()
3325 g_nodeStack.push(this);
3326 DBG(("DocHtmlCaption::parse() start\n"));
3328 while ((tok=doctokenizerYYlex()))
3330 if (!defaultHandleToken(this,tok,m_children))
3335 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <caption> tag",
3336 qPrint(g_token->name));
3339 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3340 qPrint(g_token->name));
3344 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3345 if (tagId==HTML_CAPTION && g_token->endTag) // found </caption> tag
3352 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <caption> context",
3353 g_token->endTag?"/":"",qPrint(g_token->name));
3358 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3366 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3367 " <caption> tag",doctokenizerYYlineno);
3370 handlePendingStyleCommands(this,m_children);
3371 DBG(("DocHtmlCaption::parse() end\n"));
3372 DocNode *n=g_nodeStack.pop();
3377 //---------------------------------------------------------------------------
3379 int DocHtmlCell::parse()
3381 int retval=RetVal_OK;
3382 g_nodeStack.push(this);
3383 DBG(("DocHtmlCell::parse() start\n"));
3385 // parse one or more paragraphs
3390 par = new DocPara(this);
3391 if (isFirst) { par->markFirst(); isFirst=FALSE; }
3392 m_children.append(par);
3393 retval=par->parse();
3394 if (retval==TK_HTMLTAG)
3396 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3397 if (tagId==HTML_TD && g_token->endTag) // found </dt> tag
3399 retval=TK_NEWPARA; // ignore the tag
3401 else if (tagId==HTML_TH && g_token->endTag) // found </th> tag
3403 retval=TK_NEWPARA; // ignore the tag
3407 while (retval==TK_NEWPARA);
3408 if (par) par->markLast();
3410 DBG(("DocHtmlCell::parse() end\n"));
3411 DocNode *n=g_nodeStack.pop();
3416 int DocHtmlCell::parseXml()
3418 int retval=RetVal_OK;
3419 g_nodeStack.push(this);
3420 DBG(("DocHtmlCell::parseXml() start\n"));
3422 // parse one or more paragraphs
3427 par = new DocPara(this);
3428 if (isFirst) { par->markFirst(); isFirst=FALSE; }
3429 m_children.append(par);
3430 retval=par->parse();
3431 if (retval==TK_HTMLTAG)
3433 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3434 if (tagId==XML_ITEM && g_token->endTag) // found </item> tag
3436 retval=TK_NEWPARA; // ignore the tag
3438 else if (tagId==XML_DESCRIPTION && g_token->endTag) // found </description> tag
3440 retval=TK_NEWPARA; // ignore the tag
3444 while (retval==TK_NEWPARA);
3445 if (par) par->markLast();
3447 DBG(("DocHtmlCell::parseXml() end\n"));
3448 DocNode *n=g_nodeStack.pop();
3453 int DocHtmlCell::rowSpan() const
3456 HtmlAttribList attrs = attribs();
3458 for (i=0; i<attrs.count(); ++i)
3460 if (attrs.at(i)->name.lower()=="rowspan")
3462 retval = attrs.at(i)->value.toInt();
3469 int DocHtmlCell::colSpan() const
3472 HtmlAttribList attrs = attribs();
3474 for (i=0; i<attrs.count(); ++i)
3476 if (attrs.at(i)->name.lower()=="colspan")
3478 retval = QMAX(1,attrs.at(i)->value.toInt());
3485 DocHtmlCell::Alignment DocHtmlCell::alignment() const
3487 HtmlAttribList attrs = attribs();
3489 for (i=0; i<attrs.count(); ++i)
3491 if (attrs.at(i)->name.lower()=="align")
3493 if (attrs.at(i)->value.lower()=="center")
3495 else if (attrs.at(i)->value.lower()=="right")
3504 //---------------------------------------------------------------------------
3506 int DocHtmlRow::parse()
3508 int retval=RetVal_OK;
3509 g_nodeStack.push(this);
3510 DBG(("DocHtmlRow::parse() start\n"));
3512 bool isHeading=FALSE;
3514 DocHtmlCell *cell=0;
3517 int tok=doctokenizerYYlex();
3519 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3520 // should find a html tag now
3521 if (tok==TK_HTMLTAG)
3523 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3524 if (tagId==HTML_TD && !g_token->endTag) // found <td> tag
3527 else if (tagId==HTML_TH && !g_token->endTag) // found <th> tag
3531 else // found some other tag
3533 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but "
3534 "found <%s> instead!",qPrint(g_token->name));
3535 doctokenizerYYpushBackHtmlTag(g_token->name);
3539 else if (tok==0) // premature end of comment
3541 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
3542 " for a html description title");
3545 else // token other than html token
3547 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!",
3552 // parse one or more cells
3555 cell=new DocHtmlCell(this,g_token->attribs,isHeading);
3556 cell->markFirst(isFirst);
3558 m_children.append(cell);
3559 retval=cell->parse();
3560 isHeading = retval==RetVal_TableHCell;
3562 while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
3563 if (cell) cell->markLast(TRUE);
3566 DBG(("DocHtmlRow::parse() end\n"));
3567 DocNode *n=g_nodeStack.pop();
3572 int DocHtmlRow::parseXml(bool isHeading)
3574 int retval=RetVal_OK;
3575 g_nodeStack.push(this);
3576 DBG(("DocHtmlRow::parseXml() start\n"));
3579 DocHtmlCell *cell=0;
3582 int tok=doctokenizerYYlex();
3584 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3585 // should find a html tag now
3586 if (tok==TK_HTMLTAG)
3588 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3589 if (tagId==XML_TERM && !g_token->endTag) // found <term> tag
3592 else if (tagId==XML_DESCRIPTION && !g_token->endTag) // found <description> tag
3595 else // found some other tag
3597 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <term> or <description> tag but "
3598 "found <%s> instead!",qPrint(g_token->name));
3599 doctokenizerYYpushBackHtmlTag(g_token->name);
3603 else if (tok==0) // premature end of comment
3605 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
3606 " for a html description title");
3609 else // token other than html token
3611 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!",
3618 cell=new DocHtmlCell(this,g_token->attribs,isHeading);
3619 cell->markFirst(isFirst);
3621 m_children.append(cell);
3622 retval=cell->parseXml();
3624 while (retval==RetVal_TableCell || retval==RetVal_TableHCell);
3625 if (cell) cell->markLast(TRUE);
3628 DBG(("DocHtmlRow::parseXml() end\n"));
3629 DocNode *n=g_nodeStack.pop();
3634 //---------------------------------------------------------------------------
3636 int DocHtmlTable::parse()
3638 int retval=RetVal_OK;
3639 g_nodeStack.push(this);
3640 DBG(("DocHtmlTable::parse() start\n"));
3644 int tok=doctokenizerYYlex();
3646 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3647 // should find a html tag now
3648 if (tok==TK_HTMLTAG)
3650 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3651 if (tagId==HTML_TR && !g_token->endTag) // found <tr> tag
3653 // no caption, just rows
3654 retval=RetVal_TableRow;
3656 else if (tagId==HTML_CAPTION && !g_token->endTag) // found <caption> tag
3660 warn_doc_error(g_fileName,doctokenizerYYlineno,"table already has a caption, found another one");
3664 m_caption = new DocHtmlCaption(this,g_token->attribs);
3665 retval=m_caption->parse();
3667 if (retval==RetVal_OK) // caption was parsed ok
3673 else // found wrong token
3675 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> or <caption> tag but "
3676 "found <%s%s> instead!", g_token->endTag ? "/" : "", qPrint(g_token->name));
3679 else if (tok==0) // premature end of comment
3681 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
3682 " for a <tr> or <caption> tag");
3684 else // token other than html token
3686 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> tag but found %s token instead!",
3690 // parse one or more rows
3691 while (retval==RetVal_TableRow)
3693 DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs);
3694 m_children.append(tr);
3700 DBG(("DocHtmlTable::parse() end\n"));
3701 DocNode *n=g_nodeStack.pop();
3703 return retval==RetVal_EndTable ? RetVal_OK : retval;
3706 int DocHtmlTable::parseXml()
3708 int retval=RetVal_OK;
3709 g_nodeStack.push(this);
3710 DBG(("DocHtmlTable::parseXml() start\n"));
3713 int tok=doctokenizerYYlex();
3715 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
3716 // should find a html tag now
3718 bool isHeader=FALSE;
3719 if (tok==TK_HTMLTAG)
3721 tagId=Mappers::htmlTagMapper->map(g_token->name);
3722 if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag
3724 retval=RetVal_TableRow;
3726 if (tagId==XML_LISTHEADER && !g_token->endTag) // found <listheader> tag
3728 retval=RetVal_TableRow;
3733 // parse one or more rows
3734 while (retval==RetVal_TableRow)
3736 DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs);
3737 m_children.append(tr);
3738 retval=tr->parseXml(isHeader);
3744 DBG(("DocHtmlTable::parseXml() end\n"));
3745 DocNode *n=g_nodeStack.pop();
3747 return retval==RetVal_EndTable ? RetVal_OK : retval;
3750 /** Helper class to compute the grid for an HTML style table */
3751 struct ActiveRowSpan
3753 ActiveRowSpan(int rows,int col) : rowsLeft(rows), column(col) {}
3758 /** List of ActiveRowSpan classes. */
3759 typedef QList<ActiveRowSpan> RowSpanList;
3761 /** determines the location of all cells in a grid, resolving row and
3762 column spans. For each the total number of visible cells is computed,
3763 and the total number of visible columns over all rows is stored.
3765 void DocHtmlTable::computeTableGrid()
3767 //printf("computeTableGrid()\n");
3768 RowSpanList rowSpans;
3769 rowSpans.setAutoDelete(TRUE);
3772 QListIterator<DocNode> li(children());
3774 for (li.toFirst();(rowNode=li.current());++li)
3778 if (rowNode->kind()==DocNode::Kind_HtmlRow)
3781 DocHtmlRow *row = (DocHtmlRow*)rowNode;
3782 QListIterator<DocNode> rli(row->children());
3784 for (rli.toFirst();(cellNode=rli.current());++rli)
3786 if (cellNode->kind()==DocNode::Kind_HtmlCell)
3788 DocHtmlCell *cell = (DocHtmlCell*)cellNode;
3789 int rs = cell->rowSpan();
3790 int cs = cell->colSpan();
3792 for (i=0;i<rowSpans.count();i++)
3794 if (rowSpans.at(i)->rowsLeft>0 &&
3795 rowSpans.at(i)->column==colIdx)
3797 colIdx=rowSpans.at(i)->column+1;
3801 if (rs>0) rowSpans.append(new ActiveRowSpan(rs,colIdx));
3802 //printf("found cell at (%d,%d)\n",rowIdx,colIdx);
3803 cell->setRowIndex(rowIdx);
3804 cell->setColumnIndex(colIdx);
3809 for (i=0;i<rowSpans.count();i++)
3811 if (rowSpans.at(i)->rowsLeft>0) rowSpans.at(i)->rowsLeft--;
3813 row->setVisibleCells(cells);
3814 row->setRowIndex(rowIdx);
3817 if (colIdx-1>maxCols) maxCols=colIdx-1;
3819 m_numCols = maxCols;
3822 void DocHtmlTable::accept(DocVisitor *v)
3825 // for HTML output we put the caption first
3826 if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v);
3827 QListIterator<DocNode> cli(m_children);
3829 for (cli.toFirst();(n=cli.current());++cli) n->accept(v);
3830 // for other output formats we put the caption last
3831 if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v);
3835 //---------------------------------------------------------------------------
3837 int DocHtmlDescTitle::parse()
3840 g_nodeStack.push(this);
3841 DBG(("DocHtmlDescTitle::parse() start\n"));
3844 while ((tok=doctokenizerYYlex()))
3846 if (!defaultHandleToken(this,tok,m_children))
3852 QCString cmdName=g_token->name;
3853 bool isJavaLink=FALSE;
3854 switch (Mappers::cmdMapper->map(cmdName))
3858 int tok=doctokenizerYYlex();
3859 if (tok!=TK_WHITESPACE)
3861 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
3862 qPrint(g_token->name));
3866 doctokenizerYYsetStateRef();
3867 tok=doctokenizerYYlex(); // get the reference id
3870 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
3871 tokToString(tok),qPrint(cmdName));
3875 DocRef *ref = new DocRef(this,g_token->name,g_context);
3876 m_children.append(ref);
3879 doctokenizerYYsetStatePara();
3888 int tok=doctokenizerYYlex();
3889 if (tok!=TK_WHITESPACE)
3891 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
3896 doctokenizerYYsetStateLink();
3897 tok=doctokenizerYYlex();
3900 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
3901 tokToString(tok),qPrint(cmdName));
3905 doctokenizerYYsetStatePara();
3906 DocLink *lnk = new DocLink(this,g_token->name);
3907 m_children.append(lnk);
3908 QCString leftOver = lnk->parse(isJavaLink);
3909 if (!leftOver.isEmpty())
3911 m_children.append(new DocWord(this,leftOver));
3919 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <dt> tag",
3920 qPrint(g_token->name));
3925 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
3926 qPrint(g_token->name));
3930 int tagId=Mappers::htmlTagMapper->map(g_token->name);
3931 if (tagId==HTML_DD && !g_token->endTag) // found <dd> tag
3933 retval = RetVal_DescData;
3936 else if (tagId==HTML_DT && g_token->endTag)
3938 // ignore </dt> tag.
3940 else if (tagId==HTML_DT)
3942 // missing <dt> tag.
3943 retval = RetVal_DescTitle;
3946 else if (tagId==HTML_DL && g_token->endTag)
3948 retval=RetVal_EndDesc;
3951 else if (tagId==HTML_A)
3953 if (!g_token->endTag)
3955 handleAHref(this,m_children,g_token->attribs);
3960 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <dt> context",
3961 g_token->endTag?"/":"",qPrint(g_token->name));
3966 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
3974 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside"
3978 handlePendingStyleCommands(this,m_children);
3979 DBG(("DocHtmlDescTitle::parse() end\n"));
3980 DocNode *n=g_nodeStack.pop();
3985 //---------------------------------------------------------------------------
3987 int DocHtmlDescData::parse()
3989 m_attribs = g_token->attribs;
3991 g_nodeStack.push(this);
3992 DBG(("DocHtmlDescData::parse() start\n"));
3998 par = new DocPara(this);
3999 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4000 m_children.append(par);
4001 retval=par->parse();
4003 while (retval==TK_NEWPARA);
4004 if (par) par->markLast();
4006 DBG(("DocHtmlDescData::parse() end\n"));
4007 DocNode *n=g_nodeStack.pop();
4012 //---------------------------------------------------------------------------
4014 int DocHtmlDescList::parse()
4016 int retval=RetVal_OK;
4017 g_nodeStack.push(this);
4018 DBG(("DocHtmlDescList::parse() start\n"));
4021 int tok=doctokenizerYYlex();
4023 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
4024 // should find a html tag now
4025 if (tok==TK_HTMLTAG)
4027 int tagId=Mappers::htmlTagMapper->map(g_token->name);
4028 if (tagId==HTML_DT && !g_token->endTag) // found <dt> tag
4032 else // found some other tag
4034 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but "
4035 "found <%s> instead!",qPrint(g_token->name));
4036 doctokenizerYYpushBackHtmlTag(g_token->name);
4040 else if (tok==0) // premature end of comment
4042 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
4043 " for a html description title");
4046 else // token other than html token
4048 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but found %s token instead!",
4055 DocHtmlDescTitle *dt=new DocHtmlDescTitle(this,g_token->attribs);
4056 m_children.append(dt);
4057 DocHtmlDescData *dd=new DocHtmlDescData(this);
4058 m_children.append(dd);
4060 if (retval==RetVal_DescData)
4064 else if (retval!=RetVal_DescTitle)
4069 } while (retval==RetVal_DescTitle);
4073 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <dl> block");
4078 DocNode *n=g_nodeStack.pop();
4080 DBG(("DocHtmlDescList::parse() end\n"));
4081 return retval==RetVal_EndDesc ? RetVal_OK : retval;
4084 //---------------------------------------------------------------------------
4086 int DocHtmlListItem::parse()
4088 DBG(("DocHtmlListItem::parse() start\n"));
4090 g_nodeStack.push(this);
4092 // parse one or more paragraphs
4097 par = new DocPara(this);
4098 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4099 m_children.append(par);
4100 retval=par->parse();
4102 while (retval==TK_NEWPARA);
4103 if (par) par->markLast();
4105 DocNode *n=g_nodeStack.pop();
4107 DBG(("DocHtmlListItem::parse() end retval=%x\n",retval));
4111 int DocHtmlListItem::parseXml()
4113 DBG(("DocHtmlListItem::parseXml() start\n"));
4115 g_nodeStack.push(this);
4117 // parse one or more paragraphs
4122 par = new DocPara(this);
4123 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4124 m_children.append(par);
4125 retval=par->parse();
4126 if (retval==0) break;
4128 //printf("new item: retval=%x g_token->name=%s g_token->endTag=%d\n",
4129 // retval,qPrint(g_token->name),g_token->endTag);
4130 if (retval==RetVal_ListItem)
4135 while (retval!=RetVal_CloseXml);
4137 if (par) par->markLast();
4139 DocNode *n=g_nodeStack.pop();
4141 DBG(("DocHtmlListItem::parseXml() end retval=%x\n",retval));
4145 //---------------------------------------------------------------------------
4147 int DocHtmlList::parse()
4149 DBG(("DocHtmlList::parse() start\n"));
4150 int retval=RetVal_OK;
4152 g_nodeStack.push(this);
4155 int tok=doctokenizerYYlex();
4156 // skip whitespace and paragraph breaks
4157 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
4158 // should find a html tag now
4159 if (tok==TK_HTMLTAG)
4161 int tagId=Mappers::htmlTagMapper->map(g_token->name);
4162 if (tagId==HTML_LI && !g_token->endTag) // found <li> tag
4164 // ok, we can go on.
4166 else if (((m_type==Unordered && tagId==HTML_UL) ||
4167 (m_type==Ordered && tagId==HTML_OL)
4168 ) && g_token->endTag
4169 ) // found empty list
4171 // add dummy item to obtain valid HTML
4172 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4173 warn_doc_error(g_fileName,doctokenizerYYlineno,"empty list!");
4174 retval = RetVal_EndList;
4177 else // found some other tag
4179 // add dummy item to obtain valid HTML
4180 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4181 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but "
4182 "found <%s%s> instead!",g_token->endTag?"/":"",qPrint(g_token->name));
4183 doctokenizerYYpushBackHtmlTag(g_token->name);
4187 else if (tok==0) // premature end of comment
4189 // add dummy item to obtain valid HTML
4190 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4191 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
4192 " for a html list item");
4195 else // token other than html token
4197 // add dummy item to obtain valid HTML
4198 m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1));
4199 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but found %s token instead!",
4206 DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++);
4207 m_children.append(li);
4209 } while (retval==RetVal_ListItem);
4213 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <%cl> block",
4214 m_type==Unordered ? 'u' : 'o');
4218 DBG(("DocHtmlList::parse() end retval=%x\n",retval));
4219 DocNode *n=g_nodeStack.pop();
4221 return retval==RetVal_EndList ? RetVal_OK : retval;
4224 int DocHtmlList::parseXml()
4226 DBG(("DocHtmlList::parseXml() start\n"));
4227 int retval=RetVal_OK;
4229 g_nodeStack.push(this);
4232 int tok=doctokenizerYYlex();
4233 // skip whitespace and paragraph breaks
4234 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex();
4235 // should find a html tag now
4236 if (tok==TK_HTMLTAG)
4238 int tagId=Mappers::htmlTagMapper->map(g_token->name);
4239 //printf("g_token->name=%s g_token->endTag=%d\n",qPrint(g_token->name),g_token->endTag);
4240 if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag
4242 // ok, we can go on.
4244 else // found some other tag
4246 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but "
4247 "found <%s> instead!",qPrint(g_token->name));
4248 doctokenizerYYpushBackHtmlTag(g_token->name);
4252 else if (tok==0) // premature end of comment
4254 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking"
4255 " for a html list item");
4258 else // token other than html token
4260 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but found %s token instead!",
4267 DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++);
4268 m_children.append(li);
4269 retval=li->parseXml();
4270 if (retval==0) break;
4271 //printf("retval=%x g_token->name=%s\n",retval,qPrint(g_token->name));
4272 } while (retval==RetVal_ListItem);
4276 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <list type=\"%s\"> block",
4277 m_type==Unordered ? "bullet" : "number");
4281 DBG(("DocHtmlList::parseXml() end retval=%x\n",retval));
4282 DocNode *n=g_nodeStack.pop();
4284 return retval==RetVal_EndList ||
4285 (retval==RetVal_CloseXml || g_token->name=="list") ?
4289 //--------------------------------------------------------------------------
4291 int DocHtmlBlockQuote::parse()
4293 DBG(("DocHtmlBlockQuote::parse() start\n"));
4295 g_nodeStack.push(this);
4297 // parse one or more paragraphs
4302 par = new DocPara(this);
4303 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4304 m_children.append(par);
4305 retval=par->parse();
4307 while (retval==TK_NEWPARA);
4308 if (par) par->markLast();
4310 DocNode *n=g_nodeStack.pop();
4312 DBG(("DocHtmlBlockQuote::parse() end retval=%x\n",retval));
4313 return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
4316 //---------------------------------------------------------------------------
4318 int DocParBlock::parse()
4320 DBG(("DocParBlock::parse() start\n"));
4322 g_nodeStack.push(this);
4324 // parse one or more paragraphs
4329 par = new DocPara(this);
4330 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4331 m_children.append(par);
4332 retval=par->parse();
4334 while (retval==TK_NEWPARA);
4335 if (par) par->markLast();
4337 DocNode *n=g_nodeStack.pop();
4339 DBG(("DocParBlock::parse() end retval=%x\n",retval));
4340 return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
4343 //---------------------------------------------------------------------------
4345 int DocSimpleListItem::parse()
4347 g_nodeStack.push(this);
4348 int rv=m_paragraph->parse();
4349 m_paragraph->markFirst();
4350 m_paragraph->markLast();
4351 DocNode *n=g_nodeStack.pop();
4356 //--------------------------------------------------------------------------
4358 int DocSimpleList::parse()
4360 g_nodeStack.push(this);
4364 DocSimpleListItem *li=new DocSimpleListItem(this);
4365 m_children.append(li);
4367 } while (rv==RetVal_ListItem);
4368 DocNode *n=g_nodeStack.pop();
4370 return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4373 //--------------------------------------------------------------------------
4375 DocAutoListItem::DocAutoListItem(DocNode *parent,int indent,int num)
4376 : m_indent(indent), m_itemNum(num)
4381 int DocAutoListItem::parse()
4383 int retval = RetVal_OK;
4384 g_nodeStack.push(this);
4386 // first parse any number of paragraphs
4391 DocPara *par = new DocPara(this);
4392 if (isFirst) { par->markFirst(); isFirst=FALSE; }
4393 retval=par->parse();
4394 if (!par->isEmpty())
4396 m_children.append(par);
4397 if (lastPar) lastPar->markLast(FALSE);
4404 // next paragraph should be more indented than the - marker to belong
4406 } while (retval==TK_NEWPARA && g_token->indent>m_indent);
4407 if (lastPar) lastPar->markLast();
4409 DocNode *n=g_nodeStack.pop();
4411 //printf("DocAutoListItem: retval=%d indent=%d\n",retval,g_token->indent);
4415 //--------------------------------------------------------------------------
4417 DocAutoList::DocAutoList(DocNode *parent,int indent,bool isEnumList,
4419 m_indent(indent), m_isEnumList(isEnumList),
4425 int DocAutoList::parse()
4427 int retval = RetVal_OK;
4429 g_nodeStack.push(this);
4430 doctokenizerYYstartAutoList();
4431 // first item or sub list => create new list
4434 if (g_token->id!=-1) // explicitly numbered list
4436 num=g_token->id; // override num with real number given
4438 DocAutoListItem *li = new DocAutoListItem(this,m_indent,num++);
4439 m_children.append(li);
4441 //printf("DocAutoList::parse(): retval=0x%x g_token->indent=%d m_indent=%d "
4442 // "m_isEnumList=%d g_token->isEnumList=%d g_token->name=%s\n",
4443 // retval,g_token->indent,m_indent,m_isEnumList,g_token->isEnumList,
4444 // g_token->name.data());
4445 //printf("num=%d g_token->id=%d\n",num,g_token->id);
4447 while (retval==TK_LISTITEM && // new list item
4448 m_indent==g_token->indent && // at same indent level
4449 m_isEnumList==g_token->isEnumList && // of the same kind
4450 (g_token->id==-1 || g_token->id>=num) // increasing number (or no number)
4453 doctokenizerYYendAutoList();
4454 DocNode *n=g_nodeStack.pop();
4459 //--------------------------------------------------------------------------
4461 void DocTitle::parse()
4463 DBG(("DocTitle::parse() start\n"));
4464 g_nodeStack.push(this);
4465 doctokenizerYYsetStateTitle();
4467 while ((tok=doctokenizerYYlex()))
4469 if (!defaultHandleToken(this,tok,m_children))
4474 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a title section",
4475 qPrint(g_token->name));
4478 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
4479 qPrint(g_token->name));
4482 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
4488 doctokenizerYYsetStatePara();
4489 handlePendingStyleCommands(this,m_children);
4490 DBG(("DocTitle::parse() end\n"));
4491 DocNode *n = g_nodeStack.pop();
4495 void DocTitle::parseFromString(const QCString &text)
4497 m_children.append(new DocWord(this,text));
4500 //--------------------------------------------------------------------------
4502 DocSimpleSect::DocSimpleSect(DocNode *parent,Type t) :
4509 DocSimpleSect::~DocSimpleSect()
4514 void DocSimpleSect::accept(DocVisitor *v)
4517 if (m_title) m_title->accept(v);
4518 QListIterator<DocNode> cli(m_children);
4520 for (cli.toFirst();(n=cli.current());++cli) n->accept(v);
4524 int DocSimpleSect::parse(bool userTitle,bool needsSeparator)
4526 DBG(("DocSimpleSect::parse() start\n"));
4527 g_nodeStack.push(this);
4529 // handle case for user defined title
4532 m_title = new DocTitle(this);
4536 // add new paragraph as child
4537 DocPara *par = new DocPara(this);
4538 if (m_children.isEmpty())
4544 ASSERT(m_children.getLast()->kind()==DocNode::Kind_Para);
4545 ((DocPara *)m_children.getLast())->markLast(FALSE);
4548 if (needsSeparator) m_children.append(new DocSimpleSectSep(this));
4549 m_children.append(par);
4551 // parse the contents of the paragraph
4552 int retval = par->parse();
4554 DBG(("DocSimpleSect::parse() end retval=%d\n",retval));
4555 DocNode *n=g_nodeStack.pop();
4557 return retval; // 0==EOF, TK_NEWPARA, TK_LISTITEM, TK_ENDLIST, RetVal_SimpleSec
4560 int DocSimpleSect::parseRcs()
4562 DBG(("DocSimpleSect::parseRcs() start\n"));
4563 g_nodeStack.push(this);
4565 m_title = new DocTitle(this);
4566 m_title->parseFromString(g_token->name);
4568 QCString text = g_token->text;
4569 docParserPushContext(); // this will create a new g_token
4570 internalValidatingParseDoc(this,m_children,text);
4571 docParserPopContext(); // this will restore the old g_token
4573 DBG(("DocSimpleSect::parseRcs()\n"));
4574 DocNode *n=g_nodeStack.pop();
4579 int DocSimpleSect::parseXml()
4581 DBG(("DocSimpleSect::parse() start\n"));
4582 g_nodeStack.push(this);
4584 int retval = RetVal_OK;
4587 // add new paragraph as child
4588 DocPara *par = new DocPara(this);
4589 if (m_children.isEmpty())
4595 ASSERT(m_children.getLast()->kind()==DocNode::Kind_Para);
4596 ((DocPara *)m_children.getLast())->markLast(FALSE);
4599 m_children.append(par);
4601 // parse the contents of the paragraph
4602 retval = par->parse();
4603 if (retval == 0) break;
4604 if (retval == RetVal_CloseXml)
4611 DBG(("DocSimpleSect::parseXml() end retval=%d\n",retval));
4612 DocNode *n=g_nodeStack.pop();
4617 void DocSimpleSect::appendLinkWord(const QCString &word)
4620 if (m_children.isEmpty() || m_children.getLast()->kind()!=DocNode::Kind_Para)
4622 p = new DocPara(this);
4623 m_children.append(p);
4627 p = (DocPara *)m_children.getLast();
4629 // Comma-seperate <seealso> links.
4630 p->injectToken(TK_WORD,",");
4631 p->injectToken(TK_WHITESPACE," ");
4635 p->injectToken(TK_LNKWORD,word);
4639 QCString DocSimpleSect::typeString() const
4643 case Unknown: break;
4644 case See: return "see";
4645 case Return: return "return";
4646 case Author: // fall through
4647 case Authors: return "author";
4648 case Version: return "version";
4649 case Since: return "since";
4650 case Date: return "date";
4651 case Note: return "note";
4652 case Warning: return "warning";
4653 case Pre: return "pre";
4654 case Post: return "post";
4655 case Copyright: return "copyright";
4656 case Invar: return "invariant";
4657 case Remark: return "remark";
4658 case Attention: return "attention";
4659 case User: return "user";
4660 case Rcs: return "rcs";
4665 //--------------------------------------------------------------------------
4667 int DocParamList::parse(const QCString &cmdName)
4669 int retval=RetVal_OK;
4670 DBG(("DocParamList::parse() start\n"));
4671 g_nodeStack.push(this);
4674 int tok=doctokenizerYYlex();
4675 if (tok!=TK_WHITESPACE)
4677 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
4680 doctokenizerYYsetStateParam();
4681 tok=doctokenizerYYlex();
4682 while (tok==TK_WORD) /* there is a parameter name */
4684 if (m_type==DocParamSect::Param)
4686 int typeSeparator = g_token->name.find('#'); // explicit type position
4687 if (typeSeparator!=-1)
4689 handleParameterType(this,m_paramTypes,g_token->name.left(typeSeparator));
4690 g_token->name = g_token->name.mid(typeSeparator+1);
4691 g_hasParamCommand=TRUE;
4692 checkArgumentName(g_token->name,TRUE);
4693 ((DocParamSect*)parent())->m_hasTypeSpecifier=TRUE;
4697 g_hasParamCommand=TRUE;
4698 checkArgumentName(g_token->name,TRUE);
4701 else if (m_type==DocParamSect::RetVal)
4703 g_hasReturnCommand=TRUE;
4704 checkArgumentName(g_token->name,FALSE);
4706 //m_params.append(g_token->name);
4707 handleLinkedWord(this,m_params);
4708 tok=doctokenizerYYlex();
4710 doctokenizerYYsetStatePara();
4711 if (tok==0) /* premature end of comment block */
4713 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
4714 "argument of command %s",qPrint(cmdName));
4718 ASSERT(tok==TK_WHITESPACE);
4720 par = new DocPara(this);
4721 m_paragraphs.append(par);
4722 retval = par->parse();
4727 DBG(("DocParamList::parse() end retval=%d\n",retval));
4728 DocNode *n=g_nodeStack.pop();
4733 int DocParamList::parseXml(const QCString ¶mName)
4735 int retval=RetVal_OK;
4736 DBG(("DocParamList::parseXml() start\n"));
4737 g_nodeStack.push(this);
4739 g_token->name = paramName;
4740 if (m_type==DocParamSect::Param)
4742 g_hasParamCommand=TRUE;
4743 checkArgumentName(g_token->name,TRUE);
4745 else if (m_type==DocParamSect::RetVal)
4747 g_hasReturnCommand=TRUE;
4748 checkArgumentName(g_token->name,FALSE);
4751 handleLinkedWord(this,m_params);
4755 DocPara *par = new DocPara(this);
4756 retval = par->parse();
4757 if (par->isEmpty()) // avoid adding an empty paragraph for the whitespace
4758 // after </para> and before </param>
4763 else // append the paragraph to the list
4765 if (m_paragraphs.isEmpty())
4771 m_paragraphs.getLast()->markLast(FALSE);
4774 m_paragraphs.append(par);
4777 if (retval == 0) break;
4779 } while (retval==RetVal_CloseXml &&
4780 Mappers::htmlTagMapper->map(g_token->name)!=XML_PARAM &&
4781 Mappers::htmlTagMapper->map(g_token->name)!=XML_TYPEPARAM &&
4782 Mappers::htmlTagMapper->map(g_token->name)!=XML_EXCEPTION);
4785 if (retval==0) /* premature end of comment block */
4787 warn_doc_error(g_fileName,doctokenizerYYlineno,"unterminated param or exception tag");
4795 DBG(("DocParamList::parse() end retval=%d\n",retval));
4796 DocNode *n=g_nodeStack.pop();
4801 //--------------------------------------------------------------------------
4803 int DocParamSect::parse(const QCString &cmdName,bool xmlContext, Direction d)
4805 int retval=RetVal_OK;
4806 DBG(("DocParamSect::parse() start\n"));
4807 g_nodeStack.push(this);
4811 m_hasInOutSpecifier=TRUE;
4814 DocParamList *pl = new DocParamList(this,m_type,d);
4815 if (m_children.isEmpty())
4822 ASSERT(m_children.getLast()->kind()==DocNode::Kind_ParamList);
4823 ((DocParamList *)m_children.getLast())->markLast(FALSE);
4826 m_children.append(pl);
4829 retval = pl->parseXml(cmdName);
4833 retval = pl->parse(cmdName);
4835 if (retval==RetVal_EndParBlock)
4840 DBG(("DocParamSect::parse() end retval=%d\n",retval));
4841 DocNode *n=g_nodeStack.pop();
4846 //--------------------------------------------------------------------------
4848 int DocPara::handleSimpleSection(DocSimpleSect::Type t, bool xmlContext)
4850 DocSimpleSect *ss=0;
4851 bool needsSeparator = FALSE;
4852 if (!m_children.isEmpty() && // previous element
4853 m_children.getLast()->kind()==Kind_SimpleSect && // was a simple sect
4854 ((DocSimpleSect *)m_children.getLast())->type()==t && // of same type
4855 t!=DocSimpleSect::User) // but not user defined
4857 // append to previous section
4858 ss=(DocSimpleSect *)m_children.getLast();
4859 needsSeparator = TRUE;
4861 else // start new section
4863 ss=new DocSimpleSect(this,t);
4864 m_children.append(ss);
4869 return ss->parseXml();
4873 rv = ss->parse(t==DocSimpleSect::User,needsSeparator);
4875 return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4878 int DocPara::handleParamSection(const QCString &cmdName,
4879 DocParamSect::Type t,
4880 bool xmlContext=FALSE,
4881 int direction=DocParamSect::Unspecified)
4884 if (!m_children.isEmpty() && // previous element
4885 m_children.getLast()->kind()==Kind_ParamSect && // was a param sect
4886 ((DocParamSect *)m_children.getLast())->type()==t) // of same type
4888 // append to previous section
4889 ps=(DocParamSect *)m_children.getLast();
4891 else // start new section
4893 ps=new DocParamSect(this,t);
4894 m_children.append(ps);
4896 int rv=ps->parse(cmdName,xmlContext,(DocParamSect::Direction)direction);
4897 return (rv!=TK_NEWPARA) ? rv : RetVal_OK;
4900 void DocPara::handleCite()
4902 // get the argument of the cite command.
4903 int tok=doctokenizerYYlex();
4904 if (tok!=TK_WHITESPACE)
4906 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
4910 doctokenizerYYsetStateCite();
4911 tok=doctokenizerYYlex();
4914 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
4915 "argument of command %s\n", qPrint("cite"));
4918 else if (tok!=TK_WORD && tok!=TK_LNKWORD)
4920 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
4921 tokToString(tok),qPrint("cite"));
4924 g_token->sectionId = g_token->name;
4925 DocCite *cite = new DocCite(this,g_token->name,g_context);
4926 m_children.append(cite);
4929 doctokenizerYYsetStatePara();
4932 int DocPara::handleXRefItem()
4934 int retval=doctokenizerYYlex();
4935 ASSERT(retval==TK_WHITESPACE);
4936 doctokenizerYYsetStateXRefItem();
4937 retval=doctokenizerYYlex();
4938 if (retval==RetVal_OK)
4940 DocXRefItem *ref = new DocXRefItem(this,g_token->id,g_token->name);
4943 m_children.append(ref);
4950 doctokenizerYYsetStatePara();
4954 void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type t)
4956 DBG(("handleIncludeOperator(%s)\n",qPrint(cmdName)));
4957 int tok=doctokenizerYYlex();
4958 if (tok!=TK_WHITESPACE)
4960 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
4964 doctokenizerYYsetStatePattern();
4965 tok=doctokenizerYYlex();
4966 doctokenizerYYsetStatePara();
4969 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
4970 "argument of command %s", qPrint(cmdName));
4973 else if (tok!=TK_WORD)
4975 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
4976 tokToString(tok),qPrint(cmdName));
4979 DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName);
4980 QListIterator<DocNode> it(m_children);
4981 DocNode *n1 = it.toLast();
4983 DocNode *n2 = n1!=0 ? it.current() : 0;
4984 bool isFirst = n1==0 || // no last node
4985 (n1->kind()!=DocNode::Kind_IncOperator &&
4986 n1->kind()!=DocNode::Kind_WhiteSpace
4987 ) || // last node is not operator or whitespace
4988 (n1->kind()==DocNode::Kind_WhiteSpace &&
4989 n2!=0 && n2->kind()!=DocNode::Kind_IncOperator
4990 ); // previous not is not operator
4991 op->markFirst(isFirst);
4993 if (n1!=0 && n1->kind()==DocNode::Kind_IncOperator)
4995 ((DocIncOperator *)n1)->markLast(FALSE);
4997 else if (n1!=0 && n1->kind()==DocNode::Kind_WhiteSpace &&
4998 n2!=0 && n2->kind()==DocNode::Kind_IncOperator
5001 ((DocIncOperator *)n2)->markLast(FALSE);
5003 m_children.append(op);
5007 void DocPara::handleImage(const QCString &cmdName)
5009 int tok=doctokenizerYYlex();
5010 if (tok!=TK_WHITESPACE)
5012 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5016 tok=doctokenizerYYlex();
5017 if (tok!=TK_WORD && tok!=TK_LNKWORD)
5019 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5020 tokToString(tok),qPrint(cmdName));
5023 tok=doctokenizerYYlex();
5024 if (tok!=TK_WHITESPACE)
5026 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5031 QCString imgType = g_token->name.lower();
5032 if (imgType=="html") t=DocImage::Html;
5033 else if (imgType=="latex") t=DocImage::Latex;
5034 else if (imgType=="docbook") t=DocImage::DocBook;
5035 else if (imgType=="rtf") t=DocImage::Rtf;
5038 warn_doc_error(g_fileName,doctokenizerYYlineno,"image type %s specified as the first argument of "
5040 qPrint(imgType),qPrint(cmdName));
5043 doctokenizerYYsetStateFile();
5044 tok=doctokenizerYYlex();
5045 doctokenizerYYsetStatePara();
5048 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5049 tokToString(tok),qPrint(cmdName));
5052 HtmlAttribList attrList;
5053 DocImage *img = new DocImage(this,attrList,findAndCopyImage(g_token->name,t),t);
5054 m_children.append(img);
5058 void DocPara::handleDotFile(const QCString &cmdName)
5060 int tok=doctokenizerYYlex();
5061 if (tok!=TK_WHITESPACE)
5063 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5067 doctokenizerYYsetStateFile();
5068 tok=doctokenizerYYlex();
5069 doctokenizerYYsetStatePara();
5072 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5073 tokToString(tok),qPrint(cmdName));
5076 QCString name = g_token->name;
5077 DocDotFile *df = new DocDotFile(this,name,g_context);
5078 m_children.append(df);
5082 void DocPara::handleMscFile(const QCString &cmdName)
5084 int tok=doctokenizerYYlex();
5085 if (tok!=TK_WHITESPACE)
5087 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5091 doctokenizerYYsetStateFile();
5092 tok=doctokenizerYYlex();
5093 doctokenizerYYsetStatePara();
5096 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5097 tokToString(tok),qPrint(cmdName));
5100 QCString name = g_token->name;
5101 DocMscFile *df = new DocMscFile(this,name,g_context);
5102 m_children.append(df);
5106 void DocPara::handleDiaFile(const QCString &cmdName)
5108 int tok=doctokenizerYYlex();
5109 if (tok!=TK_WHITESPACE)
5111 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5115 doctokenizerYYsetStateFile();
5116 tok=doctokenizerYYlex();
5117 doctokenizerYYsetStatePara();
5120 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5121 tokToString(tok),qPrint(cmdName));
5124 QCString name = g_token->name;
5125 DocDiaFile *df = new DocDiaFile(this,name,g_context);
5126 m_children.append(df);
5130 void DocPara::handleVhdlFlow()
5132 DocVhdlFlow *vf = new DocVhdlFlow(this);
5133 m_children.append(vf);
5137 void DocPara::handleLink(const QCString &cmdName,bool isJavaLink)
5139 int tok=doctokenizerYYlex();
5140 if (tok!=TK_WHITESPACE)
5142 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5146 doctokenizerYYsetStateLink();
5147 tok=doctokenizerYYlex();
5150 warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s",
5151 tokToString(tok),qPrint(cmdName));
5154 doctokenizerYYsetStatePara();
5155 DocLink *lnk = new DocLink(this,g_token->name);
5156 m_children.append(lnk);
5157 QCString leftOver = lnk->parse(isJavaLink);
5158 if (!leftOver.isEmpty())
5160 m_children.append(new DocWord(this,leftOver));
5164 void DocPara::handleRef(const QCString &cmdName)
5166 DBG(("handleRef(%s)\n",qPrint(cmdName)));
5167 int tok=doctokenizerYYlex();
5168 if (tok!=TK_WHITESPACE)
5170 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5174 doctokenizerYYsetStateRef();
5175 tok=doctokenizerYYlex(); // get the reference id
5179 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5180 tokToString(tok),qPrint(cmdName));
5183 ref = new DocRef(this,g_token->name,g_context);
5184 m_children.append(ref);
5187 doctokenizerYYsetStatePara();
5191 void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t)
5193 DBG(("handleInclude(%s)\n",qPrint(cmdName)));
5194 int tok=doctokenizerYYlex();
5195 if (tok!=TK_WHITESPACE)
5197 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5201 doctokenizerYYsetStateFile();
5202 tok=doctokenizerYYlex();
5203 doctokenizerYYsetStatePara();
5206 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
5207 "argument of command %s",qPrint(cmdName));
5210 else if (tok!=TK_WORD)
5212 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5213 tokToString(tok),qPrint(cmdName));
5216 QCString fileName = g_token->name;
5218 if (t==DocInclude::Snippet)
5220 doctokenizerYYsetStateSnippet();
5221 tok=doctokenizerYYlex();
5222 doctokenizerYYsetStatePara();
5225 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command",
5226 tokToString(tok),qPrint(cmdName));
5229 blockId = "["+g_token->name+"]";
5231 DocInclude *inc = new DocInclude(this,fileName,g_context,t,g_isExample,g_exampleName,blockId);
5232 m_children.append(inc);
5236 void DocPara::handleSection(const QCString &cmdName)
5238 // get the argument of the section command.
5239 int tok=doctokenizerYYlex();
5240 if (tok!=TK_WHITESPACE)
5242 warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
5246 tok=doctokenizerYYlex();
5249 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
5250 "argument of command %s\n", qPrint(cmdName));
5253 else if (tok!=TK_WORD && tok!=TK_LNKWORD)
5255 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
5256 tokToString(tok),qPrint(cmdName));
5259 g_token->sectionId = g_token->name;
5260 doctokenizerYYsetStateSkipTitle();
5261 doctokenizerYYlex();
5262 doctokenizerYYsetStatePara();
5265 int DocPara::handleHtmlHeader(const HtmlAttribList &tagHtmlAttribs,int level)
5267 DocHtmlHeader *header = new DocHtmlHeader(this,tagHtmlAttribs,level);
5268 m_children.append(header);
5269 int retval = header->parse();
5270 return (retval==RetVal_OK) ? TK_NEWPARA : retval;
5273 // For XML tags whose content is stored in attributes rather than
5274 // contained within the element, we need a way to inject the attribute
5275 // text into the current paragraph.
5276 bool DocPara::injectToken(int tok,const QCString &tokText)
5278 g_token->name = tokText;
5279 return defaultHandleToken(this,tok,m_children);
5282 int DocPara::handleStartCode()
5284 int retval = doctokenizerYYlex();
5285 QCString lang = g_token->name;
5286 if (!lang.isEmpty() && lang.at(0)!='.')
5290 // search for the first non-whitespace line, index is stored in li
5291 int i=0,li=0,l=g_token->verb.length();
5292 while (i<l && (g_token->verb.at(i)==' ' || g_token->verb.at(i)=='\n'))
5294 if (g_token->verb.at(i)=='\n') li=i+1;
5297 m_children.append(new DocVerbatim(this,g_context,stripIndentation(g_token->verb.mid(li)),DocVerbatim::Code,g_isExample,g_exampleName,FALSE,lang));
5298 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"code section ended without end marker");
5299 doctokenizerYYsetStatePara();
5303 void DocPara::handleInheritDoc()
5305 if (g_memberDef) // inheriting docs from a member
5307 MemberDef *reMd = g_memberDef->reimplements();
5308 if (reMd) // member from which was inherited.
5310 MemberDef *thisMd = g_memberDef;
5311 //printf("{InheritDocs:%s=>%s}\n",g_memberDef->qualifiedName().data(),reMd->qualifiedName().data());
5312 docParserPushContext();
5313 g_scope=reMd->getOuterScope();
5314 if (g_scope!=Doxygen::globalScope)
5316 g_context=g_scope->name();
5319 g_styleStack.clear();
5320 g_nodeStack.clear();
5321 g_copyStack.append(reMd);
5322 internalValidatingParseDoc(this,m_children,reMd->briefDescription());
5323 internalValidatingParseDoc(this,m_children,reMd->documentation());
5324 g_copyStack.remove(reMd);
5325 docParserPopContext(TRUE);
5326 g_memberDef = thisMd;
5332 int DocPara::handleCommand(const QCString &cmdName)
5334 DBG(("handleCommand(%s)\n",qPrint(cmdName)));
5335 int retval = RetVal_OK;
5336 int cmdId = Mappers::cmdMapper->map(cmdName);
5340 warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unknown command `\\%s'",qPrint(cmdName));
5343 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
5344 retval=handleStyleArgument(this,m_children,cmdName);
5345 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
5346 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
5349 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
5350 retval=handleStyleArgument(this,m_children,cmdName);
5351 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
5352 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
5355 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,TRUE));
5356 retval=handleStyleArgument(this,m_children,cmdName);
5357 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,FALSE));
5358 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
5361 m_children.append(new DocSymbol(this,DocSymbol::Sym_BSlash));
5364 m_children.append(new DocSymbol(this,DocSymbol::Sym_At));
5367 m_children.append(new DocSymbol(this,DocSymbol::Sym_Less));
5370 m_children.append(new DocSymbol(this,DocSymbol::Sym_Greater));
5373 m_children.append(new DocSymbol(this,DocSymbol::Sym_Amp));
5376 m_children.append(new DocSymbol(this,DocSymbol::Sym_Dollar));
5379 m_children.append(new DocSymbol(this,DocSymbol::Sym_Hash));
5382 m_children.append(new DocSymbol(this,DocSymbol::Sym_Pipe));
5385 m_children.append(new DocSymbol(this,DocSymbol::Sym_DoubleColon));
5388 m_children.append(new DocSymbol(this,DocSymbol::Sym_Percent));
5391 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5392 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5395 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5396 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5397 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
5400 m_children.append(new DocSymbol(this,DocSymbol::Sym_Quot));
5404 retval = handleSimpleSection(DocSimpleSect::See);
5408 retval = handleSimpleSection(DocSimpleSect::Return);
5409 g_hasReturnCommand=TRUE;
5412 retval = handleSimpleSection(DocSimpleSect::Author);
5415 retval = handleSimpleSection(DocSimpleSect::Authors);
5418 retval = handleSimpleSection(DocSimpleSect::Version);
5421 retval = handleSimpleSection(DocSimpleSect::Since);
5424 retval = handleSimpleSection(DocSimpleSect::Date);
5427 retval = handleSimpleSection(DocSimpleSect::Note);
5430 retval = handleSimpleSection(DocSimpleSect::Warning);
5433 retval = handleSimpleSection(DocSimpleSect::Pre);
5436 retval = handleSimpleSection(DocSimpleSect::Post);
5439 retval = handleSimpleSection(DocSimpleSect::Copyright);
5442 retval = handleSimpleSection(DocSimpleSect::Invar);
5445 retval = handleSimpleSection(DocSimpleSect::Remark);
5448 retval = handleSimpleSection(DocSimpleSect::Attention);
5451 retval = handleSimpleSection(DocSimpleSect::User);
5455 DocSimpleList *sl=new DocSimpleList(this);
5456 m_children.append(sl);
5457 retval = sl->parse();
5462 handleSection(cmdName);
5463 retval = RetVal_Section;
5466 case CMD_SUBSECTION:
5468 handleSection(cmdName);
5469 retval = RetVal_Subsection;
5472 case CMD_SUBSUBSECTION:
5474 handleSection(cmdName);
5475 retval = RetVal_Subsubsection;
5480 handleSection(cmdName);
5481 retval = RetVal_Paragraph;
5486 doctokenizerYYsetStateCode();
5487 retval = handleStartCode();
5492 doctokenizerYYsetStateHtmlOnly();
5493 retval = doctokenizerYYlex();
5494 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block"));
5495 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker");
5496 doctokenizerYYsetStatePara();
5501 doctokenizerYYsetStateManOnly();
5502 retval = doctokenizerYYlex();
5503 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName));
5504 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker");
5505 doctokenizerYYsetStatePara();
5510 doctokenizerYYsetStateRtfOnly();
5511 retval = doctokenizerYYlex();
5512 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName));
5513 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker");
5514 doctokenizerYYsetStatePara();
5519 doctokenizerYYsetStateLatexOnly();
5520 retval = doctokenizerYYlex();
5521 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName));
5522 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker");
5523 doctokenizerYYsetStatePara();
5528 doctokenizerYYsetStateXmlOnly();
5529 retval = doctokenizerYYlex();
5530 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName));
5531 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker");
5532 doctokenizerYYsetStatePara();
5537 doctokenizerYYsetStateDbOnly();
5538 retval = doctokenizerYYlex();
5539 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName));
5540 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker",doctokenizerYYlineno);
5541 doctokenizerYYsetStatePara();
5546 doctokenizerYYsetStateVerbatim();
5547 retval = doctokenizerYYlex();
5548 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Verbatim,g_isExample,g_exampleName));
5549 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"verbatim section ended without end marker");
5550 doctokenizerYYsetStatePara();
5555 doctokenizerYYsetStateDot();
5556 retval = doctokenizerYYlex();
5557 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Dot,g_isExample,g_exampleName));
5558 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"dot section ended without end marker");
5559 doctokenizerYYsetStatePara();
5564 doctokenizerYYsetStateMsc();
5565 retval = doctokenizerYYlex();
5566 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName));
5567 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"msc section ended without end marker");
5568 doctokenizerYYsetStatePara();
5573 static QCString jarPath = Config_getString("PLANTUML_JAR_PATH");
5574 doctokenizerYYsetStatePlantUML();
5575 retval = doctokenizerYYlex();
5576 if (jarPath.isEmpty())
5578 warn_doc_error(g_fileName,doctokenizerYYlineno,"ignoring startuml command because PLANTUML_JAR_PATH is not set");
5582 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::PlantUML,FALSE,g_token->sectionId));
5584 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"startuml section ended without end marker");
5585 doctokenizerYYsetStatePara();
5588 case CMD_ENDPARBLOCK:
5589 retval=RetVal_EndParBlock;
5592 case CMD_ENDHTMLONLY:
5593 case CMD_ENDMANONLY:
5594 case CMD_ENDRTFONLY:
5595 case CMD_ENDLATEXONLY:
5596 case CMD_ENDXMLONLY:
5599 case CMD_ENDVERBATIM:
5603 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5606 retval = handleParamSection(cmdName,DocParamSect::Param,FALSE,g_token->paramDir);
5609 retval = handleParamSection(cmdName,DocParamSect::TemplateParam,FALSE,g_token->paramDir);
5612 retval = handleParamSection(cmdName,DocParamSect::RetVal);
5615 retval = handleParamSection(cmdName,DocParamSect::Exception);
5618 retval = handleXRefItem();
5622 DocLineBreak *lb = new DocLineBreak(this);
5623 m_children.append(lb);
5628 DocAnchor *anchor = handleAnchor(this);
5631 m_children.append(anchor);
5637 DocIndexEntry *ie = new DocIndexEntry(this,
5638 g_scope!=Doxygen::globalScope?g_scope:0,
5640 m_children.append(ie);
5641 retval = ie->parse();
5645 retval = RetVal_Internal;
5647 case CMD_ENDINTERNAL:
5648 retval = RetVal_EndInternal;
5652 DocParBlock *block = new DocParBlock(this);
5653 m_children.append(block);
5654 retval = block->parse();
5657 case CMD_COPYDOC: // fall through
5658 case CMD_COPYBRIEF: // fall through
5659 case CMD_COPYDETAILS:
5660 //retval = RetVal_CopyDoc;
5661 // these commands should already be resolved by processCopyDoc()
5664 handleInclude(cmdName,DocInclude::Include);
5666 case CMD_INCWITHLINES:
5667 handleInclude(cmdName,DocInclude::IncWithLines);
5669 case CMD_DONTINCLUDE:
5670 handleInclude(cmdName,DocInclude::DontInclude);
5672 case CMD_HTMLINCLUDE:
5673 handleInclude(cmdName,DocInclude::HtmlInclude);
5675 case CMD_LATEXINCLUDE:
5676 handleInclude(cmdName,DocInclude::LatexInclude);
5678 case CMD_VERBINCLUDE:
5679 handleInclude(cmdName,DocInclude::VerbInclude);
5682 handleInclude(cmdName,DocInclude::Snippet);
5685 handleIncludeOperator(cmdName,DocIncOperator::Skip);
5688 handleIncludeOperator(cmdName,DocIncOperator::Until);
5691 handleIncludeOperator(cmdName,DocIncOperator::SkipLine);
5694 handleIncludeOperator(cmdName,DocIncOperator::Line);
5697 handleImage(cmdName);
5700 handleDotFile(cmdName);
5706 handleMscFile(cmdName);
5709 handleDiaFile(cmdName);
5712 handleLink(cmdName,FALSE);
5715 handleLink(cmdName,TRUE);
5720 case CMD_REF: // fall through
5724 case CMD_SECREFLIST:
5726 DocSecRefList *list = new DocSecRefList(this);
5727 m_children.append(list);
5731 case CMD_SECREFITEM:
5732 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5734 case CMD_ENDSECREFLIST:
5735 warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5739 DocFormula *form=new DocFormula(this,g_token->id);
5740 m_children.append(form);
5743 //case CMD_LANGSWITCH:
5744 // retval = handleLanguageSwitch();
5746 case CMD_INTERNALREF:
5747 //warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
5749 DocInternalRef *ref = handleInternalRef(this);
5752 m_children.append(ref);
5755 doctokenizerYYsetStatePara();
5758 case CMD_INHERITDOC:
5762 // we should not get here!
5766 INTERNAL_ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec ||
5767 retval==TK_LISTITEM || retval==TK_ENDLIST || retval==TK_NEWPARA ||
5768 retval==RetVal_Section || retval==RetVal_EndList ||
5769 retval==RetVal_Internal || retval==RetVal_SwitchLang ||
5770 retval==RetVal_EndInternal
5772 DBG(("handleCommand(%s) end retval=%x\n",qPrint(cmdName),retval));
5776 static bool findAttribute(const HtmlAttribList &tagHtmlAttribs,
5777 const char *attrName,
5781 HtmlAttribListIterator li(tagHtmlAttribs);
5783 for (li.toFirst();(opt=li.current());++li)
5785 if (opt->name==attrName)
5787 *result = opt->value;
5794 int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &tagHtmlAttribs)
5796 DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.count()));
5797 int retval=RetVal_OK;
5798 int tagId = Mappers::htmlTagMapper->map(tagName);
5799 if (g_token->emptyTag && !(tagId&XML_CmdMask) &&
5800 tagId!=HTML_UNKNOWN && tagId!=HTML_IMG && tagId!=HTML_BR)
5802 warn_doc_error(g_fileName,doctokenizerYYlineno,"HTML tags may not use the 'empty tag' XHTML syntax.");
5808 DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Unordered);
5809 m_children.append(list);
5810 retval=list->parse();
5815 DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Ordered);
5816 m_children.append(list);
5817 retval=list->parse();
5821 if (!insideUL(this) && !insideOL(this))
5823 warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <li> tag found");
5827 retval=RetVal_ListItem;
5831 handleStyleEnter(this,m_children,DocStyleChange::Bold,&g_token->attribs);
5834 if (/*getLanguageFromFileName(g_fileName)==SrcLangExt_CSharp ||*/ g_xmlComment)
5835 // for C# source or inside a <summary> or <remark> section we
5836 // treat <code> as an XML tag (so similar to @code)
5838 doctokenizerYYsetStateXmlCode();
5839 retval = handleStartCode();
5841 else // normal HTML markup
5843 handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs);
5847 handleStyleEnter(this,m_children,DocStyleChange::Italic,&g_token->attribs);
5850 handleStyleEnter(this,m_children,DocStyleChange::Div,&g_token->attribs);
5853 handleStyleEnter(this,m_children,DocStyleChange::Span,&g_token->attribs);
5856 handleStyleEnter(this,m_children,DocStyleChange::Subscript,&g_token->attribs);
5859 handleStyleEnter(this,m_children,DocStyleChange::Superscript,&g_token->attribs);
5862 handleStyleEnter(this,m_children,DocStyleChange::Center,&g_token->attribs);
5865 handleStyleEnter(this,m_children,DocStyleChange::Small,&g_token->attribs);
5868 handleStyleEnter(this,m_children,DocStyleChange::Preformatted,&g_token->attribs);
5869 setInsidePreformatted(TRUE);
5870 doctokenizerYYsetInsidePre(TRUE);
5877 DocHtmlDescList *list = new DocHtmlDescList(this,tagHtmlAttribs);
5878 m_children.append(list);
5879 retval=list->parse();
5883 retval = RetVal_DescTitle;
5886 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <dd> found");
5890 DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs);
5891 m_children.append(table);
5892 retval=table->parse();
5896 retval = RetVal_TableRow;
5899 retval = RetVal_TableCell;
5902 retval = RetVal_TableHCell;
5905 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <caption> found");
5909 DocLineBreak *lb = new DocLineBreak(this);
5910 m_children.append(lb);
5915 DocHorRuler *hr = new DocHorRuler(this);
5916 m_children.append(hr);
5920 retval=handleAHref(this,m_children,tagHtmlAttribs);
5923 retval=handleHtmlHeader(tagHtmlAttribs,1);
5926 retval=handleHtmlHeader(tagHtmlAttribs,2);
5929 retval=handleHtmlHeader(tagHtmlAttribs,3);
5932 retval=handleHtmlHeader(tagHtmlAttribs,4);
5935 retval=handleHtmlHeader(tagHtmlAttribs,5);
5938 retval=handleHtmlHeader(tagHtmlAttribs,6);
5942 handleImg(this,m_children,tagHtmlAttribs);
5945 case HTML_BLOCKQUOTE:
5947 DocHtmlBlockQuote *block = new DocHtmlBlockQuote(this,tagHtmlAttribs);
5948 m_children.append(block);
5949 retval = block->parse();
5959 if (!m_children.isEmpty())
5961 retval = TK_NEWPARA;
5965 case XML_DESCRIPTION:
5966 if (insideTable(this))
5968 retval=RetVal_TableCell;
5972 handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs);
5978 if (findAttribute(tagHtmlAttribs,"name",¶mName))
5980 if (paramName.isEmpty())
5982 if (Config_getBool("WARN_NO_PARAMDOC"))
5984 warn_doc_error(g_fileName,doctokenizerYYlineno,"empty 'name' attribute for <param> tag.");
5989 retval = handleParamSection(paramName,
5990 tagId==XML_PARAM ? DocParamSect::Param : DocParamSect::TemplateParam,
5996 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param> tag.");
6001 case XML_TYPEPARAMREF:
6004 if (findAttribute(tagHtmlAttribs,"name",¶mName))
6006 //printf("paramName=%s\n",paramName.data());
6007 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE));
6008 m_children.append(new DocWord(this,paramName));
6009 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE));
6010 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," "));
6014 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type");
6020 QCString exceptName;
6021 if (findAttribute(tagHtmlAttribs,"cref",&exceptName))
6023 retval = handleParamSection(exceptName,DocParamSect::Exception,TRUE);
6027 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <exception> tag.");
6032 case XML_LISTHEADER:
6033 if (insideTable(this))
6035 retval=RetVal_TableRow;
6037 else if (insideUL(this) || insideOL(this))
6039 retval=RetVal_ListItem;
6043 warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <item> tag found");
6047 retval = handleSimpleSection(DocSimpleSect::Return,TRUE);
6048 g_hasReturnCommand=TRUE;
6051 //m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE));
6052 if (insideTable(this))
6054 retval=RetVal_TableCell;
6058 // I'm not sure if <see> is the same as <seealso> or if it
6059 // should you link a member without producing a section. The
6060 // C# specification is extremely vague about this (but what else
6061 // can we expect from Microsoft...)
6064 //printf("XML_SEE: empty tag=%d\n",g_token->emptyTag);
6065 if (findAttribute(tagHtmlAttribs,"cref",&cref))
6067 if (g_token->emptyTag) // <see cref="..."/> style
6069 bool inSeeBlock = g_inSeeBlock;
6070 g_token->name = cref;
6071 g_inSeeBlock = TRUE;
6072 handleLinkedWord(this,m_children);
6073 g_inSeeBlock = inSeeBlock;
6075 else // <see cref="...">...</see> style
6077 //DocRef *ref = new DocRef(this,cref);
6078 //m_children.append(ref);
6080 doctokenizerYYsetStatePara();
6081 DocLink *lnk = new DocLink(this,cref);
6082 m_children.append(lnk);
6083 QCString leftOver = lnk->parse(FALSE,TRUE);
6084 if (!leftOver.isEmpty())
6086 m_children.append(new DocWord(this,leftOver));
6092 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <see> tag.");
6099 if (findAttribute(tagHtmlAttribs,"cref",&cref))
6101 // Look for an existing "see" section
6102 DocSimpleSect *ss=0;
6103 QListIterator<DocNode> cli(m_children);
6105 for (cli.toFirst();(n=cli.current());++cli)
6107 if (n->kind()==Kind_SimpleSect && ((DocSimpleSect *)n)->type()==DocSimpleSect::See)
6109 ss = (DocSimpleSect *)n;
6113 if (!ss) // start new section
6115 ss=new DocSimpleSect(this,DocSimpleSect::See);
6116 m_children.append(ss);
6119 ss->appendLinkWord(cref);
6124 warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <seealso> tag.");
6131 findAttribute(tagHtmlAttribs,"type",&type);
6132 DocHtmlList::Type listType = DocHtmlList::Unordered;
6133 HtmlAttribList emptyList;
6136 listType=DocHtmlList::Ordered;
6140 DocHtmlTable *table = new DocHtmlTable(this,emptyList);
6141 m_children.append(table);
6142 retval=table->parseXml();
6146 DocHtmlList *list = new DocHtmlList(this,emptyList,listType);
6147 m_children.append(list);
6148 retval=list->parseXml();
6153 case XML_PERMISSION:
6154 // These tags are defined in .Net but are currently unsupported
6157 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag <%s> found", qPrint(tagName));
6158 m_children.append(new DocWord(this, "<"+tagName+tagHtmlAttribs.toString()+">"));
6160 case XML_INHERITDOC:
6165 // we should not get here!
6172 int DocPara::handleHtmlEndTag(const QCString &tagName)
6174 DBG(("handleHtmlEndTag(%s)\n",qPrint(tagName)));
6175 int tagId = Mappers::htmlTagMapper->map(tagName);
6176 int retval=RetVal_OK;
6180 if (!insideUL(this))
6182 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ul> tag without matching <ul>");
6186 retval=RetVal_EndList;
6190 if (!insideOL(this))
6192 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ol> tag without matching <ol>");
6196 retval=RetVal_EndList;
6200 if (!insideLI(this))
6202 warn_doc_error(g_fileName,doctokenizerYYlineno,"found </li> tag without matching <li>");
6206 // ignore </li> tags
6209 case HTML_BLOCKQUOTE:
6210 retval=RetVal_EndBlockQuote;
6213 // if (!insidePRE(this))
6215 // warn_doc_error(g_fileName,doctokenizerYYlineno,"found </pre> tag without matching <pre>");
6219 // retval=RetVal_EndPre;
6223 handleStyleLeave(this,m_children,DocStyleChange::Bold,"b");
6226 handleStyleLeave(this,m_children,DocStyleChange::Code,"code");
6229 handleStyleLeave(this,m_children,DocStyleChange::Italic,"em");
6232 handleStyleLeave(this,m_children,DocStyleChange::Div,"div");
6235 handleStyleLeave(this,m_children,DocStyleChange::Span,"span");
6238 handleStyleLeave(this,m_children,DocStyleChange::Subscript,"sub");
6241 handleStyleLeave(this,m_children,DocStyleChange::Superscript,"sup");
6244 handleStyleLeave(this,m_children,DocStyleChange::Center,"center");
6247 handleStyleLeave(this,m_children,DocStyleChange::Small,"small");
6250 handleStyleLeave(this,m_children,DocStyleChange::Preformatted,"pre");
6251 setInsidePreformatted(FALSE);
6252 doctokenizerYYsetInsidePre(FALSE);
6258 retval=RetVal_EndDesc;
6267 retval=RetVal_EndTable;
6279 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </caption> found");
6282 warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal </br> tag found\n");
6285 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h1> found");
6288 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h2> found");
6291 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h3> found");
6294 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h4> found");
6297 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h5> found");
6300 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h6> found");
6303 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </img> found");
6306 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </hr> found");
6309 //warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </a> found");
6310 // ignore </a> tag (can be part of <a name=...></a>
6314 //m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
6328 case XML_INHERITDOC:
6329 retval = RetVal_CloseXml;
6332 handleStyleLeave(this,m_children,DocStyleChange::Code,"c");
6335 case XML_LISTHEADER:
6337 case XML_PERMISSION:
6338 case XML_DESCRIPTION:
6340 case XML_TYPEPARAMREF:
6341 // These tags are defined in .Net but are currently unsupported
6344 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag </%s> found", qPrint(tagName));
6345 m_children.append(new DocWord(this,"</"+tagName+">"));
6348 // we should not get here!
6349 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end tag %s\n",qPrint(tagName));
6356 int DocPara::parse()
6358 DBG(("DocPara::parse() start\n"));
6359 g_nodeStack.push(this);
6360 // handle style commands "inherited" from the previous paragraph
6361 handleInitialStyleCommands(this,m_children);
6364 while ((tok=doctokenizerYYlex())) // get the next token
6367 DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
6368 if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
6369 tok==TK_COMMAND || tok==TK_HTMLTAG
6372 DBG((" name=%s",qPrint(g_token->name)));
6378 m_children.append(new DocWord(this,g_token->name));
6381 handleLinkedWord(this,m_children);
6384 m_children.append(new DocURL(this,g_token->name,g_token->isEMailAddr));
6388 // prevent leading whitespace and collapse multiple whitespace areas
6390 if (insidePRE(this) || // all whitespace is relevant
6392 // remove leading whitespace
6393 !m_children.isEmpty() &&
6394 // and whitespace after certain constructs
6395 (k=m_children.getLast()->kind())!=DocNode::Kind_HtmlDescList &&
6396 k!=DocNode::Kind_HtmlTable &&
6397 k!=DocNode::Kind_HtmlList &&
6398 k!=DocNode::Kind_SimpleSect &&
6399 k!=DocNode::Kind_AutoList &&
6400 k!=DocNode::Kind_SimpleList &&
6401 /*k!=DocNode::Kind_Verbatim &&*/
6402 k!=DocNode::Kind_HtmlHeader &&
6403 k!=DocNode::Kind_HtmlBlockQuote &&
6404 k!=DocNode::Kind_ParamSect &&
6405 k!=DocNode::Kind_XRefItem
6409 m_children.append(new DocWhiteSpace(this,g_token->chars));
6415 DBG(("found list item at %d parent=%d\n",g_token->indent,parent()->kind()));
6416 DocNode *n=parent();
6417 while (n && n->kind()!=DocNode::Kind_AutoList) n=n->parent();
6418 if (n) // we found an auto list up in the hierarchy
6420 DocAutoList *al = (DocAutoList *)n;
6421 DBG(("previous list item at %d\n",al->indent()));
6422 if (al->indent()>=g_token->indent)
6423 // new item at the same or lower indent level
6430 // determine list depth
6435 if (n->kind() == DocNode::Kind_AutoList &&
6436 ((DocAutoList*)n)->isEnumList()) depth++;
6440 // first item or sub list => create new list
6444 al = new DocAutoList(this,g_token->indent,
6445 g_token->isEnumList,depth);
6446 m_children.append(al);
6447 retval = al->parse();
6448 } while (retval==TK_LISTITEM && // new list
6449 al->indent()==g_token->indent // at same indent level
6452 // check the return value
6453 if (retval==RetVal_SimpleSec) // auto list ended due to simple section command
6455 // Reparse the token that ended the section at this level,
6456 // so a new simple section will be started at this level.
6457 // This is the same as unputting the last read token and continuing.
6458 g_token->name = g_token->simpleSectName;
6459 if (g_token->name.left(4)=="rcs:") // RCS section
6461 g_token->name = g_token->name.mid(4);
6462 g_token->text = g_token->simpleSectText;
6465 else // other section
6469 DBG(("reparsing command %s\n",qPrint(g_token->name)));
6472 else if (retval==TK_ENDLIST)
6474 if (al->indent()>g_token->indent) // end list
6478 else // continue with current paragraph
6482 else // paragraph ended due to TK_NEWPARA, TK_LISTITEM, or EOF
6489 DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno));
6490 if (parent()->kind()==DocNode::Kind_AutoListItem)
6492 ASSERT(parent()->parent()->kind()==DocNode::Kind_AutoList);
6493 DocAutoList *al = (DocAutoList *)parent()->parent();
6494 if (al->indent()>=g_token->indent)
6496 // end of list marker ends this paragraph
6502 warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found "
6503 "has invalid indent level");
6508 warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found without any preceding "
6514 // see if we have to start a simple section
6515 int cmd = Mappers::cmdMapper->map(g_token->name);
6516 DocNode *n=parent();
6518 n->kind()!=DocNode::Kind_SimpleSect &&
6519 n->kind()!=DocNode::Kind_ParamSect
6524 if (cmd&SIMPLESECT_BIT)
6526 if (n) // already in a simple section
6528 // simple section cannot start in this paragraph, need
6529 // to unwind the stack and remember the command.
6530 g_token->simpleSectName = g_token->name.copy();
6531 retval=RetVal_SimpleSec;
6535 // see if we are in a simple list
6537 while (n && n->kind()!=DocNode::Kind_SimpleListItem) n=n->parent();
6542 retval=RetVal_ListItem;
6547 // handle the command
6548 retval=handleCommand(g_token->name);
6549 DBG(("handleCommand returns %x\n",retval));
6551 // check the return value
6552 if (retval==RetVal_SimpleSec)
6554 // Reparse the token that ended the section at this level,
6555 // so a new simple section will be started at this level.
6556 // This is the same as unputting the last read token and continuing.
6557 g_token->name = g_token->simpleSectName;
6558 if (g_token->name.left(4)=="rcs:") // RCS section
6560 g_token->name = g_token->name.mid(4);
6561 g_token->text = g_token->simpleSectText;
6564 else // other section
6568 DBG(("reparsing command %s\n",qPrint(g_token->name)));
6571 else if (retval==RetVal_OK)
6573 // the command ended normally, keep scanning for new tokens.
6576 else if (retval>0 && retval<RetVal_OK)
6578 // the command ended with a new command, reparse this token
6582 else // end of file, end of paragraph, start or end of section
6583 // or some auto list marker
6591 if (!g_token->endTag) // found a start tag
6593 retval = handleHtmlStartTag(g_token->name,g_token->attribs);
6595 else // found an end tag
6597 retval = handleHtmlEndTag(g_token->name);
6599 if (retval==RetVal_OK)
6601 // the command ended normally, keep scanner for new tokens.
6612 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name);
6613 if (s!=DocSymbol::Sym_Unknown)
6615 m_children.append(new DocSymbol(this,s));
6619 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
6620 qPrint(g_token->name));
6629 DocNode *n=parent();
6631 n->kind()!=DocNode::Kind_SimpleSect &&
6632 n->kind()!=DocNode::Kind_ParamSect
6637 if (n) // already in a simple section
6639 // simple section cannot start in this paragraph, need
6640 // to unwind the stack and remember the command.
6641 g_token->simpleSectName = "rcs:"+g_token->name;
6642 g_token->simpleSectText = g_token->text;
6643 retval=RetVal_SimpleSec;
6647 // see if we are in a simple list
6648 DocSimpleSect *ss=new DocSimpleSect(this,DocSimpleSect::Rcs);
6649 m_children.append(ss);
6654 warn_doc_error(g_fileName,doctokenizerYYlineno,
6655 "Found unexpected token (id=%x)\n",tok);
6661 handlePendingStyleCommands(this,m_children);
6662 DocNode *n = g_nodeStack.pop();
6664 DBG(("DocPara::parse() end retval=%x\n",retval));
6665 INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM ||
6666 retval==TK_ENDLIST || retval>RetVal_OK
6672 //--------------------------------------------------------------------------
6674 int DocSection::parse()
6676 DBG(("DocSection::parse() start %s level=%d\n",qPrint(g_token->sectionId),m_level));
6677 int retval=RetVal_OK;
6678 g_nodeStack.push(this);
6681 if (!m_id.isEmpty())
6683 sec=Doxygen::sectionDict->find(m_id);
6686 m_file = sec->fileName;
6687 m_anchor = sec->label;
6688 m_title = sec->title;
6689 if (m_title.isEmpty()) m_title = sec->label;
6690 if (g_sectionDict && g_sectionDict->find(m_id)==0)
6692 g_sectionDict->append(m_id,sec);
6697 // first parse any number of paragraphs
6702 DocPara *par = new DocPara(this);
6703 if (isFirst) { par->markFirst(); isFirst=FALSE; }
6704 retval=par->parse();
6705 if (!par->isEmpty())
6707 m_children.append(par);
6714 if (retval==TK_LISTITEM)
6716 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found");
6718 if (retval==RetVal_Internal)
6720 DocInternal *in = new DocInternal(this);
6721 m_children.append(in);
6722 retval = in->parse(m_level+1);
6723 if (retval==RetVal_EndInternal)
6728 } while (retval!=0 &&
6729 retval!=RetVal_Section &&
6730 retval!=RetVal_Subsection &&
6731 retval!=RetVal_Subsubsection &&
6732 retval!=RetVal_Paragraph &&
6733 retval!=RetVal_EndInternal
6736 if (lastPar) lastPar->markLast();
6738 //printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel);
6740 if (retval==RetVal_Subsection && m_level==Doxygen::subpageNestingLevel+1)
6742 // then parse any number of nested sections
6743 while (retval==RetVal_Subsection) // more sections follow
6745 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
6746 DocSection *s=new DocSection(this,
6747 QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6748 m_children.append(s);
6749 retval = s->parse();
6752 else if (retval==RetVal_Subsubsection && m_level==Doxygen::subpageNestingLevel+2)
6754 // then parse any number of nested sections
6755 while (retval==RetVal_Subsubsection) // more sections follow
6757 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
6758 DocSection *s=new DocSection(this,
6759 QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6760 m_children.append(s);
6761 retval = s->parse();
6764 else if (retval==RetVal_Paragraph && m_level==QMIN(5,Doxygen::subpageNestingLevel+3))
6766 // then parse any number of nested sections
6767 while (retval==RetVal_Paragraph) // more sections follow
6769 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
6770 DocSection *s=new DocSection(this,
6771 QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6772 m_children.append(s);
6773 retval = s->parse();
6776 else if ((m_level<=1+Doxygen::subpageNestingLevel && retval==RetVal_Subsubsection) ||
6777 (m_level<=2+Doxygen::subpageNestingLevel && retval==RetVal_Paragraph)
6781 if (retval==RetVal_Subsection) level=2;
6782 else if (retval==RetVal_Subsubsection) level=3;
6784 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected %s "
6785 "command found inside %s!",
6786 sectionLevelToName[level],sectionLevelToName[m_level]);
6787 retval=0; // stop parsing
6794 INTERNAL_ASSERT(retval==0 ||
6795 retval==RetVal_Section ||
6796 retval==RetVal_Subsection ||
6797 retval==RetVal_Subsubsection ||
6798 retval==RetVal_Paragraph ||
6799 retval==RetVal_Internal ||
6800 retval==RetVal_EndInternal
6803 DBG(("DocSection::parse() end: retval=%x\n",retval));
6804 DocNode *n = g_nodeStack.pop();
6809 //--------------------------------------------------------------------------
6811 void DocText::parse()
6813 DBG(("DocText::parse() start\n"));
6814 g_nodeStack.push(this);
6815 doctokenizerYYsetStateText();
6818 while ((tok=doctokenizerYYlex())) // get the next token
6823 m_children.append(new DocWord(this,g_token->name));
6826 m_children.append(new DocWhiteSpace(this,g_token->chars));
6830 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name);
6831 if (s!=DocSymbol::Sym_Unknown)
6833 m_children.append(new DocSymbol(this,s));
6837 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
6838 qPrint(g_token->name));
6843 switch (Mappers::cmdMapper->map(g_token->name))
6846 m_children.append(new DocSymbol(this,DocSymbol::Sym_BSlash));
6849 m_children.append(new DocSymbol(this,DocSymbol::Sym_At));
6852 m_children.append(new DocSymbol(this,DocSymbol::Sym_Less));
6855 m_children.append(new DocSymbol(this,DocSymbol::Sym_Greater));
6858 m_children.append(new DocSymbol(this,DocSymbol::Sym_Amp));
6861 m_children.append(new DocSymbol(this,DocSymbol::Sym_Dollar));
6864 m_children.append(new DocSymbol(this,DocSymbol::Sym_Hash));
6867 m_children.append(new DocSymbol(this,DocSymbol::Sym_DoubleColon));
6870 m_children.append(new DocSymbol(this,DocSymbol::Sym_Percent));
6873 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6874 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6877 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6878 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6879 m_children.append(new DocSymbol(this,DocSymbol::Sym_Minus));
6882 m_children.append(new DocSymbol(this,DocSymbol::Sym_Quot));
6885 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command `%s' found",
6886 qPrint(g_token->name));
6891 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
6897 handleUnclosedStyleCommands();
6899 DocNode *n = g_nodeStack.pop();
6901 DBG(("DocText::parse() end\n"));
6905 //--------------------------------------------------------------------------
6907 void DocRoot::parse()
6909 DBG(("DocRoot::parse() start\n"));
6910 g_nodeStack.push(this);
6911 doctokenizerYYsetStatePara();
6914 // first parse any number of paragraphs
6919 DocPara *par = new DocPara(this);
6920 if (isFirst) { par->markFirst(); isFirst=FALSE; }
6921 retval=par->parse();
6922 if (!par->isEmpty())
6924 m_children.append(par);
6931 if (retval==TK_LISTITEM)
6933 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found");
6935 else if (retval==RetVal_Subsection)
6937 warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!");
6939 else if (retval==RetVal_Subsubsection)
6941 warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!");
6943 else if (retval==RetVal_Paragraph)
6945 warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!");
6947 if (retval==RetVal_Internal)
6949 DocInternal *in = new DocInternal(this);
6950 m_children.append(in);
6951 retval = in->parse(1);
6953 } while (retval!=0 && retval!=RetVal_Section);
6954 if (lastPar) lastPar->markLast();
6956 //printf("DocRoot::parse() retval=%d %d\n",retval,RetVal_Section);
6957 // then parse any number of level1 sections
6958 while (retval==RetVal_Section)
6960 SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId);
6963 DocSection *s=new DocSection(this,
6964 QMIN(1+Doxygen::subpageNestingLevel,5),g_token->sectionId);
6965 m_children.append(s);
6966 retval = s->parse();
6970 warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid section id `%s'; ignoring section",qPrint(g_token->sectionId));
6975 handleUnclosedStyleCommands();
6977 DocNode *n = g_nodeStack.pop();
6979 DBG(("DocRoot::parse() end\n"));
6982 static QCString extractCopyDocId(const char *data, uint &j, uint len)
6987 bool insideDQuote=FALSE;
6988 bool insideSQuote=FALSE;
6990 while (j<len && !found)
6992 if (!insideSQuote && !insideDQuote)
6996 case '(': round++; break;
6997 case ')': round--; break;
6998 case '"': insideDQuote=TRUE; break;
6999 case '\'': insideSQuote=TRUE; break;
7000 case ' ': // fall through
7001 case '\t': // fall through
7007 else if (insideSQuote) // look for single quote end
7009 if (data[j]=='\'' && (j==0 || data[j]!='\\'))
7014 else if (insideDQuote) // look for double quote end
7016 if (data[j]=='"' && (j==0 || data[j]!='\\'))
7023 if (qstrncmp(data+j," const",6)==0)
7027 else if (qstrncmp(data+j," volatile",9)==0)
7033 if (e>s) memcpy(id.data(),data+s,e-s);
7035 //printf("extractCopyDocId='%s' input='%s'\n",id.data(),&data[s]);
7039 static uint isCopyBriefOrDetailsCmd(const char *data, uint i,uint len,bool &brief)
7042 if (i==0 || (data[i-1]!='@' && data[i-1]!='\\')) // not an escaped command
7044 if (i+10<len && qstrncmp(data+i+1,"copybrief",9)==0) // @copybrief or \copybrief
7049 else if (i+12<len && qstrncmp(data+i+1,"copydetails",11)==0) // @copydetails or \copydetails
7058 static QCString processCopyDoc(const char *data,uint &len)
7060 //printf("processCopyDoc start '%s'\n",data);
7066 if (c=='@' || c=='\\') // look for a command
7069 uint j=isCopyBriefOrDetailsCmd(data,i,len,isBrief);
7073 while (j<len && (data[j]==' ' || data[j]=='\t')) j++;
7074 // extract the argument
7075 QCString id = extractCopyDocId(data,j,len);
7078 //printf("resolving docs='%s'\n",id.data());
7079 if (findDocsForMemberOrCompound(id,&doc,&brief,&def))
7081 //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,brief.data(),doc.data(),isBrief);
7082 if (g_copyStack.findRef(def)==-1) // definition not parsed earlier
7084 g_copyStack.append(def);
7087 uint l=brief.length();
7088 buf.addStr(processCopyDoc(brief,l));
7092 uint l=doc.length();
7093 buf.addStr(processCopyDoc(doc,l));
7095 g_copyStack.remove(def);
7099 warn_doc_error(g_fileName,doctokenizerYYlineno,
7100 "Found recursive @copy%s or @copydoc relation for argument '%s'.\n",
7101 isBrief?"brief":"details",id.data());
7104 // skip over command
7113 else // not a command, just copy
7124 //--------------------------------------------------------------------------
7126 DocRoot *validatingParseDoc(const char *fileName,int startLine,
7127 Definition *ctx,MemberDef *md,
7128 const char *input,bool indexWords,
7129 bool isExample, const char *exampleName,
7130 bool singleLine, bool linkFromIndex)
7132 //printf("validatingParseDoc(%s,%s)=[%s]\n",ctx?ctx->name().data():"<none>",
7133 // md?md->name().data():"<none>",
7135 //printf("========== validating %s at line %d\n",fileName,startLine);
7136 //printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",input);
7137 //g_token = new TokenInfo;
7139 // store parser state so we can re-enter this function if needed
7140 //bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
7141 docParserPushContext();
7143 if (ctx && ctx!=Doxygen::globalScope &&
7144 (ctx->definitionType()==Definition::TypeClass ||
7145 ctx->definitionType()==Definition::TypeNamespace
7149 g_context = ctx->name();
7151 else if (ctx && ctx->definitionType()==Definition::TypePage)
7153 Definition *scope = ((PageDef*)ctx)->getPageScope();
7154 if (scope && scope!=Doxygen::globalScope) g_context = scope->name();
7156 else if (ctx && ctx->definitionType()==Definition::TypeGroup)
7158 Definition *scope = ((GroupDef*)ctx)->getGroupScope();
7159 if (scope && scope!=Doxygen::globalScope) g_context = scope->name();
7167 if (indexWords && Doxygen::searchIndex)
7171 g_searchUrl=md->getOutputFileBase();
7172 Doxygen::searchIndex->setCurrentDoc(md,md->anchor(),FALSE);
7176 g_searchUrl=ctx->getOutputFileBase();
7177 Doxygen::searchIndex->setCurrentDoc(ctx,ctx->anchor(),FALSE);
7181 if (indexWords && md && Doxygen::searchIndex)
7183 g_searchUrl=md->getOutputFileBase();
7184 Doxygen::searchIndex->setCurrentDoc(
7185 (md->getLanguage()==SrcLangExt_Fortran ?
7186 theTranslator->trSubprogram(TRUE,TRUE):
7187 theTranslator->trMember(TRUE,TRUE))+" "+md->qualifiedName(),
7191 else if (indexWords && ctx && Doxygen::searchIndex)
7193 g_searchUrl=ctx->getOutputFileBase();
7194 QCString name = ctx->qualifiedName();
7196 SrcLangExt lang = ctx->getLanguage();
7197 QCString sep = getLanguageSpecificSeparator(lang);
7200 name = substitute(name,"::",sep);
7203 switch (ctx->definitionType())
7205 case Definition::TypePage:
7207 PageDef *pd = (PageDef *)ctx;
7208 if (!pd->title().isEmpty())
7210 name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title();
7214 name = theTranslator->trPage(TRUE,TRUE)+" "+pd->name();
7218 case Definition::TypeClass:
7220 ClassDef *cd = (ClassDef *)ctx;
7221 name.prepend(cd->compoundTypeString()+" ");
7224 case Definition::TypeNamespace:
7226 if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
7228 name = theTranslator->trPackage(name);
7230 else if (lang==SrcLangExt_Fortran)
7232 name.prepend(theTranslator->trModule(TRUE,TRUE)+" ");
7236 name.prepend(theTranslator->trNamespace(TRUE,TRUE)+" ");
7240 case Definition::TypeGroup:
7242 GroupDef *gd = (GroupDef *)ctx;
7243 if (gd->groupTitle())
7245 name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle();
7249 name.prepend(theTranslator->trGroup(TRUE,TRUE)+" ");
7256 Doxygen::searchIndex->setCurrentDoc(name,g_searchUrl);
7264 g_fileName = fileName;
7265 g_relPath = (!linkFromIndex && ctx) ?
7266 QCString(relativePathToRoot(ctx->getOutputFileBase())) :
7268 //printf("ctx->name=%s relPath=%s\n",ctx->name().data(),g_relPath.data());
7270 g_nodeStack.clear();
7271 g_styleStack.clear();
7272 g_initialStyleStack.clear();
7273 g_inSeeBlock = FALSE;
7274 g_xmlComment = FALSE;
7275 g_insideHtmlLink = FALSE;
7276 g_includeFileText = "";
7277 g_includeFileOffset = 0;
7278 g_includeFileLength = 0;
7279 g_isExample = isExample;
7280 g_exampleName = exampleName;
7281 g_hasParamCommand = FALSE;
7282 g_hasReturnCommand = FALSE;
7283 g_paramsFound.setAutoDelete(FALSE);
7284 g_paramsFound.clear();
7285 g_sectionDict = 0; //sections;
7287 //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine);
7288 doctokenizerYYlineno=startLine;
7289 uint inpLen=qstrlen(input);
7290 QCString inpStr = processCopyDoc(input,inpLen);
7291 if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n')
7295 //printf("processCopyDoc(in='%s' out='%s')\n",input,inpStr.data());
7296 doctokenizerYYinit(inpStr,g_fileName);
7298 // build abstract syntax tree
7299 DocRoot *root = new DocRoot(md!=0,singleLine);
7303 if (Debug::isFlagSet(Debug::PrintTree))
7305 // pretty print the result
7306 PrintDocVisitor *v = new PrintDocVisitor;
7311 checkUndocumentedParams();
7312 detectNoDocumentedParams();
7314 // TODO: These should be called at the end of the program.
7315 //doctokenizerYYcleanup();
7316 //Mappers::cmdMapper->freeInstance();
7317 //Mappers::htmlTagMapper->freeInstance();
7319 // restore original parser state
7320 docParserPopContext();
7322 //printf(">>>>>> end validatingParseDoc(%s,%s)\n",ctx?ctx->name().data():"<none>",
7323 // md?md->name().data():"<none>");
7328 DocText *validatingParseText(const char *input)
7330 // store parser state so we can re-enter this function if needed
7331 docParserPushContext();
7333 //printf("------------ input ---------\n%s\n"
7334 // "------------ end input -----\n",input);
7335 //g_token = new TokenInfo;
7337 g_fileName = "<parseText>";
7340 g_nodeStack.clear();
7341 g_styleStack.clear();
7342 g_initialStyleStack.clear();
7343 g_inSeeBlock = FALSE;
7344 g_xmlComment = FALSE;
7345 g_insideHtmlLink = FALSE;
7346 g_includeFileText = "";
7347 g_includeFileOffset = 0;
7348 g_includeFileLength = 0;
7349 g_isExample = FALSE;
7351 g_hasParamCommand = FALSE;
7352 g_hasReturnCommand = FALSE;
7353 g_paramsFound.setAutoDelete(FALSE);
7354 g_paramsFound.clear();
7357 DocText *txt = new DocText;
7361 doctokenizerYYlineno=1;
7362 doctokenizerYYinit(input,g_fileName);
7364 // build abstract syntax tree
7367 if (Debug::isFlagSet(Debug::PrintTree))
7369 // pretty print the result
7370 PrintDocVisitor *v = new PrintDocVisitor;
7376 // restore original parser state
7377 docParserPopContext();
7381 void docFindSections(const char *input,
7384 const char *fileName)
7386 doctokenizerYYFindSections(input,d,mg,fileName);