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