Imported Upstream version 1.8.4
[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                                      BEGIN(SkipChar);
324                                    }
325 <Scan>\n                           { /* new line */ 
326                                      copyToOutput(yytext,(int)yyleng); 
327                                    }
328 <Scan>"//!"/.*\n[ \t]*"//"[\/!][^\/] | /* start C++ style special comment block */
329 <Scan>("///"[/]*)/[^/].*\n[ \t]*"//"[\/!][^\/] { /* start C++ style special comment block */
330                                      if (g_mlBrief) 
331                                      {
332                                        REJECT; // bail out if we do not need to convert
333                                      }
334                                      else
335                                      {
336                                        int i=3;
337                                        if (yytext[2]=='/')
338                                        {
339                                          while (i<(int)yyleng && yytext[i]=='/') i++;
340                                        }
341                                        g_blockHeadCol=g_col;
342                                        copyToOutput("/**",3); 
343                                        replaceAliases(yytext+i);
344                                        g_inSpecialComment=TRUE;
345                                        //BEGIN(SComment); 
346                                        g_readLineCtx=SComment;
347                                        BEGIN(ReadLine);
348                                      }
349                                    }
350 <Scan>"//##Documentation".*/\n     { /* Start of Rational Rose ANSI C++ comment block */
351                                      if (g_mlBrief) REJECT;
352                                      int i=17; //=strlen("//##Documentation");
353                                      g_blockHeadCol=g_col;
354                                      copyToOutput("/**",3);
355                                      replaceAliases(yytext+i);
356                                      g_inRoseComment=TRUE;
357                                      BEGIN(SComment);
358                                    }
359 <Scan>"//"/.*\n                    { /* one line C++ comment */ 
360                                      g_inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
361                                      copyToOutput(yytext,(int)yyleng); 
362                                      g_readLineCtx=YY_START;
363                                      BEGIN(ReadLine);
364                                    }
365 <Scan>"/*"[*!]?                    { /* start of a C comment */
366                                      g_specialComment=(int)yyleng==3;
367                                      copyToOutput(yytext,(int)yyleng); 
368                                      BEGIN(CComment); 
369                                    }
370 <Scan>"#"("#")?                    {
371                                      if (g_lang!=SrcLangExt_Python)
372                                      {
373                                        REJECT;
374                                      }
375                                      else
376                                      {
377                                        copyToOutput(yytext,(int)yyleng); 
378                                        BEGIN(CComment);
379                                      }
380                                    }
381 <Scan>"--!"                        {
382                                      if (g_lang!=SrcLangExt_VHDL)
383                                      {
384                                        REJECT;
385                                      }
386                                      else
387                                      {
388                                        copyToOutput(yytext,(int)yyleng); 
389                                        BEGIN(CComment);
390                                      }
391                                    }
392 <Scan>![><!]                       {
393                                      if (g_lang!=SrcLangExt_Fortran)
394                                      {
395                                        REJECT;
396                                      }
397                                      else
398                                      {
399                                        copyToOutput(yytext,(int)yyleng); 
400                                        BEGIN(CComment);
401                                      }
402                                    }
403 <CComment>"{@code"/[ \t\n]         {
404                                      copyToOutput("@code",5); 
405                                      g_lastCommentContext = YY_START;
406                                      g_javaBlock=1;
407                                      g_blockName=&yytext[1];
408                                      BEGIN(VerbatimCode);
409                                    }
410 <CComment,ReadLine>[\\@]("dot"|"code"|"msc")/[^a-z_A-Z0-9] { /* start of a verbatim block */
411                                      copyToOutput(yytext,(int)yyleng); 
412                                      g_lastCommentContext = YY_START;
413                                      g_javaBlock=0;
414                                      g_blockName=&yytext[1];
415                                      BEGIN(VerbatimCode);
416                                    }
417 <CComment,ReadLine>[\\@]("f$"|"f["|"f{"[a-z]*) {
418                                      copyToOutput(yytext,(int)yyleng); 
419                                      g_blockName=&yytext[1];
420                                      if (g_blockName.at(1)=='[')
421                                      {
422                                        g_blockName.at(1)=']';
423                                      }
424                                      else if (g_blockName.at(1)=='{')
425                                      {
426                                        g_blockName.at(1)='}';
427                                      }
428                                      g_lastCommentContext = YY_START;
429                                      BEGIN(Verbatim);
430                                    }
431 <CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
432                                      copyToOutput(yytext,(int)yyleng); 
433                                      g_blockName=&yytext[1];
434                                      g_lastCommentContext = YY_START;
435                                      BEGIN(Verbatim);
436                                    }
437 <Scan>.                            { /* any ather character */
438                                      copyToOutput(yytext,(int)yyleng); 
439                                    }
440 <Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"docbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}") { /* end of verbatim block */
441                                      copyToOutput(yytext,(int)yyleng);
442                                      if (yytext[1]=='f') // end of formula
443                                      {
444                                        BEGIN(g_lastCommentContext);
445                                      }
446                                      else if (&yytext[4]==g_blockName)
447                                      {
448                                        BEGIN(g_lastCommentContext);
449                                      }
450                                    }
451 <VerbatimCode>"{"                  {
452                                      if (g_javaBlock==0)
453                                      {
454                                        REJECT;
455                                      }
456                                      else
457                                      {
458                                        g_javaBlock++;
459                                        copyToOutput(yytext,(int)yyleng);
460                                      }
461                                    }
462 <VerbatimCode>"}"                  {
463                                      if (g_javaBlock==0)
464                                      {
465                                        REJECT;
466                                      }
467                                      else
468                                      {
469                                        g_javaBlock--;
470                                        if (g_javaBlock==0)
471                                        {
472                                          copyToOutput(" @endcode ",10);
473                                          BEGIN(g_lastCommentContext);
474                                        }
475                                        else
476                                        {
477                                          copyToOutput(yytext,(int)yyleng);
478                                        }
479                                      }
480                                    }
481 <VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc") { /* end of verbatim block */
482                                      copyToOutput(yytext,(int)yyleng);
483                                      if (&yytext[4]==g_blockName)
484                                      {
485                                        BEGIN(g_lastCommentContext);
486                                      }
487                                    }
488 <VerbatimCode>^[ \t]*"//"[\!\/]?   { /* skip leading comments */
489                                      if (!g_inSpecialComment)
490                                      {
491                                        copyToOutput(yytext,(int)yyleng); 
492                                      }
493                                      else
494                                      {
495                                        int l=0;
496                                        while (yytext[l]==' ' || yytext[l]=='\t')
497                                        {
498                                          l++;
499                                        }
500                                        copyToOutput(yytext,l);
501                                        if (yyleng-l==3) // ends with //! or ///
502                                        {
503                                          copyToOutput(" * ",3);
504                                        }
505                                        else // ends with //
506                                        {
507                                          copyToOutput("//",2);
508                                        }
509                                      }
510                                    }
511 <Verbatim,VerbatimCode>[^@\/\\\n{}]* { /* any character not a backslash or new line or } */
512                                      copyToOutput(yytext,(int)yyleng); 
513                                    }
514 <Verbatim,VerbatimCode>\n          { /* new line in verbatim block */
515                                      copyToOutput(yytext,(int)yyleng); 
516                                    }
517 <Verbatim>^[ \t]*"///"             {
518                                      if (g_blockName=="dot" || g_blockName=="msc" || g_blockName.at(0)=='f')
519                                      {
520                                        // see bug 487871, strip /// from dot images and formulas.
521                                        int l=0;
522                                        while (yytext[l]==' ' || yytext[l]=='\t')
523                                        {
524                                          l++;
525                                        }
526                                        copyToOutput(yytext,l);
527                                        copyToOutput("   ",3);
528                                      }
529                                      else // even slashes are verbatim (e.g. \verbatim, \code)
530                                      {
531                                        REJECT;
532                                      }
533                                    }
534 <Verbatim,VerbatimCode>.           { /* any other character */
535                                      copyToOutput(yytext,(int)yyleng); 
536                                    }
537 <SkipString>\\.                    { /* escaped character in string */
538                                      copyToOutput(yytext,(int)yyleng); 
539                                    }
540 <SkipString>"\""                   { /* end of string */ 
541                                      copyToOutput(yytext,(int)yyleng); 
542                                      BEGIN(g_stringContext); 
543                                    }
544 <SkipString>.                      { /* any other string character */ 
545                                      copyToOutput(yytext,(int)yyleng); 
546                                    }
547 <SkipString>\n                     { /* new line inside string (illegal for some compilers) */ 
548                                      copyToOutput(yytext,(int)yyleng); 
549                                    }
550 <SkipChar>\\.                      { /* escaped character */
551                                      copyToOutput(yytext,(int)yyleng); 
552                                    }
553 <SkipChar>'                        { /* end of character literal */ 
554                                      copyToOutput(yytext,(int)yyleng); 
555                                      BEGIN(g_charContext);
556                                    }
557 <SkipChar>.                        { /* any other string character */ 
558                                      copyToOutput(yytext,(int)yyleng); 
559                                    }
560 <SkipChar>\n                       { /* new line character */
561                                      copyToOutput(yytext,(int)yyleng); 
562                                    }
563
564 <CComment>[^\\!@*\n{\"]*           { /* anything that is not a '*' or command */ 
565                                      copyToOutput(yytext,(int)yyleng); 
566                                    }
567 <CComment>"*"+[^*/\\@\n{\"]*       { /* stars without slashes */
568                                      copyToOutput(yytext,(int)yyleng); 
569                                    }
570 <CComment>"\"\"\""                 { /* end of Python docstring */
571                                      if (g_lang!=SrcLangExt_Python)
572                                      {
573                                        REJECT;
574                                      }
575                                      else
576                                      {
577                                        g_pythonDocString = FALSE;
578                                        copyToOutput(yytext,(int)yyleng);
579                                        BEGIN(Scan);
580                                      }
581                                    }
582 <CComment>\n                       { /* new line in comment */
583                                      copyToOutput(yytext,(int)yyleng); 
584                                      /* in case of Fortran always end of comment */
585                                      if (g_lang==SrcLangExt_Fortran)
586                                      {
587                                        BEGIN(Scan);
588                                      }
589                                    }
590 <CComment>"*"+"/"                  { /* end of C comment */
591                                      if (g_lang==SrcLangExt_Python)
592                                      {
593                                        REJECT;
594                                      }
595                                      else
596                                      {
597                                        copyToOutput(yytext,(int)yyleng);
598                                        BEGIN(Scan);
599                                      }
600                                    }
601 <CComment>"\n"/[ \t]*[^#]          { /* end of Python comment */
602                                      if (g_lang!=SrcLangExt_Python || g_pythonDocString)
603                                      {
604                                        REJECT;
605                                      }
606                                      else
607                                      {
608                                        copyToOutput(yytext,(int)yyleng);
609                                        BEGIN(Scan);
610                                      }
611                                    }
612 <CComment>"\n"/[ \t]*[^\-]         { /* end of VHDL comment */
613                                      if (g_lang!=SrcLangExt_VHDL)
614                                      {
615                                        REJECT;
616                                      }
617                                      else
618                                      {
619                                        copyToOutput(yytext,(int)yyleng);
620                                        BEGIN(Scan);
621                                      }
622                                    }
623    /* removed for bug 674842 (bug was introduced in rev 768)
624 <CComment>"'"                      {
625                                      g_charContext = YY_START;
626                                      copyToOutput(yytext,(int)yyleng);
627                                      BEGIN(SkipChar);
628                                    }
629 <CComment>"\""                     {
630                                      g_stringContext = YY_START;
631                                      copyToOutput(yytext,(int)yyleng);
632                                      BEGIN(SkipString);
633                                    }
634    */
635 <CComment>.                        {
636                                      copyToOutput(yytext,(int)yyleng); 
637                                    }
638 <SComment>^[ \t]*"///"[\/]*/\n     {
639                                      replaceComment(0);
640                                    }
641 <SComment>\n[ \t]*"///"[\/]*/\n    {
642                                      replaceComment(1); 
643                                    }
644 <SComment>^[ \t]*"///"[^\/\n]/.*\n { 
645                                      replaceComment(0);
646                                      g_readLineCtx=YY_START;
647                                      BEGIN(ReadLine);
648                                    }
649 <SComment>\n[ \t]*"///"[^\/\n]/.*\n  { 
650                                      replaceComment(1); 
651                                      g_readLineCtx=YY_START;
652                                      BEGIN(ReadLine);
653                                    }
654 <SComment>^[ \t]*"//!"             |    // just //!
655 <SComment>^[ \t]*"//!<"/.*\n       |    // or   //!< something
656 <SComment>^[ \t]*"//!"[^<]/.*\n    {    // or   //!something
657                                      replaceComment(0);
658                                      g_readLineCtx=YY_START;
659                                      BEGIN(ReadLine);
660                                    }
661 <SComment>\n[ \t]*"//!"            |
662 <SComment>\n[ \t]*"//!<"/.*\n      |
663 <SComment>\n[ \t]*"//!"[^<\n]/.*\n { 
664                                      replaceComment(1); 
665                                      g_readLineCtx=YY_START;
666                                      BEGIN(ReadLine);
667                                    }
668 <SComment>^[ \t]*"//##"/.*\n       {
669                                      if (!g_inRoseComment)
670                                      {
671                                        REJECT;
672                                      }
673                                      else
674                                      {
675                                        replaceComment(0);
676                                        g_readLineCtx=YY_START;
677                                        BEGIN(ReadLine);
678                                      }
679                                    }
680 <SComment>\n[ \t]*"//##"/.*\n      {
681                                      if (!g_inRoseComment)
682                                      {
683                                        REJECT;
684                                      }
685                                      else
686                                      {
687                                        replaceComment(1); 
688                                        g_readLineCtx=YY_START;
689                                        BEGIN(ReadLine);
690                                      }
691                                    }
692 <SComment>\n                       { /* end of special comment */
693                                      copyToOutput(" */",3); 
694                                      copyToOutput(yytext,(int)yyleng); 
695                                      g_inSpecialComment=FALSE;
696                                      g_inRoseComment=FALSE;
697                                      BEGIN(Scan); 
698                                    }
699 <ReadLine>[^\\@\n]*/\n             {
700                                      copyToOutput(yytext,(int)yyleng);
701                                      BEGIN(g_readLineCtx);
702                                    }
703 <CComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
704                                      copyToOutput(yytext,(int)yyleng);
705                                    }
706 <CComment,ReadLine>[\\@]"cond"[ \t]+       { // conditional section
707                                      g_condCtx = YY_START; 
708                                      BEGIN(CondLine);
709                                    }
710 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
711                                      bool oldSkip=g_skip;
712                                      endCondSection();
713                                      if (YY_START==CComment && oldSkip && !g_skip) 
714                                      {
715                                        //printf("** Adding start of comment!\n");
716                                        if (g_lang!=SrcLangExt_Python &&
717                                            g_lang!=SrcLangExt_VHDL &&
718                                            g_lang!=SrcLangExt_Fortran)
719                                        {
720                                          ADDCHAR('/');
721                                          ADDCHAR('*');
722                                          if (g_specialComment)
723                                          {
724                                            ADDCHAR('*');
725                                          }
726                                        }
727                                      }
728                                     }
729 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
730                                      bool oldSkip=g_skip;
731                                      startCondSection(yytext);
732                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
733                                          !oldSkip && g_skip) 
734                                      {
735                                        if (g_lang!=SrcLangExt_Python &&
736                                            g_lang!=SrcLangExt_VHDL &&
737                                            g_lang!=SrcLangExt_Fortran)
738                                        {
739                                          ADDCHAR('*');
740                                          ADDCHAR('/');
741                                        }
742                                      }
743                                      if (g_readLineCtx==SComment)
744                                      {
745                                        BEGIN(SComment);
746                                      }
747                                      else
748                                      {
749                                        BEGIN(g_condCtx);
750                                      }
751                                    }
752 <CondLine>[ \t]*
753 <CComment,ReadLine>[\\@]"cond"[ \t\r]*/\n |
754 <CondLine>.                        { // forgot section id?
755                                      if (YY_START!=CondLine) g_condCtx=YY_START;
756                                      bool oldSkip=g_skip;
757                                      startCondSection(" "); // fake section id causing the section to be hidden unconditionally
758                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
759                                          !oldSkip && g_skip) 
760                                      {
761                                        //printf("** Adding terminator for comment!\n");
762                                        if (g_lang!=SrcLangExt_Python &&
763                                            g_lang!=SrcLangExt_VHDL)
764                                        {
765                                          ADDCHAR('*');
766                                          ADDCHAR('/');
767                                        }
768                                      }
769                                      if (*yytext=='\n') g_lineNr++;
770                                      if (g_readLineCtx==SComment)
771                                      {
772                                        BEGIN(SComment);
773                                      }
774                                      else
775                                      {
776                                        BEGIN(g_condCtx);
777                                      }
778                                    }
779 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*  { // expand alias without arguments
780                                      replaceAliases(yytext);
781                                    }
782 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
783                                      g_lastBlockContext=YY_START;
784                                      g_blockCount=1;
785                                      g_aliasString=yytext;
786                                      g_lastEscaped=0;
787                                      BEGIN( ReadAliasArgs );
788                                    }
789 <ReadAliasArgs>^[ \t]*"//"[/!]/[^\n]+   { // skip leading special comments (see bug 618079)
790                                    }
791 <ReadAliasArgs>"*/"                { // oops, end of comment in the middle of an alias?
792                                      if (g_lang==SrcLangExt_Python)
793                                      {
794                                        REJECT;
795                                      }
796                                      else // abort the alias, restart scanning
797                                      {
798                                        copyToOutput(g_aliasString,g_aliasString.length());
799                                        copyToOutput(yytext,(int)yyleng);
800                                        BEGIN(Scan);
801                                      }
802                                    }
803 <ReadAliasArgs>[^{}\n\\\*]+        {
804                                      g_aliasString+=yytext;
805                                      g_lastEscaped=FALSE;
806                                    }
807 <ReadAliasArgs>"\\"                {
808                                      if (g_lastEscaped)  g_lastEscaped=FALSE;
809                                      else                g_lastEscaped=TRUE;
810                                      g_aliasString+=yytext;
811                                    }
812 <ReadAliasArgs>\n                  {
813                                      g_aliasString+=yytext;
814                                      g_lineNr++;
815                                      g_lastEscaped=FALSE;
816                                    }
817 <ReadAliasArgs>"{"                 {
818                                      g_aliasString+=yytext;
819                                      if (!g_lastEscaped) g_blockCount++;
820                                      g_lastEscaped=FALSE;
821                                    }
822 <ReadAliasArgs>"}"                 {
823                                      g_aliasString+=yytext;
824                                      if (!g_lastEscaped) g_blockCount--;
825                                      if (g_blockCount==0)
826                                      {
827                                        replaceAliases(g_aliasString);
828                                        BEGIN( g_lastBlockContext );
829                                      }
830                                      g_lastEscaped=FALSE;
831                                    }
832 <ReadAliasArgs>.                   {
833                                      g_aliasString+=yytext;
834                                      g_lastEscaped=FALSE;
835                                    }
836 <ReadLine>.                        {
837                                      copyToOutput(yytext,(int)yyleng);
838                                    }
839
840 %%
841
842 void replaceComment(int offset)
843 {
844   if (g_mlBrief || g_skip)
845   {
846     copyToOutput(yytext,(int)yyleng);
847   }
848   else
849   {
850     //printf("replaceComment(%s)\n",yytext);
851     int i=computeIndent(&yytext[offset]);
852     if (i==g_blockHeadCol)
853     {
854       replaceCommentMarker(yytext,(int)yyleng);
855     }
856     else
857     {
858       copyToOutput(" */",3);
859       int i;for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
860       g_inSpecialComment=FALSE;
861       BEGIN(Scan);                                            
862     }                                                         
863   }
864 }
865
866 // simplified way to know if this is fixed form
867 // duplicate in fortrancode.l
868 static bool recognizeFixedForm(const char* contents)
869 {
870   int column=0;
871   bool skipLine=FALSE;
872
873   for(int i=0;;i++) {
874     column++;
875
876     switch(contents[i]) {
877       case '\n':
878         column=0;
879         skipLine=FALSE;
880         break;
881       case ' ':
882         break;
883       case '\000':
884         return FALSE;
885       case 'C':
886       case 'c':
887       case '*':
888         if(column==1) return TRUE;
889         if(skipLine) break;
890         return FALSE;
891       case '!':
892         if(column>1 && column<7) return FALSE;
893         skipLine=TRUE;
894         break;
895       default:
896         if(skipLine) break;
897         if(column==7) return TRUE;
898         return FALSE;
899     }
900   }
901   return FALSE;
902 }
903
904
905 /*! This function does three things:
906  *  -# It converts multi-line C++ style comment blocks (that are aligned)
907  *     to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
908  *  -# It replaces aliases with their definition (see ALIASES)
909  *  -# It handles conditional sections (cond...endcond blocks)
910  */
911 void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
912 {
913   //printf("convertCppComments(%s)\n",fileName);
914   g_inBuf    = inBuf;
915   g_outBuf   = outBuf;
916   g_inBufPos = 0;
917   g_col      = 0;
918   g_mlBrief = Config_getBool("MULTILINE_CPP_IS_BRIEF");
919   g_skip     = FALSE;
920   g_fileName = fileName;
921   g_lang = getLanguageFromFileName(fileName);
922   g_pythonDocString = FALSE;
923   g_lineNr   = 1;
924   g_condStack.clear();
925   g_condStack.setAutoDelete(TRUE);
926
927   isFixedForm = FALSE;
928   if (g_lang==SrcLangExt_Fortran)
929   {
930     isFixedForm = recognizeFixedForm(inBuf->data());
931   }
932
933   if (g_lang==SrcLangExt_Markdown)
934   {
935     BEGIN(CComment);
936   }
937   else
938   {
939     BEGIN(Scan);
940   }
941   yylex();
942   while (!g_condStack.isEmpty())
943   {
944     CondCtx *ctx = g_condStack.pop();
945     QCString sectionInfo = " ";
946     if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label %s ",ctx->sectionId.data()); 
947     warn(g_fileName,ctx->lineNr,"Conditional section%sdoes not have "
948         "a corresponding \\endcond command within this file.",sectionInfo.data());
949   }
950   if (Debug::isFlagSet(Debug::CommentCnv))
951   {
952     g_outBuf->at(g_outBuf->curPos())='\0';
953     msg("-------------\n%s\n-------------\n",g_outBuf->data());
954   }
955 }
956
957
958 //----------------------------------------------------------------------------
959 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
960 extern "C" { // some bogus code to keep the compiler happy
961     void commentcnvYYdummy() { yy_flex_realloc(0,0); } 
962 }
963 #endif
964