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