Imported Upstream version 1.8.6
[platform/upstream/doxygen.git] / src / commentcnv.l
1 /*****************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2013 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 %{
19
20 #define YY_NEVER_INTERACTIVE 1
21
22   
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include <qstack.h>
27 #include <qregexp.h>
28 #include <qtextstream.h>
29 #include <qglobal.h>
30
31 #include "bufstr.h"
32 #include "debug.h"
33 #include "message.h"
34 #include "config.h"
35 #include "doxygen.h"
36 #include "util.h"
37 #include "condparser.h"
38
39 #include <assert.h>
40
41 #define YY_NO_INPUT 1
42
43 #define ADDCHAR(c)    g_outBuf->addChar(c)
44 #define ADDARRAY(a,s) g_outBuf->addArray(a,s)
45   
46 struct CondCtx
47 {
48   CondCtx(int line,QCString id,bool b) 
49     : lineNr(line),sectionId(id), skip(b) {}
50   int lineNr;
51   QCString sectionId;
52   bool skip;
53 };
54   
55 static BufStr * g_inBuf;
56 static BufStr * g_outBuf;
57 static int      g_inBufPos;
58 static int      g_col;
59 static int      g_blockHeadCol;
60 static bool     g_mlBrief;
61 static int      g_readLineCtx;
62 static bool     g_skip;
63 static QCString g_fileName;
64 static int      g_lineNr;
65 static int      g_condCtx;
66 static QStack<CondCtx> g_condStack;
67 static QCString g_blockName;
68 static int      g_lastCommentContext;
69 static bool     g_inSpecialComment;
70 static bool     g_inRoseComment;
71 static int      g_stringContext;
72 static int      g_charContext;
73 static int      g_javaBlock;
74 static bool     g_specialComment;
75
76 static QCString g_aliasString;
77 static int      g_blockCount;
78 static bool     g_lastEscaped;
79 static int      g_lastBlockContext;
80 static bool     g_pythonDocString;
81 static int      g_nestingCount;
82
83 static SrcLangExt g_lang;
84 static bool       isFixedForm; // For Fortran
85
86 static void replaceCommentMarker(const char *s,int len)
87 {
88   const char *p=s;
89   char c;
90   // copy leading blanks
91   while ((c=*p) && (c==' ' || c=='\t' || c=='\n')) 
92   {
93     ADDCHAR(c);
94     g_lineNr += c=='\n';
95     p++;
96   }
97   // replace start of comment marker by blanks and the last character by a *
98   int blanks=0;
99   while ((c=*p) && (c=='/' || c=='!' || c=='#')) 
100   {
101     blanks++;
102     p++;
103     if (*p=='<') // comment-after-item marker 
104     { 
105       blanks++;
106       p++; 
107     }
108     if (c=='!') // end after first !
109     {
110       break;
111     }
112   }
113   if (blanks>0)
114   {
115     while (blanks>2)
116     {
117       ADDCHAR(' ');
118       blanks--;
119     }
120     if (blanks>1) ADDCHAR('*');
121     ADDCHAR(' ');
122   }
123   // copy comment line to output
124   ADDARRAY(p,len-(int)(p-s));
125 }
126
127 static inline int computeIndent(const char *s)
128 {
129   int col=0;
130   static int tabSize=Config_getInt("TAB_SIZE");
131   const char *p=s;
132   char c;
133   while ((c=*p++))
134   {
135     if (c==' ') col++;
136     else if (c=='\t') col+=tabSize-(col%tabSize); 
137     else break;
138   }
139   return col;
140 }
141
142 static inline void copyToOutput(const char *s,int len)
143 {
144   int i;
145   if (g_skip) // only add newlines.
146   {
147     for (i=0;i<len;i++) 
148     {
149       if (s[i]=='\n') 
150       {
151         ADDCHAR('\n');
152         //fprintf(stderr,"---> skip %d\n",g_lineNr);
153         g_lineNr++;
154       }
155     }
156   }
157   else if (len>0)
158   {
159     ADDARRAY(s,len);
160     static int tabSize=Config_getInt("TAB_SIZE");
161     for (i=0;i<len;i++) 
162     {
163       switch (s[i])
164       {
165         case '\n': g_col=0; 
166                    //fprintf(stderr,"---> copy %d\n",g_lineNr);
167                    g_lineNr++; break;
168         case '\t': g_col+=tabSize-(g_col%tabSize); break;
169         default:   g_col++; break;
170       }
171     }
172   }
173 }
174
175 static void startCondSection(const char *sectId)
176 {
177   //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
178   CondParser prs;
179   bool expResult = prs.parse(g_fileName,g_lineNr,sectId);
180   g_condStack.push(new CondCtx(g_lineNr,sectId,g_skip));
181   if (!expResult) // not enabled
182   {
183     g_skip=TRUE;
184   }
185 }
186
187 static void endCondSection()
188 {
189   if (g_condStack.isEmpty())
190   {
191     warn(g_fileName,g_lineNr,"Found \\endcond command without matching \\cond");
192     g_skip=FALSE;
193   }
194   else
195   {
196     CondCtx *ctx = g_condStack.pop();
197     g_skip=ctx->skip;
198   }
199   //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
200 }
201
202 /** copies string \a s with length \a len to the output, while 
203  *  replacing any alias commands found in the string.
204  */
205 static void replaceAliases(const char *s)
206 {
207   QCString result = resolveAliasCmd(s);
208   //printf("replaceAliases(%s)->'%s'\n",s,result.data());
209   copyToOutput(result,result.length());
210 }
211
212
213 #undef  YY_INPUT
214 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
215
216 static int yyread(char *buf,int max_size)
217 {
218   int bytesInBuf = g_inBuf->curPos()-g_inBufPos;
219   int bytesToCopy = QMIN(max_size,bytesInBuf);
220   memcpy(buf,g_inBuf->data()+g_inBufPos,bytesToCopy);
221   g_inBufPos+=bytesToCopy;
222   return bytesToCopy;
223 }
224
225 void replaceComment(int offset);
226
227 %}
228
229 %option noyywrap
230
231 %x Scan
232 %x SkipString
233 %x SkipChar
234 %x SComment
235 %x CComment
236 %x Verbatim
237 %x VerbatimCode
238 %x ReadLine
239 %x CondLine
240 %x ReadAliasArgs
241
242 %%
243
244 <Scan>[^"'!\/\n\\#-,]*              { /* eat anything that is not " / , or \n */ 
245                                        copyToOutput(yytext,(int)yyleng);
246                                     }
247 <Scan>[,]                           { /* eat , so we have a nice separator in long initialization lines */ 
248                                        copyToOutput(yytext,(int)yyleng);
249                                     }
250 <Scan>"\"\"\""!                     { /* start of python long comment */
251                                      if (g_lang!=SrcLangExt_Python)
252                                      {
253                                        REJECT;
254                                      }
255                                      else
256                                      {
257                                        g_pythonDocString = TRUE;
258                                        g_nestingCount=0;
259                                        copyToOutput(yytext,(int)yyleng);
260                                        BEGIN(CComment);
261                                      }
262                                    }
263 <Scan>![><!]/.*\n          {
264                                      if (g_lang!=SrcLangExt_Fortran)
265                                      {
266                                        REJECT;
267                                      }
268                                      else
269                                      {
270                                        copyToOutput(yytext,(int)yyleng); 
271                                        g_nestingCount=0;
272                                        BEGIN(CComment);
273                                      }
274                                    }
275 <Scan>[Cc\*][><!]/.*\n     {
276                                      if (g_lang!=SrcLangExt_Fortran)
277                                      {
278                                        REJECT;
279                                      }
280                                      else
281                                      {
282                                        /* check for fixed format; we might have some conditional as part of multilene if like C<5 .and. & */
283                                        if (isFixedForm && (g_col == 0))
284                                        {
285                                          copyToOutput(yytext,(int)yyleng); 
286                                          g_nestingCount=0;
287                                          BEGIN(CComment);
288                                        }
289                                        else
290                                        {
291                                          REJECT;
292                                        }
293                                      }
294                                    }
295 <Scan>!.*\n                {
296                                      if (g_lang!=SrcLangExt_Fortran)
297                                      {
298                                        REJECT;
299                                      }
300                                      else
301                                      {
302                                        copyToOutput(yytext,(int)yyleng); 
303                                      }
304                                    }
305 <Scan>[Cc\*].*\n                   {
306                                      if (g_lang!=SrcLangExt_Fortran)
307                                      {
308                                        REJECT;
309                                      }
310                                      else
311                                      {
312                                        if (g_col == 0)
313                                        {
314                                          copyToOutput(yytext,(int)yyleng); 
315                                        }
316                                        else
317                                        {
318                                          REJECT;
319                                        }
320                                      }
321                                    }
322 <Scan>"\""                         { /* start of a string */ 
323                                      copyToOutput(yytext,(int)yyleng); 
324                                      g_stringContext = YY_START;
325                                      BEGIN(SkipString); 
326                                    }
327 <Scan>'                            {
328                                      copyToOutput(yytext,(int)yyleng); 
329                                      g_charContext = YY_START;
330                                      if (g_lang!=SrcLangExt_VHDL)
331                                      {
332                                        BEGIN(SkipChar);
333                                      }
334                                    }
335 <Scan>\n                           { /* new line */ 
336                                      copyToOutput(yytext,(int)yyleng); 
337                                    }
338 <Scan>"//!"/.*\n[ \t]*"//"[\/!][^\/] | /* start C++ style special comment block */
339 <Scan>("///"[/]*)/[^/].*\n[ \t]*"//"[\/!][^\/] { /* start C++ style special comment block */
340                                      if (g_mlBrief) 
341                                      {
342                                        REJECT; // bail out if we do not need to convert
343                                      }
344                                      else
345                                      {
346                                        int i=3;
347                                        if (yytext[2]=='/')
348                                        {
349                                          while (i<(int)yyleng && yytext[i]=='/') i++;
350                                        }
351                                        g_blockHeadCol=g_col;
352                                        copyToOutput("/**",3); 
353                                        replaceAliases(yytext+i);
354                                        g_inSpecialComment=TRUE;
355                                        //BEGIN(SComment); 
356                                        g_readLineCtx=SComment;
357                                        BEGIN(ReadLine);
358                                      }
359                                    }
360 <Scan>"//##Documentation".*/\n     { /* Start of Rational Rose ANSI C++ comment block */
361                                      if (g_mlBrief) REJECT;
362                                      int i=17; //=strlen("//##Documentation");
363                                      g_blockHeadCol=g_col;
364                                      copyToOutput("/**",3);
365                                      replaceAliases(yytext+i);
366                                      g_inRoseComment=TRUE;
367                                      BEGIN(SComment);
368                                    }
369 <Scan>"//"/.*\n                    { /* one line C++ comment */ 
370                                      g_inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
371                                      copyToOutput(yytext,(int)yyleng); 
372                                      g_readLineCtx=YY_START;
373                                      BEGIN(ReadLine);
374                                    }
375 <Scan>"/**/"                       { /* avoid matching next rule for empty C comment, see bug 711723 */
376                                      copyToOutput(yytext,(int)yyleng);
377                                    }
378 <Scan>"/*"[*!]?                    { /* start of a C comment */
379                                      g_specialComment=(int)yyleng==3;
380                                      g_nestingCount=0;
381                                      copyToOutput(yytext,(int)yyleng); 
382                                      BEGIN(CComment); 
383                                    }
384 <Scan>"#"("#")?                    {
385                                      if (g_lang!=SrcLangExt_Python)
386                                      {
387                                        REJECT;
388                                      }
389                                      else
390                                      {
391                                        copyToOutput(yytext,(int)yyleng); 
392                                        g_nestingCount=0;
393                                        BEGIN(CComment);
394                                      }
395                                    }
396 <Scan>"--!"                        {
397                                      if (g_lang!=SrcLangExt_VHDL)
398                                      {
399                                        REJECT;
400                                      }
401                                      else
402                                      {
403                                        copyToOutput(yytext,(int)yyleng); 
404                                        g_nestingCount=0;
405                                        BEGIN(CComment);
406                                      }
407                                    }
408 <Scan>![><!]                       {
409                                      if (g_lang!=SrcLangExt_Fortran)
410                                      {
411                                        REJECT;
412                                      }
413                                      else
414                                      {
415                                        copyToOutput(yytext,(int)yyleng); 
416                                        g_nestingCount=0;
417                                        BEGIN(CComment);
418                                      }
419                                    }
420 <CComment>"{@code"/[ \t\n]         {
421                                      copyToOutput("@code",5); 
422                                      g_lastCommentContext = YY_START;
423                                      g_javaBlock=1;
424                                      g_blockName=&yytext[1];
425                                      BEGIN(VerbatimCode);
426                                    }
427 <CComment,ReadLine>[\\@]("dot"|"code"|"msc")/[^a-z_A-Z0-9] { /* start of a verbatim block */
428                                      copyToOutput(yytext,(int)yyleng); 
429                                      g_lastCommentContext = YY_START;
430                                      g_javaBlock=0;
431                                      g_blockName=&yytext[1];
432                                      BEGIN(VerbatimCode);
433                                    }
434 <CComment,ReadLine>[\\@]("f$"|"f["|"f{"[a-z]*) {
435                                      copyToOutput(yytext,(int)yyleng); 
436                                      g_blockName=&yytext[1];
437                                      if (g_blockName.at(1)=='[')
438                                      {
439                                        g_blockName.at(1)=']';
440                                      }
441                                      else if (g_blockName.at(1)=='{')
442                                      {
443                                        g_blockName.at(1)='}';
444                                      }
445                                      g_lastCommentContext = YY_START;
446                                      BEGIN(Verbatim);
447                                    }
448 <CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
449                                      copyToOutput(yytext,(int)yyleng); 
450                                      g_blockName=&yytext[1];
451                                      g_lastCommentContext = YY_START;
452                                      BEGIN(Verbatim);
453                                    }
454 <Scan>.                            { /* any ather character */
455                                      copyToOutput(yytext,(int)yyleng); 
456                                    }
457 <Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"docbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}") { /* end of verbatim block */
458                                      copyToOutput(yytext,(int)yyleng);
459                                      if (yytext[1]=='f') // end of formula
460                                      {
461                                        BEGIN(g_lastCommentContext);
462                                      }
463                                      else if (&yytext[4]==g_blockName)
464                                      {
465                                        BEGIN(g_lastCommentContext);
466                                      }
467                                    }
468 <VerbatimCode>"{"                  {
469                                      if (g_javaBlock==0)
470                                      {
471                                        REJECT;
472                                      }
473                                      else
474                                      {
475                                        g_javaBlock++;
476                                        copyToOutput(yytext,(int)yyleng);
477                                      }
478                                    }
479 <VerbatimCode>"}"                  {
480                                      if (g_javaBlock==0)
481                                      {
482                                        REJECT;
483                                      }
484                                      else
485                                      {
486                                        g_javaBlock--;
487                                        if (g_javaBlock==0)
488                                        {
489                                          copyToOutput(" @endcode ",10);
490                                          BEGIN(g_lastCommentContext);
491                                        }
492                                        else
493                                        {
494                                          copyToOutput(yytext,(int)yyleng);
495                                        }
496                                      }
497                                    }
498 <VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc") { /* end of verbatim block */
499                                      copyToOutput(yytext,(int)yyleng);
500                                      if (&yytext[4]==g_blockName)
501                                      {
502                                        BEGIN(g_lastCommentContext);
503                                      }
504                                    }
505 <VerbatimCode>^[ \t]*"//"[\!\/]?   { /* skip leading comments */
506                                      if (!g_inSpecialComment)
507                                      {
508                                        copyToOutput(yytext,(int)yyleng); 
509                                      }
510                                      else
511                                      {
512                                        int l=0;
513                                        while (yytext[l]==' ' || yytext[l]=='\t')
514                                        {
515                                          l++;
516                                        }
517                                        copyToOutput(yytext,l);
518                                        if (yyleng-l==3) // ends with //! or ///
519                                        {
520                                          copyToOutput(" * ",3);
521                                        }
522                                        else // ends with //
523                                        {
524                                          copyToOutput("//",2);
525                                        }
526                                      }
527                                    }
528 <Verbatim,VerbatimCode>[^@\/\\\n{}]* { /* any character not a backslash or new line or } */
529                                      copyToOutput(yytext,(int)yyleng); 
530                                    }
531 <Verbatim,VerbatimCode>\n          { /* new line in verbatim block */
532                                      copyToOutput(yytext,(int)yyleng); 
533                                    }
534 <Verbatim>^[ \t]*"///"             {
535                                      if (g_blockName=="dot" || g_blockName=="msc" || g_blockName.at(0)=='f')
536                                      {
537                                        // see bug 487871, strip /// from dot images and formulas.
538                                        int l=0;
539                                        while (yytext[l]==' ' || yytext[l]=='\t')
540                                        {
541                                          l++;
542                                        }
543                                        copyToOutput(yytext,l);
544                                        copyToOutput("   ",3);
545                                      }
546                                      else // even slashes are verbatim (e.g. \verbatim, \code)
547                                      {
548                                        REJECT;
549                                      }
550                                    }
551 <Verbatim,VerbatimCode>.           { /* any other character */
552                                      copyToOutput(yytext,(int)yyleng); 
553                                    }
554 <SkipString>\\.                    { /* escaped character in string */
555                                      copyToOutput(yytext,(int)yyleng); 
556                                    }
557 <SkipString>"\""                   { /* end of string */ 
558                                      copyToOutput(yytext,(int)yyleng); 
559                                      BEGIN(g_stringContext); 
560                                    }
561 <SkipString>.                      { /* any other string character */ 
562                                      copyToOutput(yytext,(int)yyleng); 
563                                    }
564 <SkipString>\n                     { /* new line inside string (illegal for some compilers) */ 
565                                      copyToOutput(yytext,(int)yyleng); 
566                                    }
567 <SkipChar>\\.                      { /* escaped character */
568                                      copyToOutput(yytext,(int)yyleng); 
569                                    }
570 <SkipChar>'                        { /* end of character literal */ 
571                                      copyToOutput(yytext,(int)yyleng); 
572                                      BEGIN(g_charContext);
573                                    }
574 <SkipChar>.                        { /* any other string character */ 
575                                      copyToOutput(yytext,(int)yyleng); 
576                                    }
577 <SkipChar>\n                       { /* new line character */
578                                      copyToOutput(yytext,(int)yyleng); 
579                                    }
580
581 <CComment>[^\\!@*\n{\"\/]*           { /* anything that is not a '*' or command */ 
582                                      copyToOutput(yytext,(int)yyleng); 
583                                    }
584 <CComment>"*"+[^*/\\@\n{\"]*       { /* stars without slashes */
585                                      copyToOutput(yytext,(int)yyleng); 
586                                    }
587 <CComment>"\"\"\""                 { /* end of Python docstring */
588                                      if (g_lang!=SrcLangExt_Python)
589                                      {
590                                        REJECT;
591                                      }
592                                      else
593                                      {
594                                        g_pythonDocString = FALSE;
595                                        copyToOutput(yytext,(int)yyleng);
596                                        BEGIN(Scan);
597                                      }
598                                    }
599 <CComment>\n                       { /* new line in comment */
600                                      copyToOutput(yytext,(int)yyleng); 
601                                      /* in case of Fortran always end of comment */
602                                      if (g_lang==SrcLangExt_Fortran)
603                                      {
604                                        BEGIN(Scan);
605                                      }
606                                    }
607 <CComment>"/"+"*"                  { /* nested C comment */
608                                      g_nestingCount++;
609                                      copyToOutput(yytext,(int)yyleng); 
610                                    }
611 <CComment>"*"+"/"                  { /* end of C comment */
612                                      if (g_lang==SrcLangExt_Python)
613                                      {
614                                        REJECT;
615                                      }
616                                      else
617                                      {
618                                        if (g_nestingCount<=0)
619                                        {
620                                          copyToOutput(yytext,(int)yyleng);
621                                          BEGIN(Scan);
622                                        }
623                                        else
624                                        {
625                                          g_nestingCount--;
626                                        }
627                                      }
628                                    }
629 <CComment>"\n"/[ \t]*[^#]          { /* end of Python comment */
630                                      if (g_lang!=SrcLangExt_Python || g_pythonDocString)
631                                      {
632                                        REJECT;
633                                      }
634                                      else
635                                      {
636                                        copyToOutput(yytext,(int)yyleng);
637                                        BEGIN(Scan);
638                                      }
639                                    }
640 <CComment>"\n"/[ \t]*[^\-]         { /* end of VHDL comment */
641                                      if (g_lang!=SrcLangExt_VHDL)
642                                      {
643                                        REJECT;
644                                      }
645                                      else
646                                      {
647                                        copyToOutput(yytext,(int)yyleng);
648                                        BEGIN(Scan);
649                                      }
650                                    }
651    /* removed for bug 674842 (bug was introduced in rev 768)
652 <CComment>"'"                      {
653                                      g_charContext = YY_START;
654                                      copyToOutput(yytext,(int)yyleng);
655                                      BEGIN(SkipChar);
656                                    }
657 <CComment>"\""                     {
658                                      g_stringContext = YY_START;
659                                      copyToOutput(yytext,(int)yyleng);
660                                      BEGIN(SkipString);
661                                    }
662    */
663 <CComment>.                        {
664                                      copyToOutput(yytext,(int)yyleng); 
665                                    }
666 <SComment>^[ \t]*"///"[\/]*/\n     {
667                                      replaceComment(0);
668                                    }
669 <SComment>\n[ \t]*"///"[\/]*/\n    {
670                                      replaceComment(1); 
671                                    }
672 <SComment>^[ \t]*"///"[^\/\n]/.*\n { 
673                                      replaceComment(0);
674                                      g_readLineCtx=YY_START;
675                                      BEGIN(ReadLine);
676                                    }
677 <SComment>\n[ \t]*"///"[^\/\n]/.*\n  { 
678                                      replaceComment(1); 
679                                      g_readLineCtx=YY_START;
680                                      BEGIN(ReadLine);
681                                    }
682 <SComment>^[ \t]*"//!"             |    // just //!
683 <SComment>^[ \t]*"//!<"/.*\n       |    // or   //!< something
684 <SComment>^[ \t]*"//!"[^<]/.*\n    {    // or   //!something
685                                      replaceComment(0);
686                                      g_readLineCtx=YY_START;
687                                      BEGIN(ReadLine);
688                                    }
689 <SComment>\n[ \t]*"//!"            |
690 <SComment>\n[ \t]*"//!<"/.*\n      |
691 <SComment>\n[ \t]*"//!"[^<\n]/.*\n { 
692                                      replaceComment(1); 
693                                      g_readLineCtx=YY_START;
694                                      BEGIN(ReadLine);
695                                    }
696 <SComment>^[ \t]*"//##"/.*\n       {
697                                      if (!g_inRoseComment)
698                                      {
699                                        REJECT;
700                                      }
701                                      else
702                                      {
703                                        replaceComment(0);
704                                        g_readLineCtx=YY_START;
705                                        BEGIN(ReadLine);
706                                      }
707                                    }
708 <SComment>\n[ \t]*"//##"/.*\n      {
709                                      if (!g_inRoseComment)
710                                      {
711                                        REJECT;
712                                      }
713                                      else
714                                      {
715                                        replaceComment(1); 
716                                        g_readLineCtx=YY_START;
717                                        BEGIN(ReadLine);
718                                      }
719                                    }
720 <SComment>\n                       { /* end of special comment */
721                                      copyToOutput(" */",3); 
722                                      copyToOutput(yytext,(int)yyleng); 
723                                      g_inSpecialComment=FALSE;
724                                      g_inRoseComment=FALSE;
725                                      BEGIN(Scan); 
726                                    }
727 <ReadLine>[^\\@\n]*/\n             {
728                                      copyToOutput(yytext,(int)yyleng);
729                                      BEGIN(g_readLineCtx);
730                                    }
731 <CComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
732                                      copyToOutput(yytext,(int)yyleng);
733                                    }
734 <CComment,ReadLine>[\\@]"cond"[ \t]+       { // conditional section
735                                      g_condCtx = YY_START; 
736                                      BEGIN(CondLine);
737                                    }
738 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
739                                      bool oldSkip=g_skip;
740                                      endCondSection();
741                                      if (YY_START==CComment && oldSkip && !g_skip) 
742                                      {
743                                        //printf("** Adding start of comment!\n");
744                                        if (g_lang!=SrcLangExt_Python &&
745                                            g_lang!=SrcLangExt_VHDL &&
746                                            g_lang!=SrcLangExt_Fortran)
747                                        {
748                                          ADDCHAR('/');
749                                          ADDCHAR('*');
750                                          if (g_specialComment)
751                                          {
752                                            ADDCHAR('*');
753                                          }
754                                        }
755                                      }
756                                     }
757 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
758                                      bool oldSkip=g_skip;
759                                      startCondSection(yytext);
760                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
761                                          !oldSkip && g_skip) 
762                                      {
763                                        if (g_lang!=SrcLangExt_Python &&
764                                            g_lang!=SrcLangExt_VHDL &&
765                                            g_lang!=SrcLangExt_Fortran)
766                                        {
767                                          ADDCHAR('*');
768                                          ADDCHAR('/');
769                                        }
770                                      }
771                                      if (g_readLineCtx==SComment)
772                                      {
773                                        BEGIN(SComment);
774                                      }
775                                      else
776                                      {
777                                        BEGIN(g_condCtx);
778                                      }
779                                    }
780 <CondLine>[ \t]*
781 <CComment,ReadLine>[\\@]"cond"[ \t\r]*/\n |
782 <CondLine>.                        { // forgot section id?
783                                      if (YY_START!=CondLine) g_condCtx=YY_START;
784                                      bool oldSkip=g_skip;
785                                      startCondSection(" "); // fake section id causing the section to be hidden unconditionally
786                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
787                                          !oldSkip && g_skip) 
788                                      {
789                                        //printf("** Adding terminator for comment!\n");
790                                        if (g_lang!=SrcLangExt_Python &&
791                                            g_lang!=SrcLangExt_VHDL)
792                                        {
793                                          ADDCHAR('*');
794                                          ADDCHAR('/');
795                                        }
796                                      }
797                                      if (*yytext=='\n') g_lineNr++;
798                                      if (g_readLineCtx==SComment)
799                                      {
800                                        BEGIN(SComment);
801                                      }
802                                      else
803                                      {
804                                        BEGIN(g_condCtx);
805                                      }
806                                    }
807 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*  { // expand alias without arguments
808                                      replaceAliases(yytext);
809                                    }
810 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
811                                      g_lastBlockContext=YY_START;
812                                      g_blockCount=1;
813                                      g_aliasString=yytext;
814                                      g_lastEscaped=0;
815                                      BEGIN( ReadAliasArgs );
816                                    }
817 <ReadAliasArgs>^[ \t]*"//"[/!]/[^\n]+   { // skip leading special comments (see bug 618079)
818                                    }
819 <ReadAliasArgs>"*/"                { // oops, end of comment in the middle of an alias?
820                                      if (g_lang==SrcLangExt_Python)
821                                      {
822                                        REJECT;
823                                      }
824                                      else // abort the alias, restart scanning
825                                      {
826                                        copyToOutput(g_aliasString,g_aliasString.length());
827                                        copyToOutput(yytext,(int)yyleng);
828                                        BEGIN(Scan);
829                                      }
830                                    }
831 <ReadAliasArgs>[^{}\n\\\*]+        {
832                                      g_aliasString+=yytext;
833                                      g_lastEscaped=FALSE;
834                                    }
835 <ReadAliasArgs>"\\"                {
836                                      if (g_lastEscaped)  g_lastEscaped=FALSE;
837                                      else                g_lastEscaped=TRUE;
838                                      g_aliasString+=yytext;
839                                    }
840 <ReadAliasArgs>\n                  {
841                                      g_aliasString+=yytext;
842                                      g_lineNr++;
843                                      g_lastEscaped=FALSE;
844                                    }
845 <ReadAliasArgs>"{"                 {
846                                      g_aliasString+=yytext;
847                                      if (!g_lastEscaped) g_blockCount++;
848                                      g_lastEscaped=FALSE;
849                                    }
850 <ReadAliasArgs>"}"                 {
851                                      g_aliasString+=yytext;
852                                      if (!g_lastEscaped) g_blockCount--;
853                                      if (g_blockCount==0)
854                                      {
855                                        replaceAliases(g_aliasString);
856                                        BEGIN( g_lastBlockContext );
857                                      }
858                                      g_lastEscaped=FALSE;
859                                    }
860 <ReadAliasArgs>.                   {
861                                      g_aliasString+=yytext;
862                                      g_lastEscaped=FALSE;
863                                    }
864 <ReadLine>.                        {
865                                      copyToOutput(yytext,(int)yyleng);
866                                    }
867
868 %%
869
870 void replaceComment(int offset)
871 {
872   if (g_mlBrief || g_skip)
873   {
874     copyToOutput(yytext,(int)yyleng);
875   }
876   else
877   {
878     //printf("replaceComment(%s)\n",yytext);
879     int i=computeIndent(&yytext[offset]);
880     if (i==g_blockHeadCol)
881     {
882       replaceCommentMarker(yytext,(int)yyleng);
883     }
884     else
885     {
886       copyToOutput(" */",3);
887       int i;for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
888       g_inSpecialComment=FALSE;
889       BEGIN(Scan);                                            
890     }                                                         
891   }
892 }
893
894 // simplified way to know if this is fixed form
895 // duplicate in fortrancode.l
896 static bool recognizeFixedForm(const char* contents)
897 {
898   int column=0;
899   bool skipLine=FALSE;
900
901   for(int i=0;;i++) {
902     column++;
903
904     switch(contents[i]) {
905       case '\n':
906         column=0;
907         skipLine=FALSE;
908         break;
909       case ' ':
910         break;
911       case '\000':
912         return FALSE;
913       case 'C':
914       case 'c':
915       case '*':
916         if(column==1) return TRUE;
917         if(skipLine) break;
918         return FALSE;
919       case '!':
920         if(column>1 && column<7) return FALSE;
921         skipLine=TRUE;
922         break;
923       default:
924         if(skipLine) break;
925         if(column==7) return TRUE;
926         return FALSE;
927     }
928   }
929   return FALSE;
930 }
931
932
933 /*! This function does three things:
934  *  -# It converts multi-line C++ style comment blocks (that are aligned)
935  *     to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
936  *  -# It replaces aliases with their definition (see ALIASES)
937  *  -# It handles conditional sections (cond...endcond blocks)
938  */
939 void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
940 {
941   //printf("convertCppComments(%s)\n",fileName);
942   g_inBuf    = inBuf;
943   g_outBuf   = outBuf;
944   g_inBufPos = 0;
945   g_col      = 0;
946   g_mlBrief = Config_getBool("MULTILINE_CPP_IS_BRIEF");
947   g_skip     = FALSE;
948   g_fileName = fileName;
949   g_lang = getLanguageFromFileName(fileName);
950   g_pythonDocString = FALSE;
951   g_lineNr   = 1;
952   g_condStack.clear();
953   g_condStack.setAutoDelete(TRUE);
954
955   printlex(yy_flex_debug, TRUE, __FILE__, fileName);
956   isFixedForm = FALSE;
957   if (g_lang==SrcLangExt_Fortran)
958   {
959     isFixedForm = recognizeFixedForm(inBuf->data());
960   }
961
962   if (g_lang==SrcLangExt_Markdown)
963   {
964     g_nestingCount=0;
965     BEGIN(CComment);
966   }
967   else
968   {
969     BEGIN(Scan);
970   }
971   yylex();
972   while (!g_condStack.isEmpty())
973   {
974     CondCtx *ctx = g_condStack.pop();
975     QCString sectionInfo = " ";
976     if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label %s ",ctx->sectionId.data()); 
977     warn(g_fileName,ctx->lineNr,"Conditional section%sdoes not have "
978         "a corresponding \\endcond command within this file.",sectionInfo.data());
979   }
980   if (Debug::isFlagSet(Debug::CommentCnv))
981   {
982     g_outBuf->at(g_outBuf->curPos())='\0';
983     msg("-------------\n%s\n-------------\n",g_outBuf->data());
984   }
985   printlex(yy_flex_debug, FALSE, __FILE__, fileName);
986 }
987
988
989 //----------------------------------------------------------------------------
990 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
991 extern "C" { // some bogus code to keep the compiler happy
992     void commentcnvYYdummy() { yy_flex_realloc(0,0); } 
993 }
994 #endif
995