/***************************************************************************** * * * * Copyright (C) 1997-2002 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */ %{ /* * includes */ #include #include #include #include #include "qtbc.h" #include #include #include #include "doc.h" #include "code.h" #include "message.h" #include "doxygen.h" #include "config.h" #include "util.h" #include "language.h" #include "outputlist.h" #include "reflist.h" #include "page.h" #ifndef WIN32 #include #endif #define YY_NEVER_INTERACTIVE 1 /* ----------------------------------------------------------------- * * scanner's state variables */ static MemberDef * memberDef; static bool hasParamCommand; static QDict paramsFound; static OutputDocInterface * outDoc; static bool insideArgumentList; static QCString className; static QCString linkRef; static QCString linkText; static QCString codeBlock; static const char * inputString; static int inputPosition; static char yyFileName[4096] ; static int yyLineNr = 1 ; static bool exampleDoc; static QCString exampleName; static QCString htmlUrl,htmlText; static QCString currentIncludeFile; static int includeFileOffset = 0; static int includeFileLength = 0; static bool firstLine; static bool inParamBlock; static bool inRetValBlock; static bool inExceptionBlock; static bool inSeeBlock; static bool inReturnBlock; static bool inAuthorBlock; static bool inDeprecatedBlock; static bool inVersionBlock; static bool inSinceBlock; static bool inDateBlock; static bool inBugBlock; static bool inNoteBlock; static bool inPreBlock; static bool inPostBlock; static bool inInvarBlock; static bool inWarningBlock; static bool inRemarkBlock; static bool inAttentionBlock; static bool inParBlock; static bool insideHtmlLink; static QCString sectionRef; static bool insideVerbatim = FALSE; static bool insidePre = FALSE; static int depthIf; static QCString curImageName; static QCString curImageCaption; static QCString curDotFileName; static QCString curDotFileCaption; static QCString internalRefFile; static QCString internalRefAnchor; static QCString caption; static QStack currentListIndent; // indent stack of all list items static bool insideItemList = FALSE; struct DocLexerContext { int rule; int position; const char *inputString; YY_BUFFER_STATE lexerState; }; static QStack lexerStack; static void pushContext() { DocLexerContext *ctx = new DocLexerContext; ctx->rule = YY_START; ctx->position = inputPosition; ctx->inputString = inputString; ctx->lexerState = YY_CURRENT_BUFFER; lexerStack.push(ctx); yy_switch_to_buffer(yy_create_buffer(docYYin, YY_BUF_SIZE)); } static bool popContext() { if (lexerStack.isEmpty()) return TRUE; DocLexerContext *ctx = lexerStack.pop(); inputPosition = ctx->position; inputString = ctx->inputString; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(ctx->lexerState); BEGIN(ctx->rule); delete ctx; return TRUE; } static QCString copyDocString; static QCString copyDocScope; static QList copyDocDefList; //----------------------------------------------------------------------------- static void initParser() { insideArgumentList=FALSE; className.resize(0); linkRef.resize(0); linkText.resize(0); codeBlock.resize(0); htmlUrl.resize(0); htmlText.resize(0); currentIncludeFile.resize(0); includeFileOffset = 0; includeFileLength = 0; firstLine = TRUE; inParamBlock = FALSE; inRetValBlock = FALSE; inExceptionBlock = FALSE; inSeeBlock = FALSE; inReturnBlock = FALSE; inAuthorBlock = FALSE; inDeprecatedBlock = FALSE; inVersionBlock = FALSE; inSinceBlock = FALSE; inDateBlock = FALSE; inBugBlock = FALSE; inNoteBlock = FALSE; inPreBlock = FALSE; inPostBlock = FALSE; inInvarBlock = FALSE; inWarningBlock = FALSE; inRemarkBlock = FALSE; inAttentionBlock = FALSE; inParBlock = FALSE; insideHtmlLink = FALSE; } //----------------------------------------------------------------------------- void scanString(const char *s); void scanDoc(const char *s); void internalParseDocument(const char *s); //----------------------------------------------------------------------------- class TableElem { public: TableElem(int r,int c); ~TableElem(); int getRow() { return row; } int getCol() { return col; } OutputDocInterface *outputDocInterface() { return od; } private: OutputDocInterface *od; int row; int col; }; TableElem::TableElem(int r,int c) { //printf("TableElem::TableElem(%d,%d)\n",r,c); od=outDoc->clone(); outDoc=od; row=r; col=c; } TableElem::~TableElem() { //printf("TableElem::~TableElem(%d,%d)\n",row,col); delete od; od=0; } class Table { public: Table(); ~Table(); void newRow(); void newElem(); void setCaption(const char *s); private: OutputDocInterface *m_parentDoc; QList *m_elemList; QCString m_caption; int m_curRow; int m_curCol; int m_rows; int m_cols; }; Table::Table() { m_parentDoc=outDoc; m_elemList=new QList; m_elemList->setAutoDelete(TRUE); m_curRow=m_curCol=m_rows=m_cols=0; } Table::~Table() { //printf("Table::~Table()\n"); // use elemList & cols & rows if (m_cols>0 && m_rows>0) { m_parentDoc->startTable(!m_caption.isEmpty(),m_cols); TableElem *e=m_elemList->first(); while (e) { if (e->getRow()>0) { if (e->getCol()==0) { if (e->getRow()>1) m_parentDoc->endTableRow(); m_parentDoc->nextTableRow(); } else { m_parentDoc->nextTableColumn(); } m_parentDoc->append(e->outputDocInterface()); m_parentDoc->endTableColumn(); } e=m_elemList->next(); } if (!m_caption.isEmpty()) { m_parentDoc->startCaption(); m_parentDoc->docify(m_caption); m_parentDoc->endCaption(); } m_parentDoc->endTable(!m_caption.isEmpty()); } delete m_elemList; m_elemList=0; outDoc=m_parentDoc; } void Table::setCaption(const char *s) { m_caption=s; } void Table::newRow() { //printf("Table::newRow()\n"); m_curRow++; if (m_curRow>m_rows) m_rows=m_curRow; m_curCol=0; } void Table::newElem() { //printf("Table::newElem(%d,%d)\n",curRow,curCol); TableElem *te = new TableElem(m_curRow,m_curCol); m_elemList->append(te); m_curCol++; if (m_curCol>m_cols) m_cols=m_curCol; } static QStack tableStack; static Table *curTable; static void startTable() { //printf("startTable()\n"); curTable=new Table; tableStack.push(curTable); } static void endTable() { //printf("endTable()\n"); delete tableStack.pop(); // the destructor adds the table to the stream! curTable=tableStack.top(); } static void forceEndTable() { err("Error: More
tags found than
" "tags in documentation block in file %s!\n",yyFileName); while (!tableStack.isEmpty()) { endTable(); } } //----------------------------------------------------------------------------- static void includeFile(OutputDocInterface &od,const char *fileName,bool quiet) { bool ambig; FileDef *fd; if ((fd=findFileDef(Doxygen::exampleNameDict,fileName,ambig))) { currentIncludeFile=fileToString(fd->absFilePath()); includeFileOffset=0; includeFileLength=currentIncludeFile.length(); OutputDocInterface *codeFrag = od.clone(); parseCode(*codeFrag,0,currentIncludeFile,exampleDoc,exampleName); if (!quiet) { od.startCodeFragment(); od.append(codeFrag); od.endCodeFragment(); } delete codeFrag; } else if (ambig) { QCString text; text.sprintf("Include file name %s is ambigious.\n",fileName); text+="Possible candidates:\n"; text+=showFileDefMatches(Doxygen::exampleNameDict,fileName); warn(yyFileName,yyLineNr,text); } else { warn(yyFileName,yyLineNr, "Warning: example file %s is not found. " "Check your EXAMPLE_PATH",fileName ); } } static void verbIncludeFile(OutputDocInterface &od,const char *name) { bool ambig; FileDef *fd; if ((fd=findFileDef(Doxygen::exampleNameDict,name,ambig))) { od.startCodeFragment(); od.codify(fileToString(fd->absFilePath())+"\n"); od.endCodeFragment(); } else if (ambig) { QCString text; text.sprintf("Include file name %s is ambigious.\n",name); text+=("Possible candidates:\n"); text+=showFileDefMatches(Doxygen::exampleNameDict,name); warn(yyFileName,yyLineNr,text); } else { warn(yyFileName,yyLineNr, "Warning: example file %s is not found. " "Check your EXAMPLE_PATH",name); } } static void rawIncludeFile(OutputDocInterface &od,const char *name) { bool ambig; FileDef *fd; if ((fd=findFileDef(Doxygen::exampleNameDict,name,ambig))) { od.writeString(fileToString(fd->absFilePath())); } else if (ambig) { QCString text; text.sprintf("Include file name %s is ambigious.\n",name); text+=("Possible candidates:\n"); text+=showFileDefMatches(Doxygen::exampleNameDict,name); warn(yyFileName,yyLineNr,text); } else { warn(yyFileName,yyLineNr, "Warning: include file %s is not found. " "Check your EXAMPLE_PATH",name); } } static QCString stripQuotes(const char *s) { QCString name; if (s==0 || *s==0) return name; name=s; if (name.at(0)=='"' && name.at(name.length()-1)=='"') { name=name.mid(1,name.length()-2); } return name; } static QCString stripKnownExtensions(const char *text) { QCString result=text; if (result.right(4)==".tex") result=result.left(result.length()-4); else if (result.right(htmlFileExtensionLength)==htmlFileExtension) result=result.left(result.length()-htmlFileExtensionLength); //printf("%s stripKnowExtensions(%s)\n",result.data(),text); return result; } static void skipLine(OutputDocInterface &od,const char *key) { bool found=FALSE; while (!found) { QCString s; char c; while ( includeFileOffsetendDescTableData(); outDoc->endDescTable(); outDoc->endParamList(); } else { outDoc->endSimpleSect(); } currentListIndent.pop(); inParamBlock=inRetValBlock=inSeeBlock=inReturnBlock=inAuthorBlock= inVersionBlock=inSinceBlock=inDateBlock=inBugBlock=inNoteBlock=inWarningBlock= inParBlock=inExceptionBlock=inDeprecatedBlock=inPreBlock=inPostBlock= inInvarBlock=inRemarkBlock=inAttentionBlock=FALSE; } //----------------------------------------------------------------- struct IndentInfo { public: IndentInfo(int i,bool e) : indent(i), enumerated(e) {}; ~IndentInfo() {} void startList() { if (enumerated) outDoc->startEnumList(); else outDoc->startItemList(); } void endList() { if (enumerated) outDoc->endEnumList(); else outDoc->endItemList(); } void writeItem() { outDoc->writeListItem(); } int indent; bool enumerated; }; static QStack listIndentStack; // indent stack of - items static int computeIndent(const char *str,int length) { int i; int indent=0; int tabSize=Config_getInt("TAB_SIZE"); for (i=0;istartList(); listIndentStack.top()->writeItem(); insideItemList=TRUE; } else { IndentInfo *pPrevInfo = listIndentStack.top(); if (pPrevInfo->indent==indent && pPrevInfo->enumerated==enumerated) // new item of same kind at the same indent level { pPrevInfo->writeItem(); } else if (pPrevInfo->indent==indent) // new item of diffent kind at the same indent level { // switch to a diffent list type pPrevInfo->endList(); pPrevInfo->enumerated=enumerated; pPrevInfo->startList(); pPrevInfo->writeItem(); } else if (pPrevInfo->indentstartList(); listIndentStack.top()->writeItem(); } else // end sub item list { while (pPrevInfo && pPrevInfo->indent>indent) { pPrevInfo->endList(); listIndentStack.pop(); currentListIndent.pop(); delete pPrevInfo; pPrevInfo = listIndentStack.top(); } // safe guard against wrong indenting if (listIndentStack.isEmpty()) { insideItemList=FALSE; warn(yyFileName,yyLineNr, "Warning: list item with invalid indent found!"); } else { listIndentStack.top()->writeItem(); } } } } static void endListMarker(const char *marker,int dotPos) { int indent=computeIndent(marker,dotPos); //printf("endListMarker indent=%d " // "insideItemList=%d listIndentStack.count()=%d\n", // indent,insideItemList,listIndentStack.count()); if (insideItemList && !listIndentStack.isEmpty()) { IndentInfo *ii = listIndentStack.top(); while (ii && indent<=ii->indent) { ii->endList(); listIndentStack.pop(); currentListIndent.pop(); delete ii; ii = listIndentStack.top(); //printf("ending list new indent=%d\n",ii ? ii->indent : -1); } if (listIndentStack.isEmpty()) { insideItemList=FALSE; //printf("ending last list\n"); } } } // end the current (nested) list regardless of the nesting level. static void forceEndItemList() { IndentInfo *info; while ((info=listIndentStack.pop())!=0) { delete info; } while (!currentListIndent.isEmpty()) { char c=*currentListIndent.pop(); switch(c) { case 'O': outDoc->endEnumList(); break; case 'U': outDoc->endItemList(); break; case 'D': outDoc->endDescription(); break; case 'P': if (inBlock()) endBlock(); break; default: err("Unexpected list indent token `%c'\n",c); } } insideItemList=FALSE; } static void endArgumentList() { if (insideArgumentList) { insideArgumentList=FALSE; outDoc->endItemList(); } } //----------------------------------------------------------------- enum ImageTypes { IT_Html, IT_Latex, IT_RTF }; /*! search for an image in the imageNameDict and if found * copies the image to the output directory (which is the * html directory if type==0 or the latex directory if type==1) */ static QCString findAndCopyImage(const char *fileName,ImageTypes type) { QCString result; bool ambig; FileDef *fd; //printf("Search for %s\n",fileName); if ((fd=findFileDef(Doxygen::imageNameDict,fileName,ambig))) { QFile inImage(QString(fd->absFilePath().data())); if (inImage.open(IO_ReadOnly)) { result = fileName; int i; if ((i=result.findRev('/'))!=-1 || (i=result.findRev('\\'))!=-1) { result.right(result.length()-i-1); } QCString outputDir; switch(type) { case IT_Html: if (!Config_getBool("GENERATE_HTML")) return result; outputDir = Config_getString("HTML_OUTPUT"); break; case IT_Latex: if (!Config_getBool("GENERATE_LATEX")) return result; outputDir = Config_getString("LATEX_OUTPUT"); break; case IT_RTF: if (!Config_getBool("GENERATE_RTF")) return result; outputDir = Config_getString("RTF_OUTPUT"); break; } QCString outputFile = outputDir+"/"+result; QFile outImage(QString(outputFile.data())); if (outImage.open(IO_WriteOnly)) // copy the image { char *buffer = new char[inImage.size()]; inImage.readBlock(buffer,inImage.size()); outImage.writeBlock(buffer,inImage.size()); outImage.flush(); delete buffer; } else { warn(yyFileName,yyLineNr, "Warning: could not write output image %s",outputFile.data()); } } else { warn(yyFileName,yyLineNr, "Warning: could not open image %s",fileName); } if (type==IT_Latex && Config_getBool("USE_PDFLATEX") && fd->name().right(4)==".eps" ) { // we have an .eps image in pdflatex mode => convert it to a pdf. QCString outputDir = Config_getString("LATEX_OUTPUT"); QCString baseName = fd->name().left(fd->name().length()-4); QCString epstopdfArgs(4096); epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"", outputDir.data(), baseName.data(), outputDir.data(), baseName.data()); if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0) { err("Error: Problems running epstopdf. Check your TeX installation!\n"); } return baseName; } } else if (ambig) { QCString text; text.sprintf("Warning: image file name %s is ambigious.\n",fileName); text+="Possible candidates:\n"; text+=showFileDefMatches(Doxygen::imageNameDict,fileName); warn(yyFileName,yyLineNr,text); } else { result=fileName; if (result.left(5)!="http:" && result.left(6)!="https:") { warn(yyFileName,yyLineNr, "Warning: image file %s is not found in IMAGE_PATH: " "assuming external image.",fileName ); } } return result; } void writeImage(ImageTypes it,const char *size) { bool hasCaption=!curImageCaption.isEmpty(); outDoc->pushGeneratorState(); switch(it) { case IT_Latex: { outDoc->disableAllBut(OutputGenerator::Latex); outDoc->startImage(curImageName,size,hasCaption); if (hasCaption) { scanString(curImageCaption); } outDoc->endImage(hasCaption); } break; case IT_Html: { outDoc->disableAllBut(OutputGenerator::Html); outDoc->startImage(curImageName,0,hasCaption); if (hasCaption) { scanString(curImageCaption); } outDoc->endImage(hasCaption); } break; case IT_RTF: { outDoc->disableAllBut(OutputGenerator::RTF); outDoc->startImage(curImageName,0,hasCaption); if (hasCaption) { scanString(curImageCaption); } outDoc->endImage(hasCaption); } } outDoc->popGeneratorState(); } // search for a dot file in the dotFileNameDict, and if found // generates the graph in the output directories. static void writeDotFile(const char *fileName, const char *captionText) { bool ambig; FileDef *fd; bool hasCaption = captionText!=0; if ((fd=findFileDef(Doxygen::dotFileNameDict,fileName,ambig))) { outDoc->startDotFile(fd->absFilePath(),hasCaption); if (hasCaption) { scanString(captionText); } outDoc->endDotFile(hasCaption); } else if (ambig) { QCString text; text.sprintf("Warning: dot file name %s is ambigious.\n",fileName); text+="Possible candidates:\n"; text+=showFileDefMatches(Doxygen::dotFileNameDict,fileName); warn(yyFileName,yyLineNr,text); } else { warn(yyFileName,yyLineNr, "Warning: dot file %s is not found in DOTFILE_DIRS! ",fileName ); } } /* ----------------------------------------------------------------- */ static void checkArgName(const QCString &name,bool isParam) { hasParamCommand=TRUE; if (memberDef==0) return; // not a member ArgumentList *al=memberDef->isDocsForDefinition() ? memberDef->argumentList() : memberDef->declArgumentList(); if (al==0) return; // no argument list if (!Config_getBool("WARN_IF_UNDOCUMENTED")) return; //printf("name=%s\n",name.data()); static QRegExp re("[a-zA-Z0-9_]+\\.*"); int p=0,i=0,l; while ((i=re.match(name,p,&l))!=-1) { QCString aName=name.mid(i,l); //printf("aName=%s\n",aName.data()); ArgumentListIterator ali(*al); Argument *a; bool found=FALSE; for (ali.toFirst();(a=ali.current());++ali) { QCString argName = memberDef->isDefine() ? a->type : a->name; if (argName.right(3)=="...") argName=argName.left(argName.length()-3); if (aName==argName) { //printf("adding `%s'\n",aName.data()); paramsFound.insert(aName,(void *)(0x8)); found=TRUE; break; } } if (!found && isParam) { //printf("member type=%d\n",memberDef->memberType()); QCString scope=memberDef->getScopeString(); if (!scope.isEmpty()) scope+="::"; else scope=""; warn(memberDef->docFile(),memberDef->docLine(), "Warning: argument `%s' of command @param " "is not found in the argument list of %s%s%s", aName.data(),scope.data(),memberDef->name().data(), argListToString(al).data() ); } p=i+l; } } /* ----------------------------------------------------------------- */ /*! Looks for a documentation block with name commandName in the current * context (copyDocScope). The resulting documentation string is * put in pDoc, the definition in which the documentation was found is * put in pDef. * @retval TRUE if name was found. * @retval FALSE if name was not found. */ bool findDocsForMemberOrCompound(const char *commandName, QCString *pDoc, Definition **pDef) { pDoc->resize(0); *pDef=0; QCString cmdArg=commandName; int l=cmdArg.length(); if (l==0) return FALSE; int funcStart=cmdArg.find('('); if (funcStart==-1) funcStart=l; //int lastScopeStart=cmdArg.findRev("::",funcStart); //int lastScopeEnd = lastScopeStart==-1 ? 0 : lastScopeStart+2; //QCString scope=cmdArg.left(QMAX(lastScopeStart,0)); //QCString name=cmdArg.mid(lastScopeEnd,funcStart-lastScopeEnd); QCString name=cmdArg.left(funcStart); QCString args=cmdArg.right(l-funcStart); // try if the link is to a member MemberDef *md=0; ClassDef *cd=0; FileDef *fd=0; NamespaceDef *nd=0; GroupDef *gd=0; PageInfo *pi=0; bool found = getDefs(copyDocScope,name,args,md,cd,fd,nd,gd,FALSE,0,TRUE); if (found && md) { *pDoc=md->documentation(); *pDef=md; return TRUE; } int scopeOffset=copyDocScope.length(); do // for each scope { QCString fullName=cmdArg; if (scopeOffset>0) { fullName.prepend(copyDocScope.left(scopeOffset)+"::"); } //printf("Trying fullName=`%s'\n",fullName.data()); // try class, namespace, group, page, file reference cd = Doxygen::classSDict[fullName]; if (cd) // class { *pDoc=cd->documentation(); *pDef=cd; return TRUE; } nd = Doxygen::namespaceSDict[fullName]; if (nd) // namespace { *pDoc=nd->documentation(); *pDef=nd; return TRUE; } gd = Doxygen::groupSDict[cmdArg]; if (gd) // group { *pDoc=gd->documentation(); *pDef=gd; return TRUE; } pi = Doxygen::pageSDict->find(cmdArg); if (pi) // page { *pDoc=pi->doc; *pDef=(Definition *)pi; return TRUE; } bool ambig; fd = findFileDef(Doxygen::inputNameDict,cmdArg,ambig); if (fd && !ambig) // file { *pDoc=fd->documentation(); *pDef=fd; return TRUE; } if (scopeOffset==0) { scopeOffset=-1; } else { scopeOffset = copyDocScope.findRev("::",scopeOffset-1); if (scopeOffset==-1) scopeOffset=0; } } while (scopeOffset>=0); return FALSE; } /* ----------------------------------------------------------------- */ static void writeSpecialItem(const char *commandString) { QCString cmd = commandString; // format "\test 20" or "\todo 4" int sepPos=cmd.find(' '); QCString listName = cmd.mid(1,cmd.length()-sepPos-1); // i.e. "test" or "todo" RefList *refList = Doxygen::specialLists->find(cmd.mid(1,sepPos-1)); ASSERT(refList!=0); if (Config_getBool(refList->optionName())) { QCString numStr=cmd.right(cmd.length()-sepPos-1); // i.e. "20" or "4" bool ok; int num = numStr.toUInt(&ok); RefItem *item = refList->getRefItem(num); ASSERT(item!=0); if (insideItemList) { forceEndItemList(); } endArgumentList(); if (inBlock()) endBlock(); currentListIndent.push("P"); outDoc->startSimpleSect(refList->sectionType(), refList->listName(), item->listAnchor, refList->sectionTitle()+": " ); outDoc->writeDescItem(); internalParseDocument(item->text); outDoc->endSimpleSect(); currentListIndent.pop(); } } /* ----------------------------------------------------------------- */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); static int yyread(char *buf,int max_size) { int c=0; while ( c < max_size && inputString[inputPosition] ) { *buf = inputString[inputPosition++] ; //printf("%d (%c)\n",*buf,*buf); c++; buf++; } return c; } //ATTR ((({BN}+[^\>]+)/">")?) %} CMD ("\\"|"@") BN [ \t\n\r] BL [ \t\r]*"\n" BSEP [ \t\r]*([ \t\r]|"\n")({BL}{0,100}) B [ \t] BS ^(({B}*"//")?)(({B}*"*"+)?){B}* FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+] FILEECHAR [a-z_A-Z0-9\-\+] FILEMASK {FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)+ FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]+"\"") ID [a-z_A-Z][a-z_A-Z0-9]* SCOPENAME (({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID}) SCOPEMASK {ID}?(("::"|"#")?(~)?{ID})+ URLCHAR [a-z_A-Z0-9\!\~\:\;\'\$\?\@\&\%\#\.\-\+\/\=] URLMASK (([a-z_A-Z][^\>\"\n]*{URLCHAR})|({URLCHAR}+))([({]{URLCHAR}*[)}])? NONTERM [\{\}\[\]\`\~\@\|\-\+\#\$\/\\\!\%\^\&\*()a-z_A-Z<>0-9\x80-\xff] WORD ({NONTERM}+([^\n\t ]*{NONTERM}+)?)|("\""[^\n\"]*"\"") ATTR ({B}+[^>\n]*)? A [aA] BOLD [bB] BODY [bB][oO][dD][yY] BR [bB][rR] EM [eE][mM] CENTER [cC][eE][nN][tT][eE][rR] CODE [cC][oO][dD][eE] DL [dD][lL] DD [dD][dD] DT [dD][tT] DFN [dD][fF][nN] FORM [fF][oO][rR][mM] H1 [hH]1 H2 [hH]2 H3 [hH][3-6] HEAD [hH][eE][aA][dD] HR [hH][rR] HREF [hH][rR][eE][fF] I [iI] IMG [iI][mM][gG] INPUT [iI][nN][pP][uU][tT] KBD [kK][bB][dD] LI [lL][iI] META [mM][eE][tT][aA] MULTICOL [mM][uU][lL][tT][iI][cC][oO][lL] NAME [nN][aA][mM][eE] OL [oO][lL] P [pP] PRE [pP][rR][eE] SMALL [sS][mM][aA][lL][lL] STRONG [sS][tT][rR][oO][nN][gG] SUB [sS][uU][bB] SUP [sS][uU][pP] SRC [sS][rR][cC] TABLE [tT][aA][bB][lL][eE] CAPTION [cC][aA][pP][tT][iI][oO][nN] TITLE [tT][iI][tT][lL][eE] TD [tT][dD] TR [tT][rR] TT [tT][tT] UL [uU][lL] VAR [vV][aA][rR] BLOCKQUOTE [bB][lL][oO][cC][kK][qQ][uU][oO][tT][eE] DOCPARAM ("#")?([a-z_A-Z0-9:\!\<\~\>\^\&\=\.\-]+)|("\"".*"\"") OPNEW {B}+"new"({B}*"[]")? OPDEL {B}+"delete"({B}*"[]")? OPARG "("[a-z_A-Z0-9,\<\> \t\*\&]*")" OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()" OPCAST {B}+[^(\r\n.,]+ OPMASK ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG}) LINKMASK [a-z_A-Z0-9:#.,~&*/\[\]<>()\-\+]+({B}*("const"|"volatile"))? %option noyywrap %x Text %x DocScan %x DocParam %x DocException %x DocHtmlScan %x DocLatexScan %x DocEmphasis %x DocBold %x DocCode %x DocCodeBlock %x DocInternal %x DocLink %x DocJavaLink %x DocLinkText %x DocJavaLinkText %x DocSkipWord %x DocInclude %x DocDontInclude %x DocHtmlLink %x DocHtmlAnchor %x DocHtmlHref %x DocSkiplineKey %x DocSkipKey %x DocLineKey %x DocUntilKey %x DocKeyEnd %x DocPar %x DocRefName %x DocVerbatim %x DocVerbInc %x DocHtmlInc %x DocIndexWord %x DocRefArg %x DocRefArgStart %x DocRefItem %x DocRefItemName %x DocInternalRef %x DocInternalRefText %x DocImage %x DocCaption %x DocHtmlImageName %x DocHtmlImageOpt %x DocLatexImageName %x DocLatexImageOpt %x DocRtfImageName %x DocRtfImageOpt %x DocDotFile %x DocDotFileOpt %x DocSkipLanguage %x DocCopyFind %x DocCopyArg %x DocCopySkipVerb %% <*>\x0d ^{B}*(("//"{B}*)?)"*"*{B}*"-"("#")?{B}+ { /* found list item marker */ QCString text=yytext; int dashPos = text.findRev('-'); //printf("dashPos=%d char='%c'\n",dashPos,text.at(dashPos+1)); bool isEnumerated = text.at(dashPos+1)=='#'; addListItemMarker(yytext,dashPos+1,isEnumerated); } ^{B}*(("//"{B}*)?)"*"*{B}*"."{B}*/\n { /* found end list marker */ QCString text=yytext; int dotPos = text.findRev('.'); endListMarker(yytext,dotPos+1); } \n{B}*(("//"{B}*)?)"*"*{B}*"-"("#")?{B}+ { /* found list item marker */ QCString text=yytext; int dashPos = text.findRev('-'); //printf("dashPos=%d char='%c'\n",dashPos,text.at(dashPos+1)); bool isEnumerated = text.at(dashPos+1)=='#'; addListItemMarker(yytext+1,dashPos,isEnumerated); } \n{B}*(("//"{B}*)?)"*"*{B}*"."{B}*/\n { /* found end list marker */ QCString text=yytext; int dotPos = text.findRev('.'); endListMarker(yytext+1,dotPos); } "©" { outDoc->writeCopyright(); } "<" { outDoc->docify("<"); } ">" { outDoc->docify(">"); } "&" { outDoc->docify("&"); } "'" { outDoc->docify("'"); } """ { outDoc->docify("\""); } "&"[AEIOUYaeiouy]"uml;" { outDoc->writeUmlaut(yytext[1]); } "&"[AEIOUYaeiouy]"acute;" { outDoc->writeAcute(yytext[1]); } "&"[AEIOUaeiou]"grave;" { outDoc->writeGrave(yytext[1]); } "&"[AEIOUaeiou]"circ;" { outDoc->writeCirc(yytext[1]); } "&"[ANOano]"tilde;" { outDoc->writeTilde(yytext[1]); } "ß" { outDoc->writeSharpS(); } "&"[cC]"cedil;" { outDoc->writeCCedil(yytext[1]); } "&"[aA]"ring;" { outDoc->writeRing(yytext[1]); } " " { outDoc->writeNonBreakableSpace(1); } "$("[a-z_A-Z]+")" { QCString envvar=&yytext[2]; envvar=envvar.left(envvar.length()-1); outDoc->docify(getenv(envvar)); } {CMD}"htmlonly"/[^a-z_A-Z0-9] { outDoc->startHtmlOnly(); outDoc->pushGeneratorState(); outDoc->disableAllBut(OutputGenerator::Html); BEGIN(DocHtmlScan); } {CMD}"endhtmlonly"/[^a-z_A-Z0-9] { outDoc->popGeneratorState(); outDoc->endHtmlOnly(); BEGIN(DocScan); } {CMD}"latexonly"/[^a-z_A-Z0-9] { outDoc->startLatexOnly(); outDoc->pushGeneratorState(); outDoc->disableAllBut(OutputGenerator::Latex); BEGIN(DocLatexScan); } {CMD}"endlatexonly"/[^a-z_A-Z0-9] { outDoc->popGeneratorState(); outDoc->endLatexOnly(); BEGIN(DocScan); } "//"|"/*"|"*/" { outDoc->writeString(yytext); } .|\n { outDoc->writeString(yytext); } "\\postheader"/{BN} "\\functionindex"/{BN} { /* writeMemberList(*outDoc,FALSE);*/ } "\\classhierarchy"/{BN} { /* writeClassHierarchy(*outDoc); */ } "\\annotatedclasslist"/{BN} { /* writeAnnotatedClassList(*outDoc); */ } "\\headerfilelist"/{BN} { /* writeHeaderFileList(*outDoc); */ } "\\header"/{BN} { BEGIN( DocSkipWord ); } "\\define"/{BN} { BEGIN( DocSkipWord ); } {CMD}"verbinclude"/{BN} { BEGIN( DocVerbInc ); } {FILE} { verbIncludeFile(*outDoc,stripQuotes(yytext)); BEGIN( DocScan ); } {CMD}"htmlinclude"/{BN} { BEGIN( DocHtmlInc ); } {FILE} { outDoc->pushGeneratorState(); outDoc->disableAllBut(OutputGenerator::Html); rawIncludeFile(*outDoc,stripQuotes(yytext)); outDoc->popGeneratorState(); BEGIN( DocScan ); } {CMD}"verbatim"/[^a-z_A-Z0-9] { outDoc->startVerbatimFragment(); insideVerbatim=TRUE; BEGIN(DocVerbatim); } {CMD}"endverbatim"/[^a-z_A-Z0-9] { outDoc->endVerbatimFragment(); insideVerbatim=FALSE; BEGIN(DocScan); } [^\n\\\@]*"\n" { //printf("docifying: %s\n",yytext); outDoc->codify(yytext); } "\n"|"//"|"/*"|"*/" { outDoc->codify(yytext); } . { //printf("char %c\n",*yytext); char c[2];c[0]=*yytext;c[1]='\0'; outDoc->codify(c); } {CMD}"~"[a-z_A-Z0-9]*/{BN} { if (yytext[2]) { if (theTranslator->idLanguage()!=&yytext[2]) // not current language { BEGIN(DocSkipLanguage); } } } {CMD}"~"[a-z_A-Z0-9]*/{BN} { if (yytext[2]) { if (theTranslator->idLanguage()==&yytext[2]) { BEGIN( DocScan ); // current language => include } } else // back to "all language" processing. { BEGIN( DocScan ); } } [^\\\@\~\n]+ {CMD}"internal"/{BN} { outDoc->newParagraph(); outDoc->startBold(); scanString(theTranslator->trForInternalUseOnly()+"\n"); outDoc->endBold(); outDoc->newParagraph(); } "\\reimp"/{BN} { outDoc->newParagraph(); scanString(theTranslator->trReimplementedForInternalReasons()+"\n"); } {CMD}"link"/{BN} { BEGIN( DocLink ); } "{"{CMD}"link"{BN}+ { BEGIN( DocJavaLink ); } [a-z_A-Z0-9.:()]+ { BEGIN( DocScan ); } {LINKMASK} { // TODO: support operators as well! linkRef = stripKnownExtensions(yytext); linkText = ""; BEGIN( DocLinkText ); } {LINKMASK} { // TODO: support operators as well! linkRef = yytext; linkText = ""; BEGIN( DocJavaLinkText ); } "}" { //printf("Trying to link `%s'\n",linkRef.data()); if (!generateLink(*outDoc,className,linkRef,inSeeBlock,linkText.stripWhiteSpace())) { warn(yyFileName,yyLineNr,"Warning: link to unknown entity `%s' in the documentation of this entity!",linkRef.data()); } BEGIN( DocScan ); } . { linkText += *yytext; } "\n" { linkText += " "; } {CMD}"endlink" { // <- needed for things like \endlink. //printf("GenerateLink className=`%s' linkRef=`%s' linkText=`%s'\n", // className.data(),linkRef.data(),linkText.data()); if (!generateLink(*outDoc,className,linkRef,inSeeBlock,linkText.stripWhiteSpace())) { warn(yyFileName,yyLineNr,"Warning: link to unknown entity `%s' in the documentation of this entity!",linkRef.data()); } BEGIN( DocScan ); } {CMD}"endlink"/[^a-z_A-Z0-9] { warn(yyFileName,yyLineNr, "Warning: \\endlink without \\link " "in documentation of this entity." ); } {CMD}"addindex"{B}+ { BEGIN(DocIndexWord); } "\\form#"[0-9]+ { Formula *formula=Doxygen::formulaNameDict[yytext]; if (formula) { QCString formName; formName.sprintf("form_%d",formula->getId()); outDoc->writeFormula(formName,formula->getFormulaText()); } } [^\n]+ { //printf("Adding %s to index\n",yytext); outDoc->addIndexItem(yytext,0); BEGIN(DocScan); } {CMD}("arg"|"li")/{BN} { if (insideItemList) { forceEndItemList(); } if (insideArgumentList) { outDoc->writeListItem(); } else { outDoc->startItemList(); outDoc->writeListItem(); insideArgumentList=TRUE; } } (({B}*"\n"){2,}{B}*)?{CMD}"par"{B}* { QCString t=yytext; if (/*t.contains('\n')>1 &&*/ insideItemList) { forceEndItemList(); } BEGIN(DocPar); } [^\n]*{BSEP} { QCString title=QCString(yytext).stripWhiteSpace(); bool b = inBlock(); if (!title.isEmpty()) { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (b) endBlock(); inParBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Par,0,0,title); outDoc->writeDescItem(); } else { outDoc->newParagraph(); } BEGIN(DocScan); } {CMD}"warning"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inWarningBlock) { if (inBlock()) endBlock(); inWarningBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Warning,0,0,theTranslator->trWarning()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"remark"[s]?{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inRemarkBlock) { if (inBlock()) endBlock(); inRemarkBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Remark,0,0,theTranslator->trRemarks()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"attention"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inAttentionBlock) { if (inBlock()) endBlock(); inAttentionBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Attention,0,0,theTranslator->trAttention()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"note"[s]?{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inNoteBlock) { if (inBlock()) endBlock(); inNoteBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Note,0,0,theTranslator->trNote()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"pre"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inPreBlock) { if (inBlock()) endBlock(); inPreBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Pre,0,0,theTranslator->trPrecondition()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"post"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inPostBlock) { if (inBlock()) endBlock(); inPostBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Post,0,0,theTranslator->trPostcondition()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"invariant"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inInvarBlock) { if (inBlock()) endBlock(); inInvarBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Invar,0,0,theTranslator->trInvariant()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"version"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inVersionBlock) { if (inBlock()) endBlock(); inVersionBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Version,0,0,theTranslator->trVersion()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"since"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inSinceBlock) { if (inBlock()) endBlock(); inSinceBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Since,0,0,theTranslator->trSince()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } {CMD}"date"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inDateBlock) { if (inBlock()) endBlock(); inDateBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Date,0,0,theTranslator->trDate()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } "\\todo "[0-9]+ | /* generated labels */ "\\test "[0-9]+ | "\\bug "[0-9]+ { writeSpecialItem(yytext); } {CMD}"deprecated"{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inDeprecatedBlock) { if (inBlock()) endBlock(); inDeprecatedBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Deprecated,0,0,theTranslator->trDeprecated()+": "); outDoc->writeDescItem(); } else { outDoc->writeDescItem(); } } "$"[a-zA-Z_0-9]+":"[^\n\$]+"$" { // RCS tag QCString tagName(&yytext[1]); int i=tagName.find(':'); tagName=tagName.left(i); QCString tagText=&yytext[i+2]; tagText=tagText.left(tagText.length()-1); if (insideItemList) { forceEndItemList(); } endArgumentList(); if (inBlock()) endBlock(); currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::RCS,0,0,tagName+": "); outDoc->writeDescItem(); scanString(tagText); outDoc->endSimpleSect(); currentListIndent.pop(); } {CMD}"author"[s]?{BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inAuthorBlock) { if (inBlock()) endBlock(); inAuthorBlock=TRUE; currentListIndent.push("P"); bool singular = ((QString)yytext).find('s')==-1; outDoc->startSimpleSect(BaseOutputDocInterface::Author, 0,0,theTranslator->trAuthor(TRUE,singular)+": "); outDoc->writeDescItem(); } else { outDoc->docify(", "); } } {CMD}("return"([s])?|"result"){BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inReturnBlock) { if (inBlock()) endBlock(); inReturnBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::Return,0,0,theTranslator->trReturns()+" :"); outDoc->writeDescItem(); } } {CMD}("sa"|"see"){BSEP} { if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inSeeBlock) { if (inBlock()) endBlock(); inSeeBlock=TRUE; currentListIndent.push("P"); outDoc->startSimpleSect(BaseOutputDocInterface::See,0,0,theTranslator->trSeeAlso()+": "); outDoc->writeDescItem(); } else { outDoc->docify(", "); } } (({B}*"\n"){2,}{B}*)?{CMD}"param"{BSEP} { QCString t=yytext; if (insideItemList) { forceEndItemList(); } endArgumentList(); if (!inParamBlock) { if (inBlock()) endBlock(); inParamBlock=TRUE; currentListIndent.push("P"); outDoc->startParamList(BaseOutputDocInterface::Param,theTranslator->trParameters()+": "); outDoc->writeDescItem(); outDoc->startDescTable(); } else { outDoc->endDescTableData(); } BEGIN(DocParam); } (({B}*"\n"){2,}{B}*)?{CMD}"retval"{BSEP} { QCString t=yytext; if (/*t.contains('\n')>1 &&*/ insideItemList) { forceEndItemList(); } endArgumentList(); if (!inRetValBlock) { if (inBlock()) endBlock(); inRetValBlock=TRUE; currentListIndent.push("P"); outDoc->startParamList(BaseOutputDocInterface::RetVal,theTranslator->trReturnValues()+": "); outDoc->writeDescItem(); outDoc->startDescTable(); } else { outDoc->endDescTableData(); } BEGIN(DocParam); } (({B}*"\n"){2,}{B}*)?{CMD}("exception"|"throw")s?{BSEP} { QCString t=yytext; if (/*t.contains('\n')>1 &&*/ insideItemList) { forceEndItemList(); } endArgumentList(); if (!inExceptionBlock) { if (inBlock()) endBlock(); inExceptionBlock=TRUE; currentListIndent.push("P"); outDoc->startParamList(BaseOutputDocInterface::Exception,theTranslator->trExceptions()+": "); outDoc->writeDescItem(); outDoc->startDescTable(); } else { outDoc->endDescTableData(); } BEGIN(DocException); } "\\capt".* ({DOCPARAM}{BN}*","{BN}*)*{DOCPARAM}{BSEP}* { QCString argName = substitute(yytext,"\"","").stripWhiteSpace(); if (inParamBlock) { checkArgName(argName,TRUE); } else if (inRetValBlock) { checkArgName(argName,FALSE); } outDoc->startDescTableTitle(); scanDoc(argName); outDoc->endDescTableTitle(); outDoc->startDescTableData(); BEGIN(DocScan); } {SCOPENAME} { outDoc->startDescTableTitle(); generateRef(*outDoc,className,yytext,FALSE); outDoc->endDescTableTitle(); outDoc->startDescTableData(); BEGIN(DocScan); } {CMD}"section "{ID}"\n" { QCString secName=&yytext[9]; // skip "\section " secName=secName.left(secName.length()-1); // remove \n //printf("SectionName %s found\n",secName.data()); SectionInfo *sec; if ((sec=Doxygen::sectionDict[secName])) { //printf("Title %s\n",sec->title.data()); outDoc->startSection(sec->label,sec->title, sec->type==SectionInfo::Subsection); scanString(sec->title); outDoc->endSection(sec->label, sec->type==SectionInfo::Subsection); } else { warn(yyFileName,yyLineNr,"Warning: reference to unknown section %s in the documentation of this entity!",yytext); } } {CMD}"anchor "{ID}"\n" { QCString secName=&yytext[8]; secName=secName.left(secName.length()-1); SectionInfo *sec; if ((sec=Doxygen::sectionDict[secName])) { //printf("writeAnchor %s_%s\n",sec->fileName.data(),sec->label.data()); outDoc->writeAnchor(sec->fileName,sec->label); } } "\\_internalref"{B}+ { // for internal use only! internalRefFile.resize(0); internalRefAnchor.resize(0); BEGIN(DocInternalRef); } [A-Z_a-z0-9.:\-\+]+ { internalRefFile=yytext; int i = internalRefFile.find(':'); if (i!=-1) { internalRefAnchor=internalRefFile.right(internalRefFile.length()-i-1); internalRefFile=internalRefFile.left(i); } //printf("InternalRef yytext=`%s' file=`%s' anchor=`%s'\n",yytext,internalRefFile.data(),internalRefAnchor.data()); BEGIN(DocInternalRefText); } \"[^\n\"]*\" { QCString text=substitute(yytext,"\"",""); outDoc->writeObjectLink(0,internalRefFile,internalRefAnchor,text); BEGIN(DocScan); } {CMD}"ref"/{BN} { BEGIN(DocRefName); } {CMD}"refitem"/{BN} { BEGIN(DocRefItem); } /* {CMD}"if"/{BN} { outDoc->pushGeneratorState(); depthIf++; BEGIN(DocIf); } {CMD}"endif"/[^a-z_A-Z0-9] { if (--depthIf<0) { warn(yyFileName,yyLineNr, "Warning: documentation block contains \\endif without " "matching \\if found in documentation of this entity." ); } else { outDoc->popGeneratorState(); } } [^\n\t ]+ { if (Config_getList("ENABLED_SECTIONS").find(yytext)==-1) { outDoc->disableAll(); } BEGIN(DocScan); } */ {SCOPENAME}|{FILE} { QCString ref=yytext; SectionInfo *sec; //printf(">>> ref `%s'\n",yytext); if ((sec=Doxygen::sectionDict[ref])) { //printf("Is a section!\n"); QCString text; if (sec->title.isEmpty()) text=sec->label; else text=sec->title; if (sec->type==SectionInfo::Anchor) { outDoc->writeObjectLink(sec->ref,sec->fileName,sec->label,text); if (sec->ref.isEmpty()) { writePageRef(*outDoc,sec->label,0); } } else { //printf(" ref sec=%p sec->fileName=%s text=%s\n",sec,sec->fileName.data(),text.data()); outDoc->writeSectionRef(sec->ref,sec->fileName,sec->label,text); } } else if (!generateLink(*outDoc,className,yytext,TRUE,0)) { warn(yyFileName,yyLineNr,"Warning: reference to unknown section %s in the documentation of this entity!",yytext); } BEGIN(DocScan); } ({SCOPENAME}|{FILE}){B}+/"\"" { //printf(">>> ref `%s'\n",yytext); sectionRef=yytext; sectionRef=sectionRef.stripWhiteSpace(); BEGIN(DocRefArgStart); } "\"" { BEGIN(DocRefArg); } [^\"\n]+[\n\"] { yytext[yyleng-1]='\0'; QCString text=substitute(yytext,"\\\\","\\"); SectionInfo *sec; if ((sec=Doxygen::sectionDict[sectionRef])) { //printf("Is a section!\n"); if (sec->type==SectionInfo::Anchor) { outDoc->writeObjectLink(sec->ref,sec->fileName,sec->label,text); if (sec->ref.isEmpty()) { writePageRef(*outDoc,sec->label,0); } } else { outDoc->writeSectionRef(sec->ref,sec->fileName,sec->label,text); } } else if (!generateLink(*outDoc,className,sectionRef,TRUE,text)) { warn(yyFileName,yyLineNr,"Warning: reference to unknown section %s in the documentation of this entity!",sectionRef.data()); outDoc->startBold(); outDoc->writeString(" unknown reference! "); outDoc->endBold(); } BEGIN(DocScan); } {ID} { sectionRef=yytext; BEGIN(DocRefItemName); } .*/"\n" { SectionInfo *sec; QCString text=yytext; if ((sec=Doxygen::sectionDict[sectionRef])) { outDoc->writeSectionRefItem(sec->fileName,sec->label,text.stripWhiteSpace()); } else { warn(yyFileName,yyLineNr,"Warning: reference to unknown section %s in the documentation of this entity!",sectionRef.data()); outDoc->startBold(); outDoc->writeString(" unknown reference! "); outDoc->endBold(); } BEGIN(DocScan); } {CMD}"image"{B}+ { BEGIN(DocImage); } [hH][tT][mM][lL] { BEGIN(DocHtmlImageName); } [lL][aA][tT][eE][xX] { BEGIN(DocLatexImageName); } [rR][tT][fF] { BEGIN(DocRtfImageName); } [^ \t\n]+ { curImageName = findAndCopyImage(stripQuotes(yytext),IT_Html); curImageCaption.resize(0); if (curImageName.isEmpty()) { BEGIN(DocScan); } else { BEGIN(DocHtmlImageOpt); } } \n { writeImage(IT_Html,0); BEGIN(DocScan); } \"[^\n"]*\" { curImageCaption=stripQuotes(yytext); } {FILE} { curImageName = findAndCopyImage(stripQuotes(yytext),IT_RTF); curImageCaption.resize(0); if (curImageName.isEmpty()) { BEGIN(DocScan); } else { BEGIN(DocRtfImageOpt); } } \n { writeImage(IT_RTF,0); } \"[^\n"]*\" { curImageCaption=stripQuotes(yytext); } {FILE} { curImageName = findAndCopyImage(stripQuotes(yytext),IT_Latex); curImageCaption.resize(0); if (curImageName.isEmpty()) BEGIN(DocScan); else BEGIN(DocLatexImageOpt); } \n { // no width specified writeImage(IT_Latex,0); BEGIN(DocScan); } \"[^\n"]*\" { curImageCaption=stripQuotes(yytext); } ("width"{B}*"="{B}*)(([0-9\.]+({B}*{ID})?)|("\\"{ID})) { writeImage(IT_Latex,yytext); BEGIN(DocScan); } ("height"{B}*"="{B}*)(([0-9\.]+({B}*{ID})?)|("\\"{ID})) { writeImage(IT_Latex,yytext); BEGIN(DocScan); } [a-z_A-Z0-9\.\-]+ { warn(yyFileName,yyLineNr,"Warning: %s is an unsupported output format for \\image in the documentation of the entity",yytext); } \n { warn(yyFileName,yyLineNr,"Warning: invalid \\image command found in the documentation of this entity!"); outDoc->enableAll(); BEGIN(DocScan); } {CMD}"dotfile"{B}* { BEGIN(DocDotFile); } {FILE} { curDotFileName = stripQuotes(yytext); curDotFileCaption.resize(0); if (curDotFileName.isEmpty()) { BEGIN(DocScan); } else { BEGIN(DocDotFileOpt); } } \n { writeDotFile(curDotFileName,curDotFileCaption); BEGIN(DocScan); } \"[^\n"]*\" { curDotFileCaption = stripQuotes(yytext); writeDotFile(curDotFileName,curDotFileCaption); BEGIN(DocScan); } {CMD}"code"({BN}*"\n"|{B}*) { outDoc->startCodeFragment(); codeBlock.resize(0); BEGIN( DocCodeBlock ); } {CMD}"endcode"/[^a-z_A-Z0-9] { warn(yyFileName,yyLineNr,"Warning: \\endcode without \\code " "in the documentation of this entity."); } {ID}"<"[^>\ \t\n]*">"("::"{ID})+"("?[a-z_A-Z0-9,:\<\> \t\*\&]*")"? { if (!insideHtmlLink) { generateRef(*outDoc,className,yytext,inSeeBlock); } else { outDoc->docify(yytext); } BEGIN(DocScan); } {SCOPEMASK}"("[a-z_A-Z0-9,:\<\> \t\*\&]+")"({B}*("const"|"volatile"))? { if (!insideHtmlLink) { generateRef(*outDoc,className,yytext,inSeeBlock); } else { outDoc->docify(yytext); } BEGIN(DocScan); } {SCOPEMASK}("()"({B}*("const"|"volatile"))?)? { if (!insideHtmlLink) { generateRef(*outDoc,className,yytext,inSeeBlock); } else { outDoc->docify(yytext); } BEGIN(DocScan); } ({SCOPEMASK}"::")?"operator"{OPMASK} { QCString oName=yytext; if (!insideHtmlLink) { generateRef(*outDoc,className, removeRedundantWhiteSpace(oName),inSeeBlock); } else { outDoc->docify(yytext); } BEGIN(DocScan); } ("http:"|"https:"|"ftp:"|"file:"){URLMASK} { outDoc->startHtmlLink(yytext); outDoc->docify(yytext); outDoc->endHtmlLink(); } [a-zA-Z_0-9\.\-]+"@"[0-9a-z_A-Z\.\-]+ { outDoc->writeMailLink(yytext); } {FILESCHAR}*{FILEECHAR}+/".\\n" { // special exception that is otherwise matches by FILEMASK if (!insideHtmlLink) { generateRef(*outDoc,className,yytext,inSeeBlock); } else { outDoc->docify(yytext); } } {FILEMASK} { if (!insideHtmlLink) { generateFileRef(*outDoc,yytext); } else { outDoc->docify(yytext); } } {BN}*{CMD}"endcode"/[^a-z_A-Z0-9] { // needed to match things like \endcode. (note the dot) codeBlock+="\n"; parseCode(*outDoc,className,codeBlock,exampleDoc,exampleName); //printf("Code block\n-------------\n%s\n--------------\n",codeBlock.data()); outDoc->endCodeFragment(); BEGIN( DocScan ); } {CMD}("e"|"em"|"a"){BN}+ { BEGIN( DocEmphasis ); } {CMD}"b"{BN}+ { BEGIN( DocBold ); } {CMD}("c"|"p"){BN}+ { BEGIN( DocCode ); } {CMD}"l"{BN}+ "\\n"/[^a-z_A-Z0-9] { outDoc->lineBreak(); } {CMD}"include"{BN}+ { BEGIN( DocInclude ); } {CMD}"dontinclude"{BN}+ { BEGIN( DocDontInclude ); } {CMD}"skip"{BN}+ { BEGIN( DocSkipKey ); } {CMD}"skipline"{BN}+ { BEGIN( DocSkiplineKey ); firstLine=TRUE; } {CMD}"line"{BN}+ { BEGIN( DocLineKey ); firstLine=TRUE; } {CMD}"until"{BN}+ { BEGIN( DocUntilKey ); firstLine=TRUE; } [^\r\n]+ { if (includeFileLength>0) { QCString pattern=yytext; skipUntil(pattern.stripWhiteSpace()); } BEGIN( DocScan ); } [^\r\n]+ { if (includeFileLength>0) { QCString pattern=yytext; if (firstLine) outDoc->startCodeFragment(); firstLine=FALSE; showLine(*outDoc,pattern.stripWhiteSpace()); BEGIN( DocKeyEnd ); } else { BEGIN( DocScan ); } } [^\r\n]+ { if (includeFileLength>0) { QCString pattern=yytext; if (firstLine) outDoc->startCodeFragment(); firstLine=FALSE; skipLine(*outDoc,pattern.stripWhiteSpace()); BEGIN( DocKeyEnd ); } else { BEGIN( DocScan ); } } [^\r\n]+ { if (includeFileLength>0) { QCString pattern=yytext; if (firstLine) outDoc->startCodeFragment(); firstLine=FALSE; showUntil(*outDoc,pattern.stripWhiteSpace()); BEGIN( DocKeyEnd ); } else { BEGIN( DocScan ); } } {CMD}"line"{BN}+ { BEGIN(DocLineKey); } {CMD}"until"{BN}+ { BEGIN(DocUntilKey); } {CMD}"skipline"{BN}+ { BEGIN(DocSkiplineKey); } \n <> { if (!firstLine) outDoc->endCodeFragment(); yyterminate(); } . { unput(*yytext); if (!firstLine) outDoc->endCodeFragment(); BEGIN( DocScan ); } "<"{MULTICOL}{ATTR}">" "" "<"{STRONG}{ATTR}">" { outDoc->startBold(); } "" { outDoc->endBold(); } "<"{CENTER}{ATTR}">" { outDoc->startCenter(); } "" { outDoc->endCenter(); } "<"{TABLE}{ATTR}">" { startTable(); } "" { endTable(); } "<"{CAPTION}{ATTR}">" { caption.resize(0); BEGIN( DocCaption ); } [^\n\<\>\/]+ { caption+=yytext; } \n { caption+=" "; } . { caption+=*yytext; } "" { if (curTable) { curTable->setCaption(caption); } BEGIN( DocScan ); } "<"{INPUT}{ATTR}">" "<"{SMALL}{ATTR}">" { outDoc->startSmall(); } "" { outDoc->endSmall(); } "<"{META}{ATTR}">" "<"{FORM}{ATTR}">" "" "<"{HEAD}{ATTR}">" "" "<"{BODY}{ATTR}">" "" "<"{BLOCKQUOTE}{ATTR}">" "" "<"{CODE}{ATTR}">" { outDoc->startTypewriter(); } "" { outDoc->endTypewriter(); } "<"{DFN}{ATTR}">" { outDoc->startTypewriter(); } "" { outDoc->endTypewriter(); } "<"{VAR}{ATTR}">" { outDoc->startEmphasis(); } "" { outDoc->endEmphasis(); } "<"{IMG}{ATTR}">" { /*storeOutputListState();*/ outDoc->pushGeneratorState(); outDoc->disableAllBut(OutputGenerator::Html); outDoc->writeString(yytext); /*restoreOutputListState();*/ outDoc->popGeneratorState(); } "<"{PRE}{ATTR}">" { if (insidePre) { warn(yyFileName,yyLineNr,"Warning in the documentation of this entity:\nNested
 found in the documentation of this entity!");
					  }
  					  outDoc->startPreFragment(); 
					  insidePre=TRUE;
					}
""	        { 
  					  outDoc->endPreFragment(); 
					  insidePre=FALSE;
					}
"<"{SUB}{ATTR}">"		{ outDoc->startSubscript(); }
""		{ outDoc->endSubscript(); }
"<"{SUP}{ATTR}">"		{ outDoc->startSuperscript(); }
""		{ outDoc->endSuperscript(); }
"<"{TR}{ATTR}">"		{ if (curTable) curTable->newRow(); }
""			
"<"{TD}{ATTR}">"		{ if (curTable) curTable->newElem(); }
""
"<"{OL}{ATTR}">"{BN}*		{ outDoc->startEnumList(); 
  					  currentListIndent.push("O");
					}
""{BN}*		{ 
					  if (currentListIndent.isEmpty())
					  {
					    warn(yyFileName,yyLineNr,
                                                 "Warning in the documentation of this entity:\nMore  tags than 
    tags in the documentation of this entity." ); } else if (*currentListIndent.top()!='O') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe
tag does not end a
    tag." ); } else { outDoc->endEnumList(); currentListIndent.pop(); } } "<"{UL}{ATTR}">"{BN}* { outDoc->startItemList(); currentListIndent.push("U"); } ""{BN}* { if (currentListIndent.isEmpty()) { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nMore tags than
      tags." ); } else if (*currentListIndent.top()!='U') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe
    tag does not end a
      tag." ); } else { outDoc->endItemList(); currentListIndent.pop(); } } "<"{LI}{ATTR}">" { if (/*currentListIndent.isEmpty() ||*/ //DvH: I removed this check because I use this in the manual (the
        is in a \htmlonly block!) !currentListIndent.isEmpty() && *currentListIndent.top()=='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe
      • tag can only be used inside a
          ...
        or a
          ...
        block." ); } else { outDoc->writeListItem(); } } "" "<"{TT}{ATTR}">" { outDoc->startTypewriter(); } "" { outDoc->endTypewriter(); } "<"{KBD}{ATTR}">" { outDoc->startTypewriter(); } "" { outDoc->endTypewriter(); } "<"{EM}{ATTR}">" { outDoc->startEmphasis(); } "" { outDoc->endEmphasis(); } "<"{HR}{ATTR}">" { outDoc->writeRuler(); } "<"{DL}{ATTR}">" { outDoc->startDescription(); currentListIndent.push("D"); } "" { if (currentListIndent.isEmpty()) { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nMore tags than
        tags in the documentation." ); } else if (*currentListIndent.top()!='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe
        tag does not end a
        tag in the documentation." ); } else { outDoc->endDescription(); currentListIndent.pop(); } } "<"{DT}{ATTR}">" { if (currentListIndent.isEmpty() || *currentListIndent.top()!='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe
        tag can only be used inside a
        ...
        block." ); } else { outDoc->startDescItem(); } } "" "<"{DD}{ATTR}">" { if (currentListIndent.isEmpty() || *currentListIndent.top()!='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe
        tag can only be used inside a
        ...
        block." ); } else { outDoc->endDescItem(); } } "" "<"{BR}{ATTR}">" { outDoc->lineBreak(); } "<"{I}{ATTR}">" { outDoc->startEmphasis(); } "" { outDoc->endEmphasis(); } "" { if (insideHtmlLink) { outDoc->endHtmlLink(); insideHtmlLink=FALSE; } } "<"{A}{BN}+ { BEGIN(DocHtmlLink); } "<"{BOLD}{ATTR}">" { outDoc->startBold(); } "" { outDoc->endBold(); } "<"{P}{ATTR}">" { if (inBlock()) endBlock(); outDoc->newParagraph(); } "" "<"{H1}{ATTR}">" { outDoc->startTitle(); } "" { outDoc->endTitle(); } "<"{H2}{ATTR}">" { outDoc->startSubsection(); } "" { outDoc->endSubsection(); } "<"{H3}{ATTR}">" { outDoc->startSubsubsection(); } "" { outDoc->endSubsubsection(); } {NAME}{BN}*"="{BN}*("\""?) { BEGIN(DocHtmlAnchor); } [a-z_A-Z0-9.\-\+\/]+ { outDoc->writeAnchor(0,yytext); } {HREF}{BN}*"="{BN}*("\""?) { htmlUrl.resize(0); htmlText.resize(0); BEGIN(DocHtmlHref); } {URLMASK} { htmlUrl=yytext; } ">" { outDoc->startHtmlLink(htmlUrl); insideHtmlLink=TRUE; BEGIN(DocScan); } ">" { BEGIN(DocScan); } {CMD}("\\"|"@"|"<"|">"|"&"|"$"|"#"|"%") { outDoc->docify(&yytext[1]); } "%"[a-z_A-Z][a-z_A-Z0-9:\-]* { outDoc->docify(yytext+1); } {FILEMASK} { outDoc->startEmphasis(); if (!insideHtmlLink) { generateFileRef(*outDoc,yytext); } else { outDoc->docify(yytext); } outDoc->endEmphasis(); BEGIN( DocScan ); } [a-z_A-Z][a-z_A-Z:0-9<>&\-=^%~!\[\]()|\*/]*"("[a-z_A-Z0-9,:\<\> \t\*\&]*")" { outDoc->startEmphasis(); if (!insideHtmlLink) { generateRef(*outDoc,className,yytext,inSeeBlock); } else { outDoc->docify(yytext); } outDoc->endEmphasis(); BEGIN( DocScan ); } {WORD} { outDoc->startEmphasis(); if (!insideHtmlLink) { linkifyText(TextGeneratorOLImpl(*outDoc),className,0,yytext,FALSE,TRUE); } else { outDoc->docify(yytext); } outDoc->endEmphasis(); BEGIN( DocScan ); } {FILEMASK} { outDoc->startBold(); if (!insideHtmlLink) { generateFileRef(*outDoc,yytext); } else { outDoc->docify(yytext); } outDoc->endBold(); BEGIN( DocScan ); } [a-z_A-Z][a-z_A-Z:0-9<>&\-=^%~!\[\]()|\*/]*"("[a-z_A-Z0-9,:\<\> \t\*\&]*")" { outDoc->startBold(); if (!insideHtmlLink) { generateRef(*outDoc,className,yytext,inSeeBlock); } else { outDoc->docify(yytext); } outDoc->endBold(); BEGIN( DocScan ); } {WORD} { outDoc->startBold(); if (!insideHtmlLink) { linkifyText(TextGeneratorOLImpl(*outDoc),className,0,yytext,FALSE,TRUE); } else { outDoc->docify(yytext); } outDoc->endBold(); BEGIN( DocScan ); } {FILEMASK} { outDoc->startTypewriter(); if (!insideHtmlLink) { generateFileRef(*outDoc,yytext); } else { outDoc->docify(yytext); } outDoc->endTypewriter(); BEGIN( DocScan ); } [a-z_A-Z][a-z_A-Z:0-9<>&\-=^%~!\[\]()!\*/]*"("[a-z_A-Z0-9,:\<\> \t\*\&]*")" { outDoc->startTypewriter(); if (!insideHtmlLink) { generateRef(*outDoc,className,yytext,inSeeBlock); } else { outDoc->docify(yytext); } outDoc->endTypewriter(); BEGIN( DocScan ); } {WORD} { outDoc->startTypewriter(); if (!insideHtmlLink) { linkifyText(TextGeneratorOLImpl(*outDoc),className,0,yytext,FALSE,TRUE); } else { outDoc->docify(yytext); } outDoc->endTypewriter(); BEGIN( DocScan ); } {FILE} { includeFile(*outDoc,stripQuotes(yytext),FALSE); BEGIN( DocScan ); } {FILE} { includeFile(*outDoc,stripQuotes(yytext),TRUE); BEGIN( DocScan ); } "//" { codeBlock += yytext; } "/*" { codeBlock += yytext; } \n { codeBlock += '\n'; } [^\/\\\<\n]* { codeBlock += yytext; } . { codeBlock += *yytext; } "//" { outDoc->docify(yytext); } "/*" { outDoc->docify(yytext); } "\n" { outDoc->writeChar('\n'); } ({B}*"\n"){2,}{B}*"*"*{B}*"-"("#")?{B}+ { // new paragraph & start of a list QCString text=yytext; int dashPos = text.findRev('-'); bool isEnumerated = text.at(dashPos+1)=='#'; if (insideArgumentList) { insideArgumentList=FALSE; outDoc->endItemList(); } else if (insideItemList) { forceEndItemList(); } else { outDoc->newParagraph(); } if (inBlock()) endBlock(); addListItemMarker(yytext,dashPos+1,isEnumerated); } ({B}*"\n"){2,}{B}* { // new paragraph bool ib = inBlock(); if (insideArgumentList) { insideArgumentList=FALSE; outDoc->endItemList(); if (ib) endBlock(); } else if (insideItemList) { forceEndItemList(); } else { if (insidePre) { outDoc->docify(yytext); } else if (!ib) { outDoc->newParagraph(); } if (ib && currentListIndent.top()=="P") { // inside paragraph block endBlock(); } } } {BN}+/\n { outDoc->writeChar(' '); } \n?{B}* { if (insidePre) { outDoc->docify(yytext); } else { outDoc->writeChar(' '); } } [a-z_A-Z0-9]+ { outDoc->docify(yytext); } . { outDoc->writeChar(*yytext); } {CMD}"copydoc"{B}+ { // found copydoc command BEGIN(DocCopyArg); } {CMD}"verbatim"/[^a-z_A-Z0-9] { // skip verbatim sections copyDocString+=yytext; BEGIN(DocCopySkipVerb); } [^@\\\n]+ { copyDocString+=yytext; } "\\\\"|"@@" { copyDocString+=yytext; /* skip escaped commands */ } [^@\\\n]+ { copyDocString+=yytext; } {CMD}"endverbatim" { copyDocString+=yytext; BEGIN(DocCopyFind); } \n { copyDocString+=yytext; } . { copyDocString+=yytext; } {LINKMASK} { //printf("found @copydoc with arg `%s'\n",yytext); QCString doc; Definition *def; if (findDocsForMemberOrCompound(yytext,&doc,&def)) { //printf("found docs `%s'\n",doc.data()); if (copyDocDefList.findRef(def)!=-1) { warn(yyFileName,yyLineNr,"Recursive @copydoc relation!"); } else { copyDocDefList.append(def); pushContext(); inputString = doc; inputPosition = 0; BEGIN(DocCopyFind); docYYlex(); popContext(); copyDocDefList.remove(def); BEGIN(DocCopyFind); } } else // reference not found! { warn(yyFileName,yyLineNr,"Argument `%s' of @copydoc command " "could not be resolved!",yytext); } BEGIN(DocCopyFind); } <*>\n { yyLineNr++ ; } <*>. %% //---------------------------------------------------------------------------- void scanString(const char *s) { pushContext(); inputString = s; inputPosition = 0; BEGIN( Text ); docYYlex(); popContext(); } void scanDoc(const char *s) { pushContext(); inputString = s; inputPosition = 0; BEGIN( DocScan ); docYYlex(); popContext(); } void internalParseDocument(const char *s) { if (s==0) return; pushContext(); inputString = s; inputPosition = 0; BEGIN( DocScan ); docYYlex(); popContext(); } //---------------------------------------------------------------------------- void parseDocument(OutputDocInterface &od,const QCString &docString) { //inParamBlock=inSeeBlock=inReturnBlock=FALSE; curTable = 0; depthIf = 0; outDoc = od.clone(); currentIncludeFile.resize(0); includeFileOffset=0; includeFileLength=0; currentListIndent.clear(); listIndentStack.clear(); if (!docString) return; linkRef = ""; linkText = ""; inputString = docString; inputPosition = 0; docYYrestart( docYYin ); BEGIN( DocScan ); insideArgumentList = FALSE; insideVerbatim = FALSE; docYYlex(); if (insideArgumentList) { insideArgumentList=FALSE; outDoc->endItemList(); } if (insideItemList) { forceEndItemList(); } if (inBlock()) endBlock(); if (!currentListIndent.isEmpty()) { warn(yyFileName,yyLineNr,"Warning: Documentation ended in the middle " "of a list!"); warn_cont("Missing: "); while (!currentListIndent.isEmpty()) { char c; switch((c=*currentListIndent.pop())) { case 'O': warn_cont("
"); break; case 'U': warn_cont(""); break; case 'D': warn_cont(""); break; } } warn_cont("\n"); } if (depthIf!=0) { warn(yyFileName,yyLineNr,"Warning: Documentation block contains \\if " "without matching \\endif: nesting level is %d",depthIf); } if (!tableStack.isEmpty()) { forceEndTable(); } if (insideVerbatim) { warn(yyFileName,yyLineNr, "Warning: file ended inside a \\verbatim block!" ); } od.append(outDoc); delete outDoc; outDoc=0; return; } //---------------------------------------------------------------------------- // in this pass all @copydoc commands are resolved. void resolveCopyDocCommands(const char *scope,QCString &docString) { copyDocString.resize(0); copyDocScope = scope; inputString = docString; inputPosition = 0; docYYrestart( docYYin ); BEGIN( DocCopyFind ); docYYlex(); docString = copyDocString; } //---------------------------------------------------------------------------- void parseDoc(OutputDocInterface &od,const char *fileName,int startLine, const char *clName,MemberDef *md,const QCString &docStr) { strcpy(yyFileName,fileName); yyLineNr = startLine; QCString docString=docStr; resolveCopyDocCommands(clName,docString); yyLineNr = startLine; //printf("parseDoc(file=`%s',line=%d)\n",fileName,startLine); initParser(); initParseCodeContext(); exampleDoc=FALSE; // do not cross reference with member docs className=clName; memberDef = md; hasParamCommand = FALSE; paramsFound.setAutoDelete(FALSE); paramsFound.clear(); parseDocument(od,docString); if (md && hasParamCommand && Config_getBool("WARN_IF_UNDOCUMENTED")) { ArgumentList *al=memberDef->isDocsForDefinition() ? memberDef->argumentList() : memberDef->declArgumentList(); if (al) { ArgumentListIterator ali(*al); Argument *a; bool found=FALSE; for (ali.toFirst();(a=ali.current());++ali) { QCString argName = memberDef->isDefine() ? a->type : a->name; if (argName.right(3)=="...") argName=argName.left(argName.length()-3); if (!argName.isEmpty() && paramsFound.find(argName)==0) { found = TRUE; break; } } if (found) { QCString scope=memberDef->getScopeString(); if (!scope.isEmpty()) scope+="::"; else scope=""; warn(memberDef->docFile(),memberDef->docLine(), "Warning: The following parameters of " "%s%s%s are not documented:", scope.data(),memberDef->name().data(), argListToString(al).data()); for (ali.toFirst();(a=ali.current());++ali) { QCString argName = memberDef->isDefine() ? a->type : a->name; if (!argName.isEmpty() && paramsFound.find(argName)==0) { warn_cont( " parameter %s\n",argName.data()); } } } } } } //---------------------------------------------------------------------------- void parseText(OutputDocInterface &od,const QCString &txtString) { if (txtString.isEmpty()) return; inputString = txtString; outDoc = od.clone(); inputPosition = 0; docYYrestart( docYYin ); BEGIN( Text ); docYYlex(); od.append(outDoc); delete outDoc; outDoc=0; return; } //---------------------------------------------------------------------------- void parseExample(OutputDocInterface &od,const QCString &docString, const char *fileName) { initParser(); initParseCodeContext(); exampleDoc=TRUE; // cross reference with member docs exampleName=fileName; strcpy(yyFileName,fileName); parseDocument(od,docString); } //---------------------------------------------------------------------------- extern "C" { // some bogus code to keep the compiler happy void docYYdummy() { yy_flex_realloc(0,0); } }