Orb/Doxygen/src/commentscan.l
changeset 3 d8fccb2cd802
child 4 468f4c8d3d5b
equal deleted inserted replaced
2:932c358ece3e 3:d8fccb2cd802
       
     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 		  //printf("Setting docFile to %s\n", yyFileName.data());
       
   696           current->docFile = yyFileName;
       
   697           current->docLine = yyLineNr;
       
   698         }
       
   699       }
       
   700       pOutputString = &current->doc;
       
   701       break;
       
   702     case OutputBrief:
       
   703       if (oldContext!=inContext)
       
   704       {
       
   705 	if (current->briefFile.isEmpty())
       
   706 	{
       
   707 	  current->briefFile = yyFileName;
       
   708 	  current->briefLine = yyLineNr;
       
   709 	}
       
   710       }
       
   711       if (current->brief.stripWhiteSpace().isEmpty()) // we only want one brief
       
   712 	                                              // description even if multiple
       
   713 	                                              // are given...
       
   714       {
       
   715         pOutputString = &current->brief;
       
   716       }
       
   717       else
       
   718       {
       
   719         pOutputString = &current->doc;
       
   720       }
       
   721       break;
       
   722     case OutputXRef:
       
   723       pOutputString = &outputXRef;
       
   724       // first item found, so can't append to previous
       
   725       //xrefAppendFlag = FALSE;
       
   726       break;
       
   727     case OutputInbody:
       
   728       pOutputString = &current->inbodyDocs;
       
   729       break;
       
   730   }
       
   731 }
       
   732 
       
   733 // add a string to the output
       
   734 static inline void addOutput(const char *s)
       
   735 {
       
   736   *pOutputString+=s;
       
   737 }
       
   738 
       
   739 // add a character to the output
       
   740 static inline void addOutput(char c)
       
   741 {
       
   742   *pOutputString+=c;
       
   743 }
       
   744 
       
   745 static void endBrief(bool addToOutput=TRUE)
       
   746 {
       
   747   if (!current->brief.stripWhiteSpace().isEmpty())
       
   748   { // only go to the detailed description if we have
       
   749     // found some brief description and not just whitespace
       
   750     briefEndsAtDot=FALSE;
       
   751     setOutput(OutputDoc);
       
   752     if (addToOutput) addOutput(yytext);
       
   753   }
       
   754 }
       
   755 
       
   756 /* ----------------------------------------------------------------- */
       
   757 #undef	YY_INPUT
       
   758 #define	YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
       
   759 
       
   760 static int prevPosition=0;
       
   761 
       
   762 static int yyread(char *buf,int max_size)
       
   763 {
       
   764     prevPosition=inputPosition;
       
   765     int c=0;
       
   766     while( c < max_size && inputString[inputPosition] )
       
   767     {
       
   768 	*buf = inputString[inputPosition++] ;
       
   769 	//printf("%d (%c)\n",*buf,*buf);
       
   770 	c++; buf++;
       
   771     }
       
   772     return c;
       
   773 }
       
   774 
       
   775 %}
       
   776 
       
   777        /* start command character */
       
   778 CMD	  ("\\"|"@")
       
   779 DCMD1     ("arg"|"attention"|"author"|"code")
       
   780 DCMD2     ("date"|"dot"|"msc"|"dotfile"|"example")
       
   781 DCMD3     ("htmlinclude"|"htmlonly"|"image"|"include")
       
   782 DCMD4     ("includelineno"|"internal"|"invariant")
       
   783 DCMD5     ("latexonly"|"li"|"line"|"manonly"|"name") 
       
   784 DCMD6     ("note"|"par"|"paragraph"|"param"|"post")
       
   785 DCMD7     ("pre"|"remarks"|(("relate"[sd])("also")?))
       
   786 DCMD8     ("remarks"|("return"[s]?)|"retval"|"sa"|"section")
       
   787 DCMD9     ("see"|"since"|"subsection"|"subsubsection")
       
   788 DCMD10    ("throw"|"until"|"verbatim")
       
   789 DCMD11    ("verbinclude"|"version"|"warning")
       
   790 DETAILEDCMD {CMD}({DCMD1}|{DCMD2}|{DCMD3}|{DCMD4}|{DCMD5}|{DCMD6}|{DCMD7}|{DCMD8}|{DCMD9}|{DCMD10}|{DCMD11})
       
   791 XREFCMD   {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem")  
       
   792 PRE       [pP][rR][eE]
       
   793 TABLE	  [tT][aA][bB][lL][eE]
       
   794 P	  [pP]
       
   795 UL        [uU][lL]
       
   796 OL	  [oO][lL]
       
   797 DL	  [dD][lL]
       
   798 IMG       [iI][mM][gG]
       
   799 HR        [hH][rR]
       
   800 DETAILEDHTML {PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}
       
   801 BN        [ \t\n\r]
       
   802 BL        [ \t\r]*"\n" 
       
   803 B         [ \t]
       
   804 BS        ^(({B}*"//")?)(({B}*"*"+)?){B}*
       
   805 ATTR      ({B}+[^>\n]*)?
       
   806 DOCNL     "\n"|"\\_linebr"
       
   807 LC        "\\"{B}*"\n"
       
   808 NW	  [^a-z_A-Z0-9]
       
   809 FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+]
       
   810 FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+]
       
   811 FILE      ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"")
       
   812 ID        "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
       
   813 LABELID   [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
       
   814 SCOPEID   {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
       
   815 SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID})
       
   816 MAILADR   [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ 
       
   817 RCSTAG    "$"{ID}":"[^\n$]+"$"
       
   818 
       
   819 %option noyywrap
       
   820 
       
   821   /* comment parsing states. */
       
   822 %x      Comment
       
   823 %x      PageDocArg1
       
   824 %x      PageDocArg2
       
   825 %x      RelatesParam1
       
   826 %x      ClassDocArg1
       
   827 %x      ClassDocArg2
       
   828 %x      ClassDocArg3
       
   829 %x      CategoryDocArg1
       
   830 %x      XRefItemParam1
       
   831 %x      XRefItemParam2
       
   832 %x      XRefItemParam3
       
   833 %x      FileDocArg1
       
   834 %x	EnumDocArg1
       
   835 %x	NameSpaceDocArg1
       
   836 %x	PackageDocArg1
       
   837 %x	GroupDocArg1
       
   838 %x	GroupDocArg2
       
   839 %x	SectionLabel
       
   840 %x	SectionTitle
       
   841 %x	SubpageLabel
       
   842 %x	SubpageTitle
       
   843 %x	FormatBlock
       
   844 %x	LineParam
       
   845 %x	GuardParam
       
   846 %x	SkipGuardedSection
       
   847 %x	SkipInternal
       
   848 %x      NameParam
       
   849 %x	InGroupParam
       
   850 %x	FnParam
       
   851 %x	OverloadParam
       
   852 %x	InheritParam
       
   853 %x	ExtendsParam
       
   854 %x      ReadFormulaShort
       
   855 %x	ReadFormulaLong
       
   856 %x	AnchorLabel
       
   857 %x      HtmlComment
       
   858 %x      SkipLang
       
   859 
       
   860 %%
       
   861 
       
   862   /* What can happen in while parsing a comment block:
       
   863    *   commands (e.g. @page, or \page)
       
   864    *   escaped commands (e.g. @@page or \\page).
       
   865    *   formulas (e.g. \f$ \f[ \f{..)
       
   866    *   directories (e.g. \doxygen\src\)
       
   867    *   autolist end. (e.g. a dot on an otherwise empty line)
       
   868    *   newlines.
       
   869    *   end of brief description due to blank line.
       
   870    *   end of brief description due to some command (@command, or <command>).
       
   871    *   words and whitespace and other characters (#,?!, etc).
       
   872    *   grouping commands (e.g. @{ and @})
       
   873    *   language switch (e.g. \~english or \~).
       
   874    *   mail adress (e.g. dimitri@stack.nl).
       
   875    *   quoted text, such as "foo@bar"
       
   876    *   XML commands, <summary></summary><remarks></remarks>
       
   877    */
       
   878 
       
   879 <Comment>{CMD}{CMD}[a-z_A-Z]+{B}*	{ // escaped command
       
   880   					  addOutput(yytext);
       
   881   					}
       
   882 <Comment>{CMD}{CMD}"~"[a-z_A-Z]*	{ // escaped command
       
   883   					  addOutput(yytext);
       
   884   					}
       
   885 <Comment>{MAILADR}			{ // mail adress
       
   886   					  addOutput(yytext);
       
   887   					}
       
   888 <Comment>"\""[^"\n]*"\""		{ // quoted text
       
   889                                           addOutput(yytext);
       
   890   					}
       
   891 <Comment>("\\"[a-z_A-Z]+)+"\\"		{ // directory (or chain of commands!)
       
   892   					  addOutput(yytext);
       
   893   					}
       
   894 <Comment>{XREFCMD}/[^a-z_A-Z]*		{ // xref command 
       
   895 					  if (inContext!=OutputXRef) 
       
   896 					  {
       
   897 					    briefEndsAtDot=FALSE;
       
   898 					    setOutput(OutputDoc);
       
   899 					  }
       
   900 					  // continue with the same input
       
   901                                           REJECT;
       
   902 					}
       
   903    /*
       
   904 <Comment>{DETAILEDCMD}/[^a-z_A-Z]*	{ // command that can end a brief description
       
   905 				          briefEndsAtDot=FALSE;
       
   906 				          setOutput(OutputDoc);
       
   907 					  // continue with the same input
       
   908                                           REJECT;
       
   909 					}
       
   910    */
       
   911 <Comment>"<"{DETAILEDHTML}{ATTR}">"	{ // HTML command that ends a brief description
       
   912 					  setOutput(OutputDoc);
       
   913 					  // continue with the same input
       
   914                                           REJECT;
       
   915 					}
       
   916 <Comment>"<summary>"			{ // start of a .NET XML style brief description
       
   917 					  setOutput(OutputBrief);
       
   918   					}
       
   919 <Comment>"<remarks>"|"</summary>"	{ // start of a .NET XML style detailed description
       
   920 					  setOutput(OutputDoc);
       
   921   					}
       
   922 <Comment>"</remarks>"			{ // end of a brief or detailed description
       
   923   					}
       
   924 <Comment>{RCSTAG}			{ // RCS tag which end a brief description
       
   925   					  setOutput(OutputDoc);
       
   926 					  REJECT;
       
   927   					}
       
   928 <Comment>"<!--"				{ 
       
   929   					  BEGIN(HtmlComment);
       
   930 					}
       
   931 <Comment>{CMD}[a-z_A-Z]+{B}*		{ // potentially interesting command
       
   932   					  QCString cmdName = QCString(&yytext[1]).stripWhiteSpace();
       
   933 					  DocCmdMapper::Cmd *cmdPtr = DocCmdMapper::map(cmdName);
       
   934 					  if (cmdPtr) // special action is required
       
   935 					  {
       
   936 					    if (cmdPtr->endsBrief)
       
   937 					    { 
       
   938 					      briefEndsAtDot=FALSE;
       
   939 					      // this command forces the end of brief description
       
   940 					      setOutput(OutputDoc);
       
   941 					    }
       
   942 					    if (cmdPtr->func && cmdPtr->func(cmdName))
       
   943 					    {
       
   944 					      // implicit split of the comment block into two
       
   945 					      // entries. Restart the next block at the start
       
   946 					      // of this command.
       
   947 					      parseMore=TRUE;
       
   948 
       
   949 					      // yuk, this is probably not very portable across lex implementations, 
       
   950 					      // but we need to know the position in the input buffer where this 
       
   951 					      // rule matched.
       
   952 					      // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE
       
   953 #if YY_FLEX_MINOR_VERSION>=5 && YY_FLEX_SUBMINOR_VERSION>=33
       
   954 					      inputPosition=prevPosition + yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
       
   955 #else
       
   956 					      inputPosition=prevPosition + yy_bp - yy_current_buffer->yy_ch_buf;
       
   957 #endif
       
   958 					      yyterminate();
       
   959 					    }
       
   960 					    else if (cmdPtr->func==0)
       
   961 					    {
       
   962 					      // command without handler, to be processed
       
   963 					      // later by parsedoc.cpp
       
   964 					      addOutput(yytext);
       
   965 					    }
       
   966 					  }
       
   967 					  else // command not relevant
       
   968 					  {
       
   969 					    addOutput(yytext);
       
   970 					  }
       
   971   					}
       
   972 <Comment>("\\\\"|"@@")"f"[$\[{]		{ // escaped formula command
       
   973   					  addOutput(yytext);
       
   974   					}
       
   975 <Comment>{CMD}"~"[a-z_A-Z]*		{ // language switch command
       
   976                                           QCString langId = &yytext[2];
       
   977 			       	          if (!langId.isEmpty() &&
       
   978 					      stricmp(Config_getEnum("OUTPUT_LANGUAGE"),langId)!=0)
       
   979 				          { // enable language specific section
       
   980 				            BEGIN(SkipLang);
       
   981 				          }
       
   982   					}
       
   983 <Comment>{CMD}"f{"[^}\n]+"}"("{"?)      { // start of a formula with custom environment
       
   984 					  formulaText="\\begin";
       
   985 					  formulaEnv=&yytext[2];
       
   986 					  if (formulaEnv.at(formulaEnv.length()-1)=='{')
       
   987 					  {
       
   988 					    // remove trailing open brace
       
   989 					    formulaEnv=formulaEnv.left(formulaEnv.length()-1);
       
   990 					  }
       
   991 					  formulaText+=formulaEnv;
       
   992 					  formulaNewLines=0;
       
   993 					  BEGIN(ReadFormulaLong);
       
   994   					}
       
   995 <Comment>{CMD}"f$"			{ // start of a inline formula
       
   996 					  formulaText="$";
       
   997 					  formulaNewLines=0;
       
   998 					  BEGIN(ReadFormulaShort);
       
   999   					}
       
  1000 <Comment>{CMD}"f["			{ // start of a block formula
       
  1001 					  formulaText="\\[";
       
  1002 					  formulaNewLines=0;
       
  1003 					  BEGIN(ReadFormulaLong);
       
  1004   					}
       
  1005 <Comment>{CMD}"{"                       { // begin of a group
       
  1006                                           //langParser->handleGroupStartCommand(g_memberGroupHeader);
       
  1007                                           openGroup(current,yyFileName,yyLineNr);
       
  1008                                         }
       
  1009 <Comment>{CMD}"}"                       { // end of a group
       
  1010                                           //langParser->handleGroupEndCommand();
       
  1011                                           closeGroup(current,yyFileName,yyLineNr);
       
  1012                                           g_memberGroupHeader.resize(0);
       
  1013                                         }
       
  1014 <Comment>{CMD}[$@\\&~<>#%]		{ // escaped character
       
  1015   					  addOutput(yytext);
       
  1016   					}
       
  1017 <Comment>[a-z_A-Z]+			{ // normal word
       
  1018 					  addOutput(yytext);
       
  1019   					}
       
  1020 <Comment>^{B}*"."{B}*/\n                { // explicit end autolist: e.g "  ."
       
  1021   				          addOutput(yytext); 
       
  1022 					}
       
  1023 <Comment>("."+)[a-z_A-Z0-9]		{ // . at start or in the middle of a word, or ellipsis
       
  1024   					  addOutput(yytext);
       
  1025   					}
       
  1026 <Comment>".\\"[ \t]			{ // . with escaped space.
       
  1027   					  addOutput(yytext[0]);
       
  1028   					  addOutput(yytext[2]);
       
  1029   					}
       
  1030 <Comment>".,"				{ // . with comma such as "e.g.," 
       
  1031   					  addOutput(yytext);
       
  1032   					}
       
  1033 <Comment>(\n|\\_linebr)({B}*(\n|\\_linebr))+	{ // at least one blank line (or blank line command)
       
  1034   					  if (inContext!=OutputBrief)
       
  1035 					  {
       
  1036   					    addOutput("\n\n");
       
  1037 					    setOutput(OutputDoc);
       
  1038 					  }
       
  1039 					  else 
       
  1040 					  { // only go to the detailed description if we have
       
  1041 					    // found some brief description and not just whitespace
       
  1042 					    endBrief(FALSE);
       
  1043 					  }
       
  1044   					  lineCount();
       
  1045   					}
       
  1046 <Comment>"."				{ // potential end of a JavaDoc style comment
       
  1047   					  addOutput(*yytext);
       
  1048   					  if (briefEndsAtDot)
       
  1049 					  {
       
  1050 					    setOutput(OutputDoc);
       
  1051 					    briefEndsAtDot=FALSE;
       
  1052 					  }
       
  1053   					}
       
  1054 <Comment>\n				{ // newline
       
  1055   					  addOutput(*yytext);
       
  1056   					  yyLineNr++;
       
  1057   					}
       
  1058 <Comment>.				{ // catch-all for anything else
       
  1059   					  addOutput(*yytext);
       
  1060   					}
       
  1061 
       
  1062 
       
  1063  /* --------------   Rules for handling HTML comments ----------- */
       
  1064 
       
  1065 <HtmlComment>"--"[!]?">"{B}*		{ BEGIN( Comment ); }
       
  1066 <HtmlComment>{DOCNL}			{ 
       
  1067   					  if (*yytext=='\n') yyLineNr++;
       
  1068   					}
       
  1069 <HtmlComment>[^\\\n\-]+			{ // ignore unimportant characters
       
  1070   					}
       
  1071 <HtmlComment>.				{ // ignore every else
       
  1072   					}
       
  1073 
       
  1074  /* --------------   Rules for handling formulas ---------------- */
       
  1075  
       
  1076 <ReadFormulaShort>{CMD}"f$"		{ // end of inline formula
       
  1077   					  formulaText+="$";
       
  1078 					  addOutput(addFormula());
       
  1079 					  BEGIN(Comment);
       
  1080   					}
       
  1081 <ReadFormulaLong>{CMD}"f]"		{ // end of block formula
       
  1082 					  formulaText+="\\]";
       
  1083 					  addOutput(addFormula());
       
  1084 					  BEGIN(Comment);
       
  1085   					}
       
  1086 <ReadFormulaLong>{CMD}"f}"		{ // end of custom env formula
       
  1087 					  formulaText+="\\end";
       
  1088 					  formulaText+=formulaEnv;
       
  1089 					  addOutput(addFormula());
       
  1090 					  BEGIN(Comment);
       
  1091   					}
       
  1092 <ReadFormulaLong,ReadFormulaShort>[^\\@\n]+ { // any non-special character
       
  1093                                           formulaText+=yytext; 
       
  1094  					} 
       
  1095 <ReadFormulaLong,ReadFormulaShort>\n	{ // new line
       
  1096                                           formulaNewLines++;
       
  1097                                           formulaText+=*yytext; 
       
  1098 					  yyLineNr++; 
       
  1099 					}
       
  1100 <ReadFormulaLong,ReadFormulaShort>.     { // any othe character
       
  1101                                           formulaText+=*yytext; 
       
  1102 					}
       
  1103 
       
  1104   /* ------------ handle argument of enum command --------------- */
       
  1105 
       
  1106 <EnumDocArg1>{SCOPEID}			{ // handle argument
       
  1107   					  current->name = yytext;
       
  1108 					  BEGIN( Comment );
       
  1109   					}
       
  1110 <EnumDocArg1>{LC}			{ // line continuation
       
  1111   					  yyLineNr++;
       
  1112 					  addOutput('\n');
       
  1113                                         }
       
  1114 <EnumDocArg1>{DOCNL}			{ // missing argument
       
  1115   					  warn(yyFileName,yyLineNr,
       
  1116                                                "Warning: missing argument after \\enum."
       
  1117                                               );
       
  1118 					  addOutput('\n');
       
  1119   					  if (*yytext=='\n') yyLineNr++;
       
  1120 					  BEGIN( Comment );
       
  1121   					}
       
  1122 <EnumDocArg1>.				{ // ignore other stuff
       
  1123   					}
       
  1124 
       
  1125   /* ------------ handle argument of namespace command --------------- */
       
  1126 
       
  1127 <NameSpaceDocArg1>{SCOPENAME}		{ // handle argument
       
  1128   					  current->name = substitute(yytext,".","::");
       
  1129 					  BEGIN( Comment );
       
  1130   					}
       
  1131 <NameSpaceDocArg1>{LC}			{ // line continuation
       
  1132                                           yyLineNr++; 
       
  1133 					  addOutput('\n');
       
  1134                                         }
       
  1135 <NameSpaceDocArg1>{DOCNL}		{ // missing argument
       
  1136   					  warn(yyFileName,yyLineNr,
       
  1137                                                "Warning: missing argument after "
       
  1138 					       "\\namespace."
       
  1139                                               );
       
  1140 					  addOutput('\n');
       
  1141   					  if (*yytext=='\n') yyLineNr++;
       
  1142 					  BEGIN( Comment );
       
  1143   					}
       
  1144 <NameSpaceDocArg1>.			{ // ignore other stuff
       
  1145   					}
       
  1146 
       
  1147   /* ------------ handle argument of package command --------------- */
       
  1148 
       
  1149 <PackageDocArg1>{ID}("."{ID})*		{ // handle argument
       
  1150   					  current->name = yytext;
       
  1151 					  BEGIN( Comment );
       
  1152   					}
       
  1153 <PackageDocArg1>{LC}			{ // line continuation 
       
  1154                                           yyLineNr++; 
       
  1155 					  addOutput('\n');
       
  1156                                         }
       
  1157 <PackageDocArg1>{DOCNL}			{ // missing argument
       
  1158   					  warn(yyFileName,yyLineNr,
       
  1159                                                "Warning: missing argument after "
       
  1160 					       "\\package."
       
  1161                                               );
       
  1162 					  addOutput('\n');
       
  1163   					  if (*yytext=='\n') yyLineNr++;
       
  1164 					  BEGIN( Comment );
       
  1165   					}
       
  1166 <PackageDocArg1>.			{ // ignore other stuff
       
  1167   					}
       
  1168 
       
  1169   /* ------ handle argument of class/struct/union command --------------- */
       
  1170 
       
  1171 <ClassDocArg1>{SCOPENAME}		{ // first argument
       
  1172   					  current->name = substitute(yytext,".","::");
       
  1173 					  if (current->section==Entry::PROTOCOLDOC_SEC)
       
  1174 					  {
       
  1175 					    current->name+="-p";
       
  1176 					  }
       
  1177 					  // prepend outer scope name 
       
  1178 					  BEGIN( ClassDocArg2 );
       
  1179 					}
       
  1180 <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" {
       
  1181   					  current->name = substitute(yytext,".","::");
       
  1182 					  BEGIN( ClassDocArg2 );
       
  1183    					}
       
  1184 <ClassDocArg1,CategoryDocArg1>{LC}      { // line continuation
       
  1185                                           yyLineNr++; 
       
  1186 					  addOutput('\n');
       
  1187                                         }
       
  1188 <ClassDocArg1,CategoryDocArg1>{DOCNL}	{
       
  1189   					  warn(yyFileName,yyLineNr,
       
  1190                                                "Warning: missing argument after "
       
  1191 					       "\\%s.",YY_START==ClassDocArg1?"class":"category"
       
  1192                                               );
       
  1193 					  addOutput('\n');
       
  1194   					  if (*yytext=='\n') yyLineNr++;
       
  1195 					  BEGIN( Comment );
       
  1196   					}
       
  1197 <ClassDocArg1,CategoryDocArg1>.		{ // ignore other stuff
       
  1198   					}
       
  1199 
       
  1200 <ClassDocArg2>{FILE}|"<>"		{ // second argument; include file
       
  1201 					  current->includeFile = yytext;
       
  1202 					  BEGIN( ClassDocArg3 );
       
  1203 					}
       
  1204 <ClassDocArg2>{LC}			{ // line continuation
       
  1205                                           yyLineNr++; 
       
  1206 					  addOutput('\n');
       
  1207                                         }
       
  1208 <ClassDocArg2>{DOCNL}			{ 
       
  1209 					  addOutput('\n');
       
  1210   					  if (*yytext=='\n') yyLineNr++;
       
  1211 					  BEGIN( Comment );
       
  1212 					}
       
  1213 <ClassDocArg2>.				{ // ignore other stuff
       
  1214   					}
       
  1215 
       
  1216 <ClassDocArg3>[<]?{FILE}?[>]?		{ // third argument; include file name
       
  1217  					  current->includeName = yytext;
       
  1218 					  BEGIN( Comment );
       
  1219 					}
       
  1220 <ClassDocArg3>{LC}			{ // line continuation
       
  1221                                           yyLineNr++;
       
  1222 					  addOutput('\n');
       
  1223                                         }
       
  1224 <ClassDocArg3>{DOCNL}			{ 
       
  1225   					  if (*yytext=='\n') yyLineNr++;
       
  1226   					  BEGIN( Comment );
       
  1227 					}
       
  1228 <ClassDocArg3>.				{ // ignore other stuff
       
  1229   					}
       
  1230 
       
  1231   /* --------- handle arguments of {def,add,weak}group commands --------- */
       
  1232 
       
  1233 <GroupDocArg1>{ID}(".html"?)		{ // group name
       
  1234   					  current->name = yytext;
       
  1235 					  //lastDefGroup.groupname = yytext;
       
  1236 					  //lastDefGroup.pri = current->groupingPri();
       
  1237   					  // the .html stuff is for Qt compatibility
       
  1238 					  if (current->name.right(5)==".html") 
       
  1239 					  {
       
  1240 					    current->name=current->name.left(current->name.length()-5);
       
  1241 					  }
       
  1242 					  current->type.resize(0);
       
  1243 					  BEGIN(GroupDocArg2);
       
  1244   					}
       
  1245 <GroupDocArg1>"\\"{B}*"\n"		{ // line continuation
       
  1246   					  yyLineNr++; 
       
  1247 					  addOutput('\n');
       
  1248                                         }
       
  1249 <GroupDocArg1>{DOCNL}			{ // missing argument!
       
  1250   					  warn(yyFileName,yyLineNr,
       
  1251                                                "Warning: missing group name after %s",
       
  1252 					       current->groupDocCmd()
       
  1253                                               );
       
  1254 					  addOutput('\n');
       
  1255   					  if (*yytext=='\n') yyLineNr++;
       
  1256 					  BEGIN( Comment );
       
  1257   					}
       
  1258 <GroupDocArg2>"\\"{B}*"\n"		{ // line continuation
       
  1259   					  yyLineNr++; 
       
  1260 					  addOutput('\n');
       
  1261                                         }
       
  1262 <GroupDocArg2>[^\n\\\*]+		{ // title (stored in type)
       
  1263 					  current->type += yytext;
       
  1264 					  current->type = current->type.stripWhiteSpace();
       
  1265   					}
       
  1266 <GroupDocArg2>{DOCNL}			{
       
  1267                                           if ( current->groupDocType==Entry::GROUPDOC_NORMAL &&
       
  1268                                                current->type.isEmpty() 
       
  1269 					     ) // defgroup requires second argument
       
  1270 					  {
       
  1271   					    warn(yyFileName,yyLineNr,
       
  1272                                                  "Warning: missing title after "
       
  1273 					         "\\defgroup %s", current->name.data()
       
  1274                                                 );
       
  1275 					  }
       
  1276   					  if (*yytext=='\n') yyLineNr++; 
       
  1277 					  addOutput('\n');
       
  1278 					  BEGIN( Comment );
       
  1279   					}
       
  1280 
       
  1281   /* --------- handle arguments of page/mainpage command ------------------- */
       
  1282 
       
  1283 <PageDocArg1>{FILE}			{ // first argument; page name
       
  1284 					  current->name = stripQuotes(yytext);
       
  1285 					  BEGIN( PageDocArg2 ); 
       
  1286 					}
       
  1287 <PageDocArg1>{LC}			{ yyLineNr++; 
       
  1288 					  addOutput('\n');
       
  1289                                         }
       
  1290 <PageDocArg1>{DOCNL}			{
       
  1291   					  warn(yyFileName,yyLineNr,
       
  1292                                                "Warning: missing argument after "
       
  1293 					       "\\page."
       
  1294                                               );
       
  1295   					  if (*yytext=='\n') yyLineNr++;
       
  1296 					  addOutput('\n');
       
  1297 					  BEGIN( Comment );
       
  1298   					}
       
  1299 <PageDocArg1>.				{ // ignore other stuff
       
  1300   					}
       
  1301 <PageDocArg2>.*"\n"			{ // second argument; page title
       
  1302   				          yyLineNr++;
       
  1303 					  current->args = yytext;
       
  1304 					  addOutput('\n');
       
  1305 					  BEGIN( Comment );
       
  1306 					}
       
  1307 
       
  1308   /* --------- handle arguments of the file/dir/example command ------------ */
       
  1309 
       
  1310 <FileDocArg1>{DOCNL}			{ // no file name specfied
       
  1311   					  if (*yytext=='\n') yyLineNr++;
       
  1312 					  addOutput('\n');
       
  1313 					  BEGIN( Comment );
       
  1314 					}
       
  1315 <FileDocArg1>{FILE}			{ // first argument; name
       
  1316   					  current->name = stripQuotes(yytext);
       
  1317 					  BEGIN( Comment );
       
  1318   				        }
       
  1319 <FileDocArg1>{LC}			{ yyLineNr++; 
       
  1320 					  addOutput('\n');
       
  1321                                         }
       
  1322 <FileDocArg1>.				{ // ignore other stuff
       
  1323   					}
       
  1324 
       
  1325   /* --------- handle arguments of the xrefitem command ------------ */
       
  1326 
       
  1327 <XRefItemParam1>{ID}			{ // first argument
       
  1328   					  newXRefItemKey=yytext;
       
  1329                                           setOutput(OutputXRef);
       
  1330 					  BEGIN(XRefItemParam2);
       
  1331 					}
       
  1332 <XRefItemParam1>{LC}			{ // line continuation
       
  1333                                           yyLineNr++; 
       
  1334 					  addOutput('\n');
       
  1335                                         }
       
  1336 <XRefItemParam1>{DOCNL}			{ // missing arguments
       
  1337   					  warn(yyFileName,yyLineNr,
       
  1338 					       "Warning: Missing first argument of \\xrefitem"
       
  1339 					      );
       
  1340   					  if (*yytext=='\n') yyLineNr++;
       
  1341 					  addOutput('\n');
       
  1342 					  inContext = OutputDoc;
       
  1343 					  BEGIN( Comment );
       
  1344   					}
       
  1345 <XRefItemParam1>.			{ // ignore other stuff 
       
  1346   					}
       
  1347 
       
  1348 <XRefItemParam2>"\""[^\n\"]*"\""	{ // second argument
       
  1349   					  xrefItemTitle = stripQuotes(yytext);
       
  1350 					  BEGIN(XRefItemParam3);
       
  1351   					}
       
  1352 <XRefItemParam2>{LC}			{ // line continuation
       
  1353                                           yyLineNr++; 
       
  1354 					  addOutput('\n');
       
  1355   					}
       
  1356 <XRefItemParam2>{DOCNL}			{ // missing argument
       
  1357   					  warn(yyFileName,yyLineNr,
       
  1358 					      "Warning: Missing second argument of \\xrefitem"
       
  1359 					      );
       
  1360   					  if (*yytext=='\n') yyLineNr++;
       
  1361 					  addOutput('\n');
       
  1362 					  inContext = OutputDoc;
       
  1363 					  BEGIN( Comment );
       
  1364   					}
       
  1365 <XRefItemParam2>.			{ // ignore other stuff
       
  1366   					}
       
  1367 
       
  1368 <XRefItemParam3>"\""[^\n\"]*"\""	{ // third argument
       
  1369   					  xrefListTitle = stripQuotes(yytext);
       
  1370                                           xrefKind = XRef_Item;
       
  1371 					  BEGIN( Comment );
       
  1372   					}
       
  1373 <XRefItemParam2,XRefItemParam3>{LC}	{ // line continuation
       
  1374                                           yyLineNr++; 
       
  1375 					  addOutput('\n');
       
  1376   					}
       
  1377 <XRefItemParam3>{DOCNL}			{ // missing argument
       
  1378   					  warn(yyFileName,yyLineNr,
       
  1379 					      "Warning: Missing third argument of \\xrefitem"
       
  1380 					      );
       
  1381   					  if (*yytext=='\n') yyLineNr++;
       
  1382 					  addOutput('\n');
       
  1383 					  inContext = OutputDoc;
       
  1384 					  BEGIN( Comment );
       
  1385   					}
       
  1386 <XRefItemParam3>.			{ // ignore other stuff
       
  1387   					}
       
  1388 
       
  1389 
       
  1390   /* ----- handle arguments of the relates(also)/memberof command ------- */
       
  1391 
       
  1392 <RelatesParam1>({ID}("::"|"."))*{ID}	{ // argument
       
  1393   					  current->relates = yytext;
       
  1394                                           //if (current->mGrpId!=DOX_NOGROUP) 
       
  1395                                           //{
       
  1396                                           //  memberGroupRelates = yytext;
       
  1397                                           //}
       
  1398 					  BEGIN( Comment );
       
  1399 					}
       
  1400 <RelatesParam1>{LC}			{ // line continuation
       
  1401                                           yyLineNr++; 
       
  1402 					  addOutput('\n');
       
  1403   					}
       
  1404 <RelatesParam1>{DOCNL}			{ // missing argument
       
  1405   					  warn(yyFileName,yyLineNr,
       
  1406 					      "Warning: Missing argument of \\relates or \\memberof command"
       
  1407 					      );
       
  1408   					  if (*yytext=='\n') yyLineNr++;
       
  1409 					  addOutput('\n');
       
  1410 					  BEGIN( Comment );
       
  1411   					}
       
  1412 <RelatesParam1>.			{ // ignore other stuff
       
  1413   					}
       
  1414 
       
  1415 
       
  1416   /* ----- handle arguments of the relates(also)/addindex commands ----- */
       
  1417 
       
  1418 <LineParam>{DOCNL}			{ // end of argument
       
  1419   					  if (*yytext=='\n') yyLineNr++;
       
  1420 					  addOutput('\n');
       
  1421 					  BEGIN( Comment );
       
  1422   					}
       
  1423 <LineParam>{LC}				{ // line continuation
       
  1424                                           yyLineNr++; 
       
  1425 					  addOutput('\n');
       
  1426   					}
       
  1427 <LineParam>.				{ // ignore other stuff
       
  1428   					  addOutput(*yytext);
       
  1429   					}
       
  1430 
       
  1431   /* ----- handle arguments of the section/subsection/.. commands ------- */
       
  1432 
       
  1433 <SectionLabel>{LABELID}			{ // first argyment
       
  1434   					  sectionLabel=yytext;
       
  1435                                           addOutput(yytext);
       
  1436 					  sectionTitle.resize(0);
       
  1437 					  BEGIN(SectionTitle);
       
  1438   					}
       
  1439 <SectionLabel>{DOCNL}			{ // missing argument
       
  1440   					  warn(yyFileName,yyLineNr,
       
  1441 					      "Warning: \\section command has no label"
       
  1442 					      );
       
  1443   					  if (*yytext=='\n') yyLineNr++;
       
  1444 					  addOutput('\n');
       
  1445 					  BEGIN( Comment );
       
  1446   					}
       
  1447 <SectionLabel>.				{ // invalid character for section label
       
  1448   					  warn(yyFileName,yyLineNr,
       
  1449 					      "Warning: Invalid or missing section label"
       
  1450 					      );
       
  1451 					  BEGIN(Comment);
       
  1452   					}
       
  1453 
       
  1454 <SectionTitle>[^\n@\\*]*/"\n"            { // end of section title
       
  1455   					  addSection();
       
  1456                                           addOutput(yytext);
       
  1457 					  BEGIN( Comment );
       
  1458   					}
       
  1459 <SectionTitle>[^\n@\\]*/"\\_linebr"     { // end of section title
       
  1460   					  addSection();
       
  1461                                           addOutput(yytext);
       
  1462 					  BEGIN( Comment );
       
  1463   					}
       
  1464 <SectionTitle>{LC}			{ // line continuation
       
  1465                                           yyLineNr++; 
       
  1466 					  addOutput('\n');
       
  1467   					}
       
  1468 <SectionTitle>[^\n@\\]*			{ // any character without special meaning
       
  1469   					  sectionTitle+=yytext;
       
  1470 					  addOutput(yytext);
       
  1471   					}
       
  1472 <SectionTitle>("\\\\"|"@@"){ID}		{ // unescape escaped command
       
  1473   					  sectionTitle+=&yytext[1];
       
  1474 					  addOutput(yytext);
       
  1475   					}
       
  1476 <SectionTitle>{CMD}[$@\\&~<>#%]		{ // unescape escaped character
       
  1477   					  sectionTitle+=yytext[1];
       
  1478   					  addOutput(yytext);
       
  1479   					}
       
  1480 <SectionTitle>.				{ // anything else
       
  1481   					  sectionTitle+=yytext;
       
  1482 					  addOutput(*yytext);
       
  1483   					}
       
  1484 
       
  1485   /* ----- handle arguments of the subpage command ------- */
       
  1486 
       
  1487 <SubpageLabel>{LABELID}			{ // first argument
       
  1488                                           addOutput(yytext);
       
  1489 					  // we add subpage labels as a kind of "inheritance" relation to prevent
       
  1490 					  // needing to add another list to the Entry class.
       
  1491 					  current->extends->append(new BaseInfo(yytext,Public,Normal));
       
  1492 					  BEGIN(SubpageTitle);
       
  1493   					}
       
  1494 <SubpageLabel>{DOCNL}			{ // missing argument
       
  1495   					  warn(yyFileName,yyLineNr,
       
  1496 					      "Warning: \\subpage command has no label"
       
  1497 					      );
       
  1498   					  if (*yytext=='\n') yyLineNr++;
       
  1499 					  addOutput('\n');
       
  1500 					  BEGIN( Comment );
       
  1501   					}
       
  1502 <SubpageTitle>{DOCNL}			{ // no title, end command
       
  1503   					  addOutput(yytext);
       
  1504 					  BEGIN( Comment );
       
  1505   					}
       
  1506 <SubpageTitle>[ \t]*"\""[^\"\n]*"\""	{ // add title, end of command
       
  1507   					  addOutput(yytext);
       
  1508 					  BEGIN( Comment );
       
  1509   					}
       
  1510 <SubpageTitle>.				{ // no title, end of command
       
  1511   					  unput(*yytext);
       
  1512 					  BEGIN( Comment );
       
  1513   					}
       
  1514 
       
  1515   /* ----- handle arguments of the anchor command ------- */
       
  1516 
       
  1517 <AnchorLabel>{LABELID}			{ // found argument
       
  1518                                           SectionInfo  *si = new SectionInfo(yyFileName,yytext,0,SectionInfo::Anchor);
       
  1519                                           Doxygen::sectionDict.insert(yytext,si);
       
  1520   					  current->anchors->append(si);
       
  1521 					  addOutput(yytext);
       
  1522 					  BEGIN( Comment );
       
  1523   					}
       
  1524 <AnchorLabel>{DOCNL}			{ // missing argument
       
  1525   					  warn(yyFileName,yyLineNr,
       
  1526 					      "Warning: \\anchor command has no label"
       
  1527 					      );
       
  1528   					  if (*yytext=='\n') yyLineNr++;
       
  1529 					  addOutput('\n');
       
  1530 					  BEGIN( Comment );
       
  1531   					}
       
  1532 <AnchorLabel>.				{ // invalid character for anchor label
       
  1533   					  warn(yyFileName,yyLineNr,
       
  1534 					      "Warning: Invalid or missing anchor label"
       
  1535 					      );
       
  1536 					  BEGIN(Comment);
       
  1537   					}
       
  1538 
       
  1539 
       
  1540   /* ----- handle arguments of the preformatted block commands ------- */
       
  1541 
       
  1542 <FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends
       
  1543   					  addOutput(yytext);
       
  1544 					  if (&yytext[4]==blockName) // found end of the block
       
  1545 					  {
       
  1546   					    BEGIN(Comment);
       
  1547 					  }
       
  1548   					}
       
  1549 <FormatBlock>[^ \@\*\/\\\n]*		{ // some word
       
  1550   					  addOutput(yytext);
       
  1551   					}
       
  1552 <FormatBlock>{DOCNL}			{ // new line
       
  1553   					  if (*yytext=='\n') yyLineNr++;
       
  1554 					  addOutput('\n');
       
  1555   					}
       
  1556 <FormatBlock>"/*"			{ // start of a C-comment
       
  1557   					  g_commentCount++;
       
  1558   					  addOutput(yytext);
       
  1559   					}
       
  1560 <FormatBlock>"*/"			{ // end of a C-comment
       
  1561   					  addOutput(yytext);
       
  1562   					  g_commentCount--;
       
  1563 					  if (g_commentCount<0 && blockName!="verbatim")
       
  1564 					  {
       
  1565 					    warn(yyFileName,yyLineNr,
       
  1566 					         "Warning: found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",blockName.data(),blockName.data());
       
  1567 					  }
       
  1568   					}
       
  1569 <FormatBlock>.				{
       
  1570   					  addOutput(*yytext);
       
  1571   					}
       
  1572 <FormatBlock><<EOF>>			{
       
  1573                                           warn(yyFileName,yyLineNr,
       
  1574 	                                    "Warning: reached end of comment while inside a @%s block; check for missing @end%s tag!",
       
  1575 	                                    blockName.data(),blockName.data()
       
  1576 	                                  );				
       
  1577 					  yyterminate();
       
  1578     					}
       
  1579 
       
  1580   /* ----- handle arguments of if/ifnot commands ------- */
       
  1581 
       
  1582 <GuardParam>{LABELID}			{ // parameter of if/ifnot guard
       
  1583                                           bool sectionEnabled = Config_getList("ENABLED_SECTIONS").find(yytext)!=-1;
       
  1584 					  bool parentEnabled = TRUE;
       
  1585 					  if (!guards.isEmpty()) parentEnabled = guards.top()->isEnabled();
       
  1586 					  if (parentEnabled)
       
  1587 					  {
       
  1588 					    if (
       
  1589 						(sectionEnabled && guardType==Guard_If) ||  
       
  1590 						(!sectionEnabled && guardType==Guard_IfNot)
       
  1591 					       ) // section is visible
       
  1592 					    {
       
  1593 					      guards.push(new GuardedSection(TRUE,TRUE));
       
  1594 					      enabledSectionFound=TRUE;
       
  1595 					      BEGIN( Comment );
       
  1596 					    }
       
  1597 					    else // section is invisible
       
  1598 					    {
       
  1599 					      if (guardType!=Guard_Skip)
       
  1600 					      {
       
  1601 					      	guards.push(new GuardedSection(FALSE,TRUE));
       
  1602 					      }
       
  1603 					      BEGIN( SkipGuardedSection );
       
  1604 					    }
       
  1605 					  }
       
  1606 					  else // invisible because of parent
       
  1607 					  {
       
  1608 					    guards.push(new GuardedSection(FALSE,FALSE));
       
  1609 					    BEGIN( SkipGuardedSection );
       
  1610 					  }
       
  1611   					}
       
  1612 <GuardParam>{DOCNL}			{ // end of argument
       
  1613   					  if (*yytext=='\n') yyLineNr++;
       
  1614 					  addOutput('\n');
       
  1615 					  BEGIN( Comment );
       
  1616   					}
       
  1617 <GuardParam>{LC}			{ // line continuation
       
  1618                                           yyLineNr++; 
       
  1619 					  addOutput('\n');
       
  1620   					}
       
  1621 <GuardParam>.				{ // ignore other stuff
       
  1622   					  addOutput(*yytext);
       
  1623   					}
       
  1624 
       
  1625   /* ----- handle skipping of conditional sections ------- */
       
  1626 
       
  1627 <SkipGuardedSection>{CMD}"ifnot"/{NW}	{
       
  1628                                           guardType = Guard_IfNot;
       
  1629   					  BEGIN( GuardParam );
       
  1630   					}
       
  1631 <SkipGuardedSection>{CMD}"if"/{NW}	{
       
  1632                                           guardType = Guard_If;
       
  1633   					  BEGIN( GuardParam );
       
  1634   					}
       
  1635 <SkipGuardedSection>{CMD}"endif"/{NW}	{
       
  1636   					  if (guards.isEmpty())
       
  1637 					  {
       
  1638 					    warn(yyFileName,yyLineNr,
       
  1639 						"Warning: found @endif without matching start command");
       
  1640 					  }
       
  1641 					  else
       
  1642 					  {
       
  1643 					    delete guards.pop();
       
  1644 					    BEGIN( Comment );
       
  1645 					  }
       
  1646   					}
       
  1647 <SkipGuardedSection>{CMD}"else"/{NW}	{
       
  1648   					  if (guards.isEmpty())
       
  1649 					  {
       
  1650 					    warn(yyFileName,yyLineNr,
       
  1651 						"Warning: found @else without matching start command");
       
  1652 					  }
       
  1653 					  else
       
  1654 					  {
       
  1655 					    if (!enabledSectionFound && guards.top()->parentVisible())
       
  1656 					    {
       
  1657 					      delete guards.pop();
       
  1658 					      guards.push(new GuardedSection(TRUE,TRUE));
       
  1659 					      enabledSectionFound=TRUE;
       
  1660 					      BEGIN( Comment );
       
  1661 					    }
       
  1662 					  }
       
  1663   					}
       
  1664 <SkipGuardedSection>{CMD}"elseif"/{NW}  {
       
  1665   					  if (guards.isEmpty())
       
  1666 					  {
       
  1667 					    warn(yyFileName,yyLineNr,
       
  1668 						"Warning: found @elseif without matching start command");
       
  1669 					  }
       
  1670 					  else
       
  1671 					  {
       
  1672 					    if (!enabledSectionFound && guards.top()->parentVisible())
       
  1673 					    {
       
  1674 					      delete guards.pop();
       
  1675 					      BEGIN( GuardParam );
       
  1676 					    }
       
  1677 					  }
       
  1678   					}
       
  1679 <SkipGuardedSection>{DOCNL}		{ // skip line
       
  1680   					  if (*yytext=='\n') yyLineNr++;
       
  1681 					  addOutput('\n');
       
  1682   					}
       
  1683 <SkipGuardedSection>[^ \\@\n]+		{ // skip non-special characters
       
  1684   					}
       
  1685 <SkipGuardedSection>.			{ // any other character
       
  1686   					}
       
  1687 
       
  1688 
       
  1689   /* ----- handle skipping of internal section ------- */
       
  1690 
       
  1691 <SkipInternal>{DOCNL}			{ // skip line
       
  1692   					  if (*yytext=='\n') yyLineNr++;
       
  1693 					  addOutput('\n');
       
  1694   					}
       
  1695 <SkipInternal>[^ \\@\n]+		{ // skip non-special characters
       
  1696   					}
       
  1697 <SkipInternal>.				{ // any other character
       
  1698   					}
       
  1699 
       
  1700 
       
  1701   /* ----- handle argument of name command ------- */
       
  1702 
       
  1703 <NameParam>{DOCNL}			{ // end of argument
       
  1704   					  if (*yytext=='\n') yyLineNr++;
       
  1705 					  addOutput('\n');
       
  1706 					  BEGIN( Comment );
       
  1707   					}
       
  1708 <NameParam>{LC}				{ // line continuation
       
  1709                                           yyLineNr++; 
       
  1710 					  addOutput('\n');
       
  1711 					  g_memberGroupHeader+=' ';
       
  1712   					}
       
  1713 <NameParam>.				{ // ignore other stuff
       
  1714 					  g_memberGroupHeader+=*yytext;
       
  1715 					  current->name+=*yytext;
       
  1716   					}
       
  1717 
       
  1718   /* ----- handle argument of ingroup command ------- */
       
  1719 
       
  1720 <InGroupParam>{ID}			{ // group id
       
  1721   					  current->groups->append(
       
  1722 					    new Grouping(yytext, Grouping::GROUPING_INGROUP)
       
  1723 					  );
       
  1724 					  inGroupParamFound=TRUE;
       
  1725   					}
       
  1726 <InGroupParam>{DOCNL}			{ // missing argument
       
  1727   					  if (!inGroupParamFound)
       
  1728 					  {
       
  1729   					    warn(yyFileName,yyLineNr,
       
  1730 					        "Warning: Missing group name for \\ingroup command"
       
  1731 					        );
       
  1732 					  }
       
  1733   					  if (*yytext=='\n') yyLineNr++;
       
  1734 					  addOutput('\n');
       
  1735 					  BEGIN( Comment );
       
  1736   					}
       
  1737 <InGroupParam>{LC}			{ // line continuation
       
  1738                                           yyLineNr++; 
       
  1739 					  addOutput('\n');
       
  1740   					}
       
  1741 <InGroupParam>.				{ // ignore other stuff
       
  1742   					  addOutput(*yytext);
       
  1743   					}
       
  1744 
       
  1745   /* ----- handle argument of fn command ------- */
       
  1746 
       
  1747 <FnParam>{DOCNL}			{ // end of argument
       
  1748   					  if (braceCount==0)
       
  1749 					  {
       
  1750 					    if (*yytext=='\n') yyLineNr++;
       
  1751 					    addOutput('\n');
       
  1752 					    langParser->parsePrototype(functionProto);
       
  1753 					    BEGIN( Comment );
       
  1754 					  }
       
  1755   					}
       
  1756 <FnParam>{LC}				{ // line continuation
       
  1757                                           yyLineNr++; 
       
  1758 					  functionProto+=' ';
       
  1759   					}
       
  1760 <FnParam>[^@\\\n()]+			{ // non-special characters
       
  1761                                           functionProto+=yytext;
       
  1762   					}
       
  1763 <FnParam>"("				{
       
  1764                                           functionProto+=yytext;
       
  1765 					  braceCount++;
       
  1766 					}
       
  1767 <FnParam>")"				{
       
  1768                                           functionProto+=yytext;
       
  1769 					  braceCount--;
       
  1770 					}
       
  1771 <FnParam>.				{ // add other stuff
       
  1772                                           functionProto+=*yytext;
       
  1773   					}
       
  1774 
       
  1775 
       
  1776   /* ----- handle argument of overload command ------- */
       
  1777 
       
  1778 
       
  1779 <OverloadParam>{DOCNL}			{ // end of argument
       
  1780   					  if (*yytext=='\n') yyLineNr++;
       
  1781 					  addOutput('\n');
       
  1782 					  if (functionProto.stripWhiteSpace().isEmpty())
       
  1783 					  { // plain overload command
       
  1784 					    addOutput(getOverloadDocs());
       
  1785 					  }
       
  1786 					  else // overload declaration
       
  1787 					  {
       
  1788                                             makeStructuralIndicator(Entry::OVERLOADDOC_SEC);
       
  1789 					    langParser->parsePrototype(functionProto);
       
  1790 					  }
       
  1791 					  BEGIN( Comment );
       
  1792   					}
       
  1793 <OverloadParam>{LC}			{ // line continuation
       
  1794                                           yyLineNr++; 
       
  1795 					  functionProto+=' ';
       
  1796   					}
       
  1797 <OverloadParam>.			{ // add other stuff
       
  1798                                           functionProto+=*yytext;
       
  1799   					}
       
  1800 
       
  1801   /* ----- handle argument of inherit command ------- */
       
  1802 
       
  1803 <InheritParam>({ID}("::"|"."))*{ID}	{ // found argument
       
  1804 					  current->extends->append(
       
  1805 					    new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal)
       
  1806 					  );
       
  1807 					  BEGIN( Comment );
       
  1808   					}
       
  1809 <InheritParam>{DOCNL}			{ // missing argument
       
  1810   					  warn(yyFileName,yyLineNr,
       
  1811 					      "Warning: \\inherit command has no argument"
       
  1812 					      );
       
  1813   					  if (*yytext=='\n') yyLineNr++;
       
  1814 					  addOutput('\n');
       
  1815 					  BEGIN( Comment );
       
  1816   					}
       
  1817 <InheritParam>.				{ // invalid character for anchor label
       
  1818   					  warn(yyFileName,yyLineNr,
       
  1819 					      "Warning: Invalid or missing name for \\inherit command"
       
  1820 					      );
       
  1821 					  BEGIN(Comment);
       
  1822   					}
       
  1823 
       
  1824   /* ----- handle argument of extends and implements commands ------- */
       
  1825 
       
  1826 <ExtendsParam>({ID}("::"|"."))*{ID}	{ // found argument
       
  1827 					  current->extends->append(
       
  1828 					    new BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal)
       
  1829 					  );
       
  1830 					  BEGIN( Comment );
       
  1831   					}
       
  1832 <ExtendsParam>{DOCNL}			{ // missing argument
       
  1833   					  warn(yyFileName,yyLineNr,
       
  1834 					      "Warning: \\extends or \\implements command has no argument"
       
  1835 					      );
       
  1836   					  if (*yytext=='\n') yyLineNr++;
       
  1837 					  addOutput('\n');
       
  1838 					  BEGIN( Comment );
       
  1839   					}
       
  1840 <ExtendsParam>.				{ // ignore other stuff
       
  1841   					}
       
  1842 
       
  1843   /* ----- handle language specific sections ------- */
       
  1844 
       
  1845 <SkipLang>[\\@]"~"[a-zA-Z]*        { /* language switch */
       
  1846                                      QCString langId = &yytext[2];
       
  1847 				     if (langId.isEmpty() ||
       
  1848 					 stricmp(Config_getEnum("OUTPUT_LANGUAGE"),langId)==0)
       
  1849 				     { // enable language specific section
       
  1850 				       BEGIN(Comment);
       
  1851 				     }
       
  1852                                    }
       
  1853 <SkipLang>[^*@\\\n]*		   { /* any character not a *, @, backslash or new line */
       
  1854                                    }
       
  1855 <SkipLang>{DOCNL}		   { /* new line in verbatim block */
       
  1856   		                     if (*yytext=='\n') yyLineNr++;
       
  1857                                    }
       
  1858 <SkipLang>.			   { /* any other character */
       
  1859                                    }
       
  1860 
       
  1861 
       
  1862 %%
       
  1863 
       
  1864 //----------------------------------------------------------------------------
       
  1865 
       
  1866 static bool handleBrief(const QCString &)
       
  1867 {
       
  1868   //printf("handleBrief\n");
       
  1869   setOutput(OutputBrief);
       
  1870   return FALSE;
       
  1871 }
       
  1872 
       
  1873 static bool handleFn(const QCString &)
       
  1874 {
       
  1875   bool stop=makeStructuralIndicator(Entry::MEMBERDOC_SEC);
       
  1876   functionProto.resize(0);
       
  1877   braceCount=0;
       
  1878   BEGIN(FnParam);
       
  1879   return stop;
       
  1880 }
       
  1881 
       
  1882 static bool handleDef(const QCString &)
       
  1883 {
       
  1884   bool stop=makeStructuralIndicator(Entry::DEFINEDOC_SEC);
       
  1885   functionProto.resize(0);
       
  1886   BEGIN(FnParam);
       
  1887   return stop;
       
  1888 }
       
  1889 
       
  1890 static bool handleOverload(const QCString &)
       
  1891 {
       
  1892   functionProto.resize(0);
       
  1893   BEGIN(OverloadParam);
       
  1894   return FALSE;
       
  1895 }
       
  1896 
       
  1897 static bool handleEnum(const QCString &)
       
  1898 {
       
  1899   bool stop=makeStructuralIndicator(Entry::ENUMDOC_SEC);
       
  1900   BEGIN(EnumDocArg1);
       
  1901   return stop;
       
  1902 }
       
  1903 
       
  1904 static bool handleDefGroup(const QCString &)
       
  1905 {
       
  1906   bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
       
  1907   current->groupDocType = Entry::GROUPDOC_NORMAL;
       
  1908   BEGIN( GroupDocArg1 );
       
  1909   return stop;
       
  1910 }
       
  1911 
       
  1912 static bool handleAddToGroup(const QCString &)
       
  1913 {
       
  1914   bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
       
  1915   current->groupDocType = Entry::GROUPDOC_ADD;
       
  1916   BEGIN( GroupDocArg1 );
       
  1917   return stop;
       
  1918 }
       
  1919 
       
  1920 static bool handleWeakGroup(const QCString &)
       
  1921 {
       
  1922   bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
       
  1923   current->groupDocType = Entry::GROUPDOC_WEAK;
       
  1924   BEGIN( GroupDocArg1 );
       
  1925   return stop;
       
  1926 }
       
  1927 
       
  1928 static bool handleNamespace(const QCString &)
       
  1929 {
       
  1930   bool stop=makeStructuralIndicator(Entry::NAMESPACEDOC_SEC);
       
  1931   BEGIN( NameSpaceDocArg1 );
       
  1932   return stop;
       
  1933 }
       
  1934 
       
  1935 static bool handlePackage(const QCString &)
       
  1936 {
       
  1937   bool stop=makeStructuralIndicator(Entry::PACKAGEDOC_SEC);
       
  1938   BEGIN( PackageDocArg1 );
       
  1939   return stop;
       
  1940 }
       
  1941 
       
  1942 static bool handleClass(const QCString &)
       
  1943 {
       
  1944   bool stop=makeStructuralIndicator(Entry::CLASSDOC_SEC);
       
  1945   BEGIN( ClassDocArg1 ); 
       
  1946   return stop;
       
  1947 }
       
  1948 
       
  1949 static bool handleHeaderFile(const QCString &)
       
  1950 {
       
  1951   BEGIN( ClassDocArg2 );
       
  1952   return FALSE;
       
  1953 }
       
  1954 
       
  1955 static bool handleProtocol(const QCString &)
       
  1956 { // Obj-C protocol
       
  1957   bool stop=makeStructuralIndicator(Entry::PROTOCOLDOC_SEC);
       
  1958   BEGIN( ClassDocArg1 ); 
       
  1959   return stop;
       
  1960 }
       
  1961 
       
  1962 static bool handleCategory(const QCString &)
       
  1963 { // Obj-C category
       
  1964   bool stop=makeStructuralIndicator(Entry::CATEGORYDOC_SEC);
       
  1965   BEGIN( CategoryDocArg1 ); 
       
  1966   return stop;
       
  1967 }
       
  1968 
       
  1969 static bool handleUnion(const QCString &)
       
  1970 {
       
  1971   bool stop=makeStructuralIndicator(Entry::UNIONDOC_SEC);
       
  1972   BEGIN( ClassDocArg1 ); 
       
  1973   return stop;
       
  1974 }
       
  1975 
       
  1976 static bool handleStruct(const QCString &)
       
  1977 {
       
  1978   bool stop=makeStructuralIndicator(Entry::STRUCTDOC_SEC);
       
  1979   BEGIN( ClassDocArg1 ); 
       
  1980   return stop;
       
  1981 }
       
  1982 
       
  1983 static bool handleInterface(const QCString &)
       
  1984 {
       
  1985   bool stop=makeStructuralIndicator(Entry::INTERFACEDOC_SEC);
       
  1986   BEGIN( ClassDocArg1 ); 
       
  1987   return stop;
       
  1988 }
       
  1989 
       
  1990 static bool handleIdlException(const QCString &)
       
  1991 {
       
  1992   bool stop=makeStructuralIndicator(Entry::EXCEPTIONDOC_SEC);
       
  1993   BEGIN( ClassDocArg1 ); 
       
  1994   return stop;
       
  1995 }
       
  1996 
       
  1997 static bool handlePage(const QCString &)
       
  1998 {
       
  1999   bool stop=makeStructuralIndicator(Entry::PAGEDOC_SEC);
       
  2000   BEGIN( PageDocArg1 );
       
  2001   return stop;
       
  2002 }
       
  2003 
       
  2004 static bool handleMainpage(const QCString &)
       
  2005 {
       
  2006   bool stop=makeStructuralIndicator(Entry::MAINPAGEDOC_SEC);
       
  2007   if (!stop) 
       
  2008   {
       
  2009     current->name = "mainpage";
       
  2010   }
       
  2011   BEGIN( PageDocArg2 );
       
  2012   return stop;
       
  2013 }
       
  2014 
       
  2015 static bool handleFile(const QCString &)
       
  2016 {
       
  2017   bool stop=makeStructuralIndicator(Entry::FILEDOC_SEC);
       
  2018   if (!stop) 
       
  2019   {
       
  2020     current->name = yyFileName;
       
  2021   }
       
  2022   BEGIN( FileDocArg1 );
       
  2023   return stop;
       
  2024 }
       
  2025 
       
  2026 static bool handleDir(const QCString &)
       
  2027 {
       
  2028   bool stop=makeStructuralIndicator(Entry::DIRDOC_SEC);
       
  2029   if (!stop) current->name = yyFileName;
       
  2030   BEGIN( FileDocArg1 );
       
  2031   return stop;
       
  2032 }
       
  2033 
       
  2034 static bool handleExample(const QCString &)
       
  2035 {
       
  2036   bool stop=makeStructuralIndicator(Entry::EXAMPLE_SEC);
       
  2037   if (!stop) current->name = yyFileName;
       
  2038   BEGIN( FileDocArg1 );
       
  2039   return stop;
       
  2040 }
       
  2041 
       
  2042 static bool handleDetails(const QCString &)
       
  2043 {
       
  2044   if (inContext!=OutputBrief)
       
  2045   {
       
  2046     addOutput("\n\n"); // treat @details outside brief description
       
  2047                        // as a new paragraph
       
  2048   }
       
  2049   setOutput(OutputDoc);
       
  2050   return FALSE;
       
  2051 }
       
  2052 
       
  2053 static bool handleName(const QCString &)
       
  2054 {
       
  2055   bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC);
       
  2056   if (!stop)
       
  2057   {
       
  2058     g_memberGroupHeader.resize(0);
       
  2059     BEGIN( NameParam );
       
  2060     if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group
       
  2061     {
       
  2062       closeGroup(current,yyFileName,yyLineNr);
       
  2063     }
       
  2064   }
       
  2065   return stop;
       
  2066 }
       
  2067 
       
  2068 static bool handleTodo(const QCString &)
       
  2069 {
       
  2070   newXRefKind = XRef_Todo;
       
  2071   setOutput(OutputXRef);
       
  2072   xrefKind = XRef_Todo;
       
  2073   return FALSE;
       
  2074 }
       
  2075 
       
  2076 static bool handleTest(const QCString &)
       
  2077 {
       
  2078   newXRefKind = XRef_Test;
       
  2079   setOutput(OutputXRef);
       
  2080   xrefKind = XRef_Test;
       
  2081   return FALSE;
       
  2082 }
       
  2083 
       
  2084 static bool handleBug(const QCString &)
       
  2085 {
       
  2086   newXRefKind = XRef_Bug;
       
  2087   setOutput(OutputXRef);
       
  2088   xrefKind = XRef_Bug;
       
  2089   return FALSE;
       
  2090 }
       
  2091 
       
  2092 static bool handleDeprecated(const QCString &)
       
  2093 {
       
  2094   newXRefKind = XRef_Deprecated;
       
  2095   setOutput(OutputXRef);
       
  2096   xrefKind = XRef_Deprecated;
       
  2097   return FALSE;
       
  2098 }
       
  2099 
       
  2100 static bool handleXRefItem(const QCString &)
       
  2101 {
       
  2102   BEGIN(XRefItemParam1);
       
  2103   return FALSE;
       
  2104 }
       
  2105 
       
  2106 static bool handleRelated(const QCString &)
       
  2107 {
       
  2108   BEGIN(RelatesParam1);
       
  2109   return FALSE;
       
  2110 }
       
  2111 
       
  2112 static bool handleRelatedAlso(const QCString &)
       
  2113 {
       
  2114   current->relatesType = Duplicate;
       
  2115   BEGIN(RelatesParam1);
       
  2116   return FALSE;
       
  2117 }
       
  2118 
       
  2119 static bool handleMemberOf(const QCString &)
       
  2120 {
       
  2121   current->relatesType = MemberOf;
       
  2122   BEGIN(RelatesParam1);
       
  2123   return FALSE;
       
  2124 }
       
  2125 
       
  2126 static bool handleRefItem(const QCString &)
       
  2127 {
       
  2128   addOutput("@refitem ");
       
  2129   BEGIN(LineParam);
       
  2130   return FALSE;
       
  2131 }
       
  2132 
       
  2133 static bool handleSection(const QCString &s)
       
  2134 {
       
  2135   setOutput(OutputDoc);
       
  2136   addOutput("@"+s+" ");
       
  2137   BEGIN(SectionLabel);
       
  2138   return FALSE;
       
  2139 }
       
  2140 
       
  2141 static bool handleSubpage(const QCString &s)
       
  2142 {
       
  2143   if (current->section!=Entry::EMPTY_SEC && 
       
  2144       current->section!=Entry::PAGEDOC_SEC &&
       
  2145       current->section!=Entry::MAINPAGEDOC_SEC
       
  2146      )
       
  2147   {
       
  2148     warn(yyFileName,yyLineNr,
       
  2149 	"Warning: found \\subpage command in a comment block that is not marked as a page!");
       
  2150   }
       
  2151   addOutput("@"+s+" ");
       
  2152   BEGIN(SubpageLabel);
       
  2153   return FALSE;
       
  2154 }
       
  2155 
       
  2156 static bool handleAnchor(const QCString &s)
       
  2157 {
       
  2158   addOutput("@"+s+" ");
       
  2159   BEGIN(AnchorLabel);
       
  2160   return FALSE;
       
  2161 }
       
  2162 
       
  2163 static bool handleFormatBlock(const QCString &s)
       
  2164 {
       
  2165   addOutput("@"+s+" ");
       
  2166   //printf("handleFormatBlock(%s)\n",s.data());
       
  2167   blockName=s;
       
  2168   g_commentCount=0;
       
  2169   BEGIN(FormatBlock);
       
  2170   return FALSE;
       
  2171 }
       
  2172 
       
  2173 static bool handleAddIndex(const QCString &)
       
  2174 {
       
  2175   addOutput("@addindex ");
       
  2176   BEGIN(LineParam);
       
  2177   return FALSE;
       
  2178 }
       
  2179 
       
  2180 static bool handleIf(const QCString &)
       
  2181 {
       
  2182   enabledSectionFound=FALSE;
       
  2183   guardType = Guard_If;
       
  2184   BEGIN(GuardParam);
       
  2185   return FALSE;
       
  2186 }
       
  2187 
       
  2188 static bool handleIfNot(const QCString &)
       
  2189 {
       
  2190   enabledSectionFound=FALSE;
       
  2191   guardType = Guard_IfNot;
       
  2192   BEGIN(GuardParam);
       
  2193   return FALSE;
       
  2194 }
       
  2195 
       
  2196 static bool handleElseIf(const QCString &)
       
  2197 {
       
  2198   if (guards.isEmpty())
       
  2199   {
       
  2200     warn(yyFileName,yyLineNr,
       
  2201 	"Warning: found \\else without matching start command");
       
  2202   }
       
  2203   else
       
  2204   {
       
  2205     guardType = enabledSectionFound ? Guard_Skip : Guard_If;
       
  2206     BEGIN(GuardParam);
       
  2207   }
       
  2208   return FALSE;
       
  2209 }
       
  2210 
       
  2211 static bool handleElse(const QCString &)
       
  2212 {
       
  2213   if (guards.isEmpty())
       
  2214   {
       
  2215     warn(yyFileName,yyLineNr,
       
  2216 	"Warning: found \\else without matching start command");
       
  2217   }
       
  2218   else
       
  2219   {
       
  2220     BEGIN( SkipGuardedSection );
       
  2221   }
       
  2222   return FALSE;
       
  2223 }
       
  2224 
       
  2225 static bool handleEndIf(const QCString &)
       
  2226 {
       
  2227   if (guards.isEmpty())
       
  2228   {
       
  2229     warn(yyFileName,yyLineNr,
       
  2230 	"Warning: found \\endif without matching start command");
       
  2231   }
       
  2232   else
       
  2233   {
       
  2234     delete guards.pop();
       
  2235   }
       
  2236   enabledSectionFound=FALSE;
       
  2237   return FALSE;
       
  2238 }
       
  2239 
       
  2240 static bool handleIngroup(const QCString &)
       
  2241 {
       
  2242   inGroupParamFound=FALSE;
       
  2243   BEGIN( InGroupParam );
       
  2244   return FALSE;
       
  2245 }
       
  2246 
       
  2247 static bool handleNoSubGrouping(const QCString &)
       
  2248 {
       
  2249   current->subGrouping = FALSE; 
       
  2250   return FALSE;
       
  2251 }
       
  2252 
       
  2253 static bool handleShowInitializer(const QCString &)
       
  2254 {
       
  2255   current->initLines = 100000; // ON
       
  2256   return FALSE;
       
  2257 }
       
  2258 
       
  2259 static bool handleHideInitializer(const QCString &)
       
  2260 {
       
  2261   current->initLines = 0; // OFF
       
  2262   return FALSE;
       
  2263 }
       
  2264 
       
  2265 static bool handleCallgraph(const QCString &)
       
  2266 {
       
  2267   current->callGraph = TRUE; // ON
       
  2268   return FALSE;
       
  2269 }
       
  2270 
       
  2271 static bool handleCallergraph(const QCString &)
       
  2272 {
       
  2273   current->callerGraph = TRUE; // ON
       
  2274   return FALSE;
       
  2275 }
       
  2276 
       
  2277 static bool handleInternal(const QCString &)
       
  2278 {
       
  2279   if (!Config_getBool("INTERNAL_DOCS"))
       
  2280   {
       
  2281     // make sure some whitespace before a \internal command
       
  2282     // is not treated as "documentation"
       
  2283     if (current->doc.stripWhiteSpace().isEmpty())
       
  2284     { 
       
  2285       current->doc.resize(0);
       
  2286     }
       
  2287     BEGIN( SkipInternal );
       
  2288   }
       
  2289   else
       
  2290   {
       
  2291     addOutput("\\internal "); 
       
  2292   }
       
  2293   return FALSE;
       
  2294 }
       
  2295 
       
  2296 static bool handleLineBr(const QCString &)
       
  2297 {
       
  2298   addOutput('\n');
       
  2299   return FALSE;
       
  2300 }
       
  2301 
       
  2302 static bool handleStatic(const QCString &)
       
  2303 {
       
  2304   endBrief();
       
  2305   current->stat = TRUE; 
       
  2306   return FALSE;
       
  2307 }
       
  2308 
       
  2309 static bool handlePure(const QCString &)
       
  2310 {
       
  2311   endBrief();
       
  2312   current->virt = Pure; 
       
  2313   return FALSE;
       
  2314 }
       
  2315 
       
  2316 static bool handlePrivate(const QCString &)
       
  2317 {
       
  2318   current->protection = Private;
       
  2319   return FALSE;
       
  2320 }
       
  2321 
       
  2322 static bool handlePrivateSection(const QCString &)
       
  2323 {
       
  2324   current->protection = protection = Private;
       
  2325   return FALSE;
       
  2326 }
       
  2327 
       
  2328 static bool handleProtected(const QCString &)
       
  2329 {
       
  2330   current->protection = Protected;
       
  2331   return FALSE;
       
  2332 }
       
  2333 
       
  2334 static bool handleProtectedSection(const QCString &)
       
  2335 {
       
  2336   current->protection = protection = Protected ;
       
  2337   return FALSE;
       
  2338 }
       
  2339 
       
  2340 static bool handlePublic(const QCString &)
       
  2341 {
       
  2342   current->protection = Public;
       
  2343   return FALSE;
       
  2344 }
       
  2345 
       
  2346 static bool handlePublicSection(const QCString &)
       
  2347 {
       
  2348   current->protection = protection = Public;
       
  2349   return FALSE;
       
  2350 }
       
  2351 
       
  2352 static bool handleInherit(const QCString &)
       
  2353 {
       
  2354   BEGIN(InheritParam);
       
  2355   return FALSE;
       
  2356 }
       
  2357 
       
  2358 static bool handleExtends(const QCString &)
       
  2359 {
       
  2360   BEGIN(ExtendsParam);
       
  2361   return FALSE;
       
  2362 }
       
  2363 
       
  2364 //----------------------------------------------------------------------------
       
  2365 
       
  2366 static void checkFormula()
       
  2367 {
       
  2368   if (YY_START==ReadFormulaShort || YY_START==ReadFormulaLong)
       
  2369   {
       
  2370     warn(yyFileName,yyLineNr,"Warning: End of comment block while inside formula.");
       
  2371   }
       
  2372 }
       
  2373 
       
  2374 //----------------------------------------------------------------------------
       
  2375 
       
  2376 bool parseCommentBlock(/* in */     ParserInterface *parser,
       
  2377                        /* in */     Entry *curEntry,
       
  2378                        /* in */     const QCString &comment,
       
  2379 		       /* in */     const QCString &fileName,
       
  2380 		       /* in,out */ int  &lineNr,
       
  2381 		       /* in */     bool isBrief,
       
  2382 		       /* in */     bool isAutoBriefOn,
       
  2383 		       /* in */     bool isInbody,
       
  2384 		       /* in,out */ Protection &prot,
       
  2385 		       /* in,out */ int &position,
       
  2386 		       /* out */    bool &newEntryNeeded
       
  2387 		      )
       
  2388 {
       
  2389   //printf("parseCommentBlock() isBrief=%d isAutoBriefOn=%d lineNr=%d\n",
       
  2390   //    isBrief,isAutoBriefOn,lineNr);
       
  2391   //printf("parseCommentBlock() lineNr=%d file=%s\n", lineNr, fileName.data());
       
  2392   initParser();
       
  2393   guards.setAutoDelete(TRUE);
       
  2394   guards.clear();
       
  2395   langParser     = parser;
       
  2396   current        = curEntry;
       
  2397   if (comment.isEmpty()) return FALSE; // avoid empty strings
       
  2398   inputString    = comment;
       
  2399   inputString.append(" ");
       
  2400   inputPosition  = position;
       
  2401   yyLineNr       = lineNr;
       
  2402   yyFileName     = fileName;
       
  2403   protection     = prot;
       
  2404   needNewEntry   = FALSE;
       
  2405   xrefKind       = XRef_None;
       
  2406   xrefAppendFlag = FALSE;
       
  2407   insidePre      = FALSE;
       
  2408   parseMore      = FALSE;
       
  2409   inBody         = isInbody;
       
  2410   outputXRef.resize(0);
       
  2411   setOutput( isBrief || isAutoBriefOn ? OutputBrief : OutputDoc );
       
  2412   briefEndsAtDot = isAutoBriefOn;
       
  2413 
       
  2414   if (!current->inbodyDocs.isEmpty() && isInbody) // separate in body fragments
       
  2415   {
       
  2416     current->inbodyDocs+="\n\n";
       
  2417   }
       
  2418 
       
  2419   Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\n"
       
  2420                "input=[%s]\n",fileName.data(),lineNr,comment.data()
       
  2421               );
       
  2422   
       
  2423   commentScanYYrestart( commentScanYYin );
       
  2424   BEGIN( Comment );
       
  2425   commentScanYYlex();
       
  2426   setOutput( OutputDoc );
       
  2427 
       
  2428   if (YY_START==OverloadParam) // comment ended with \overload
       
  2429   {
       
  2430     addOutput(getOverloadDocs());
       
  2431   }
       
  2432 
       
  2433   if (!guards.isEmpty())
       
  2434   {
       
  2435     warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
       
  2436   }
       
  2437 
       
  2438   current->doc=stripLeadingAndTrailingEmptyLines(current->doc);
       
  2439 
       
  2440   if (current->section==Entry::FILEDOC_SEC && current->doc.isEmpty())
       
  2441   {
       
  2442     // to allow a comment block with just a @file command.
       
  2443     current->doc="\n\n";
       
  2444   }
       
  2445 
       
  2446   if (current->section==Entry::MEMBERGRP_SEC &&
       
  2447       g_memberGroupId==DOX_NOGROUP) // @name section but no group started yet
       
  2448   {
       
  2449     openGroup(current,yyFileName,yyLineNr);
       
  2450   }
       
  2451 
       
  2452   Debug::print(Debug::CommentScan,0,
       
  2453                "brief=[%s]\ndocs=[%s]\ninbody=[%s]\n===========\n",
       
  2454 	       current->brief.data(),current->doc.data(),current->inbodyDocs.data()
       
  2455               );
       
  2456   
       
  2457   checkFormula();
       
  2458   prot = protection;
       
  2459   
       
  2460   groupAddDocs(curEntry,fileName);
       
  2461 
       
  2462   newEntryNeeded = needNewEntry;
       
  2463 
       
  2464   // if we did not proceed during this call, it does not make
       
  2465   // sence to continue, since we get stuck. See bug 567346 for situations
       
  2466   // were this happens
       
  2467   if (parseMore && position==inputPosition) parseMore=FALSE;
       
  2468 
       
  2469   if (parseMore) position=inputPosition; else position=0;
       
  2470 
       
  2471   lineNr = yyLineNr;
       
  2472   //printf("position=%d parseMore=%d\n",position,parseMore);
       
  2473 
       
  2474   return parseMore;
       
  2475 }
       
  2476 
       
  2477 //---------------------------------------------------------------------------
       
  2478 
       
  2479 void groupEnterFile(const char *fileName,int)
       
  2480 {
       
  2481   g_autoGroupStack.setAutoDelete(TRUE);
       
  2482   g_autoGroupStack.clear();
       
  2483   g_memberGroupId = DOX_NOGROUP;
       
  2484   g_memberGroupDocs.resize(0);
       
  2485   g_memberGroupRelates.resize(0);
       
  2486   g_compoundName=fileName;
       
  2487 }
       
  2488 
       
  2489 void groupLeaveFile(const char *fileName,int line)
       
  2490 {
       
  2491   //if (g_memberGroupId!=DOX_NOGROUP)
       
  2492   //{
       
  2493   //  warn(fileName,line,"Warning: end of file while inside a member group\n");
       
  2494   //}
       
  2495   g_memberGroupId=DOX_NOGROUP;
       
  2496   g_memberGroupRelates.resize(0);
       
  2497   g_memberGroupDocs.resize(0);
       
  2498   if (!g_autoGroupStack.isEmpty())
       
  2499   {
       
  2500     warn(fileName,line,"Warning: end of file while inside a group\n");
       
  2501   }
       
  2502 }
       
  2503 
       
  2504 void groupEnterCompound(const char *fileName,int line,const char *name)
       
  2505 {
       
  2506   if (g_memberGroupId!=DOX_NOGROUP)
       
  2507   {
       
  2508     warn(fileName,line,"Warning: try to put compound %s inside a member group\n",name);
       
  2509   }
       
  2510   g_memberGroupId=DOX_NOGROUP;
       
  2511   g_memberGroupRelates.resize(0);
       
  2512   g_memberGroupDocs.resize(0);
       
  2513   g_compoundName = name;
       
  2514   int i = g_compoundName.find('(');
       
  2515   if (i!=-1) 
       
  2516   {
       
  2517     g_compoundName=g_compoundName.left(i); // strip category (Obj-C)
       
  2518   }
       
  2519   if (g_compoundName.isEmpty())
       
  2520   {
       
  2521     g_compoundName=fileName;
       
  2522   }
       
  2523   //printf("groupEnterCompound(%s)\n",name);
       
  2524 }
       
  2525 
       
  2526 void groupLeaveCompound(const char *,int,const char * /*name*/)
       
  2527 {
       
  2528   //printf("groupLeaveCompound(%s)\n",name);
       
  2529   //if (g_memberGroupId!=DOX_NOGROUP)
       
  2530   //{
       
  2531   //  warn(fileName,line,"Warning: end of compound %s while inside a member group\n",name);
       
  2532   //}
       
  2533   g_memberGroupId=DOX_NOGROUP;
       
  2534   g_memberGroupRelates.resize(0);
       
  2535   g_memberGroupDocs.resize(0);
       
  2536   g_compoundName.resize(0);
       
  2537 }
       
  2538 
       
  2539 static int findExistingGroup(int &groupId,const MemberGroupInfo *info)
       
  2540 {
       
  2541   //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data());
       
  2542   QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict);
       
  2543   MemberGroupInfo *mi;
       
  2544   for (di.toFirst();(mi=di.current());++di)
       
  2545   {
       
  2546     if (g_compoundName==mi->compoundName &&  // same file or scope
       
  2547 	!mi->header.isEmpty() &&             // not a nameless group
       
  2548 	stricmp(mi->header,info->header)==0  // same header name
       
  2549        )
       
  2550     {
       
  2551       //printf("Found it!\n");
       
  2552       return di.currentKey(); // put the item in this group
       
  2553     }
       
  2554   }
       
  2555   groupId++; // start new group
       
  2556   return groupId;
       
  2557 }
       
  2558 
       
  2559 void openGroup(Entry *e,const char *,int)
       
  2560 {
       
  2561   //printf("==> openGroup(name=%s,sec=%x) g_autoGroupStack=%d\n",
       
  2562   //  	e->name.data(),e->section,g_autoGroupStack.count());
       
  2563   if (e->section==Entry::GROUPDOC_SEC) // auto group
       
  2564   {
       
  2565     g_autoGroupStack.push(new Grouping(e->name,e->groupingPri()));
       
  2566   }
       
  2567   else // start of a member group
       
  2568   {
       
  2569     //printf("    membergroup id=%d\n",g_memberGroupId);
       
  2570     if (g_memberGroupId==DOX_NOGROUP) // no group started yet
       
  2571     {
       
  2572       static int curGroupId=0;
       
  2573 
       
  2574       MemberGroupInfo *info = new MemberGroupInfo;
       
  2575       info->header = g_memberGroupHeader.stripWhiteSpace();
       
  2576       info->compoundName = g_compoundName;
       
  2577       g_memberGroupId = findExistingGroup(curGroupId,info);
       
  2578       //printf("    use membergroup %d\n",g_memberGroupId);
       
  2579       Doxygen::memGrpInfoDict.insert(g_memberGroupId,info);
       
  2580 
       
  2581       g_memberGroupRelates = e->relates;
       
  2582       e->mGrpId = g_memberGroupId;
       
  2583     }
       
  2584   }
       
  2585 }
       
  2586 
       
  2587 void closeGroup(Entry *e,const char *fileName,int)
       
  2588 {
       
  2589   //printf("==> closeGroup(name=%s,sec=%x) g_autoGroupStack=%d\n",
       
  2590   //    e->name.data(),e->section,g_autoGroupStack.count());
       
  2591   if (g_memberGroupId!=DOX_NOGROUP) // end of member group
       
  2592   {
       
  2593     MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
       
  2594     if (info) // known group
       
  2595     {
       
  2596       info->doc = g_memberGroupDocs;
       
  2597       info->docFile = fileName;
       
  2598     }
       
  2599     g_memberGroupId=DOX_NOGROUP;
       
  2600     g_memberGroupRelates.resize(0);
       
  2601     g_memberGroupDocs.resize(0);
       
  2602     e->mGrpId=DOX_NOGROUP;
       
  2603     //printf("new group id=%d\n",g_memberGroupId);
       
  2604   }
       
  2605   else if (!g_autoGroupStack.isEmpty()) // end of auto group
       
  2606   {
       
  2607     Grouping *grp = g_autoGroupStack.pop();
       
  2608     e->groups->removeLast();
       
  2609     //printf("Removing %s\n",grp->groupname.data());
       
  2610     delete grp;
       
  2611     initGroupInfo(e);
       
  2612   }
       
  2613 }
       
  2614 
       
  2615 void initGroupInfo(Entry *e)
       
  2616 {
       
  2617   //printf("==> initGroup(id=%d,related=%s)\n",g_memberGroupId,
       
  2618   //       g_memberGroupRelates.data());
       
  2619   e->mGrpId     = g_memberGroupId;
       
  2620   e->relates    = g_memberGroupRelates;
       
  2621   if (!g_autoGroupStack.isEmpty())
       
  2622   {
       
  2623     //printf("Appending group %s to %s: count=%d entry=%p\n",
       
  2624     //	g_autoGroupStack.top()->groupname.data(),
       
  2625     //	e->name.data(),e->groups->count(),e);
       
  2626     e->groups->append(new Grouping(*g_autoGroupStack.top()));
       
  2627   }
       
  2628 }
       
  2629 
       
  2630 static void groupAddDocs(Entry *e,const char *fileName)
       
  2631 {
       
  2632   if (e->section==Entry::MEMBERGRP_SEC)
       
  2633   {
       
  2634     g_memberGroupDocs=e->brief.stripWhiteSpace();
       
  2635     e->doc = stripLeadingAndTrailingEmptyLines(e->doc);
       
  2636     if (!g_memberGroupDocs.isEmpty() && !e->doc.isEmpty())
       
  2637     {
       
  2638       g_memberGroupDocs+="\n\n";
       
  2639     }
       
  2640     g_memberGroupDocs+=e->doc;
       
  2641     MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
       
  2642     if (info) 
       
  2643     {
       
  2644       info->doc = g_memberGroupDocs;
       
  2645       info->docFile = fileName;
       
  2646       info->setRefItems(e->sli);
       
  2647     }
       
  2648     e->doc.resize(0);
       
  2649     e->brief.resize(0);
       
  2650   }
       
  2651 }
       
  2652 
       
  2653 
       
  2654 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
       
  2655 //----------------------------------------------------------------------------
       
  2656 extern "C" { // some bogus code to keep the compiler happy
       
  2657   void commentScanYYdummy() { yy_flex_realloc(0,0); } 
       
  2658 }
       
  2659 #endif
       
  2660