/***************************************************************************** * * Copyright (C) 1997-2015 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. * */ %option never-interactive %option prefix="commentscanYY" %{ /* * includes */ #include #include #include #include #include #include #include #include #include #include "scanner.h" #include "entry.h" #include "doxygen.h" #include "message.h" #include "config.h" #include "util.h" #include "index.h" #include "defargs.h" #include "language.h" #include "outputlist.h" #include "membergroup.h" #include "reflist.h" #include "debug.h" #include "parserintf.h" #include "cite.h" #include "markdown.h" #include "condparser.h" #include "formula.h" #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 // forward declarations static bool handleBrief(const QCString &, const QCString &); static bool handleFn(const QCString &, const QCString &); static bool handleDef(const QCString &, const QCString &); static bool handleOverload(const QCString &, const QCString &); static bool handleEnum(const QCString &, const QCString &); static bool handleDefGroup(const QCString &, const QCString &); static bool handleAddToGroup(const QCString &, const QCString &); static bool handleWeakGroup(const QCString &, const QCString &); static bool handleNamespace(const QCString &, const QCString &); static bool handlePackage(const QCString &, const QCString &); static bool handleClass(const QCString &, const QCString &); static bool handleHeaderFile(const QCString &, const QCString &); static bool handleProtocol(const QCString &, const QCString &); static bool handleCategory(const QCString &, const QCString &); static bool handleUnion(const QCString &, const QCString &); static bool handleStruct(const QCString &, const QCString &); static bool handleInterface(const QCString &, const QCString &); static bool handleIdlException(const QCString &, const QCString &); static bool handlePage(const QCString &, const QCString &); static bool handleMainpage(const QCString &, const QCString &); static bool handleFile(const QCString &, const QCString &); static bool handleDir(const QCString &, const QCString &); static bool handleExample(const QCString &, const QCString &); static bool handleDetails(const QCString &, const QCString &); static bool handleName(const QCString &, const QCString &); static bool handleTodo(const QCString &, const QCString &); static bool handleTest(const QCString &, const QCString &); static bool handleBug(const QCString &, const QCString &); static bool handleSubpage(const QCString &s, const QCString &); static bool handleDeprecated(const QCString &, const QCString &); static bool handleXRefItem(const QCString &, const QCString &); static bool handleRelated(const QCString &, const QCString &); static bool handleRelatedAlso(const QCString &, const QCString &); static bool handleMemberOf(const QCString &, const QCString &); static bool handleRefItem(const QCString &, const QCString &); static bool handleSection(const QCString &, const QCString &); static bool handleAnchor(const QCString &, const QCString &); static bool handleCite(const QCString &, const QCString &); static bool handleFormatBlock(const QCString &, const QCString &); static bool handleAddIndex(const QCString &, const QCString &); static bool handleIf(const QCString &, const QCString &); static bool handleIfNot(const QCString &, const QCString &); static bool handleElseIf(const QCString &, const QCString &); static bool handleElse(const QCString &, const QCString &); static bool handleEndIf(const QCString &, const QCString &); static bool handleIngroup(const QCString &, const QCString &); static bool handleNoSubGrouping(const QCString &, const QCString &); static bool handleShowInitializer(const QCString &, const QCString &); static bool handleHideInitializer(const QCString &, const QCString &); static bool handleCallgraph(const QCString &, const QCString &); static bool handleHideCallgraph(const QCString &, const QCString &); static bool handleCallergraph(const QCString &, const QCString &); static bool handleHideCallergraph(const QCString &, const QCString &); static bool handleInternal(const QCString &, const QCString &); static bool handleLineBr(const QCString &, const QCString &); static bool handleStatic(const QCString &, const QCString &); static bool handlePure(const QCString &, const QCString &); static bool handlePrivate(const QCString &, const QCString &); static bool handlePrivateSection(const QCString &, const QCString &); static bool handleProtected(const QCString &, const QCString &); static bool handleProtectedSection(const QCString &, const QCString &); static bool handlePublic(const QCString &s, const QCString &); static bool handlePublicSection(const QCString &s, const QCString &); static bool handleToc(const QCString &s, const QCString &); static bool handleInherit(const QCString &, const QCString &); static bool handleExtends(const QCString &, const QCString &); static bool handleCopyDoc(const QCString &, const QCString &); static bool handleCopyBrief(const QCString &, const QCString &); static bool handleCopyDetails(const QCString &, const QCString &); static bool handleParBlock(const QCString &, const QCString &); static bool handleEndParBlock(const QCString &, const QCString &); static bool handleParam(const QCString &, const QCString &); static bool handleRetval(const QCString &, const QCString &); typedef bool (*DocCmdFunc)(const QCString &name, const QCString &opt); struct DocCmdMap { const char *cmdName; DocCmdFunc handler; bool endsBrief; }; // map of command to handler function static DocCmdMap docCmdMap[] = { // command name handler function ends brief description { "brief", &handleBrief, FALSE }, { "short", &handleBrief, FALSE }, { "fn", &handleFn, FALSE }, { "var", &handleFn, FALSE }, { "typedef", &handleFn, FALSE }, { "property", &handleFn, FALSE }, { "def", &handleDef, FALSE }, { "overload", &handleOverload, FALSE }, { "enum", &handleEnum, FALSE }, { "defgroup", &handleDefGroup, FALSE }, { "addtogroup", &handleAddToGroup, FALSE }, { "weakgroup", &handleWeakGroup, FALSE }, { "namespace", &handleNamespace, FALSE }, { "package", &handlePackage, FALSE }, { "class", &handleClass, FALSE }, { "headerfile", &handleHeaderFile, FALSE }, { "protocol", &handleProtocol, FALSE }, { "category", &handleCategory, FALSE }, { "union", &handleUnion, FALSE }, { "struct", &handleStruct, FALSE }, { "interface", &handleInterface, FALSE }, { "idlexcept", &handleIdlException, FALSE }, { "page", &handlePage, FALSE }, { "mainpage", &handleMainpage, FALSE }, { "file", &handleFile, FALSE }, { "dir", &handleDir, FALSE }, { "example", &handleExample, FALSE }, { "details", &handleDetails, TRUE }, { "name", &handleName, FALSE }, { "todo", &handleTodo, FALSE }, // end brief will be done differently { "test", &handleTest, FALSE }, // end brief will be done differently { "bug", &handleBug, FALSE }, // end brief will be done differently { "deprecated", &handleDeprecated, FALSE }, // end brief will be done differently { "xrefitem", &handleXRefItem, FALSE }, // end brief will be done differently { "related", &handleRelated, TRUE }, { "relates", &handleRelated, TRUE }, { "relatedalso", &handleRelatedAlso, TRUE }, { "relatesalso", &handleRelatedAlso, TRUE }, { "parblock", &handleParBlock, TRUE }, { "endparblock", &handleEndParBlock, TRUE }, { "refitem", &handleRefItem, TRUE }, { "cite", &handleCite, FALSE }, { "subpage", &handleSubpage, TRUE }, { "section", &handleSection, TRUE }, { "subsection", &handleSection, TRUE }, { "subsubsection", &handleSection, TRUE }, { "paragraph", &handleSection, TRUE }, { "anchor", &handleAnchor, TRUE }, { "verbatim", &handleFormatBlock, TRUE }, { "latexonly", &handleFormatBlock, FALSE }, { "htmlonly", &handleFormatBlock, FALSE }, { "xmlonly", &handleFormatBlock, FALSE }, { "docbookonly", &handleFormatBlock, FALSE }, { "rtfonly", &handleFormatBlock, FALSE }, { "manonly", &handleFormatBlock, FALSE }, { "dot", &handleFormatBlock, TRUE }, { "msc", &handleFormatBlock, TRUE }, { "startuml", &handleFormatBlock, TRUE }, { "code", &handleFormatBlock, TRUE }, { "addindex", &handleAddIndex, FALSE }, { "if", &handleIf, FALSE }, { "ifnot", &handleIfNot, FALSE }, { "elseif", &handleElseIf, FALSE }, { "else", &handleElse, FALSE }, { "endif", &handleEndIf, FALSE }, { "ingroup", &handleIngroup, FALSE }, { "nosubgrouping", &handleNoSubGrouping, FALSE }, { "showinitializer", &handleShowInitializer, FALSE }, { "hideinitializer", &handleHideInitializer, FALSE }, { "callgraph", &handleCallgraph, FALSE }, { "hidecallgraph", &handleHideCallgraph, FALSE }, { "callergraph", &handleCallergraph, FALSE }, { "hidecallergraph", &handleHideCallergraph, FALSE }, { "internal", &handleInternal, TRUE }, { "_linebr", &handleLineBr, FALSE }, { "static", &handleStatic, FALSE }, { "pure", &handlePure, FALSE }, { "private", &handlePrivate, FALSE }, { "privatesection", &handlePrivateSection, FALSE }, { "protected", &handleProtected, FALSE }, { "protectedsection",&handleProtectedSection, FALSE }, { "public", &handlePublic, FALSE }, { "publicsection", &handlePublicSection, FALSE }, { "tableofcontents", &handleToc, FALSE }, { "inherit", &handleInherit, TRUE }, { "extends", &handleExtends, TRUE }, { "implements", &handleExtends, TRUE }, { "memberof", &handleMemberOf, TRUE }, { "arg", 0, TRUE }, { "attention", 0, TRUE }, { "author", 0, TRUE }, { "authors", 0, TRUE }, { "copydoc", &handleCopyDoc, TRUE }, { "copybrief", &handleCopyBrief, FALSE }, { "copydetails", &handleCopyDetails, TRUE }, { "copyright", 0, TRUE }, { "date", 0, TRUE }, { "dotfile", 0, TRUE }, { "htmlinclude", 0, FALSE }, { "image", 0, TRUE }, { "include", 0, TRUE }, { "includelineno", 0, TRUE }, { "invariant", 0, TRUE }, { "latexinclude", 0, FALSE }, { "li", 0, TRUE }, { "line", 0, TRUE }, { "note", 0, TRUE }, { "par", 0, TRUE }, { "param", &handleParam, TRUE }, { "tparam", 0, TRUE }, { "post", 0, TRUE }, { "pre", 0, TRUE }, { "remark", 0, TRUE }, { "remarks", 0, TRUE }, { "result", 0, TRUE }, { "return", 0, TRUE }, { "returns", 0, TRUE }, { "exception", 0, TRUE }, { "retval", &handleRetval, TRUE }, { "sa", 0, TRUE }, { "see", 0, TRUE }, { "since", 0, TRUE }, { "throw", 0, TRUE }, { "throws", 0, TRUE }, { "until", 0, TRUE }, { "verbinclude", 0, FALSE }, { "version", 0, TRUE }, { "warning", 0, TRUE }, { 0, 0, FALSE } }; /** @brief Command mapper. * * Maps a command name (as found in a comment block) onto a * specific handler function. */ class DocCmdMapper { public: struct Cmd { DocCmdFunc func; bool endsBrief; }; /** maps a command name to a handler function */ static Cmd *map(const char *name) { return instance()->find(name); } /** release the singleton */ static void freeInstance() { delete s_instance; s_instance=0; } private: static DocCmdMapper *instance() { if (s_instance==0) s_instance = new DocCmdMapper; return s_instance; } DocCmdMapper() : m_map(113) { m_map.setAutoDelete(TRUE); DocCmdMap *p = docCmdMap; while (p->cmdName) { if (m_map.find(p->cmdName)!=0) { err("DocCmdMapper: command %s already added\n",p->cmdName); exit(1); } Cmd *cmd = new Cmd; cmd->func = p->handler; cmd->endsBrief = p->endsBrief; m_map.insert(p->cmdName,cmd); p++; } } Cmd *find(const char *name) { return m_map.find(name); } QDict m_map; static DocCmdMapper *s_instance; }; DocCmdMapper *DocCmdMapper::s_instance=0; bool inInternalDocs = FALSE; #define YY_NEVER_INTERACTIVE 1 enum XRefKind { XRef_Item, XRef_Todo, XRef_Test, XRef_Bug, XRef_Deprecated, XRef_None }; enum OutputContext { OutputDoc, OutputBrief, OutputXRef, OutputInbody }; enum GuardType { Guard_If, Guard_IfNot, Guard_Skip }; class GuardedSection { public: GuardedSection(bool enabled,bool parentVisible) : m_enabled(enabled),m_parentVisible(parentVisible) {} bool isEnabled() const { return m_enabled; } bool parentVisible() const { return m_parentVisible; } private: bool m_enabled; bool m_parentVisible; }; void openGroup(Entry *e,const char *file,int line); void closeGroup(Entry *e,const char *file,int line,bool foundInline=FALSE); void initGroupInfo(Entry *e); static void groupAddDocs(Entry *e); /* ----------------------------------------------------------------- * * statics */ static ParserInterface *langParser; // the language parser that is calling us static QCString inputString; // input string static int inputPosition; // read pointer static QCString yyFileName; // file name that is read from static int yyLineNr; // line number in the input static bool inBody; // was the comment found inside the body of a function? static OutputContext inContext; // are we inside the brief, details or xref part static bool briefEndsAtDot; // does the brief description stop at a dot? static QCString formulaText; // Running text of a formula static QCString formulaEnv; // environment name static int formulaNewLines; // amount of new lines in the formula static QCString *pOutputString; // pointer to string to which the output is appended. static QCString outputXRef; // temp argument of todo/test/../xrefitem commands static QCString blockName; // preformatted block name (e.g. verbatim, latexonly,...) static XRefKind xrefKind; // kind of cross-reference command static XRefKind newXRefKind; // static GuardType guardType; // kind of guard for conditional section static bool enabledSectionFound; static QCString functionProto; // function prototype static QStack guards; // tracks nested conditional sections (if,ifnot,..) static Entry* current = 0 ; // working entry //static Entry* current_root = 0 ; // parent of working entry //static Entry* previous = 0 ; // TODO: remove need for this static bool needNewEntry; static QCString g_sectionLabel; static QCString g_sectionTitle; static int g_sectionLevel; static QCString xrefItemKey; static QCString newXRefItemKey; static QCString xrefItemTitle; static QCString xrefListTitle; static Protection protection; static bool xrefAppendFlag; static bool inGroupParamFound; static int braceCount; static bool insidePre; static bool parseMore; static int g_condCount; static int g_commentCount; static QCString g_spaceBeforeCmd; static QCString g_spaceBeforeIf; static QCString g_copyDocArg; static QCString g_guardExpr; static int g_roundCount; static bool g_insideParBlock; //----------------------------------------------------------------------------- static QStack g_autoGroupStack; static int g_memberGroupId = DOX_NOGROUP; static QCString g_memberGroupHeader; static QCString g_memberGroupDocs; static QCString g_memberGroupRelates; static QCString g_compoundName; //----------------------------------------------------------------------------- static void initParser() { g_sectionLabel.resize(0); g_sectionTitle.resize(0); g_memberGroupHeader.resize(0); g_insideParBlock = FALSE; } //----------------------------------------------------------------------------- static bool getDocSectionName(int s) { switch(s) { case Entry::CLASSDOC_SEC: case Entry::STRUCTDOC_SEC: case Entry::UNIONDOC_SEC: case Entry::EXCEPTIONDOC_SEC: case Entry::NAMESPACEDOC_SEC: case Entry::PROTOCOLDOC_SEC: case Entry::CATEGORYDOC_SEC: case Entry::ENUMDOC_SEC: case Entry::PAGEDOC_SEC: case Entry::VARIABLEDOC_SEC: case Entry::MEMBERDOC_SEC: case Entry::OVERLOADDOC_SEC: case Entry::FILEDOC_SEC: case Entry::DEFINEDOC_SEC: case Entry::GROUPDOC_SEC: case Entry::MAINPAGEDOC_SEC: case Entry::PACKAGEDOC_SEC: case Entry::DIRDOC_SEC: case Entry::EXAMPLE_SEC: case Entry::MEMBERGRP_SEC: return TRUE; default: return FALSE; } } //----------------------------------------------------------------------------- static bool makeStructuralIndicator(Entry::Sections s) { //printf("current->section=%x\n",current->section); if (getDocSectionName(current->section)) { return TRUE; } else { needNewEntry = TRUE; current->section = s; current->fileName = yyFileName; current->startLine = yyLineNr; return FALSE; } } static void lineCount() { for( const char* c = yytext ; *c ; ++c ) yyLineNr += (*c == '\n') ; } 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 void addXRefItem(const char *listName,const char *itemTitle, const char *listTitle,bool append) { Entry *docEntry = current; // inBody && previous ? previous : current; if (listName==0) return; //printf("addXRefItem(%s,%s,%s,%d)\n",listName,itemTitle,listTitle,append); ListItemInfo *lii=0; RefList *refList = Doxygen::xrefLists->find(listName); if (refList==0) // new list { refList = new RefList(listName,listTitle,itemTitle); Doxygen::xrefLists->insert(listName,refList); //printf("new list!\n"); } if (docEntry->sli) { QListIterator slii(*docEntry->sli); for (slii.toLast();(lii=slii.current());--slii) { if (qstrcmp(lii->type,listName)==0) { //printf("found %s lii->type=%s\n",listName,lii->type); break; } } } if (lii && append) // already found item of same type just before this one { //printf("listName=%s item id = %d existing\n",listName,lii->itemId); RefItem *item = refList->getRefItem(lii->itemId); ASSERT(item!=0); item->text += "

"; item->text += outputXRef; //printf("%s: text +=%s\n",listName,item->text.data()); } else // new item { int itemId = refList->addRefItem(); //printf("listName=%s item id = %d new current=%p\n",listName,itemId,current); // if we have already an item from the same list type (e.g. a second @todo) // in the same Entry (i.e. lii!=0) then we reuse its link anchor. char anchorLabel[1024]; //sprintf(anchorLabel,"_%s%06d",listName,lii ? lii->itemId : itemId); sprintf(anchorLabel,"_%s%06d",listName,itemId); RefItem *item = refList->getRefItem(itemId); ASSERT(item!=0); item->text = outputXRef; item->listAnchor = anchorLabel; docEntry->addSpecialListItem(listName,itemId); QCString cmdString; cmdString.sprintf(" \\xrefitem %s %d.",listName,itemId); if (inBody) { docEntry->inbodyDocs += cmdString; } else { docEntry->doc += cmdString; } SectionInfo *si = Doxygen::sectionDict->find(anchorLabel); if (si) { if (si->lineNr != -1) { warn(listName,yyLineNr,"multiple use of section label '%s', (first occurrence: %s, line %d)",anchorLabel,si->fileName.data(),si->lineNr); } else { warn(listName,yyLineNr,"multiple use of section label '%s', (first occurrence: %s)",anchorLabel,si->fileName.data()); } } else { si=new SectionInfo(listName,yyLineNr,anchorLabel, g_sectionTitle,SectionInfo::Anchor, g_sectionLevel); Doxygen::sectionDict->append(anchorLabel,si); docEntry->anchors->append(si); } } outputXRef.resize(0); } //----------------------------------------------------------------------------- // Adds a formula text to the list/dictionary of formulas if it was // not already added. Returns the label of the formula. static QCString addFormula() { QCString formLabel; QCString fText=formulaText.simplifyWhiteSpace(); Formula *f=0; if ((f=Doxygen::formulaDict->find(fText))==0) { f = new Formula(fText); Doxygen::formulaList->append(f); Doxygen::formulaDict->insert(fText,f); formLabel.sprintf("\\form#%d",f->getId()); Doxygen::formulaNameDict->insert(formLabel,f); } else { formLabel.sprintf("\\form#%d",f->getId()); } int i; for (i=0;i=0 && level<5) return (SectionInfo::SectionType)level; return SectionInfo::Anchor; } static void addSection() { SectionInfo *si = Doxygen::sectionDict->find(g_sectionLabel); if (si) { if (si->lineNr != -1) { warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s, line %d)",g_sectionLabel.data(),si->fileName.data(),si->lineNr); } else { warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s)",g_sectionLabel.data(),si->fileName.data()); } } else { // create a new section element g_sectionTitle+=yytext; g_sectionTitle=g_sectionTitle.stripWhiteSpace(); si = new SectionInfo(yyFileName,yyLineNr,g_sectionLabel, g_sectionTitle,sectionLevelToType(g_sectionLevel),g_sectionLevel); // add section to this entry current->anchors->append(si); // add section to the global dictionary Doxygen::sectionDict->append(g_sectionLabel,si); } } //----------------------------------------------------------------------------- static void addCite() { Doxygen::citeDict->insert(yytext); } //----------------------------------------------------------------------------- // strip trailing whitespace (excluding newlines) from string s static void stripTrailingWhiteSpace(QCString &s) { uint len = s.length(); int i = (int)len-1; char c; while (i>=0 && ((c = s.at(i))==' ' || c=='\t' || c=='\r')) i--; if (i!=(int)len-1) { s.resize(i+2); // string up to and including char at pos i and \0 terminator } } // selects the output to write to static inline void setOutput(OutputContext ctx) { bool xrefAppendToPrev = xrefAppendFlag; // determine append flag for the next item (i.e. the end of this item) xrefAppendFlag = !inBody && inContext==OutputXRef && ctx==OutputXRef && // two consecutive xref items newXRefKind==xrefKind && // of the same kind (xrefKind!=XRef_Item || newXRefItemKey==xrefItemKey); // with the same key if \xrefitem //printf("%d && %d && %d && (%d || %d)\n", // inContext==OutputXRef, // ctx==OutputXRef, // newXRefKind==xrefKind, // xrefKind!=XRef_Item, // newXRefItemKey==xrefItemKey); //printf("refKind=%d newXRefKind=%d xrefAppendToPrev=%d xrefAppendFlag=%d\n", // xrefKind,newXRefKind,xrefAppendToPrev,xrefAppendFlag); //printf("setOutput(inContext=%d ctx=%d)\n",inContext,ctx); if (inContext==OutputXRef) // end of XRef section => add the item { // See if we can append this new xref item to the previous one. // We know this at the start of the next item of the same // type and need to remember this until the end of that item. switch(xrefKind) { case XRef_Todo: addXRefItem("todo", theTranslator->trTodo(), theTranslator->trTodoList(), xrefAppendToPrev ); break; case XRef_Test: addXRefItem("test", theTranslator->trTest(), theTranslator->trTestList(), xrefAppendToPrev ); break; case XRef_Bug: addXRefItem("bug", theTranslator->trBug(), theTranslator->trBugList(), xrefAppendToPrev ); break; case XRef_Deprecated: addXRefItem("deprecated", theTranslator->trDeprecated(), theTranslator->trDeprecatedList(), xrefAppendToPrev ); break; case XRef_Item: // user defined list addXRefItem(xrefItemKey, xrefItemTitle, xrefListTitle, xrefAppendToPrev ); break; case XRef_None: ASSERT(0); break; } } xrefItemKey = newXRefItemKey; int oldContext = inContext; inContext = ctx; if (inContext!=OutputXRef && inBody) inContext=OutputInbody; switch(inContext) { case OutputDoc: if (oldContext!=inContext) { stripTrailingWhiteSpace(current->doc); if (current->docFile.isEmpty()) { current->docFile = yyFileName; current->docLine = yyLineNr; } } pOutputString = ¤t->doc; break; case OutputBrief: if (oldContext!=inContext) { if (current->briefFile.isEmpty()) { current->briefFile = yyFileName; current->briefLine = yyLineNr; } } if (current->brief.stripWhiteSpace().isEmpty()) // we only want one brief // description even if multiple // are given... { pOutputString = ¤t->brief; } else { pOutputString = ¤t->doc; inContext = OutputDoc; // need to switch to detailed docs, see bug 631380 } break; case OutputXRef: pOutputString = &outputXRef; // first item found, so can't append to previous //xrefAppendFlag = FALSE; break; case OutputInbody: pOutputString = ¤t->inbodyDocs; break; } } static void addAnchor(const char *anchor) { SectionInfo *si = Doxygen::sectionDict->find(anchor); if (si) { if (si->lineNr != -1) { warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s, line %d)",anchor,si->fileName.data(),si->lineNr); } else { warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s)",anchor,si->fileName.data()); } } else { si = new SectionInfo(yyFileName,yyLineNr,anchor,0,SectionInfo::Anchor,0); Doxygen::sectionDict->append(anchor,si); current->anchors->append(si); } } // add a string to the output static inline void addOutput(const char *s) { //printf("addOutput(%s)\n",s); *pOutputString+=s; } // add a character to the output static inline void addOutput(char c) { *pOutputString+=c; } static void endBrief(bool addToOutput=TRUE) { if (!current->brief.stripWhiteSpace().isEmpty()) { // only go to the detailed description if we have // found some brief description and not just whitespace briefEndsAtDot=FALSE; setOutput(OutputDoc); if (addToOutput) addOutput(yytext); } } static void handleGuard(const QCString &expr); /* ----------------------------------------------------------------- */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); static int prevPosition=0; static int yyread(char *buf,int max_size) { prevPosition=inputPosition; int c=0; while( c < max_size && inputString[inputPosition] ) { *buf = inputString[inputPosition++] ; //printf("%d (%c)\n",*buf,*buf); c++; buf++; } return c; } %} /* start command character */ CMD ("\\"|"@") DCMD1 ("arg"|"attention"|"author"|"cite"|"code") DCMD2 ("date"|"dot"|"msc"|"dotfile"|"example"|"startuml") DCMD3 ("htmlinclude"|"htmlonly"|"image"|"include") DCMD4 ("includelineno"|"internal"|"invariant") DCMD5 ("latexinclude"|"latexonly"|"li"|"line"|"manonly"|"name") DCMD6 ("note"|"par"|"paragraph"|"param"|"post") DCMD7 ("pre"|"remarks"|(("relate"[sd])("also")?)) DCMD8 ("remarks"|("return"[s]?)|"retval"|"sa"|"section") DCMD9 ("see"|"since"|"subsection"|"subsubsection") DCMD10 ("throw"|"until"|"verbatim") DCMD11 ("verbinclude"|"version"|"warning") DETAILEDCMD {CMD}({DCMD1}|{DCMD2}|{DCMD3}|{DCMD4}|{DCMD5}|{DCMD6}|{DCMD7}|{DCMD8}|{DCMD9}|{DCMD10}|{DCMD11}) XREFCMD {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem") PRE [pP][rR][eE] TABLE [tT][aA][bB][lL][eE] P [pP] UL [uU][lL] OL [oO][lL] DL [dD][lL] IMG [iI][mM][gG] HR [hH][rR] PARA [pP][aA][rR][aA] CODE [cC][oO][dD][eE] CAPTION [cC][aA][pP][tT][iI][oO][nN] DETAILEDHTML {PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA} DETAILEDHTMLOPT {CODE} BN [ \t\n\r] BL [ \t\r]*"\n" B [ \t] BS ^(({B}*"//")?)(({B}*"*"+)?){B}* ATTR ({B}+[^>\n]*)? DOCNL "\n"|"\\_linebr" LC "\\"{B}*"\n" NW [^a-z_A-Z0-9] FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+@&#] FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+@&#] FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"") ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]* CITESCHAR [a-z_A-Z0-9\x80-\xFF] CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/]* CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)* SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID}) TMPLSPEC "<"{BN}*[^>]+{BN}*">" MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ RCSTAG "$"{ID}":"[^\n$]+"$" %option noyywrap /* comment parsing states. */ %x Comment %x PageDocArg1 %x PageDocArg2 %x RelatesParam1 %x ClassDocArg1 %x ClassDocArg2 %x ClassDocArg3 %x CategoryDocArg1 %x XRefItemParam1 %x XRefItemParam2 %x XRefItemParam3 %x FileDocArg1 %x ParamArg1 %x EnumDocArg1 %x NameSpaceDocArg1 %x PackageDocArg1 %x GroupDocArg1 %x GroupDocArg2 %x SectionLabel %x SectionTitle %x SubpageLabel %x SubpageTitle %x FormatBlock %x LineParam %x GuardParam %x GuardParamEnd %x SkipGuardedSection %x SkipInternal %x NameParam %x InGroupParam %x FnParam %x OverloadParam %x InheritParam %x ExtendsParam %x ReadFormulaShort %x ReadFormulaLong %x AnchorLabel %x HtmlComment %x SkipLang %x CiteLabel %x CopyDoc %x GuardExpr %x CdataSection %% /* What can happen in while parsing a comment block: * commands (e.g. @page, or \page) * escaped commands (e.g. @@page or \\page). * formulas (e.g. \f$ \f[ \f{..) * directories (e.g. \doxygen\src\) * autolist end. (e.g. a dot on an otherwise empty line) * newlines. * end of brief description due to blank line. * end of brief description due to some command (@command, or ). * words and whitespace and other characters (#,?!, etc). * grouping commands (e.g. @{ and @}) * language switch (e.g. \~english or \~). * mail address (e.g. dimitri@stack.nl). * quoted text, such as "foo@bar" * XML commands,

*/ {CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command addOutput(yytext); } {CMD}{CMD}"~"[a-z_A-Z]* { // escaped command addOutput(yytext); } {MAILADDR} { // mail address addOutput(yytext); } "\""[^"\n]*"\"" { // quoted text addOutput(yytext); } ("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!) addOutput(yytext); } "<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description setOutput(OutputDoc); // continue with the same input REJECT; } "<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML command that ends a brief description if (current->lang==SrcLangExt_CSharp) { setOutput(OutputDoc); } // continue with the same input REJECT; } "" { // start of a .NET XML style brief description setOutput(OutputBrief); addOutput(yytext); } "" { // start of a .NET XML style detailed description setOutput(OutputDoc); addOutput(yytext); } "" { // start of a .NET XML style detailed description setOutput(OutputBrief); addOutput(yytext); setOutput(OutputDoc); } "" { // end of a brief or detailed description setOutput(OutputDoc); addOutput(yytext); } "<"{CAPTION}{ATTR}">" { QCString tag=yytext; int s=tag.find("id="); if (s!=-1) // command has id attribute { char c=tag[s+3]; if (c=='\'' || c=='"') // valid start { int e=tag.find(c,s+4); if (e!=-1) // found matching end { QCString id=tag.mid(s+4,e-s-4); // extract id addAnchor(id); } } } addOutput(yytext); } "<"{PRE}{ATTR}">" { insidePre=TRUE; addOutput(yytext); } "" { insidePre=FALSE; addOutput(yytext); } {RCSTAG} { // RCS tag which end a brief description setOutput(OutputDoc); REJECT; } "