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