00001 /****************************************************************************** 00002 * 00003 * $Id: $ 00004 * 00005 * 00006 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00007 * 00008 * Permission to use, copy, modify, and distribute this software and its 00009 * documentation under the terms of the GNU General Public License is hereby 00010 * granted. No representations are made about the suitability of this software 00011 * for any purpose. It is provided "as is" without express or implied warranty. 00012 * See the GNU General Public License for more details. 00013 * 00014 * Documents produced by Doxygen are derivative works derived from the 00015 * input used in their production; they are not affected by this license. 00016 * 00017 */ 00018 00019 #include <stdio.h> 00020 #include <stdlib.h> 00021 00022 #include <qfile.h> 00023 #include <qfileinfo.h> 00024 #include <qcstring.h> 00025 #include <qstack.h> 00026 #include <qdict.h> 00027 #include <qregexp.h> 00028 #include <ctype.h> 00029 00030 #include "doxygen.h" 00031 #include "debug.h" 00032 #include "util.h" 00033 #include "pagedef.h" 00034 00035 #include "docparser.h" 00036 #include "doctokenizer.h" 00037 #include "cmdmapper.h" 00038 #include "printdocvisitor.h" 00039 #include "message.h" 00040 #include "section.h" 00041 #include "searchindex.h" 00042 #include "language.h" 00043 #include "portable.h" 00044 00045 // debug off 00046 #define DBG(x) do {} while(0) 00047 00048 // debug to stdout 00049 //#define DBG(x) printf x 00050 00051 // debug to stderr 00052 //#define myprintf(x...) fprintf(stderr,x) 00053 //#define DBG(x) myprintf x 00054 00055 #define INTERNAL_ASSERT(x) do {} while(0) 00056 //#define INTERNAL_ASSERT(x) if (!(x)) DBG(("INTERNAL_ASSERT(%s) failed retval=0x%x: file=%s line=%d\n",#x,retval,__FILE__,__LINE__)); 00057 00058 //--------------------------------------------------------------------------- 00059 00060 static const char *sectionLevelToName[] = 00061 { 00062 "page", 00063 "section", 00064 "subsection", 00065 "subsubsection", 00066 "paragraph" 00067 }; 00068 00069 //--------------------------------------------------------------------------- 00070 00071 // Parser state: global variables during a call to validatingParseDoc 00072 static QString g_context; 00073 static bool g_inSeeBlock; 00074 static bool g_insideHtmlLink; 00075 static QStack<DocNode> g_nodeStack; 00076 static QStack<DocStyleChange> g_styleStack; 00077 static QStack<DocStyleChange> g_initialStyleStack; 00078 static QList<Definition> g_copyStack; 00079 static QString g_fileName; 00080 static QString g_relPath; 00081 00082 static bool g_hasParamCommand; 00083 static bool g_hasReturnCommand; 00084 static MemberDef * g_memberDef; 00085 static QDict<void> g_paramsFound; 00086 static bool g_isExample; 00087 static QCString g_exampleName; 00088 static SectionDict * g_sectionDict; 00089 static QCString g_searchUrl; 00090 00091 static QString g_includeFileText; 00092 static uint g_includeFileOffset; 00093 static uint g_includeFileLength; 00094 00095 // parser's context to store all global variables 00096 struct DocParserContext 00097 { 00098 QString context; 00099 bool inSeeBlock; 00100 bool insideHtmlLink; 00101 QStack<DocNode> nodeStack; 00102 QStack<DocStyleChange> styleStack; 00103 QStack<DocStyleChange> initialStyleStack; 00104 QList<Definition> copyStack; 00105 QString fileName; 00106 QString relPath; 00107 00108 bool hasParamCommand; 00109 bool hasReturnCommand; 00110 MemberDef * memberDef; 00111 QDict<void> paramsFound; 00112 bool isExample; 00113 QCString exampleName; 00114 SectionDict *sectionDict; 00115 QCString searchUrl; 00116 00117 QString includeFileText; 00118 uint includeFileOffset; 00119 uint includeFileLength; 00120 00121 TokenInfo *token; 00122 }; 00123 00124 static QStack<DocParserContext> g_parserStack; 00125 00126 //--------------------------------------------------------------------------- 00127 00128 static void docParserPushContext() 00129 { 00130 //QCString indent; 00131 //indent.fill(' ',g_parserStack.count()*2+2); 00132 //printf("%sdocParserPushContext() count=%d\n",indent.data(),g_nodeStack.count()); 00133 00134 doctokenizerYYpushContext(); 00135 DocParserContext *ctx = new DocParserContext; 00136 ctx->context = g_context; 00137 ctx->inSeeBlock = g_inSeeBlock; 00138 ctx->insideHtmlLink = g_insideHtmlLink; 00139 ctx->nodeStack = g_nodeStack; 00140 ctx->styleStack = g_styleStack; 00141 ctx->initialStyleStack = g_initialStyleStack; 00142 ctx->copyStack = g_copyStack; 00143 ctx->fileName = g_fileName; 00144 ctx->relPath = g_relPath; 00145 00146 ctx->hasParamCommand = g_hasParamCommand; 00147 ctx->hasReturnCommand = g_hasReturnCommand; 00148 ctx->memberDef = g_memberDef; 00149 ctx->paramsFound = g_paramsFound; 00150 ctx->isExample = g_isExample; 00151 ctx->exampleName = g_exampleName; 00152 ctx->sectionDict = g_sectionDict; 00153 ctx->searchUrl = g_searchUrl; 00154 00155 ctx->includeFileText = g_includeFileText; 00156 ctx->includeFileOffset = g_includeFileOffset; 00157 ctx->includeFileLength = g_includeFileLength; 00158 00159 ctx->token = g_token; 00160 g_token = new TokenInfo; 00161 00162 g_parserStack.push(ctx); 00163 } 00164 00165 static void docParserPopContext(bool keepParamInfo=FALSE) 00166 { 00167 DocParserContext *ctx = g_parserStack.pop(); 00168 g_context = ctx->context; 00169 g_inSeeBlock = ctx->inSeeBlock; 00170 g_insideHtmlLink = ctx->insideHtmlLink; 00171 g_nodeStack = ctx->nodeStack; 00172 g_styleStack = ctx->styleStack; 00173 g_initialStyleStack = ctx->initialStyleStack; 00174 g_copyStack = ctx->copyStack; 00175 g_fileName = ctx->fileName; 00176 g_relPath = ctx->relPath; 00177 00178 if (!keepParamInfo) 00179 { 00180 g_hasParamCommand = ctx->hasParamCommand; 00181 g_hasReturnCommand = ctx->hasReturnCommand; 00182 g_paramsFound = ctx->paramsFound; 00183 } 00184 g_memberDef = ctx->memberDef; 00185 g_isExample = ctx->isExample; 00186 g_exampleName = ctx->exampleName; 00187 g_sectionDict = ctx->sectionDict; 00188 g_searchUrl = ctx->searchUrl; 00189 00190 g_includeFileText = ctx->includeFileText; 00191 g_includeFileOffset = ctx->includeFileOffset; 00192 g_includeFileLength = ctx->includeFileLength; 00193 00194 delete g_token; 00195 g_token = ctx->token; 00196 00197 delete ctx; 00198 doctokenizerYYpopContext(); 00199 00200 //QCString indent; 00201 //indent.fill(' ',g_parserStack.count()*2+2); 00202 //printf("%sdocParserPopContext() count=%d\n",indent.data(),g_nodeStack.count()); 00203 } 00204 00205 //--------------------------------------------------------------------------- 00206 00211 static QCString findAndCopyImage(const char *fileName,DocImage::Type type) 00212 { 00213 QCString result; 00214 bool ambig; 00215 FileDef *fd; 00216 //printf("Search for %s\n",fileName); 00217 if ((fd=findFileDef(Doxygen::imageNameDict,fileName,ambig))) 00218 { 00219 QCString inputFile = fd->absFilePath(); 00220 QFile inImage(inputFile); 00221 if (inImage.open(IO_ReadOnly)) 00222 { 00223 result = fileName; 00224 int i; 00225 if ((i=result.findRev('/'))!=-1 || (i=result.findRev('\\'))!=-1) 00226 { 00227 result = result.right(result.length()-i-1); 00228 } 00229 //printf("fileName=%s result=%s\n",fileName,result.data()); 00230 QCString outputDir; 00231 switch(type) 00232 { 00233 case DocImage::Html: 00234 if (!Config_getBool("GENERATE_HTML")) return result; 00235 outputDir = Config_getString("HTML_OUTPUT"); 00236 break; 00237 case DocImage::Latex: 00238 if (!Config_getBool("GENERATE_LATEX")) return result; 00239 outputDir = Config_getString("LATEX_OUTPUT"); 00240 break; 00241 case DocImage::Rtf: 00242 if (!Config_getBool("GENERATE_RTF")) return result; 00243 outputDir = Config_getString("RTF_OUTPUT"); 00244 break; 00245 } 00246 QCString outputFile = outputDir+"/"+result; 00247 if (outputFile!=inputFile) // prevent copying to ourself 00248 { 00249 QFile outImage(outputFile.data()); 00250 if (outImage.open(IO_WriteOnly)) // copy the image 00251 { 00252 char *buffer = new char[inImage.size()]; 00253 inImage.readBlock(buffer,inImage.size()); 00254 outImage.writeBlock(buffer,inImage.size()); 00255 outImage.flush(); 00256 delete buffer; 00257 } 00258 else 00259 { 00260 warn_doc_error(g_fileName,doctokenizerYYlineno, 00261 "Warning: could not write output image %s",outputFile.data()); 00262 } 00263 } 00264 } 00265 else 00266 { 00267 warn_doc_error(g_fileName,doctokenizerYYlineno, 00268 "Warning: could not open image %s",fileName); 00269 } 00270 00271 if (type==DocImage::Latex && Config_getBool("USE_PDFLATEX") && 00272 fd->name().right(4)==".eps" 00273 ) 00274 { // we have an .eps image in pdflatex mode => convert it to a pdf. 00275 QCString outputDir = Config_getString("LATEX_OUTPUT"); 00276 QCString baseName = fd->name().left(fd->name().length()-4); 00277 QCString epstopdfArgs(4096); 00278 epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"", 00279 outputDir.data(), baseName.data(), 00280 outputDir.data(), baseName.data()); 00281 if (portable_system("epstopdf",epstopdfArgs)!=0) 00282 { 00283 err("Error: Problems running epstopdf. Check your TeX installation!\n"); 00284 } 00285 return baseName; 00286 } 00287 } 00288 else if (ambig) 00289 { 00290 QCString text; 00291 text.sprintf("Warning: image file name %s is ambigious.\n",fileName); 00292 text+="Possible candidates:\n"; 00293 text+=showFileDefMatches(Doxygen::imageNameDict,fileName); 00294 warn_doc_error(g_fileName,doctokenizerYYlineno,text); 00295 } 00296 else 00297 { 00298 result=fileName; 00299 if (result.left(5)!="http:" && result.left(6)!="https:") 00300 { 00301 warn_doc_error(g_fileName,doctokenizerYYlineno, 00302 "Warning: image file %s is not found in IMAGE_PATH: " 00303 "assuming external image.",fileName 00304 ); 00305 } 00306 } 00307 return result; 00308 } 00309 00316 static void checkArgumentName(const QString &name,bool isParam) 00317 { 00318 if (!Config_getBool("WARN_IF_DOC_ERROR")) return; 00319 if (g_memberDef==0) return; // not a member 00320 LockingPtr<ArgumentList> al=g_memberDef->isDocsForDefinition() ? 00321 g_memberDef->argumentList() : 00322 g_memberDef->declArgumentList(); 00323 if (al==0) return; // no argument list 00324 00325 static QRegExp re("[a-zA-Z0-9_]+\\.*"); 00326 int p=0,i=0,l; 00327 while ((i=re.match(name,p,&l))!=-1) // to handle @param x,y 00328 { 00329 QString aName=name.mid(i,l); 00330 //printf("aName=`%s'\n",aName.data()); 00331 ArgumentListIterator ali(*al); 00332 Argument *a; 00333 bool found=FALSE; 00334 for (ali.toFirst();(a=ali.current());++ali) 00335 { 00336 QString argName = g_memberDef->isDefine() ? a->type : a->name; 00337 //printf("argName=`%s'\n",argName.data()); 00338 if (argName.right(3)=="...") argName=argName.left(argName.length()-3); 00339 if (aName==argName) 00340 { 00341 //printf("adding `%s'\n",aName.data()); 00342 g_paramsFound.insert(aName,(void *)(0x8)); 00343 found=TRUE; 00344 break; 00345 } 00346 } 00347 if (!found && isParam) 00348 { 00349 //printf("member type=%d\n",memberDef->memberType()); 00350 QString scope=g_memberDef->getScopeString(); 00351 if (!scope.isEmpty()) scope+="::"; else scope=""; 00352 QString inheritedFrom = ""; 00353 QString docFile = g_memberDef->docFile(); 00354 int docLine = g_memberDef->docLine(); 00355 MemberDef *inheritedMd = g_memberDef->inheritsDocsFrom(); 00356 if (inheritedMd) // documentation was inherited 00357 { 00358 inheritedFrom.sprintf(" inherited from member %s at line " 00359 "%d in file %s",inheritedMd->name().data(), 00360 inheritedMd->docLine(),inheritedMd->docFile().data()); 00361 docFile = g_memberDef->getDefFileName(); 00362 docLine = g_memberDef->getDefLine(); 00363 00364 } 00365 warn_doc_error(docFile,docLine, 00366 "Warning: argument `%s' of command @param " 00367 "is not found in the argument list of %s%s%s%s", 00368 aName.data(),scope.data(),g_memberDef->name().data(), 00369 argListToString(al.pointer()).data(),inheritedFrom.data()); 00370 } 00371 p=i+l; 00372 } 00373 } 00374 00380 static void checkUndocumentedParams() 00381 { 00382 if (g_memberDef && g_hasParamCommand && Config_getBool("WARN_IF_DOC_ERROR")) 00383 { 00384 LockingPtr<ArgumentList> al=g_memberDef->isDocsForDefinition() ? 00385 g_memberDef->argumentList() : 00386 g_memberDef->declArgumentList(); 00387 if (al!=0) 00388 { 00389 ArgumentListIterator ali(*al); 00390 Argument *a; 00391 bool found=FALSE; 00392 for (ali.toFirst();(a=ali.current());++ali) 00393 { 00394 QString argName = g_memberDef->isDefine() ? a->type : a->name; 00395 if (argName.right(3)=="...") argName=argName.left(argName.length()-3); 00396 if (!argName.isEmpty() && g_paramsFound.find(argName)==0 && a->docs.isEmpty()) 00397 { 00398 found = TRUE; 00399 break; 00400 } 00401 } 00402 if (found) 00403 { 00404 bool first=TRUE; 00405 QString errMsg= 00406 "Warning: The following parameters of "+ 00407 QString(g_memberDef->qualifiedName()) + 00408 QString(argListToString(al.pointer())) + 00409 " are not documented:\n"; 00410 for (ali.toFirst();(a=ali.current());++ali) 00411 { 00412 QString argName = g_memberDef->isDefine() ? a->type : a->name; 00413 if (!argName.isEmpty() && g_paramsFound.find(argName)==0) 00414 { 00415 if (!first) 00416 { 00417 errMsg+="\n"; 00418 } 00419 else 00420 { 00421 first=FALSE; 00422 } 00423 errMsg+=" parameter "+argName; 00424 } 00425 } 00426 if (g_memberDef->inheritsDocsFrom()) 00427 { 00428 warn_doc_error(g_memberDef->getDefFileName(), 00429 g_memberDef->getDefLine(), 00430 substitute(errMsg,"%","%%")); 00431 } 00432 else 00433 { 00434 warn_doc_error(g_memberDef->docFile(), 00435 g_memberDef->docLine(), 00436 substitute(errMsg,"%","%%")); 00437 } 00438 } 00439 } 00440 } 00441 } 00442 00448 static void detectNoDocumentedParams() 00449 { 00450 if (g_memberDef && Config_getBool("WARN_NO_PARAMDOC")) 00451 { 00452 LockingPtr<ArgumentList> al = g_memberDef->argumentList(); 00453 LockingPtr<ArgumentList> declAl = g_memberDef->declArgumentList(); 00454 QString returnType = g_memberDef->typeString(); 00455 00456 if (!g_memberDef->hasDocumentedParams() && 00457 g_hasParamCommand) 00458 { 00459 //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data()); 00460 g_memberDef->setHasDocumentedParams(TRUE); 00461 } 00462 else if (!g_memberDef->hasDocumentedParams()) 00463 { 00464 bool allDoc=TRUE; // no paramater => all parameters are documented 00465 if ( // member has parameters 00466 al!=0 && // but the member has a parameter list 00467 al->count()>0 // with at least one parameter (that is not void) 00468 ) 00469 { 00470 ArgumentListIterator ali(*al); 00471 Argument *a; 00472 00473 // see if all parameters have documentation 00474 for (ali.toFirst();(a=ali.current()) && allDoc;++ali) 00475 { 00476 if (!a->name.isEmpty() && a->type!="void") 00477 { 00478 allDoc = !a->docs.isEmpty(); 00479 } 00480 //printf("a->type=%s a->name=%s doc=%s\n", 00481 // a->type.data(),a->name.data(),a->docs.data()); 00482 } 00483 if (!allDoc && declAl!=0) // try declaration arguments as well 00484 { 00485 allDoc=TRUE; 00486 ArgumentListIterator ali(*declAl); 00487 Argument *a; 00488 for (ali.toFirst();(a=ali.current()) && allDoc;++ali) 00489 { 00490 if (!a->name.isEmpty() && a->type!="void") 00491 { 00492 allDoc = !a->docs.isEmpty(); 00493 } 00494 //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data()); 00495 } 00496 } 00497 } 00498 if (allDoc) 00499 { 00500 //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data()); 00501 g_memberDef->setHasDocumentedParams(TRUE); 00502 } 00503 } 00504 //printf("Member %s hasReturnCommand=%d\n",g_memberDef->name().data(),g_hasReturnCommand); 00505 if (!g_memberDef->hasDocumentedReturnType() && // docs not yet found 00506 g_hasReturnCommand) 00507 { 00508 g_memberDef->setHasDocumentedReturnType(TRUE); 00509 } 00510 else if ( // see if return needs to documented 00511 g_memberDef->hasDocumentedReturnType() || 00512 returnType.isEmpty() || // empty return type 00513 returnType.find("void")!=-1 || // void return type 00514 !g_memberDef->isConstructor() || // a constructor 00515 !g_memberDef->isDestructor() // or destructor 00516 ) 00517 { 00518 g_memberDef->setHasDocumentedReturnType(TRUE); 00519 } 00520 00521 } 00522 } 00523 00524 00525 //--------------------------------------------------------------------------- 00526 00528 static QString stripKnownExtensions(const char *text) 00529 { 00530 QString result=text; 00531 if (result.right(4)==".tex") 00532 { 00533 result=result.left(result.length()-4); 00534 } 00535 else if (result.right(Doxygen::htmlFileExtension.length())== 00536 QString(Doxygen::htmlFileExtension)) 00537 { 00538 result=result.left(result.length()-Doxygen::htmlFileExtension.length()); 00539 } 00540 return result; 00541 } 00542 00543 00544 //--------------------------------------------------------------------------- 00545 00547 static bool insidePRE(DocNode *n) 00548 { 00549 while (n) 00550 { 00551 if (n->isPreformatted()) return TRUE; 00552 n=n->parent(); 00553 } 00554 return FALSE; 00555 } 00556 00557 //--------------------------------------------------------------------------- 00558 00560 static bool insideLI(DocNode *n) 00561 { 00562 while (n) 00563 { 00564 if (n->kind()==DocNode::Kind_HtmlListItem) return TRUE; 00565 n=n->parent(); 00566 } 00567 return FALSE; 00568 } 00569 00570 //--------------------------------------------------------------------------- 00571 00573 static bool insideUL(DocNode *n) 00574 { 00575 while (n) 00576 { 00577 if (n->kind()==DocNode::Kind_HtmlList && 00578 ((DocHtmlList *)n)->type()==DocHtmlList::Unordered) return TRUE; 00579 n=n->parent(); 00580 } 00581 return FALSE; 00582 } 00583 00584 //--------------------------------------------------------------------------- 00585 00587 static bool insideOL(DocNode *n) 00588 { 00589 while (n) 00590 { 00591 if (n->kind()==DocNode::Kind_HtmlList && 00592 ((DocHtmlList *)n)->type()==DocHtmlList::Ordered) return TRUE; 00593 n=n->parent(); 00594 } 00595 return FALSE; 00596 } 00597 00598 //--------------------------------------------------------------------------- 00599 00600 static bool insideTable(DocNode *n) 00601 { 00602 while (n) 00603 { 00604 if (n->kind()==DocNode::Kind_HtmlTable) return TRUE; 00605 n=n->parent(); 00606 } 00607 return FALSE; 00608 } 00609 00610 //--------------------------------------------------------------------------- 00611 00613 //static bool insideLang(DocNode *n) 00614 //{ 00615 // while (n) 00616 // { 00617 // if (n->kind()==DocNode::Kind_Language) return TRUE; 00618 // n=n->parent(); 00619 // } 00620 // return FALSE; 00621 //} 00622 00623 00624 //--------------------------------------------------------------------------- 00625 00633 static bool findDocsForMemberOrCompound(const char *commandName, 00634 QString *pDoc, 00635 QString *pBrief, 00636 Definition **pDef) 00637 { 00638 //printf("findDocsForMemberOrCompound(%s)\n",commandName); 00639 *pDoc=""; 00640 *pBrief=""; 00641 *pDef=0; 00642 QString cmdArg=substitute(commandName,"#","::"); 00643 int l=cmdArg.length(); 00644 if (l==0) return FALSE; 00645 00646 int funcStart=cmdArg.find('('); 00647 if (funcStart==-1) funcStart=l; 00648 00649 QString name=removeRedundantWhiteSpace(cmdArg.left(funcStart).latin1()); 00650 QString args=cmdArg.right(l-funcStart); 00651 00652 // try if the link is to a member 00653 MemberDef *md=0; 00654 ClassDef *cd=0; 00655 FileDef *fd=0; 00656 NamespaceDef *nd=0; 00657 GroupDef *gd=0; 00658 PageDef *pd=0; 00659 bool found = getDefs( 00660 g_context.find('.')==-1?g_context.latin1():"", // `find('.') is a hack to detect files 00661 name.latin1(), 00662 args.isEmpty()?0:args.latin1(), 00663 md,cd,fd,nd,gd,FALSE,0,TRUE); 00664 //printf("found=%d context=%s name=%s\n",found,g_context.data(),name.data()); 00665 if (found && md) 00666 { 00667 *pDoc=md->documentation(); 00668 *pBrief=md->briefDescription(); 00669 *pDef=md; 00670 return TRUE; 00671 } 00672 00673 00674 int scopeOffset=g_context.length(); 00675 do // for each scope 00676 { 00677 QString fullName=cmdArg; 00678 if (scopeOffset>0) 00679 { 00680 fullName.prepend(g_context.left(scopeOffset)+"::"); 00681 } 00682 //printf("Trying fullName=`%s'\n",fullName.data()); 00683 00684 // try class, namespace, group, page, file reference 00685 cd = Doxygen::classSDict->find(fullName); 00686 if (cd) // class 00687 { 00688 *pDoc=cd->documentation(); 00689 *pBrief=cd->briefDescription(); 00690 *pDef=cd; 00691 return TRUE; 00692 } 00693 nd = Doxygen::namespaceSDict->find(fullName); 00694 if (nd) // namespace 00695 { 00696 *pDoc=nd->documentation(); 00697 *pBrief=nd->briefDescription(); 00698 *pDef=nd; 00699 return TRUE; 00700 } 00701 gd = Doxygen::groupSDict->find(cmdArg); 00702 if (gd) // group 00703 { 00704 *pDoc=gd->documentation(); 00705 *pBrief=gd->briefDescription(); 00706 *pDef=gd; 00707 return TRUE; 00708 } 00709 pd = Doxygen::pageSDict->find(cmdArg); 00710 if (pd) // page 00711 { 00712 *pDoc=pd->documentation(); 00713 *pBrief=pd->briefDescription(); 00714 *pDef=pd; 00715 return TRUE; 00716 } 00717 bool ambig; 00718 fd = findFileDef(Doxygen::inputNameDict,cmdArg,ambig); 00719 if (fd && !ambig) // file 00720 { 00721 *pDoc=fd->documentation(); 00722 *pBrief=fd->briefDescription(); 00723 *pDef=fd; 00724 return TRUE; 00725 } 00726 00727 if (scopeOffset==0) 00728 { 00729 scopeOffset=-1; 00730 } 00731 else 00732 { 00733 scopeOffset = g_context.findRev("::",scopeOffset-1); 00734 if (scopeOffset==-1) scopeOffset=0; 00735 } 00736 } while (scopeOffset>=0); 00737 00738 00739 return FALSE; 00740 } 00741 //--------------------------------------------------------------------------- 00742 00743 // forward declaration 00744 static bool defaultHandleToken(DocNode *parent,int tok, 00745 QList<DocNode> &children,bool 00746 handleWord=TRUE); 00747 00748 00749 static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, 00750 const QString &cmdName) 00751 { 00752 DBG(("handleStyleArgument(%s)\n",cmdName.data())); 00753 QString tokenName = g_token->name; 00754 int tok=doctokenizerYYlex(); 00755 if (tok!=TK_WHITESPACE) 00756 { 00757 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 00758 cmdName.data()); 00759 return tok; 00760 } 00761 while ((tok=doctokenizerYYlex()) && 00762 tok!=TK_WHITESPACE && 00763 tok!=TK_NEWPARA && 00764 tok!=TK_LISTITEM && 00765 tok!=TK_ENDLIST 00766 ) 00767 { 00768 static QRegExp specialChar("[.,|()\\[\\]:;\\?]"); 00769 if (tok==TK_WORD && g_token->name.length()==1 && 00770 g_token->name.find(specialChar)!=-1) 00771 { 00772 // special character that ends the markup command 00773 return tok; 00774 } 00775 if (!defaultHandleToken(parent,tok,children)) 00776 { 00777 switch (tok) 00778 { 00779 case TK_COMMAND: 00780 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command \\%s as the argument of a \\%s command", 00781 g_token->name.data(),cmdName.data()); 00782 break; 00783 case TK_SYMBOL: 00784 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found while handling command %s", 00785 g_token->name.data(),cmdName.data()); 00786 break; 00787 case TK_HTMLTAG: 00788 if (insideLI(parent) && Mappers::htmlTagMapper->map(g_token->name) && g_token->endTag) 00789 { // ignore </li> as the end of a style command 00790 continue; 00791 } 00792 return tok; 00793 break; 00794 default: 00795 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s while handling command %s", 00796 tokToString(tok),cmdName.data()); 00797 break; 00798 } 00799 break; 00800 } 00801 } 00802 DBG(("handleStyleArgument(%s) end tok=%x\n",cmdName.data(),tok)); 00803 return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST 00804 ) ? tok : RetVal_OK; 00805 } 00806 00810 static void handleStyleEnter(DocNode *parent,QList<DocNode> &children, 00811 DocStyleChange::Style s,const HtmlAttribList *attribs) 00812 { 00813 DBG(("HandleStyleEnter\n")); 00814 DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,TRUE,attribs); 00815 children.append(sc); 00816 g_styleStack.push(sc); 00817 } 00818 00822 static void handleStyleLeave(DocNode *parent,QList<DocNode> &children, 00823 DocStyleChange::Style s,const char *tagName) 00824 { 00825 DBG(("HandleStyleLeave\n")); 00826 if (g_styleStack.isEmpty() || // no style change 00827 g_styleStack.top()->style()!=s || // wrong style change 00828 g_styleStack.top()->position()!=g_nodeStack.count() // wrong position 00829 ) 00830 { 00831 if (g_styleStack.isEmpty()) 00832 { 00833 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </%s> tag without matching <%s>", 00834 tagName,tagName); 00835 } 00836 else 00837 { 00838 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </%s> tag while expecting </%s>", 00839 tagName,g_styleStack.top()->styleString()); 00840 } 00841 } 00842 else // end the section 00843 { 00844 DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,FALSE); 00845 children.append(sc); 00846 g_styleStack.pop(); 00847 } 00848 } 00849 00854 static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children) 00855 { 00856 if (!g_styleStack.isEmpty()) 00857 { 00858 DocStyleChange *sc = g_styleStack.top(); 00859 while (sc && sc->position()>=g_nodeStack.count()) 00860 { // there are unclosed style modifiers in the paragraph 00861 children.append(new DocStyleChange(parent,g_nodeStack.count(),sc->style(),FALSE)); 00862 g_initialStyleStack.push(sc); 00863 g_styleStack.pop(); 00864 sc = g_styleStack.top(); 00865 } 00866 } 00867 } 00868 00869 static void handleInitialStyleCommands(DocPara *parent,QList<DocNode> &children) 00870 { 00871 DocStyleChange *sc; 00872 while ((sc=g_initialStyleStack.pop())) 00873 { 00874 handleStyleEnter(parent,children,sc->style(),&sc->attribs()); 00875 } 00876 } 00877 00878 static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs) 00879 { 00880 HtmlAttribListIterator li(tagHtmlAttribs); 00881 HtmlAttrib *opt; 00882 int index=0; 00883 int retval = RetVal_OK; 00884 for (li.toFirst();(opt=li.current());++li,++index) 00885 { 00886 if (opt->name=="name") // <a name=label> tag 00887 { 00888 if (!opt->value.isEmpty()) 00889 { 00890 DocAnchor *anc = new DocAnchor(parent,opt->value,TRUE); 00891 children.append(anc); 00892 break; // stop looking for other tag attribs 00893 } 00894 else 00895 { 00896 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found <a> tag with name option but without value!"); 00897 } 00898 } 00899 else if (opt->name=="href") // <a href=url>..</a> tag 00900 { 00901 // copy attributes 00902 HtmlAttribList attrList = tagHtmlAttribs; 00903 // and remove the href attribute 00904 bool result = attrList.remove(index); 00905 ASSERT(result); 00906 DocHRef *href = new DocHRef(parent,attrList,opt->value); 00907 children.append(href); 00908 g_insideHtmlLink=TRUE; 00909 retval = href->parse(); 00910 g_insideHtmlLink=FALSE; 00911 break; 00912 } 00913 else // unsupported option for tag a 00914 { 00915 } 00916 } 00917 return retval; 00918 } 00919 00920 const char *DocStyleChange::styleString() const 00921 { 00922 switch (m_style) 00923 { 00924 case DocStyleChange::Bold: return "b"; 00925 case DocStyleChange::Italic: return "em"; 00926 case DocStyleChange::Code: return "code"; 00927 case DocStyleChange::Center: return "center"; 00928 case DocStyleChange::Small: return "small"; 00929 case DocStyleChange::Subscript: return "subscript"; 00930 case DocStyleChange::Superscript: return "superscript"; 00931 case DocStyleChange::Preformatted: return "pre"; 00932 case DocStyleChange::Div: return "div"; 00933 case DocStyleChange::Span: return "span"; 00934 } 00935 return "<invalid>"; 00936 } 00937 00938 static void handleUnclosedStyleCommands() 00939 { 00940 if (!g_initialStyleStack.isEmpty()) 00941 { 00942 DocStyleChange *sc = g_initialStyleStack.top(); 00943 g_initialStyleStack.pop(); 00944 handleUnclosedStyleCommands(); 00945 warn_doc_error(g_fileName,doctokenizerYYlineno, 00946 "Warning: end of comment block while expecting " 00947 "command </%s>",sc->styleString()); 00948 } 00949 } 00950 00951 00952 static void handleLinkedWord(DocNode *parent,QList<DocNode> &children) 00953 { 00954 Definition *compound=0; 00955 MemberDef *member=0; 00956 QString name = linkToText(g_token->name,TRUE); 00957 int len = g_token->name.length(); 00958 ClassDef *cd=0; 00959 //printf("handleLinkedWord(%s) g_context=%s\n",name.data(),g_context.data()); 00960 if (!g_insideHtmlLink && 00961 (resolveRef(g_context,g_token->name,g_inSeeBlock,&compound,&member) 00962 || (!g_context.isEmpty() && // also try with global scope 00963 resolveRef("",g_token->name,g_inSeeBlock,&compound,&member)) 00964 ) 00965 ) 00966 { 00967 //printf("resolveRef %s = %p (linkable?=%d)\n",g_token->name.data(),member,member ? member->isLinkable() : FALSE); 00968 if (member && member->isLinkable()) // member link 00969 { 00970 if (member->isObjCMethod()) 00971 { 00972 bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE; 00973 name = member->objCMethodName(localLink,g_inSeeBlock); 00974 } 00975 children.append(new 00976 DocLinkedWord(parent,name, 00977 member->getReference(), 00978 member->getOutputFileBase(), 00979 member->anchor(), 00980 member->briefDescriptionAsTooltip() 00981 ) 00982 ); 00983 } 00984 else if (compound->isLinkable()) // compound link 00985 { 00986 if (compound->definitionType()==Definition::TypeFile) 00987 { 00988 name=g_token->name; 00989 } 00990 else if (compound->definitionType()==Definition::TypeGroup) 00991 { 00992 name=((GroupDef*)compound)->groupTitle(); 00993 } 00994 children.append(new 00995 DocLinkedWord(parent,name, 00996 compound->getReference(), 00997 compound->getOutputFileBase(), 00998 "", 00999 compound->briefDescriptionAsTooltip() 01000 ) 01001 ); 01002 } 01003 else if (compound->definitionType()==Definition::TypeFile && 01004 ((FileDef*)compound)->generateSourceFile() 01005 ) // undocumented file that has source code we can link to 01006 { 01007 children.append(new 01008 DocLinkedWord(parent,g_token->name, 01009 compound->getReference(), 01010 compound->getSourceFileBase(), 01011 "", 01012 compound->briefDescriptionAsTooltip() 01013 ) 01014 ); 01015 } 01016 else // not linkable 01017 { 01018 children.append(new DocWord(parent,name)); 01019 } 01020 } 01021 else if (!g_insideHtmlLink && len>1 && g_token->name.at(len-1)==':') 01022 { 01023 // special case, where matching Foo: fails to be an Obj-C reference, 01024 // but Foo itself might be linkable. 01025 g_token->name=g_token->name.left(len-1); 01026 handleLinkedWord(parent,children); 01027 children.append(new DocWord(parent,":")); 01028 } 01029 else if (!g_insideHtmlLink && (cd=getClass(g_token->name+"-p"))) 01030 { 01031 // special case 2, where the token name is not a class, but could 01032 // be a Obj-C protocol 01033 children.append(new 01034 DocLinkedWord(parent,name, 01035 cd->getReference(), 01036 cd->getOutputFileBase(), 01037 "", 01038 cd->briefDescriptionAsTooltip() 01039 )); 01040 } 01041 else // normal non-linkable word 01042 { 01043 if (g_token->name.at(0)=='#') 01044 { 01045 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: explicit link request to '%s' could not be resolved",name.data()); 01046 } 01047 children.append(new DocWord(parent,name)); 01048 } 01049 } 01050 01051 /* Helper function that deals with the most common tokens allowed in 01052 * title like sections. 01053 * @param parent Parent node, owner of the children list passed as 01054 * the third argument. 01055 * @param tok The token to process. 01056 * @param children The list of child nodes to which the node representing 01057 * the token can be added. 01058 * @param handleWord Indicates if word token should be processed 01059 * @retval TRUE The token was handled. 01060 * @retval FALSE The token was not handled. 01061 */ 01062 static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool 01063 handleWord) 01064 { 01065 DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); 01066 if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || 01067 tok==TK_COMMAND || tok==TK_HTMLTAG 01068 ) 01069 { 01070 DBG((" name=%s",g_token->name.data())); 01071 } 01072 DBG(("\n")); 01073 reparsetoken: 01074 QString tokenName = g_token->name; 01075 switch (tok) 01076 { 01077 case TK_COMMAND: 01078 switch (Mappers::cmdMapper->map(tokenName)) 01079 { 01080 case CMD_BSLASH: 01081 children.append(new DocSymbol(parent,DocSymbol::BSlash)); 01082 break; 01083 case CMD_AT: 01084 children.append(new DocSymbol(parent,DocSymbol::At)); 01085 break; 01086 case CMD_LESS: 01087 children.append(new DocSymbol(parent,DocSymbol::Less)); 01088 break; 01089 case CMD_GREATER: 01090 children.append(new DocSymbol(parent,DocSymbol::Greater)); 01091 break; 01092 case CMD_AMP: 01093 children.append(new DocSymbol(parent,DocSymbol::Amp)); 01094 break; 01095 case CMD_DOLLAR: 01096 children.append(new DocSymbol(parent,DocSymbol::Dollar)); 01097 break; 01098 case CMD_HASH: 01099 children.append(new DocSymbol(parent,DocSymbol::Hash)); 01100 break; 01101 case CMD_PERCENT: 01102 children.append(new DocSymbol(parent,DocSymbol::Percent)); 01103 break; 01104 case CMD_EMPHASIS: 01105 { 01106 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,TRUE)); 01107 tok=handleStyleArgument(parent,children,tokenName); 01108 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,FALSE)); 01109 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," ")); 01110 if (tok==TK_NEWPARA) goto handlepara; 01111 else if (tok==TK_WORD || tok==TK_HTMLTAG) 01112 { 01113 DBG(("CMD_EMPHASIS: reparsing command %s\n",g_token->name.data())); 01114 goto reparsetoken; 01115 } 01116 } 01117 break; 01118 case CMD_BOLD: 01119 { 01120 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,TRUE)); 01121 tok=handleStyleArgument(parent,children,tokenName); 01122 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,FALSE)); 01123 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," ")); 01124 if (tok==TK_NEWPARA) goto handlepara; 01125 else if (tok==TK_WORD || tok==TK_HTMLTAG) 01126 { 01127 DBG(("CMD_BOLD: reparsing command %s\n",g_token->name.data())); 01128 goto reparsetoken; 01129 } 01130 } 01131 break; 01132 case CMD_CODE: 01133 { 01134 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,TRUE)); 01135 tok=handleStyleArgument(parent,children,tokenName); 01136 children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,FALSE)); 01137 if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," ")); 01138 if (tok==TK_NEWPARA) goto handlepara; 01139 else if (tok==TK_WORD || tok==TK_HTMLTAG) 01140 { 01141 DBG(("CMD_CODE: reparsing command %s\n",g_token->name.data())); 01142 goto reparsetoken; 01143 } 01144 } 01145 break; 01146 case CMD_HTMLONLY: 01147 { 01148 doctokenizerYYsetStateHtmlOnly(); 01149 tok = doctokenizerYYlex(); 01150 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName)); 01151 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: htmlonly section ended without end marker"); 01152 doctokenizerYYsetStatePara(); 01153 } 01154 break; 01155 case CMD_MANONLY: 01156 { 01157 doctokenizerYYsetStateManOnly(); 01158 tok = doctokenizerYYlex(); 01159 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName)); 01160 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: manonly section ended without end marker"); 01161 doctokenizerYYsetStatePara(); 01162 } 01163 break; 01164 case CMD_LATEXONLY: 01165 { 01166 doctokenizerYYsetStateLatexOnly(); 01167 tok = doctokenizerYYlex(); 01168 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName)); 01169 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: latexonly section ended without end marker",doctokenizerYYlineno); 01170 doctokenizerYYsetStatePara(); 01171 } 01172 break; 01173 case CMD_XMLONLY: 01174 { 01175 doctokenizerYYsetStateXmlOnly(); 01176 tok = doctokenizerYYlex(); 01177 children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName)); 01178 if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: xmlonly section ended without end marker",doctokenizerYYlineno); 01179 doctokenizerYYsetStatePara(); 01180 } 01181 break; 01182 case CMD_FORMULA: 01183 { 01184 DocFormula *form=new DocFormula(parent,g_token->id); 01185 children.append(form); 01186 } 01187 break; 01188 case CMD_ANCHOR: 01189 { 01190 tok=doctokenizerYYlex(); 01191 if (tok!=TK_WHITESPACE) 01192 { 01193 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 01194 tokenName.data()); 01195 break; 01196 } 01197 tok=doctokenizerYYlex(); 01198 if (tok==0) 01199 { 01200 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the " 01201 "argument of command %s",tokenName.data()); 01202 break; 01203 } 01204 else if (tok!=TK_WORD && tok!=TK_LNKWORD) 01205 { 01206 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 01207 tokToString(tok),tokenName.data()); 01208 break; 01209 } 01210 DocAnchor *anchor = new DocAnchor(parent,g_token->name,FALSE); 01211 children.append(anchor); 01212 } 01213 break; 01214 case CMD_INTERNALREF: 01215 { 01216 tok=doctokenizerYYlex(); 01217 if (tok!=TK_WHITESPACE) 01218 { 01219 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 01220 tokenName.data()); 01221 break; 01222 } 01223 doctokenizerYYsetStateInternalRef(); 01224 tok=doctokenizerYYlex(); // get the reference id 01225 DocInternalRef *ref=0; 01226 if (tok!=TK_WORD && tok!=TK_LNKWORD) 01227 { 01228 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 01229 tokToString(tok),tokenName.data()); 01230 doctokenizerYYsetStatePara(); 01231 break; 01232 } 01233 ref = new DocInternalRef(parent,g_token->name); 01234 children.append(ref); 01235 ref->parse(); 01236 doctokenizerYYsetStatePara(); 01237 } 01238 break; 01239 default: 01240 return FALSE; 01241 } 01242 break; 01243 case TK_HTMLTAG: 01244 { 01245 switch (Mappers::htmlTagMapper->map(tokenName)) 01246 { 01247 case HTML_DIV: 01248 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found <div> tag in heading\n"); 01249 break; 01250 case HTML_PRE: 01251 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found <pre> tag in heading\n"); 01252 break; 01253 case HTML_BOLD: 01254 if (!g_token->endTag) 01255 { 01256 handleStyleEnter(parent,children,DocStyleChange::Bold,&g_token->attribs); 01257 } 01258 else 01259 { 01260 handleStyleLeave(parent,children,DocStyleChange::Bold,tokenName); 01261 } 01262 break; 01263 case HTML_CODE: 01264 case XML_C: 01265 if (!g_token->endTag) 01266 { 01267 handleStyleEnter(parent,children,DocStyleChange::Code,&g_token->attribs); 01268 } 01269 else 01270 { 01271 handleStyleLeave(parent,children,DocStyleChange::Code,tokenName); 01272 } 01273 break; 01274 case HTML_EMPHASIS: 01275 if (!g_token->endTag) 01276 { 01277 handleStyleEnter(parent,children,DocStyleChange::Italic,&g_token->attribs); 01278 } 01279 else 01280 { 01281 handleStyleLeave(parent,children,DocStyleChange::Italic,tokenName); 01282 } 01283 break; 01284 case HTML_SUB: 01285 if (!g_token->endTag) 01286 { 01287 handleStyleEnter(parent,children,DocStyleChange::Subscript,&g_token->attribs); 01288 } 01289 else 01290 { 01291 handleStyleLeave(parent,children,DocStyleChange::Subscript,tokenName); 01292 } 01293 break; 01294 case HTML_SUP: 01295 if (!g_token->endTag) 01296 { 01297 handleStyleEnter(parent,children,DocStyleChange::Superscript,&g_token->attribs); 01298 } 01299 else 01300 { 01301 handleStyleLeave(parent,children,DocStyleChange::Superscript,tokenName); 01302 } 01303 break; 01304 case HTML_CENTER: 01305 if (!g_token->endTag) 01306 { 01307 handleStyleEnter(parent,children,DocStyleChange::Center,&g_token->attribs); 01308 } 01309 else 01310 { 01311 handleStyleLeave(parent,children,DocStyleChange::Center,tokenName); 01312 } 01313 break; 01314 case HTML_SMALL: 01315 if (!g_token->endTag) 01316 { 01317 handleStyleEnter(parent,children,DocStyleChange::Small,&g_token->attribs); 01318 } 01319 else 01320 { 01321 handleStyleLeave(parent,children,DocStyleChange::Small,tokenName); 01322 } 01323 break; 01324 default: 01325 return FALSE; 01326 break; 01327 } 01328 } 01329 break; 01330 case TK_SYMBOL: 01331 { 01332 char letter='\0'; 01333 DocSymbol::SymType s = DocSymbol::decodeSymbol(tokenName,&letter); 01334 if (s!=DocSymbol::Unknown) 01335 { 01336 children.append(new DocSymbol(parent,s,letter)); 01337 } 01338 else 01339 { 01340 return FALSE; 01341 } 01342 } 01343 break; 01344 case TK_WHITESPACE: 01345 case TK_NEWPARA: 01346 handlepara: 01347 if (insidePRE(parent) || !children.isEmpty()) 01348 { 01349 children.append(new DocWhiteSpace(parent,g_token->chars)); 01350 } 01351 break; 01352 case TK_LNKWORD: 01353 if (handleWord) 01354 { 01355 handleLinkedWord(parent,children); 01356 } 01357 else 01358 return FALSE; 01359 break; 01360 case TK_WORD: 01361 if (handleWord) 01362 { 01363 children.append(new DocWord(parent,g_token->name)); 01364 } 01365 else 01366 return FALSE; 01367 break; 01368 case TK_URL: 01369 if (g_insideHtmlLink) 01370 { 01371 children.append(new DocWord(parent,g_token->name)); 01372 } 01373 else 01374 { 01375 children.append(new DocURL(parent,g_token->name,g_token->isEMailAddr)); 01376 } 01377 break; 01378 default: 01379 return FALSE; 01380 } 01381 return TRUE; 01382 } 01383 01384 01385 //--------------------------------------------------------------------------- 01386 01387 DocSymbol::SymType DocSymbol::decodeSymbol(const QString &symName,char *letter) 01388 { 01389 int l=symName.length(); 01390 DBG(("decodeSymbol(%s) l=%d\n",symName.data(),l)); 01391 if (symName=="©") return DocSymbol::Copy; 01392 else if (symName=="™") return DocSymbol::Tm; 01393 else if (symName=="&tm;") return DocSymbol::Tm; // alias for &trace; 01394 else if (symName=="®") return DocSymbol::Reg; 01395 else if (symName=="<") return DocSymbol::Less; 01396 else if (symName==">") return DocSymbol::Greater; 01397 else if (symName=="&") return DocSymbol::Amp; 01398 else if (symName=="'") return DocSymbol::Apos; 01399 else if (symName==""") return DocSymbol::Quot; 01400 else if (symName=="‘") return DocSymbol::Lsquo; 01401 else if (symName=="’") return DocSymbol::Rsquo; 01402 else if (symName=="“") return DocSymbol::Ldquo; 01403 else if (symName=="”") return DocSymbol::Rdquo; 01404 else if (symName=="–") return DocSymbol::Ndash; 01405 else if (symName=="—") return DocSymbol::Mdash; 01406 else if (symName=="ß") return DocSymbol::Szlig; 01407 else if (symName==" ") return DocSymbol::Nbsp; 01408 else if (l==6 && symName.right(4)=="uml;") 01409 { 01410 *letter=symName.at(1); 01411 return DocSymbol::Uml; 01412 } 01413 else if (l==8 && symName.right(6)=="acute;") 01414 { 01415 *letter=symName.at(1); 01416 return DocSymbol::Acute; 01417 } 01418 else if (l==8 && symName.right(6)=="grave;") 01419 { 01420 *letter=symName.at(1); 01421 return DocSymbol::Grave; 01422 } 01423 else if (l==7 && symName.right(5)=="circ;") 01424 { 01425 *letter=symName.at(1); 01426 return DocSymbol::Circ; 01427 } 01428 else if (l==8 && symName.right(6)=="tilde;") 01429 { 01430 *letter=symName.at(1); 01431 return DocSymbol::Tilde; 01432 } 01433 else if (l==8 && symName.right(6)=="cedil;") 01434 { 01435 *letter=symName.at(1); 01436 return DocSymbol::Cedil; 01437 } 01438 else if (l==7 && symName.right(5)=="ring;") 01439 { 01440 *letter=symName.at(1); 01441 return DocSymbol::Ring; 01442 } 01443 else if (l==8 && symName.right(6)=="slash;") 01444 { 01445 *letter=symName.at(1); 01446 return DocSymbol::Slash; 01447 } 01448 return DocSymbol::Unknown; 01449 } 01450 01451 //--------------------------------------------------------------------------- 01452 01453 static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children, 01454 const QString &doc) 01455 { 01456 int retval = RetVal_OK; 01457 01458 if (doc.isEmpty()) return retval; 01459 01460 doctokenizerYYinit(doc,g_fileName); 01461 01462 // first parse any number of paragraphs 01463 bool isFirst=TRUE; 01464 DocPara *lastPar=0; 01465 if (!children.isEmpty() && children.last()->kind()==DocNode::Kind_Para) 01466 { // last child item was a paragraph 01467 lastPar = (DocPara*)children.last(); 01468 isFirst=FALSE; 01469 } 01470 do 01471 { 01472 DocPara *par = new DocPara(parent); 01473 if (isFirst) { par->markFirst(); isFirst=FALSE; } 01474 retval=par->parse(); 01475 if (!par->isEmpty()) 01476 { 01477 children.append(par); 01478 if (lastPar) lastPar->markLast(FALSE); 01479 lastPar=par; 01480 } 01481 else 01482 { 01483 delete par; 01484 } 01485 } while (retval==TK_NEWPARA); 01486 if (lastPar) lastPar->markLast(); 01487 01488 return retval; 01489 } 01490 01491 //--------------------------------------------------------------------------- 01492 01493 static void readTextFileByName(const QString &file,QString &text) 01494 { 01495 bool ambig; 01496 FileDef *fd; 01497 if ((fd=findFileDef(Doxygen::exampleNameDict,file,ambig))) 01498 { 01499 text = fileToString(fd->absFilePath(),Config_getBool("FILTER_SOURCE_FILES")); 01500 } 01501 else if (ambig) 01502 { 01503 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included file name %s is ambigious" 01504 "Possible candidates:\n%s",file.data(), 01505 showFileDefMatches(Doxygen::exampleNameDict,file).data() 01506 ); 01507 } 01508 else 01509 { 01510 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included file %s is not found. " 01511 "Check your EXAMPLE_PATH",file.data()); 01512 } 01513 } 01514 01515 //--------------------------------------------------------------------------- 01516 01517 DocWord::DocWord(DocNode *parent,const QString &word) : 01518 m_parent(parent), m_word(word) 01519 { 01520 //printf("new word %s url=%s\n",word.data(),g_searchUrl.data()); 01521 if (!g_searchUrl.isEmpty()) 01522 { 01523 Doxygen::searchIndex->addWord(word,FALSE); 01524 } 01525 } 01526 01527 //--------------------------------------------------------------------------- 01528 01529 DocLinkedWord::DocLinkedWord(DocNode *parent,const QString &word, 01530 const QString &ref,const QString &file, 01531 const QString &anchor,const QString &tooltip) : 01532 m_parent(parent), m_word(word), m_ref(ref), 01533 m_file(file), m_relPath(g_relPath), m_anchor(anchor), 01534 m_tooltip(tooltip) 01535 { 01536 //printf("new word %s url=%s\n",word.data(),g_searchUrl.data()); 01537 if (!g_searchUrl.isEmpty()) 01538 { 01539 Doxygen::searchIndex->addWord(word,FALSE); 01540 } 01541 } 01542 01543 //--------------------------------------------------------------------------- 01544 01545 DocAnchor::DocAnchor(DocNode *parent,const QString &id,bool newAnchor) 01546 : m_parent(parent) 01547 { 01548 if (id.isEmpty()) 01549 { 01550 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Empty anchor label"); 01551 } 01552 if (newAnchor) // found <a name="label"> 01553 { 01554 m_anchor = id; 01555 } 01556 else // found \anchor label 01557 { 01558 SectionInfo *sec = Doxygen::sectionDict[id]; 01559 if (sec) 01560 { 01561 //printf("Found anchor %s\n",id.data()); 01562 m_file = sec->fileName; 01563 m_anchor = sec->label; 01564 if (g_sectionDict && g_sectionDict->find(id)==0) 01565 { 01566 //printf("Inserting in dictionary!\n"); 01567 g_sectionDict->insert(id,sec); 01568 } 01569 } 01570 else 01571 { 01572 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid anchor id `%s'",id.data()); 01573 m_anchor = "invalid"; 01574 m_file = "invalid"; 01575 } 01576 } 01577 } 01578 01579 //--------------------------------------------------------------------------- 01580 01581 DocVerbatim::DocVerbatim(DocNode *parent,const QString &context, 01582 const QString &text, Type t,bool isExample, 01583 const QString &exampleFile) 01584 : m_parent(parent), m_context(context), m_text(text), m_type(t), 01585 m_isExample(isExample), m_exampleFile(exampleFile), m_relPath(g_relPath) 01586 { 01587 } 01588 01589 01590 //--------------------------------------------------------------------------- 01591 01592 void DocInclude::parse() 01593 { 01594 DBG(("DocInclude::parse(file=%s,text=%s)\n",m_file.data(),m_text.data())); 01595 switch(m_type) 01596 { 01597 case IncWithLines: 01598 // fall through 01599 case Include: 01600 // fall through 01601 case DontInclude: 01602 readTextFileByName(m_file,m_text); 01603 g_includeFileText = m_text; 01604 g_includeFileOffset = 0; 01605 g_includeFileLength = m_text.length(); 01606 //printf("g_includeFile=<<%s>>\n",g_includeFileText.data()); 01607 break; 01608 case VerbInclude: 01609 // fall through 01610 case HtmlInclude: 01611 readTextFileByName(m_file,m_text); 01612 break; 01613 } 01614 } 01615 01616 //--------------------------------------------------------------------------- 01617 01618 void DocIncOperator::parse() 01619 { 01620 const char *p = g_includeFileText; 01621 uint l = g_includeFileLength; 01622 uint o = g_includeFileOffset; 01623 DBG(("DocIncOperator::parse() text=%s off=%d len=%d\n",p,o,l)); 01624 uint so = o,bo; 01625 bool nonEmpty = FALSE; 01626 switch(type()) 01627 { 01628 case Line: 01629 while (o<l) 01630 { 01631 char c = p[o]; 01632 if (c=='\n') 01633 { 01634 if (nonEmpty) break; // we have a pattern to match 01635 so=o+1; // no pattern, skip empty line 01636 } 01637 else if (!isspace((uchar)c)) // no white space char 01638 { 01639 nonEmpty=TRUE; 01640 } 01641 o++; 01642 } 01643 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1) 01644 { 01645 m_text = g_includeFileText.mid(so,o-so); 01646 DBG(("DocIncOperator::parse() Line: %s\n",m_text.data())); 01647 } 01648 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line 01649 break; 01650 case SkipLine: 01651 while (o<l) 01652 { 01653 so=o; 01654 while (o<l) 01655 { 01656 char c = p[o]; 01657 if (c=='\n') 01658 { 01659 if (nonEmpty) break; // we have a pattern to match 01660 so=o+1; // no pattern, skip empty line 01661 } 01662 else if (!isspace((uchar)c)) // no white space char 01663 { 01664 nonEmpty=TRUE; 01665 } 01666 o++; 01667 } 01668 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1) 01669 { 01670 m_text = g_includeFileText.mid(so,o-so); 01671 DBG(("DocIncOperator::parse() SkipLine: %s\n",m_text.data())); 01672 break; 01673 } 01674 o++; // skip new line 01675 } 01676 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line 01677 break; 01678 case Skip: 01679 while (o<l) 01680 { 01681 so=o; 01682 while (o<l) 01683 { 01684 char c = p[o]; 01685 if (c=='\n') 01686 { 01687 if (nonEmpty) break; // we have a pattern to match 01688 so=o+1; // no pattern, skip empty line 01689 } 01690 else if (!isspace((uchar)c)) // no white space char 01691 { 01692 nonEmpty=TRUE; 01693 } 01694 o++; 01695 } 01696 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1) 01697 { 01698 break; 01699 } 01700 o++; // skip new line 01701 } 01702 g_includeFileOffset = so; // set pointer to start of new line 01703 break; 01704 case Until: 01705 bo=o; 01706 while (o<l) 01707 { 01708 so=o; 01709 while (o<l) 01710 { 01711 char c = p[o]; 01712 if (c=='\n') 01713 { 01714 if (nonEmpty) break; // we have a pattern to match 01715 so=o+1; // no pattern, skip empty line 01716 } 01717 else if (!isspace((uchar)c)) // no white space char 01718 { 01719 nonEmpty=TRUE; 01720 } 01721 o++; 01722 } 01723 if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1) 01724 { 01725 m_text = g_includeFileText.mid(bo,o-bo); 01726 DBG(("DocIncOperator::parse() Until: %s\n",m_text.data())); 01727 break; 01728 } 01729 o++; // skip new line 01730 } 01731 g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line 01732 break; 01733 } 01734 } 01735 01736 //--------------------------------------------------------------------------- 01737 01738 void DocCopy::parse() 01739 { 01740 QString doc,brief; 01741 Definition *def; 01742 if (findDocsForMemberOrCompound(m_link,&doc,&brief,&def)) 01743 { 01744 if (g_copyStack.findRef(def)==-1) // definition not parsed earlier 01745 { 01746 docParserPushContext(); 01747 if (def->definitionType()==Definition::TypeMember && def->getOuterScope()) 01748 { 01749 g_context=def->getOuterScope()->name(); 01750 } 01751 else 01752 { 01753 g_context=def->name(); 01754 } 01755 g_styleStack.clear(); 01756 g_nodeStack.clear(); 01757 g_copyStack.append(def); 01758 // make sure the descriptions end with a newline, so the parser will correctly 01759 // handle them in all cases. 01760 //printf("doc='%s'\n",doc.data()); 01761 //printf("brief='%s'\n",brief.data()); 01762 brief+='\n'; 01763 doc+='\n'; 01764 internalValidatingParseDoc(this,m_children,brief); 01765 internalValidatingParseDoc(this,m_children,doc); 01766 g_copyStack.remove(def); 01767 ASSERT(g_styleStack.isEmpty()); 01768 ASSERT(g_nodeStack.isEmpty()); 01769 docParserPopContext(TRUE); 01770 } 01771 else // oops, recursion 01772 { 01773 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: recursive call chain of \\copydoc commands detected at %d\n", 01774 doctokenizerYYlineno); 01775 } 01776 } 01777 else 01778 { 01779 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: target %s of \\copydoc command not found", 01780 m_link.data()); 01781 } 01782 } 01783 01784 //--------------------------------------------------------------------------- 01785 01786 DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) : 01787 m_parent(parent), m_id(id), m_key(key), m_relPath(g_relPath) 01788 { 01789 } 01790 01791 bool DocXRefItem::parse() 01792 { 01793 QString listName; 01794 RefList *refList = Doxygen::xrefLists->find(m_key); 01795 if (refList && 01796 ( 01797 // either not a built-in list or the list is enabled 01798 (m_key!="todo" || Config_getBool("GENERATE_TODOLIST")) && 01799 (m_key!="test" || Config_getBool("GENERATE_TESTLIST")) && 01800 (m_key!="bug" || Config_getBool("GENERATE_BUGLIST")) && 01801 (m_key!="deprecated" || Config_getBool("GENERATE_DEPRECATEDLIST")) 01802 ) 01803 ) 01804 { 01805 RefItem *item = refList->getRefItem(m_id); 01806 ASSERT(item!=0); 01807 if (item) 01808 { 01809 if (g_memberDef && g_memberDef->name().at(0)=='@') 01810 { 01811 m_file = "@"; // can't cross reference anonymous enum 01812 m_anchor = "@"; 01813 } 01814 else 01815 { 01816 m_file = refList->listName(); 01817 m_anchor = item->listAnchor; 01818 } 01819 m_title = refList->sectionTitle(); 01820 //printf("DocXRefItem: file=%s anchor=%s title=%s\n", 01821 // m_file.data(),m_anchor.data(),m_title.data()); 01822 01823 if (!item->text.isEmpty()) 01824 { 01825 docParserPushContext(); 01826 internalValidatingParseDoc(this,m_children,item->text); 01827 docParserPopContext(); 01828 } 01829 } 01830 return TRUE; 01831 } 01832 return FALSE; 01833 } 01834 01835 //--------------------------------------------------------------------------- 01836 01837 DocFormula::DocFormula(DocNode *parent,int id) : 01838 m_parent(parent), m_relPath(g_relPath) 01839 { 01840 QString formCmd; 01841 formCmd.sprintf("\\form#%d",id); 01842 Formula *formula=Doxygen::formulaNameDict[formCmd]; 01843 if (formula) 01844 { 01845 m_id = formula->getId(); 01846 m_name.sprintf("form_%d",m_id); 01847 m_text = formula->getFormulaText(); 01848 } 01849 } 01850 01851 //--------------------------------------------------------------------------- 01852 01853 //int DocLanguage::parse() 01854 //{ 01855 // int retval; 01856 // DBG(("DocLanguage::parse() start\n")); 01857 // g_nodeStack.push(this); 01858 // 01859 // // parse one or more paragraphs 01860 // bool isFirst=TRUE; 01861 // DocPara *par=0; 01862 // do 01863 // { 01864 // par = new DocPara(this); 01865 // if (isFirst) { par->markFirst(); isFirst=FALSE; } 01866 // m_children.append(par); 01867 // retval=par->parse(); 01868 // } 01869 // while (retval==TK_NEWPARA); 01870 // if (par) par->markLast(); 01871 // 01872 // DBG(("DocLanguage::parse() end\n")); 01873 // DocNode *n = g_nodeStack.pop(); 01874 // ASSERT(n==this); 01875 // return retval; 01876 //} 01877 01878 //--------------------------------------------------------------------------- 01879 01880 void DocSecRefItem::parse() 01881 { 01882 DBG(("DocSecRefItem::parse() start\n")); 01883 g_nodeStack.push(this); 01884 01885 doctokenizerYYsetStateTitle(); 01886 int tok; 01887 while ((tok=doctokenizerYYlex())) 01888 { 01889 if (!defaultHandleToken(this,tok,m_children)) 01890 { 01891 switch (tok) 01892 { 01893 case TK_COMMAND: 01894 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\refitem", 01895 g_token->name.data()); 01896 break; 01897 case TK_SYMBOL: 01898 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 01899 g_token->name.data()); 01900 break; 01901 default: 01902 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 01903 tokToString(tok)); 01904 break; 01905 } 01906 } 01907 } 01908 doctokenizerYYsetStatePara(); 01909 handlePendingStyleCommands(this,m_children); 01910 01911 SectionInfo *sec=0; 01912 if (!m_target.isEmpty()) 01913 { 01914 sec=Doxygen::sectionDict[m_target]; 01915 if (sec) 01916 { 01917 m_file = sec->fileName; 01918 m_anchor = sec->label; 01919 if (g_sectionDict && g_sectionDict->find(m_target)==0) 01920 { 01921 g_sectionDict->insert(m_target,sec); 01922 } 01923 } 01924 else 01925 { 01926 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning reference to unknown section %s", 01927 m_target.data()); 01928 } 01929 } 01930 else 01931 { 01932 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning reference to empty target"); 01933 } 01934 01935 DBG(("DocSecRefItem::parse() end\n")); 01936 DocNode *n = g_nodeStack.pop(); 01937 ASSERT(n==this); 01938 } 01939 01940 //--------------------------------------------------------------------------- 01941 01942 void DocSecRefList::parse() 01943 { 01944 DBG(("DocSecRefList::parse() start\n")); 01945 g_nodeStack.push(this); 01946 01947 int tok=doctokenizerYYlex(); 01948 // skip white space 01949 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 01950 // handle items 01951 while (tok) 01952 { 01953 if (tok==TK_COMMAND) 01954 { 01955 switch (Mappers::cmdMapper->map(g_token->name)) 01956 { 01957 case CMD_SECREFITEM: 01958 { 01959 int tok=doctokenizerYYlex(); 01960 if (tok!=TK_WHITESPACE) 01961 { 01962 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after \\refitem command"); 01963 break; 01964 } 01965 tok=doctokenizerYYlex(); 01966 if (tok!=TK_WORD && tok!=TK_LNKWORD) 01967 { 01968 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of \\refitem", 01969 tokToString(tok)); 01970 break; 01971 } 01972 01973 DocSecRefItem *item = new DocSecRefItem(this,g_token->name); 01974 m_children.append(item); 01975 item->parse(); 01976 } 01977 break; 01978 case CMD_ENDSECREFLIST: 01979 goto endsecreflist; 01980 default: 01981 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\secreflist", 01982 g_token->name.data()); 01983 goto endsecreflist; 01984 } 01985 } 01986 else if (tok==TK_WHITESPACE) 01987 { 01988 // ignore whitespace 01989 } 01990 else 01991 { 01992 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s inside section reference list", 01993 tokToString(tok)); 01994 goto endsecreflist; 01995 } 01996 tok=doctokenizerYYlex(); 01997 } 01998 01999 endsecreflist: 02000 DBG(("DocSecRefList::parse() end\n")); 02001 DocNode *n = g_nodeStack.pop(); 02002 ASSERT(n==this); 02003 } 02004 02005 //--------------------------------------------------------------------------- 02006 02007 DocInternalRef::DocInternalRef(DocNode *parent,const QString &ref) 02008 : m_parent(parent), m_relPath(g_relPath) 02009 { 02010 int i=ref.find('#'); 02011 if (i!=-1) 02012 { 02013 m_anchor = ref.right(ref.length()-i-1); 02014 m_file = ref.left(i); 02015 } 02016 else 02017 { 02018 m_file = ref; 02019 } 02020 } 02021 02022 void DocInternalRef::parse() 02023 { 02024 g_nodeStack.push(this); 02025 DBG(("DocInternalRef::parse() start\n")); 02026 02027 int tok; 02028 while ((tok=doctokenizerYYlex())) 02029 { 02030 if (!defaultHandleToken(this,tok,m_children)) 02031 { 02032 switch (tok) 02033 { 02034 case TK_COMMAND: 02035 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\ref", 02036 g_token->name.data()); 02037 break; 02038 case TK_SYMBOL: 02039 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02040 g_token->name.data()); 02041 break; 02042 default: 02043 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02044 tokToString(tok)); 02045 break; 02046 } 02047 } 02048 } 02049 02050 handlePendingStyleCommands(this,m_children); 02051 DBG(("DocInternalRef::parse() end\n")); 02052 DocNode *n=g_nodeStack.pop(); 02053 ASSERT(n==this); 02054 } 02055 02056 //--------------------------------------------------------------------------- 02057 02058 DocRef::DocRef(DocNode *parent,const QString &target,const QString &context) : 02059 m_parent(parent), m_refToSection(FALSE), m_refToAnchor(FALSE) 02060 { 02061 Definition *compound = 0; 02062 QCString anchor; 02063 ASSERT(!target.isEmpty()); 02064 m_relPath = g_relPath; 02065 SectionInfo *sec = Doxygen::sectionDict[target]; 02066 if (sec) // ref to section or anchor 02067 { 02068 m_text = sec->title; 02069 if (m_text.isEmpty()) m_text = sec->label; 02070 02071 m_ref = sec->ref; 02072 m_file = stripKnownExtensions(sec->fileName); 02073 if (sec->type!=SectionInfo::Page) m_anchor = sec->label; 02074 m_refToAnchor = sec->type==SectionInfo::Anchor; 02075 m_refToSection = sec->type!=SectionInfo::Anchor; 02076 //printf("m_text=%s,m_ref=%s,m_file=%s,m_refToAnchor=%d\n", 02077 // m_text.data(),m_ref.data(),m_file.data(),m_refToAnchor); 02078 return; 02079 } 02080 else if (resolveLink(context,target,TRUE,&compound,anchor)) 02081 { 02082 bool isFile = compound ? 02083 (compound->definitionType()==Definition::TypeFile ? TRUE : FALSE) : 02084 FALSE; 02085 m_text = linkToText(target,isFile); 02086 m_anchor = anchor; 02087 if (compound && compound->isLinkable()) // ref to compound 02088 { 02089 if (anchor.isEmpty() && /* compound link */ 02090 compound->definitionType()==Definition::TypeGroup && /* is group */ 02091 ((GroupDef *)compound)->groupTitle() /* with title */ 02092 ) 02093 { 02094 m_text=((GroupDef *)compound)->groupTitle(); // use group's title as link 02095 } 02096 else if (compound->definitionType()==Definition::TypeMember && 02097 ((MemberDef*)compound)->isObjCMethod()) 02098 { 02099 // Objective C Method 02100 MemberDef *member = (MemberDef*)compound; 02101 bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE; 02102 m_text = member->objCMethodName(localLink,g_inSeeBlock); 02103 } 02104 02105 m_file = compound->getOutputFileBase(); 02106 m_ref = compound->getReference(); 02107 return; 02108 } 02109 else if (compound->definitionType()==Definition::TypeFile && 02110 ((FileDef*)compound)->generateSourceFile() 02111 ) // undocumented file that has source code we can link to 02112 { 02113 m_file = compound->getSourceFileBase(); 02114 m_ref = compound->getReference(); 02115 return; 02116 } 02117 } 02118 m_text = linkToText(target,FALSE); 02119 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unable to resolve reference to `%s' for \\ref command", 02120 target.data()); 02121 } 02122 02123 static void flattenParagraphs(QList<DocNode> &children) 02124 { 02125 QListIterator<DocNode> li(children); 02126 QList<DocNode> newChildren; 02127 DocNode *dn; 02128 for (li.toFirst();(dn=li.current());++li) 02129 { 02130 if (dn->kind()==DocNode::Kind_Para) 02131 { 02132 DocPara *para = (DocPara*)dn; 02133 QList<DocNode> ¶Children = para->children(); 02134 paraChildren.setAutoDelete(FALSE); // unlink children from paragraph node 02135 QListIterator<DocNode> li2(paraChildren); 02136 DocNode *dn2; 02137 for (li2.toFirst();(dn2=li2.current());++li2) 02138 { 02139 newChildren.append(dn2); // add them to new node 02140 } 02141 } 02142 } 02143 children.clear(); 02144 QListIterator<DocNode> li3(newChildren); 02145 for (li3.toFirst();(dn=li3.current());++li3) 02146 { 02147 children.append(dn); 02148 } 02149 } 02150 02151 void DocRef::parse() 02152 { 02153 g_nodeStack.push(this); 02154 DBG(("DocRef::parse() start\n")); 02155 02156 int tok; 02157 while ((tok=doctokenizerYYlex())) 02158 { 02159 if (!defaultHandleToken(this,tok,m_children)) 02160 { 02161 switch (tok) 02162 { 02163 case TK_COMMAND: 02164 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\ref", 02165 g_token->name.data()); 02166 break; 02167 case TK_SYMBOL: 02168 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02169 g_token->name.data()); 02170 break; 02171 case TK_HTMLTAG: 02172 break; 02173 default: 02174 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02175 tokToString(tok)); 02176 break; 02177 } 02178 } 02179 } 02180 02181 if (m_children.isEmpty() && !m_text.isEmpty()) 02182 { 02183 g_insideHtmlLink=TRUE; 02184 docParserPushContext(); 02185 internalValidatingParseDoc(this,m_children,m_text); 02186 docParserPopContext(); 02187 g_insideHtmlLink=FALSE; 02188 flattenParagraphs(m_children); 02189 } 02190 02191 handlePendingStyleCommands(this,m_children); 02192 02193 DocNode *n=g_nodeStack.pop(); 02194 ASSERT(n==this); 02195 } 02196 02197 //--------------------------------------------------------------------------- 02198 02199 DocLink::DocLink(DocNode *parent,const QString &target) : 02200 m_parent(parent) 02201 { 02202 Definition *compound; 02203 //PageInfo *page; 02204 QCString anchor; 02205 m_refText = target; 02206 m_relPath = g_relPath; 02207 if (!m_refText.isEmpty() && m_refText.at(0)=='#') 02208 { 02209 m_refText = m_refText.right(m_refText.length()-1); 02210 } 02211 if (resolveLink(g_context,stripKnownExtensions(target),g_inSeeBlock, 02212 &compound,anchor)) 02213 { 02214 m_anchor = anchor; 02215 if (compound && compound->isLinkable()) 02216 { 02217 m_file = compound->getOutputFileBase(); 02218 m_ref = compound->getReference(); 02219 } 02220 else if (compound->definitionType()==Definition::TypeFile && 02221 ((FileDef*)compound)->generateSourceFile() 02222 ) // undocumented file that has source code we can link to 02223 { 02224 m_file = compound->getSourceFileBase(); 02225 m_ref = compound->getReference(); 02226 } 02227 return; 02228 } 02229 02230 // bogus link target 02231 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unable to resolve link to `%s' for \\link command", 02232 target.data()); 02233 } 02234 02235 02236 QString DocLink::parse(bool isJavaLink,bool isXmlLink) 02237 { 02238 QString result; 02239 g_nodeStack.push(this); 02240 DBG(("DocLink::parse() start\n")); 02241 02242 int tok; 02243 while ((tok=doctokenizerYYlex())) 02244 { 02245 if (!defaultHandleToken(this,tok,m_children,FALSE)) 02246 { 02247 switch (tok) 02248 { 02249 case TK_COMMAND: 02250 switch (Mappers::cmdMapper->map(g_token->name)) 02251 { 02252 case CMD_ENDLINK: 02253 if (isJavaLink) 02254 { 02255 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: {@link.. ended with @endlink command"); 02256 } 02257 goto endlink; 02258 default: 02259 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\link", 02260 g_token->name.data()); 02261 break; 02262 } 02263 break; 02264 case TK_SYMBOL: 02265 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02266 g_token->name.data()); 02267 break; 02268 case TK_HTMLTAG: 02269 if (g_token->name!="see" || !isXmlLink) 02270 { 02271 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected xml/html command %s found", 02272 g_token->name.data()); 02273 } 02274 goto endlink; 02275 case TK_LNKWORD: 02276 case TK_WORD: 02277 if (isJavaLink) // special case to detect closing } 02278 { 02279 QString w = g_token->name; 02280 int p; 02281 if (w=="}") 02282 { 02283 goto endlink; 02284 } 02285 else if ((p=w.find('}'))!=-1) 02286 { 02287 uint l=w.length(); 02288 m_children.append(new DocWord(this,w.left(p))); 02289 if ((uint)p<l-1) // something left after the } (for instance a .) 02290 { 02291 result=w.right(l-p-1); 02292 } 02293 goto endlink; 02294 } 02295 } 02296 m_children.append(new DocWord(this,g_token->name)); 02297 break; 02298 default: 02299 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02300 tokToString(tok)); 02301 break; 02302 } 02303 } 02304 } 02305 if (tok==0) 02306 { 02307 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside" 02308 " link command\n"); 02309 } 02310 endlink: 02311 02312 if (m_children.isEmpty()) // no link text 02313 { 02314 m_children.append(new DocWord(this,m_refText)); 02315 } 02316 02317 handlePendingStyleCommands(this,m_children); 02318 DBG(("DocLink::parse() end\n")); 02319 DocNode *n=g_nodeStack.pop(); 02320 ASSERT(n==this); 02321 return result; 02322 } 02323 02324 02325 //--------------------------------------------------------------------------- 02326 02327 DocDotFile::DocDotFile(DocNode *parent,const QString &name,const QString &context) : 02328 m_parent(parent), m_name(name), m_relPath(g_relPath), m_context(context) 02329 { 02330 } 02331 02332 void DocDotFile::parse() 02333 { 02334 g_nodeStack.push(this); 02335 DBG(("DocDotFile::parse() start\n")); 02336 02337 doctokenizerYYsetStateTitle(); 02338 int tok; 02339 while ((tok=doctokenizerYYlex())) 02340 { 02341 if (!defaultHandleToken(this,tok,m_children)) 02342 { 02343 switch (tok) 02344 { 02345 case TK_COMMAND: 02346 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\dotfile", 02347 g_token->name.data()); 02348 break; 02349 case TK_SYMBOL: 02350 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02351 g_token->name.data()); 02352 break; 02353 default: 02354 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02355 tokToString(tok)); 02356 break; 02357 } 02358 } 02359 } 02360 tok=doctokenizerYYlex(); 02361 while (tok==TK_WORD) // there are values following the title 02362 { 02363 if (g_token->name=="width") 02364 { 02365 m_width=g_token->chars; 02366 } 02367 else if (g_token->name=="height") 02368 { 02369 m_height=g_token->chars; 02370 } 02371 else 02372 { 02373 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unknown option %s after image title", 02374 g_token->name.data()); 02375 } 02376 tok=doctokenizerYYlex(); 02377 } 02378 ASSERT(tok==0); 02379 doctokenizerYYsetStatePara(); 02380 handlePendingStyleCommands(this,m_children); 02381 02382 bool ambig; 02383 FileDef *fd = findFileDef(Doxygen::dotFileNameDict,m_name,ambig); 02384 if (fd) 02385 { 02386 m_file = fd->absFilePath(); 02387 } 02388 else if (ambig) 02389 { 02390 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included dot file name %s is ambigious.\n" 02391 "Possible candidates:\n%s",m_name.data(), 02392 showFileDefMatches(Doxygen::exampleNameDict,m_name).data() 02393 ); 02394 } 02395 else 02396 { 02397 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: included dot file %s is not found " 02398 "in any of the paths specified via DOTFILE_DIRS!",m_name.data()); 02399 } 02400 02401 DBG(("DocDotFile::parse() end\n")); 02402 DocNode *n=g_nodeStack.pop(); 02403 ASSERT(n==this); 02404 } 02405 02406 02407 //--------------------------------------------------------------------------- 02408 02409 DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QString &name,Type t) : 02410 m_parent(parent), m_attribs(attribs), m_name(name), 02411 m_type(t), m_relPath(g_relPath) 02412 { 02413 } 02414 02415 void DocImage::parse() 02416 { 02417 g_nodeStack.push(this); 02418 DBG(("DocImage::parse() start\n")); 02419 02420 // parse title 02421 doctokenizerYYsetStateTitle(); 02422 int tok; 02423 while ((tok=doctokenizerYYlex())) 02424 { 02425 if (tok==TK_WORD && (g_token->name=="width=" || g_token->name=="height=")) 02426 { 02427 // special case: no title, but we do have a size indicator 02428 doctokenizerYYsetStateTitleAttrValue(); 02429 // strip = 02430 g_token->name=g_token->name.left(g_token->name.length()-1); 02431 break; 02432 } 02433 if (!defaultHandleToken(this,tok,m_children)) 02434 { 02435 switch (tok) 02436 { 02437 case TK_COMMAND: 02438 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a \\image", 02439 g_token->name.data()); 02440 break; 02441 case TK_SYMBOL: 02442 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02443 g_token->name.data()); 02444 break; 02445 default: 02446 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02447 tokToString(tok)); 02448 break; 02449 } 02450 } 02451 } 02452 // parse size attributes 02453 tok=doctokenizerYYlex(); 02454 while (tok==TK_WORD) // there are values following the title 02455 { 02456 if (g_token->name=="width") 02457 { 02458 m_width=g_token->chars; 02459 } 02460 else if (g_token->name=="height") 02461 { 02462 m_height=g_token->chars; 02463 } 02464 else 02465 { 02466 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unknown option %s after image title", 02467 g_token->name.data()); 02468 } 02469 tok=doctokenizerYYlex(); 02470 } 02471 doctokenizerYYsetStatePara(); 02472 02473 handlePendingStyleCommands(this,m_children); 02474 DBG(("DocImage::parse() end\n")); 02475 DocNode *n=g_nodeStack.pop(); 02476 ASSERT(n==this); 02477 } 02478 02479 02480 //--------------------------------------------------------------------------- 02481 02482 int DocHtmlHeader::parse() 02483 { 02484 int retval=RetVal_OK; 02485 g_nodeStack.push(this); 02486 DBG(("DocHtmlHeader::parse() start\n")); 02487 02488 int tok; 02489 while ((tok=doctokenizerYYlex())) 02490 { 02491 if (!defaultHandleToken(this,tok,m_children)) 02492 { 02493 switch (tok) 02494 { 02495 case TK_COMMAND: 02496 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <h%d> tag", 02497 g_token->name.data(),m_level); 02498 break; 02499 case TK_HTMLTAG: 02500 { 02501 int tagId=Mappers::htmlTagMapper->map(g_token->name); 02502 if (tagId==HTML_H1 && g_token->endTag) // found </h1> tag 02503 { 02504 if (m_level!=1) 02505 { 02506 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h1>", 02507 m_level); 02508 } 02509 goto endheader; 02510 } 02511 else if (tagId==HTML_H2 && g_token->endTag) // found </h2> tag 02512 { 02513 if (m_level!=2) 02514 { 02515 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h2>", 02516 m_level); 02517 } 02518 goto endheader; 02519 } 02520 else if (tagId==HTML_H3 && g_token->endTag) // found </h3> tag 02521 { 02522 if (m_level!=3) 02523 { 02524 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h3>", 02525 m_level); 02526 } 02527 goto endheader; 02528 } 02529 else if (tagId==HTML_H4 && g_token->endTag) // found </h4> tag 02530 { 02531 if (m_level!=4) 02532 { 02533 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h4>", 02534 m_level); 02535 } 02536 goto endheader; 02537 } 02538 else if (tagId==HTML_H5 && g_token->endTag) // found </h5> tag 02539 { 02540 if (m_level!=5) 02541 { 02542 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h5>", 02543 m_level); 02544 } 02545 goto endheader; 02546 } 02547 else if (tagId==HTML_H6 && g_token->endTag) // found </h6> tag 02548 { 02549 if (m_level!=6) 02550 { 02551 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: <h%d> ended with </h6>", 02552 m_level); 02553 } 02554 goto endheader; 02555 } 02556 else if (tagId==HTML_A) 02557 { 02558 if (!g_token->endTag) 02559 { 02560 handleAHref(this,m_children,g_token->attribs); 02561 } 02562 } 02563 else if (tagId==HTML_BR) 02564 { 02565 DocLineBreak *lb = new DocLineBreak(this); 02566 m_children.append(lb); 02567 } 02568 else 02569 { 02570 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <h%d> context", 02571 g_token->endTag?"/":"",g_token->name.data(),m_level); 02572 } 02573 02574 } 02575 break; 02576 case TK_SYMBOL: 02577 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02578 g_token->name.data()); 02579 break; 02580 default: 02581 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02582 tokToString(tok)); 02583 break; 02584 } 02585 } 02586 } 02587 if (tok==0) 02588 { 02589 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside" 02590 " <h%d> tag\n",m_level); 02591 } 02592 endheader: 02593 handlePendingStyleCommands(this,m_children); 02594 DBG(("DocHtmlHeader::parse() end\n")); 02595 DocNode *n=g_nodeStack.pop(); 02596 ASSERT(n==this); 02597 return retval; 02598 } 02599 02600 //--------------------------------------------------------------------------- 02601 02602 int DocHRef::parse() 02603 { 02604 int retval=RetVal_OK; 02605 g_nodeStack.push(this); 02606 DBG(("DocHRef::parse() start\n")); 02607 02608 int tok; 02609 while ((tok=doctokenizerYYlex())) 02610 { 02611 if (!defaultHandleToken(this,tok,m_children)) 02612 { 02613 switch (tok) 02614 { 02615 case TK_COMMAND: 02616 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <a>..</a> block", 02617 g_token->name.data()); 02618 break; 02619 case TK_SYMBOL: 02620 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02621 g_token->name.data()); 02622 break; 02623 case TK_HTMLTAG: 02624 { 02625 int tagId=Mappers::htmlTagMapper->map(g_token->name); 02626 if (tagId==HTML_A && g_token->endTag) // found </a> tag 02627 { 02628 goto endhref; 02629 } 02630 else 02631 { 02632 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <a href=...> context", 02633 g_token->endTag?"/":"",g_token->name.data(),doctokenizerYYlineno); 02634 } 02635 } 02636 break; 02637 default: 02638 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02639 tokToString(tok),doctokenizerYYlineno); 02640 break; 02641 } 02642 } 02643 } 02644 if (tok==0) 02645 { 02646 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside" 02647 " <a href=...> tag",doctokenizerYYlineno); 02648 } 02649 endhref: 02650 handlePendingStyleCommands(this,m_children); 02651 DBG(("DocHRef::parse() end\n")); 02652 DocNode *n=g_nodeStack.pop(); 02653 ASSERT(n==this); 02654 return retval; 02655 } 02656 02657 //--------------------------------------------------------------------------- 02658 02659 int DocInternal::parse(int level) 02660 { 02661 int retval=RetVal_OK; 02662 g_nodeStack.push(this); 02663 DBG(("DocInternal::parse() start\n")); 02664 02665 // first parse any number of paragraphs 02666 bool isFirst=TRUE; 02667 DocPara *lastPar=0; 02668 do 02669 { 02670 DocPara *par = new DocPara(this); 02671 if (isFirst) { par->markFirst(); isFirst=FALSE; } 02672 retval=par->parse(); 02673 if (!par->isEmpty()) 02674 { 02675 m_children.append(par); 02676 lastPar=par; 02677 } 02678 else 02679 { 02680 delete par; 02681 } 02682 if (retval==TK_LISTITEM) 02683 { 02684 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid list item found",doctokenizerYYlineno); 02685 } 02686 } while (retval!=0 && 02687 retval!=RetVal_Section && 02688 retval!=RetVal_Subsection && 02689 retval!=RetVal_Subsubsection && 02690 retval!=RetVal_Paragraph 02691 ); 02692 if (lastPar) lastPar->markLast(); 02693 02694 // then parse any number of level-n sections 02695 while ((level==1 && retval==RetVal_Section) || 02696 (level==2 && retval==RetVal_Subsection) || 02697 (level==3 && retval==RetVal_Subsubsection) || 02698 (level==4 && retval==RetVal_Paragraph) 02699 ) 02700 { 02701 DocSection *s=new DocSection(this,level,g_token->sectionId); 02702 m_children.append(s); 02703 retval = s->parse(); 02704 } 02705 02706 if (retval==RetVal_Internal) 02707 { 02708 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: \\internal command found inside internal section"); 02709 } 02710 02711 DBG(("DocInternal::parse() end\n")); 02712 DocNode *n=g_nodeStack.pop(); 02713 ASSERT(n==this); 02714 return retval; 02715 } 02716 02717 //--------------------------------------------------------------------------- 02718 02719 int DocIndexEntry::parse() 02720 { 02721 int retval=RetVal_OK; 02722 g_nodeStack.push(this); 02723 DBG(("DocIndexEntry::parse() start\n")); 02724 int tok=doctokenizerYYlex(); 02725 if (tok!=TK_WHITESPACE) 02726 { 02727 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after \\addindex command"); 02728 goto endindexentry; 02729 } 02730 doctokenizerYYsetStateTitle(); 02731 m_entry=""; 02732 while ((tok=doctokenizerYYlex())) 02733 { 02734 switch (tok) 02735 { 02736 case TK_WHITESPACE: 02737 m_entry+=" "; 02738 break; 02739 case TK_WORD: 02740 case TK_LNKWORD: 02741 m_entry+=g_token->name; 02742 break; 02743 case TK_SYMBOL: 02744 { 02745 char letter='\0'; 02746 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name,&letter); 02747 switch (s) 02748 { 02749 case DocSymbol::BSlash: m_entry+='\\'; break; 02750 case DocSymbol::At: m_entry+='@'; break; 02751 case DocSymbol::Less: m_entry+='<'; break; 02752 case DocSymbol::Greater: m_entry+='>'; break; 02753 case DocSymbol::Amp: m_entry+='&'; break; 02754 case DocSymbol::Dollar: m_entry+='$'; break; 02755 case DocSymbol::Hash: m_entry+='#'; break; 02756 case DocSymbol::Percent: m_entry+='%'; break; 02757 case DocSymbol::Apos: m_entry+='\''; break; 02758 case DocSymbol::Quot: m_entry+='"'; break; 02759 case DocSymbol::Lsquo: m_entry+='`'; break; 02760 case DocSymbol::Rsquo: m_entry+='\''; break; 02761 case DocSymbol::Ldquo: m_entry+="``"; break; 02762 case DocSymbol::Rdquo: m_entry+="''"; break; 02763 case DocSymbol::Ndash: m_entry+="--"; break; 02764 case DocSymbol::Mdash: m_entry+="---"; break; 02765 default: 02766 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected symbol found as argument of \\addindex"); 02767 break; 02768 } 02769 } 02770 break; 02771 case TK_COMMAND: 02772 switch (Mappers::cmdMapper->map(g_token->name)) 02773 { 02774 case CMD_BSLASH: m_entry+='\\'; break; 02775 case CMD_AT: m_entry+='@'; break; 02776 case CMD_LESS: m_entry+='<'; break; 02777 case CMD_GREATER: m_entry+='>'; break; 02778 case CMD_AMP: m_entry+='&'; break; 02779 case CMD_DOLLAR: m_entry+='$'; break; 02780 case CMD_HASH: m_entry+='#'; break; 02781 case CMD_PERCENT: m_entry+='%'; break; 02782 default: 02783 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected command %s found as argument of \\addindex", 02784 g_token->name.data()); 02785 break; 02786 } 02787 break; 02788 default: 02789 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02790 tokToString(tok)); 02791 break; 02792 } 02793 } 02794 if (tok!=0) retval=tok; 02795 doctokenizerYYsetStatePara(); 02796 endindexentry: 02797 DBG(("DocIndexEntry::parse() end retval=%x\n",retval)); 02798 DocNode *n=g_nodeStack.pop(); 02799 ASSERT(n==this); 02800 return retval; 02801 } 02802 02803 //--------------------------------------------------------------------------- 02804 02805 int DocHtmlCaption::parse() 02806 { 02807 int retval=0; 02808 g_nodeStack.push(this); 02809 DBG(("DocHtmlCaption::parse() start\n")); 02810 int tok; 02811 while ((tok=doctokenizerYYlex())) 02812 { 02813 if (!defaultHandleToken(this,tok,m_children)) 02814 { 02815 switch (tok) 02816 { 02817 case TK_COMMAND: 02818 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <caption> tag", 02819 g_token->name.data()); 02820 break; 02821 case TK_SYMBOL: 02822 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 02823 g_token->name.data()); 02824 break; 02825 case TK_HTMLTAG: 02826 { 02827 int tagId=Mappers::htmlTagMapper->map(g_token->name); 02828 if (tagId==HTML_CAPTION && g_token->endTag) // found </caption> tag 02829 { 02830 retval = RetVal_OK; 02831 goto endcaption; 02832 } 02833 else 02834 { 02835 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <caption> context", 02836 g_token->endTag?"/":"",g_token->name.data()); 02837 } 02838 } 02839 break; 02840 default: 02841 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 02842 tokToString(tok)); 02843 break; 02844 } 02845 } 02846 } 02847 if (tok==0) 02848 { 02849 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside" 02850 " <caption> tag",doctokenizerYYlineno); 02851 } 02852 endcaption: 02853 handlePendingStyleCommands(this,m_children); 02854 DBG(("DocHtmlCaption::parse() end\n")); 02855 DocNode *n=g_nodeStack.pop(); 02856 ASSERT(n==this); 02857 return retval; 02858 } 02859 02860 //--------------------------------------------------------------------------- 02861 02862 int DocHtmlCell::parse() 02863 { 02864 int retval=RetVal_OK; 02865 g_nodeStack.push(this); 02866 DBG(("DocHtmlCell::parse() start\n")); 02867 02868 // parse one or more paragraphs 02869 bool isFirst=TRUE; 02870 DocPara *par=0; 02871 do 02872 { 02873 par = new DocPara(this); 02874 if (isFirst) { par->markFirst(); isFirst=FALSE; } 02875 m_children.append(par); 02876 retval=par->parse(); 02877 if (retval==TK_HTMLTAG) 02878 { 02879 int tagId=Mappers::htmlTagMapper->map(g_token->name); 02880 if (tagId==HTML_TD && g_token->endTag) // found </dt> tag 02881 { 02882 retval=TK_NEWPARA; // ignore the tag 02883 } 02884 else if (tagId==HTML_TH && g_token->endTag) // found </th> tag 02885 { 02886 retval=TK_NEWPARA; // ignore the tag 02887 } 02888 } 02889 } 02890 while (retval==TK_NEWPARA); 02891 if (par) par->markLast(); 02892 02893 DBG(("DocHtmlCell::parse() end\n")); 02894 DocNode *n=g_nodeStack.pop(); 02895 ASSERT(n==this); 02896 return retval; 02897 } 02898 02899 int DocHtmlCell::parseXml() 02900 { 02901 int retval=RetVal_OK; 02902 g_nodeStack.push(this); 02903 DBG(("DocHtmlCell::parseXml() start\n")); 02904 02905 // parse one or more paragraphs 02906 bool isFirst=TRUE; 02907 DocPara *par=0; 02908 do 02909 { 02910 par = new DocPara(this); 02911 if (isFirst) { par->markFirst(); isFirst=FALSE; } 02912 m_children.append(par); 02913 retval=par->parse(); 02914 if (retval==TK_HTMLTAG) 02915 { 02916 int tagId=Mappers::htmlTagMapper->map(g_token->name); 02917 if (tagId==XML_ITEM && g_token->endTag) // found </item> tag 02918 { 02919 retval=TK_NEWPARA; // ignore the tag 02920 } 02921 else if (tagId==XML_DESCRIPTION && g_token->endTag) // found </description> tag 02922 { 02923 retval=TK_NEWPARA; // ignore the tag 02924 } 02925 } 02926 } 02927 while (retval==TK_NEWPARA); 02928 if (par) par->markLast(); 02929 02930 DBG(("DocHtmlCell::parseXml() end\n")); 02931 DocNode *n=g_nodeStack.pop(); 02932 ASSERT(n==this); 02933 return retval; 02934 } 02935 02936 //--------------------------------------------------------------------------- 02937 02938 int DocHtmlRow::parse() 02939 { 02940 int retval=RetVal_OK; 02941 g_nodeStack.push(this); 02942 DBG(("DocHtmlRow::parse() start\n")); 02943 02944 bool isHeading=FALSE; 02945 bool isFirst=TRUE; 02946 DocHtmlCell *cell=0; 02947 02948 // get next token 02949 int tok=doctokenizerYYlex(); 02950 // skip whitespace 02951 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 02952 // should find a html tag now 02953 if (tok==TK_HTMLTAG) 02954 { 02955 int tagId=Mappers::htmlTagMapper->map(g_token->name); 02956 if (tagId==HTML_TD && !g_token->endTag) // found <td> tag 02957 { 02958 } 02959 else if (tagId==HTML_TH && !g_token->endTag) // found <th> tag 02960 { 02961 isHeading=TRUE; 02962 } 02963 else // found some other tag 02964 { 02965 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but " 02966 "found <%s> instead!",g_token->name.data()); 02967 doctokenizerYYpushBackHtmlTag(g_token->name); 02968 goto endrow; 02969 } 02970 } 02971 else if (tok==0) // premature end of comment 02972 { 02973 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" 02974 " for a html description title"); 02975 goto endrow; 02976 } 02977 else // token other than html token 02978 { 02979 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but found %s token instead!", 02980 tokToString(tok)); 02981 goto endrow; 02982 } 02983 02984 // parse one or more cells 02985 do 02986 { 02987 cell=new DocHtmlCell(this,g_token->attribs,isHeading); 02988 cell->markFirst(isFirst); 02989 isFirst=FALSE; 02990 m_children.append(cell); 02991 retval=cell->parse(); 02992 isHeading = retval==RetVal_TableHCell; 02993 } 02994 while (retval==RetVal_TableCell || retval==RetVal_TableHCell); 02995 if (cell) cell->markLast(TRUE); 02996 02997 endrow: 02998 DBG(("DocHtmlRow::parse() end\n")); 02999 DocNode *n=g_nodeStack.pop(); 03000 ASSERT(n==this); 03001 return retval; 03002 } 03003 03004 int DocHtmlRow::parseXml(bool isHeading) 03005 { 03006 int retval=RetVal_OK; 03007 g_nodeStack.push(this); 03008 DBG(("DocHtmlRow::parseXml() start\n")); 03009 03010 bool isFirst=TRUE; 03011 DocHtmlCell *cell=0; 03012 03013 // get next token 03014 int tok=doctokenizerYYlex(); 03015 // skip whitespace 03016 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 03017 // should find a html tag now 03018 if (tok==TK_HTMLTAG) 03019 { 03020 int tagId=Mappers::htmlTagMapper->map(g_token->name); 03021 if (tagId==XML_TERM && !g_token->endTag) // found <term> tag 03022 { 03023 } 03024 else if (tagId==XML_DESCRIPTION && !g_token->endTag) // found <description> tag 03025 { 03026 } 03027 else // found some other tag 03028 { 03029 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <term> or <description> tag but " 03030 "found <%s> instead!",g_token->name.data()); 03031 doctokenizerYYpushBackHtmlTag(g_token->name); 03032 goto endrow; 03033 } 03034 } 03035 else if (tok==0) // premature end of comment 03036 { 03037 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" 03038 " for a html description title"); 03039 goto endrow; 03040 } 03041 else // token other than html token 03042 { 03043 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but found %s token instead!", 03044 tokToString(tok)); 03045 goto endrow; 03046 } 03047 03048 do 03049 { 03050 cell=new DocHtmlCell(this,g_token->attribs,isHeading); 03051 cell->markFirst(isFirst); 03052 isFirst=FALSE; 03053 m_children.append(cell); 03054 retval=cell->parseXml(); 03055 } 03056 while (retval==RetVal_TableCell || retval==RetVal_TableHCell); 03057 if (cell) cell->markLast(TRUE); 03058 03059 endrow: 03060 DBG(("DocHtmlRow::parseXml() end\n")); 03061 DocNode *n=g_nodeStack.pop(); 03062 ASSERT(n==this); 03063 return retval; 03064 } 03065 03066 //--------------------------------------------------------------------------- 03067 03068 int DocHtmlTable::parse() 03069 { 03070 int retval=RetVal_OK; 03071 g_nodeStack.push(this); 03072 DBG(("DocHtmlTable::parse() start\n")); 03073 03074 getrow: 03075 // get next token 03076 int tok=doctokenizerYYlex(); 03077 // skip whitespace 03078 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 03079 // should find a html tag now 03080 if (tok==TK_HTMLTAG) 03081 { 03082 int tagId=Mappers::htmlTagMapper->map(g_token->name); 03083 if (tagId==HTML_TR && !g_token->endTag) // found <tr> tag 03084 { 03085 // no caption, just rows 03086 retval=RetVal_TableRow; 03087 } 03088 else if (tagId==HTML_CAPTION && !g_token->endTag) // found <caption> tag 03089 { 03090 if (m_caption) 03091 { 03092 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: table already has a caption, found another one"); 03093 } 03094 else 03095 { 03096 m_caption = new DocHtmlCaption(this,g_token->attribs); 03097 retval=m_caption->parse(); 03098 03099 if (retval==RetVal_OK) // caption was parsed ok 03100 { 03101 goto getrow; 03102 } 03103 } 03104 } 03105 else // found wrong token 03106 { 03107 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <tr> or <caption> tag but " 03108 "found <%s%s> instead!", g_token->endTag ? "/" : "", g_token->name.data()); 03109 } 03110 } 03111 else if (tok==0) // premature end of comment 03112 { 03113 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" 03114 " for a <tr> or <caption> tag"); 03115 } 03116 else // token other than html token 03117 { 03118 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <tr> tag but found %s token instead!", 03119 tokToString(tok)); 03120 } 03121 03122 // parse one or more rows 03123 while (retval==RetVal_TableRow) 03124 { 03125 DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs); 03126 m_children.append(tr); 03127 retval=tr->parse(); 03128 } 03129 03130 DBG(("DocHtmlTable::parse() end\n")); 03131 DocNode *n=g_nodeStack.pop(); 03132 ASSERT(n==this); 03133 return retval==RetVal_EndTable ? RetVal_OK : retval; 03134 } 03135 03136 int DocHtmlTable::parseXml() 03137 { 03138 int retval=RetVal_OK; 03139 g_nodeStack.push(this); 03140 DBG(("DocHtmlTable::parseXml() start\n")); 03141 03142 // get next token 03143 int tok=doctokenizerYYlex(); 03144 // skip whitespace 03145 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 03146 // should find a html tag now 03147 int tagId=0; 03148 bool isHeader=FALSE; 03149 if (tok==TK_HTMLTAG) 03150 { 03151 tagId=Mappers::htmlTagMapper->map(g_token->name); 03152 if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag 03153 { 03154 retval=RetVal_TableRow; 03155 } 03156 if (tagId==XML_LISTHEADER && !g_token->endTag) // found <listheader> tag 03157 { 03158 retval=RetVal_TableRow; 03159 isHeader=TRUE; 03160 } 03161 } 03162 03163 // parse one or more rows 03164 while (retval==RetVal_TableRow) 03165 { 03166 DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs); 03167 m_children.append(tr); 03168 retval=tr->parseXml(isHeader); 03169 isHeader=FALSE; 03170 } 03171 03172 DBG(("DocHtmlTable::parseXml() end\n")); 03173 DocNode *n=g_nodeStack.pop(); 03174 ASSERT(n==this); 03175 return retval==RetVal_EndTable ? RetVal_OK : retval; 03176 } 03177 03178 uint DocHtmlTable::numCols() const 03179 { 03180 uint cols=0; 03181 QListIterator<DocNode> cli(m_children); 03182 DocNode *n; 03183 for (cli.toFirst();(n=cli.current());++cli) 03184 { 03185 ASSERT(n->kind()==DocNode::Kind_HtmlRow); 03186 cols=QMAX(cols,((DocHtmlRow *)n)->numCells()); 03187 } 03188 return cols; 03189 } 03190 03191 void DocHtmlTable::accept(DocVisitor *v) 03192 { 03193 v->visitPre(this); 03194 // for HTML output we put the caption first 03195 if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v); 03196 QListIterator<DocNode> cli(m_children); 03197 DocNode *n; 03198 for (cli.toFirst();(n=cli.current());++cli) n->accept(v); 03199 // for other output formats we put the caption last 03200 if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v); 03201 v->visitPost(this); 03202 } 03203 03204 //--------------------------------------------------------------------------- 03205 03206 int DocHtmlDescTitle::parse() 03207 { 03208 int retval=0; 03209 g_nodeStack.push(this); 03210 DBG(("DocHtmlDescTitle::parse() start\n")); 03211 03212 int tok; 03213 while ((tok=doctokenizerYYlex())) 03214 { 03215 if (!defaultHandleToken(this,tok,m_children)) 03216 { 03217 switch (tok) 03218 { 03219 case TK_COMMAND: 03220 { 03221 QString cmdName=g_token->name; 03222 bool isJavaLink=FALSE; 03223 switch (Mappers::cmdMapper->map(cmdName)) 03224 { 03225 case CMD_REF: 03226 { 03227 int tok=doctokenizerYYlex(); 03228 if (tok!=TK_WHITESPACE) 03229 { 03230 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 03231 g_token->name.data()); 03232 } 03233 else 03234 { 03235 doctokenizerYYsetStateRef(); 03236 tok=doctokenizerYYlex(); // get the reference id 03237 if (tok!=TK_WORD) 03238 { 03239 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 03240 tokToString(tok),cmdName.data()); 03241 } 03242 else 03243 { 03244 DocRef *ref = new DocRef(this,g_token->name,g_context); 03245 m_children.append(ref); 03246 ref->parse(); 03247 } 03248 doctokenizerYYsetStatePara(); 03249 } 03250 } 03251 break; 03252 case CMD_JAVALINK: 03253 isJavaLink=TRUE; 03254 // fall through 03255 case CMD_LINK: 03256 { 03257 int tok=doctokenizerYYlex(); 03258 if (tok!=TK_WHITESPACE) 03259 { 03260 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 03261 cmdName.data()); 03262 } 03263 else 03264 { 03265 doctokenizerYYsetStateLink(); 03266 tok=doctokenizerYYlex(); 03267 if (tok!=TK_WORD) 03268 { 03269 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 03270 tokToString(tok),cmdName.data()); 03271 } 03272 else 03273 { 03274 doctokenizerYYsetStatePara(); 03275 DocLink *lnk = new DocLink(this,g_token->name); 03276 m_children.append(lnk); 03277 QString leftOver = lnk->parse(isJavaLink); 03278 if (!leftOver.isEmpty()) 03279 { 03280 m_children.append(new DocWord(this,leftOver)); 03281 } 03282 } 03283 } 03284 } 03285 03286 break; 03287 default: 03288 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <dt> tag", 03289 g_token->name.data()); 03290 } 03291 } 03292 break; 03293 case TK_SYMBOL: 03294 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 03295 g_token->name.data()); 03296 break; 03297 case TK_HTMLTAG: 03298 { 03299 int tagId=Mappers::htmlTagMapper->map(g_token->name); 03300 if (tagId==HTML_DD && !g_token->endTag) // found <dd> tag 03301 { 03302 retval = RetVal_DescData; 03303 goto endtitle; 03304 } 03305 else if (tagId==HTML_DT && g_token->endTag) 03306 { 03307 // ignore </dt> tag. 03308 } 03309 else if (tagId==HTML_DT) 03310 { 03311 // missing <dt> tag. 03312 retval = RetVal_DescTitle; 03313 goto endtitle; 03314 } 03315 else if (tagId==HTML_DL && g_token->endTag) 03316 { 03317 retval=RetVal_EndDesc; 03318 goto endtitle; 03319 } 03320 else 03321 { 03322 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <dt> context", 03323 g_token->endTag?"/":"",g_token->name.data()); 03324 } 03325 } 03326 break; 03327 default: 03328 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 03329 tokToString(tok)); 03330 break; 03331 } 03332 } 03333 } 03334 if (tok==0) 03335 { 03336 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected end of comment while inside" 03337 " <dt> tag"); 03338 } 03339 endtitle: 03340 handlePendingStyleCommands(this,m_children); 03341 DBG(("DocHtmlDescTitle::parse() end\n")); 03342 DocNode *n=g_nodeStack.pop(); 03343 ASSERT(n==this); 03344 return retval; 03345 } 03346 03347 //--------------------------------------------------------------------------- 03348 03349 int DocHtmlDescData::parse() 03350 { 03351 m_attribs = g_token->attribs; 03352 int retval=0; 03353 g_nodeStack.push(this); 03354 DBG(("DocHtmlDescData::parse() start\n")); 03355 03356 bool isFirst=TRUE; 03357 DocPara *par=0; 03358 do 03359 { 03360 par = new DocPara(this); 03361 if (isFirst) { par->markFirst(); isFirst=FALSE; } 03362 m_children.append(par); 03363 retval=par->parse(); 03364 } 03365 while (retval==TK_NEWPARA); 03366 if (par) par->markLast(); 03367 03368 DBG(("DocHtmlDescData::parse() end\n")); 03369 DocNode *n=g_nodeStack.pop(); 03370 ASSERT(n==this); 03371 return retval; 03372 } 03373 03374 //--------------------------------------------------------------------------- 03375 03376 int DocHtmlDescList::parse() 03377 { 03378 int retval=RetVal_OK; 03379 g_nodeStack.push(this); 03380 DBG(("DocHtmlDescList::parse() start\n")); 03381 03382 // get next token 03383 int tok=doctokenizerYYlex(); 03384 // skip whitespace 03385 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 03386 // should find a html tag now 03387 if (tok==TK_HTMLTAG) 03388 { 03389 int tagId=Mappers::htmlTagMapper->map(g_token->name); 03390 if (tagId==HTML_DT && !g_token->endTag) // found <dt> tag 03391 { 03392 // continue 03393 } 03394 else // found some other tag 03395 { 03396 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <dt> tag but " 03397 "found <%s> instead!",g_token->name.data()); 03398 doctokenizerYYpushBackHtmlTag(g_token->name); 03399 goto enddesclist; 03400 } 03401 } 03402 else if (tok==0) // premature end of comment 03403 { 03404 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" 03405 " for a html description title"); 03406 goto enddesclist; 03407 } 03408 else // token other than html token 03409 { 03410 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <dt> tag but found %s token instead!", 03411 tokToString(tok)); 03412 goto enddesclist; 03413 } 03414 03415 do 03416 { 03417 DocHtmlDescTitle *dt=new DocHtmlDescTitle(this,g_token->attribs); 03418 m_children.append(dt); 03419 DocHtmlDescData *dd=new DocHtmlDescData(this); 03420 m_children.append(dd); 03421 retval=dt->parse(); 03422 if (retval==RetVal_DescData) 03423 { 03424 retval=dd->parse(); 03425 } 03426 else if (retval!=RetVal_DescTitle) 03427 { 03428 // error 03429 break; 03430 } 03431 } while (retval==RetVal_DescTitle); 03432 03433 if (retval==0) 03434 { 03435 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while inside <dl> block"); 03436 } 03437 03438 enddesclist: 03439 03440 DocNode *n=g_nodeStack.pop(); 03441 ASSERT(n==this); 03442 DBG(("DocHtmlDescList::parse() end\n")); 03443 return retval==RetVal_EndDesc ? RetVal_OK : retval; 03444 } 03445 03446 //--------------------------------------------------------------------------- 03447 03448 int DocHtmlListItem::parse() 03449 { 03450 DBG(("DocHtmlListItem::parse() start\n")); 03451 int retval=0; 03452 g_nodeStack.push(this); 03453 03454 // parse one or more paragraphs 03455 bool isFirst=TRUE; 03456 DocPara *par=0; 03457 do 03458 { 03459 par = new DocPara(this); 03460 if (isFirst) { par->markFirst(); isFirst=FALSE; } 03461 m_children.append(par); 03462 retval=par->parse(); 03463 } 03464 while (retval==TK_NEWPARA); 03465 if (par) par->markLast(); 03466 03467 DocNode *n=g_nodeStack.pop(); 03468 ASSERT(n==this); 03469 DBG(("DocHtmlListItem::parse() end retval=%x\n",retval)); 03470 return retval; 03471 } 03472 03473 int DocHtmlListItem::parseXml() 03474 { 03475 DBG(("DocHtmlListItem::parseXml() start\n")); 03476 int retval=0; 03477 g_nodeStack.push(this); 03478 03479 // parse one or more paragraphs 03480 bool isFirst=TRUE; 03481 DocPara *par=0; 03482 do 03483 { 03484 par = new DocPara(this); 03485 if (isFirst) { par->markFirst(); isFirst=FALSE; } 03486 m_children.append(par); 03487 retval=par->parse(); 03488 if (retval==0) break; 03489 03490 //printf("new item: retval=%x g_token->name=%s g_token->endTag=%d\n", 03491 // retval,g_token->name.data(),g_token->endTag); 03492 if (retval==RetVal_ListItem) 03493 { 03494 break; 03495 } 03496 } 03497 while (retval!=RetVal_CloseXml); 03498 03499 if (par) par->markLast(); 03500 03501 DocNode *n=g_nodeStack.pop(); 03502 ASSERT(n==this); 03503 DBG(("DocHtmlListItem::parseXml() end retval=%x\n",retval)); 03504 return retval; 03505 } 03506 03507 //--------------------------------------------------------------------------- 03508 03509 int DocHtmlList::parse() 03510 { 03511 DBG(("DocHtmlList::parse() start\n")); 03512 int retval=RetVal_OK; 03513 int num=1; 03514 g_nodeStack.push(this); 03515 03516 // get next token 03517 int tok=doctokenizerYYlex(); 03518 // skip whitespace and paragraph breaks 03519 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 03520 // should find a html tag now 03521 if (tok==TK_HTMLTAG) 03522 { 03523 int tagId=Mappers::htmlTagMapper->map(g_token->name); 03524 if (tagId==HTML_LI && !g_token->endTag) // found <li> tag 03525 { 03526 // ok, we can go on. 03527 } 03528 else // found some other tag 03529 { 03530 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <li> tag but " 03531 "found <%s> instead!",g_token->name.data()); 03532 doctokenizerYYpushBackHtmlTag(g_token->name); 03533 goto endlist; 03534 } 03535 } 03536 else if (tok==0) // premature end of comment 03537 { 03538 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" 03539 " for a html list item"); 03540 goto endlist; 03541 } 03542 else // token other than html token 03543 { 03544 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <li> tag but found %s token instead!", 03545 tokToString(tok)); 03546 goto endlist; 03547 } 03548 03549 do 03550 { 03551 DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++); 03552 m_children.append(li); 03553 retval=li->parse(); 03554 } while (retval==RetVal_ListItem); 03555 03556 if (retval==0) 03557 { 03558 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while inside <%cl> block", 03559 m_type==Unordered ? 'u' : 'o'); 03560 } 03561 03562 endlist: 03563 DBG(("DocHtmlList::parse() end retval=%x\n",retval)); 03564 DocNode *n=g_nodeStack.pop(); 03565 ASSERT(n==this); 03566 return retval==RetVal_EndList ? RetVal_OK : retval; 03567 } 03568 03569 int DocHtmlList::parseXml() 03570 { 03571 DBG(("DocHtmlList::parseXml() start\n")); 03572 int retval=RetVal_OK; 03573 int num=1; 03574 g_nodeStack.push(this); 03575 03576 // get next token 03577 int tok=doctokenizerYYlex(); 03578 // skip whitespace and paragraph breaks 03579 while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); 03580 // should find a html tag now 03581 if (tok==TK_HTMLTAG) 03582 { 03583 int tagId=Mappers::htmlTagMapper->map(g_token->name); 03584 //printf("g_token->name=%s g_token->endTag=%d\n",g_token->name.data(),g_token->endTag); 03585 if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag 03586 { 03587 // ok, we can go on. 03588 } 03589 else // found some other tag 03590 { 03591 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <item> tag but " 03592 "found <%s> instead!",g_token->name.data()); 03593 doctokenizerYYpushBackHtmlTag(g_token->name); 03594 goto endlist; 03595 } 03596 } 03597 else if (tok==0) // premature end of comment 03598 { 03599 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" 03600 " for a html list item"); 03601 goto endlist; 03602 } 03603 else // token other than html token 03604 { 03605 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <item> tag but found %s token instead!", 03606 tokToString(tok)); 03607 goto endlist; 03608 } 03609 03610 do 03611 { 03612 DocHtmlListItem *li=new DocHtmlListItem(this,g_token->attribs,num++); 03613 m_children.append(li); 03614 retval=li->parseXml(); 03615 if (retval==0) break; 03616 //printf("retval=%x g_token->name=%s\n",retval,g_token->name.data()); 03617 } while (retval==RetVal_ListItem); 03618 03619 if (retval==0) 03620 { 03621 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while inside <list type=\"%s\"> block", 03622 m_type==Unordered ? "bullet" : "number"); 03623 } 03624 03625 endlist: 03626 DBG(("DocHtmlList::parseXml() end retval=%x\n",retval)); 03627 DocNode *n=g_nodeStack.pop(); 03628 ASSERT(n==this); 03629 return retval==RetVal_EndList || 03630 (retval==RetVal_CloseXml || g_token->name=="list") ? 03631 RetVal_OK : retval; 03632 } 03633 03634 //--------------------------------------------------------------------------- 03635 03636 int DocSimpleListItem::parse() 03637 { 03638 g_nodeStack.push(this); 03639 int rv=m_paragraph->parse(); 03640 m_paragraph->markFirst(); 03641 m_paragraph->markLast(); 03642 DocNode *n=g_nodeStack.pop(); 03643 ASSERT(n==this); 03644 return rv; 03645 } 03646 03647 //-------------------------------------------------------------------------- 03648 03649 int DocSimpleList::parse() 03650 { 03651 g_nodeStack.push(this); 03652 int rv; 03653 do 03654 { 03655 DocSimpleListItem *li=new DocSimpleListItem(this); 03656 m_children.append(li); 03657 rv=li->parse(); 03658 } while (rv==RetVal_ListItem); 03659 DocNode *n=g_nodeStack.pop(); 03660 ASSERT(n==this); 03661 return (rv!=TK_NEWPARA) ? rv : RetVal_OK; 03662 } 03663 03664 //-------------------------------------------------------------------------- 03665 03666 int DocAutoListItem::parse() 03667 { 03668 int retval = RetVal_OK; 03669 g_nodeStack.push(this); 03670 retval=m_paragraph->parse(); 03671 m_paragraph->markFirst(); 03672 m_paragraph->markLast(); 03673 DocNode *n=g_nodeStack.pop(); 03674 ASSERT(n==this); 03675 return retval; 03676 } 03677 03678 //-------------------------------------------------------------------------- 03679 03680 int DocAutoList::parse() 03681 { 03682 int retval = RetVal_OK; 03683 int num=1; 03684 g_nodeStack.push(this); 03685 // first item or sub list => create new list 03686 do 03687 { 03688 DocAutoListItem *li = new DocAutoListItem(this,num++); 03689 m_children.append(li); 03690 retval=li->parse(); 03691 } 03692 while (retval==TK_LISTITEM && // new list item 03693 m_indent==g_token->indent && // at same indent level 03694 m_isEnumList==g_token->isEnumList // of the same kind 03695 ); 03696 03697 DocNode *n=g_nodeStack.pop(); 03698 ASSERT(n==this); 03699 return retval; 03700 } 03701 03702 //-------------------------------------------------------------------------- 03703 03704 void DocTitle::parse() 03705 { 03706 DBG(("DocTitle::parse() start\n")); 03707 g_nodeStack.push(this); 03708 doctokenizerYYsetStateTitle(); 03709 int tok; 03710 while ((tok=doctokenizerYYlex())) 03711 { 03712 if (!defaultHandleToken(this,tok,m_children)) 03713 { 03714 switch (tok) 03715 { 03716 case TK_COMMAND: 03717 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a title section", 03718 g_token->name.data()); 03719 break; 03720 case TK_SYMBOL: 03721 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 03722 g_token->name.data()); 03723 break; 03724 default: 03725 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 03726 tokToString(tok)); 03727 break; 03728 } 03729 } 03730 } 03731 doctokenizerYYsetStatePara(); 03732 handlePendingStyleCommands(this,m_children); 03733 DBG(("DocTitle::parse() end\n")); 03734 DocNode *n = g_nodeStack.pop(); 03735 ASSERT(n==this); 03736 } 03737 03738 void DocTitle::parseFromString(const QString &text) 03739 { 03740 m_children.append(new DocWord(this,text)); 03741 } 03742 03743 //-------------------------------------------------------------------------- 03744 03745 DocSimpleSect::DocSimpleSect(DocNode *parent,Type t) : 03746 m_parent(parent), m_type(t) 03747 { 03748 m_title=0; 03749 } 03750 03751 DocSimpleSect::~DocSimpleSect() 03752 { 03753 delete m_title; 03754 } 03755 03756 void DocSimpleSect::accept(DocVisitor *v) 03757 { 03758 v->visitPre(this); 03759 if (m_title) m_title->accept(v); 03760 QListIterator<DocNode> cli(m_children); 03761 DocNode *n; 03762 for (cli.toFirst();(n=cli.current());++cli) n->accept(v); 03763 v->visitPost(this); 03764 } 03765 03766 int DocSimpleSect::parse(bool userTitle) 03767 { 03768 DBG(("DocSimpleSect::parse() start\n")); 03769 g_nodeStack.push(this); 03770 03771 // handle case for user defined title 03772 if (userTitle) 03773 { 03774 m_title = new DocTitle(this); 03775 m_title->parse(); 03776 } 03777 03778 // add new paragraph as child 03779 DocPara *par = new DocPara(this); 03780 if (m_children.isEmpty()) 03781 { 03782 par->markFirst(); 03783 } 03784 else 03785 { 03786 ASSERT(m_children.last()->kind()==DocNode::Kind_Para); 03787 ((DocPara *)m_children.last())->markLast(FALSE); 03788 } 03789 par->markLast(); 03790 m_children.append(par); 03791 03792 // parse the contents of the paragraph 03793 int retval = par->parse(); 03794 03795 DBG(("DocSimpleSect::parse() end retval=%d\n",retval)); 03796 DocNode *n=g_nodeStack.pop(); 03797 ASSERT(n==this); 03798 return retval; // 0==EOF, TK_NEWPARA, TK_LISTITEM, TK_ENDLIST, RetVal_SimpleSec 03799 } 03800 03801 int DocSimpleSect::parseRcs() 03802 { 03803 DBG(("DocSimpleSect::parseRcs() start\n")); 03804 g_nodeStack.push(this); 03805 03806 m_title = new DocTitle(this); 03807 m_title->parseFromString(g_token->name); 03808 03809 QString text = g_token->text; 03810 docParserPushContext(); // this will create a new g_token 03811 internalValidatingParseDoc(this,m_children,text); 03812 docParserPopContext(); // this will restore the old g_token 03813 03814 DBG(("DocSimpleSect::parseRcs()\n")); 03815 DocNode *n=g_nodeStack.pop(); 03816 ASSERT(n==this); 03817 return RetVal_OK; 03818 } 03819 03820 int DocSimpleSect::parseXml() 03821 { 03822 DBG(("DocSimpleSect::parse() start\n")); 03823 g_nodeStack.push(this); 03824 03825 int retval = RetVal_OK; 03826 for (;;) 03827 { 03828 // add new paragraph as child 03829 DocPara *par = new DocPara(this); 03830 if (m_children.isEmpty()) 03831 { 03832 par->markFirst(); 03833 } 03834 else 03835 { 03836 ASSERT(m_children.last()->kind()==DocNode::Kind_Para); 03837 ((DocPara *)m_children.last())->markLast(FALSE); 03838 } 03839 par->markLast(); 03840 m_children.append(par); 03841 03842 // parse the contents of the paragraph 03843 retval = par->parse(); 03844 if (retval == 0) break; 03845 if (retval == RetVal_CloseXml) 03846 { 03847 retval = RetVal_OK; 03848 break; 03849 } 03850 } 03851 03852 DBG(("DocSimpleSect::parseXml() end retval=%d\n",retval)); 03853 DocNode *n=g_nodeStack.pop(); 03854 ASSERT(n==this); 03855 return retval; 03856 } 03857 03858 void DocSimpleSect::appendLinkWord(const QString &word) 03859 { 03860 DocPara *p; 03861 if (m_children.isEmpty() || m_children.last()->kind()!=DocNode::Kind_Para) 03862 { 03863 p = new DocPara(this); 03864 m_children.append(p); 03865 } 03866 else 03867 { 03868 p = (DocPara *)m_children.last(); 03869 03870 // Comma-seperate <seealso> links. 03871 p->injectToken(TK_WORD,","); 03872 p->injectToken(TK_WHITESPACE," "); 03873 } 03874 03875 g_inSeeBlock=TRUE; 03876 p->injectToken(TK_LNKWORD,word); 03877 g_inSeeBlock=FALSE; 03878 } 03879 03880 QCString DocSimpleSect::typeString() const 03881 { 03882 switch (m_type) 03883 { 03884 case Unknown: break; 03885 case See: return "see"; 03886 case Return: return "return"; 03887 case Author: // fall through 03888 case Authors: return "author"; 03889 case Version: return "version"; 03890 case Since: return "since"; 03891 case Date: return "date"; 03892 case Note: return "note"; 03893 case Warning: return "warning"; 03894 case Pre: return "pre"; 03895 case Post: return "post"; 03896 case Invar: return "invariant"; 03897 case Remark: return "remark"; 03898 case Attention: return "attention"; 03899 case User: return "user"; 03900 case Rcs: return "rcs"; 03901 } 03902 return "unknown"; 03903 } 03904 03905 //-------------------------------------------------------------------------- 03906 03907 int DocParamList::parse(const QString &cmdName) 03908 { 03909 int retval=RetVal_OK; 03910 DBG(("DocParamList::parse() start\n")); 03911 g_nodeStack.push(this); 03912 DocPara *par=0; 03913 03914 int tok=doctokenizerYYlex(); 03915 if (tok!=TK_WHITESPACE) 03916 { 03917 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 03918 cmdName.data()); 03919 } 03920 doctokenizerYYsetStateParam(); 03921 tok=doctokenizerYYlex(); 03922 while (tok==TK_WORD) /* there is a parameter name */ 03923 { 03924 if (m_type==DocParamSect::Param) 03925 { 03926 g_hasParamCommand=TRUE; 03927 checkArgumentName(g_token->name,TRUE); 03928 } 03929 else if (m_type==DocParamSect::RetVal) 03930 { 03931 g_hasReturnCommand=TRUE; 03932 checkArgumentName(g_token->name,FALSE); 03933 } 03934 //m_params.append(g_token->name); 03935 handleLinkedWord(this,m_params); 03936 tok=doctokenizerYYlex(); 03937 } 03938 doctokenizerYYsetStatePara(); 03939 if (tok==0) /* premature end of comment block */ 03940 { 03941 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the " 03942 "argument of command %s",cmdName.data()); 03943 retval=0; 03944 goto endparamlist; 03945 } 03946 ASSERT(tok==TK_WHITESPACE); 03947 03948 par = new DocPara(this); 03949 m_paragraphs.append(par); 03950 retval = par->parse(); 03951 par->markFirst(); 03952 par->markLast(); 03953 03954 endparamlist: 03955 DBG(("DocParamList::parse() end retval=%d\n",retval)); 03956 DocNode *n=g_nodeStack.pop(); 03957 ASSERT(n==this); 03958 return retval; 03959 } 03960 03961 int DocParamList::parseXml(const QString ¶mName) 03962 { 03963 int retval=RetVal_OK; 03964 DBG(("DocParamList::parseXml() start\n")); 03965 g_nodeStack.push(this); 03966 03967 g_token->name = paramName; 03968 if (m_type==DocParamSect::Param) 03969 { 03970 g_hasParamCommand=TRUE; 03971 checkArgumentName(g_token->name,TRUE); 03972 } 03973 else if (m_type==DocParamSect::RetVal) 03974 { 03975 g_hasReturnCommand=TRUE; 03976 checkArgumentName(g_token->name,FALSE); 03977 } 03978 03979 handleLinkedWord(this,m_params); 03980 03981 do 03982 { 03983 DocPara *par = new DocPara(this); 03984 retval = par->parse(); 03985 if (par->isEmpty()) // avoid adding an empty paragraph for the whitespace 03986 // after </para> and before </param> 03987 { 03988 delete par; 03989 break; 03990 } 03991 else // append the paragraph to the list 03992 { 03993 if (m_paragraphs.isEmpty()) 03994 { 03995 par->markFirst(); 03996 } 03997 else 03998 { 03999 m_paragraphs.last()->markLast(FALSE); 04000 } 04001 par->markLast(); 04002 m_paragraphs.append(par); 04003 } 04004 04005 if (retval == 0) break; 04006 04007 } while (retval==RetVal_CloseXml && 04008 Mappers::htmlTagMapper->map(g_token->name)!=XML_PARAM && 04009 Mappers::htmlTagMapper->map(g_token->name)!=XML_TYPEPARAM && 04010 Mappers::htmlTagMapper->map(g_token->name)!=XML_EXCEPTION); 04011 04012 04013 if (retval==0) /* premature end of comment block */ 04014 { 04015 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unterminated param or exception tag"); 04016 } 04017 else 04018 { 04019 retval=RetVal_OK; 04020 } 04021 04022 04023 DBG(("DocParamList::parse() end retval=%d\n",retval)); 04024 DocNode *n=g_nodeStack.pop(); 04025 ASSERT(n==this); 04026 return retval; 04027 } 04028 04029 //-------------------------------------------------------------------------- 04030 04031 int DocParamSect::parse(const QString &cmdName,bool xmlContext, Direction d) 04032 { 04033 int retval=RetVal_OK; 04034 DBG(("DocParamSect::parse() start\n")); 04035 g_nodeStack.push(this); 04036 04037 DocParamList *pl = new DocParamList(this,m_type,d); 04038 if (m_children.isEmpty()) 04039 { 04040 pl->markFirst(); 04041 pl->markLast(); 04042 } 04043 else 04044 { 04045 ASSERT(m_children.last()->kind()==DocNode::Kind_ParamList); 04046 ((DocParamList *)m_children.last())->markLast(FALSE); 04047 pl->markLast(); 04048 } 04049 m_children.append(pl); 04050 if (xmlContext) 04051 { 04052 retval = pl->parseXml(cmdName); 04053 } 04054 else 04055 { 04056 retval = pl->parse(cmdName); 04057 } 04058 04059 DBG(("DocParamSect::parse() end retval=%d\n",retval)); 04060 DocNode *n=g_nodeStack.pop(); 04061 ASSERT(n==this); 04062 return retval; 04063 } 04064 04065 //-------------------------------------------------------------------------- 04066 04067 int DocPara::handleSimpleSection(DocSimpleSect::Type t, bool xmlContext) 04068 { 04069 DocSimpleSect *ss=0; 04070 if (!m_children.isEmpty() && // previous element 04071 m_children.last()->kind()==Kind_SimpleSect && // was a simple sect 04072 ((DocSimpleSect *)m_children.last())->type()==t && // of same type 04073 t!=DocSimpleSect::User) // but not user defined 04074 { 04075 // append to previous section 04076 ss=(DocSimpleSect *)m_children.last(); 04077 } 04078 else // start new section 04079 { 04080 ss=new DocSimpleSect(this,t); 04081 m_children.append(ss); 04082 } 04083 int rv = RetVal_OK; 04084 if (xmlContext) 04085 { 04086 return ss->parseXml(); 04087 } 04088 else 04089 { 04090 rv = ss->parse(t==DocSimpleSect::User); 04091 } 04092 return (rv!=TK_NEWPARA) ? rv : RetVal_OK; 04093 } 04094 04095 int DocPara::handleParamSection(const QString &cmdName, 04096 DocParamSect::Type t, 04097 bool xmlContext=FALSE, 04098 int direction=DocParamSect::Unspecified) 04099 { 04100 DocParamSect *ps=0; 04101 if (!m_children.isEmpty() && // previous element 04102 m_children.last()->kind()==Kind_ParamSect && // was a param sect 04103 ((DocParamSect *)m_children.last())->type()==t) // of same type 04104 { 04105 // append to previous section 04106 ps=(DocParamSect *)m_children.last(); 04107 } 04108 else // start new section 04109 { 04110 ps=new DocParamSect(this,t); 04111 m_children.append(ps); 04112 } 04113 int rv=ps->parse(cmdName,xmlContext,(DocParamSect::Direction)direction); 04114 return (rv!=TK_NEWPARA) ? rv : RetVal_OK; 04115 } 04116 04117 int DocPara::handleXRefItem() 04118 { 04119 int retval=doctokenizerYYlex(); 04120 ASSERT(retval==TK_WHITESPACE); 04121 doctokenizerYYsetStateXRefItem(); 04122 retval=doctokenizerYYlex(); 04123 if (retval==RetVal_OK) 04124 { 04125 DocXRefItem *ref = new DocXRefItem(this,g_token->id,g_token->name); 04126 if (ref->parse()) 04127 { 04128 m_children.append(ref); 04129 } 04130 else 04131 { 04132 delete ref; 04133 } 04134 } 04135 doctokenizerYYsetStatePara(); 04136 return retval; 04137 } 04138 04139 void DocPara::handleIncludeOperator(const QString &cmdName,DocIncOperator::Type t) 04140 { 04141 DBG(("handleIncludeOperator(%s)\n",cmdName.data())); 04142 int tok=doctokenizerYYlex(); 04143 if (tok!=TK_WHITESPACE) 04144 { 04145 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04146 cmdName.data()); 04147 return; 04148 } 04149 doctokenizerYYsetStatePattern(); 04150 tok=doctokenizerYYlex(); 04151 doctokenizerYYsetStatePara(); 04152 if (tok==0) 04153 { 04154 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the " 04155 "argument of command %s", cmdName.data()); 04156 return; 04157 } 04158 else if (tok!=TK_WORD) 04159 { 04160 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04161 tokToString(tok),cmdName.data()); 04162 return; 04163 } 04164 DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName); 04165 DocNode *n1 = m_children.last(); 04166 DocNode *n2 = n1!=0 ? m_children.prev() : 0; 04167 bool isFirst = n1==0 || // no last node 04168 (n1->kind()!=DocNode::Kind_IncOperator && 04169 n1->kind()!=DocNode::Kind_WhiteSpace 04170 ) || // last node is not operator or whitespace 04171 (n1->kind()==DocNode::Kind_WhiteSpace && 04172 n2!=0 && n2->kind()!=DocNode::Kind_IncOperator 04173 ); // previous not is not operator 04174 op->markFirst(isFirst); 04175 op->markLast(TRUE); 04176 if (n1!=0 && n1->kind()==DocNode::Kind_IncOperator) 04177 { 04178 ((DocIncOperator *)n1)->markLast(FALSE); 04179 } 04180 else if (n1!=0 && n1->kind()==DocNode::Kind_WhiteSpace && 04181 n2!=0 && n2->kind()==DocNode::Kind_IncOperator 04182 ) 04183 { 04184 ((DocIncOperator *)n2)->markLast(FALSE); 04185 } 04186 m_children.append(op); 04187 op->parse(); 04188 } 04189 04190 void DocPara::handleImage(const QString &cmdName) 04191 { 04192 int tok=doctokenizerYYlex(); 04193 if (tok!=TK_WHITESPACE) 04194 { 04195 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04196 cmdName.data()); 04197 return; 04198 } 04199 tok=doctokenizerYYlex(); 04200 if (tok!=TK_WORD && tok!=TK_LNKWORD) 04201 { 04202 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04203 tokToString(tok),cmdName.data()); 04204 return; 04205 } 04206 tok=doctokenizerYYlex(); 04207 if (tok!=TK_WHITESPACE) 04208 { 04209 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04210 cmdName.data()); 04211 return; 04212 } 04213 DocImage::Type t; 04214 QString imgType = g_token->name.lower(); 04215 if (imgType=="html") t=DocImage::Html; 04216 else if (imgType=="latex") t=DocImage::Latex; 04217 else if (imgType=="rtf") t=DocImage::Rtf; 04218 else 04219 { 04220 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: image type %s specified as the first argument of " 04221 "%s is not valid", 04222 imgType.data(),cmdName.data()); 04223 return; 04224 } 04225 doctokenizerYYsetStateFile(); 04226 tok=doctokenizerYYlex(); 04227 doctokenizerYYsetStatePara(); 04228 if (tok!=TK_WORD) 04229 { 04230 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04231 tokToString(tok),cmdName.data()); 04232 return; 04233 } 04234 HtmlAttribList attrList; 04235 DocImage *img = new DocImage(this,attrList,findAndCopyImage(g_token->name,t),t); 04236 m_children.append(img); 04237 img->parse(); 04238 } 04239 04240 void DocPara::handleDotFile(const QString &cmdName) 04241 { 04242 int tok=doctokenizerYYlex(); 04243 if (tok!=TK_WHITESPACE) 04244 { 04245 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04246 cmdName.data()); 04247 return; 04248 } 04249 doctokenizerYYsetStateFile(); 04250 tok=doctokenizerYYlex(); 04251 doctokenizerYYsetStatePara(); 04252 if (tok!=TK_WORD) 04253 { 04254 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04255 tokToString(tok),cmdName.data()); 04256 return; 04257 } 04258 QString name = g_token->name; 04259 DocDotFile *df = new DocDotFile(this,name,g_context); 04260 m_children.append(df); 04261 df->parse(); 04262 } 04263 04264 void DocPara::handleLink(const QString &cmdName,bool isJavaLink) 04265 { 04266 int tok=doctokenizerYYlex(); 04267 if (tok!=TK_WHITESPACE) 04268 { 04269 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04270 cmdName.data()); 04271 return; 04272 } 04273 doctokenizerYYsetStateLink(); 04274 tok=doctokenizerYYlex(); 04275 if (tok!=TK_WORD) 04276 { 04277 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04278 tokToString(tok),cmdName.data()); 04279 return; 04280 } 04281 doctokenizerYYsetStatePara(); 04282 DocLink *lnk = new DocLink(this,g_token->name); 04283 m_children.append(lnk); 04284 QString leftOver = lnk->parse(isJavaLink); 04285 if (!leftOver.isEmpty()) 04286 { 04287 m_children.append(new DocWord(this,leftOver)); 04288 } 04289 } 04290 04291 void DocPara::handleRef(const QString &cmdName) 04292 { 04293 DBG(("handleRef(%s)\n",cmdName.data())); 04294 int tok=doctokenizerYYlex(); 04295 if (tok!=TK_WHITESPACE) 04296 { 04297 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04298 cmdName.data()); 04299 return; 04300 } 04301 doctokenizerYYsetStateRef(); 04302 tok=doctokenizerYYlex(); // get the reference id 04303 DocRef *ref=0; 04304 if (tok!=TK_WORD) 04305 { 04306 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04307 tokToString(tok),cmdName.data()); 04308 goto endref; 04309 } 04310 ref = new DocRef(this,g_token->name,g_context); 04311 m_children.append(ref); 04312 ref->parse(); 04313 endref: 04314 doctokenizerYYsetStatePara(); 04315 } 04316 04317 04318 void DocPara::handleInclude(const QString &cmdName,DocInclude::Type t) 04319 { 04320 DBG(("handleInclude(%s)\n",cmdName.data())); 04321 int tok=doctokenizerYYlex(); 04322 if (tok!=TK_WHITESPACE) 04323 { 04324 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04325 cmdName.data()); 04326 return; 04327 } 04328 doctokenizerYYsetStateFile(); 04329 tok=doctokenizerYYlex(); 04330 doctokenizerYYsetStatePara(); 04331 if (tok==0) 04332 { 04333 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the " 04334 "argument of command %s",cmdName.data()); 04335 return; 04336 } 04337 else if (tok!=TK_WORD) 04338 { 04339 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04340 tokToString(tok),cmdName.data()); 04341 return; 04342 } 04343 DocInclude *inc = new DocInclude(this,g_token->name,g_context,t,g_isExample,g_exampleName); 04344 m_children.append(inc); 04345 inc->parse(); 04346 } 04347 04348 void DocPara::handleSection(const QString &cmdName) 04349 { 04350 // get the argument of the section command. 04351 int tok=doctokenizerYYlex(); 04352 if (tok!=TK_WHITESPACE) 04353 { 04354 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04355 cmdName.data()); 04356 return; 04357 } 04358 tok=doctokenizerYYlex(); 04359 if (tok==0) 04360 { 04361 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the " 04362 "argument of command %s\n", cmdName.data()); 04363 return; 04364 } 04365 else if (tok!=TK_WORD && tok!=TK_LNKWORD) 04366 { 04367 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04368 tokToString(tok),cmdName.data()); 04369 return; 04370 } 04371 g_token->sectionId = g_token->name; 04372 doctokenizerYYsetStateSkipTitle(); 04373 doctokenizerYYlex(); 04374 doctokenizerYYsetStatePara(); 04375 } 04376 04377 int DocPara::handleHtmlHeader(const HtmlAttribList &tagHtmlAttribs,int level) 04378 { 04379 DocHtmlHeader *header = new DocHtmlHeader(this,tagHtmlAttribs,level); 04380 m_children.append(header); 04381 int retval = header->parse(); 04382 return (retval==RetVal_OK) ? TK_NEWPARA : retval; 04383 } 04384 04385 // For XML tags whose content is stored in attributes rather than 04386 // contained within the element, we need a way to inject the attribute 04387 // text into the current paragraph. 04388 bool DocPara::injectToken(int tok,const QString &tokText) 04389 { 04390 g_token->name = tokText; 04391 return defaultHandleToken(this,tok,m_children); 04392 } 04393 04394 int DocPara::handleStartCode() 04395 { 04396 int retval = doctokenizerYYlex(); 04397 // search for the first non-whitespace line, index is stored in li 04398 int i=0,li=0,l=g_token->verb.length(); 04399 while (i<l && g_token->verb.at(i)==' ' || g_token->verb.at(i)=='\n') 04400 { 04401 if (g_token->verb.at(i)=='\n') li=i+1; 04402 i++; 04403 } 04404 m_children.append(new DocVerbatim(this,g_context,g_token->verb.mid(li),DocVerbatim::Code,g_isExample,g_exampleName)); 04405 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: code section ended without end marker"); 04406 doctokenizerYYsetStatePara(); 04407 return retval; 04408 } 04409 04410 void DocPara::handleInheritDoc() 04411 { 04412 if (g_memberDef) // inheriting docs from a member 04413 { 04414 MemberDef *reMd = g_memberDef->reimplements(); 04415 if (reMd) // member from which was inherited. 04416 { 04417 MemberDef *thisMd = g_memberDef; 04418 //printf("{InheritDocs:%s=>%s}\n",g_memberDef->qualifiedName().data(),reMd->qualifiedName().data()); 04419 docParserPushContext(); 04420 g_context=reMd->getOuterScope()->name(); 04421 g_memberDef=reMd; 04422 g_styleStack.clear(); 04423 g_nodeStack.clear(); 04424 g_copyStack.append(reMd); 04425 internalValidatingParseDoc(this,m_children,reMd->briefDescription()); 04426 internalValidatingParseDoc(this,m_children,reMd->documentation()); 04427 g_copyStack.remove(reMd); 04428 docParserPopContext(TRUE); 04429 g_memberDef = thisMd; 04430 } 04431 } 04432 } 04433 04434 04435 int DocPara::handleCommand(const QString &cmdName) 04436 { 04437 DBG(("handleCommand(%s)\n",cmdName.data())); 04438 int retval = RetVal_OK; 04439 switch (Mappers::cmdMapper->map(cmdName)) 04440 { 04441 case CMD_UNKNOWN: 04442 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Found unknown command `\\%s'",cmdName.data()); 04443 break; 04444 case CMD_EMPHASIS: 04445 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE)); 04446 retval=handleStyleArgument(this,m_children,cmdName); 04447 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE)); 04448 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); 04449 break; 04450 case CMD_BOLD: 04451 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE)); 04452 retval=handleStyleArgument(this,m_children,cmdName); 04453 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE)); 04454 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); 04455 break; 04456 case CMD_CODE: 04457 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,TRUE)); 04458 retval=handleStyleArgument(this,m_children,cmdName); 04459 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,FALSE)); 04460 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); 04461 break; 04462 case CMD_BSLASH: 04463 m_children.append(new DocSymbol(this,DocSymbol::BSlash)); 04464 break; 04465 case CMD_AT: 04466 m_children.append(new DocSymbol(this,DocSymbol::At)); 04467 break; 04468 case CMD_LESS: 04469 m_children.append(new DocSymbol(this,DocSymbol::Less)); 04470 break; 04471 case CMD_GREATER: 04472 m_children.append(new DocSymbol(this,DocSymbol::Greater)); 04473 break; 04474 case CMD_AMP: 04475 m_children.append(new DocSymbol(this,DocSymbol::Amp)); 04476 break; 04477 case CMD_DOLLAR: 04478 m_children.append(new DocSymbol(this,DocSymbol::Dollar)); 04479 break; 04480 case CMD_HASH: 04481 m_children.append(new DocSymbol(this,DocSymbol::Hash)); 04482 break; 04483 case CMD_PERCENT: 04484 m_children.append(new DocSymbol(this,DocSymbol::Percent)); 04485 break; 04486 case CMD_SA: 04487 g_inSeeBlock=TRUE; 04488 retval = handleSimpleSection(DocSimpleSect::See); 04489 g_inSeeBlock=FALSE; 04490 break; 04491 case CMD_RETURN: 04492 retval = handleSimpleSection(DocSimpleSect::Return); 04493 g_hasReturnCommand=TRUE; 04494 break; 04495 case CMD_AUTHOR: 04496 retval = handleSimpleSection(DocSimpleSect::Author); 04497 break; 04498 case CMD_AUTHORS: 04499 retval = handleSimpleSection(DocSimpleSect::Authors); 04500 break; 04501 case CMD_VERSION: 04502 retval = handleSimpleSection(DocSimpleSect::Version); 04503 break; 04504 case CMD_SINCE: 04505 retval = handleSimpleSection(DocSimpleSect::Since); 04506 break; 04507 case CMD_DATE: 04508 retval = handleSimpleSection(DocSimpleSect::Date); 04509 break; 04510 case CMD_NOTE: 04511 retval = handleSimpleSection(DocSimpleSect::Note); 04512 break; 04513 case CMD_WARNING: 04514 retval = handleSimpleSection(DocSimpleSect::Warning); 04515 break; 04516 case CMD_PRE: 04517 retval = handleSimpleSection(DocSimpleSect::Pre); 04518 break; 04519 case CMD_POST: 04520 retval = handleSimpleSection(DocSimpleSect::Post); 04521 break; 04522 case CMD_INVARIANT: 04523 retval = handleSimpleSection(DocSimpleSect::Invar); 04524 break; 04525 case CMD_REMARK: 04526 retval = handleSimpleSection(DocSimpleSect::Remark); 04527 break; 04528 case CMD_ATTENTION: 04529 retval = handleSimpleSection(DocSimpleSect::Attention); 04530 break; 04531 case CMD_PAR: 04532 retval = handleSimpleSection(DocSimpleSect::User); 04533 break; 04534 case CMD_LI: 04535 { 04536 DocSimpleList *sl=new DocSimpleList(this); 04537 m_children.append(sl); 04538 retval = sl->parse(); 04539 } 04540 break; 04541 case CMD_SECTION: 04542 { 04543 handleSection(cmdName); 04544 retval = RetVal_Section; 04545 } 04546 break; 04547 case CMD_SUBSECTION: 04548 { 04549 handleSection(cmdName); 04550 retval = RetVal_Subsection; 04551 } 04552 break; 04553 case CMD_SUBSUBSECTION: 04554 { 04555 handleSection(cmdName); 04556 retval = RetVal_Subsubsection; 04557 } 04558 break; 04559 case CMD_PARAGRAPH: 04560 { 04561 handleSection(cmdName); 04562 retval = RetVal_Paragraph; 04563 } 04564 break; 04565 case CMD_STARTCODE: 04566 { 04567 doctokenizerYYsetStateCode(); 04568 retval = handleStartCode(); 04569 } 04570 break; 04571 case CMD_HTMLONLY: 04572 { 04573 doctokenizerYYsetStateHtmlOnly(); 04574 retval = doctokenizerYYlex(); 04575 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName)); 04576 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: htmlonly section ended without end marker"); 04577 doctokenizerYYsetStatePara(); 04578 } 04579 break; 04580 case CMD_MANONLY: 04581 { 04582 doctokenizerYYsetStateManOnly(); 04583 retval = doctokenizerYYlex(); 04584 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName)); 04585 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: manonly section ended without end marker"); 04586 doctokenizerYYsetStatePara(); 04587 } 04588 break; 04589 case CMD_LATEXONLY: 04590 { 04591 doctokenizerYYsetStateLatexOnly(); 04592 retval = doctokenizerYYlex(); 04593 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName)); 04594 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: latexonly section ended without end marker"); 04595 doctokenizerYYsetStatePara(); 04596 } 04597 break; 04598 case CMD_XMLONLY: 04599 { 04600 doctokenizerYYsetStateXmlOnly(); 04601 retval = doctokenizerYYlex(); 04602 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName)); 04603 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: xmlonly section ended without end marker"); 04604 doctokenizerYYsetStatePara(); 04605 } 04606 break; 04607 case CMD_VERBATIM: 04608 { 04609 doctokenizerYYsetStateVerbatim(); 04610 retval = doctokenizerYYlex(); 04611 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Verbatim,g_isExample,g_exampleName)); 04612 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: verbatim section ended without end marker"); 04613 doctokenizerYYsetStatePara(); 04614 } 04615 break; 04616 case CMD_DOT: 04617 { 04618 doctokenizerYYsetStateDot(); 04619 retval = doctokenizerYYlex(); 04620 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Dot,g_isExample,g_exampleName)); 04621 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: dot section ended without end marker"); 04622 doctokenizerYYsetStatePara(); 04623 } 04624 break; 04625 case CMD_MSC: 04626 { 04627 doctokenizerYYsetStateMsc(); 04628 retval = doctokenizerYYlex(); 04629 m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName)); 04630 if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: msc section ended without end marker"); 04631 doctokenizerYYsetStatePara(); 04632 } 04633 break; 04634 case CMD_ENDCODE: 04635 case CMD_ENDHTMLONLY: 04636 case CMD_ENDMANONLY: 04637 case CMD_ENDLATEXONLY: 04638 case CMD_ENDXMLONLY: 04639 case CMD_ENDLINK: 04640 case CMD_ENDVERBATIM: 04641 case CMD_ENDDOT: 04642 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data()); 04643 break; 04644 case CMD_ENDMSC: 04645 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data()); 04646 break; 04647 case CMD_PARAM: 04648 retval = handleParamSection(cmdName,DocParamSect::Param,FALSE,g_token->paramDir); 04649 break; 04650 case CMD_TPARAM: 04651 retval = handleParamSection(cmdName,DocParamSect::TemplateParam,FALSE,g_token->paramDir); 04652 break; 04653 case CMD_RETVAL: 04654 retval = handleParamSection(cmdName,DocParamSect::RetVal); 04655 break; 04656 case CMD_EXCEPTION: 04657 retval = handleParamSection(cmdName,DocParamSect::Exception); 04658 break; 04659 case CMD_XREFITEM: 04660 retval = handleXRefItem(); 04661 break; 04662 case CMD_LINEBREAK: 04663 { 04664 DocLineBreak *lb = new DocLineBreak(this); 04665 m_children.append(lb); 04666 } 04667 break; 04668 case CMD_ANCHOR: 04669 { 04670 int tok=doctokenizerYYlex(); 04671 if (tok!=TK_WHITESPACE) 04672 { 04673 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04674 cmdName.data()); 04675 break; 04676 } 04677 tok=doctokenizerYYlex(); 04678 if (tok==0) 04679 { 04680 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the " 04681 "argument of command %s",cmdName.data()); 04682 break; 04683 } 04684 else if (tok!=TK_WORD && tok!=TK_LNKWORD) 04685 { 04686 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04687 tokToString(tok),cmdName.data()); 04688 break; 04689 } 04690 DocAnchor *anchor = new DocAnchor(this,g_token->name,FALSE); 04691 m_children.append(anchor); 04692 } 04693 break; 04694 case CMD_ADDINDEX: 04695 { 04696 DocIndexEntry *ie = new DocIndexEntry(this); 04697 m_children.append(ie); 04698 retval = ie->parse(); 04699 } 04700 break; 04701 case CMD_INTERNAL: 04702 retval = RetVal_Internal; 04703 break; 04704 case CMD_COPYDOC: 04705 { 04706 int tok=doctokenizerYYlex(); 04707 if (tok!=TK_WHITESPACE) 04708 { 04709 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command", 04710 cmdName.data()); 04711 break; 04712 } 04713 tok=doctokenizerYYlex(); 04714 if (tok==0) 04715 { 04716 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment block while parsing the " 04717 "argument of command %s\n", cmdName.data()); 04718 break; 04719 } 04720 else if (tok!=TK_WORD && tok!=TK_LNKWORD) 04721 { 04722 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s", 04723 tokToString(tok),cmdName.data()); 04724 break; 04725 } 04726 DocCopy *cpy = new DocCopy(this,g_token->name); 04727 m_children.append(cpy); 04728 cpy->parse(); 04729 } 04730 break; 04731 case CMD_INCLUDE: 04732 handleInclude(cmdName,DocInclude::Include); 04733 break; 04734 case CMD_INCWITHLINES: 04735 handleInclude(cmdName,DocInclude::IncWithLines); 04736 break; 04737 case CMD_DONTINCLUDE: 04738 handleInclude(cmdName,DocInclude::DontInclude); 04739 break; 04740 case CMD_HTMLINCLUDE: 04741 handleInclude(cmdName,DocInclude::HtmlInclude); 04742 break; 04743 case CMD_VERBINCLUDE: 04744 handleInclude(cmdName,DocInclude::VerbInclude); 04745 break; 04746 case CMD_SKIP: 04747 handleIncludeOperator(cmdName,DocIncOperator::Skip); 04748 break; 04749 case CMD_UNTIL: 04750 handleIncludeOperator(cmdName,DocIncOperator::Until); 04751 break; 04752 case CMD_SKIPLINE: 04753 handleIncludeOperator(cmdName,DocIncOperator::SkipLine); 04754 break; 04755 case CMD_LINE: 04756 handleIncludeOperator(cmdName,DocIncOperator::Line); 04757 break; 04758 case CMD_IMAGE: 04759 handleImage(cmdName); 04760 break; 04761 case CMD_DOTFILE: 04762 handleDotFile(cmdName); 04763 break; 04764 case CMD_LINK: 04765 handleLink(cmdName,FALSE); 04766 break; 04767 case CMD_JAVALINK: 04768 handleLink(cmdName,TRUE); 04769 break; 04770 case CMD_REF: // fall through 04771 case CMD_SUBPAGE: 04772 handleRef(cmdName); 04773 break; 04774 case CMD_SECREFLIST: 04775 { 04776 DocSecRefList *list = new DocSecRefList(this); 04777 m_children.append(list); 04778 list->parse(); 04779 } 04780 break; 04781 case CMD_SECREFITEM: 04782 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data()); 04783 break; 04784 case CMD_ENDSECREFLIST: 04785 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data()); 04786 break; 04787 case CMD_FORMULA: 04788 { 04789 DocFormula *form=new DocFormula(this,g_token->id); 04790 m_children.append(form); 04791 } 04792 break; 04793 //case CMD_LANGSWITCH: 04794 // retval = handleLanguageSwitch(); 04795 // break; 04796 case CMD_INTERNALREF: 04797 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected command %s",g_token->name.data()); 04798 break; 04799 case CMD_INHERITDOC: 04800 handleInheritDoc(); 04801 break; 04802 default: 04803 // we should not get here! 04804 ASSERT(0); 04805 break; 04806 } 04807 INTERNAL_ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec || 04808 retval==TK_LISTITEM || retval==TK_ENDLIST || retval==TK_NEWPARA || 04809 retval==RetVal_Section || retval==RetVal_EndList || 04810 retval==RetVal_Internal || retval==RetVal_SwitchLang 04811 ); 04812 DBG(("handleCommand(%s) end retval=%x\n",cmdName.data(),retval)); 04813 return retval; 04814 } 04815 04816 static bool findAttribute(const HtmlAttribList &tagHtmlAttribs, 04817 const char *attrName, 04818 QString *result) 04819 { 04820 04821 HtmlAttribListIterator li(tagHtmlAttribs); 04822 HtmlAttrib *opt; 04823 for (li.toFirst();(opt=li.current());++li) 04824 { 04825 if (opt->name==attrName) 04826 { 04827 *result = opt->value; 04828 return TRUE; 04829 } 04830 } 04831 return FALSE; 04832 } 04833 04834 int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tagHtmlAttribs) 04835 { 04836 DBG(("handleHtmlStartTag(%s,%d)\n",tagName.data(),tagHtmlAttribs.count())); 04837 int retval=RetVal_OK; 04838 int tagId = Mappers::htmlTagMapper->map(tagName); 04839 if (g_token->emptyTag && !(tagId&XML_CmdMask) && tagId!=HTML_UNKNOWN) 04840 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: HTML tags may not use the 'empty tag' XHTML syntax."); 04841 switch (tagId) 04842 { 04843 case HTML_UL: 04844 { 04845 DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Unordered); 04846 m_children.append(list); 04847 retval=list->parse(); 04848 } 04849 break; 04850 case HTML_OL: 04851 { 04852 DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Ordered); 04853 m_children.append(list); 04854 retval=list->parse(); 04855 } 04856 break; 04857 case HTML_LI: 04858 if (!insideUL(this) && !insideOL(this)) 04859 { 04860 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <li> tag found"); 04861 } 04862 else 04863 { 04864 retval=RetVal_ListItem; 04865 } 04866 break; 04867 case HTML_BOLD: 04868 handleStyleEnter(this,m_children,DocStyleChange::Bold,&g_token->attribs); 04869 break; 04870 case HTML_CODE: 04871 if (g_fileName.right(3)==".cs") 04872 // for C# code we treat <code> as an XML tag 04873 { 04874 doctokenizerYYsetStateXmlCode(); 04875 retval = handleStartCode(); 04876 } 04877 else // normal HTML markup 04878 { 04879 handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs); 04880 } 04881 break; 04882 case HTML_EMPHASIS: 04883 handleStyleEnter(this,m_children,DocStyleChange::Italic,&g_token->attribs); 04884 break; 04885 case HTML_DIV: 04886 handleStyleEnter(this,m_children,DocStyleChange::Div,&g_token->attribs); 04887 break; 04888 case HTML_SPAN: 04889 handleStyleEnter(this,m_children,DocStyleChange::Span,&g_token->attribs); 04890 break; 04891 case HTML_SUB: 04892 handleStyleEnter(this,m_children,DocStyleChange::Subscript,&g_token->attribs); 04893 break; 04894 case HTML_SUP: 04895 handleStyleEnter(this,m_children,DocStyleChange::Superscript,&g_token->attribs); 04896 break; 04897 case HTML_CENTER: 04898 handleStyleEnter(this,m_children,DocStyleChange::Center,&g_token->attribs); 04899 break; 04900 case HTML_SMALL: 04901 handleStyleEnter(this,m_children,DocStyleChange::Small,&g_token->attribs); 04902 break; 04903 case HTML_PRE: 04904 handleStyleEnter(this,m_children,DocStyleChange::Preformatted,&g_token->attribs); 04905 setInsidePreformatted(TRUE); 04906 //doctokenizerYYsetInsidePre(TRUE); 04907 break; 04908 case HTML_P: 04909 retval=TK_NEWPARA; 04910 break; 04911 case HTML_DL: 04912 { 04913 DocHtmlDescList *list = new DocHtmlDescList(this,tagHtmlAttribs); 04914 m_children.append(list); 04915 retval=list->parse(); 04916 } 04917 break; 04918 case HTML_DT: 04919 retval = RetVal_DescTitle; 04920 break; 04921 case HTML_DD: 04922 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag <dd> found"); 04923 break; 04924 case HTML_TABLE: 04925 { 04926 DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs); 04927 m_children.append(table); 04928 retval=table->parse(); 04929 } 04930 break; 04931 case HTML_TR: 04932 retval = RetVal_TableRow; 04933 break; 04934 case HTML_TD: 04935 retval = RetVal_TableCell; 04936 break; 04937 case HTML_TH: 04938 retval = RetVal_TableHCell; 04939 break; 04940 case HTML_CAPTION: 04941 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag <caption> found"); 04942 break; 04943 case HTML_BR: 04944 { 04945 DocLineBreak *lb = new DocLineBreak(this); 04946 m_children.append(lb); 04947 } 04948 break; 04949 case HTML_HR: 04950 { 04951 DocHorRuler *hr = new DocHorRuler(this); 04952 m_children.append(hr); 04953 } 04954 break; 04955 case HTML_A: 04956 retval=handleAHref(this,m_children,tagHtmlAttribs); 04957 break; 04958 case HTML_H1: 04959 retval=handleHtmlHeader(tagHtmlAttribs,1); 04960 break; 04961 case HTML_H2: 04962 retval=handleHtmlHeader(tagHtmlAttribs,2); 04963 break; 04964 case HTML_H3: 04965 retval=handleHtmlHeader(tagHtmlAttribs,3); 04966 break; 04967 case HTML_H4: 04968 retval=handleHtmlHeader(tagHtmlAttribs,4); 04969 break; 04970 case HTML_H5: 04971 retval=handleHtmlHeader(tagHtmlAttribs,5); 04972 break; 04973 case HTML_H6: 04974 retval=handleHtmlHeader(tagHtmlAttribs,6); 04975 break; 04976 case HTML_IMG: 04977 { 04978 HtmlAttribListIterator li(tagHtmlAttribs); 04979 HtmlAttrib *opt; 04980 bool found=FALSE; 04981 int index=0; 04982 for (li.toFirst();(opt=li.current());++li,++index) 04983 { 04984 //printf("option name=%s value=%s\n",opt->name.data(),opt->value.data()); 04985 if (opt->name=="src" && !opt->value.isEmpty()) 04986 { 04987 // copy attributes 04988 HtmlAttribList attrList = tagHtmlAttribs; 04989 // and remove the href attribute 04990 bool result = attrList.remove(index); 04991 ASSERT(result); 04992 DocImage *img = new DocImage(this,attrList,opt->value,DocImage::Html); 04993 m_children.append(img); 04994 found = TRUE; 04995 } 04996 } 04997 if (!found) 04998 { 04999 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: IMG tag does not have a SRC attribute!\n"); 05000 } 05001 } 05002 break; 05003 05004 case XML_SUMMARY: 05005 case XML_REMARKS: 05006 case XML_VALUE: 05007 case XML_PARA: 05008 if (!m_children.isEmpty()) 05009 { 05010 retval = TK_NEWPARA; 05011 } 05012 break; 05013 case XML_EXAMPLE: 05014 case XML_DESCRIPTION: 05015 if (insideTable(this)) 05016 { 05017 retval=RetVal_TableCell; 05018 } 05019 break; 05020 case XML_C: 05021 handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs); 05022 break; 05023 case XML_PARAM: 05024 case XML_TYPEPARAM: 05025 { 05026 QString paramName; 05027 if (findAttribute(tagHtmlAttribs,"name",¶mName)) 05028 { 05029 retval = handleParamSection(paramName, 05030 tagId==XML_PARAM ? DocParamSect::Param : DocParamSect::TemplateParam, 05031 TRUE); 05032 } 05033 else 05034 { 05035 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'name' attribute from <param> tag."); 05036 } 05037 } 05038 break; 05039 case XML_PARAMREF: 05040 case XML_TYPEPARAMREF: 05041 { 05042 QString paramName; 05043 if (findAttribute(tagHtmlAttribs,"name",¶mName)) 05044 { 05045 //printf("paramName=%s\n",paramName.data()); 05046 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE)); 05047 m_children.append(new DocWord(this,paramName)); 05048 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE)); 05049 if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); 05050 } 05051 else 05052 { 05053 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type"); 05054 } 05055 } 05056 break; 05057 case XML_EXCEPTION: 05058 { 05059 QString exceptName; 05060 if (findAttribute(tagHtmlAttribs,"cref",&exceptName)) 05061 { 05062 retval = handleParamSection(exceptName,DocParamSect::Exception,TRUE); 05063 } 05064 else 05065 { 05066 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'name' attribute from <exception> tag."); 05067 } 05068 } 05069 break; 05070 case XML_ITEM: 05071 case XML_LISTHEADER: 05072 if (insideTable(this)) 05073 { 05074 retval=RetVal_TableRow; 05075 } 05076 else if (insideUL(this) || insideOL(this)) 05077 { 05078 retval=RetVal_ListItem; 05079 } 05080 else 05081 { 05082 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <item> tag found"); 05083 } 05084 break; 05085 case XML_RETURNS: 05086 retval = handleSimpleSection(DocSimpleSect::Return,TRUE); 05087 g_hasReturnCommand=TRUE; 05088 break; 05089 case XML_TERM: 05090 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE)); 05091 if (insideTable(this)) 05092 { 05093 retval=RetVal_TableCell; 05094 } 05095 break; 05096 case XML_SEE: 05097 // I'm not sure if <see> is the same as <seealso> or if it 05098 // should you link a member without producing a section. The 05099 // C# specification is extremely vague about this (but what else 05100 // can we expect from Microsoft...) 05101 { 05102 QString cref; 05103 //printf("XML_SEE: empty tag=%d\n",g_token->emptyTag); 05104 if (findAttribute(tagHtmlAttribs,"cref",&cref)) 05105 { 05106 if (g_token->emptyTag) // <see cref="..."/> style 05107 { 05108 bool inSeeBlock = g_inSeeBlock; 05109 g_token->name = cref; 05110 g_inSeeBlock = TRUE; 05111 handleLinkedWord(this,m_children); 05112 g_inSeeBlock = inSeeBlock; 05113 } 05114 else // <see cref="...">...</see> style 05115 { 05116 //DocRef *ref = new DocRef(this,cref); 05117 //m_children.append(ref); 05118 //ref->parse(); 05119 doctokenizerYYsetStatePara(); 05120 DocLink *lnk = new DocLink(this,cref); 05121 m_children.append(lnk); 05122 QString leftOver = lnk->parse(FALSE,TRUE); 05123 if (!leftOver.isEmpty()) 05124 { 05125 m_children.append(new DocWord(this,leftOver)); 05126 } 05127 } 05128 } 05129 else 05130 { 05131 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'cref' attribute from <see> tag."); 05132 } 05133 } 05134 break; 05135 case XML_SEEALSO: 05136 { 05137 QString cref; 05138 if (findAttribute(tagHtmlAttribs,"cref",&cref)) 05139 { 05140 // Look for an existing "see" section 05141 DocSimpleSect *ss=0; 05142 QListIterator<DocNode> cli(m_children); 05143 DocNode *n; 05144 for (cli.toFirst();(n=cli.current());++cli) 05145 { 05146 if (n->kind()==Kind_SimpleSect && ((DocSimpleSect *)n)->type()==DocSimpleSect::See) 05147 { 05148 ss = (DocSimpleSect *)n; 05149 } 05150 } 05151 05152 if (!ss) // start new section 05153 { 05154 ss=new DocSimpleSect(this,DocSimpleSect::See); 05155 m_children.append(ss); 05156 } 05157 05158 ss->appendLinkWord(cref); 05159 retval = RetVal_OK; 05160 } 05161 else 05162 { 05163 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Missing 'cref' attribute from <seealso> tag."); 05164 } 05165 } 05166 break; 05167 case XML_LIST: 05168 { 05169 QString type; 05170 findAttribute(tagHtmlAttribs,"type",&type); 05171 DocHtmlList::Type listType = DocHtmlList::Unordered; 05172 if (type=="number") 05173 { 05174 listType=DocHtmlList::Ordered; 05175 } 05176 if (type=="table") 05177 { 05178 DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs); 05179 m_children.append(table); 05180 retval=table->parseXml(); 05181 } 05182 else 05183 { 05184 HtmlAttribList emptyList; 05185 DocHtmlList *list = new DocHtmlList(this,emptyList,listType); 05186 m_children.append(list); 05187 retval=list->parseXml(); 05188 } 05189 } 05190 break; 05191 case XML_INCLUDE: 05192 case XML_PERMISSION: 05193 // These tags are defined in .Net but are currently unsupported 05194 break; 05195 case HTML_UNKNOWN: 05196 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported xml/html tag <%s> found", tagName.data()); 05197 m_children.append(new DocWord(this, "<"+tagName+tagHtmlAttribs.toString()+">")); 05198 break; 05199 default: 05200 // we should not get here! 05201 ASSERT(0); 05202 break; 05203 } 05204 return retval; 05205 } 05206 05207 int DocPara::handleHtmlEndTag(const QString &tagName) 05208 { 05209 DBG(("handleHtmlEndTag(%s)\n",tagName.data())); 05210 int tagId = Mappers::htmlTagMapper->map(tagName); 05211 int retval=RetVal_OK; 05212 switch (tagId) 05213 { 05214 case HTML_UL: 05215 if (!insideUL(this)) 05216 { 05217 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </ul> tag without matching <ul>"); 05218 } 05219 else 05220 { 05221 retval=RetVal_EndList; 05222 } 05223 break; 05224 case HTML_OL: 05225 if (!insideOL(this)) 05226 { 05227 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </ol> tag without matching <ol>"); 05228 } 05229 else 05230 { 05231 retval=RetVal_EndList; 05232 } 05233 break; 05234 case HTML_LI: 05235 if (!insideLI(this)) 05236 { 05237 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </li> tag without matching <li>"); 05238 } 05239 else 05240 { 05241 // ignore </li> tags 05242 } 05243 break; 05244 //case HTML_PRE: 05245 // if (!insidePRE(this)) 05246 // { 05247 // warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </pre> tag without matching <pre>"); 05248 // } 05249 // else 05250 // { 05251 // retval=RetVal_EndPre; 05252 // } 05253 // break; 05254 case HTML_BOLD: 05255 handleStyleLeave(this,m_children,DocStyleChange::Bold,"b"); 05256 break; 05257 case HTML_CODE: 05258 handleStyleLeave(this,m_children,DocStyleChange::Code,"code"); 05259 break; 05260 case HTML_EMPHASIS: 05261 handleStyleLeave(this,m_children,DocStyleChange::Italic,"em"); 05262 break; 05263 case HTML_DIV: 05264 handleStyleLeave(this,m_children,DocStyleChange::Div,"div"); 05265 break; 05266 case HTML_SPAN: 05267 handleStyleLeave(this,m_children,DocStyleChange::Span,"span"); 05268 break; 05269 case HTML_SUB: 05270 handleStyleLeave(this,m_children,DocStyleChange::Subscript,"sub"); 05271 break; 05272 case HTML_SUP: 05273 handleStyleLeave(this,m_children,DocStyleChange::Superscript,"sup"); 05274 break; 05275 case HTML_CENTER: 05276 handleStyleLeave(this,m_children,DocStyleChange::Center,"center"); 05277 break; 05278 case HTML_SMALL: 05279 handleStyleLeave(this,m_children,DocStyleChange::Small,"small"); 05280 break; 05281 case HTML_PRE: 05282 handleStyleLeave(this,m_children,DocStyleChange::Preformatted,"pre"); 05283 setInsidePreformatted(FALSE); 05284 //doctokenizerYYsetInsidePre(FALSE); 05285 break; 05286 case HTML_P: 05287 // ignore </p> tag 05288 break; 05289 case HTML_DL: 05290 retval=RetVal_EndDesc; 05291 break; 05292 case HTML_DT: 05293 // ignore </dt> tag 05294 break; 05295 case HTML_DD: 05296 // ignore </dd> tag 05297 break; 05298 case HTML_TABLE: 05299 retval=RetVal_EndTable; 05300 break; 05301 case HTML_TR: 05302 // ignore </tr> tag 05303 break; 05304 case HTML_TD: 05305 // ignore </td> tag 05306 break; 05307 case HTML_TH: 05308 // ignore </th> tag 05309 break; 05310 case HTML_CAPTION: 05311 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </caption> found"); 05312 break; 05313 case HTML_BR: 05314 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal </br> tag found\n"); 05315 break; 05316 case HTML_H1: 05317 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </h1> found"); 05318 break; 05319 case HTML_H2: 05320 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </h2> found"); 05321 break; 05322 case HTML_H3: 05323 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </h3> found"); 05324 break; 05325 case HTML_IMG: 05326 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </img> found"); 05327 break; 05328 case HTML_HR: 05329 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </hr> found"); 05330 break; 05331 case HTML_A: 05332 //warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected tag </a> found"); 05333 // ignore </a> tag (can be part of <a name=...></a> 05334 break; 05335 05336 case XML_TERM: 05337 m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE)); 05338 break; 05339 case XML_SUMMARY: 05340 case XML_REMARKS: 05341 case XML_PARA: 05342 case XML_VALUE: 05343 case XML_LIST: 05344 case XML_EXAMPLE: 05345 case XML_PARAM: 05346 case XML_TYPEPARAM: 05347 case XML_RETURNS: 05348 case XML_SEEALSO: 05349 case XML_EXCEPTION: 05350 retval = RetVal_CloseXml; 05351 break; 05352 case XML_C: 05353 handleStyleLeave(this,m_children,DocStyleChange::Code,"c"); 05354 break; 05355 case XML_ITEM: 05356 case XML_LISTHEADER: 05357 case XML_INCLUDE: 05358 case XML_PERMISSION: 05359 case XML_DESCRIPTION: 05360 case XML_PARAMREF: 05361 case XML_TYPEPARAMREF: 05362 // These tags are defined in .Net but are currently unsupported 05363 break; 05364 case HTML_UNKNOWN: 05365 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported xml/html tag </%s> found", tagName.data()); 05366 m_children.append(new DocWord(this,"</"+tagName+">")); 05367 break; 05368 default: 05369 // we should not get here! 05370 warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end tag %s\n",tagName.data()); 05371 ASSERT(0); 05372 break; 05373 } 05374 return retval; 05375 } 05376 05377 int DocPara::parse() 05378 { 05379 DBG(("DocPara::parse() start\n")); 05380 g_nodeStack.push(this); 05381 // handle style commands "inherited" from the previous paragraph 05382 handleInitialStyleCommands(this,m_children); 05383 int tok; 05384 int retval=0; 05385 while ((tok=doctokenizerYYlex())) // get the next token 05386 { 05387 reparsetoken: 05388 DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); 05389 if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || 05390 tok==TK_COMMAND || tok==TK_HTMLTAG 05391 ) 05392 { 05393 DBG((" name=%s",g_token->name.data())); 05394 } 05395 DBG(("\n")); 05396 switch(tok) 05397 { 05398 case TK_WORD: 05399 m_children.append(new DocWord(this,g_token->name)); 05400 break; 05401 case TK_LNKWORD: 05402 handleLinkedWord(this,m_children); 05403 break; 05404 case TK_URL: 05405 m_children.append(new DocURL(this,g_token->name,g_token->isEMailAddr)); 05406 break; 05407 case TK_WHITESPACE: 05408 { 05409 // prevent leading whitespace and collapse multiple whitespace areas 05410 DocNode::Kind k; 05411 if (insidePRE(this) || // all whitespace is relevant 05412 ( 05413 // remove leading whitespace 05414 !m_children.isEmpty() && 05415 // and whitespace after certain constructs 05416 (k=m_children.last()->kind())!=DocNode::Kind_HtmlDescList && 05417 k!=DocNode::Kind_HtmlTable && 05418 k!=DocNode::Kind_HtmlList && 05419 k!=DocNode::Kind_SimpleSect && 05420 k!=DocNode::Kind_AutoList && 05421 k!=DocNode::Kind_SimpleList && 05422 /*k!=DocNode::Kind_Verbatim &&*/ 05423 k!=DocNode::Kind_HtmlHeader && 05424 k!=DocNode::Kind_ParamSect && 05425 k!=DocNode::Kind_XRefItem 05426 ) 05427 ) 05428 { 05429 m_children.append(new DocWhiteSpace(this,g_token->chars)); 05430 } 05431 } 05432 break; 05433 case TK_LISTITEM: 05434 { 05435 DBG(("found list item at %d parent=%d\n",g_token->indent,parent()->kind())); 05436 DocNode *n=parent(); 05437 while (n && n->kind()!=DocNode::Kind_AutoList) n=n->parent(); 05438 if (n) // we found an auto list up in the hierarchy 05439 { 05440 DocAutoList *al = (DocAutoList *)n; 05441 DBG(("previous list item at %d\n",al->indent())); 05442 if (al->indent()>=g_token->indent) 05443 // new item at the same or lower indent level 05444 { 05445 retval=TK_LISTITEM; 05446 goto endparagraph; 05447 } 05448 } 05449 05450 // determine list depth 05451 int depth = 0; 05452 n=parent(); 05453 while(n) { 05454 if(n->kind() == DocNode::Kind_AutoList) ++depth; 05455 n=n->parent(); 05456 } 05457 05458 // first item or sub list => create new list 05459 DocAutoList *al=0; 05460 do 05461 { 05462 al = new DocAutoList(this,g_token->indent,g_token->isEnumList, 05463 depth); 05464 m_children.append(al); 05465 retval = al->parse(); 05466 } while (retval==TK_LISTITEM && // new list 05467 al->indent()==g_token->indent // at same indent level 05468 ); 05469 05470 // check the return value 05471 if (retval==RetVal_SimpleSec) // auto list ended due to simple section command 05472 { 05473 // Reparse the token that ended the section at this level, 05474 // so a new simple section will be started at this level. 05475 // This is the same as unputting the last read token and continuing. 05476 g_token->name = g_token->simpleSectName; 05477 if (g_token->name.left(4)=="rcs:") // RCS section 05478 { 05479 g_token->name = g_token->name.mid(4); 05480 g_token->text = g_token->simpleSectText; 05481 tok = TK_RCSTAG; 05482 } 05483 else // other section 05484 { 05485 tok = TK_COMMAND; 05486 } 05487 DBG(("reparsing command %s\n",g_token->name.data())); 05488 goto reparsetoken; 05489 } 05490 else if (retval==TK_ENDLIST) 05491 { 05492 if (al->indent()>g_token->indent) // end list 05493 { 05494 goto endparagraph; 05495 } 05496 else // continue with current paragraph 05497 { 05498 } 05499 } 05500 else // paragraph ended due to TK_NEWPARA, TK_LISTITEM, or EOF 05501 { 05502 goto endparagraph; 05503 } 05504 } 05505 break; 05506 case TK_ENDLIST: 05507 DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno)); 05508 if (parent()->kind()==DocNode::Kind_AutoListItem) 05509 { 05510 ASSERT(parent()->parent()->kind()==DocNode::Kind_AutoList); 05511 DocAutoList *al = (DocAutoList *)parent()->parent(); 05512 if (al->indent()>=g_token->indent) 05513 { 05514 // end of list marker ends this paragraph 05515 retval=TK_ENDLIST; 05516 goto endparagraph; 05517 } 05518 else 05519 { 05520 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: End of list marker found " 05521 "has invalid indent level"); 05522 } 05523 } 05524 else 05525 { 05526 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: End of list marker found without any preceding " 05527 "list items"); 05528 } 05529 break; 05530 case TK_COMMAND: 05531 { 05532 // see if we have to start a simple section 05533 int cmd = Mappers::cmdMapper->map(g_token->name); 05534 DocNode *n=parent(); 05535 while (n && 05536 n->kind()!=DocNode::Kind_SimpleSect && 05537 n->kind()!=DocNode::Kind_ParamSect 05538 ) 05539 { 05540 n=n->parent(); 05541 } 05542 if (cmd&SIMPLESECT_BIT) 05543 { 05544 if (n) // already in a simple section 05545 { 05546 // simple section cannot start in this paragraph, need 05547 // to unwind the stack and remember the command. 05548 g_token->simpleSectName = g_token->name.copy(); 05549 retval=RetVal_SimpleSec; 05550 goto endparagraph; 05551 } 05552 } 05553 // see if we are in a simple list 05554 n=parent(); 05555 while (n && n->kind()!=DocNode::Kind_SimpleListItem) n=n->parent(); 05556 if (n) 05557 { 05558 if (cmd==CMD_LI) 05559 { 05560 retval=RetVal_ListItem; 05561 goto endparagraph; 05562 } 05563 } 05564 05565 // handle the command 05566 retval=handleCommand(g_token->name.copy()); 05567 DBG(("handleCommand returns %x\n",retval)); 05568 05569 // check the return value 05570 if (retval==RetVal_SimpleSec) 05571 { 05572 // Reparse the token that ended the section at this level, 05573 // so a new simple section will be started at this level. 05574 // This is the same as unputting the last read token and continuing. 05575 g_token->name = g_token->simpleSectName; 05576 if (g_token->name.left(4)=="rcs:") // RCS section 05577 { 05578 g_token->name = g_token->name.mid(4); 05579 g_token->text = g_token->simpleSectText; 05580 tok = TK_RCSTAG; 05581 } 05582 else // other section 05583 { 05584 tok = TK_COMMAND; 05585 } 05586 DBG(("reparsing command %s\n",g_token->name.data())); 05587 goto reparsetoken; 05588 } 05589 else if (retval==RetVal_OK) 05590 { 05591 // the command ended normally, keep scanning for new tokens. 05592 retval = 0; 05593 } 05594 else if (retval>0 && retval<RetVal_OK) 05595 { 05596 // the command ended with a new command, reparse this token 05597 tok = retval; 05598 goto reparsetoken; 05599 } 05600 else // end of file, end of paragraph, start or end of section 05601 // or some auto list marker 05602 { 05603 goto endparagraph; 05604 } 05605 } 05606 break; 05607 case TK_HTMLTAG: 05608 { 05609 if (!g_token->endTag) // found a start tag 05610 { 05611 retval = handleHtmlStartTag(g_token->name,g_token->attribs); 05612 } 05613 else // found an end tag 05614 { 05615 retval = handleHtmlEndTag(g_token->name); 05616 } 05617 if (retval==RetVal_OK) 05618 { 05619 // the command ended normally, keep scanner for new tokens. 05620 retval = 0; 05621 } 05622 else 05623 { 05624 goto endparagraph; 05625 } 05626 } 05627 break; 05628 case TK_SYMBOL: 05629 { 05630 char letter='\0'; 05631 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name,&letter); 05632 if (s!=DocSymbol::Unknown) 05633 { 05634 m_children.append(new DocSymbol(this,s,letter)); 05635 } 05636 else 05637 { 05638 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 05639 g_token->name.data()); 05640 } 05641 break; 05642 } 05643 case TK_NEWPARA: 05644 retval=TK_NEWPARA; 05645 goto endparagraph; 05646 case TK_RCSTAG: 05647 { 05648 DocNode *n=parent(); 05649 while (n && 05650 n->kind()!=DocNode::Kind_SimpleSect && 05651 n->kind()!=DocNode::Kind_ParamSect 05652 ) 05653 { 05654 n=n->parent(); 05655 } 05656 if (n) // already in a simple section 05657 { 05658 // simple section cannot start in this paragraph, need 05659 // to unwind the stack and remember the command. 05660 g_token->simpleSectName = "rcs:"+g_token->name; 05661 g_token->simpleSectText = g_token->text; 05662 retval=RetVal_SimpleSec; 05663 goto endparagraph; 05664 } 05665 05666 // see if we are in a simple list 05667 DocSimpleSect *ss=new DocSimpleSect(this,DocSimpleSect::Rcs); 05668 m_children.append(ss); 05669 ss->parseRcs(); 05670 } 05671 break; 05672 default: 05673 warn_doc_error(g_fileName,doctokenizerYYlineno, 05674 "Warning: Found unexpected token (id=%x)\n",tok); 05675 break; 05676 } 05677 } 05678 retval=0; 05679 endparagraph: 05680 handlePendingStyleCommands(this,m_children); 05681 DocNode *n = g_nodeStack.pop(); 05682 ASSERT(n==this); 05683 DBG(("DocPara::parse() end retval=%x\n",retval)); 05684 INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM || 05685 retval==TK_ENDLIST || retval>RetVal_OK 05686 ); 05687 05688 return retval; 05689 } 05690 05691 //-------------------------------------------------------------------------- 05692 05693 int DocSection::parse() 05694 { 05695 DBG(("DocSection::parse() start %s level=%d\n",g_token->sectionId.data(),m_level)); 05696 int retval=RetVal_OK; 05697 g_nodeStack.push(this); 05698 05699 SectionInfo *sec; 05700 if (!m_id.isEmpty()) 05701 { 05702 sec=Doxygen::sectionDict[m_id]; 05703 if (sec) 05704 { 05705 m_file = sec->fileName; 05706 m_anchor = sec->label; 05707 m_title = sec->title; 05708 if (m_title.isEmpty()) m_title = sec->label; 05709 if (g_sectionDict && g_sectionDict->find(m_id)==0) 05710 { 05711 g_sectionDict->insert(m_id,sec); 05712 } 05713 } 05714 } 05715 05716 // first parse any number of paragraphs 05717 bool isFirst=TRUE; 05718 DocPara *lastPar=0; 05719 do 05720 { 05721 DocPara *par = new DocPara(this); 05722 if (isFirst) { par->markFirst(); isFirst=FALSE; } 05723 retval=par->parse(); 05724 if (!par->isEmpty()) 05725 { 05726 m_children.append(par); 05727 lastPar=par; 05728 } 05729 else 05730 { 05731 delete par; 05732 } 05733 if (retval==TK_LISTITEM) 05734 { 05735 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid list item found"); 05736 } 05737 } while (retval!=0 && 05738 retval!=RetVal_Internal && 05739 retval!=RetVal_Section && 05740 retval!=RetVal_Subsection && 05741 retval!=RetVal_Subsubsection && 05742 retval!=RetVal_Paragraph 05743 ); 05744 05745 if (lastPar) lastPar->markLast(); 05746 05747 if (retval==RetVal_Subsection && m_level==1) 05748 { 05749 // then parse any number of nested sections 05750 while (retval==RetVal_Subsection) // more sections follow 05751 { 05752 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; 05753 DocSection *s=new DocSection(this,2,g_token->sectionId); 05754 m_children.append(s); 05755 retval = s->parse(); 05756 } 05757 } 05758 else if (retval==RetVal_Subsubsection && m_level==2) 05759 { 05760 // then parse any number of nested sections 05761 while (retval==RetVal_Subsubsection) // more sections follow 05762 { 05763 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; 05764 DocSection *s=new DocSection(this,3,g_token->sectionId); 05765 m_children.append(s); 05766 retval = s->parse(); 05767 } 05768 } 05769 else if (retval==RetVal_Paragraph && m_level==3) 05770 { 05771 // then parse any number of nested sections 05772 while (retval==RetVal_Paragraph) // more sections follow 05773 { 05774 //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; 05775 DocSection *s=new DocSection(this,4,g_token->sectionId); 05776 m_children.append(s); 05777 retval = s->parse(); 05778 } 05779 } 05780 else if ((m_level<=1 && retval==RetVal_Subsubsection) || 05781 (m_level<=2 && retval==RetVal_Paragraph) 05782 ) 05783 { 05784 int level; 05785 if (retval==RetVal_Subsection) level=2; 05786 else if (retval==RetVal_Subsubsection) level=3; 05787 else level=4; 05788 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected %s " 05789 "command found inside %s!", 05790 sectionLevelToName[level],sectionLevelToName[m_level]); 05791 retval=0; // stop parsing 05792 05793 } 05794 else if (retval==RetVal_Internal) 05795 { 05796 DocInternal *in = new DocInternal(this); 05797 m_children.append(in); 05798 retval = in->parse(m_level+1); 05799 } 05800 else 05801 { 05802 } 05803 05804 INTERNAL_ASSERT(retval==0 || 05805 retval==RetVal_Section || 05806 retval==RetVal_Subsection || 05807 retval==RetVal_Subsubsection || 05808 retval==RetVal_Paragraph || 05809 retval==RetVal_Internal 05810 ); 05811 05812 DBG(("DocSection::parse() end\n")); 05813 DocNode *n = g_nodeStack.pop(); 05814 ASSERT(n==this); 05815 return retval; 05816 } 05817 05818 //-------------------------------------------------------------------------- 05819 05820 void DocText::parse() 05821 { 05822 DBG(("DocText::parse() start\n")); 05823 g_nodeStack.push(this); 05824 doctokenizerYYsetStateText(); 05825 05826 int tok; 05827 while ((tok=doctokenizerYYlex())) // get the next token 05828 { 05829 switch(tok) 05830 { 05831 case TK_WORD: 05832 m_children.append(new DocWord(this,g_token->name)); 05833 break; 05834 case TK_WHITESPACE: 05835 m_children.append(new DocWhiteSpace(this,g_token->chars)); 05836 break; 05837 case TK_SYMBOL: 05838 { 05839 char letter='\0'; 05840 DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name,&letter); 05841 if (s!=DocSymbol::Unknown) 05842 { 05843 m_children.append(new DocSymbol(this,s,letter)); 05844 } 05845 else 05846 { 05847 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found", 05848 g_token->name.data()); 05849 } 05850 } 05851 break; 05852 case TK_COMMAND: 05853 switch (Mappers::cmdMapper->map(g_token->name)) 05854 { 05855 case CMD_BSLASH: 05856 m_children.append(new DocSymbol(this,DocSymbol::BSlash)); 05857 break; 05858 case CMD_AT: 05859 m_children.append(new DocSymbol(this,DocSymbol::At)); 05860 break; 05861 case CMD_LESS: 05862 m_children.append(new DocSymbol(this,DocSymbol::Less)); 05863 break; 05864 case CMD_GREATER: 05865 m_children.append(new DocSymbol(this,DocSymbol::Greater)); 05866 break; 05867 case CMD_AMP: 05868 m_children.append(new DocSymbol(this,DocSymbol::Amp)); 05869 break; 05870 case CMD_DOLLAR: 05871 m_children.append(new DocSymbol(this,DocSymbol::Dollar)); 05872 break; 05873 case CMD_HASH: 05874 m_children.append(new DocSymbol(this,DocSymbol::Hash)); 05875 break; 05876 case CMD_PERCENT: 05877 m_children.append(new DocSymbol(this,DocSymbol::Percent)); 05878 break; 05879 default: 05880 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected command `%s' found", 05881 g_token->name.data()); 05882 break; 05883 } 05884 break; 05885 default: 05886 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected token %s", 05887 tokToString(tok)); 05888 break; 05889 } 05890 } 05891 05892 handleUnclosedStyleCommands(); 05893 05894 DocNode *n = g_nodeStack.pop(); 05895 ASSERT(n==this); 05896 DBG(("DocText::parse() end\n")); 05897 } 05898 05899 05900 //-------------------------------------------------------------------------- 05901 05902 void DocRoot::parse() 05903 { 05904 DBG(("DocRoot::parse() start\n")); 05905 g_nodeStack.push(this); 05906 doctokenizerYYsetStatePara(); 05907 int retval=0; 05908 05909 // first parse any number of paragraphs 05910 bool isFirst=TRUE; 05911 DocPara *lastPar=0; 05912 do 05913 { 05914 DocPara *par = new DocPara(this); 05915 if (isFirst) { par->markFirst(); isFirst=FALSE; } 05916 retval=par->parse(); 05917 if (!par->isEmpty()) 05918 { 05919 m_children.append(par); 05920 lastPar=par; 05921 } 05922 else 05923 { 05924 delete par; 05925 } 05926 if (retval==TK_LISTITEM) 05927 { 05928 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid list item found"); 05929 } 05930 else if (retval==RetVal_Subsection) 05931 { 05932 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found subsection command outside of section context!"); 05933 } 05934 else if (retval==RetVal_Subsubsection) 05935 { 05936 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found subsubsection command outside of subsection context!"); 05937 } 05938 else if (retval==RetVal_Paragraph) 05939 { 05940 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found paragraph command outside of subsubsection context!"); 05941 } 05942 } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Internal); 05943 if (lastPar) lastPar->markLast(); 05944 05945 // then parse any number of level1 sections 05946 while (retval==RetVal_Section) 05947 { 05948 SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; 05949 if (sec) 05950 { 05951 DocSection *s=new DocSection(this,1,g_token->sectionId); 05952 m_children.append(s); 05953 retval = s->parse(); 05954 } 05955 else 05956 { 05957 warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Invalid section id `%s'; ignoring section",g_token->sectionId.data()); 05958 retval = 0; 05959 } 05960 } 05961 05962 if (retval==RetVal_Internal) 05963 { 05964 DocInternal *in = new DocInternal(this); 05965 m_children.append(in); 05966 retval = in->parse(1); 05967 } 05968 05969 05970 handleUnclosedStyleCommands(); 05971 05972 DocNode *n = g_nodeStack.pop(); 05973 ASSERT(n==this); 05974 DBG(("DocRoot::parse() end\n")); 05975 } 05976 05977 //-------------------------------------------------------------------------- 05978 05979 DocNode *validatingParseDoc(const char *fileName,int startLine, 05980 Definition *ctx,MemberDef *md, 05981 const char *input,bool indexWords, 05982 bool isExample, const char *exampleName, 05983 bool singleLine, bool linkFromIndex) 05984 { 05985 //printf("validatingParseDoc(%s,%s)\n",ctx?ctx->name().data():"<none>", 05986 // md?md->name().data():"<none>"); 05987 //printf("========== validating %s at line %d\n",fileName,startLine); 05988 //printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",input); 05989 //g_token = new TokenInfo; 05990 05991 // store parser state so we can re-enter this function if needed 05992 bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); 05993 docParserPushContext(); 05994 05995 if (ctx && 05996 (ctx->definitionType()==Definition::TypeClass || 05997 ctx->definitionType()==Definition::TypeNamespace 05998 ) 05999 ) 06000 { 06001 g_context = ctx->name(); 06002 } 06003 else if (ctx && ctx->definitionType()==Definition::TypePage) 06004 { 06005 Definition *scope = ((PageDef*)ctx)->getPageScope(); 06006 if (scope) g_context = scope->name(); 06007 } 06008 else if (ctx && ctx->definitionType()==Definition::TypeGroup) 06009 { 06010 Definition *scope = ((GroupDef*)ctx)->getGroupScope(); 06011 if (scope) g_context = scope->name(); 06012 } 06013 else 06014 { 06015 g_context = ""; 06016 } 06017 06018 if (indexWords && md && Config_getBool("SEARCHENGINE")) 06019 { 06020 06021 g_searchUrl=md->getOutputFileBase(); 06022 Doxygen::searchIndex->setCurrentDoc( 06023 (fortranOpt?theTranslator->trSubprogram(TRUE,TRUE):theTranslator->trMember(TRUE,TRUE))+" "+md->qualifiedName(), 06024 g_searchUrl, 06025 md->anchor()); 06026 } 06027 else if (indexWords && ctx && Config_getBool("SEARCHENGINE")) 06028 { 06029 g_searchUrl=ctx->getOutputFileBase(); 06030 QCString name = ctx->qualifiedName(); 06031 if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) 06032 { 06033 name = substitute(name,"::","."); 06034 } 06035 switch (ctx->definitionType()) 06036 { 06037 case Definition::TypePage: 06038 { 06039 PageDef *pd = (PageDef *)ctx; 06040 if (!pd->title().isEmpty()) 06041 { 06042 name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title(); 06043 } 06044 else 06045 { 06046 name = theTranslator->trPage(TRUE,TRUE)+" "+pd->name(); 06047 } 06048 } 06049 break; 06050 case Definition::TypeClass: 06051 { 06052 ClassDef *cd = (ClassDef *)ctx; 06053 name.prepend(cd->compoundTypeString()+" "); 06054 } 06055 break; 06056 case Definition::TypeNamespace: 06057 { 06058 if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) 06059 { 06060 name = theTranslator->trPackage(name); 06061 } 06062 else if(fortranOpt) 06063 { 06064 name.prepend(theTranslator->trModule(TRUE,TRUE)+" "); 06065 } 06066 else 06067 { 06068 name.prepend(theTranslator->trNamespace(TRUE,TRUE)+" "); 06069 } 06070 } 06071 break; 06072 case Definition::TypeGroup: 06073 { 06074 GroupDef *gd = (GroupDef *)ctx; 06075 if (gd->groupTitle()) 06076 { 06077 name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle(); 06078 } 06079 else 06080 { 06081 name.prepend(theTranslator->trGroup(TRUE,TRUE)+" "); 06082 } 06083 } 06084 break; 06085 default: 06086 break; 06087 } 06088 Doxygen::searchIndex->setCurrentDoc(name,g_searchUrl); 06089 } 06090 else 06091 { 06092 g_searchUrl=""; 06093 } 06094 06095 g_fileName = fileName; 06096 g_relPath = (!linkFromIndex && ctx) ? 06097 QString(relativePathToRoot(ctx->getOutputFileBase())) : 06098 QString(""); 06099 //printf("ctx->name=%s relPath=%s\n",ctx->name().data(),g_relPath.data()); 06100 g_memberDef = md; 06101 g_nodeStack.clear(); 06102 g_styleStack.clear(); 06103 g_initialStyleStack.clear(); 06104 g_inSeeBlock = FALSE; 06105 g_insideHtmlLink = FALSE; 06106 g_includeFileText = ""; 06107 g_includeFileOffset = 0; 06108 g_includeFileLength = 0; 06109 g_isExample = isExample; 06110 g_exampleName = exampleName; 06111 g_hasParamCommand = FALSE; 06112 g_hasReturnCommand = FALSE; 06113 g_paramsFound.setAutoDelete(FALSE); 06114 g_paramsFound.clear(); 06115 g_sectionDict = 0; //sections; 06116 06117 //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine); 06118 doctokenizerYYlineno=startLine; 06119 doctokenizerYYinit(input,g_fileName); 06120 06121 06122 // build abstract syntax tree 06123 DocRoot *root = new DocRoot(md!=0,singleLine); 06124 root->parse(); 06125 06126 06127 if (Debug::isFlagSet(Debug::PrintTree)) 06128 { 06129 // pretty print the result 06130 PrintDocVisitor *v = new PrintDocVisitor; 06131 root->accept(v); 06132 delete v; 06133 } 06134 06135 06136 checkUndocumentedParams(); 06137 detectNoDocumentedParams(); 06138 06139 // TODO: These should be called at the end of the program. 06140 //doctokenizerYYcleanup(); 06141 //Mappers::cmdMapper->freeInstance(); 06142 //Mappers::htmlTagMapper->freeInstance(); 06143 06144 // restore original parser state 06145 docParserPopContext(); 06146 06147 return root; 06148 } 06149 06150 DocNode *validatingParseText(const char *input) 06151 { 06152 // store parser state so we can re-enter this function if needed 06153 docParserPushContext(); 06154 06155 //printf("------------ input ---------\n%s\n" 06156 // "------------ end input -----\n",input); 06157 //g_token = new TokenInfo; 06158 g_context = ""; 06159 g_fileName = "<parseText>"; 06160 g_relPath = ""; 06161 g_memberDef = 0; 06162 g_nodeStack.clear(); 06163 g_styleStack.clear(); 06164 g_initialStyleStack.clear(); 06165 g_inSeeBlock = FALSE; 06166 g_insideHtmlLink = FALSE; 06167 g_includeFileText = ""; 06168 g_includeFileOffset = 0; 06169 g_includeFileLength = 0; 06170 g_isExample = FALSE; 06171 g_exampleName = ""; 06172 g_hasParamCommand = FALSE; 06173 g_hasReturnCommand = FALSE; 06174 g_paramsFound.setAutoDelete(FALSE); 06175 g_paramsFound.clear(); 06176 g_searchUrl=""; 06177 06178 DocText *txt = new DocText; 06179 06180 if (input) 06181 { 06182 doctokenizerYYlineno=1; 06183 doctokenizerYYinit(input,g_fileName); 06184 06185 // build abstract syntax tree 06186 txt->parse(); 06187 06188 if (Debug::isFlagSet(Debug::PrintTree)) 06189 { 06190 // pretty print the result 06191 PrintDocVisitor *v = new PrintDocVisitor; 06192 txt->accept(v); 06193 delete v; 06194 } 06195 } 06196 06197 // restore original parser state 06198 docParserPopContext(); 06199 return txt; 06200 } 06201 06202 void docFindSections(const char *input, 06203 Definition *d, 06204 MemberGroup *mg, 06205 const char *fileName) 06206 { 06207 doctokenizerYYFindSections(input,d,mg,fileName); 06208 } 06209 06210 void initDocParser() 06211 { 06212 if (Config_getBool("SEARCHENGINE")) 06213 { 06214 Doxygen::searchIndex = new SearchIndex; 06215 } 06216 else 06217 { 06218 Doxygen::searchIndex = 0; 06219 } 06220 } 06221 06222 void finializeDocParser() 06223 { 06224 delete Doxygen::searchIndex; 06225 } 06226