Orb/Doxygen/src/commentscan.l
changeset 0 42188c7ea2d9
child 1 82f11024044a
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /*****************************************************************************
       
     2  *
       
     3  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     4  *
       
     5  * Permission to use, copy, modify, and distribute this software and its
       
     6  * documentation under the terms of the GNU General Public License is hereby 
       
     7  * granted. No representations are made about the suitability of this software 
       
     8  * for any purpose. It is provided "as is" without express or implied warranty.
       
     9  * See the GNU General Public License for more details.
       
    10  *
       
    11  * Documents produced by Doxygen are derivative works derived from the
       
    12  * input used in their production; they are not affected by this license.
       
    13  *
       
    14  */
       
    15   
       
    16 %{
       
    17 
       
    18 /*
       
    19  *	includes
       
    20  */
       
    21 #include <stdio.h>
       
    22 #include <stdlib.h>
       
    23 #include <assert.h>
       
    24 #include <ctype.h>
       
    25 
       
    26 #include "qtbc.h"
       
    27 #include <qarray.h>
       
    28 #include <qstack.h>
       
    29 #include <qregexp.h>
       
    30 #include <unistd.h>
       
    31 #include <qfile.h>
       
    32   
       
    33 #include "scanner.h"
       
    34 #include "entry.h"
       
    35 #include "doxygen.h"
       
    36 #include "message.h"
       
    37 #include "config.h"
       
    38 #include "util.h"
       
    39 #include "index.h"
       
    40 #include "defargs.h"
       
    41 #include "language.h"
       
    42 #include "outputlist.h"
       
    43 #include "membergroup.h"
       
    44 #include "reflist.h"
       
    45 #include "debug.h"
       
    46 #include "parserintf.h"
       
    47 
       
    48 // forward declarations
       
    49 static bool handleBrief(const QCString &);
       
    50 static bool handleFn(const QCString &);
       
    51 static bool handleDef(const QCString &);
       
    52 static bool handleOverload(const QCString &);
       
    53 static bool handleEnum(const QCString &);
       
    54 static bool handleDefGroup(const QCString &);
       
    55 static bool handleAddToGroup(const QCString &);
       
    56 static bool handleWeakGroup(const QCString &);
       
    57 static bool handleNamespace(const QCString &);
       
    58 static bool handlePackage(const QCString &);
       
    59 static bool handleClass(const QCString &);
       
    60 static bool handleHeaderFile(const QCString &);
       
    61 static bool handleProtocol(const QCString &);
       
    62 static bool handleCategory(const QCString &);
       
    63 static bool handleUnion(const QCString &);
       
    64 static bool handleStruct(const QCString &);
       
    65 static bool handleInterface(const QCString &);
       
    66 static bool handleIdlException(const QCString &);
       
    67 static bool handlePage(const QCString &);
       
    68 static bool handleMainpage(const QCString &);
       
    69 static bool handleFile(const QCString &);
       
    70 static bool handleDir(const QCString &);
       
    71 static bool handleExample(const QCString &);
       
    72 static bool handleDetails(const QCString &);
       
    73 static bool handleName(const QCString &);
       
    74 static bool handleTodo(const QCString &);
       
    75 static bool handleTest(const QCString &);
       
    76 static bool handleBug(const QCString &);
       
    77 static bool handleSubpage(const QCString &s);
       
    78 static bool handleDeprecated(const QCString &);
       
    79 static bool handleXRefItem(const QCString &);
       
    80 static bool handleRelated(const QCString &);
       
    81 static bool handleRelatedAlso(const QCString &);
       
    82 static bool handleMemberOf(const QCString &);
       
    83 static bool handleRefItem(const QCString &);
       
    84 static bool handleSection(const QCString &);
       
    85 static bool handleAnchor(const QCString &);
       
    86 static bool handleFormatBlock(const QCString &);
       
    87 static bool handleAddIndex(const QCString &);
       
    88 static bool handleIf(const QCString &);
       
    89 static bool handleIfNot(const QCString &);
       
    90 static bool handleElseIf(const QCString &);
       
    91 static bool handleElse(const QCString &);
       
    92 static bool handleEndIf(const QCString &);
       
    93 static bool handleIngroup(const QCString &);
       
    94 static bool handleNoSubGrouping(const QCString &);
       
    95 static bool handleShowInitializer(const QCString &);
       
    96 static bool handleHideInitializer(const QCString &);
       
    97 static bool handleCallgraph(const QCString &);
       
    98 static bool handleCallergraph(const QCString &);
       
    99 static bool handleInternal(const QCString &);
       
   100 static bool handleLineBr(const QCString &);
       
   101 static bool handleStatic(const QCString &);
       
   102 static bool handlePure(const QCString &);
       
   103 static bool handlePrivate(const QCString &);
       
   104 static bool handlePrivateSection(const QCString &);
       
   105 static bool handleProtected(const QCString &);
       
   106 static bool handleProtectedSection(const QCString &);
       
   107 static bool handlePublic(const QCString &s);
       
   108 static bool handlePublicSection(const QCString &s);
       
   109 static bool handleInherit(const QCString &);
       
   110 static bool handleExtends(const QCString &);
       
   111 
       
   112 typedef bool (*DocCmdFunc)(const QCString &name);
       
   113 
       
   114 struct DocCmdMap
       
   115 {
       
   116   const char *cmdName;
       
   117   DocCmdFunc handler;
       
   118   bool endsBrief;
       
   119 };
       
   120 
       
   121 // map of command to handler function
       
   122 static DocCmdMap docCmdMap[] =
       
   123 {
       
   124   // command name      handler function         ends brief description
       
   125   { "brief",           &handleBrief,            FALSE },
       
   126   { "short",           &handleBrief,            FALSE },
       
   127   { "fn",              &handleFn,               FALSE },
       
   128   { "var",             &handleFn,               FALSE },
       
   129   { "typedef",         &handleFn,               FALSE },
       
   130   { "property",        &handleFn,               FALSE },
       
   131   { "def",             &handleDef,              FALSE },
       
   132   { "overload",        &handleOverload,         FALSE },
       
   133   { "enum",            &handleEnum,             FALSE },
       
   134   { "defgroup",        &handleDefGroup,         FALSE },
       
   135   { "addtogroup",      &handleAddToGroup,       FALSE },
       
   136   { "weakgroup",       &handleWeakGroup,        FALSE },
       
   137   { "namespace",       &handleNamespace,        FALSE },
       
   138   { "package",         &handlePackage,          FALSE },
       
   139   { "class",           &handleClass,            FALSE },
       
   140   { "headerfile",      &handleHeaderFile,       FALSE },
       
   141   { "protocol",        &handleProtocol,         FALSE },
       
   142   { "category",        &handleCategory,         FALSE },
       
   143   { "union",           &handleUnion,            FALSE },
       
   144   { "struct",          &handleStruct,           FALSE },
       
   145   { "interface",       &handleInterface,        FALSE },
       
   146   { "idlexcept",       &handleIdlException,     FALSE },
       
   147   { "page",            &handlePage,             FALSE },
       
   148   { "mainpage",        &handleMainpage,         FALSE },
       
   149   { "file",            &handleFile,             FALSE },
       
   150   { "dir",             &handleDir,              FALSE },
       
   151   { "example",         &handleExample,          FALSE },
       
   152   { "details",         &handleDetails,          TRUE  },
       
   153   { "name",            &handleName,             FALSE },
       
   154   { "todo",            &handleTodo,             FALSE }, // end brief will be done differently
       
   155   { "test",            &handleTest,             FALSE }, // end brief will be done differently
       
   156   { "bug",             &handleBug,              FALSE }, // end brief will be done differently
       
   157   { "deprecated",      &handleDeprecated,       FALSE }, // end brief will be done differently
       
   158   { "xrefitem",        &handleXRefItem,         FALSE }, // end brief will be done differently
       
   159   { "related",         &handleRelated,          TRUE  },
       
   160   { "relates",         &handleRelated,          TRUE  },
       
   161   { "relatedalso",     &handleRelatedAlso,      TRUE  },
       
   162   { "relatesalso",     &handleRelatedAlso,      TRUE  },
       
   163   { "refitem",         &handleRefItem,          TRUE  },
       
   164   { "subpage",         &handleSubpage,          TRUE  },
       
   165   { "section",         &handleSection,          TRUE  },
       
   166   { "subsection",      &handleSection,          TRUE  },
       
   167   { "subsubsection",   &handleSection,          TRUE  },
       
   168   { "paragraph",       &handleSection,          TRUE  },
       
   169   { "anchor",          &handleAnchor,           TRUE  },
       
   170   { "verbatim",        &handleFormatBlock,      TRUE },
       
   171   { "latexonly",       &handleFormatBlock,      FALSE },
       
   172   { "htmlonly",        &handleFormatBlock,      FALSE },
       
   173   { "xmlonly",         &handleFormatBlock,      FALSE },
       
   174   { "rtfonly",         &handleFormatBlock,      FALSE },
       
   175   { "manonly",         &handleFormatBlock,      FALSE },
       
   176   { "dot",             &handleFormatBlock,      TRUE  },
       
   177   { "msc",             &handleFormatBlock,      TRUE  },
       
   178   { "code",            &handleFormatBlock,      TRUE  },
       
   179   { "addindex",        &handleAddIndex,         FALSE },
       
   180   { "if",              &handleIf,               FALSE },
       
   181   { "ifnot",           &handleIfNot,            FALSE },
       
   182   { "elseif",          &handleElseIf,           FALSE },
       
   183   { "else",            &handleElse,             FALSE },
       
   184   { "endif",           &handleEndIf,            FALSE },
       
   185   { "ingroup",         &handleIngroup,          FALSE },
       
   186   { "nosubgrouping",   &handleNoSubGrouping,    FALSE },
       
   187   { "showinitializer", &handleShowInitializer,  FALSE },
       
   188   { "hideinitializer", &handleHideInitializer,  FALSE },
       
   189   { "callgraph",       &handleCallgraph,        FALSE },
       
   190   { "callergraph",     &handleCallergraph,      FALSE },
       
   191   { "internal",        &handleInternal,         TRUE  },
       
   192   { "_linebr",         &handleLineBr,           FALSE },
       
   193   { "static",          &handleStatic,           FALSE },
       
   194   { "pure",            &handlePure,             FALSE },
       
   195   { "private",         &handlePrivate,          FALSE },
       
   196   { "privatesection",  &handlePrivateSection,   FALSE },
       
   197   { "protected",       &handleProtected,        FALSE },
       
   198   { "protectedsection",&handleProtectedSection, FALSE },
       
   199   { "public",          &handlePublic,           FALSE },
       
   200   { "publicsection",   &handlePublicSection,    FALSE },
       
   201   { "inherit",         &handleInherit,          TRUE  },
       
   202   { "extends",         &handleExtends,          TRUE  },
       
   203   { "implements",      &handleExtends,          TRUE  },
       
   204   { "memberof",        &handleMemberOf,         TRUE  },
       
   205   { "arg",             0,                       TRUE  },
       
   206   { "attention",       0,                       TRUE  },
       
   207   { "author",          0,                       TRUE  },
       
   208   { "authors",         0,                       TRUE  },
       
   209   { "copydoc",         0,                       TRUE  },
       
   210   { "copybrief",       0,                       FALSE },
       
   211   { "copydetails",     0,                       TRUE  },
       
   212   { "date",            0,                       TRUE  },
       
   213   { "dotfile",         0,                       TRUE  },
       
   214   { "htmlinclude",     0,                       TRUE  },
       
   215   { "image",           0,                       TRUE  },
       
   216   { "include",         0,                       TRUE  },
       
   217   { "includelineno",   0,                       TRUE  },
       
   218   { "invariant",       0,                       TRUE  },
       
   219   { "li",              0,                       TRUE  },
       
   220   { "line",            0,                       TRUE  },
       
   221   { "note",            0,                       TRUE  },
       
   222   { "par",             0,                       TRUE  },
       
   223   { "param",           0,                       TRUE  },
       
   224   { "tparam",          0,                       TRUE  },
       
   225   { "post",            0,                       TRUE  },
       
   226   { "pre",             0,                       TRUE  },
       
   227   { "remark",          0,                       TRUE  },
       
   228   { "remarks",         0,                       TRUE  },
       
   229   { "result",          0,                       TRUE  },
       
   230   { "return",          0,                       TRUE  },
       
   231   { "returns",         0,                       TRUE  },
       
   232   { "retval",          0,                       TRUE  },
       
   233   { "sa",              0,                       TRUE  },
       
   234   { "see",             0,                       TRUE  },
       
   235   { "since",           0,                       TRUE  },
       
   236   { "throw",           0,                       TRUE  },
       
   237   { "throws",          0,                       TRUE  },
       
   238   { "until",           0,                       TRUE  },
       
   239   { "verbinclude",     0,                       TRUE  },
       
   240   { "version",         0,                       TRUE  },
       
   241   { "warning",         0,                       TRUE  },
       
   242   { 0, 0, FALSE }
       
   243 };
       
   244 
       
   245 /** @brief Command mapper.
       
   246  *
       
   247  *  Maps a command name (as found in a comment block) onto a
       
   248  *  specific handler function.
       
   249  */
       
   250 class DocCmdMapper
       
   251 {
       
   252   public:
       
   253     struct Cmd
       
   254     {
       
   255       DocCmdFunc func;
       
   256       bool endsBrief;
       
   257     };
       
   258 
       
   259     /** maps a command name to a handler function */
       
   260     static Cmd *map(const char *name)
       
   261     {
       
   262       return instance()->find(name);
       
   263     }
       
   264 
       
   265     /** release the singleton */
       
   266     static void freeInstance()
       
   267     {
       
   268       delete s_instance; s_instance=0;
       
   269     }
       
   270 
       
   271   private:
       
   272     static DocCmdMapper *instance()
       
   273     {
       
   274       if (s_instance==0) s_instance = new DocCmdMapper;
       
   275       return s_instance;
       
   276     }
       
   277 
       
   278     DocCmdMapper() : m_map(113)
       
   279     {
       
   280       m_map.setAutoDelete(TRUE);
       
   281       DocCmdMap *p = docCmdMap;
       
   282       while (p->cmdName)
       
   283       {
       
   284 	if (m_map.find(p->cmdName)!=0)
       
   285 	{
       
   286 	  printf("Error: DocCmdMapper: command %s already added\n",p->cmdName);
       
   287 	  exit(1);
       
   288 	}
       
   289 	Cmd *cmd = new Cmd;
       
   290 	cmd->func = p->handler;
       
   291 	cmd->endsBrief = p->endsBrief;
       
   292 	m_map.insert(p->cmdName,cmd);
       
   293 	p++;
       
   294       }
       
   295     }
       
   296 
       
   297     Cmd *find(const char *name)
       
   298     {
       
   299       return m_map.find(name);
       
   300     }
       
   301     QDict<Cmd> m_map;
       
   302     static DocCmdMapper *s_instance;
       
   303 };
       
   304 
       
   305 DocCmdMapper *DocCmdMapper::s_instance=0;
       
   306   
       
   307   
       
   308 #define YY_NEVER_INTERACTIVE 1
       
   309 
       
   310 enum XRefKind
       
   311 {
       
   312   XRef_Item,
       
   313   XRef_Todo,
       
   314   XRef_Test,
       
   315   XRef_Bug,
       
   316   XRef_Deprecated,
       
   317   XRef_None
       
   318 };
       
   319 
       
   320 enum OutputContext
       
   321 {
       
   322   OutputDoc,
       
   323   OutputBrief,
       
   324   OutputXRef,
       
   325   OutputInbody
       
   326 };
       
   327 
       
   328 enum GuardType
       
   329 {
       
   330   Guard_If,
       
   331   Guard_IfNot,
       
   332   Guard_Skip
       
   333 };
       
   334 
       
   335 class GuardedSection
       
   336 {
       
   337   public:
       
   338     GuardedSection(bool enabled,bool parentVisible) 
       
   339       : m_enabled(enabled),m_parentVisible(parentVisible) {}
       
   340     bool isEnabled() const { return m_enabled; }
       
   341     bool parentVisible() const { return m_parentVisible; }
       
   342   
       
   343   private:
       
   344     bool m_enabled;
       
   345     bool m_parentVisible;
       
   346 };
       
   347 
       
   348 void openGroup(Entry *e,const char *file,int line);
       
   349 void closeGroup(Entry *e,const char *file,int line);
       
   350 void initGroupInfo(Entry *e);
       
   351 static void groupAddDocs(Entry *e,const char *fileName);
       
   352 
       
   353 /* -----------------------------------------------------------------
       
   354  *
       
   355  *	statics
       
   356  */
       
   357 
       
   358 static ParserInterface *langParser;          // the language parser that is calling us
       
   359 static QCString         inputString;         // input string
       
   360 static int		inputPosition;       // read pointer
       
   361 static QCString		yyFileName;          // file name that is read from
       
   362 static int		yyLineNr;            // line number in the input
       
   363 static bool             inBody;              // was the comment found inside the body of a function?
       
   364 static OutputContext    inContext;           // are we inside the brief, details or xref part
       
   365 static bool             briefEndsAtDot;      // does the brief description stop at a dot?
       
   366 static QCString         formulaText;         // Running text of a formula
       
   367 static QCString         formulaEnv;          // environment name
       
   368 static int              formulaNewLines;     // amount of new lines in the formula
       
   369 static QCString        *pOutputString;       // pointer to string to which the output is appended.
       
   370 static QCString         outputXRef;          // temp argument of todo/test/../xrefitem commands
       
   371 static QCString         blockName;           // preformatted block name (e.g. verbatim, latexonly,...)
       
   372 static XRefKind         xrefKind;            // kind of cross-reference command
       
   373 static XRefKind         newXRefKind;         // 
       
   374 static GuardType        guardType;           // kind of guard for conditional section
       
   375 static bool             enabledSectionFound;
       
   376 static QCString         functionProto;       // function prototype
       
   377 static QStack<GuardedSection> guards;        // tracks nested conditional sections (if,ifnot,..)
       
   378 static Entry*		current      = 0 ;   // working entry
       
   379 //static Entry*		current_root = 0 ;   // parent of working entry
       
   380 
       
   381 
       
   382 //static Entry*		previous     = 0 ;   // TODO: remove need for this
       
   383 static bool             needNewEntry;
       
   384 
       
   385 static QCString         sectionLabel;
       
   386 static QCString		sectionTitle;
       
   387 static QCString         xrefItemKey;
       
   388 static QCString         newXRefItemKey;
       
   389 static QCString         xrefItemTitle;
       
   390 static QCString         xrefListTitle;
       
   391 static Protection	protection;
       
   392 
       
   393 static bool             xrefAppendFlag;
       
   394 static bool             inGroupParamFound;
       
   395 static int              braceCount;
       
   396 static bool             insidePre;
       
   397 static bool             parseMore;
       
   398 
       
   399 static int              g_commentCount;
       
   400 
       
   401 //-----------------------------------------------------------------------------
       
   402 
       
   403 static QStack<Grouping> g_autoGroupStack;
       
   404 static int              g_memberGroupId = DOX_NOGROUP;
       
   405 static QCString         g_memberGroupHeader;
       
   406 static QCString         g_memberGroupDocs;
       
   407 static QCString         g_memberGroupRelates;
       
   408 static QCString         g_compoundName;
       
   409 
       
   410 //-----------------------------------------------------------------------------
       
   411 
       
   412 static void initParser()
       
   413 {
       
   414   sectionLabel.resize(0);
       
   415   sectionTitle.resize(0);
       
   416   g_memberGroupHeader.resize(0);
       
   417 }
       
   418 
       
   419 //-----------------------------------------------------------------------------
       
   420 
       
   421 static QCString getDocSectionName(int s)
       
   422 {
       
   423   switch(s)
       
   424   {
       
   425     case Entry::CLASSDOC_SEC:       return "\\class";
       
   426     case Entry::STRUCTDOC_SEC:      return "\\struct";
       
   427     case Entry::UNIONDOC_SEC:       return "\\union";
       
   428     case Entry::EXCEPTIONDOC_SEC:   return "\\exception";
       
   429     case Entry::NAMESPACEDOC_SEC:   return "\\namespace";
       
   430     case Entry::PROTOCOLDOC_SEC:    return "\\protocol";
       
   431     case Entry::CATEGORYDOC_SEC:    return "\\category";
       
   432     case Entry::ENUMDOC_SEC:        return "\\enum";
       
   433     case Entry::PAGEDOC_SEC:        return "\\page";
       
   434     case Entry::MEMBERDOC_SEC:      return "\\fn";
       
   435     case Entry::OVERLOADDOC_SEC:    return "\\overload";
       
   436     case Entry::FILEDOC_SEC:        return "\\file";
       
   437     case Entry::DEFINEDOC_SEC:      return "\\def";
       
   438     case Entry::GROUPDOC_SEC:       return "\\defgroup";
       
   439     case Entry::MAINPAGEDOC_SEC:    return "\\mainpage";
       
   440     case Entry::PACKAGEDOC_SEC:     return "\\package";
       
   441     case Entry::DIRDOC_SEC:         return "\\dir";
       
   442     case Entry::EXAMPLE_SEC:        return "\\example";
       
   443     case Entry::MEMBERGRP_SEC:      return "\\name";
       
   444     default: return "";
       
   445   }
       
   446 }
       
   447 
       
   448 //-----------------------------------------------------------------------------
       
   449 
       
   450 static bool makeStructuralIndicator(Entry::Sections s)
       
   451 {
       
   452   if (!getDocSectionName(current->section).isEmpty())
       
   453   {
       
   454     return TRUE;
       
   455   }
       
   456   else
       
   457   {
       
   458     needNewEntry = TRUE;
       
   459     current->section = s;
       
   460     current->fileName = yyFileName;
       
   461     current->startLine = yyLineNr;
       
   462     return FALSE;
       
   463   }
       
   464 }
       
   465 
       
   466 static void lineCount()
       
   467 {
       
   468   for( const char* c = yytext ; *c ; ++c )
       
   469     yyLineNr += (*c == '\n') ;
       
   470 }
       
   471 
       
   472 
       
   473 static QCString stripQuotes(const char *s)
       
   474 {
       
   475   QCString name;
       
   476   if (s==0 || *s==0) return name;
       
   477   name=s;
       
   478   if (name.at(0)=='"' && name.at(name.length()-1)=='"')
       
   479   {
       
   480     name=name.mid(1,name.length()-2);
       
   481   }
       
   482   return name;
       
   483 }
       
   484 
       
   485 //-----------------------------------------------------------------
       
   486 
       
   487 static void addXRefItem(const char *listName,const char *itemTitle,
       
   488                         const char *listTitle,bool append)
       
   489 {
       
   490   Entry *docEntry = current; // inBody && previous ? previous : current;
       
   491   if (listName==0) return;
       
   492   //printf("addXRefItem(%s,%s,%s,%d)\n",listName,itemTitle,listTitle,append);
       
   493 
       
   494   ListItemInfo *lii=0;
       
   495   RefList *refList = Doxygen::xrefLists->find(listName);
       
   496   if (refList==0) // new list
       
   497   {
       
   498     refList = new RefList(listName,listTitle,itemTitle);
       
   499     Doxygen::xrefLists->insert(listName,refList);
       
   500     //printf("new list!\n");
       
   501   }
       
   502   if (docEntry->sli)
       
   503   {
       
   504     QListIterator<ListItemInfo> slii(*docEntry->sli);
       
   505     for (slii.toFirst();(lii=slii.current());++slii)
       
   506     {
       
   507       if (strcmp(lii->type,listName)==0) 
       
   508       {
       
   509         //printf("found %s lii->type=%s\n",listName,lii->type);
       
   510         break;
       
   511       }
       
   512     }
       
   513   }
       
   514   if (lii && append) // already found item of same type just before this one
       
   515   {
       
   516     //printf("listName=%s item id = %d existing\n",listName,lii->itemId);
       
   517     RefItem *item = refList->getRefItem(lii->itemId);
       
   518     ASSERT(item!=0);
       
   519     item->text += " <p>";
       
   520     item->text += outputXRef;
       
   521     //printf("%s: text +=%s\n",listName,item->text.data());
       
   522   }
       
   523   else // new item
       
   524   {
       
   525     int itemId  = refList->addRefItem();
       
   526     //printf("listName=%s item id = %d new current=%p\n",listName,itemId,current);
       
   527 
       
   528     // if we have already an item from the same list type (e.g. a second @todo)
       
   529     // in the same Entry (i.e. lii!=0) then we reuse its link anchor.
       
   530     char anchorLabel[1024];
       
   531     //sprintf(anchorLabel,"_%s%06d",listName,lii ? lii->itemId : itemId);
       
   532     sprintf(anchorLabel,"_%s%06d",listName,itemId);
       
   533     RefItem *item = refList->getRefItem(itemId);
       
   534     ASSERT(item!=0);
       
   535     item->text = outputXRef;
       
   536     item->listAnchor = anchorLabel;
       
   537     docEntry->addSpecialListItem(listName,itemId);
       
   538     QCString cmdString;
       
   539     cmdString.sprintf("\\xrefitem %s %d.",listName,itemId);
       
   540     if (inBody)
       
   541     {
       
   542       docEntry->inbodyDocs += cmdString;
       
   543     }
       
   544     else
       
   545     {
       
   546       docEntry->doc += cmdString;
       
   547     }
       
   548     SectionInfo *si=new SectionInfo(listName,anchorLabel,
       
   549 	                            sectionTitle,SectionInfo::Anchor);
       
   550     Doxygen::sectionDict.insert(anchorLabel,si);
       
   551     docEntry->anchors->append(si);
       
   552   }
       
   553   outputXRef.resize(0);
       
   554 }
       
   555 
       
   556 //-----------------------------------------------------------------------------
       
   557 
       
   558 // Adds a formula text to the list/dictionary of formulas if it was
       
   559 // not already added. Returns the label of the formula.
       
   560 static QCString addFormula()
       
   561 {
       
   562   QCString formLabel;
       
   563   QCString fText=formulaText.simplifyWhiteSpace();
       
   564   Formula *f=0;
       
   565   if ((f=Doxygen::formulaDict[fText])==0)
       
   566   {
       
   567     f = new Formula(fText);
       
   568     Doxygen::formulaList.append(f);
       
   569     Doxygen::formulaDict.insert(fText,f);
       
   570     formLabel.sprintf("\\form#%d",f->getId());
       
   571     Doxygen::formulaNameDict.insert(formLabel,f);
       
   572   }
       
   573   else
       
   574   {
       
   575     formLabel.sprintf("\\form#%d",f->getId());
       
   576   }
       
   577   int i;
       
   578   for (i=0;i<formulaNewLines;i++) formLabel+="\\_fakenl"; // add fake newlines to
       
   579                                                           // keep the warnings 
       
   580                                                           // correctly aligned.
       
   581   return formLabel;
       
   582 }
       
   583 
       
   584 //-----------------------------------------------------------------------------
       
   585 
       
   586 static void checkFormula();
       
   587 //-----------------------------------------------------------------------------
       
   588 
       
   589 static void addSection()
       
   590 {
       
   591   sectionTitle+=yytext;
       
   592   sectionTitle=sectionTitle.stripWhiteSpace();
       
   593   //printf("Adding new section file=%s label=%s title=%s\n",yyFileName,sectionLabel.data(),sectionTitle.data()); 
       
   594   SectionInfo *si = new SectionInfo(yyFileName,sectionLabel,sectionTitle,SectionInfo::Anchor);
       
   595   current->anchors->append(si);
       
   596   Doxygen::sectionDict.insert(yytext,si);
       
   597 }
       
   598 
       
   599 //-----------------------------------------------------------------------------
       
   600 
       
   601 // strip trailing whitespace (excluding newlines) from string s
       
   602 static void stripTrailingWhiteSpace(QCString &s)
       
   603 {
       
   604   uint len = s.length();
       
   605   int i = (int)len-1;
       
   606   char c;
       
   607   while (i>=0 && ((c = s.at(i))==' ' || c=='\t' || c=='\r')) i--;
       
   608   if (i!=(int)len-1) 
       
   609   {
       
   610     s.resize(i+2); // string upto and including char at pos i and \0 terminator
       
   611   }
       
   612 }
       
   613 
       
   614 // selects the output to write to
       
   615 static inline void setOutput(OutputContext ctx)
       
   616 {
       
   617   bool xrefAppendToPrev = xrefAppendFlag;
       
   618   // determine append flag for the next item (i.e. the end of this item)
       
   619   xrefAppendFlag = !inBody &&
       
   620                    inContext==OutputXRef && ctx==OutputXRef && // two consecutive xref items
       
   621                    newXRefKind==xrefKind &&                    // of the same kind
       
   622                    (xrefKind!=XRef_Item || 
       
   623 		    newXRefItemKey==xrefItemKey);              // with the same key if \xrefitem
       
   624   //printf("%d && %d && %d && (%d || %d)\n",
       
   625   //                 inContext==OutputXRef,
       
   626   //                 ctx==OutputXRef,
       
   627   //                 newXRefKind==xrefKind,
       
   628   //                 xrefKind!=XRef_Item,
       
   629   //	  	     newXRefItemKey==xrefItemKey);
       
   630       
       
   631   //printf("refKind=%d newXRefKind=%d xrefAppendToPrev=%d xrefAppendFlag=%d\n",
       
   632   //   	  xrefKind,newXRefKind,xrefAppendToPrev,xrefAppendFlag);
       
   633 
       
   634   //printf("setOutput(inContext=%d ctx=%d)\n",inContext,ctx);
       
   635   if (inContext==OutputXRef) // end of XRef section => add the item 
       
   636   {
       
   637     // See if we can append this new xref item to the previous one.
       
   638     // We know this at the start of the next item of the same
       
   639     // type and need to remember this until the end of that item.
       
   640     switch(xrefKind)
       
   641     {
       
   642       case XRef_Todo:
       
   643 	addXRefItem("todo",
       
   644 	            theTranslator->trTodo(),
       
   645 	            theTranslator->trTodoList(),
       
   646 		    xrefAppendToPrev
       
   647 		   );
       
   648 	break;
       
   649       case XRef_Test:
       
   650 	addXRefItem("test",
       
   651 	            theTranslator->trTest(),
       
   652 		    theTranslator->trTestList(),
       
   653 		    xrefAppendToPrev
       
   654 		   );
       
   655 	break;
       
   656       case XRef_Bug:
       
   657 	addXRefItem("bug",
       
   658 	            theTranslator->trBug(),
       
   659 		    theTranslator->trBugList(),
       
   660 		    xrefAppendToPrev
       
   661 		   );
       
   662 	break;
       
   663       case XRef_Deprecated:
       
   664 	addXRefItem("deprecated",
       
   665 	            theTranslator->trDeprecated(),
       
   666 		    theTranslator->trDeprecatedList(),
       
   667 		    xrefAppendToPrev
       
   668 		   );
       
   669 	break;
       
   670       case XRef_Item:  // user defined list
       
   671 	addXRefItem(xrefItemKey,
       
   672 	            xrefItemTitle,
       
   673 		    xrefListTitle,
       
   674 		    xrefAppendToPrev
       
   675 		   );
       
   676 	break;
       
   677       case XRef_None:
       
   678 	ASSERT(0);
       
   679 	break;
       
   680     }
       
   681   }
       
   682   xrefItemKey = newXRefItemKey;
       
   683 
       
   684   int oldContext = inContext;
       
   685   inContext = ctx;
       
   686   if (inContext!=OutputXRef && inBody) inContext=OutputInbody;
       
   687   switch(inContext)
       
   688   {
       
   689     case OutputDoc:
       
   690       if (oldContext!=inContext)
       
   691       {
       
   692         stripTrailingWhiteSpace(current->doc);
       
   693         if (current->docFile.isEmpty())
       
   694         {
       
   695           current->docFile = yyFileName;
       
   696           current->docLine = yyLineNr;
       
   697         }
       
   698       }
       
   699       pOutputString = &current->doc;
       
   700       break;
       
   701     case OutputBrief:
       
   702       if (oldContext!=inContext)
       
   703       {
       
   704 	if (current->briefFile.isEmpty())
       
   705 	{
       
   706 	  current->briefFile = yyFileName;
       
   707 	  current->briefLine = yyLineNr;
       
   708 	}
       
   709       }
       
   710       if (current->brief.stripWhiteSpace().isEmpty()) // we only want one brief
       
   711 	                                              // description even if multiple
       
   712 	                                              // are given...
       
   713       {
       
   714         pOutputString = &current->brief;
       
   715       }
       
   716       else
       
   717       {
       
   718         pOutputString = &current->doc;
       
   719       }
       
   720       break;
       
   721     case OutputXRef:
       
   722       pOutputString = &outputXRef;
       
   723       // first item found, so can't append to previous
       
   724       //xrefAppendFlag = FALSE;
       
   725       break;
       
   726     case OutputInbody:
       
   727       pOutputString = &current->inbodyDocs;
       
   728       break;
       
   729   }
       
   730 }
       
   731 
       
   732 // add a string to the output
       
   733 static inline void addOutput(const char *s)
       
   734 {
       
   735   *pOutputString+=s;
       
   736 }
       
   737 
       
   738 // add a character to the output
       
   739 static inline void addOutput(char c)
       
   740 {
       
   741   *pOutputString+=c;
       
   742 }
       
   743 
       
   744 static void endBrief(bool addToOutput=TRUE)
       
   745 {
       
   746   if (!current->brief.stripWhiteSpace().isEmpty())
       
   747   { // only go to the detailed description if we have
       
   748     // found some brief description and not just whitespace
       
   749     briefEndsAtDot=FALSE;
       
   750     setOutput(OutputDoc);
       
   751     if (addToOutput) addOutput(yytext);
       
   752   }
       
   753 }
       
   754 
       
   755 /* ----------------------------------------------------------------- */
       
   756 #undef	YY_INPUT
       
   757 #define	YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
       
   758 
       
   759 static int prevPosition=0;
       
   760 
       
   761 static int yyread(char *buf,int max_size)
       
   762 {
       
   763     prevPosition=inputPosition;
       
   764     int c=0;
       
   765     while( c < max_size && inputString[inputPosition] )
       
   766     {
       
   767 	*buf = inputString[inputPosition++] ;
       
   768 	//printf("%d (%c)\n",*buf,*buf);
       
   769 	c++; buf++;
       
   770     }
       
   771     return c;
       
   772 }
       
   773 
       
   774 %}
       
   775 
       
   776        /* start command character */
       
   777 CMD	  ("\\"|"@")
       
   778 DCMD1     ("arg"|"attention"|"author"|"code")
       
   779 DCMD2     ("date"|"dot"|"msc"|"dotfile"|"example")
       
   780 DCMD3     ("htmlinclude"|"htmlonly"|"image"|"include")
       
   781 DCMD4     ("includelineno"|"internal"|"invariant")
       
   782 DCMD5     ("latexonly"|"li"|"line"|"manonly"|"name") 
       
   783 DCMD6     ("note"|"par"|"paragraph"|"param"|"post")
       
   784 DCMD7     ("pre"|"remarks"|(("relate"[sd])("also")?))
       
   785 DCMD8     ("remarks"|("return"[s]?)|"retval"|"sa"|"section")
       
   786 DCMD9     ("see"|"since"|"subsection"|"subsubsection")
       
   787 DCMD10    ("throw"|"until"|"verbatim")
       
   788 DCMD11    ("verbinclude"|"version"|"warning")
       
   789 DETAILEDCMD {CMD}({DCMD1}|{DCMD2}|{DCMD3}|{DCMD4}|{DCMD5}|{DCMD6}|{DCMD7}|{DCMD8}|{DCMD9}|{DCMD10}|{DCMD11})
       
   790 XREFCMD   {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem")  
       
   791 PRE       [pP][rR][eE]
       
   792 TABLE	  [tT][aA][bB][lL][eE]
       
   793 P	  [pP]
       
   794 UL        [uU][lL]
       
   795 OL	  [oO][lL]
       
   796 DL	  [dD][lL]
       
   797 IMG       [iI][mM][gG]
       
   798 HR        [hH][rR]
       
   799 DETAILEDHTML {PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}
       
   800 BN        [ \t\n\r]
       
   801 BL        [ \t\r]*"\n" 
       
   802 B         [ \t]
       
   803 BS        ^(({B}*"//")?)(({B}*"*"+)?){B}*
       
   804 ATTR      ({B}+[^>\n]*)?
       
   805 DOCNL     "\n"|"\\_linebr"
       
   806 LC        "\\"{B}*"\n"
       
   807 NW	  [^a-z_A-Z0-9]
       
   808 FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+]
       
   809 FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+]
       
   810 FILE      ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"")
       
   811 ID        "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
       
   812 LABELID   [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
       
   813 SCOPEID   {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
       
   814 SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID})
       
   815 MAILADR   [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ 
       
   816 RCSTAG    "$"{ID}":"[^\n$]+"$"
       
   817 
       
   818 %option noyywrap
       
   819 
       
   820   /* comment parsing states. */
       
   821 %x      Comment
       
   822 %x      PageDocArg1
       
   823 %x      PageDocArg2
       
   824 %x      RelatesParam1
       
   825 %x      ClassDocArg1
       
   826 %x      ClassDocArg2
       
   827 %x      ClassDocArg3
       
   828 %x      CategoryDocArg1
       
   829 %x      XRefItemParam1
       
   830 %x      XRefItemParam2
       
   831 %x      XRefItemParam3
       
   832 %x      FileDocArg1
       
   833 %x	EnumDocArg1
       
   834 %x	NameSpaceDocArg1
       
   835 %x	PackageDocArg1
       
   836 %x	GroupDocArg1
       
   837 %x	GroupDocArg2
       
   838 %x	SectionLabel
       
   839 %x	SectionTitle
       
   840 %x	SubpageLabel
       
   841 %x	SubpageTitle
       
   842 %x	FormatBlock
       
   843 %x	LineParam
       
   844 %x	GuardParam
       
   845 %x	SkipGuardedSection
       
   846 %x	SkipInternal
       
   847 %x      NameParam
       
   848 %x	InGroupParam
       
   849 %x	FnParam
       
   850 %x	OverloadParam
       
   851 %x	InheritParam
       
   852 %x	ExtendsParam
       
   853 %x      ReadFormulaShort
       
   854 %x	ReadFormulaLong
       
   855 %x	AnchorLabel
       
   856 %x      HtmlComment
       
   857 %x      SkipLang
       
   858 
       
   859 %%
       
   860 
       
   861   /* What can happen in while parsing a comment block:
       
   862    *   commands (e.g. @page, or \page)
       
   863    *   escaped commands (e.g. @@page or \\page).
       
   864    *   formulas (e.g. \f$ \f[ \f{..)
       
   865    *   directories (e.g. \doxygen\src\)
       
   866    *   autolist end. (e.g. a dot on an otherwise empty line)
       
   867    *   newlines.
       
   868    *   end of brief description due to blank line.
       
   869    *   end of brief description due to some command (@command, or <command>).
       
   870    *   words and whitespace and other characters (#,?!, etc).
       
   871    *   grouping commands (e.g. @{ and @})
       
   872    *   language switch (e.g. \~english or \~).
       
   873    *   mail adress (e.g. dimitri@stack.nl).
       
   874    *   quoted text, such as "foo@bar"
       
   875    *   XML commands, <summary></summary><remarks></remarks>
       
   876    */
       
   877 
       
   878 <Comment>{CMD}{CMD}[a-z_A-Z]+{B}*	{ // escaped command
       
   879   					  addOutput(yytext);
       
   880   					}
       
   881 <Comment>{CMD}{CMD}"~"[a-z_A-Z]*	{ // escaped command
       
   882   					  addOutput(yytext);
       
   883   					}
       
   884 <Comment>{MAILADR}			{ // mail adress
       
   885   					  addOutput(yytext);
       
   886   					}
       
   887 <Comment>"\""[^"\n]*"\""		{ // quoted text
       
   888                                           addOutput(yytext);
       
   889   					}
       
   890 <Comment>("\\"[a-z_A-Z]+)+"\\"		{ // directory (or chain of commands!)
       
   891   					  addOutput(yytext);
       
   892   					}
       
   893 <Comment>{XREFCMD}/[^a-z_A-Z]*		{ // xref command 
       
   894 					  if (inContext!=OutputXRef) 
       
   895 					  {
       
   896 					    briefEndsAtDot=FALSE;
       
   897 					    setOutput(OutputDoc);
       
   898 					  }
       
   899 					  // continue with the same input
       
   900                                           REJECT;
       
   901 					}
       
   902    /*
       
   903 <Comment>{DETAILEDCMD}/[^a-z_A-Z]*	{ // command that can end a brief description
       
   904 				          briefEndsAtDot=FALSE;
       
   905 				          setOutput(OutputDoc);
       
   906 					  // continue with the same input
       
   907                                           REJECT;
       
   908 					}
       
   909    */
       
   910 <Comment>"<"{DETAILEDHTML}{ATTR}">"	{ // HTML command that ends a brief description
       
   911 					  setOutput(OutputDoc);
       
   912 					  // continue with the same input
       
   913                                           REJECT;
       
   914 					}
       
   915 <Comment>"<summary>"			{ // start of a .NET XML style brief description
       
   916 					  setOutput(OutputBrief);
       
   917   					}
       
   918 <Comment>"<remarks>"|"</summary>"	{ // start of a .NET XML style detailed description
       
   919 					  setOutput(OutputDoc);
       
   920   					}
       
   921 <Comment>"</remarks>"			{ // end of a brief or detailed description
       
   922   					}
       
   923 <Comment>{RCSTAG}			{ // RCS tag which end a brief description
       
   924   					  setOutput(OutputDoc);
       
   925 					  REJECT;
       
   926   					}
       
   927 <Comment>"<!--"				{ 
       
   928   					  BEGIN(HtmlComment);
       
   929 					}
       
   930 <Comment>{CMD}[a-z_A-Z]+{B}*		{ // potentially interesting command
       
   931   					  QCString cmdName = QCString(&yytext[1]).stripWhiteSpace();
       
   932 					  DocCmdMapper::Cmd *cmdPtr = DocCmdMapper::map(cmdName);
       
   933 					  if (cmdPtr) // special action is required
       
   934 					  {
       
   935 					    if (cmdPtr->endsBrief)
       
   936 					    { 
       
   937 					      briefEndsAtDot=FALSE;
       
   938 					      // this command forces the end of brief description
       
   939 					      setOutput(OutputDoc);
       
   940 					    }
       
   941 					    if (cmdPtr->func && cmdPtr->func(cmdName))
       
   942 					    {
       
   943 					      // implicit split of the comment block into two
       
   944 					      // entries. Restart the next block at the start
       
   945 					      // of this command.
       
   946 					      parseMore=TRUE;
       
   947 
       
   948 					      // yuk, this is probably not very portable across lex implementations, 
       
   949 					      // but we need to know the position in the input buffer where this 
       
   950 					      // rule matched.
       
   951 					      // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE
       
   952 #if YY_FLEX_MINOR_VERSION>=5 && YY_FLEX_SUBMINOR_VERSION>=33
       
   953 					      inputPosition=prevPosition + yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
       
   954 #else
       
   955 					      inputPosition=prevPosition + yy_bp - yy_current_buffer->yy_ch_buf;
       
   956 #endif
       
   957 					      yyterminate();
       
   958 					    }
       
   959 					    else if (cmdPtr->func==0)
       
   960 					    {
       
   961 					      // command without handler, to be processed
       
   962 					      // later by parsedoc.cpp
       
   963 					      addOutput(yytext);
       
   964 					    }
       
   965 					  }
       
   966 					  else // command not relevant
       
   967 					  {
       
   968 					    addOutput(yytext);
       
   969 					  }
       
   970   					}
       
   971 <Comment>("\\\\"|"@@")"f"[$\[{]		{ // escaped formula command
       
   972   					  addOutput(yytext);
       
   973   					}
       
   974 <Comment>{CMD}"~"[a-z_A-Z]*		{ // language switch command
       
   975                                           QCString langId = &yytext[2];
       
   976 			       	          if (!langId.isEmpty() &&
       
   977 					      stricmp(Config_getEnum("OUTPUT_LANGUAGE"),langId)!=0)
       
   978 				          { // enable language specific section
       
   979 				            BEGIN(SkipLang);
       
   980 				          }
       
   981   					}
       
   982 <Comment>{CMD}"f{"[^}\n]+"}"("{"?)      { // start of a formula with custom environment
       
   983 					  formulaText="\\begin";
       
   984 					  formulaEnv=&yytext[2];
       
   985 					  if (formulaEnv.at(formulaEnv.length()-1)=='{')
       
   986 					  {
       
   987 					    // remove trailing open brace
       
   988 					    formulaEnv=formulaEnv.left(formulaEnv.length()-1);
       
   989 					  }
       
   990 					  formulaText+=formulaEnv;
       
   991 					  formulaNewLines=0;
       
   992 					  BEGIN(ReadFormulaLong);
       
   993   					}
       
   994 <Comment>{CMD}"f$"			{ // start of a inline formula
       
   995 					  formulaText="$";
       
   996 					  formulaNewLines=0;
       
   997 					  BEGIN(ReadFormulaShort);
       
   998   					}
       
   999 <Comment>{CMD}"f["			{ // start of a block formula
       
  1000 					  formulaText="\\[";
       
  1001 					  formulaNewLines=0;
       
  1002 					  BEGIN(ReadFormulaLong);
       
  1003   					}
       
  1004 <Comment>{CMD}"{"                       { // begin of a group
       
  1005                                           //langParser->handleGroupStartCommand(g_memberGroupHeader);
       
  1006                                           openGroup(current,yyFileName,yyLineNr);
       
  1007                                         }
       
  1008 <Comment>{CMD}"}"                       { // end of a group
       
  1009                                           //langParser->handleGroupEndCommand();
       
  1010                                           closeGroup(current,yyFileName,yyLineNr);
       
  1011                                           g_memberGroupHeader.resize(0);
       
  1012                                         }
       
  1013 <Comment>{CMD}[$@\\&~<>#%]		{ // escaped character
       
  1014   					  addOutput(yytext);
       
  1015   					}
       
  1016 <Comment>[a-z_A-Z]+			{ // normal word
       
  1017 					  addOutput(yytext);
       
  1018   					}
       
  1019 <Comment>^{B}*"."{B}*/\n                { // explicit end autolist: e.g "  ."
       
  1020   				          addOutput(yytext); 
       
  1021 					}
       
  1022 <Comment>("."+)[a-z_A-Z0-9]		{ // . at start or in the middle of a word, or ellipsis
       
  1023   					  addOutput(yytext);
       
  1024   					}
       
  1025 <Comment>".\\"[ \t]			{ // . with escaped space.
       
  1026   					  addOutput(yytext[0]);
       
  1027   					  addOutput(yytext[2]);
       
  1028   					}
       
  1029 <Comment>".,"				{ // . with comma such as "e.g.," 
       
  1030   					  addOutput(yytext);
       
  1031   					}
       
  1032 <Comment>(\n|\\_linebr)({B}*(\n|\\_linebr))+	{ // at least one blank line (or blank line command)
       
  1033   					  if (inContext!=OutputBrief)
       
  1034 					  {
       
  1035   					    addOutput("\n\n");
       
  1036 					    setOutput(OutputDoc);
       
  1037 					  }
       
  1038 					  else 
       
  1039 					  { // only go to the detailed description if we have
       
  1040 					    // found some brief description and not just whitespace
       
  1041 					    endBrief(FALSE);
       
  1042 					  }
       
  1043   					  lineCount();
       
  1044   					}
       
  1045 <Comment>"."				{ // potential end of a JavaDoc style comment
       
  1046   					  addOutput(*yytext);
       
  1047   					  if (briefEndsAtDot)
       
  1048 					  {
       
  1049 					    setOutput(OutputDoc);
       
  1050 					    briefEndsAtDot=FALSE;
       
  1051 					  }
       
  1052   					}
       
  1053 <Comment>\n				{ // newline
       
  1054   					  addOutput(*yytext);
       
  1055   					  yyLineNr++;
       
  1056   					}
       
  1057 <Comment>.				{ // catch-all for anything else
       
  1058   					  addOutput(*yytext);
       
  1059   					}
       
  1060 
       
  1061 
       
  1062  /* --------------   Rules for handling HTML comments ----------- */
       
  1063 
       
  1064 <HtmlComment>"--"[!]?">"{B}*		{ BEGIN( Comment ); }
       
  1065 <HtmlComment>{DOCNL}			{ 
       
  1066   					  if (*yytext=='\n') yyLineNr++;
       
  1067   					}
       
  1068 <HtmlComment>[^\\\n\-]+			{ // ignore unimportant characters
       
  1069   					}
       
  1070 <HtmlComment>.				{ // ignore every else
       
  1071   					}
       
  1072 
       
  1073  /* --------------   Rules for handling formulas ---------------- */
       
  1074  
       
  1075 <ReadFormulaShort>{CMD}"f$"		{ // end of inline formula
       
  1076   					  formulaText+="$";
       
  1077 					  addOutput(addFormula());
       
  1078 					  BEGIN(Comment);
       
  1079   					}
       
  1080 <ReadFormulaLong>{CMD}"f]"		{ // end of block formula
       
  1081 					  formulaText+="\\]";
       
  1082 					  addOutput(addFormula());
       
  1083 					  BEGIN(Comment);
       
  1084   					}
       
  1085 <ReadFormulaLong>{CMD}"f}"		{ // end of custom env formula
       
  1086 					  formulaText+="\\end";
       
  1087 					  formulaText+=formulaEnv;
       
  1088 					  addOutput(addFormula());
       
  1089 					  BEGIN(Comment);
       
  1090   					}
       
  1091 <ReadFormulaLong,ReadFormulaShort>[^\\@\n]+ { // any non-special character
       
  1092                                           formulaText+=yytext; 
       
  1093  					} 
       
  1094 <ReadFormulaLong,ReadFormulaShort>\n	{ // new line
       
  1095                                           formulaNewLines++;
       
  1096                                           formulaText+=*yytext; 
       
  1097 					  yyLineNr++; 
       
  1098 					}
       
  1099 <ReadFormulaLong,ReadFormulaShort>.     { // any othe character
       
  1100                                           formulaText+=*yytext; 
       
  1101 					}
       
  1102 
       
  1103   /* ------------ handle argument of enum command --------------- */
       
  1104 
       
  1105 <EnumDocArg1>{SCOPEID}			{ // handle argument
       
  1106   					  current->name = yytext;
       
  1107 					  BEGIN( Comment );
       
  1108   					}
       
  1109 <EnumDocArg1>{LC}			{ // line continuation
       
  1110   					  yyLineNr++;
       
  1111 					  addOutput('\n');
       
  1112                                         }
       
  1113 <EnumDocArg1>{DOCNL}			{ // missing argument
       
  1114   					  warn(yyFileName,yyLineNr,
       
  1115                                                "Warning: missing argument after \\enum."
       
  1116                                               );
       
  1117 					  addOutput('\n');
       
  1118   					  if (*yytext=='\n') yyLineNr++;
       
  1119 					  BEGIN( Comment );
       
  1120   					}
       
  1121 <EnumDocArg1>.				{ // ignore other stuff
       
  1122   					}
       
  1123 
       
  1124   /* ------------ handle argument of namespace command --------------- */
       
  1125 
       
  1126 <NameSpaceDocArg1>{SCOPENAME}		{ // handle argument
       
  1127   					  current->name = substitute(yytext,".","::");
       
  1128 					  BEGIN( Comment );
       
  1129   					}
       
  1130 <NameSpaceDocArg1>{LC}			{ // line continuation
       
  1131                                           yyLineNr++; 
       
  1132 					  addOutput('\n');
       
  1133                                         }
       
  1134 <NameSpaceDocArg1>{DOCNL}		{ // missing argument
       
  1135   					  warn(yyFileName,yyLineNr,
       
  1136                                                "Warning: missing argument after "
       
  1137 					       "\\namespace."
       
  1138                                               );
       
  1139 					  addOutput('\n');
       
  1140   					  if (*yytext=='\n') yyLineNr++;
       
  1141 					  BEGIN( Comment );
       
  1142   					}
       
  1143 <NameSpaceDocArg1>.			{ // ignore other stuff
       
  1144   					}
       
  1145 
       
  1146   /* ------------ handle argument of package command --------------- */
       
  1147 
       
  1148 <PackageDocArg1>{ID}("."{ID})*		{ // handle argument
       
  1149   					  current->name = yytext;
       
  1150 					  BEGIN( Comment );
       
  1151   					}
       
  1152 <PackageDocArg1>{LC}			{ // line continuation 
       
  1153                                           yyLineNr++; 
       
  1154 					  addOutput('\n');
       
  1155                                         }
       
  1156 <PackageDocArg1>{DOCNL}			{ // missing argument
       
  1157   					  warn(yyFileName,yyLineNr,
       
  1158                                                "Warning: missing argument after "
       
  1159 					       "\\package."
       
  1160                                               );
       
  1161 					  addOutput('\n');
       
  1162   					  if (*yytext=='\n') yyLineNr++;
       
  1163 					  BEGIN( Comment );
       
  1164   					}
       
  1165 <PackageDocArg1>.			{ // ignore other stuff
       
  1166   					}
       
  1167 
       
  1168   /* ------ handle argument of class/struct/union command --------------- */
       
  1169 
       
  1170 <ClassDocArg1>{SCOPENAME}		{ // first argument
       
  1171   					  current->name = substitute(yytext,".","::");
       
  1172 					  if (current->section==Entry::PROTOCOLDOC_SEC)
       
  1173 					  {
       
  1174 					    current->name+="-p";
       
  1175 					  }
       
  1176 					  // prepend outer scope name 
       
  1177 					  BEGIN( ClassDocArg2 );
       
  1178 					}
       
  1179 <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" {
       
  1180   					  current->name = substitute(yytext,".","::");
       
  1181 					  BEGIN( ClassDocArg2 );
       
  1182    					}
       
  1183 <ClassDocArg1,CategoryDocArg1>{LC}      { // line continuation
       
  1184                                           yyLineNr++; 
       
  1185 					  addOutput('\n');
       
  1186                                         }
       
  1187 <ClassDocArg1,CategoryDocArg1>{DOCNL}	{
       
  1188   					  warn(yyFileName,yyLineNr,
       
  1189                                                "Warning: missing argument after "
       
  1190 					       "\\%s.",YY_START==ClassDocArg1?"class":"category"
       
  1191                                               );
       
  1192 					  addOutput('\n');
       
  1193   					  if (*yytext=='\n') yyLineNr++;
       
  1194 					  BEGIN( Comment );
       
  1195   					}
       
  1196 <ClassDocArg1,CategoryDocArg1>.		{ // ignore other stuff
       
  1197   					}
       
  1198 
       
  1199 <ClassDocArg2>{FILE}|"<>"		{ // second argument; include file
       
  1200 					  current->includeFile = yytext;
       
  1201 					  BEGIN( ClassDocArg3 );
       
  1202 					}
       
  1203 <ClassDocArg2>{LC}			{ // line continuation
       
  1204                                           yyLineNr++; 
       
  1205 					  addOutput('\n');
       
  1206                                         }
       
  1207 <ClassDocArg2>{DOCNL}			{ 
       
  1208 					  addOutput('\n');
       
  1209   					  if (*yytext=='\n') yyLineNr++;
       
  1210 					  BEGIN( Comment );
       
  1211 					}
       
  1212 <ClassDocArg2>.				{ // ignore other stuff
       
  1213   					}
       
  1214 
       
  1215 <ClassDocArg3>[<]?{FILE}?[>]?		{ // third argument; include file name
       
  1216  					  current->includeName = yytext;
       
  1217 					  BEGIN( Comment );
       
  1218 					}
       
  1219 <ClassDocArg3>{LC}			{ // line continuation
       
  1220                                           yyLineNr++;
       
  1221 					  addOutput('\n');
       
  1222                                         }
       
  1223 <ClassDocArg3>{DOCNL}			{ 
       
  1224   					  if (*yytext=='\n') yyLineNr++;
       
  1225   					  BEGIN( Comment );
       
  1226 					}
       
  1227 <ClassDocArg3>.				{ // ignore other stuff
       
  1228   					}
       
  1229 
       
  1230   /* --------- handle arguments of {def,add,weak}group commands --------- */
       
  1231 
       
  1232 <GroupDocArg1>{ID}(".html"?)		{ // group name
       
  1233   					  current->name = yytext;
       
  1234 					  //lastDefGroup.groupname = yytext;
       
  1235 					  //lastDefGroup.pri = current->groupingPri();
       
  1236   					  // the .html stuff is for Qt compatibility
       
  1237 					  if (current->name.right(5)==".html") 
       
  1238 					  {
       
  1239 					    current->name=current->name.left(current->name.length()-5);
       
  1240 					  }
       
  1241 					  current->type.resize(0);
       
  1242 					  BEGIN(GroupDocArg2);
       
  1243   					}
       
  1244 <GroupDocArg1>"\\"{B}*"\n"		{ // line continuation
       
  1245   					  yyLineNr++; 
       
  1246 					  addOutput('\n');
       
  1247                                         }
       
  1248 <GroupDocArg1>{DOCNL}			{ // missing argument!
       
  1249   					  warn(yyFileName,yyLineNr,
       
  1250                                                "Warning: missing group name after %s",
       
  1251 					       current->groupDocCmd()
       
  1252                                               );
       
  1253 					  addOutput('\n');
       
  1254   					  if (*yytext=='\n') yyLineNr++;
       
  1255 					  BEGIN( Comment );
       
  1256   					}
       
  1257 <GroupDocArg2>"\\"{B}*"\n"		{ // line continuation
       
  1258   					  yyLineNr++; 
       
  1259 					  addOutput('\n');
       
  1260                                         }
       
  1261 <GroupDocArg2>[^\n\\\*]+		{ // title (stored in type)
       
  1262 					  current->type += yytext;
       
  1263 					  current->type = current->type.stripWhiteSpace();
       
  1264   					}
       
  1265 <GroupDocArg2>{DOCNL}			{
       
  1266                                           if ( current->groupDocType==Entry::GROUPDOC_NORMAL &&
       
  1267                                                current->type.isEmpty() 
       
  1268 					     ) // defgroup requires second argument
       
  1269 					  {
       
  1270   					    warn(yyFileName,yyLineNr,
       
  1271                                                  "Warning: missing title after "
       
  1272 					         "\\defgroup %s", current->name.data()
       
  1273                                                 );
       
  1274 					  }
       
  1275   					  if (*yytext=='\n') yyLineNr++; 
       
  1276 					  addOutput('\n');
       
  1277 					  BEGIN( Comment );
       
  1278   					}
       
  1279 
       
  1280   /* --------- handle arguments of page/mainpage command ------------------- */
       
  1281 
       
  1282 <PageDocArg1>{FILE}			{ // first argument; page name
       
  1283 					  current->name = stripQuotes(yytext);
       
  1284 					  BEGIN( PageDocArg2 ); 
       
  1285 					}
       
  1286 <PageDocArg1>{LC}			{ yyLineNr++; 
       
  1287 					  addOutput('\n');
       
  1288                                         }
       
  1289 <PageDocArg1>{DOCNL}			{
       
  1290   					  warn(yyFileName,yyLineNr,
       
  1291                                                "Warning: missing argument after "
       
  1292 					       "\\page."
       
  1293                                               );
       
  1294   					  if (*yytext=='\n') yyLineNr++;
       
  1295 					  addOutput('\n');
       
  1296 					  BEGIN( Comment );
       
  1297   					}
       
  1298 <PageDocArg1>.				{ // ignore other stuff
       
  1299   					}
       
  1300 <PageDocArg2>.*"\n"			{ // second argument; page title
       
  1301   				          yyLineNr++;
       
  1302 					  current->args = yytext;
       
  1303 					  addOutput('\n');
       
  1304 					  BEGIN( Comment );
       
  1305 					}
       
  1306 
       
  1307   /* --------- handle arguments of the file/dir/example command ------------ */
       
  1308 
       
  1309 <FileDocArg1>{DOCNL}			{ // no file name specfied
       
  1310   					  if (*yytext=='\n') yyLineNr++;
       
  1311 					  addOutput('\n');
       
  1312 					  BEGIN( Comment );
       
  1313 					}
       
  1314 <FileDocArg1>{FILE}			{ // first argument; name
       
  1315   					  current->name = stripQuotes(yytext);
       
  1316 					  BEGIN( Comment );
       
  1317   				        }
       
  1318 <FileDocArg1>{LC}			{ yyLineNr++; 
       
  1319 					  addOutput('\n');
       
  1320                                         }
       
  1321 <FileDocArg1>.				{ // ignore other stuff
       
  1322   					}
       
  1323 
       
  1324   /* --------- handle arguments of the xrefitem command ------------ */
       
  1325 
       
  1326 <XRefItemParam1>{ID}			{ // first argument
       
  1327   					  newXRefItemKey=yytext;
       
  1328                                           setOutput(OutputXRef);
       
  1329 					  BEGIN(XRefItemParam2);
       
  1330 					}
       
  1331 <XRefItemParam1>{LC}			{ // line continuation
       
  1332                                           yyLineNr++; 
       
  1333 					  addOutput('\n');
       
  1334                                         }
       
  1335 <XRefItemParam1>{DOCNL}			{ // missing arguments
       
  1336   					  warn(yyFileName,yyLineNr,
       
  1337 					       "Warning: Missing first argument of \\xrefitem"
       
  1338 					      );
       
  1339   					  if (*yytext=='\n') yyLineNr++;
       
  1340 					  addOutput('\n');
       
  1341 					  inContext = OutputDoc;
       
  1342 					  BEGIN( Comment );
       
  1343   					}
       
  1344 <XRefItemParam1>.			{ // ignore other stuff 
       
  1345   					}
       
  1346 
       
  1347 <XRefItemParam2>"\""[^\n\"]*"\""	{ // second argument
       
  1348   					  xrefItemTitle = stripQuotes(yytext);
       
  1349 					  BEGIN(XRefItemParam3);
       
  1350   					}
       
  1351 <XRefItemParam2>{LC}			{ // line continuation
       
  1352                                           yyLineNr++; 
       
  1353 					  addOutput('\n');
       
  1354   					}
       
  1355 <XRefItemParam2>{DOCNL}			{ // missing argument
       
  1356   					  warn(yyFileName,yyLineNr,
       
  1357 					      "Warning: Missing second argument of \\xrefitem"
       
  1358 					      );
       
  1359   					  if (*yytext=='\n') yyLineNr++;
       
  1360 					  addOutput('\n');
       
  1361 					  inContext = OutputDoc;
       
  1362 					  BEGIN( Comment );
       
  1363   					}
       
  1364 <XRefItemParam2>.			{ // ignore other stuff
       
  1365   					}
       
  1366 
       
  1367 <XRefItemParam3>"\""[^\n\"]*"\""	{ // third argument
       
  1368   					  xrefListTitle = stripQuotes(yytext);
       
  1369                                           xrefKind = XRef_Item;
       
  1370 					  BEGIN( Comment );
       
  1371   					}
       
  1372 <XRefItemParam2,XRefItemParam3>{LC}	{ // line continuation
       
  1373                                           yyLineNr++; 
       
  1374 					  addOutput('\n');
       
  1375   					}
       
  1376 <XRefItemParam3>{DOCNL}			{ // missing argument
       
  1377   					  warn(yyFileName,yyLineNr,
       
  1378 					      "Warning: Missing third argument of \\xrefitem"
       
  1379 					      );
       
  1380   					  if (*yytext=='\n') yyLineNr++;
       
  1381 					  addOutput('\n');
       
  1382 					  inContext = OutputDoc;
       
  1383 					  BEGIN( Comment );
       
  1384   					}
       
  1385 <XRefItemParam3>.			{ // ignore other stuff
       
  1386   					}
       
  1387 
       
  1388 
       
  1389   /* ----- handle arguments of the relates(also)/memberof command ------- */
       
  1390 
       
  1391 <RelatesParam1>({ID}("::"|"."))*{ID}	{ // argument
       
  1392   					  current->relates = yytext;
       
  1393                                           //if (current->mGrpId!=DOX_NOGROUP) 
       
  1394                                           //{
       
  1395                                           //  memberGroupRelates = yytext;
       
  1396                                           //}
       
  1397 					  BEGIN( Comment );
       
  1398 					}
       
  1399 <RelatesParam1>{LC}			{ // line continuation
       
  1400                                           yyLineNr++; 
       
  1401 					  addOutput('\n');
       
  1402   					}
       
  1403 <RelatesParam1>{DOCNL}			{ // missing argument
       
  1404   					  warn(yyFileName,yyLineNr,
       
  1405 					      "Warning: Missing argument of \\relates or \\memberof command"
       
  1406 					      );
       
  1407   					  if (*yytext=='\n') yyLineNr++;
       
  1408 					  addOutput('\n');
       
  1409 					  BEGIN( Comment );
       
  1410   					}
       
  1411 <RelatesParam1>.			{ // ignore other stuff
       
  1412   					}
       
  1413 
       
  1414 
       
  1415   /* ----- handle arguments of the relates(also)/addindex commands ----- */
       
  1416 
       
  1417 <LineParam>{DOCNL}			{ // end of argument
       
  1418   					  if (*yytext=='\n') yyLineNr++;
       
  1419 					  addOutput('\n');
       
  1420 					  BEGIN( Comment );
       
  1421   					}
       
  1422 <LineParam>{LC}				{ // line continuation
       
  1423                                           yyLineNr++; 
       
  1424 					  addOutput('\n');
       
  1425   					}
       
  1426 <LineParam>.				{ // ignore other stuff
       
  1427   					  addOutput(*yytext);
       
  1428   					}
       
  1429 
       
  1430   /* ----- handle arguments of the section/subsection/.. commands ------- */
       
  1431 
       
  1432 <SectionLabel>{LABELID}			{ // first argyment
       
  1433   					  sectionLabel=yytext;
       
  1434                                           addOutput(yytext);
       
  1435 					  sectionTitle.resize(0);
       
  1436 					  BEGIN(SectionTitle);
       
  1437   					}
       
  1438 <SectionLabel>{DOCNL}			{ // missing argument
       
  1439   					  warn(yyFileName,yyLineNr,
       
  1440 					      "Warning: \\section command has no label"
       
  1441 					      );
       
  1442   					  if (*yytext=='\n') yyLineNr++;
       
  1443 					  addOutput('\n');
       
  1444 					  BEGIN( Comment );
       
  1445   					}
       
  1446 <SectionLabel>.				{ // invalid character for section label
       
  1447   					  warn(yyFileName,yyLineNr,
       
  1448 					      "Warning: Invalid or missing section label"
       
  1449 					      );
       
  1450 					  BEGIN(Comment);
       
  1451   					}
       
  1452 
       
  1453 <SectionTitle>[^\n@\\*]*/"\n"            { // end of section title
       
  1454   					  addSection();
       
  1455                                           addOutput(yytext);
       
  1456 					  BEGIN( Comment );
       
  1457   					}
       
  1458 <SectionTitle>[^\n@\\]*/"\\_linebr"     { // end of section title
       
  1459   					  addSection();
       
  1460                                           addOutput(yytext);
       
  1461 					  BEGIN( Comment );
       
  1462   					}
       
  1463 <SectionTitle>{LC}			{ // line continuation
       
  1464                                           yyLineNr++; 
       
  1465 					  addOutput('\n');
       
  1466   					}
       
  1467 <SectionTitle>[^\n@\\]*			{ // any character without special meaning
       
  1468   					  sectionTitle+=yytext;
       
  1469 					  addOutput(yytext);
       
  1470   					}
       
  1471 <SectionTitle>("\\\\"|"@@"){ID}		{ // unescape escaped command
       
  1472   					  sectionTitle+=&yytext[1];
       
  1473 					  addOutput(yytext);
       
  1474   					}
       
  1475 <SectionTitle>{CMD}[$@\\&~<>#%]		{ // unescape escaped character
       
  1476   					  sectionTitle+=yytext[1];
       
  1477   					  addOutput(yytext);
       
  1478   					}
       
  1479 <SectionTitle>.				{ // anything else
       
  1480   					  sectionTitle+=yytext;
       
  1481 					  addOutput(*yytext);
       
  1482   					}
       
  1483 
       
  1484   /* ----- handle arguments of the subpage command ------- */
       
  1485 
       
  1486 <SubpageLabel>{LABELID}			{ // first argument
       
  1487                                           addOutput(yytext);
       
  1488 					  // we add subpage labels as a kind of "inheritance" relation to prevent
       
  1489 					  // needing to add another list to the Entry class.
       
  1490 					  current->extends->append(new BaseInfo(yytext,Public,Normal));
       
  1491 					  BEGIN(SubpageTitle);
       
  1492   					}
       
  1493 <SubpageLabel>{DOCNL}			{ // missing argument
       
  1494   					  warn(yyFileName,yyLineNr,
       
  1495 					      "Warning: \\subpage command has no label"
       
  1496 					      );
       
  1497   					  if (*yytext=='\n') yyLineNr++;
       
  1498 					  addOutput('\n');
       
  1499 					  BEGIN( Comment );
       
  1500   					}
       
  1501 <SubpageTitle>{DOCNL}			{ // no title, end command
       
  1502   					  addOutput(yytext);
       
  1503 					  BEGIN( Comment );
       
  1504   					}
       
  1505 <SubpageTitle>[ \t]*"\""[^\"\n]*"\""	{ // add title, end of command
       
  1506   					  addOutput(yytext);
       
  1507 					  BEGIN( Comment );
       
  1508   					}
       
  1509 <SubpageTitle>.				{ // no title, end of command
       
  1510   					  unput(*yytext);
       
  1511 					  BEGIN( Comment );
       
  1512   					}
       
  1513 
       
  1514   /* ----- handle arguments of the anchor command ------- */
       
  1515 
       
  1516 <AnchorLabel>{LABELID}			{ // found argument
       
  1517                                           SectionInfo  *si = new SectionInfo(yyFileName,yytext,0,SectionInfo::Anchor);
       
  1518                                           Doxygen::sectionDict.insert(yytext,si);
       
  1519   					  current->anchors->append(si);
       
  1520 					  addOutput(yytext);
       
  1521 					  BEGIN( Comment );
       
  1522   					}
       
  1523 <AnchorLabel>{DOCNL}			{ // missing argument
       
  1524   					  warn(yyFileName,yyLineNr,
       
  1525 					      "Warning: \\anchor command has no label"
       
  1526 					      );
       
  1527   					  if (*yytext=='\n') yyLineNr++;
       
  1528 					  addOutput('\n');
       
  1529 					  BEGIN( Comment );
       
  1530   					}
       
  1531 <AnchorLabel>.				{ // invalid character for anchor label
       
  1532   					  warn(yyFileName,yyLineNr,
       
  1533 					      "Warning: Invalid or missing anchor label"
       
  1534 					      );
       
  1535 					  BEGIN(Comment);
       
  1536   					}
       
  1537 
       
  1538 
       
  1539   /* ----- handle arguments of the preformatted block commands ------- */
       
  1540 
       
  1541 <FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends
       
  1542   					  addOutput(yytext);
       
  1543 					  if (&yytext[4]==blockName) // found end of the block
       
  1544 					  {
       
  1545   					    BEGIN(Comment);
       
  1546 					  }
       
  1547   					}
       
  1548 <FormatBlock>[^ \@\*\/\\\n]*		{ // some word
       
  1549   					  addOutput(yytext);
       
  1550   					}
       
  1551 <FormatBlock>{DOCNL}			{ // new line
       
  1552   					  if (*yytext=='\n') yyLineNr++;
       
  1553 					  addOutput('\n');
       
  1554   					}
       
  1555 <FormatBlock>"/*"			{ // start of a C-comment
       
  1556   					  g_commentCount++;
       
  1557   					  addOutput(yytext);
       
  1558   					}
       
  1559 <FormatBlock>"*/"			{ // end of a C-comment
       
  1560   					  addOutput(yytext);
       
  1561   					  g_commentCount--;
       
  1562 					  if (g_commentCount<0 && blockName!="verbatim")
       
  1563 					  {
       
  1564 					    warn(yyFileName,yyLineNr,
       
  1565 					         "Warning: found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",blockName.data(),blockName.data());
       
  1566 					  }
       
  1567   					}
       
  1568 <FormatBlock>.				{
       
  1569   					  addOutput(*yytext);
       
  1570   					}
       
  1571 <FormatBlock><<EOF>>			{
       
  1572                                           warn(yyFileName,yyLineNr,
       
  1573 	                                    "Warning: reached end of comment while inside a @%s block; check for missing @end%s tag!",
       
  1574 	                                    blockName.data(),blockName.data()
       
  1575 	                                  );				
       
  1576 					  yyterminate();
       
  1577     					}
       
  1578 
       
  1579   /* ----- handle arguments of if/ifnot commands ------- */
       
  1580 
       
  1581 <GuardParam>{LABELID}			{ // parameter of if/ifnot guard
       
  1582                                           bool sectionEnabled = Config_getList("ENABLED_SECTIONS").find(yytext)!=-1;
       
  1583 					  bool parentEnabled = TRUE;
       
  1584 					  if (!guards.isEmpty()) parentEnabled = guards.top()->isEnabled();
       
  1585 					  if (parentEnabled)
       
  1586 					  {
       
  1587 					    if (
       
  1588 						(sectionEnabled && guardType==Guard_If) ||  
       
  1589 						(!sectionEnabled && guardType==Guard_IfNot)
       
  1590 					       ) // section is visible
       
  1591 					    {
       
  1592 					      guards.push(new GuardedSection(TRUE,TRUE));
       
  1593 					      enabledSectionFound=TRUE;
       
  1594 					      BEGIN( Comment );
       
  1595 					    }
       
  1596 					    else // section is invisible
       
  1597 					    {
       
  1598 					      if (guardType!=Guard_Skip)
       
  1599 					      {
       
  1600 					      	guards.push(new GuardedSection(FALSE,TRUE));
       
  1601 					      }
       
  1602 					      BEGIN( SkipGuardedSection );
       
  1603 					    }
       
  1604 					  }
       
  1605 					  else // invisible because of parent
       
  1606 					  {
       
  1607 					    guards.push(new GuardedSection(FALSE,FALSE));
       
  1608 					    BEGIN( SkipGuardedSection );
       
  1609 					  }
       
  1610   					}
       
  1611 <GuardParam>{DOCNL}			{ // end of argument
       
  1612   					  if (*yytext=='\n') yyLineNr++;
       
  1613 					  addOutput('\n');
       
  1614 					  BEGIN( Comment );
       
  1615   					}
       
  1616 <GuardParam>{LC}			{ // line continuation
       
  1617                                           yyLineNr++; 
       
  1618 					  addOutput('\n');
       
  1619   					}
       
  1620 <GuardParam>.				{ // ignore other stuff
       
  1621   					  addOutput(*yytext);
       
  1622   					}
       
  1623 
       
  1624   /* ----- handle skipping of conditional sections ------- */
       
  1625 
       
  1626 <SkipGuardedSection>{CMD}"ifnot"/{NW}	{
       
  1627                                           guardType = Guard_IfNot;
       
  1628   					  BEGIN( GuardParam );
       
  1629   					}
       
  1630 <SkipGuardedSection>{CMD}"if"/{NW}	{
       
  1631                                           guardType = Guard_If;
       
  1632   					  BEGIN( GuardParam );
       
  1633   					}
       
  1634 <SkipGuardedSection>{CMD}"endif"/{NW}	{
       
  1635   					  if (guards.isEmpty())
       
  1636 					  {
       
  1637 					    warn(yyFileName,yyLineNr,
       
  1638 						"Warning: found @endif without matching start command");
       
  1639 					  }
       
  1640 					  else
       
  1641 					  {
       
  1642 					    delete guards.pop();
       
  1643 					    BEGIN( Comment );
       
  1644 					  }
       
  1645   					}
       
  1646 <SkipGuardedSection>{CMD}"else"/{NW}	{
       
  1647   					  if (guards.isEmpty())
       
  1648 					  {
       
  1649 					    warn(yyFileName,yyLineNr,
       
  1650 						"Warning: found @else without matching start command");
       
  1651 					  }
       
  1652 					  else
       
  1653 					  {
       
  1654 					    if (!enabledSectionFound && guards.top()->parentVisible())
       
  1655 					    {
       
  1656 					      delete guards.pop();
       
  1657 					      guards.push(new GuardedSection(TRUE,TRUE));
       
  1658 					      enabledSectionFound=TRUE;
       
  1659 					      BEGIN( Comment );
       
  1660 					    }
       
  1661 					  }
       
  1662   					}
       
  1663 <SkipGuardedSection>{CMD}"elseif"/{NW}  {
       
  1664   					  if (guards.isEmpty())
       
  1665 					  {
       
  1666 					    warn(yyFileName,yyLineNr,
       
  1667 						"Warning: found @elseif without matching start command");
       
  1668 					  }
       
  1669 					  else
       
  1670 					  {
       
  1671 					    if (!enabledSectionFound && guards.top()->parentVisible())
       
  1672 					    {
       
  1673 					      delete guards.pop();
       
  1674 					      BEGIN( GuardParam );
       
  1675 					    }
       
  1676 					  }
       
  1677   					}
       
  1678 <SkipGuardedSection>{DOCNL}		{ // skip line
       
  1679   					  if (*yytext=='\n') yyLineNr++;
       
  1680 					  addOutput('\n');
       
  1681   					}
       
  1682 <SkipGuardedSection>[^ \\@\n]+		{ // skip non-special characters
       
  1683   					}
       
  1684 <SkipGuardedSection>.			{ // any other character
       
  1685   					}
       
  1686 
       
  1687 
       
  1688   /* ----- handle skipping of internal section ------- */
       
  1689 
       
  1690 <SkipInternal>{DOCNL}			{ // skip line
       
  1691   					  if (*yytext=='\n') yyLineNr++;
       
  1692 					  addOutput('\n');
       
  1693   					}
       
  1694 <SkipInternal>[^ \\@\n]+		{ // skip non-special characters
       
  1695   					}
       
  1696 <SkipInternal>.				{ // any other character
       
  1697   					}
       
  1698 
       
  1699 
       
  1700   /* ----- handle argument of name command ------- */
       
  1701 
       
  1702 <NameParam>{DOCNL}			{ // end of argument
       
  1703   					  if (*yytext=='\n') yyLineNr++;
       
  1704 					  addOutput('\n');
       
  1705 					  BEGIN( Comment );
       
  1706   					}
       
  1707 <NameParam>{LC}				{ // line continuation
       
  1708                                           yyLineNr++; 
       
  1709 					  addOutput('\n');
       
  1710 					  g_memberGroupHeader+=' ';
       
  1711   					}
       
  1712 <NameParam>.				{ // ignore other stuff
       
  1713 					  g_memberGroupHeader+=*yytext;
       
  1714 					  current->name+=*yytext;
       
  1715   					}
       
  1716 
       
  1717   /* ----- handle argument of ingroup command ------- */
       
  1718 
       
  1719 <InGroupParam>{ID}			{ // group id
       
  1720   					  current->groups->append(
       
  1721 					    new Grouping(yytext, Grouping::GROUPING_INGROUP)
       
  1722 					  );
       
  1723 					  inGroupParamFound=TRUE;
       
  1724   					}
       
  1725 <InGroupParam>{DOCNL}			{ // missing argument
       
  1726   					  if (!inGroupParamFound)
       
  1727 					  {
       
  1728   					    warn(yyFileName,yyLineNr,
       
  1729 					        "Warning: Missing group name for \\ingroup command"
       
  1730 					        );
       
  1731 					  }
       
  1732   					  if (*yytext=='\n') yyLineNr++;
       
  1733 					  addOutput('\n');
       
  1734 					  BEGIN( Comment );
       
  1735   					}
       
  1736 <InGroupParam>{LC}			{ // line continuation
       
  1737                                           yyLineNr++; 
       
  1738 					  addOutput('\n');
       
  1739   					}
       
  1740 <InGroupParam>.				{ // ignore other stuff
       
  1741   					  addOutput(*yytext);
       
  1742   					}
       
  1743 
       
  1744   /* ----- handle argument of fn command ------- */
       
  1745 
       
  1746 <FnParam>{DOCNL}			{ // end of argument
       
  1747   					  if (braceCount==0)
       
  1748 					  {
       
  1749 					    if (*yytext=='\n') yyLineNr++;
       
  1750 					    addOutput('\n');
       
  1751 					    langParser->parsePrototype(functionProto);
       
  1752 					    BEGIN( Comment );
       
  1753 					  }
       
  1754   					}
       
  1755 <FnParam>{LC}				{ // line continuation
       
  1756                                           yyLineNr++; 
       
  1757 					  functionProto+=' ';
       
  1758   					}
       
  1759 <FnParam>[^@\\\n()]+			{ // non-special characters
       
  1760                                           functionProto+=yytext;
       
  1761   					}
       
  1762 <FnParam>"("				{
       
  1763                                           functionProto+=yytext;
       
  1764 					  braceCount++;
       
  1765 					}
       
  1766 <FnParam>")"				{
       
  1767                                           functionProto+=yytext;
       
  1768 					  braceCount--;
       
  1769 					}
       
  1770 <FnParam>.				{ // add other stuff
       
  1771                                           functionProto+=*yytext;
       
  1772   					}
       
  1773 
       
  1774 
       
  1775   /* ----- handle argument of overload command ------- */
       
  1776 
       
  1777 
       
  1778 <OverloadParam>{DOCNL}			{ // end of argument
       
  1779   					  if (*yytext=='\n') yyLineNr++;
       
  1780 					  addOutput('\n');
       
  1781 					  if (functionProto.stripWhiteSpace().isEmpty())
       
  1782 					  { // plain overload command
       
  1783 					    addOutput(getOverloadDocs());
       
  1784 					  }
       
  1785 					  else // overload declaration
       
  1786 					  {
       
  1787                                             makeStructuralIndicator(Entry::OVERLOADDOC_SEC);
       
  1788 					    langParser->parsePrototype(functionProto);
       
  1789 					  }
       
  1790 					  BEGIN( Comment );
       
  1791   					}
       
  1792 <OverloadParam>{LC}			{ // line continuation
       
  1793                                           yyLineNr++; 
       
  1794 					  functionProto+=' ';
       
  1795   					}
       
  1796 <OverloadParam>.			{ // add other stuff
       
  1797                                           functionProto+=*yytext;
       
  1798   					}
       
  1799 
       
  1800   /* ----- handle argument of inherit command ------- */
       
  1801 
       
  1802 <InheritParam>({ID}("::"|"."))*{ID}	{ // found argument
       
  1803 					  current->extends->append(
       
  1804 					    new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal)
       
  1805 					  );
       
  1806 					  BEGIN( Comment );
       
  1807   					}
       
  1808 <InheritParam>{DOCNL}			{ // missing argument
       
  1809   					  warn(yyFileName,yyLineNr,
       
  1810 					      "Warning: \\inherit command has no argument"
       
  1811 					      );
       
  1812   					  if (*yytext=='\n') yyLineNr++;
       
  1813 					  addOutput('\n');
       
  1814 					  BEGIN( Comment );
       
  1815   					}
       
  1816 <InheritParam>.				{ // invalid character for anchor label
       
  1817   					  warn(yyFileName,yyLineNr,
       
  1818 					      "Warning: Invalid or missing name for \\inherit command"
       
  1819 					      );
       
  1820 					  BEGIN(Comment);
       
  1821   					}
       
  1822 
       
  1823   /* ----- handle argument of extends and implements commands ------- */
       
  1824 
       
  1825 <ExtendsParam>({ID}("::"|"."))*{ID}	{ // found argument
       
  1826 					  current->extends->append(
       
  1827 					    new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal)
       
  1828 					  );
       
  1829 					  BEGIN( Comment );
       
  1830   					}
       
  1831 <ExtendsParam>{DOCNL}			{ // missing argument
       
  1832   					  warn(yyFileName,yyLineNr,
       
  1833 					      "Warning: \\extends or \\implements command has no argument"
       
  1834 					      );
       
  1835   					  if (*yytext=='\n') yyLineNr++;
       
  1836 					  addOutput('\n');
       
  1837 					  BEGIN( Comment );
       
  1838   					}
       
  1839 <ExtendsParam>.				{ // ignore other stuff
       
  1840   					}
       
  1841 
       
  1842   /* ----- handle language specific sections ------- */
       
  1843 
       
  1844 <SkipLang>[\\@]"~"[a-zA-Z]*        { /* language switch */
       
  1845                                      QCString langId = &yytext[2];
       
  1846 				     if (langId.isEmpty() ||
       
  1847 					 stricmp(Config_getEnum("OUTPUT_LANGUAGE"),langId)==0)
       
  1848 				     { // enable language specific section
       
  1849 				       BEGIN(Comment);
       
  1850 				     }
       
  1851                                    }
       
  1852 <SkipLang>[^*@\\\n]*		   { /* any character not a *, @, backslash or new line */
       
  1853                                    }
       
  1854 <SkipLang>{DOCNL}		   { /* new line in verbatim block */
       
  1855   		                     if (*yytext=='\n') yyLineNr++;
       
  1856                                    }
       
  1857 <SkipLang>.			   { /* any other character */
       
  1858                                    }
       
  1859 
       
  1860 
       
  1861 %%
       
  1862 
       
  1863 //----------------------------------------------------------------------------
       
  1864 
       
  1865 static bool handleBrief(const QCString &)
       
  1866 {
       
  1867   //printf("handleBrief\n");
       
  1868   setOutput(OutputBrief);
       
  1869   return FALSE;
       
  1870 }
       
  1871 
       
  1872 static bool handleFn(const QCString &)
       
  1873 {
       
  1874   bool stop=makeStructuralIndicator(Entry::MEMBERDOC_SEC);
       
  1875   functionProto.resize(0);
       
  1876   braceCount=0;
       
  1877   BEGIN(FnParam);
       
  1878   return stop;
       
  1879 }
       
  1880 
       
  1881 static bool handleDef(const QCString &)
       
  1882 {
       
  1883   bool stop=makeStructuralIndicator(Entry::DEFINEDOC_SEC);
       
  1884   functionProto.resize(0);
       
  1885   BEGIN(FnParam);
       
  1886   return stop;
       
  1887 }
       
  1888 
       
  1889 static bool handleOverload(const QCString &)
       
  1890 {
       
  1891   functionProto.resize(0);
       
  1892   BEGIN(OverloadParam);
       
  1893   return FALSE;
       
  1894 }
       
  1895 
       
  1896 static bool handleEnum(const QCString &)
       
  1897 {
       
  1898   bool stop=makeStructuralIndicator(Entry::ENUMDOC_SEC);
       
  1899   BEGIN(EnumDocArg1);
       
  1900   return stop;
       
  1901 }
       
  1902 
       
  1903 static bool handleDefGroup(const QCString &)
       
  1904 {
       
  1905   bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
       
  1906   current->groupDocType = Entry::GROUPDOC_NORMAL;
       
  1907   BEGIN( GroupDocArg1 );
       
  1908   return stop;
       
  1909 }
       
  1910 
       
  1911 static bool handleAddToGroup(const QCString &)
       
  1912 {
       
  1913   bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
       
  1914   current->groupDocType = Entry::GROUPDOC_ADD;
       
  1915   BEGIN( GroupDocArg1 );
       
  1916   return stop;
       
  1917 }
       
  1918 
       
  1919 static bool handleWeakGroup(const QCString &)
       
  1920 {
       
  1921   bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
       
  1922   current->groupDocType = Entry::GROUPDOC_WEAK;
       
  1923   BEGIN( GroupDocArg1 );
       
  1924   return stop;
       
  1925 }
       
  1926 
       
  1927 static bool handleNamespace(const QCString &)
       
  1928 {
       
  1929   bool stop=makeStructuralIndicator(Entry::NAMESPACEDOC_SEC);
       
  1930   BEGIN( NameSpaceDocArg1 );
       
  1931   return stop;
       
  1932 }
       
  1933 
       
  1934 static bool handlePackage(const QCString &)
       
  1935 {
       
  1936   bool stop=makeStructuralIndicator(Entry::PACKAGEDOC_SEC);
       
  1937   BEGIN( PackageDocArg1 );
       
  1938   return stop;
       
  1939 }
       
  1940 
       
  1941 static bool handleClass(const QCString &)
       
  1942 {
       
  1943   bool stop=makeStructuralIndicator(Entry::CLASSDOC_SEC);
       
  1944   BEGIN( ClassDocArg1 ); 
       
  1945   return stop;
       
  1946 }
       
  1947 
       
  1948 static bool handleHeaderFile(const QCString &)
       
  1949 {
       
  1950   BEGIN( ClassDocArg2 );
       
  1951   return FALSE;
       
  1952 }
       
  1953 
       
  1954 static bool handleProtocol(const QCString &)
       
  1955 { // Obj-C protocol
       
  1956   bool stop=makeStructuralIndicator(Entry::PROTOCOLDOC_SEC);
       
  1957   BEGIN( ClassDocArg1 ); 
       
  1958   return stop;
       
  1959 }
       
  1960 
       
  1961 static bool handleCategory(const QCString &)
       
  1962 { // Obj-C category
       
  1963   bool stop=makeStructuralIndicator(Entry::CATEGORYDOC_SEC);
       
  1964   BEGIN( CategoryDocArg1 ); 
       
  1965   return stop;
       
  1966 }
       
  1967 
       
  1968 static bool handleUnion(const QCString &)
       
  1969 {
       
  1970   bool stop=makeStructuralIndicator(Entry::UNIONDOC_SEC);
       
  1971   BEGIN( ClassDocArg1 ); 
       
  1972   return stop;
       
  1973 }
       
  1974 
       
  1975 static bool handleStruct(const QCString &)
       
  1976 {
       
  1977   bool stop=makeStructuralIndicator(Entry::STRUCTDOC_SEC);
       
  1978   BEGIN( ClassDocArg1 ); 
       
  1979   return stop;
       
  1980 }
       
  1981 
       
  1982 static bool handleInterface(const QCString &)
       
  1983 {
       
  1984   bool stop=makeStructuralIndicator(Entry::INTERFACEDOC_SEC);
       
  1985   BEGIN( ClassDocArg1 ); 
       
  1986   return stop;
       
  1987 }
       
  1988 
       
  1989 static bool handleIdlException(const QCString &)
       
  1990 {
       
  1991   bool stop=makeStructuralIndicator(Entry::EXCEPTIONDOC_SEC);
       
  1992   BEGIN( ClassDocArg1 ); 
       
  1993   return stop;
       
  1994 }
       
  1995 
       
  1996 static bool handlePage(const QCString &)
       
  1997 {
       
  1998   bool stop=makeStructuralIndicator(Entry::PAGEDOC_SEC);
       
  1999   BEGIN( PageDocArg1 );
       
  2000   return stop;
       
  2001 }
       
  2002 
       
  2003 static bool handleMainpage(const QCString &)
       
  2004 {
       
  2005   bool stop=makeStructuralIndicator(Entry::MAINPAGEDOC_SEC);
       
  2006   if (!stop) 
       
  2007   {
       
  2008     current->name = "mainpage";
       
  2009   }
       
  2010   BEGIN( PageDocArg2 );
       
  2011   return stop;
       
  2012 }
       
  2013 
       
  2014 static bool handleFile(const QCString &)
       
  2015 {
       
  2016   bool stop=makeStructuralIndicator(Entry::FILEDOC_SEC);
       
  2017   if (!stop) 
       
  2018   {
       
  2019     current->name = yyFileName;
       
  2020   }
       
  2021   BEGIN( FileDocArg1 );
       
  2022   return stop;
       
  2023 }
       
  2024 
       
  2025 static bool handleDir(const QCString &)
       
  2026 {
       
  2027   bool stop=makeStructuralIndicator(Entry::DIRDOC_SEC);
       
  2028   if (!stop) current->name = yyFileName;
       
  2029   BEGIN( FileDocArg1 );
       
  2030   return stop;
       
  2031 }
       
  2032 
       
  2033 static bool handleExample(const QCString &)
       
  2034 {
       
  2035   bool stop=makeStructuralIndicator(Entry::EXAMPLE_SEC);
       
  2036   if (!stop) current->name = yyFileName;
       
  2037   BEGIN( FileDocArg1 );
       
  2038   return stop;
       
  2039 }
       
  2040 
       
  2041 static bool handleDetails(const QCString &)
       
  2042 {
       
  2043   if (inContext!=OutputBrief)
       
  2044   {
       
  2045     addOutput("\n\n"); // treat @details outside brief description
       
  2046                        // as a new paragraph
       
  2047   }
       
  2048   setOutput(OutputDoc);
       
  2049   return FALSE;
       
  2050 }
       
  2051 
       
  2052 static bool handleName(const QCString &)
       
  2053 {
       
  2054   bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC);
       
  2055   if (!stop)
       
  2056   {
       
  2057     g_memberGroupHeader.resize(0);
       
  2058     BEGIN( NameParam );
       
  2059     if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group
       
  2060     {
       
  2061       closeGroup(current,yyFileName,yyLineNr);
       
  2062     }
       
  2063   }
       
  2064   return stop;
       
  2065 }
       
  2066 
       
  2067 static bool handleTodo(const QCString &)
       
  2068 {
       
  2069   newXRefKind = XRef_Todo;
       
  2070   setOutput(OutputXRef);
       
  2071   xrefKind = XRef_Todo;
       
  2072   return FALSE;
       
  2073 }
       
  2074 
       
  2075 static bool handleTest(const QCString &)
       
  2076 {
       
  2077   newXRefKind = XRef_Test;
       
  2078   setOutput(OutputXRef);
       
  2079   xrefKind = XRef_Test;
       
  2080   return FALSE;
       
  2081 }
       
  2082 
       
  2083 static bool handleBug(const QCString &)
       
  2084 {
       
  2085   newXRefKind = XRef_Bug;
       
  2086   setOutput(OutputXRef);
       
  2087   xrefKind = XRef_Bug;
       
  2088   return FALSE;
       
  2089 }
       
  2090 
       
  2091 static bool handleDeprecated(const QCString &)
       
  2092 {
       
  2093   newXRefKind = XRef_Deprecated;
       
  2094   setOutput(OutputXRef);
       
  2095   xrefKind = XRef_Deprecated;
       
  2096   return FALSE;
       
  2097 }
       
  2098 
       
  2099 static bool handleXRefItem(const QCString &)
       
  2100 {
       
  2101   BEGIN(XRefItemParam1);
       
  2102   return FALSE;
       
  2103 }
       
  2104 
       
  2105 static bool handleRelated(const QCString &)
       
  2106 {
       
  2107   BEGIN(RelatesParam1);
       
  2108   return FALSE;
       
  2109 }
       
  2110 
       
  2111 static bool handleRelatedAlso(const QCString &)
       
  2112 {
       
  2113   current->relatesType = Duplicate;
       
  2114   BEGIN(RelatesParam1);
       
  2115   return FALSE;
       
  2116 }
       
  2117 
       
  2118 static bool handleMemberOf(const QCString &)
       
  2119 {
       
  2120   current->relatesType = MemberOf;
       
  2121   BEGIN(RelatesParam1);
       
  2122   return FALSE;
       
  2123 }
       
  2124 
       
  2125 static bool handleRefItem(const QCString &)
       
  2126 {
       
  2127   addOutput("@refitem ");
       
  2128   BEGIN(LineParam);
       
  2129   return FALSE;
       
  2130 }
       
  2131 
       
  2132 static bool handleSection(const QCString &s)
       
  2133 {
       
  2134   setOutput(OutputDoc);
       
  2135   addOutput("@"+s+" ");
       
  2136   BEGIN(SectionLabel);
       
  2137   return FALSE;
       
  2138 }
       
  2139 
       
  2140 static bool handleSubpage(const QCString &s)
       
  2141 {
       
  2142   if (current->section!=Entry::EMPTY_SEC && 
       
  2143       current->section!=Entry::PAGEDOC_SEC &&
       
  2144       current->section!=Entry::MAINPAGEDOC_SEC
       
  2145      )
       
  2146   {
       
  2147     warn(yyFileName,yyLineNr,
       
  2148 	"Warning: found \\subpage command in a comment block that is not marked as a page!");
       
  2149   }
       
  2150   addOutput("@"+s+" ");
       
  2151   BEGIN(SubpageLabel);
       
  2152   return FALSE;
       
  2153 }
       
  2154 
       
  2155 static bool handleAnchor(const QCString &s)
       
  2156 {
       
  2157   addOutput("@"+s+" ");
       
  2158   BEGIN(AnchorLabel);
       
  2159   return FALSE;
       
  2160 }
       
  2161 
       
  2162 static bool handleFormatBlock(const QCString &s)
       
  2163 {
       
  2164   addOutput("@"+s+" ");
       
  2165   //printf("handleFormatBlock(%s)\n",s.data());
       
  2166   blockName=s;
       
  2167   g_commentCount=0;
       
  2168   BEGIN(FormatBlock);
       
  2169   return FALSE;
       
  2170 }
       
  2171 
       
  2172 static bool handleAddIndex(const QCString &)
       
  2173 {
       
  2174   addOutput("@addindex ");
       
  2175   BEGIN(LineParam);
       
  2176   return FALSE;
       
  2177 }
       
  2178 
       
  2179 static bool handleIf(const QCString &)
       
  2180 {
       
  2181   enabledSectionFound=FALSE;
       
  2182   guardType = Guard_If;
       
  2183   BEGIN(GuardParam);
       
  2184   return FALSE;
       
  2185 }
       
  2186 
       
  2187 static bool handleIfNot(const QCString &)
       
  2188 {
       
  2189   enabledSectionFound=FALSE;
       
  2190   guardType = Guard_IfNot;
       
  2191   BEGIN(GuardParam);
       
  2192   return FALSE;
       
  2193 }
       
  2194 
       
  2195 static bool handleElseIf(const QCString &)
       
  2196 {
       
  2197   if (guards.isEmpty())
       
  2198   {
       
  2199     warn(yyFileName,yyLineNr,
       
  2200 	"Warning: found \\else without matching start command");
       
  2201   }
       
  2202   else
       
  2203   {
       
  2204     guardType = enabledSectionFound ? Guard_Skip : Guard_If;
       
  2205     BEGIN(GuardParam);
       
  2206   }
       
  2207   return FALSE;
       
  2208 }
       
  2209 
       
  2210 static bool handleElse(const QCString &)
       
  2211 {
       
  2212   if (guards.isEmpty())
       
  2213   {
       
  2214     warn(yyFileName,yyLineNr,
       
  2215 	"Warning: found \\else without matching start command");
       
  2216   }
       
  2217   else
       
  2218   {
       
  2219     BEGIN( SkipGuardedSection );
       
  2220   }
       
  2221   return FALSE;
       
  2222 }
       
  2223 
       
  2224 static bool handleEndIf(const QCString &)
       
  2225 {
       
  2226   if (guards.isEmpty())
       
  2227   {
       
  2228     warn(yyFileName,yyLineNr,
       
  2229 	"Warning: found \\endif without matching start command");
       
  2230   }
       
  2231   else
       
  2232   {
       
  2233     delete guards.pop();
       
  2234   }
       
  2235   enabledSectionFound=FALSE;
       
  2236   return FALSE;
       
  2237 }
       
  2238 
       
  2239 static bool handleIngroup(const QCString &)
       
  2240 {
       
  2241   inGroupParamFound=FALSE;
       
  2242   BEGIN( InGroupParam );
       
  2243   return FALSE;
       
  2244 }
       
  2245 
       
  2246 static bool handleNoSubGrouping(const QCString &)
       
  2247 {
       
  2248   current->subGrouping = FALSE; 
       
  2249   return FALSE;
       
  2250 }
       
  2251 
       
  2252 static bool handleShowInitializer(const QCString &)
       
  2253 {
       
  2254   current->initLines = 100000; // ON
       
  2255   return FALSE;
       
  2256 }
       
  2257 
       
  2258 static bool handleHideInitializer(const QCString &)
       
  2259 {
       
  2260   current->initLines = 0; // OFF
       
  2261   return FALSE;
       
  2262 }
       
  2263 
       
  2264 static bool handleCallgraph(const QCString &)
       
  2265 {
       
  2266   current->callGraph = TRUE; // ON
       
  2267   return FALSE;
       
  2268 }
       
  2269 
       
  2270 static bool handleCallergraph(const QCString &)
       
  2271 {
       
  2272   current->callerGraph = TRUE; // ON
       
  2273   return FALSE;
       
  2274 }
       
  2275 
       
  2276 static bool handleInternal(const QCString &)
       
  2277 {
       
  2278   if (!Config_getBool("INTERNAL_DOCS"))
       
  2279   {
       
  2280     // make sure some whitespace before a \internal command
       
  2281     // is not treated as "documentation"
       
  2282     if (current->doc.stripWhiteSpace().isEmpty())
       
  2283     { 
       
  2284       current->doc.resize(0);
       
  2285     }
       
  2286     BEGIN( SkipInternal );
       
  2287   }
       
  2288   else
       
  2289   {
       
  2290     addOutput("\\internal "); 
       
  2291   }
       
  2292   return FALSE;
       
  2293 }
       
  2294 
       
  2295 static bool handleLineBr(const QCString &)
       
  2296 {
       
  2297   addOutput('\n');
       
  2298   return FALSE;
       
  2299 }
       
  2300 
       
  2301 static bool handleStatic(const QCString &)
       
  2302 {
       
  2303   endBrief();
       
  2304   current->stat = TRUE; 
       
  2305   return FALSE;
       
  2306 }
       
  2307 
       
  2308 static bool handlePure(const QCString &)
       
  2309 {
       
  2310   endBrief();
       
  2311   current->virt = Pure; 
       
  2312   return FALSE;
       
  2313 }
       
  2314 
       
  2315 static bool handlePrivate(const QCString &)
       
  2316 {
       
  2317   current->protection = Private;
       
  2318   return FALSE;
       
  2319 }
       
  2320 
       
  2321 static bool handlePrivateSection(const QCString &)
       
  2322 {
       
  2323   current->protection = protection = Private;
       
  2324   return FALSE;
       
  2325 }
       
  2326 
       
  2327 static bool handleProtected(const QCString &)
       
  2328 {
       
  2329   current->protection = Protected;
       
  2330   return FALSE;
       
  2331 }
       
  2332 
       
  2333 static bool handleProtectedSection(const QCString &)
       
  2334 {
       
  2335   current->protection = protection = Protected ;
       
  2336   return FALSE;
       
  2337 }
       
  2338 
       
  2339 static bool handlePublic(const QCString &)
       
  2340 {
       
  2341   current->protection = Public;
       
  2342   return FALSE;
       
  2343 }
       
  2344 
       
  2345 static bool handlePublicSection(const QCString &)
       
  2346 {
       
  2347   current->protection = protection = Public;
       
  2348   return FALSE;
       
  2349 }
       
  2350 
       
  2351 static bool handleInherit(const QCString &)
       
  2352 {
       
  2353   BEGIN(InheritParam);
       
  2354   return FALSE;
       
  2355 }
       
  2356 
       
  2357 static bool handleExtends(const QCString &)
       
  2358 {
       
  2359   BEGIN(ExtendsParam);
       
  2360   return FALSE;
       
  2361 }
       
  2362 
       
  2363 //----------------------------------------------------------------------------
       
  2364 
       
  2365 static void checkFormula()
       
  2366 {
       
  2367   if (YY_START==ReadFormulaShort || YY_START==ReadFormulaLong)
       
  2368   {
       
  2369     warn(yyFileName,yyLineNr,"Warning: End of comment block while inside formula.");
       
  2370   }
       
  2371 }
       
  2372 
       
  2373 //----------------------------------------------------------------------------
       
  2374 
       
  2375 bool parseCommentBlock(/* in */     ParserInterface *parser,
       
  2376                        /* in */     Entry *curEntry,
       
  2377                        /* in */     const QCString &comment,
       
  2378 		       /* in */     const QCString &fileName,
       
  2379 		       /* in,out */ int  &lineNr,
       
  2380 		       /* in */     bool isBrief,
       
  2381 		       /* in */     bool isAutoBriefOn,
       
  2382 		       /* in */     bool isInbody,
       
  2383 		       /* in,out */ Protection &prot,
       
  2384 		       /* in,out */ int &position,
       
  2385 		       /* out */    bool &newEntryNeeded
       
  2386 		      )
       
  2387 {
       
  2388   //printf("parseCommentBlock() isBrief=%d isAutoBriefOn=%d lineNr=%d\n",
       
  2389   //    isBrief,isAutoBriefOn,lineNr);
       
  2390 
       
  2391   initParser();
       
  2392   guards.setAutoDelete(TRUE);
       
  2393   guards.clear();
       
  2394   langParser     = parser;
       
  2395   current        = curEntry;
       
  2396   if (comment.isEmpty()) return FALSE; // avoid empty strings
       
  2397   inputString    = comment;
       
  2398   inputString.append(" ");
       
  2399   inputPosition  = position;
       
  2400   yyLineNr       = lineNr;
       
  2401   yyFileName     = fileName;
       
  2402   protection     = prot;
       
  2403   needNewEntry   = FALSE;
       
  2404   xrefKind       = XRef_None;
       
  2405   xrefAppendFlag = FALSE;
       
  2406   insidePre      = FALSE;
       
  2407   parseMore      = FALSE;
       
  2408   inBody         = isInbody;
       
  2409   outputXRef.resize(0);
       
  2410   setOutput( isBrief || isAutoBriefOn ? OutputBrief : OutputDoc );
       
  2411   briefEndsAtDot = isAutoBriefOn;
       
  2412 
       
  2413   if (!current->inbodyDocs.isEmpty() && isInbody) // separate in body fragments
       
  2414   {
       
  2415     current->inbodyDocs+="\n\n";
       
  2416   }
       
  2417 
       
  2418   Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\n"
       
  2419                "input=[%s]\n",fileName.data(),lineNr,comment.data()
       
  2420               );
       
  2421   
       
  2422   commentScanYYrestart( commentScanYYin );
       
  2423   BEGIN( Comment );
       
  2424   commentScanYYlex();
       
  2425   setOutput( OutputDoc );
       
  2426 
       
  2427   if (YY_START==OverloadParam) // comment ended with \overload
       
  2428   {
       
  2429     addOutput(getOverloadDocs());
       
  2430   }
       
  2431 
       
  2432   if (!guards.isEmpty())
       
  2433   {
       
  2434     warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
       
  2435   }
       
  2436 
       
  2437   current->doc=stripLeadingAndTrailingEmptyLines(current->doc);
       
  2438 
       
  2439   if (current->section==Entry::FILEDOC_SEC && current->doc.isEmpty())
       
  2440   {
       
  2441     // to allow a comment block with just a @file command.
       
  2442     current->doc="\n\n";
       
  2443   }
       
  2444 
       
  2445   if (current->section==Entry::MEMBERGRP_SEC &&
       
  2446       g_memberGroupId==DOX_NOGROUP) // @name section but no group started yet
       
  2447   {
       
  2448     openGroup(current,yyFileName,yyLineNr);
       
  2449   }
       
  2450 
       
  2451   Debug::print(Debug::CommentScan,0,
       
  2452                "brief=[%s]\ndocs=[%s]\ninbody=[%s]\n===========\n",
       
  2453 	       current->brief.data(),current->doc.data(),current->inbodyDocs.data()
       
  2454               );
       
  2455   
       
  2456   checkFormula();
       
  2457   prot = protection;
       
  2458   
       
  2459   groupAddDocs(curEntry,fileName);
       
  2460 
       
  2461   newEntryNeeded = needNewEntry;
       
  2462 
       
  2463   // if we did not proceed during this call, it does not make
       
  2464   // sence to continue, since we get stuck. See bug 567346 for situations
       
  2465   // were this happens
       
  2466   if (parseMore && position==inputPosition) parseMore=FALSE;
       
  2467 
       
  2468   if (parseMore) position=inputPosition; else position=0;
       
  2469 
       
  2470   lineNr = yyLineNr;
       
  2471   //printf("position=%d parseMore=%d\n",position,parseMore);
       
  2472 
       
  2473   return parseMore;
       
  2474 }
       
  2475 
       
  2476 //---------------------------------------------------------------------------
       
  2477 
       
  2478 void groupEnterFile(const char *fileName,int)
       
  2479 {
       
  2480   g_autoGroupStack.setAutoDelete(TRUE);
       
  2481   g_autoGroupStack.clear();
       
  2482   g_memberGroupId = DOX_NOGROUP;
       
  2483   g_memberGroupDocs.resize(0);
       
  2484   g_memberGroupRelates.resize(0);
       
  2485   g_compoundName=fileName;
       
  2486 }
       
  2487 
       
  2488 void groupLeaveFile(const char *fileName,int line)
       
  2489 {
       
  2490   //if (g_memberGroupId!=DOX_NOGROUP)
       
  2491   //{
       
  2492   //  warn(fileName,line,"Warning: end of file while inside a member group\n");
       
  2493   //}
       
  2494   g_memberGroupId=DOX_NOGROUP;
       
  2495   g_memberGroupRelates.resize(0);
       
  2496   g_memberGroupDocs.resize(0);
       
  2497   if (!g_autoGroupStack.isEmpty())
       
  2498   {
       
  2499     warn(fileName,line,"Warning: end of file while inside a group\n");
       
  2500   }
       
  2501 }
       
  2502 
       
  2503 void groupEnterCompound(const char *fileName,int line,const char *name)
       
  2504 {
       
  2505   if (g_memberGroupId!=DOX_NOGROUP)
       
  2506   {
       
  2507     warn(fileName,line,"Warning: try to put compound %s inside a member group\n",name);
       
  2508   }
       
  2509   g_memberGroupId=DOX_NOGROUP;
       
  2510   g_memberGroupRelates.resize(0);
       
  2511   g_memberGroupDocs.resize(0);
       
  2512   g_compoundName = name;
       
  2513   int i = g_compoundName.find('(');
       
  2514   if (i!=-1) 
       
  2515   {
       
  2516     g_compoundName=g_compoundName.left(i); // strip category (Obj-C)
       
  2517   }
       
  2518   if (g_compoundName.isEmpty())
       
  2519   {
       
  2520     g_compoundName=fileName;
       
  2521   }
       
  2522   //printf("groupEnterCompound(%s)\n",name);
       
  2523 }
       
  2524 
       
  2525 void groupLeaveCompound(const char *,int,const char * /*name*/)
       
  2526 {
       
  2527   //printf("groupLeaveCompound(%s)\n",name);
       
  2528   //if (g_memberGroupId!=DOX_NOGROUP)
       
  2529   //{
       
  2530   //  warn(fileName,line,"Warning: end of compound %s while inside a member group\n",name);
       
  2531   //}
       
  2532   g_memberGroupId=DOX_NOGROUP;
       
  2533   g_memberGroupRelates.resize(0);
       
  2534   g_memberGroupDocs.resize(0);
       
  2535   g_compoundName.resize(0);
       
  2536 }
       
  2537 
       
  2538 static int findExistingGroup(int &groupId,const MemberGroupInfo *info)
       
  2539 {
       
  2540   //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data());
       
  2541   QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict);
       
  2542   MemberGroupInfo *mi;
       
  2543   for (di.toFirst();(mi=di.current());++di)
       
  2544   {
       
  2545     if (g_compoundName==mi->compoundName &&  // same file or scope
       
  2546 	!mi->header.isEmpty() &&             // not a nameless group
       
  2547 	stricmp(mi->header,info->header)==0  // same header name
       
  2548        )
       
  2549     {
       
  2550       //printf("Found it!\n");
       
  2551       return di.currentKey(); // put the item in this group
       
  2552     }
       
  2553   }
       
  2554   groupId++; // start new group
       
  2555   return groupId;
       
  2556 }
       
  2557 
       
  2558 void openGroup(Entry *e,const char *,int)
       
  2559 {
       
  2560   //printf("==> openGroup(name=%s,sec=%x) g_autoGroupStack=%d\n",
       
  2561   //  	e->name.data(),e->section,g_autoGroupStack.count());
       
  2562   if (e->section==Entry::GROUPDOC_SEC) // auto group
       
  2563   {
       
  2564     g_autoGroupStack.push(new Grouping(e->name,e->groupingPri()));
       
  2565   }
       
  2566   else // start of a member group
       
  2567   {
       
  2568     //printf("    membergroup id=%d\n",g_memberGroupId);
       
  2569     if (g_memberGroupId==DOX_NOGROUP) // no group started yet
       
  2570     {
       
  2571       static int curGroupId=0;
       
  2572 
       
  2573       MemberGroupInfo *info = new MemberGroupInfo;
       
  2574       info->header = g_memberGroupHeader.stripWhiteSpace();
       
  2575       info->compoundName = g_compoundName;
       
  2576       g_memberGroupId = findExistingGroup(curGroupId,info);
       
  2577       //printf("    use membergroup %d\n",g_memberGroupId);
       
  2578       Doxygen::memGrpInfoDict.insert(g_memberGroupId,info);
       
  2579 
       
  2580       g_memberGroupRelates = e->relates;
       
  2581       e->mGrpId = g_memberGroupId;
       
  2582     }
       
  2583   }
       
  2584 }
       
  2585 
       
  2586 void closeGroup(Entry *e,const char *fileName,int)
       
  2587 {
       
  2588   //printf("==> closeGroup(name=%s,sec=%x) g_autoGroupStack=%d\n",
       
  2589   //    e->name.data(),e->section,g_autoGroupStack.count());
       
  2590   if (g_memberGroupId!=DOX_NOGROUP) // end of member group
       
  2591   {
       
  2592     MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
       
  2593     if (info) // known group
       
  2594     {
       
  2595       info->doc = g_memberGroupDocs;
       
  2596       info->docFile = fileName;
       
  2597     }
       
  2598     g_memberGroupId=DOX_NOGROUP;
       
  2599     g_memberGroupRelates.resize(0);
       
  2600     g_memberGroupDocs.resize(0);
       
  2601     e->mGrpId=DOX_NOGROUP;
       
  2602     //printf("new group id=%d\n",g_memberGroupId);
       
  2603   }
       
  2604   else if (!g_autoGroupStack.isEmpty()) // end of auto group
       
  2605   {
       
  2606     Grouping *grp = g_autoGroupStack.pop();
       
  2607     e->groups->removeLast();
       
  2608     //printf("Removing %s\n",grp->groupname.data());
       
  2609     delete grp;
       
  2610     initGroupInfo(e);
       
  2611   }
       
  2612 }
       
  2613 
       
  2614 void initGroupInfo(Entry *e)
       
  2615 {
       
  2616   //printf("==> initGroup(id=%d,related=%s)\n",g_memberGroupId,
       
  2617   //       g_memberGroupRelates.data());
       
  2618   e->mGrpId     = g_memberGroupId;
       
  2619   e->relates    = g_memberGroupRelates;
       
  2620   if (!g_autoGroupStack.isEmpty())
       
  2621   {
       
  2622     //printf("Appending group %s to %s: count=%d entry=%p\n",
       
  2623     //	g_autoGroupStack.top()->groupname.data(),
       
  2624     //	e->name.data(),e->groups->count(),e);
       
  2625     e->groups->append(new Grouping(*g_autoGroupStack.top()));
       
  2626   }
       
  2627 }
       
  2628 
       
  2629 static void groupAddDocs(Entry *e,const char *fileName)
       
  2630 {
       
  2631   if (e->section==Entry::MEMBERGRP_SEC)
       
  2632   {
       
  2633     g_memberGroupDocs=e->brief.stripWhiteSpace();
       
  2634     e->doc = stripLeadingAndTrailingEmptyLines(e->doc);
       
  2635     if (!g_memberGroupDocs.isEmpty() && !e->doc.isEmpty())
       
  2636     {
       
  2637       g_memberGroupDocs+="\n\n";
       
  2638     }
       
  2639     g_memberGroupDocs+=e->doc;
       
  2640     MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
       
  2641     if (info) 
       
  2642     {
       
  2643       info->doc = g_memberGroupDocs;
       
  2644       info->docFile = fileName;
       
  2645       info->setRefItems(e->sli);
       
  2646     }
       
  2647     e->doc.resize(0);
       
  2648     e->brief.resize(0);
       
  2649   }
       
  2650 }
       
  2651 
       
  2652 
       
  2653 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
       
  2654 //----------------------------------------------------------------------------
       
  2655 extern "C" { // some bogus code to keep the compiler happy
       
  2656   void commentScanYYdummy() { yy_flex_realloc(0,0); } 
       
  2657 }
       
  2658 #endif
       
  2659