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