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