--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Orb/Doxygen/src/commentscan.l Fri Apr 23 20:47:58 2010 +0100
@@ -0,0 +1,2660 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 1997-2008 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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "qtbc.h"
+#include <qarray.h>
+#include <qstack.h>
+#include <qregexp.h>
+#include <unistd.h>
+#include <qfile.h>
+
+#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"
+
+// forward declarations
+static bool handleBrief(const QCString &);
+static bool handleFn(const QCString &);
+static bool handleDef(const QCString &);
+static bool handleOverload(const QCString &);
+static bool handleEnum(const QCString &);
+static bool handleDefGroup(const QCString &);
+static bool handleAddToGroup(const QCString &);
+static bool handleWeakGroup(const QCString &);
+static bool handleNamespace(const QCString &);
+static bool handlePackage(const QCString &);
+static bool handleClass(const QCString &);
+static bool handleHeaderFile(const QCString &);
+static bool handleProtocol(const QCString &);
+static bool handleCategory(const QCString &);
+static bool handleUnion(const QCString &);
+static bool handleStruct(const QCString &);
+static bool handleInterface(const QCString &);
+static bool handleIdlException(const QCString &);
+static bool handlePage(const QCString &);
+static bool handleMainpage(const QCString &);
+static bool handleFile(const QCString &);
+static bool handleDir(const QCString &);
+static bool handleExample(const QCString &);
+static bool handleDetails(const QCString &);
+static bool handleName(const QCString &);
+static bool handleTodo(const QCString &);
+static bool handleTest(const QCString &);
+static bool handleBug(const QCString &);
+static bool handleSubpage(const QCString &s);
+static bool handleDeprecated(const QCString &);
+static bool handleXRefItem(const QCString &);
+static bool handleRelated(const QCString &);
+static bool handleRelatedAlso(const QCString &);
+static bool handleMemberOf(const QCString &);
+static bool handleRefItem(const QCString &);
+static bool handleSection(const QCString &);
+static bool handleAnchor(const QCString &);
+static bool handleFormatBlock(const QCString &);
+static bool handleAddIndex(const QCString &);
+static bool handleIf(const QCString &);
+static bool handleIfNot(const QCString &);
+static bool handleElseIf(const QCString &);
+static bool handleElse(const QCString &);
+static bool handleEndIf(const QCString &);
+static bool handleIngroup(const QCString &);
+static bool handleNoSubGrouping(const QCString &);
+static bool handleShowInitializer(const QCString &);
+static bool handleHideInitializer(const QCString &);
+static bool handleCallgraph(const QCString &);
+static bool handleCallergraph(const QCString &);
+static bool handleInternal(const QCString &);
+static bool handleLineBr(const QCString &);
+static bool handleStatic(const QCString &);
+static bool handlePure(const QCString &);
+static bool handlePrivate(const QCString &);
+static bool handlePrivateSection(const QCString &);
+static bool handleProtected(const QCString &);
+static bool handleProtectedSection(const QCString &);
+static bool handlePublic(const QCString &s);
+static bool handlePublicSection(const QCString &s);
+static bool handleInherit(const QCString &);
+static bool handleExtends(const QCString &);
+
+typedef bool (*DocCmdFunc)(const QCString &name);
+
+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 },
+ { "refitem", &handleRefItem, TRUE },
+ { "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 },
+ { "rtfonly", &handleFormatBlock, FALSE },
+ { "manonly", &handleFormatBlock, FALSE },
+ { "dot", &handleFormatBlock, TRUE },
+ { "msc", &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 },
+ { "callergraph", &handleCallergraph, 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 },
+ { "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", 0, TRUE },
+ { "copybrief", 0, FALSE },
+ { "copydetails", 0, TRUE },
+ { "date", 0, TRUE },
+ { "dotfile", 0, TRUE },
+ { "htmlinclude", 0, TRUE },
+ { "image", 0, TRUE },
+ { "include", 0, TRUE },
+ { "includelineno", 0, TRUE },
+ { "invariant", 0, TRUE },
+ { "li", 0, TRUE },
+ { "line", 0, TRUE },
+ { "note", 0, TRUE },
+ { "par", 0, TRUE },
+ { "param", 0, 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 },
+ { "retval", 0, TRUE },
+ { "sa", 0, TRUE },
+ { "see", 0, TRUE },
+ { "since", 0, TRUE },
+ { "throw", 0, TRUE },
+ { "throws", 0, TRUE },
+ { "until", 0, TRUE },
+ { "verbinclude", 0, TRUE },
+ { "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)
+ {
+ printf("Error: 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<Cmd> m_map;
+ static DocCmdMapper *s_instance;
+};
+
+DocCmdMapper *DocCmdMapper::s_instance=0;
+
+
+#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);
+void initGroupInfo(Entry *e);
+static void groupAddDocs(Entry *e,const char *fileName);
+
+/* -----------------------------------------------------------------
+ *
+ * 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<GuardedSection> 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 sectionLabel;
+static QCString sectionTitle;
+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_commentCount;
+
+//-----------------------------------------------------------------------------
+
+static QStack<Grouping> 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()
+{
+ sectionLabel.resize(0);
+ sectionTitle.resize(0);
+ g_memberGroupHeader.resize(0);
+}
+
+//-----------------------------------------------------------------------------
+
+static QCString getDocSectionName(int s)
+{
+ switch(s)
+ {
+ case Entry::CLASSDOC_SEC: return "\\class";
+ case Entry::STRUCTDOC_SEC: return "\\struct";
+ case Entry::UNIONDOC_SEC: return "\\union";
+ case Entry::EXCEPTIONDOC_SEC: return "\\exception";
+ case Entry::NAMESPACEDOC_SEC: return "\\namespace";
+ case Entry::PROTOCOLDOC_SEC: return "\\protocol";
+ case Entry::CATEGORYDOC_SEC: return "\\category";
+ case Entry::ENUMDOC_SEC: return "\\enum";
+ case Entry::PAGEDOC_SEC: return "\\page";
+ case Entry::MEMBERDOC_SEC: return "\\fn";
+ case Entry::OVERLOADDOC_SEC: return "\\overload";
+ case Entry::FILEDOC_SEC: return "\\file";
+ case Entry::DEFINEDOC_SEC: return "\\def";
+ case Entry::GROUPDOC_SEC: return "\\defgroup";
+ case Entry::MAINPAGEDOC_SEC: return "\\mainpage";
+ case Entry::PACKAGEDOC_SEC: return "\\package";
+ case Entry::DIRDOC_SEC: return "\\dir";
+ case Entry::EXAMPLE_SEC: return "\\example";
+ case Entry::MEMBERGRP_SEC: return "\\name";
+ default: return "";
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static bool makeStructuralIndicator(Entry::Sections s)
+{
+ if (!getDocSectionName(current->section).isEmpty())
+ {
+ 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<ListItemInfo> slii(*docEntry->sli);
+ for (slii.toFirst();(lii=slii.current());++slii)
+ {
+ if (strcmp(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 += " <p>";
+ 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=new SectionInfo(listName,anchorLabel,
+ sectionTitle,SectionInfo::Anchor);
+ Doxygen::sectionDict.insert(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[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<formulaNewLines;i++) formLabel+="\\_fakenl"; // add fake newlines to
+ // keep the warnings
+ // correctly aligned.
+ return formLabel;
+}
+
+//-----------------------------------------------------------------------------
+
+static void checkFormula();
+//-----------------------------------------------------------------------------
+
+static void addSection()
+{
+ sectionTitle+=yytext;
+ sectionTitle=sectionTitle.stripWhiteSpace();
+ //printf("Adding new section file=%s label=%s title=%s\n",yyFileName,sectionLabel.data(),sectionTitle.data());
+ SectionInfo *si = new SectionInfo(yyFileName,sectionLabel,sectionTitle,SectionInfo::Anchor);
+ current->anchors->append(si);
+ Doxygen::sectionDict.insert(yytext,si);
+}
+
+//-----------------------------------------------------------------------------
+
+// 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 upto 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())
+ {
+ //printf("Setting docFile to %s\n", yyFileName.data());
+ 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;
+ }
+ break;
+ case OutputXRef:
+ pOutputString = &outputXRef;
+ // first item found, so can't append to previous
+ //xrefAppendFlag = FALSE;
+ break;
+ case OutputInbody:
+ pOutputString = ¤t->inbodyDocs;
+ break;
+ }
+}
+
+// add a string to the output
+static inline void addOutput(const char *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);
+ }
+}
+
+/* ----------------------------------------------------------------- */
+#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"|"code")
+DCMD2 ("date"|"dot"|"msc"|"dotfile"|"example")
+DCMD3 ("htmlinclude"|"htmlonly"|"image"|"include")
+DCMD4 ("includelineno"|"internal"|"invariant")
+DCMD5 ("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]
+DETAILEDHTML {PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}
+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\-]*
+SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
+SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID})
+MAILADR [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 EnumDocArg1
+%x NameSpaceDocArg1
+%x PackageDocArg1
+%x GroupDocArg1
+%x GroupDocArg2
+%x SectionLabel
+%x SectionTitle
+%x SubpageLabel
+%x SubpageTitle
+%x FormatBlock
+%x LineParam
+%x GuardParam
+%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
+
+%%
+
+ /* 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 <command>).
+ * words and whitespace and other characters (#,?!, etc).
+ * grouping commands (e.g. @{ and @})
+ * language switch (e.g. \~english or \~).
+ * mail adress (e.g. dimitri@stack.nl).
+ * quoted text, such as "foo@bar"
+ * XML commands, <summary></summary><remarks></remarks>
+ */
+
+<Comment>{CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command
+ addOutput(yytext);
+ }
+<Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command
+ addOutput(yytext);
+ }
+<Comment>{MAILADR} { // mail adress
+ addOutput(yytext);
+ }
+<Comment>"\""[^"\n]*"\"" { // quoted text
+ addOutput(yytext);
+ }
+<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!)
+ addOutput(yytext);
+ }
+<Comment>{XREFCMD}/[^a-z_A-Z]* { // xref command
+ if (inContext!=OutputXRef)
+ {
+ briefEndsAtDot=FALSE;
+ setOutput(OutputDoc);
+ }
+ // continue with the same input
+ REJECT;
+ }
+ /*
+<Comment>{DETAILEDCMD}/[^a-z_A-Z]* { // command that can end a brief description
+ briefEndsAtDot=FALSE;
+ setOutput(OutputDoc);
+ // continue with the same input
+ REJECT;
+ }
+ */
+<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description
+ setOutput(OutputDoc);
+ // continue with the same input
+ REJECT;
+ }
+<Comment>"<summary>" { // start of a .NET XML style brief description
+ setOutput(OutputBrief);
+ }
+<Comment>"<remarks>"|"</summary>" { // start of a .NET XML style detailed description
+ setOutput(OutputDoc);
+ }
+<Comment>"</remarks>" { // end of a brief or detailed description
+ }
+<Comment>{RCSTAG} { // RCS tag which end a brief description
+ setOutput(OutputDoc);
+ REJECT;
+ }
+<Comment>"<!--" {
+ BEGIN(HtmlComment);
+ }
+<Comment>{CMD}[a-z_A-Z]+{B}* { // potentially interesting command
+ QCString cmdName = QCString(&yytext[1]).stripWhiteSpace();
+ DocCmdMapper::Cmd *cmdPtr = DocCmdMapper::map(cmdName);
+ if (cmdPtr) // special action is required
+ {
+ if (cmdPtr->endsBrief)
+ {
+ briefEndsAtDot=FALSE;
+ // this command forces the end of brief description
+ setOutput(OutputDoc);
+ }
+ if (cmdPtr->func && cmdPtr->func(cmdName))
+ {
+ // implicit split of the comment block into two
+ // entries. Restart the next block at the start
+ // of this command.
+ parseMore=TRUE;
+
+ // yuk, this is probably not very portable across lex implementations,
+ // but we need to know the position in the input buffer where this
+ // rule matched.
+ // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE
+#if YY_FLEX_MINOR_VERSION>=5 && YY_FLEX_SUBMINOR_VERSION>=33
+ inputPosition=prevPosition + yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+#else
+ inputPosition=prevPosition + yy_bp - yy_current_buffer->yy_ch_buf;
+#endif
+ yyterminate();
+ }
+ else if (cmdPtr->func==0)
+ {
+ // command without handler, to be processed
+ // later by parsedoc.cpp
+ addOutput(yytext);
+ }
+ }
+ else // command not relevant
+ {
+ addOutput(yytext);
+ }
+ }
+<Comment>("\\\\"|"@@")"f"[$\[{] { // escaped formula command
+ addOutput(yytext);
+ }
+<Comment>{CMD}"~"[a-z_A-Z]* { // language switch command
+ QCString langId = &yytext[2];
+ if (!langId.isEmpty() &&
+ stricmp(Config_getEnum("OUTPUT_LANGUAGE"),langId)!=0)
+ { // enable language specific section
+ BEGIN(SkipLang);
+ }
+ }
+<Comment>{CMD}"f{"[^}\n]+"}"("{"?) { // start of a formula with custom environment
+ formulaText="\\begin";
+ formulaEnv=&yytext[2];
+ if (formulaEnv.at(formulaEnv.length()-1)=='{')
+ {
+ // remove trailing open brace
+ formulaEnv=formulaEnv.left(formulaEnv.length()-1);
+ }
+ formulaText+=formulaEnv;
+ formulaNewLines=0;
+ BEGIN(ReadFormulaLong);
+ }
+<Comment>{CMD}"f$" { // start of a inline formula
+ formulaText="$";
+ formulaNewLines=0;
+ BEGIN(ReadFormulaShort);
+ }
+<Comment>{CMD}"f[" { // start of a block formula
+ formulaText="\\[";
+ formulaNewLines=0;
+ BEGIN(ReadFormulaLong);
+ }
+<Comment>{CMD}"{" { // begin of a group
+ //langParser->handleGroupStartCommand(g_memberGroupHeader);
+ openGroup(current,yyFileName,yyLineNr);
+ }
+<Comment>{CMD}"}" { // end of a group
+ //langParser->handleGroupEndCommand();
+ closeGroup(current,yyFileName,yyLineNr);
+ g_memberGroupHeader.resize(0);
+ }
+<Comment>{CMD}[$@\\&~<>#%] { // escaped character
+ addOutput(yytext);
+ }
+<Comment>[a-z_A-Z]+ { // normal word
+ addOutput(yytext);
+ }
+<Comment>^{B}*"."{B}*/\n { // explicit end autolist: e.g " ."
+ addOutput(yytext);
+ }
+<Comment>("."+)[a-z_A-Z0-9] { // . at start or in the middle of a word, or ellipsis
+ addOutput(yytext);
+ }
+<Comment>".\\"[ \t] { // . with escaped space.
+ addOutput(yytext[0]);
+ addOutput(yytext[2]);
+ }
+<Comment>".," { // . with comma such as "e.g.,"
+ addOutput(yytext);
+ }
+<Comment>(\n|\\_linebr)({B}*(\n|\\_linebr))+ { // at least one blank line (or blank line command)
+ if (inContext!=OutputBrief)
+ {
+ addOutput("\n\n");
+ setOutput(OutputDoc);
+ }
+ else
+ { // only go to the detailed description if we have
+ // found some brief description and not just whitespace
+ endBrief(FALSE);
+ }
+ lineCount();
+ }
+<Comment>"." { // potential end of a JavaDoc style comment
+ addOutput(*yytext);
+ if (briefEndsAtDot)
+ {
+ setOutput(OutputDoc);
+ briefEndsAtDot=FALSE;
+ }
+ }
+<Comment>\n { // newline
+ addOutput(*yytext);
+ yyLineNr++;
+ }
+<Comment>. { // catch-all for anything else
+ addOutput(*yytext);
+ }
+
+
+ /* -------------- Rules for handling HTML comments ----------- */
+
+<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); }
+<HtmlComment>{DOCNL} {
+ if (*yytext=='\n') yyLineNr++;
+ }
+<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters
+ }
+<HtmlComment>. { // ignore every else
+ }
+
+ /* -------------- Rules for handling formulas ---------------- */
+
+<ReadFormulaShort>{CMD}"f$" { // end of inline formula
+ formulaText+="$";
+ addOutput(addFormula());
+ BEGIN(Comment);
+ }
+<ReadFormulaLong>{CMD}"f]" { // end of block formula
+ formulaText+="\\]";
+ addOutput(addFormula());
+ BEGIN(Comment);
+ }
+<ReadFormulaLong>{CMD}"f}" { // end of custom env formula
+ formulaText+="\\end";
+ formulaText+=formulaEnv;
+ addOutput(addFormula());
+ BEGIN(Comment);
+ }
+<ReadFormulaLong,ReadFormulaShort>[^\\@\n]+ { // any non-special character
+ formulaText+=yytext;
+ }
+<ReadFormulaLong,ReadFormulaShort>\n { // new line
+ formulaNewLines++;
+ formulaText+=*yytext;
+ yyLineNr++;
+ }
+<ReadFormulaLong,ReadFormulaShort>. { // any othe character
+ formulaText+=*yytext;
+ }
+
+ /* ------------ handle argument of enum command --------------- */
+
+<EnumDocArg1>{SCOPEID} { // handle argument
+ current->name = yytext;
+ BEGIN( Comment );
+ }
+<EnumDocArg1>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<EnumDocArg1>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: missing argument after \\enum."
+ );
+ addOutput('\n');
+ if (*yytext=='\n') yyLineNr++;
+ BEGIN( Comment );
+ }
+<EnumDocArg1>. { // ignore other stuff
+ }
+
+ /* ------------ handle argument of namespace command --------------- */
+
+<NameSpaceDocArg1>{SCOPENAME} { // handle argument
+ current->name = substitute(yytext,".","::");
+ BEGIN( Comment );
+ }
+<NameSpaceDocArg1>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<NameSpaceDocArg1>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: missing argument after "
+ "\\namespace."
+ );
+ addOutput('\n');
+ if (*yytext=='\n') yyLineNr++;
+ BEGIN( Comment );
+ }
+<NameSpaceDocArg1>. { // ignore other stuff
+ }
+
+ /* ------------ handle argument of package command --------------- */
+
+<PackageDocArg1>{ID}("."{ID})* { // handle argument
+ current->name = yytext;
+ BEGIN( Comment );
+ }
+<PackageDocArg1>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<PackageDocArg1>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: missing argument after "
+ "\\package."
+ );
+ addOutput('\n');
+ if (*yytext=='\n') yyLineNr++;
+ BEGIN( Comment );
+ }
+<PackageDocArg1>. { // ignore other stuff
+ }
+
+ /* ------ handle argument of class/struct/union command --------------- */
+
+<ClassDocArg1>{SCOPENAME} { // first argument
+ current->name = substitute(yytext,".","::");
+ if (current->section==Entry::PROTOCOLDOC_SEC)
+ {
+ current->name+="-p";
+ }
+ // prepend outer scope name
+ BEGIN( ClassDocArg2 );
+ }
+<CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" {
+ current->name = substitute(yytext,".","::");
+ BEGIN( ClassDocArg2 );
+ }
+<ClassDocArg1,CategoryDocArg1>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<ClassDocArg1,CategoryDocArg1>{DOCNL} {
+ warn(yyFileName,yyLineNr,
+ "Warning: missing argument after "
+ "\\%s.",YY_START==ClassDocArg1?"class":"category"
+ );
+ addOutput('\n');
+ if (*yytext=='\n') yyLineNr++;
+ BEGIN( Comment );
+ }
+<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff
+ }
+
+<ClassDocArg2>{FILE}|"<>" { // second argument; include file
+ current->includeFile = yytext;
+ BEGIN( ClassDocArg3 );
+ }
+<ClassDocArg2>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<ClassDocArg2>{DOCNL} {
+ addOutput('\n');
+ if (*yytext=='\n') yyLineNr++;
+ BEGIN( Comment );
+ }
+<ClassDocArg2>. { // ignore other stuff
+ }
+
+<ClassDocArg3>[<]?{FILE}?[>]? { // third argument; include file name
+ current->includeName = yytext;
+ BEGIN( Comment );
+ }
+<ClassDocArg3>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<ClassDocArg3>{DOCNL} {
+ if (*yytext=='\n') yyLineNr++;
+ BEGIN( Comment );
+ }
+<ClassDocArg3>. { // ignore other stuff
+ }
+
+ /* --------- handle arguments of {def,add,weak}group commands --------- */
+
+<GroupDocArg1>{ID}(".html"?) { // group name
+ current->name = yytext;
+ //lastDefGroup.groupname = yytext;
+ //lastDefGroup.pri = current->groupingPri();
+ // the .html stuff is for Qt compatibility
+ if (current->name.right(5)==".html")
+ {
+ current->name=current->name.left(current->name.length()-5);
+ }
+ current->type.resize(0);
+ BEGIN(GroupDocArg2);
+ }
+<GroupDocArg1>"\\"{B}*"\n" { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<GroupDocArg1>{DOCNL} { // missing argument!
+ warn(yyFileName,yyLineNr,
+ "Warning: missing group name after %s",
+ current->groupDocCmd()
+ );
+ addOutput('\n');
+ if (*yytext=='\n') yyLineNr++;
+ BEGIN( Comment );
+ }
+<GroupDocArg2>"\\"{B}*"\n" { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<GroupDocArg2>[^\n\\\*]+ { // title (stored in type)
+ current->type += yytext;
+ current->type = current->type.stripWhiteSpace();
+ }
+<GroupDocArg2>{DOCNL} {
+ if ( current->groupDocType==Entry::GROUPDOC_NORMAL &&
+ current->type.isEmpty()
+ ) // defgroup requires second argument
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: missing title after "
+ "\\defgroup %s", current->name.data()
+ );
+ }
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+
+ /* --------- handle arguments of page/mainpage command ------------------- */
+
+<PageDocArg1>{FILE} { // first argument; page name
+ current->name = stripQuotes(yytext);
+ BEGIN( PageDocArg2 );
+ }
+<PageDocArg1>{LC} { yyLineNr++;
+ addOutput('\n');
+ }
+<PageDocArg1>{DOCNL} {
+ warn(yyFileName,yyLineNr,
+ "Warning: missing argument after "
+ "\\page."
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<PageDocArg1>. { // ignore other stuff
+ }
+<PageDocArg2>.*"\n" { // second argument; page title
+ yyLineNr++;
+ current->args = yytext;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+
+ /* --------- handle arguments of the file/dir/example command ------------ */
+
+<FileDocArg1>{DOCNL} { // no file name specfied
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<FileDocArg1>{FILE} { // first argument; name
+ current->name = stripQuotes(yytext);
+ BEGIN( Comment );
+ }
+<FileDocArg1>{LC} { yyLineNr++;
+ addOutput('\n');
+ }
+<FileDocArg1>. { // ignore other stuff
+ }
+
+ /* --------- handle arguments of the xrefitem command ------------ */
+
+<XRefItemParam1>{ID} { // first argument
+ newXRefItemKey=yytext;
+ setOutput(OutputXRef);
+ BEGIN(XRefItemParam2);
+ }
+<XRefItemParam1>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<XRefItemParam1>{DOCNL} { // missing arguments
+ warn(yyFileName,yyLineNr,
+ "Warning: Missing first argument of \\xrefitem"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ inContext = OutputDoc;
+ BEGIN( Comment );
+ }
+<XRefItemParam1>. { // ignore other stuff
+ }
+
+<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument
+ xrefItemTitle = stripQuotes(yytext);
+ BEGIN(XRefItemParam3);
+ }
+<XRefItemParam2>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<XRefItemParam2>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: Missing second argument of \\xrefitem"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ inContext = OutputDoc;
+ BEGIN( Comment );
+ }
+<XRefItemParam2>. { // ignore other stuff
+ }
+
+<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument
+ xrefListTitle = stripQuotes(yytext);
+ xrefKind = XRef_Item;
+ BEGIN( Comment );
+ }
+<XRefItemParam2,XRefItemParam3>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<XRefItemParam3>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: Missing third argument of \\xrefitem"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ inContext = OutputDoc;
+ BEGIN( Comment );
+ }
+<XRefItemParam3>. { // ignore other stuff
+ }
+
+
+ /* ----- handle arguments of the relates(also)/memberof command ------- */
+
+<RelatesParam1>({ID}("::"|"."))*{ID} { // argument
+ current->relates = yytext;
+ //if (current->mGrpId!=DOX_NOGROUP)
+ //{
+ // memberGroupRelates = yytext;
+ //}
+ BEGIN( Comment );
+ }
+<RelatesParam1>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<RelatesParam1>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: Missing argument of \\relates or \\memberof command"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<RelatesParam1>. { // ignore other stuff
+ }
+
+
+ /* ----- handle arguments of the relates(also)/addindex commands ----- */
+
+<LineParam>{DOCNL} { // end of argument
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<LineParam>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<LineParam>. { // ignore other stuff
+ addOutput(*yytext);
+ }
+
+ /* ----- handle arguments of the section/subsection/.. commands ------- */
+
+<SectionLabel>{LABELID} { // first argyment
+ sectionLabel=yytext;
+ addOutput(yytext);
+ sectionTitle.resize(0);
+ BEGIN(SectionTitle);
+ }
+<SectionLabel>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: \\section command has no label"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<SectionLabel>. { // invalid character for section label
+ warn(yyFileName,yyLineNr,
+ "Warning: Invalid or missing section label"
+ );
+ BEGIN(Comment);
+ }
+
+<SectionTitle>[^\n@\\*]*/"\n" { // end of section title
+ addSection();
+ addOutput(yytext);
+ BEGIN( Comment );
+ }
+<SectionTitle>[^\n@\\]*/"\\_linebr" { // end of section title
+ addSection();
+ addOutput(yytext);
+ BEGIN( Comment );
+ }
+<SectionTitle>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<SectionTitle>[^\n@\\]* { // any character without special meaning
+ sectionTitle+=yytext;
+ addOutput(yytext);
+ }
+<SectionTitle>("\\\\"|"@@"){ID} { // unescape escaped command
+ sectionTitle+=&yytext[1];
+ addOutput(yytext);
+ }
+<SectionTitle>{CMD}[$@\\&~<>#%] { // unescape escaped character
+ sectionTitle+=yytext[1];
+ addOutput(yytext);
+ }
+<SectionTitle>. { // anything else
+ sectionTitle+=yytext;
+ addOutput(*yytext);
+ }
+
+ /* ----- handle arguments of the subpage command ------- */
+
+<SubpageLabel>{LABELID} { // first argument
+ addOutput(yytext);
+ // we add subpage labels as a kind of "inheritance" relation to prevent
+ // needing to add another list to the Entry class.
+ current->extends->append(new BaseInfo(yytext,Public,Normal));
+ BEGIN(SubpageTitle);
+ }
+<SubpageLabel>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: \\subpage command has no label"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<SubpageTitle>{DOCNL} { // no title, end command
+ addOutput(yytext);
+ BEGIN( Comment );
+ }
+<SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command
+ addOutput(yytext);
+ BEGIN( Comment );
+ }
+<SubpageTitle>. { // no title, end of command
+ unput(*yytext);
+ BEGIN( Comment );
+ }
+
+ /* ----- handle arguments of the anchor command ------- */
+
+<AnchorLabel>{LABELID} { // found argument
+ SectionInfo *si = new SectionInfo(yyFileName,yytext,0,SectionInfo::Anchor);
+ Doxygen::sectionDict.insert(yytext,si);
+ current->anchors->append(si);
+ addOutput(yytext);
+ BEGIN( Comment );
+ }
+<AnchorLabel>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: \\anchor command has no label"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<AnchorLabel>. { // invalid character for anchor label
+ warn(yyFileName,yyLineNr,
+ "Warning: Invalid or missing anchor label"
+ );
+ BEGIN(Comment);
+ }
+
+
+ /* ----- handle arguments of the preformatted block commands ------- */
+
+<FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends
+ addOutput(yytext);
+ if (&yytext[4]==blockName) // found end of the block
+ {
+ BEGIN(Comment);
+ }
+ }
+<FormatBlock>[^ \@\*\/\\\n]* { // some word
+ addOutput(yytext);
+ }
+<FormatBlock>{DOCNL} { // new line
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ }
+<FormatBlock>"/*" { // start of a C-comment
+ g_commentCount++;
+ addOutput(yytext);
+ }
+<FormatBlock>"*/" { // end of a C-comment
+ addOutput(yytext);
+ g_commentCount--;
+ if (g_commentCount<0 && blockName!="verbatim")
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",blockName.data(),blockName.data());
+ }
+ }
+<FormatBlock>. {
+ addOutput(*yytext);
+ }
+<FormatBlock><<EOF>> {
+ warn(yyFileName,yyLineNr,
+ "Warning: reached end of comment while inside a @%s block; check for missing @end%s tag!",
+ blockName.data(),blockName.data()
+ );
+ yyterminate();
+ }
+
+ /* ----- handle arguments of if/ifnot commands ------- */
+
+<GuardParam>{LABELID} { // parameter of if/ifnot guard
+ bool sectionEnabled = Config_getList("ENABLED_SECTIONS").find(yytext)!=-1;
+ bool parentEnabled = TRUE;
+ if (!guards.isEmpty()) parentEnabled = guards.top()->isEnabled();
+ if (parentEnabled)
+ {
+ if (
+ (sectionEnabled && guardType==Guard_If) ||
+ (!sectionEnabled && guardType==Guard_IfNot)
+ ) // section is visible
+ {
+ guards.push(new GuardedSection(TRUE,TRUE));
+ enabledSectionFound=TRUE;
+ BEGIN( Comment );
+ }
+ else // section is invisible
+ {
+ if (guardType!=Guard_Skip)
+ {
+ guards.push(new GuardedSection(FALSE,TRUE));
+ }
+ BEGIN( SkipGuardedSection );
+ }
+ }
+ else // invisible because of parent
+ {
+ guards.push(new GuardedSection(FALSE,FALSE));
+ BEGIN( SkipGuardedSection );
+ }
+ }
+<GuardParam>{DOCNL} { // end of argument
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<GuardParam>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<GuardParam>. { // ignore other stuff
+ addOutput(*yytext);
+ }
+
+ /* ----- handle skipping of conditional sections ------- */
+
+<SkipGuardedSection>{CMD}"ifnot"/{NW} {
+ guardType = Guard_IfNot;
+ BEGIN( GuardParam );
+ }
+<SkipGuardedSection>{CMD}"if"/{NW} {
+ guardType = Guard_If;
+ BEGIN( GuardParam );
+ }
+<SkipGuardedSection>{CMD}"endif"/{NW} {
+ if (guards.isEmpty())
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found @endif without matching start command");
+ }
+ else
+ {
+ delete guards.pop();
+ BEGIN( Comment );
+ }
+ }
+<SkipGuardedSection>{CMD}"else"/{NW} {
+ if (guards.isEmpty())
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found @else without matching start command");
+ }
+ else
+ {
+ if (!enabledSectionFound && guards.top()->parentVisible())
+ {
+ delete guards.pop();
+ guards.push(new GuardedSection(TRUE,TRUE));
+ enabledSectionFound=TRUE;
+ BEGIN( Comment );
+ }
+ }
+ }
+<SkipGuardedSection>{CMD}"elseif"/{NW} {
+ if (guards.isEmpty())
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found @elseif without matching start command");
+ }
+ else
+ {
+ if (!enabledSectionFound && guards.top()->parentVisible())
+ {
+ delete guards.pop();
+ BEGIN( GuardParam );
+ }
+ }
+ }
+<SkipGuardedSection>{DOCNL} { // skip line
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ }
+<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters
+ }
+<SkipGuardedSection>. { // any other character
+ }
+
+
+ /* ----- handle skipping of internal section ------- */
+
+<SkipInternal>{DOCNL} { // skip line
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ }
+<SkipInternal>[^ \\@\n]+ { // skip non-special characters
+ }
+<SkipInternal>. { // any other character
+ }
+
+
+ /* ----- handle argument of name command ------- */
+
+<NameParam>{DOCNL} { // end of argument
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<NameParam>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ g_memberGroupHeader+=' ';
+ }
+<NameParam>. { // ignore other stuff
+ g_memberGroupHeader+=*yytext;
+ current->name+=*yytext;
+ }
+
+ /* ----- handle argument of ingroup command ------- */
+
+<InGroupParam>{ID} { // group id
+ current->groups->append(
+ new Grouping(yytext, Grouping::GROUPING_INGROUP)
+ );
+ inGroupParamFound=TRUE;
+ }
+<InGroupParam>{DOCNL} { // missing argument
+ if (!inGroupParamFound)
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: Missing group name for \\ingroup command"
+ );
+ }
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<InGroupParam>{LC} { // line continuation
+ yyLineNr++;
+ addOutput('\n');
+ }
+<InGroupParam>. { // ignore other stuff
+ addOutput(*yytext);
+ }
+
+ /* ----- handle argument of fn command ------- */
+
+<FnParam>{DOCNL} { // end of argument
+ if (braceCount==0)
+ {
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ langParser->parsePrototype(functionProto);
+ BEGIN( Comment );
+ }
+ }
+<FnParam>{LC} { // line continuation
+ yyLineNr++;
+ functionProto+=' ';
+ }
+<FnParam>[^@\\\n()]+ { // non-special characters
+ functionProto+=yytext;
+ }
+<FnParam>"(" {
+ functionProto+=yytext;
+ braceCount++;
+ }
+<FnParam>")" {
+ functionProto+=yytext;
+ braceCount--;
+ }
+<FnParam>. { // add other stuff
+ functionProto+=*yytext;
+ }
+
+
+ /* ----- handle argument of overload command ------- */
+
+
+<OverloadParam>{DOCNL} { // end of argument
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ if (functionProto.stripWhiteSpace().isEmpty())
+ { // plain overload command
+ addOutput(getOverloadDocs());
+ }
+ else // overload declaration
+ {
+ makeStructuralIndicator(Entry::OVERLOADDOC_SEC);
+ langParser->parsePrototype(functionProto);
+ }
+ BEGIN( Comment );
+ }
+<OverloadParam>{LC} { // line continuation
+ yyLineNr++;
+ functionProto+=' ';
+ }
+<OverloadParam>. { // add other stuff
+ functionProto+=*yytext;
+ }
+
+ /* ----- handle argument of inherit command ------- */
+
+<InheritParam>({ID}("::"|"."))*{ID} { // found argument
+ current->extends->append(
+ new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal)
+ );
+ BEGIN( Comment );
+ }
+<InheritParam>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: \\inherit command has no argument"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<InheritParam>. { // invalid character for anchor label
+ warn(yyFileName,yyLineNr,
+ "Warning: Invalid or missing name for \\inherit command"
+ );
+ BEGIN(Comment);
+ }
+
+ /* ----- handle argument of extends and implements commands ------- */
+
+<ExtendsParam>({ID}("::"|"."))*{ID} { // found argument
+ current->extends->append(
+ new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal)
+ );
+ BEGIN( Comment );
+ }
+<ExtendsParam>{DOCNL} { // missing argument
+ warn(yyFileName,yyLineNr,
+ "Warning: \\extends or \\implements command has no argument"
+ );
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<ExtendsParam>. { // ignore other stuff
+ }
+
+ /* ----- handle language specific sections ------- */
+
+<SkipLang>[\\@]"~"[a-zA-Z]* { /* language switch */
+ QCString langId = &yytext[2];
+ if (langId.isEmpty() ||
+ stricmp(Config_getEnum("OUTPUT_LANGUAGE"),langId)==0)
+ { // enable language specific section
+ BEGIN(Comment);
+ }
+ }
+<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */
+ }
+<SkipLang>{DOCNL} { /* new line in verbatim block */
+ if (*yytext=='\n') yyLineNr++;
+ }
+<SkipLang>. { /* any other character */
+ }
+
+
+%%
+
+//----------------------------------------------------------------------------
+
+static bool handleBrief(const QCString &)
+{
+ //printf("handleBrief\n");
+ setOutput(OutputBrief);
+ return FALSE;
+}
+
+static bool handleFn(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::MEMBERDOC_SEC);
+ functionProto.resize(0);
+ braceCount=0;
+ BEGIN(FnParam);
+ return stop;
+}
+
+static bool handleDef(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::DEFINEDOC_SEC);
+ functionProto.resize(0);
+ BEGIN(FnParam);
+ return stop;
+}
+
+static bool handleOverload(const QCString &)
+{
+ functionProto.resize(0);
+ BEGIN(OverloadParam);
+ return FALSE;
+}
+
+static bool handleEnum(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::ENUMDOC_SEC);
+ BEGIN(EnumDocArg1);
+ return stop;
+}
+
+static bool handleDefGroup(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
+ current->groupDocType = Entry::GROUPDOC_NORMAL;
+ BEGIN( GroupDocArg1 );
+ return stop;
+}
+
+static bool handleAddToGroup(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
+ current->groupDocType = Entry::GROUPDOC_ADD;
+ BEGIN( GroupDocArg1 );
+ return stop;
+}
+
+static bool handleWeakGroup(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
+ current->groupDocType = Entry::GROUPDOC_WEAK;
+ BEGIN( GroupDocArg1 );
+ return stop;
+}
+
+static bool handleNamespace(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::NAMESPACEDOC_SEC);
+ BEGIN( NameSpaceDocArg1 );
+ return stop;
+}
+
+static bool handlePackage(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::PACKAGEDOC_SEC);
+ BEGIN( PackageDocArg1 );
+ return stop;
+}
+
+static bool handleClass(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::CLASSDOC_SEC);
+ BEGIN( ClassDocArg1 );
+ return stop;
+}
+
+static bool handleHeaderFile(const QCString &)
+{
+ BEGIN( ClassDocArg2 );
+ return FALSE;
+}
+
+static bool handleProtocol(const QCString &)
+{ // Obj-C protocol
+ bool stop=makeStructuralIndicator(Entry::PROTOCOLDOC_SEC);
+ BEGIN( ClassDocArg1 );
+ return stop;
+}
+
+static bool handleCategory(const QCString &)
+{ // Obj-C category
+ bool stop=makeStructuralIndicator(Entry::CATEGORYDOC_SEC);
+ BEGIN( CategoryDocArg1 );
+ return stop;
+}
+
+static bool handleUnion(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::UNIONDOC_SEC);
+ BEGIN( ClassDocArg1 );
+ return stop;
+}
+
+static bool handleStruct(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::STRUCTDOC_SEC);
+ BEGIN( ClassDocArg1 );
+ return stop;
+}
+
+static bool handleInterface(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::INTERFACEDOC_SEC);
+ BEGIN( ClassDocArg1 );
+ return stop;
+}
+
+static bool handleIdlException(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::EXCEPTIONDOC_SEC);
+ BEGIN( ClassDocArg1 );
+ return stop;
+}
+
+static bool handlePage(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::PAGEDOC_SEC);
+ BEGIN( PageDocArg1 );
+ return stop;
+}
+
+static bool handleMainpage(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::MAINPAGEDOC_SEC);
+ if (!stop)
+ {
+ current->name = "mainpage";
+ }
+ BEGIN( PageDocArg2 );
+ return stop;
+}
+
+static bool handleFile(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::FILEDOC_SEC);
+ if (!stop)
+ {
+ current->name = yyFileName;
+ }
+ BEGIN( FileDocArg1 );
+ return stop;
+}
+
+static bool handleDir(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::DIRDOC_SEC);
+ if (!stop) current->name = yyFileName;
+ BEGIN( FileDocArg1 );
+ return stop;
+}
+
+static bool handleExample(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::EXAMPLE_SEC);
+ if (!stop) current->name = yyFileName;
+ BEGIN( FileDocArg1 );
+ return stop;
+}
+
+static bool handleDetails(const QCString &)
+{
+ if (inContext!=OutputBrief)
+ {
+ addOutput("\n\n"); // treat @details outside brief description
+ // as a new paragraph
+ }
+ setOutput(OutputDoc);
+ return FALSE;
+}
+
+static bool handleName(const QCString &)
+{
+ bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC);
+ if (!stop)
+ {
+ g_memberGroupHeader.resize(0);
+ BEGIN( NameParam );
+ if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group
+ {
+ closeGroup(current,yyFileName,yyLineNr);
+ }
+ }
+ return stop;
+}
+
+static bool handleTodo(const QCString &)
+{
+ newXRefKind = XRef_Todo;
+ setOutput(OutputXRef);
+ xrefKind = XRef_Todo;
+ return FALSE;
+}
+
+static bool handleTest(const QCString &)
+{
+ newXRefKind = XRef_Test;
+ setOutput(OutputXRef);
+ xrefKind = XRef_Test;
+ return FALSE;
+}
+
+static bool handleBug(const QCString &)
+{
+ newXRefKind = XRef_Bug;
+ setOutput(OutputXRef);
+ xrefKind = XRef_Bug;
+ return FALSE;
+}
+
+static bool handleDeprecated(const QCString &)
+{
+ newXRefKind = XRef_Deprecated;
+ setOutput(OutputXRef);
+ xrefKind = XRef_Deprecated;
+ return FALSE;
+}
+
+static bool handleXRefItem(const QCString &)
+{
+ BEGIN(XRefItemParam1);
+ return FALSE;
+}
+
+static bool handleRelated(const QCString &)
+{
+ BEGIN(RelatesParam1);
+ return FALSE;
+}
+
+static bool handleRelatedAlso(const QCString &)
+{
+ current->relatesType = Duplicate;
+ BEGIN(RelatesParam1);
+ return FALSE;
+}
+
+static bool handleMemberOf(const QCString &)
+{
+ current->relatesType = MemberOf;
+ BEGIN(RelatesParam1);
+ return FALSE;
+}
+
+static bool handleRefItem(const QCString &)
+{
+ addOutput("@refitem ");
+ BEGIN(LineParam);
+ return FALSE;
+}
+
+static bool handleSection(const QCString &s)
+{
+ setOutput(OutputDoc);
+ addOutput("@"+s+" ");
+ BEGIN(SectionLabel);
+ return FALSE;
+}
+
+static bool handleSubpage(const QCString &s)
+{
+ if (current->section!=Entry::EMPTY_SEC &&
+ current->section!=Entry::PAGEDOC_SEC &&
+ current->section!=Entry::MAINPAGEDOC_SEC
+ )
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found \\subpage command in a comment block that is not marked as a page!");
+ }
+ addOutput("@"+s+" ");
+ BEGIN(SubpageLabel);
+ return FALSE;
+}
+
+static bool handleAnchor(const QCString &s)
+{
+ addOutput("@"+s+" ");
+ BEGIN(AnchorLabel);
+ return FALSE;
+}
+
+static bool handleFormatBlock(const QCString &s)
+{
+ addOutput("@"+s+" ");
+ //printf("handleFormatBlock(%s)\n",s.data());
+ blockName=s;
+ g_commentCount=0;
+ BEGIN(FormatBlock);
+ return FALSE;
+}
+
+static bool handleAddIndex(const QCString &)
+{
+ addOutput("@addindex ");
+ BEGIN(LineParam);
+ return FALSE;
+}
+
+static bool handleIf(const QCString &)
+{
+ enabledSectionFound=FALSE;
+ guardType = Guard_If;
+ BEGIN(GuardParam);
+ return FALSE;
+}
+
+static bool handleIfNot(const QCString &)
+{
+ enabledSectionFound=FALSE;
+ guardType = Guard_IfNot;
+ BEGIN(GuardParam);
+ return FALSE;
+}
+
+static bool handleElseIf(const QCString &)
+{
+ if (guards.isEmpty())
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found \\else without matching start command");
+ }
+ else
+ {
+ guardType = enabledSectionFound ? Guard_Skip : Guard_If;
+ BEGIN(GuardParam);
+ }
+ return FALSE;
+}
+
+static bool handleElse(const QCString &)
+{
+ if (guards.isEmpty())
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found \\else without matching start command");
+ }
+ else
+ {
+ BEGIN( SkipGuardedSection );
+ }
+ return FALSE;
+}
+
+static bool handleEndIf(const QCString &)
+{
+ if (guards.isEmpty())
+ {
+ warn(yyFileName,yyLineNr,
+ "Warning: found \\endif without matching start command");
+ }
+ else
+ {
+ delete guards.pop();
+ }
+ enabledSectionFound=FALSE;
+ return FALSE;
+}
+
+static bool handleIngroup(const QCString &)
+{
+ inGroupParamFound=FALSE;
+ BEGIN( InGroupParam );
+ return FALSE;
+}
+
+static bool handleNoSubGrouping(const QCString &)
+{
+ current->subGrouping = FALSE;
+ return FALSE;
+}
+
+static bool handleShowInitializer(const QCString &)
+{
+ current->initLines = 100000; // ON
+ return FALSE;
+}
+
+static bool handleHideInitializer(const QCString &)
+{
+ current->initLines = 0; // OFF
+ return FALSE;
+}
+
+static bool handleCallgraph(const QCString &)
+{
+ current->callGraph = TRUE; // ON
+ return FALSE;
+}
+
+static bool handleCallergraph(const QCString &)
+{
+ current->callerGraph = TRUE; // ON
+ return FALSE;
+}
+
+static bool handleInternal(const QCString &)
+{
+ if (!Config_getBool("INTERNAL_DOCS"))
+ {
+ // make sure some whitespace before a \internal command
+ // is not treated as "documentation"
+ if (current->doc.stripWhiteSpace().isEmpty())
+ {
+ current->doc.resize(0);
+ }
+ BEGIN( SkipInternal );
+ }
+ else
+ {
+ addOutput("\\internal ");
+ }
+ return FALSE;
+}
+
+static bool handleLineBr(const QCString &)
+{
+ addOutput('\n');
+ return FALSE;
+}
+
+static bool handleStatic(const QCString &)
+{
+ endBrief();
+ current->stat = TRUE;
+ return FALSE;
+}
+
+static bool handlePure(const QCString &)
+{
+ endBrief();
+ current->virt = Pure;
+ return FALSE;
+}
+
+static bool handlePrivate(const QCString &)
+{
+ current->protection = Private;
+ return FALSE;
+}
+
+static bool handlePrivateSection(const QCString &)
+{
+ current->protection = protection = Private;
+ return FALSE;
+}
+
+static bool handleProtected(const QCString &)
+{
+ current->protection = Protected;
+ return FALSE;
+}
+
+static bool handleProtectedSection(const QCString &)
+{
+ current->protection = protection = Protected ;
+ return FALSE;
+}
+
+static bool handlePublic(const QCString &)
+{
+ current->protection = Public;
+ return FALSE;
+}
+
+static bool handlePublicSection(const QCString &)
+{
+ current->protection = protection = Public;
+ return FALSE;
+}
+
+static bool handleInherit(const QCString &)
+{
+ BEGIN(InheritParam);
+ return FALSE;
+}
+
+static bool handleExtends(const QCString &)
+{
+ BEGIN(ExtendsParam);
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+
+static void checkFormula()
+{
+ if (YY_START==ReadFormulaShort || YY_START==ReadFormulaLong)
+ {
+ warn(yyFileName,yyLineNr,"Warning: End of comment block while inside formula.");
+ }
+}
+
+//----------------------------------------------------------------------------
+
+bool parseCommentBlock(/* in */ ParserInterface *parser,
+ /* in */ Entry *curEntry,
+ /* in */ const QCString &comment,
+ /* in */ const QCString &fileName,
+ /* in,out */ int &lineNr,
+ /* in */ bool isBrief,
+ /* in */ bool isAutoBriefOn,
+ /* in */ bool isInbody,
+ /* in,out */ Protection &prot,
+ /* in,out */ int &position,
+ /* out */ bool &newEntryNeeded
+ )
+{
+ //printf("parseCommentBlock() isBrief=%d isAutoBriefOn=%d lineNr=%d\n",
+ // isBrief,isAutoBriefOn,lineNr);
+ //printf("parseCommentBlock() lineNr=%d file=%s\n", lineNr, fileName.data());
+ initParser();
+ guards.setAutoDelete(TRUE);
+ guards.clear();
+ langParser = parser;
+ current = curEntry;
+ if (comment.isEmpty()) return FALSE; // avoid empty strings
+ inputString = comment;
+ inputString.append(" ");
+ inputPosition = position;
+ yyLineNr = lineNr;
+ yyFileName = fileName;
+ protection = prot;
+ needNewEntry = FALSE;
+ xrefKind = XRef_None;
+ xrefAppendFlag = FALSE;
+ insidePre = FALSE;
+ parseMore = FALSE;
+ inBody = isInbody;
+ outputXRef.resize(0);
+ setOutput( isBrief || isAutoBriefOn ? OutputBrief : OutputDoc );
+ briefEndsAtDot = isAutoBriefOn;
+
+ if (!current->inbodyDocs.isEmpty() && isInbody) // separate in body fragments
+ {
+ current->inbodyDocs+="\n\n";
+ }
+
+ Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\n"
+ "input=[%s]\n",fileName.data(),lineNr,comment.data()
+ );
+
+ commentScanYYrestart( commentScanYYin );
+ BEGIN( Comment );
+ commentScanYYlex();
+ setOutput( OutputDoc );
+
+ if (YY_START==OverloadParam) // comment ended with \overload
+ {
+ addOutput(getOverloadDocs());
+ }
+
+ if (!guards.isEmpty())
+ {
+ warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
+ }
+
+ current->doc=stripLeadingAndTrailingEmptyLines(current->doc);
+
+ if (current->section==Entry::FILEDOC_SEC && current->doc.isEmpty())
+ {
+ // to allow a comment block with just a @file command.
+ current->doc="\n\n";
+ }
+
+ if (current->section==Entry::MEMBERGRP_SEC &&
+ g_memberGroupId==DOX_NOGROUP) // @name section but no group started yet
+ {
+ openGroup(current,yyFileName,yyLineNr);
+ }
+
+ Debug::print(Debug::CommentScan,0,
+ "brief=[%s]\ndocs=[%s]\ninbody=[%s]\n===========\n",
+ current->brief.data(),current->doc.data(),current->inbodyDocs.data()
+ );
+
+ checkFormula();
+ prot = protection;
+
+ groupAddDocs(curEntry,fileName);
+
+ newEntryNeeded = needNewEntry;
+
+ // if we did not proceed during this call, it does not make
+ // sence to continue, since we get stuck. See bug 567346 for situations
+ // were this happens
+ if (parseMore && position==inputPosition) parseMore=FALSE;
+
+ if (parseMore) position=inputPosition; else position=0;
+
+ lineNr = yyLineNr;
+ //printf("position=%d parseMore=%d\n",position,parseMore);
+
+ return parseMore;
+}
+
+//---------------------------------------------------------------------------
+
+void groupEnterFile(const char *fileName,int)
+{
+ g_autoGroupStack.setAutoDelete(TRUE);
+ g_autoGroupStack.clear();
+ g_memberGroupId = DOX_NOGROUP;
+ g_memberGroupDocs.resize(0);
+ g_memberGroupRelates.resize(0);
+ g_compoundName=fileName;
+}
+
+void groupLeaveFile(const char *fileName,int line)
+{
+ //if (g_memberGroupId!=DOX_NOGROUP)
+ //{
+ // warn(fileName,line,"Warning: end of file while inside a member group\n");
+ //}
+ g_memberGroupId=DOX_NOGROUP;
+ g_memberGroupRelates.resize(0);
+ g_memberGroupDocs.resize(0);
+ if (!g_autoGroupStack.isEmpty())
+ {
+ warn(fileName,line,"Warning: end of file while inside a group\n");
+ }
+}
+
+void groupEnterCompound(const char *fileName,int line,const char *name)
+{
+ if (g_memberGroupId!=DOX_NOGROUP)
+ {
+ warn(fileName,line,"Warning: try to put compound %s inside a member group\n",name);
+ }
+ g_memberGroupId=DOX_NOGROUP;
+ g_memberGroupRelates.resize(0);
+ g_memberGroupDocs.resize(0);
+ g_compoundName = name;
+ int i = g_compoundName.find('(');
+ if (i!=-1)
+ {
+ g_compoundName=g_compoundName.left(i); // strip category (Obj-C)
+ }
+ if (g_compoundName.isEmpty())
+ {
+ g_compoundName=fileName;
+ }
+ //printf("groupEnterCompound(%s)\n",name);
+}
+
+void groupLeaveCompound(const char *,int,const char * /*name*/)
+{
+ //printf("groupLeaveCompound(%s)\n",name);
+ //if (g_memberGroupId!=DOX_NOGROUP)
+ //{
+ // warn(fileName,line,"Warning: end of compound %s while inside a member group\n",name);
+ //}
+ g_memberGroupId=DOX_NOGROUP;
+ g_memberGroupRelates.resize(0);
+ g_memberGroupDocs.resize(0);
+ g_compoundName.resize(0);
+}
+
+static int findExistingGroup(int &groupId,const MemberGroupInfo *info)
+{
+ //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data());
+ QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict);
+ MemberGroupInfo *mi;
+ for (di.toFirst();(mi=di.current());++di)
+ {
+ if (g_compoundName==mi->compoundName && // same file or scope
+ !mi->header.isEmpty() && // not a nameless group
+ stricmp(mi->header,info->header)==0 // same header name
+ )
+ {
+ //printf("Found it!\n");
+ return di.currentKey(); // put the item in this group
+ }
+ }
+ groupId++; // start new group
+ return groupId;
+}
+
+void openGroup(Entry *e,const char *,int)
+{
+ //printf("==> openGroup(name=%s,sec=%x) g_autoGroupStack=%d\n",
+ // e->name.data(),e->section,g_autoGroupStack.count());
+ if (e->section==Entry::GROUPDOC_SEC) // auto group
+ {
+ g_autoGroupStack.push(new Grouping(e->name,e->groupingPri()));
+ }
+ else // start of a member group
+ {
+ //printf(" membergroup id=%d\n",g_memberGroupId);
+ if (g_memberGroupId==DOX_NOGROUP) // no group started yet
+ {
+ static int curGroupId=0;
+
+ MemberGroupInfo *info = new MemberGroupInfo;
+ info->header = g_memberGroupHeader.stripWhiteSpace();
+ info->compoundName = g_compoundName;
+ g_memberGroupId = findExistingGroup(curGroupId,info);
+ //printf(" use membergroup %d\n",g_memberGroupId);
+ Doxygen::memGrpInfoDict.insert(g_memberGroupId,info);
+
+ g_memberGroupRelates = e->relates;
+ e->mGrpId = g_memberGroupId;
+ }
+ }
+}
+
+void closeGroup(Entry *e,const char *fileName,int)
+{
+ //printf("==> closeGroup(name=%s,sec=%x) g_autoGroupStack=%d\n",
+ // e->name.data(),e->section,g_autoGroupStack.count());
+ if (g_memberGroupId!=DOX_NOGROUP) // end of member group
+ {
+ MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
+ if (info) // known group
+ {
+ info->doc = g_memberGroupDocs;
+ info->docFile = fileName;
+ }
+ g_memberGroupId=DOX_NOGROUP;
+ g_memberGroupRelates.resize(0);
+ g_memberGroupDocs.resize(0);
+ e->mGrpId=DOX_NOGROUP;
+ //printf("new group id=%d\n",g_memberGroupId);
+ }
+ else if (!g_autoGroupStack.isEmpty()) // end of auto group
+ {
+ Grouping *grp = g_autoGroupStack.pop();
+ e->groups->removeLast();
+ //printf("Removing %s\n",grp->groupname.data());
+ delete grp;
+ initGroupInfo(e);
+ }
+}
+
+void initGroupInfo(Entry *e)
+{
+ //printf("==> initGroup(id=%d,related=%s)\n",g_memberGroupId,
+ // g_memberGroupRelates.data());
+ e->mGrpId = g_memberGroupId;
+ e->relates = g_memberGroupRelates;
+ if (!g_autoGroupStack.isEmpty())
+ {
+ //printf("Appending group %s to %s: count=%d entry=%p\n",
+ // g_autoGroupStack.top()->groupname.data(),
+ // e->name.data(),e->groups->count(),e);
+ e->groups->append(new Grouping(*g_autoGroupStack.top()));
+ }
+}
+
+static void groupAddDocs(Entry *e,const char *fileName)
+{
+ if (e->section==Entry::MEMBERGRP_SEC)
+ {
+ g_memberGroupDocs=e->brief.stripWhiteSpace();
+ e->doc = stripLeadingAndTrailingEmptyLines(e->doc);
+ if (!g_memberGroupDocs.isEmpty() && !e->doc.isEmpty())
+ {
+ g_memberGroupDocs+="\n\n";
+ }
+ g_memberGroupDocs+=e->doc;
+ MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
+ if (info)
+ {
+ info->doc = g_memberGroupDocs;
+ info->docFile = fileName;
+ info->setRefItems(e->sli);
+ }
+ e->doc.resize(0);
+ e->brief.resize(0);
+ }
+}
+
+
+#if !defined(YY_FLEX_SUBMINOR_VERSION)
+//----------------------------------------------------------------------------
+extern "C" { // some bogus code to keep the compiler happy
+ void commentScanYYdummy() { yy_flex_realloc(0,0); }
+}
+#endif
+