44e254394fcfa5d04de99a54ee4a51414522e3c0
[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 multilene 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 save 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                                      copyToOutput(yytext,(int)yyleng); 
595                                    }
596 <SkipString>"\""                   { /* end of string */ 
597                                      copyToOutput(yytext,(int)yyleng); 
598                                      BEGIN(g_stringContext); 
599                                    }
600 <SkipString>.                      { /* any other string character */ 
601                                      copyToOutput(yytext,(int)yyleng); 
602                                    }
603 <SkipString>\n                     { /* new line inside string (illegal for some compilers) */ 
604                                      copyToOutput(yytext,(int)yyleng); 
605                                    }
606 <SkipChar>\\.                      { /* escaped character */
607                                      copyToOutput(yytext,(int)yyleng); 
608                                    }
609 <SkipChar>'                        { /* end of character literal */ 
610                                      copyToOutput(yytext,(int)yyleng); 
611                                      BEGIN(g_charContext);
612                                    }
613 <SkipChar>.                        { /* any other string character */ 
614                                      copyToOutput(yytext,(int)yyleng); 
615                                    }
616 <SkipChar>\n                       { /* new line character */
617                                      copyToOutput(yytext,(int)yyleng); 
618                                    }
619
620 <CComment>[^\\!@*\n{\"\/]*           { /* anything that is not a '*' or command */ 
621                                      copyToOutput(yytext,(int)yyleng); 
622                                    }
623 <CComment>"*"+[^*/\\@\n{\"]*       { /* stars without slashes */
624                                      copyToOutput(yytext,(int)yyleng); 
625                                    }
626 <CComment>"\"\"\""                 { /* end of Python docstring */
627                                      if (g_lang!=SrcLangExt_Python)
628                                      {
629                                        REJECT;
630                                      }
631                                      else
632                                      {
633                                        g_pythonDocString = FALSE;
634                                        copyToOutput(yytext,(int)yyleng);
635                                        BEGIN(Scan);
636                                      }
637                                    }
638 <CComment>\n                       { /* new line in comment */
639                                      copyToOutput(yytext,(int)yyleng); 
640                                      /* in case of Fortran always end of comment */
641                                      if (g_lang==SrcLangExt_Fortran)
642                                      {
643                                        BEGIN(Scan);
644                                      }
645                                    }
646 <CComment>"/"+"*"                  { /* nested C comment */
647                                      g_nestingCount++;
648                                      g_commentStack.push(new CommentCtx(g_lineNr));
649                                      copyToOutput(yytext,(int)yyleng); 
650                                    }
651 <CComment>"*"+"/"                  { /* end of C comment */
652                                      if (g_lang==SrcLangExt_Python)
653                                      {
654                                        REJECT;
655                                      }
656                                      else
657                                      {
658                                        copyToOutput(yytext,(int)yyleng);
659                                        if (g_nestingCount<=0)
660                                        {
661                                          BEGIN(Scan);
662                                        }
663                                        else
664                                        {
665                                          g_nestingCount--;
666                                          delete g_commentStack.pop();
667                                        }
668                                      }
669                                    }
670   /* Python an VHDL share CComment, so special attention for ending comments is required */
671 <CComment>"\n"/[ \t]*"#"           {
672                                      if (g_lang!=SrcLangExt_VHDL)
673                                      {
674                                        REJECT;
675                                      }
676                                      else
677                                      {
678                                        if (g_vhdl) // inside --! comment
679                                        {
680                                          g_vhdl = FALSE;
681                                          copyToOutput(yytext,(int)yyleng);
682                                          BEGIN(Scan);
683                                        }
684                                        else // C-type comment
685                                        {
686                                          REJECT;
687                                        }
688                                      }
689                                    }
690 <CComment>"\n"/[ \t]*"-"           {
691                                      if (g_lang!=SrcLangExt_Python || g_pythonDocString)
692                                      {
693                                        REJECT;
694                                      }
695                                      else
696                                      {
697                                        copyToOutput(yytext,(int)yyleng);
698                                        BEGIN(Scan);
699                                      }
700                                    }
701 <CComment>"\n"/[ \t]*[^ \t#\-]     {
702                                      if (g_lang==SrcLangExt_Python)
703                                      {
704                                        if (g_pythonDocString)
705                                        {
706                                          REJECT;
707                                        }
708                                        else
709                                        {
710                                          copyToOutput(yytext,(int)yyleng);
711                                          BEGIN(Scan);
712                                        }
713                                      }
714                                      else if (g_lang==SrcLangExt_VHDL)
715                                      {
716                                        if (g_vhdl) // inside --! comment
717                                        {
718                                          g_vhdl = FALSE;
719                                          copyToOutput(yytext,(int)yyleng);
720                                          BEGIN(Scan);
721                                        }
722                                        else // C-type comment
723                                        {
724                                          REJECT;
725                                        }
726                                      }
727                                      else
728                                      {
729                                        REJECT;
730                                      }
731                                    }
732    /* removed for bug 674842 (bug was introduced in rev 768)
733 <CComment>"'"                      {
734                                      g_charContext = YY_START;
735                                      copyToOutput(yytext,(int)yyleng);
736                                      BEGIN(SkipChar);
737                                    }
738 <CComment>"\""                     {
739                                      g_stringContext = YY_START;
740                                      copyToOutput(yytext,(int)yyleng);
741                                      BEGIN(SkipString);
742                                    }
743    */
744 <CComment>.                        {
745                                      copyToOutput(yytext,(int)yyleng); 
746                                    }
747 <SComment>^[ \t]*"///"[\/]*/\n     {
748                                      replaceComment(0);
749                                    }
750 <SComment>\n[ \t]*"///"[\/]*/\n    {
751                                      replaceComment(1); 
752                                    }
753 <SComment>^[ \t]*"///"[^\/\n]/.*\n { 
754                                      replaceComment(0);
755                                      g_readLineCtx=YY_START;
756                                      BEGIN(ReadLine);
757                                    }
758 <SComment>\n[ \t]*"//"[\/!]("<")?[ \t]*[\\@]"}".*\n {   
759                                      /* See Bug 752712: end the multiline comment when finding a @} or \} command */
760                                      copyToOutput(" */",3); 
761                                      copyToOutput(yytext,(int)yyleng); 
762                                      g_inSpecialComment=FALSE;
763                                      g_inRoseComment=FALSE;
764                                      BEGIN(Scan); 
765                                    }
766 <SComment>\n[ \t]*"///"[^\/\n]/.*\n  { 
767                                      replaceComment(1); 
768                                      g_readLineCtx=YY_START;
769                                      BEGIN(ReadLine);
770                                    }
771 <SComment>^[ \t]*"//!"             |    // just //!
772 <SComment>^[ \t]*"//!<"/.*\n       |    // or   //!< something
773 <SComment>^[ \t]*"//!"[^<]/.*\n    {    // or   //!something
774                                      replaceComment(0);
775                                      g_readLineCtx=YY_START;
776                                      BEGIN(ReadLine);
777                                    }
778 <SComment>\n[ \t]*"//!"            |
779 <SComment>\n[ \t]*"//!<"/.*\n      |
780 <SComment>\n[ \t]*"//!"[^<\n]/.*\n { 
781                                      replaceComment(1); 
782                                      g_readLineCtx=YY_START;
783                                      BEGIN(ReadLine);
784                                    }
785 <SComment>^[ \t]*"//##"/.*\n       {
786                                      if (!g_inRoseComment)
787                                      {
788                                        REJECT;
789                                      }
790                                      else
791                                      {
792                                        replaceComment(0);
793                                        g_readLineCtx=YY_START;
794                                        BEGIN(ReadLine);
795                                      }
796                                    }
797 <SComment>\n[ \t]*"//##"/.*\n      {
798                                      if (!g_inRoseComment)
799                                      {
800                                        REJECT;
801                                      }
802                                      else
803                                      {
804                                        replaceComment(1); 
805                                        g_readLineCtx=YY_START;
806                                        BEGIN(ReadLine);
807                                      }
808                                    }
809 <SComment>\n                       { /* end of special comment */
810                                      copyToOutput(" */",3); 
811                                      copyToOutput(yytext,(int)yyleng); 
812                                      g_inSpecialComment=FALSE;
813                                      g_inRoseComment=FALSE;
814                                      BEGIN(Scan); 
815                                    }
816 <ReadLine>[^\\@\n]*/\n             {
817                                      copyToOutput(yytext,(int)yyleng);
818                                      BEGIN(g_readLineCtx);
819                                    }
820 <CComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
821                                      copyToOutput(yytext,(int)yyleng);
822                                    }
823 <CComment,ReadLine>[\\@]"cond"/[^a-z_A-Z0-9]       { // conditional section
824                                      g_condCtx = YY_START; 
825                                      BEGIN(CondLine);
826                                    }
827 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
828                                      bool oldSkip=g_skip;
829                                      endCondSection();
830                                      if (YY_START==CComment && oldSkip && !g_skip) 
831                                      {
832                                        //printf("** Adding start of comment!\n");
833                                        if (g_lang!=SrcLangExt_Python &&
834                                            g_lang!=SrcLangExt_VHDL &&
835                                            g_lang!=SrcLangExt_Markdown &&
836                                            g_lang!=SrcLangExt_Fortran)
837                                        {
838                                          ADDCHAR('/');
839                                          ADDCHAR('*');
840                                          if (g_specialComment)
841                                          {
842                                            ADDCHAR('*');
843                                          }
844                                        }
845                                      }
846                                     }
847 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
848                                      bool oldSkip=g_skip;
849                                      startCondSection(yytext);
850                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
851                                          !oldSkip && g_skip) 
852                                      {
853                                        if (g_lang!=SrcLangExt_Python &&
854                                            g_lang!=SrcLangExt_VHDL &&
855                                            g_lang!=SrcLangExt_Markdown &&
856                                            g_lang!=SrcLangExt_Fortran)
857                                        {
858                                          ADDCHAR('*');
859                                          ADDCHAR('/');
860                                        }
861                                      }
862                                      if (g_readLineCtx==SComment)
863                                      {
864                                        BEGIN(SComment);
865                                      }
866                                      else
867                                      {
868                                        BEGIN(g_condCtx);
869                                      }
870                                    }
871 <CondLine>[ \t]*
872 <CComment,ReadLine>[\\@]"cond"[ \t\r]*/\n |
873 <CondLine>.                        { // forgot section id?
874                                      if (YY_START!=CondLine) g_condCtx=YY_START;
875                                      bool oldSkip=g_skip;
876                                      startCondSection(" "); // fake section id causing the section to be hidden unconditionally
877                                      if ((g_condCtx==CComment || g_readLineCtx==SComment) && 
878                                          !oldSkip && g_skip) 
879                                      {
880                                        //printf("** Adding terminator for comment!\n");
881                                        if (g_lang!=SrcLangExt_Python &&
882                                            g_lang!=SrcLangExt_VHDL)
883                                        {
884                                          ADDCHAR('*');
885                                          ADDCHAR('/');
886                                        }
887                                      }
888                                      if (*yytext=='\n') g_lineNr++;
889                                      if (g_readLineCtx==SComment)
890                                      {
891                                        BEGIN(SComment);
892                                      }
893                                      else
894                                      {
895                                        BEGIN(g_condCtx);
896                                      }
897                                    }
898 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*  { // expand alias without arguments
899                                      replaceAliases(yytext);
900                                    }
901 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
902                                      g_lastBlockContext=YY_START;
903                                      g_blockCount=1;
904                                      g_aliasString=yytext;
905                                      g_lastEscaped=0;
906                                      BEGIN( ReadAliasArgs );
907                                    }
908 <ReadAliasArgs>^[ \t]*"//"[/!]/[^\n]+   { // skip leading special comments (see bug 618079)
909                                    }
910 <ReadAliasArgs>"*/"                { // oops, end of comment in the middle of an alias?
911                                      if (g_lang==SrcLangExt_Python)
912                                      {
913                                        REJECT;
914                                      }
915                                      else // abort the alias, restart scanning
916                                      {
917                                        copyToOutput(g_aliasString,g_aliasString.length());
918                                        copyToOutput(yytext,(int)yyleng);
919                                        BEGIN(Scan);
920                                      }
921                                    }
922 <ReadAliasArgs>[^{}\n\\\*]+        {
923                                      g_aliasString+=yytext;
924                                      g_lastEscaped=FALSE;
925                                    }
926 <ReadAliasArgs>"\\"                {
927                                      if (g_lastEscaped)  g_lastEscaped=FALSE;
928                                      else                g_lastEscaped=TRUE;
929                                      g_aliasString+=yytext;
930                                    }
931 <ReadAliasArgs>\n                  {
932                                      g_aliasString+=yytext;
933                                      g_lineNr++;
934                                      g_lastEscaped=FALSE;
935                                    }
936 <ReadAliasArgs>"{"                 {
937                                      g_aliasString+=yytext;
938                                      if (!g_lastEscaped) g_blockCount++;
939                                      g_lastEscaped=FALSE;
940                                    }
941 <ReadAliasArgs>"}"                 {
942                                      g_aliasString+=yytext;
943                                      if (!g_lastEscaped) g_blockCount--;
944                                      if (g_blockCount==0)
945                                      {
946                                        replaceAliases(g_aliasString);
947                                        BEGIN( g_lastBlockContext );
948                                      }
949                                      g_lastEscaped=FALSE;
950                                    }
951 <ReadAliasArgs>.                   {
952                                      g_aliasString+=yytext;
953                                      g_lastEscaped=FALSE;
954                                    }
955 <ReadLine>.                        {
956                                      copyToOutput(yytext,(int)yyleng);
957                                    }
958
959 %%
960
961 void replaceComment(int offset)
962 {
963   if (g_mlBrief || g_skip)
964   {
965     copyToOutput(yytext,(int)yyleng);
966   }
967   else
968   {
969     //printf("replaceComment(%s)\n",yytext);
970     int i=computeIndent(&yytext[offset]);
971     if (i==g_blockHeadCol)
972     {
973       replaceCommentMarker(yytext,(int)yyleng);
974     }
975     else
976     {
977       copyToOutput(" */",3);
978       int i;for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
979       g_inSpecialComment=FALSE;
980       BEGIN(Scan);                                            
981     }                                                         
982   }
983 }
984
985 // simplified way to know if this is fixed form
986 // duplicate in fortrancode.l
987 static bool recognizeFixedForm(const char* contents)
988 {
989   int column=0;
990   bool skipLine=FALSE;
991
992   for(int i=0;;i++) {
993     column++;
994
995     switch(contents[i]) {
996       case '\n':
997         column=0;
998         skipLine=FALSE;
999         break;
1000       case ' ':
1001         break;
1002       case '\000':
1003         return FALSE;
1004       case 'C':
1005       case 'c':
1006       case '*':
1007         if(column==1) return TRUE;
1008         if(skipLine) break;
1009         return FALSE;
1010       case '!':
1011         if(column>1 && column<7) return FALSE;
1012         skipLine=TRUE;
1013         break;
1014       default:
1015         if(skipLine) break;
1016         if(column==7) return TRUE;
1017         return FALSE;
1018     }
1019   }
1020   return FALSE;
1021 }
1022
1023
1024 /*! This function does three things:
1025  *  -# It converts multi-line C++ style comment blocks (that are aligned)
1026  *     to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
1027  *  -# It replaces aliases with their definition (see ALIASES)
1028  *  -# It handles conditional sections (cond...endcond blocks)
1029  */
1030 void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
1031 {
1032   //printf("convertCppComments(%s)\n",fileName);
1033   g_inBuf    = inBuf;
1034   g_outBuf   = outBuf;
1035   g_inBufPos = 0;
1036   g_col      = 0;
1037   g_mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
1038   g_skip     = FALSE;
1039   g_fileName = fileName;
1040   g_lang = getLanguageFromFileName(fileName);
1041   g_pythonDocString = FALSE;
1042   g_lineNr   = 1;
1043   g_condStack.clear();
1044   g_condStack.setAutoDelete(TRUE);
1045   g_commentStack.clear();
1046   g_commentStack.setAutoDelete(TRUE);
1047   g_vhdl = FALSE;
1048
1049   printlex(yy_flex_debug, TRUE, __FILE__, fileName);
1050   isFixedForm = FALSE;
1051   if (g_lang==SrcLangExt_Fortran)
1052   {
1053     isFixedForm = recognizeFixedForm(inBuf->data());
1054   }
1055
1056   if (g_lang==SrcLangExt_Markdown)
1057   {
1058     g_nestingCount=0;
1059     BEGIN(CComment);
1060     g_commentStack.push(new CommentCtx(g_lineNr));
1061   }
1062   else
1063   {
1064     BEGIN(Scan);
1065   }
1066   yylex();
1067   while (!g_condStack.isEmpty())
1068   {
1069     CondCtx *ctx = g_condStack.pop();
1070     QCString sectionInfo = " ";
1071     if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label %s ",ctx->sectionId.data()); 
1072     warn(g_fileName,ctx->lineNr,"Conditional section%sdoes not have "
1073         "a corresponding \\endcond command within this file.",sectionInfo.data());
1074   }
1075   if (g_nestingCount>0 && g_lang!=SrcLangExt_Markdown)
1076   {
1077     QCString tmp= "(probable line reference: ";
1078     bool first = TRUE;
1079     while (!g_commentStack.isEmpty())
1080     {
1081       CommentCtx *ctx = g_commentStack.pop();
1082       if (!first) tmp += ", ";
1083       tmp += QCString().setNum(ctx->lineNr);
1084       first = FALSE;
1085       delete ctx;
1086     }
1087     tmp += ")";
1088     warn(g_fileName,g_lineNr,"Reached end of file while still inside a (nested) comment. "
1089         "Nesting level %d %s",g_nestingCount+1,tmp.data()); // add one for "normal" expected end of comment
1090   }
1091   g_commentStack.clear();
1092   g_nestingCount = 0;
1093   if (Debug::isFlagSet(Debug::CommentCnv))
1094   {
1095     g_outBuf->at(g_outBuf->curPos())='\0';
1096     msg("-------------\n%s\n-------------\n",g_outBuf->data());
1097   }
1098   printlex(yy_flex_debug, FALSE, __FILE__, fileName);
1099 }
1100
1101
1102 //----------------------------------------------------------------------------
1103 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
1104 extern "C" { // some bogus code to keep the compiler happy
1105     void commentcnvYYdummy() { yy_flex_realloc(0,0); } 
1106 }
1107 #endif
1108