Imported Upstream version 1.8.16
[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=1;
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; // Fortran doesn't have an end comment
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; // Fortran doesn't have an end comment
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                                      if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl))
403                                      {
404                                        REJECT;
405                                      }
406                                      g_specialComment=(int)yyleng==3;
407                                      g_nestingCount=1;
408                                      g_commentStack.clear(); /*  to be on the save side */
409                                      copyToOutput(yytext,(int)yyleng); 
410                                      BEGIN(CComment); 
411                                      g_commentStack.push(new CommentCtx(g_lineNr));
412                                    }
413 <Scan>"#"("#")?                    {
414                                      if (g_lang!=SrcLangExt_Python)
415                                      {
416                                        REJECT;
417                                      }
418                                      else
419                                      {
420                                        copyToOutput(yytext,(int)yyleng); 
421                                        g_nestingCount=0; // Python doesn't have an end comment for #
422                                        g_commentStack.clear(); /*  to be on the save side */
423                                        BEGIN(CComment);
424                                        g_commentStack.push(new CommentCtx(g_lineNr));
425                                      }
426                                    }
427 <Scan>"--!"                        {
428                                      if (g_lang!=SrcLangExt_VHDL)
429                                      {
430                                        REJECT;
431                                      }
432                                      else
433                                      {
434                                        g_vhdl = TRUE;
435                                        copyToOutput(yytext,(int)yyleng); 
436                                        g_nestingCount=0;  // VHDL doesn't have an end comment
437                                        g_commentStack.clear(); /*  to be on the save side */
438                                        BEGIN(CComment);
439                                        g_commentStack.push(new CommentCtx(g_lineNr));
440                                      }
441                                    }
442 <Scan>![><!]                       {
443                                      if (g_lang!=SrcLangExt_Fortran)
444                                      {
445                                        REJECT;
446                                      }
447                                      else
448                                      {
449                                        copyToOutput(yytext,(int)yyleng); 
450                                        g_nestingCount=0;  // Fortran doesn't have an end comment
451                                        g_commentStack.clear(); /*  to be on the save side */
452                                        BEGIN(CComment);
453                                        g_commentStack.push(new CommentCtx(g_lineNr));
454                                      }
455                                    }
456 <CComment>"{@code"/[ \t\n]         {
457                                      copyToOutput("@code",5); 
458                                      g_lastCommentContext = YY_START;
459                                      g_javaBlock=1;
460                                      g_blockName=&yytext[1];
461                                      BEGIN(VerbatimCode);
462                                    }
463 <CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */
464                                      copyToOutput(yytext,(int)yyleng); 
465                                      g_lastCommentContext = YY_START;
466                                      g_javaBlock=0;
467                                      if (qstrcmp(&yytext[1],"startuml")==0)
468                                      {
469                                        g_blockName="uml";
470                                      }
471                                      else
472                                      {
473                                        g_blockName=&yytext[1];
474                                      }
475                                      BEGIN(VerbatimCode);
476                                    }
477 <CComment,ReadLine>[\\@]("f$"|"f["|"f{") {
478                                      copyToOutput(yytext,(int)yyleng); 
479                                      g_blockName=&yytext[1];
480                                      if (g_blockName.at(1)=='[')
481                                      {
482                                        g_blockName.at(1)=']';
483                                      }
484                                      else if (g_blockName.at(1)=='{')
485                                      {
486                                        g_blockName.at(1)='}';
487                                      }
488                                      g_lastCommentContext = YY_START;
489                                      BEGIN(Verbatim);
490                                    }
491 <CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
492                                      copyToOutput(yytext,(int)yyleng); 
493                                      g_blockName=&yytext[1];
494                                      g_lastCommentContext = YY_START;
495                                      BEGIN(Verbatim);
496                                    }
497 <Scan>.                            { /* any ather character */
498                                      copyToOutput(yytext,(int)yyleng); 
499                                    }
500 <Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}") { /* end of verbatim block */
501                                      copyToOutput(yytext,(int)yyleng);
502                                      if (&yytext[1]==g_blockName) // end of formula
503                                      {
504                                        BEGIN(g_lastCommentContext);
505                                      }
506                                      else if (&yytext[4]==g_blockName)
507                                      {
508                                        BEGIN(g_lastCommentContext);
509                                      }
510                                    }
511 <VerbatimCode>"{"                  {
512                                      if (g_javaBlock==0)
513                                      {
514                                        REJECT;
515                                      }
516                                      else
517                                      {
518                                        g_javaBlock++;
519                                        copyToOutput(yytext,(int)yyleng);
520                                      }
521                                    }
522 <VerbatimCode>"}"                  {
523                                      if (g_javaBlock==0)
524                                      {
525                                        REJECT;
526                                      }
527                                      else
528                                      {
529                                        g_javaBlock--;
530                                        if (g_javaBlock==0)
531                                        {
532                                          copyToOutput(" @endcode ",10);
533                                          BEGIN(g_lastCommentContext);
534                                        }
535                                        else
536                                        {
537                                          copyToOutput(yytext,(int)yyleng);
538                                        }
539                                      }
540                                    }
541 <VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */
542                                      copyToOutput(yytext,(int)yyleng);
543                                      if (&yytext[4]==g_blockName)
544                                      {
545                                        BEGIN(g_lastCommentContext);
546                                      }
547                                    }
548 <VerbatimCode>^[ \t]*"//"[\!\/]?   { /* skip leading comments */
549                                      if (!g_inSpecialComment)
550                                      {
551                                        copyToOutput(yytext,(int)yyleng); 
552                                      }
553                                      else
554                                      {
555                                        int l=0;
556                                        while (yytext[l]==' ' || yytext[l]=='\t')
557                                        {
558                                          l++;
559                                        }
560                                        copyToOutput(yytext,l);
561                                        if (yyleng-l==3) // ends with //! or ///
562                                        {
563                                          copyToOutput(" * ",3);
564                                        }
565                                        else // ends with //
566                                        {
567                                          copyToOutput("//",2);
568                                        }
569                                      }
570                                    }
571 <Verbatim,VerbatimCode>[^@\/\\\n{}]* { /* any character not a backslash or new line or } */
572                                      copyToOutput(yytext,(int)yyleng); 
573                                    }
574 <Verbatim,VerbatimCode>\n          { /* new line in verbatim block */
575                                      copyToOutput(yytext,(int)yyleng); 
576                                    }
577 <Verbatim>^[ \t]*"///"             {
578                                      if (g_blockName=="dot" || g_blockName=="msc" || g_blockName=="uml" || g_blockName.at(0)=='f')
579                                      {
580                                        // see bug 487871, strip /// from dot images and formulas.
581                                        int l=0;
582                                        while (yytext[l]==' ' || yytext[l]=='\t')
583                                        {
584                                          l++;
585                                        }
586                                        copyToOutput(yytext,l);
587                                        copyToOutput("   ",3);
588                                      }
589                                      else // even slashes are verbatim (e.g. \verbatim, \code)
590                                      {
591                                        REJECT;
592                                      }
593                                    }
594 <Verbatim,VerbatimCode>.           { /* any other character */
595                                      copyToOutput(yytext,(int)yyleng); 
596                                    }
597 <SkipString>\\.                    { /* escaped character in string */
598                                      if (g_lang==SrcLangExt_Fortran)
599                                      {
600                                        unput(yytext[1]);
601                                        copyToOutput(yytext,1);
602                                      }
603                                      else
604                                      {
605                                        copyToOutput(yytext,(int)yyleng);
606                                      }
607                                    }
608 <SkipString>"\""                   { /* end of string */ 
609                                      copyToOutput(yytext,(int)yyleng); 
610                                      BEGIN(g_stringContext); 
611                                    }
612 <SkipString>.                      { /* any other string character */ 
613                                      copyToOutput(yytext,(int)yyleng); 
614                                    }
615 <SkipString>\n                     { /* new line inside string (illegal for some compilers) */ 
616                                      copyToOutput(yytext,(int)yyleng); 
617                                    }
618 <SkipChar>\\.                      { /* escaped character */
619                                      if (g_lang==SrcLangExt_Fortran)
620                                      {
621                                        unput(yytext[1]);
622                                        copyToOutput(yytext,1);
623                                      }
624                                      else
625                                      {
626                                        copyToOutput(yytext,(int)yyleng);
627                                      }
628                                    }
629 <SkipChar>'                        { /* end of character literal */ 
630                                      copyToOutput(yytext,(int)yyleng); 
631                                      BEGIN(g_charContext);
632                                    }
633 <SkipChar>.                        { /* any other string character */ 
634                                      copyToOutput(yytext,(int)yyleng); 
635                                    }
636 <SkipChar>\n                       { /* new line character */
637                                      copyToOutput(yytext,(int)yyleng); 
638                                    }
639
640 <CComment>[^\\!@*\n{\"\/]*           { /* anything that is not a '*' or command */ 
641                                      copyToOutput(yytext,(int)yyleng); 
642                                    }
643 <CComment>"*"+[^*/\\@\n{\"]*       { /* stars without slashes */
644                                      copyToOutput(yytext,(int)yyleng); 
645                                    }
646 <CComment>"\"\"\""                 { /* end of Python docstring */
647                                      if (g_lang!=SrcLangExt_Python)
648                                      {
649                                        REJECT;
650                                      }
651                                      else
652                                      {
653                                        g_nestingCount--;
654                                        g_pythonDocString = FALSE;
655                                        copyToOutput(yytext,(int)yyleng);
656                                        BEGIN(Scan);
657                                      }
658                                    }
659 <CComment>\n                       { /* new line in comment */
660                                      copyToOutput(yytext,(int)yyleng); 
661                                      /* in case of Fortran always end of comment */
662                                      if (g_lang==SrcLangExt_Fortran)
663                                      {
664                                        BEGIN(Scan);
665                                      }
666                                    }
667 <CComment>"/"+"*"                  { /* nested C comment */
668                                      if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl))
669                                      {
670                                        REJECT;
671                                      }
672                                      g_nestingCount++;
673                                      g_commentStack.push(new CommentCtx(g_lineNr));
674                                      copyToOutput(yytext,(int)yyleng); 
675                                    }
676 <CComment>"*"+"/"                  { /* end of C comment */
677                                      if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl))
678                                      {
679                                        REJECT;
680                                      }
681                                      else
682                                      {
683                                        copyToOutput(yytext,(int)yyleng);
684                                        g_nestingCount--;
685                                        if (g_nestingCount<=0)
686                                        {
687                                          BEGIN(Scan);
688                                        }
689                                        else
690                                        {
691                                          //g_nestingCount--;
692                                          delete g_commentStack.pop();
693                                        }
694                                      }
695                                    }
696   /* Python an VHDL share CComment, so special attention for ending comments is required */
697 <CComment>"\n"/[ \t]*"#"           {
698                                      if (g_lang!=SrcLangExt_VHDL)
699                                      {
700                                        REJECT;
701                                      }
702                                      else
703                                      {
704                                        if (g_vhdl) // inside --! comment
705                                        {
706                                          g_vhdl = FALSE;
707                                          copyToOutput(yytext,(int)yyleng);
708                                          BEGIN(Scan);
709                                        }
710                                        else // C-type comment
711                                        {
712                                          REJECT;
713                                        }
714                                      }
715                                    }
716 <CComment>"\n"/[ \t]*"-"           {
717                                      if (g_lang!=SrcLangExt_Python || g_pythonDocString)
718                                      {
719                                        REJECT;
720                                      }
721                                      else
722                                      {
723                                        copyToOutput(yytext,(int)yyleng);
724                                        BEGIN(Scan);
725                                      }
726                                    }
727 <CComment>"\n"/[ \t]*[^ \t#\-]     {
728                                      if (g_lang==SrcLangExt_Python)
729                                      {
730                                        if (g_pythonDocString)
731                                        {
732                                          REJECT;
733                                        }
734                                        else
735                                        {
736                                          copyToOutput(yytext,(int)yyleng);
737                                          BEGIN(Scan);
738                                        }
739                                      }
740                                      else if (g_lang==SrcLangExt_VHDL)
741                                      {
742                                        if (g_vhdl) // inside --! comment
743                                        {
744                                          g_vhdl = FALSE;
745                                          copyToOutput(yytext,(int)yyleng);
746                                          BEGIN(Scan);
747                                        }
748                                        else // C-type comment
749                                        {
750                                          REJECT;
751                                        }
752                                      }
753                                      else
754                                      {
755                                        REJECT;
756                                      }
757                                    }
758    /* removed for bug 674842 (bug was introduced in rev 768)
759 <CComment>"'"                      {
760                                      g_charContext = YY_START;
761                                      copyToOutput(yytext,(int)yyleng);
762                                      BEGIN(SkipChar);
763                                    }
764 <CComment>"\""                     {
765                                      g_stringContext = YY_START;
766                                      copyToOutput(yytext,(int)yyleng);
767                                      BEGIN(SkipString);
768                                    }
769    */
770 <CComment>.                        {
771                                      copyToOutput(yytext,(int)yyleng); 
772                                    }
773 <SComment>^[ \t]*"///"[\/]*/\n     {
774                                      replaceComment(0);
775                                    }
776 <SComment>\n[ \t]*"///"[\/]*/\n    {
777                                      replaceComment(1); 
778                                    }
779 <SComment>^[ \t]*"///"[^\/\n]/.*\n { 
780                                      replaceComment(0);
781                                      g_readLineCtx=YY_START;
782                                      BEGIN(ReadLine);
783                                    }
784 <SComment>\n[ \t]*"//"[\/!]("<")?[ \t]*[\\@]"}".*\n {   
785                                      /* See Bug 752712: end the multiline comment when finding a @} or \} command */
786                                      copyToOutput(" */",3); 
787                                      copyToOutput(yytext,(int)yyleng); 
788                                      g_inSpecialComment=FALSE;
789                                      g_inRoseComment=FALSE;
790                                      BEGIN(Scan); 
791                                    }
792 <SComment>\n[ \t]*"///"[^\/\n]/.*\n  { 
793                                      replaceComment(1); 
794                                      g_readLineCtx=YY_START;
795                                      BEGIN(ReadLine);
796                                    }
797 <SComment>^[ \t]*"//!"             |    // just //!
798 <SComment>^[ \t]*"//!<"/.*\n       |    // or   //!< something
799 <SComment>^[ \t]*"//!"[^<]/.*\n    {    // or   //!something
800                                      replaceComment(0);
801                                      g_readLineCtx=YY_START;
802                                      BEGIN(ReadLine);
803                                    }
804 <SComment>\n[ \t]*"//!"            |
805 <SComment>\n[ \t]*"//!<"/.*\n      |
806 <SComment>\n[ \t]*"//!"[^<\n]/.*\n { 
807                                      replaceComment(1); 
808                                      g_readLineCtx=YY_START;
809                                      BEGIN(ReadLine);
810                                    }
811 <SComment>^[ \t]*"//##"/.*\n       {
812                                      if (!g_inRoseComment)
813                                      {
814                                        REJECT;
815                                      }
816                                      else
817                                      {
818                                        replaceComment(0);
819                                        g_readLineCtx=YY_START;
820                                        BEGIN(ReadLine);
821                                      }
822                                    }
823 <SComment>\n[ \t]*"//##"/.*\n      {
824                                      if (!g_inRoseComment)
825                                      {
826                                        REJECT;
827                                      }
828                                      else
829                                      {
830                                        replaceComment(1); 
831                                        g_readLineCtx=YY_START;
832                                        BEGIN(ReadLine);
833                                      }
834                                    }
835 <SComment>\n                       { /* end of special comment */
836                                      copyToOutput(" */",3); 
837                                      copyToOutput(yytext,(int)yyleng); 
838                                      g_inSpecialComment=FALSE;
839                                      g_inRoseComment=FALSE;
840                                      BEGIN(Scan); 
841                                    }
842 <ReadLine>"*/"                     {
843                                      copyToOutput("*&zwj;/",7);
844                                    }
845 <ReadLine>"*"                      {
846                                      copyToOutput(yytext,(int)yyleng);
847                                    }
848 <ReadLine>[^\\@\n\*]*              {
849                                      copyToOutput(yytext,(int)yyleng);
850                                    }
851 <ReadLine>[^\\@\n\*]*/\n           {
852                                      copyToOutput(yytext,(int)yyleng);
853                                      BEGIN(g_readLineCtx);
854                                    }
855 <CComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
856                                      copyToOutput(yytext,(int)yyleng);
857                                    }
858 <CComment,ReadLine>[\\@]"cond"/[^a-z_A-Z0-9]       { // conditional section
859                                      g_condCtx = YY_START; 
860                                      BEGIN(CondLine);
861                                    }
862 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
863                                      bool oldSkip=g_skip;
864                                      endCondSection();
865                                      if (YY_START==CComment && oldSkip && !g_skip) 
866                                      {
867                                        //printf("** Adding start of comment!\n");
868                                        if (g_lang!=SrcLangExt_Python &&
869                                            g_lang!=SrcLangExt_VHDL &&
870                                            g_lang!=SrcLangExt_Markdown &&
871                                            g_lang!=SrcLangExt_Fortran)
872                                        {
873                                          ADDCHAR('/');
874                                          ADDCHAR('*');
875                                          if (g_specialComment)
876                                          {
877                                            ADDCHAR('*');
878                                          }
879                                        }
880                                      }
881                                     }
882 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
883                                      bool oldSkip=g_skip;
884                                      startCondSection(yytext);
885                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
886                                          !oldSkip && g_skip) 
887                                      {
888                                        if (g_lang!=SrcLangExt_Python &&
889                                            g_lang!=SrcLangExt_VHDL &&
890                                            g_lang!=SrcLangExt_Markdown &&
891                                            g_lang!=SrcLangExt_Fortran)
892                                        {
893                                          ADDCHAR('*');
894                                          ADDCHAR('/');
895                                        }
896                                      }
897                                      if (g_readLineCtx==SComment)
898                                      {
899                                        BEGIN(SComment);
900                                      }
901                                      else
902                                      {
903                                        BEGIN(g_condCtx);
904                                      }
905                                    }
906 <CondLine>[ \t]*
907 <CComment,ReadLine>[\\@]"cond"[ \t\r]*/\n |
908 <CondLine>.                        { // forgot section id?
909                                      if (YY_START!=CondLine) g_condCtx=YY_START;
910                                      bool oldSkip=g_skip;
911                                      startCondSection(" "); // fake section id causing the section to be hidden unconditionally
912                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
913                                          !oldSkip && g_skip) 
914                                      {
915                                        //printf("** Adding terminator for comment!\n");
916                                        if (g_lang!=SrcLangExt_Python &&
917                                            g_lang!=SrcLangExt_VHDL)
918                                        {
919                                          ADDCHAR('*');
920                                          ADDCHAR('/');
921                                        }
922                                      }
923                                      if (*yytext=='\n') g_lineNr++;
924                                      if (g_readLineCtx==SComment)
925                                      {
926                                        BEGIN(SComment);
927                                      }
928                                      else
929                                      {
930                                        BEGIN(g_condCtx);
931                                      }
932                                    }
933 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*  { // expand alias without arguments
934                                      replaceAliases(yytext);
935                                    }
936 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
937                                      g_lastBlockContext=YY_START;
938                                      g_blockCount=1;
939                                      g_aliasString=yytext;
940                                      g_lastEscaped=0;
941                                      BEGIN( ReadAliasArgs );
942                                    }
943 <ReadAliasArgs>^[ \t]*"//"[/!]/[^\n]+   { // skip leading special comments (see bug 618079)
944                                    }
945 <ReadAliasArgs>"*/"                { // oops, end of comment in the middle of an alias?
946                                      if (g_lang==SrcLangExt_Python)
947                                      {
948                                        REJECT;
949                                      }
950                                      else // abort the alias, restart scanning
951                                      {
952                                        copyToOutput(g_aliasString,g_aliasString.length());
953                                        copyToOutput(yytext,(int)yyleng);
954                                        BEGIN(Scan);
955                                      }
956                                    }
957 <ReadAliasArgs>[^{}\n\\\*]+        {
958                                      g_aliasString+=yytext;
959                                      g_lastEscaped=FALSE;
960                                    }
961 <ReadAliasArgs>"\\"                {
962                                      if (g_lastEscaped)  g_lastEscaped=FALSE;
963                                      else                g_lastEscaped=TRUE;
964                                      g_aliasString+=yytext;
965                                    }
966 <ReadAliasArgs>\n                  {
967                                      g_aliasString+=yytext;
968                                      g_lineNr++;
969                                      g_lastEscaped=FALSE;
970                                    }
971 <ReadAliasArgs>"{"                 {
972                                      g_aliasString+=yytext;
973                                      if (!g_lastEscaped) g_blockCount++;
974                                      g_lastEscaped=FALSE;
975                                    }
976 <ReadAliasArgs>"}"                 {
977                                      g_aliasString+=yytext;
978                                      if (!g_lastEscaped) g_blockCount--;
979                                      if (g_blockCount==0)
980                                      {
981                                        replaceAliases(g_aliasString);
982                                        BEGIN( g_lastBlockContext );
983                                      }
984                                      g_lastEscaped=FALSE;
985                                    }
986 <ReadAliasArgs>.                   {
987                                      g_aliasString+=yytext;
988                                      g_lastEscaped=FALSE;
989                                    }
990 <ReadLine>.                        {
991                                      copyToOutput(yytext,(int)yyleng);
992                                    }
993
994 %%
995
996 void replaceComment(int offset)
997 {
998   if (g_mlBrief || g_skip)
999   {
1000     copyToOutput(yytext,(int)yyleng);
1001   }
1002   else
1003   {
1004     //printf("replaceComment(%s)\n",yytext);
1005     int i=computeIndent(&yytext[offset]);
1006     if (i==g_blockHeadCol)
1007     {
1008       replaceCommentMarker(yytext,(int)yyleng);
1009     }
1010     else
1011     {
1012       copyToOutput(" */",3);
1013       int i;for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1014       g_inSpecialComment=FALSE;
1015       BEGIN(Scan);                                            
1016     }                                                         
1017   }
1018 }
1019
1020 // simplified way to know if this is fixed form
1021 // duplicate in fortrancode.l
1022 static bool recognizeFixedForm(const char* contents)
1023 {
1024   int column=0;
1025   bool skipLine=FALSE;
1026
1027   for(int i=0;;i++) {
1028     column++;
1029
1030     switch(contents[i]) {
1031       case '\n':
1032         column=0;
1033         skipLine=FALSE;
1034         break;
1035       case ' ':
1036         break;
1037       case '\000':
1038         return FALSE;
1039       case 'C':
1040       case 'c':
1041       case '*':
1042         if(column==1) return TRUE;
1043         if(skipLine) break;
1044         return FALSE;
1045       case '!':
1046         if(column>1 && column<7) return FALSE;
1047         skipLine=TRUE;
1048         break;
1049       default:
1050         if(skipLine) break;
1051         if(column==7) return TRUE;
1052         return FALSE;
1053     }
1054   }
1055   return FALSE;
1056 }
1057
1058
1059 /*! This function does three things:
1060  *  -# It converts multi-line C++ style comment blocks (that are aligned)
1061  *     to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
1062  *  -# It replaces aliases with their definition (see ALIASES)
1063  *  -# It handles conditional sections (cond...endcond blocks)
1064  */
1065 void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
1066 {
1067   //printf("convertCppComments(%s)\n",fileName);
1068   g_inBuf    = inBuf;
1069   g_outBuf   = outBuf;
1070   g_inBufPos = 0;
1071   g_col      = 0;
1072   g_mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
1073   g_skip     = FALSE;
1074   g_fileName = fileName;
1075   g_lang = getLanguageFromFileName(fileName);
1076   g_pythonDocString = FALSE;
1077   g_lineNr   = 1;
1078   g_condStack.clear();
1079   g_condStack.setAutoDelete(TRUE);
1080   g_commentStack.clear();
1081   g_commentStack.setAutoDelete(TRUE);
1082   g_vhdl = FALSE;
1083
1084   printlex(yy_flex_debug, TRUE, __FILE__, fileName);
1085   isFixedForm = FALSE;
1086   if (g_lang==SrcLangExt_Fortran)
1087   {
1088     isFixedForm = recognizeFixedForm(inBuf->data());
1089   }
1090
1091   if (g_lang==SrcLangExt_Markdown)
1092   {
1093     g_nestingCount=0;
1094     BEGIN(CComment);
1095     g_commentStack.push(new CommentCtx(g_lineNr));
1096   }
1097   else
1098   {
1099     BEGIN(Scan);
1100   }
1101   yylex();
1102   while (!g_condStack.isEmpty())
1103   {
1104     CondCtx *ctx = g_condStack.pop();
1105     QCString sectionInfo = " ";
1106     if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx->sectionId.stripWhiteSpace().data());
1107     warn(g_fileName,ctx->lineNr,"Conditional section%sdoes not have "
1108         "a corresponding \\endcond command within this file.",sectionInfo.data());
1109   }
1110   if (g_nestingCount>0 && g_lang!=SrcLangExt_Markdown)
1111   {
1112     QCString tmp= "(probable line reference: ";
1113     bool first = TRUE;
1114     while (!g_commentStack.isEmpty())
1115     {
1116       CommentCtx *ctx = g_commentStack.pop();
1117       if (!first) tmp += ", ";
1118       tmp += QCString().setNum(ctx->lineNr);
1119       first = FALSE;
1120       delete ctx;
1121     }
1122     tmp += ")";
1123     warn(g_fileName,g_lineNr,"Reached end of file while still inside a (nested) comment. "
1124         "Nesting level %d %s",g_nestingCount,tmp.data());
1125   }
1126   g_commentStack.clear();
1127   g_nestingCount = 0;
1128   if (Debug::isFlagSet(Debug::CommentCnv))
1129   {
1130     g_outBuf->at(g_outBuf->curPos())='\0';
1131     Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: %s\n"
1132                  "output=[\n%s]\n-----------\n",fileName,g_outBuf->data()
1133                 );
1134   }
1135   printlex(yy_flex_debug, FALSE, __FILE__, fileName);
1136 }
1137
1138
1139 //----------------------------------------------------------------------------
1140 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
1141 extern "C" { // some bogus code to keep the compiler happy
1142     void commentcnvYYdummy() { yy_flex_realloc(0,0); } 
1143 }
1144 #endif
1145