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