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