From e55c2248b46d5580e5b184d2ff9c773f333308b2 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Mon, 30 Dec 2019 19:34:15 +0100 Subject: Make commentscan.l reentrant --- src/commentscan.h | 119 +- src/commentscan.l | 3215 ++++++++++++++++++++++++++------------------------ src/fortranscanner.l | 8 +- src/markdown.cpp | 47 +- src/markdown.h | 18 +- src/pre.h | 4 +- src/pre.l | 4 +- src/pyscanner.l | 6 +- src/scanner.l | 8 +- src/tclscanner.l | 26 +- src/vhdljjparser.cpp | 6 +- 11 files changed, 1822 insertions(+), 1639 deletions(-) diff --git a/src/commentscan.h b/src/commentscan.h index f471890..a0ad6d9 100644 --- a/src/commentscan.h +++ b/src/commentscan.h @@ -16,74 +16,71 @@ #ifndef COMMENTSCAN_H #define COMMENTSCAN_H +#include #include "types.h" class Entry; class OutlineParserInterface; /** @file - * @brief Interface for the comment block parser */ + * @brief Interface for the comment block scanner */ -/** Invokes the comment block parser with the request to preprocess a - * single comment block. - * @param[in] comment A string representing the actual comment block. - * Note that leading *'s are already stripped from the comment block. - * @param[in] fileName The name of the file in which the comment is found. - * Mainly used for producing warnings. - * @param[in] lineNr The line number at which the comment block was found. - * @returns The prepocessed comment block - */ -QCString preprocessCommentBlock(const QCString &comment, - const QCString &fileName, - int lineNr); - -/** Invokes the comment block parser with the request to parse a - * single comment block. - * @param[in] parser The language parse that invoked this function. - * The comment block parse may invoke - * ParserInterface::parsePrototype() in order to parse - * the argument of a @@fn command. - * @param[in] curEntry The Entry to which the comment block belongs. - * Any information (like documentation) that is found in - * the comment block will be stored in this entry. - * @param[in] comment A string representing the actual comment block. - * Note that leading *'s are already stripped from the comment block. - * @param[in] fileName The name of the file in which the comment is found. - * Mainly used for producing warnings. - * @param[in,out] lineNr The line number at which the comment block was found. - * When the function returns it will be set to the last line parsed. - * @param[in] isBrief TRUE iff this comment block represents a brief description. - * @param[in] isJavadocStyle TRUE iff this comment block is in "Javadoc" style. - * This means that it starts as a brief description until the end of - * the sentences is found and then proceeds as a detailed description. - * @param[in] isInbody TRUE iff this comment block is located in the body of - * a function. - * @param[in,out] prot The protection level in which this comment block was - * found. Commands in the comment block may override this. - * @param[in,out] position The character position within \a comment where the - * comment block starts. Typically used in case the comment block - * contains multiple structural commands. - * @param[out] newEntryNeeded Boolean that is TRUE if the comment block parser - * finds that a the comment block finishes the entry and a new one - * needs to be started. - * @returns TRUE if the comment requires further processing. The - * parameter \a newEntryNeeded will typically be true in this case and - * \a position will indicate the offset inside the \a comment string - * where to proceed parsing. FALSE indicates no further processing is - * needed. - */ -bool parseCommentBlock(OutlineParserInterface *parser, - Entry *curEntry, - const QCString &comment, - const QCString &fileName, - int &lineNr, - bool isBrief, - bool isJavadocStyle, - bool isInbody, - Protection &prot, - int &position, - bool &newEntryNeeded - ); +class CommentScanner +{ + public: + CommentScanner(); + ~CommentScanner(); + /** Invokes the comment block parser with the request to parse a + * single comment block. + * @param[in] parser The language parse that invoked this function. + * The comment block parse may invoke + * ParserInterface::parsePrototype() in order to parse + * the argument of a @@fn command. + * @param[in] curEntry The Entry to which the comment block belongs. + * Any information (like documentation) that is found in + * the comment block will be stored in this entry. + * @param[in] comment A string representing the actual comment block. + * Note that leading *'s are already stripped from the comment block. + * @param[in] fileName The name of the file in which the comment is found. + * Mainly used for producing warnings. + * @param[in,out] lineNr The line number at which the comment block was found. + * When the function returns it will be set to the last line parsed. + * @param[in] isBrief TRUE iff this comment block represents a brief description. + * @param[in] isJavadocStyle TRUE iff this comment block is in "Javadoc" style. + * This means that it starts as a brief description until the end of + * the sentences is found and then proceeds as a detailed description. + * @param[in] isInbody TRUE iff this comment block is located in the body of + * a function. + * @param[in,out] prot The protection level in which this comment block was + * found. Commands in the comment block may override this. + * @param[in,out] position The character position within \a comment where the + * comment block starts. Typically used in case the comment block + * contains multiple structural commands. + * @param[out] newEntryNeeded Boolean that is TRUE if the comment block parser + * finds that a the comment block finishes the entry and a new one + * needs to be started. + * @returns TRUE if the comment requires further processing. The + * parameter \a newEntryNeeded will typically be true in this case and + * \a position will indicate the offset inside the \a comment string + * where to proceed parsing. FALSE indicates no further processing is + * needed. + */ + bool parseCommentBlock(OutlineParserInterface *parser, + Entry *curEntry, + const QCString &comment, + const QCString &fileName, + int &lineNr, + bool isBrief, + bool isJavadocStyle, + bool isInbody, + Protection &prot, + int &position, + bool &newEntryNeeded + ); + private: + struct Private; + std::unique_ptr p; +}; #endif diff --git a/src/commentscan.l b/src/commentscan.l index d7cf3c8..02117c2 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -15,6 +15,8 @@ %option never-interactive %option prefix="commentscanYY" +%option reentrant +%option extra-type="struct commentscanYY_state *" %{ @@ -31,6 +33,7 @@ #include #include #include +#include "commentscan.h" #include "scanner.h" #include "entry.h" #include "doxygen.h" @@ -54,88 +57,88 @@ #define YY_NO_UNISTD_H 1 // forward declarations -static bool handleBrief(const QCString &, const QCStringList &); -static bool handleFn(const QCString &, const QCStringList &); -static bool handleDef(const QCString &, const QCStringList &); -static bool handleOverload(const QCString &, const QCStringList &); -static bool handleEnum(const QCString &, const QCStringList &); -static bool handleDefGroup(const QCString &, const QCStringList &); -static bool handleAddToGroup(const QCString &, const QCStringList &); -static bool handleWeakGroup(const QCString &, const QCStringList &); -static bool handleNamespace(const QCString &, const QCStringList &); -static bool handlePackage(const QCString &, const QCStringList &); -static bool handleClass(const QCString &, const QCStringList &); -static bool handleHeaderFile(const QCString &, const QCStringList &); -static bool handleProtocol(const QCString &, const QCStringList &); -static bool handleCategory(const QCString &, const QCStringList &); -static bool handleUnion(const QCString &, const QCStringList &); -static bool handleStruct(const QCString &, const QCStringList &); -static bool handleInterface(const QCString &, const QCStringList &); -static bool handleIdlException(const QCString &, const QCStringList &); -static bool handlePage(const QCString &, const QCStringList &); -static bool handleMainpage(const QCString &, const QCStringList &); -static bool handleFile(const QCString &, const QCStringList &); -static bool handleDir(const QCString &, const QCStringList &); -static bool handleExample(const QCString &, const QCStringList &); -static bool handleDetails(const QCString &, const QCStringList &); -static bool handleNoop(const QCString &, const QCStringList &); -static bool handleName(const QCString &, const QCStringList &); -static bool handleTodo(const QCString &, const QCStringList &); -static bool handleTest(const QCString &, const QCStringList &); -static bool handleBug(const QCString &, const QCStringList &); -static bool handleSubpage(const QCString &s, const QCStringList &); -static bool handleDeprecated(const QCString &, const QCStringList &); -static bool handleXRefItem(const QCString &, const QCStringList &); -static bool handleRelated(const QCString &, const QCStringList &); -static bool handleRelatedAlso(const QCString &, const QCStringList &); -static bool handleMemberOf(const QCString &, const QCStringList &); -static bool handleRefItem(const QCString &, const QCStringList &); -static bool handleSection(const QCString &, const QCStringList &); -static bool handleAnchor(const QCString &, const QCStringList &); -static bool handleCite(const QCString &, const QCStringList &); -static bool handleFormatBlock(const QCString &, const QCStringList &); -static bool handleAddIndex(const QCString &, const QCStringList &); -static bool handleIf(const QCString &, const QCStringList &); -static bool handleIfNot(const QCString &, const QCStringList &); -static bool handleElseIf(const QCString &, const QCStringList &); -static bool handleElse(const QCString &, const QCStringList &); -static bool handleEndIf(const QCString &, const QCStringList &); -static bool handleIngroup(const QCString &, const QCStringList &); -static bool handleNoSubGrouping(const QCString &, const QCStringList &); -static bool handleShowInitializer(const QCString &, const QCStringList &); -static bool handleHideInitializer(const QCString &, const QCStringList &); -static bool handleCallgraph(const QCString &, const QCStringList &); -static bool handleHideCallgraph(const QCString &, const QCStringList &); -static bool handleCallergraph(const QCString &, const QCStringList &); -static bool handleHideCallergraph(const QCString &, const QCStringList &); -static bool handleReferencedByRelation(const QCString &, const QCStringList &); -static bool handleHideReferencedByRelation(const QCString &, const QCStringList &); -static bool handleReferencesRelation(const QCString &, const QCStringList &); -static bool handleHideReferencesRelation(const QCString &, const QCStringList &); -static bool handleInternal(const QCString &, const QCStringList &); -static bool handleLineBr(const QCString &, const QCStringList &); -static bool handleStatic(const QCString &, const QCStringList &); -static bool handlePure(const QCString &, const QCStringList &); -static bool handlePrivate(const QCString &, const QCStringList &); -static bool handlePrivateSection(const QCString &, const QCStringList &); -static bool handleProtected(const QCString &, const QCStringList &); -static bool handleProtectedSection(const QCString &, const QCStringList &); -static bool handlePublic(const QCString &s, const QCStringList &); -static bool handlePublicSection(const QCString &s, const QCStringList &); -static bool handleToc(const QCString &s, const QCStringList &); -static bool handleInherit(const QCString &, const QCStringList &); -static bool handleExtends(const QCString &, const QCStringList &); -static bool handleCopyDoc(const QCString &, const QCStringList &); -static bool handleCopyBrief(const QCString &, const QCStringList &); -static bool handleCopyDetails(const QCString &, const QCStringList &); -static bool handleParBlock(const QCString &, const QCStringList &); -static bool handleEndParBlock(const QCString &, const QCStringList &); -static bool handleParam(const QCString &, const QCStringList &); -static bool handleRetval(const QCString &, const QCStringList &); +static bool handleBrief(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleFn(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDef(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleOverload(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleEnum(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDefGroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleAddToGroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleWeakGroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleNamespace(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePackage(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleClass(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHeaderFile(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleProtocol(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCategory(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleUnion(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleStruct(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleInterface(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIdlException(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePage(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleMainpage(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleFile(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDir(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleExample(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDetails(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleNoop(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleName(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleTodo(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleTest(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleBug(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleSubpage(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handleDeprecated(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleXRefItem(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRelated(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRelatedAlso(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleMemberOf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRefItem(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleSection(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleAnchor(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCite(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleFormatBlock(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleAddIndex(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIfNot(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleElseIf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleElse(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleEndIf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIngroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleNoSubGrouping(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleShowInitializer(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideInitializer(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCallgraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideCallgraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCallergraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideCallergraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleReferencedByRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideReferencedByRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleReferencesRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideReferencesRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleInternal(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleLineBr(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleStatic(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePure(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePrivate(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePrivateSection(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleProtected(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleProtectedSection(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePublic(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handlePublicSection(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handleToc(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handleInherit(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleExtends(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCopyBrief(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleParBlock(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleEndParBlock(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleParam(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRetval(yyscan_t yyscanner,const QCString &, const QCStringList &); static const char *stateToString(int state); -typedef bool (*DocCmdFunc)(const QCString &name, const QCStringList &optList); +typedef bool (*DocCmdFunc)(yyscan_t yyscanner,const QCString &name, const QCStringList &optList); struct DocCmdMap { @@ -325,15 +328,15 @@ class DocCmdMapper DocCmdMap *p = docCmdMap; while (p->cmdName) { - if (m_map.find(p->cmdName)!=0) - { - term("DocCmdMapper: command %s already added\n",p->cmdName); - } - Cmd *cmd = new Cmd; - cmd->func = p->handler; - cmd->endsBrief = p->endsBrief; - m_map.insert(p->cmdName,cmd); - p++; + if (m_map.find(p->cmdName)!=0) + { + term("DocCmdMapper: command %s already added\n",p->cmdName); + } + Cmd *cmd = new Cmd; + cmd->func = p->handler; + cmd->endsBrief = p->endsBrief; + m_map.insert(p->cmdName,cmd); + p++; } } @@ -347,7 +350,6 @@ class DocCmdMapper DocCmdMapper *DocCmdMapper::s_instance=0; -bool inInternalDocs = FALSE; #define YY_NEVER_INTERACTIVE 1 @@ -394,505 +396,92 @@ class GuardedSection * statics */ -static OutlineParserInterface *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 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 void initParser() -{ - g_sectionLabel.resize(0); - g_sectionTitle.resize(0); - Doxygen::docGroup.clearHeader(); - 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) -{ - if (listName==0) return; - //printf("addXRefItem(%s,%s,%s,%d)\n",listName,itemTitle,listTitle,append); - - const 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"); - } - for (const ListItemInfo &item : current->sli) - { - if (qstrcmp(item.type,listName)==0) - { - //printf("found %s lii->type=%s\n",listName,lii->type); - lii = &item; - 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; - current->addSpecialListItem(listName,itemId); - QCString cmdString; - cmdString.sprintf(" \\xrefitem %s %d.",listName,itemId); - if (inBody) - { - current->inbodyDocs += cmdString; - } - else - { - current->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); - current->anchors.push_back(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.push_back(si); - - // add section to the global dictionary - Doxygen::sectionDict->append(g_sectionLabel,si); - } -} - -//----------------------------------------------------------------------------- - -static void addCite() -{ - QCString name=yytext; - if (yytext[0] =='"') - { - name=yytext+1; - name=name.left(yyleng-2); - } - Doxygen::citeDict->insert(name.data()); -} - -//----------------------------------------------------------------------------- - -// 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 - { - if (!current->doc.isEmpty()) // when appending parts add a new line - { - current->doc += "\n"; - } - 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.push_back(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; -} +struct commentscanYY_state +{ + OutlineParserInterface *langParser = 0; // the language parser that is calling us + QCString inputString; // input string + int inputPosition = 0; // read pointer + QCString fileName; // file name that is read from + int lineNr = 0; // line number in the input + bool inBody = FALSE; // was the comment found inside the body of a function? + OutputContext inContext; // are we inside the brief, details or xref part + bool briefEndsAtDot = FALSE; // does the brief description stop at a dot? + QCString formulaText; // Running text of a formula + QCString formulaEnv; // environment name + int formulaNewLines = 0; // amount of new lines in the formula + QCString *pOutputString = 0; // pointer to string to which the output is appended. + QCString outputXRef; // temp argument of todo/test/../xrefitem commands + QCString blockName; // preformatted block name (e.g. verbatim, latexonly,...) + XRefKind xrefKind = XRef_Item; // kind of cross-reference command + XRefKind newXRefKind = XRef_Item; // + GuardType guardType = Guard_If; // kind of guards for conditional section + bool enabledSectionFound = FALSE; + QCString functionProto; // function prototype + QStack guards; // tracks nested conditional sections (if,ifnot,..) + Entry *current = 0; // working entry + + bool needNewEntry = FALSE; + + QCString sectionLabel; + QCString sectionTitle; + int sectionLevel = 0; + QCString xrefItemKey; + QCString newXRefItemKey; + QCString xrefItemTitle; + QCString xrefListTitle; + Protection protection = Public; + + bool xrefAppendFlag = FALSE; + bool inGroupParamFound = FALSE; + int braceCount = 0; + bool insidePre = FALSE; + bool parseMore = FALSE; + int condCount = 0; + + int commentCount = 0; + QCString spaceBeforeCmd; + QCString spaceBeforeIf; + QCString copyDocArg; + + QCString guardExpr; + int roundCount = 0; + + bool insideParBlock = FALSE; + bool inInternalDocs = FALSE; + int prevPosition = 0; +}; -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 QCString stripQuotes(const char *s); +static bool getDocSectionName(int s); +static SectionInfo::SectionType sectionLevelToType(int level); +static void stripTrailingWhiteSpace(QCString &s); + +static void initParser(yyscan_t yyscanner); +static bool makeStructuralIndicator(yyscan_t yyscanner,Entry::Sections s); +static void lineCount(yyscan_t yyscanner); +static QCString stripQuotes(yyscan_t yyscanner,const char *s); +static void addXRefItem(yyscan_t yyscanner, + const char *listName,const char *itemTitle, + const char *listTitle,bool append); +static QCString addFormula(yyscan_t yyscanner); +static void checkFormula(yyscan_t yyscanner); +static void addSection(yyscan_t yyscanner); +static inline void setOutput(yyscan_t yyscanner,OutputContext ctx); +static void addAnchor(yyscan_t yyscanner,const char *anchor); +static inline void addOutput(yyscan_t yyscanner,const char *s); +static inline void addOutput(yyscan_t yyscanner,char c); +static void endBrief(yyscan_t yyscanner,bool addToOutput=TRUE); +static void handleGuard(yyscan_t yyscanner,const QCString &expr); +static int yyread(yyscan_t yyscanner,char *buf,int max_size); +static void addCite(yyscan_t yyscanner); -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; -} + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} @@ -1016,50 +605,50 @@ RCSTAG "$"{ID}":"[^\n$]+"$" */ {CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command - addOutput(yytext); + addOutput(yyscanner,yytext); } {CMD}{CMD}"~"[a-z_A-Z]* { // escaped command - addOutput(yytext); + addOutput(yyscanner,yytext); } {MAILADDR} { // mail address - addOutput(yytext); + addOutput(yyscanner,yytext); } "\""[^"\n]*"\"" { // quoted text - addOutput(yytext); + addOutput(yyscanner,yytext); } ("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!) - addOutput(yytext); + addOutput(yyscanner,yytext); } "<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description - setOutput(OutputDoc); + setOutput(yyscanner,OutputDoc); // continue with the same input REJECT; } "<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML command that ends a brief description - if (current->lang==SrcLangExt_CSharp) + if (yyextra->current->lang==SrcLangExt_CSharp) { - setOutput(OutputDoc); + setOutput(yyscanner,OutputDoc); } // continue with the same input REJECT; } "

" { // start of a .NET XML style brief description - setOutput(OutputBrief); - addOutput(yytext); + setOutput(yyscanner,OutputBrief); + addOutput(yyscanner,yytext); } "" { // start of a .NET XML style detailed description - setOutput(OutputDoc); - addOutput(yytext); + setOutput(yyscanner,OutputDoc); + addOutput(yyscanner,yytext); } "" { // start of a .NET XML style detailed description - setOutput(OutputBrief); - addOutput(yytext); - setOutput(OutputDoc); + setOutput(yyscanner,OutputBrief); + addOutput(yyscanner,yytext); + setOutput(yyscanner,OutputDoc); } "" { // end of a brief or detailed description - setOutput(OutputDoc); - addOutput(yytext); + setOutput(yyscanner,OutputDoc); + addOutput(yyscanner,yytext); } "<"{CAPTION}{ATTR}">" { QCString tag=yytext; @@ -1073,22 +662,22 @@ RCSTAG "$"{ID}":"[^\n$]+"$" if (e!=-1) // found matching end { QCString id=tag.mid(s+4,e-s-4); // extract id - addAnchor(id); + addAnchor(yyscanner,id); } } } - addOutput(yytext); + addOutput(yyscanner,yytext); } "<"{PRE}{ATTR}">" { - insidePre=TRUE; - addOutput(yytext); + yyextra->insidePre=TRUE; + addOutput(yyscanner,yytext); } "" { - insidePre=FALSE; - addOutput(yytext); + yyextra->insidePre=FALSE; + addOutput(yyscanner,yytext); } {RCSTAG} { // RCS tag which end a brief description - setOutput(OutputDoc); + setOutput(yyscanner,OutputDoc); REJECT; } "