Imported Upstream version 1.9.2
[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 %option reentrant
20 %option extra-type="struct commentcnvYY_state *"
21 %top{
22 #include <stdint.h>
23 }
24
25 %{
26
27   
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stack>
31 #include <algorithm>
32
33 #include "bufstr.h"
34 #include "debug.h"
35 #include "message.h"
36 #include "config.h"
37 #include "doxygen.h"
38 #include "util.h"
39 #include "condparser.h"
40
41 #include <assert.h>
42
43 #define YY_NO_INPUT 1
44 #define YY_NO_UNISTD_H 1
45
46 #define ADDCHAR(c)    yyextra->outBuf->addChar(c)
47 #define ADDARRAY(a,s) yyextra->outBuf->addArray(a,s)
48
49 #define USE_STATE2STRING 0
50   
51 struct CondCtx
52 {
53   CondCtx(int line,QCString id,bool b) 
54     : lineNr(line),sectionId(id), skip(b) {}
55   int lineNr;
56   QCString sectionId;
57   bool skip;
58 };
59   
60 struct CommentCtx
61 {
62   CommentCtx(int line) 
63     : lineNr(line) {}
64   int lineNr;
65 };
66   
67 struct commentcnvYY_state
68 {
69   BufStr * inBuf = 0;
70   BufStr * outBuf = 0;
71   yy_size_t inBufPos = 0;
72   int      col = 0;
73   int      blockHeadCol = 0;
74   bool     mlBrief = FALSE;
75   int      readLineCtx = 0;
76   bool     skip = FALSE;
77   QCString fileName;
78   int      lineNr = 0;
79   int      condCtx = 0;
80   std::stack<CondCtx> condStack;
81   std::stack<int> commentStack;
82   QCString blockName;
83   int      lastCommentContext = 0;
84   bool     inSpecialComment = FALSE;
85   bool     inRoseComment= FALSE;
86   int      stringContext = 0;
87   int      charContext = 0;
88   int      javaBlock = 0;
89   bool     specialComment = FALSE;
90
91   QCString aliasString;
92   int      blockCount = 0;
93   bool     lastEscaped = FALSE;
94   int      lastBlockContext= 0;
95   bool     pythonDocString = FALSE;
96   int      nestingCount= 0;
97
98   bool     vhdl = FALSE; // for VHDL old style --! comment
99
100   SrcLangExt lang = SrcLangExt_Unknown;
101   bool       isFixedForm = FALSE; // For Fortran
102 };
103
104 #if USE_STATE2STRING
105 static const char *stateToString(int state);
106 #endif
107 static inline int computeIndent(const char *s);
108
109 static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len);
110 static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len);
111 static void startCondSection(yyscan_t yyscanner,const QCString &sectId);
112 static void endCondSection(yyscan_t yyscanner);
113 static void handleCondSectionId(yyscan_t yyscanner,const char *expression);
114 static void replaceAliases(yyscan_t yyscanner,const QCString &s);
115 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
116 static void replaceComment(yyscan_t yyscanner,int offset);
117 static void clearCommentStack(yyscan_t yyscanner);
118
119
120
121
122 #undef  YY_INPUT
123 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
124
125
126 %}
127
128 MAILADR   ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
129
130 %option noyywrap
131
132 %x Scan
133 %x SkipString
134 %x SkipChar
135 %x SComment
136 %x CComment
137 %x CNComment
138 %x Verbatim
139 %x VerbatimCode
140 %x ReadLine
141 %x CondLine
142 %x ReadAliasArgs
143
144   //- start: NUMBER -------------------------------------------------------------------------
145   // Note same defines in code.l: keep in sync
146 DECIMAL_INTEGER  [1-9][0-9']*[0-9]?[uU]?[lL]?[lL]?
147 HEXADECIMAL_INTEGER  "0"[xX][0-9a-zA-Z']+[0-9a-zA-Z]?
148 OCTAL_INTEGER  "0"[0-7][0-7']+[0-7]?
149 BINARY_INTEGER  "0"[bB][01][01']*[01]?
150 INTEGER_NUMBER {DECIMAL_INTEGER}|{HEXADECIMAL_INTEGER}|{OCTAL_INTEGER}|{BINARY_INTEGER}
151
152 FP_SUF [fFlL]
153
154 DIGIT_SEQ [0-9][0-9']*[0-9]?
155 FRAC_CONST {DIGIT_SEQ}"."|{DIGIT_SEQ}?"."{DIGIT_SEQ}
156 FP_EXP [eE][+-]?{DIGIT_SEQ}
157 DEC_FP1 {FRAC_CONST}{FP_EXP}?{FP_SUF}?
158 DEC_FP2 {DIGIT_SEQ}{FP_EXP}{FP_SUF}
159
160 HEX_DIGIT_SEQ [0-9a-fA-F][0-9a-fA-F']*[0-9a-fA-F]?
161 HEX_FRAC_CONST {HEX_DIGIT_SEQ}"."|{HEX_DIGIT_SEQ}?"."{HEX_DIGIT_SEQ}
162 BIN_EXP [pP][+-]?{DIGIT_SEQ}
163 HEX_FP1 "0"[xX]{HEX_FRAC_CONST}{BIN_EXP}{FP_SUF}?
164 HEX_FP2 "0"[xX]{HEX_DIGIT_SEQ}{BIN_EXP}{FP_SUF}?
165
166 FLOAT_DECIMAL {DEC_FP1}|{DEC_FP2}
167 FLOAT_HEXADECIMAL {HEX_FP1}|{HEX_FP2}
168 FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL}
169 NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER}
170   //- end: NUMBER ---------------------------------------------------------------------------
171
172   // C start comment 
173 CCS   "/\*"
174   // C end comment
175 CCE   "*\/"
176   // Cpp comment 
177 CPPC  "/\/"
178
179   // Optional any character
180 ANYopt .*
181
182   // Optional white space
183 WSopt [ \t\r]*
184   // readline non special
185 RLopt [^\\@\n\*\/]*
186   // Optional slash
187 SLASHopt [/]*
188
189 %%
190
191 <Scan>{NUMBER}                      { //Note similar code in code.l
192                                       if (yyextra->lang!=SrcLangExt_Cpp) REJECT;
193                                       copyToOutput(yyscanner,yytext,(int)yyleng); 
194                                     }
195 <Scan>[^"'!\/\n\\#,\-=; \t]*        { /* eat anything that is not " / , or \n */
196                                        copyToOutput(yyscanner,yytext,(int)yyleng);
197                                     }
198 <Scan>[,= ;\t]                      { /* eat , so we have a nice separator in long initialization lines */ 
199                                        copyToOutput(yyscanner,yytext,(int)yyleng);
200                                     }
201 <Scan>"\"\"\""!                     { /* start of python long comment */
202                                      if (yyextra->lang!=SrcLangExt_Python)
203                                      {
204                                        REJECT;
205                                      }
206                                      else
207                                      {
208                                        yyextra->pythonDocString = TRUE;
209                                        yyextra->nestingCount=1;
210                                        clearCommentStack(yyscanner); /*  to be on the save side */
211                                        copyToOutput(yyscanner,yytext,(int)yyleng);
212                                        BEGIN(CComment);
213                                        yyextra->commentStack.push(yyextra->lineNr);
214                                      }
215                                    }
216 <Scan>![><!]/.*\n          {
217                                      if (yyextra->lang!=SrcLangExt_Fortran)
218                                      {
219                                        REJECT;
220                                      }
221                                      else
222                                      {
223                                        copyToOutput(yyscanner,yytext,(int)yyleng); 
224                                        yyextra->nestingCount=0; // Fortran doesn't have an end comment
225                                        clearCommentStack(yyscanner); /*  to be on the save side */
226                                        BEGIN(CComment);
227                                        yyextra->commentStack.push(yyextra->lineNr);
228                                      }
229                                    }
230 <Scan>[Cc\*][><!]/.*\n     {
231                                      if (yyextra->lang!=SrcLangExt_Fortran)
232                                      {
233                                        REJECT;
234                                      }
235                                      else
236                                      {
237                                        /* check for fixed format; we might have some conditional as part of multiline if like C<5 .and. & */
238                                        if (yyextra->isFixedForm && (yyextra->col == 0))
239                                        {
240                                          copyToOutput(yyscanner,yytext,(int)yyleng); 
241                                          yyextra->nestingCount=0; // Fortran doesn't have an end comment
242                                          clearCommentStack(yyscanner); /*  to be on the save side */
243                                          BEGIN(CComment);
244                                          yyextra->commentStack.push(yyextra->lineNr);
245                                        }
246                                        else
247                                        {
248                                          REJECT;
249                                        }
250                                      }
251                                    }
252 <Scan>!.*\n                {
253                                      if (yyextra->lang!=SrcLangExt_Fortran)
254                                      {
255                                        REJECT;
256                                      }
257                                      else
258                                      {
259                                        copyToOutput(yyscanner,yytext,(int)yyleng); 
260                                      }
261                                    }
262 <Scan>[Cc\*].*\n                   {
263                                      if (yyextra->lang!=SrcLangExt_Fortran)
264                                      {
265                                        REJECT;
266                                      }
267                                      else
268                                      {
269                                        if (yyextra->col == 0)
270                                        {
271                                          copyToOutput(yyscanner,yytext,(int)yyleng); 
272                                        }
273                                        else
274                                        {
275                                          REJECT;
276                                        }
277                                      }
278                                    }
279 <Scan>"\""                         { /* start of a string */ 
280                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
281                                      yyextra->stringContext = YY_START;
282                                      BEGIN(SkipString); 
283                                    }
284 <Scan>'                            {
285                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
286                                      yyextra->charContext = YY_START;
287                                      if (yyextra->lang!=SrcLangExt_VHDL)
288                                      {
289                                        BEGIN(SkipChar);
290                                      }
291                                    }
292 <Scan>\n                           { /* new line */ 
293                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
294                                    }
295 <Scan>{CPPC}"!"/.*\n[ \t]*{CPPC}[\/!][^\/] | /* start C++ style special comment block */
296 <Scan>({CPPC}"/"[/]*)/[^/].*\n[ \t]*{CPPC}[\/!][^\/] { /* start C++ style special comment block */
297                                      if (yyextra->mlBrief) 
298                                      {
299                                        REJECT; // bail out if we do not need to convert
300                                      }
301                                      else
302                                      {
303                                        int i=3;
304                                        if (yytext[2]=='/')
305                                        {
306                                          while (i<(int)yyleng && yytext[i]=='/') i++;
307                                        }
308                                        yyextra->blockHeadCol=yyextra->col;
309                                        copyToOutput(yyscanner,"/**",3); 
310                                        replaceAliases(yyscanner,QCString(yytext+i));
311                                        yyextra->inSpecialComment=TRUE;
312                                        //BEGIN(SComment); 
313                                        yyextra->readLineCtx=SComment;
314                                        BEGIN(ReadLine);
315                                      }
316                                    }
317 <Scan>{CPPC}"##Documentation"{ANYopt}/\n           { /* Start of Rational Rose ANSI C++ comment block */
318                                      if (yyextra->mlBrief) REJECT;
319                                      int i=17; //=strlen("//##Documentation");
320                                      yyextra->blockHeadCol=yyextra->col;
321                                      copyToOutput(yyscanner,"/**",3);
322                                      replaceAliases(yyscanner,QCString(yytext+i));
323                                      yyextra->inRoseComment=TRUE;
324                                      BEGIN(SComment);
325                                    }
326 <Scan>{CPPC}[!\/]/.*\n[ \t]*{CPPC}[|\/][ \t]*[@\\]"}" { // next line contains an end marker, see bug 752712
327                                      yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
328                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
329                                      yyextra->readLineCtx=YY_START;
330                                      BEGIN(ReadLine);
331                                    }
332 <Scan>{CPPC}/.*\n                          { /* one line C++ comment */ 
333                                      yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
334                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
335                                      yyextra->readLineCtx=YY_START;
336                                      BEGIN(ReadLine);
337                                    }
338 <Scan>{CCS}{CCE}                       { /* avoid matching next rule for empty C comment, see bug 711723 */
339                                      copyToOutput(yyscanner,yytext,(int)yyleng);
340                                    }
341 <Scan>{CCS}[*!]?                           { /* start of a C comment */
342                                      if (yyextra->lang==SrcLangExt_Python)
343                                      {
344                                        REJECT;
345                                      }
346                                      yyextra->specialComment=(int)yyleng==3;
347                                      yyextra->nestingCount=1;
348                                      clearCommentStack(yyscanner); /*  to be on the save side */
349                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
350                                      if (yyextra->specialComment)
351                                        BEGIN(CComment); 
352                                      else
353                                        BEGIN(CNComment); 
354                                      yyextra->commentStack.push(yyextra->lineNr);
355                                    }
356 <Scan>"#"("#")?                    {
357                                      if (yyextra->lang!=SrcLangExt_Python)
358                                      {
359                                        REJECT;
360                                      }
361                                      else
362                                      {
363                                        copyToOutput(yyscanner,yytext,(int)yyleng); 
364                                        yyextra->nestingCount=0; // Python doesn't have an end comment for #
365                                        clearCommentStack(yyscanner); /*  to be on the save side */
366                                        BEGIN(CComment);
367                                        yyextra->commentStack.push(yyextra->lineNr);
368                                      }
369                                    }
370 <Scan>"--"[^!][^\n]*               {
371                                      if (yyextra->lang!=SrcLangExt_VHDL)
372                                      {
373                                        REJECT;
374                                      }
375                                      else
376                                      {
377                                        copyToOutput(yyscanner,yytext,(int)yyleng); 
378                                      }
379                                    }
380 <Scan>"--!"                        {
381                                      if (yyextra->lang!=SrcLangExt_VHDL)
382                                      {
383                                        REJECT;
384                                      }
385                                      else
386                                      {
387                                        yyextra->vhdl = TRUE;
388                                        copyToOutput(yyscanner,yytext,(int)yyleng); 
389                                        yyextra->nestingCount=0;  // VHDL doesn't have an end comment
390                                        clearCommentStack(yyscanner); /*  to be on the save side */
391                                        BEGIN(CComment);
392                                        yyextra->commentStack.push(yyextra->lineNr);
393                                      }
394                                    }
395 <Scan>![><!]                       {
396                                      if (yyextra->lang!=SrcLangExt_Fortran)
397                                      {
398                                        REJECT;
399                                      }
400                                      else
401                                      {
402                                        copyToOutput(yyscanner,yytext,(int)yyleng); 
403                                        yyextra->nestingCount=0;  // Fortran doesn't have an end comment
404                                        clearCommentStack(yyscanner); /*  to be on the save side */
405                                        BEGIN(CComment);
406                                        yyextra->commentStack.push(yyextra->lineNr);
407                                      }
408                                    }
409 <CComment,CNComment,ReadLine>{MAILADR}      |
410 <CComment,CNComment,ReadLine>"<"{MAILADR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block
411                                      copyToOutput(yyscanner,yytext,(int)yyleng);
412                                    }
413 <CComment>"{@code"/[ \t\n]         {
414                                      copyToOutput(yyscanner,"@code",5); 
415                                      yyextra->lastCommentContext = YY_START;
416                                      yyextra->javaBlock=1;
417                                      yyextra->blockName=&yytext[1];
418                                      BEGIN(VerbatimCode);
419                                    }
420 <CComment,ReadLine>^[ \t]*("```"[`]*|"~~~"[~]*) { /* start of markdown code block */
421                                      if (!Config_getBool(MARKDOWN_SUPPORT))
422                                      {
423                                        REJECT;
424                                      }
425                                      copyToOutput(yyscanner,yytext,(int)yyleng);
426                                      yyextra->lastCommentContext = YY_START;
427                                      yyextra->javaBlock=0;
428                                      yyextra->blockName=QCString(yytext).stripWhiteSpace().left(3);
429                                      BEGIN(VerbatimCode);
430                                    }
431 <CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */
432                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
433                                      yyextra->lastCommentContext = YY_START;
434                                      yyextra->javaBlock=0;
435                                      if (qstrcmp(&yytext[1],"startuml")==0)
436                                      {
437                                        yyextra->blockName="uml";
438                                      }
439                                      else
440                                      {
441                                        yyextra->blockName=&yytext[1];
442                                      }
443                                      BEGIN(VerbatimCode);
444                                    }
445 <CComment,ReadLine>[\\@]("f$"|"f["|"f{"|"f(") {
446                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
447                                      yyextra->blockName=&yytext[1];
448                                      if (yyextra->blockName.at(1)=='[')
449                                      {
450                                        yyextra->blockName.at(1)=']';
451                                      }
452                                      else if (yyextra->blockName.at(1)=='{')
453                                      {
454                                        yyextra->blockName.at(1)='}';
455                                      }
456                                      else if (yyextra->blockName.at(1)=='(')
457                                      {
458                                        yyextra->blockName.at(1)=')';
459                                      }
460                                      yyextra->lastCommentContext = YY_START;
461                                      BEGIN(Verbatim);
462                                    }
463 <CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
464                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
465                                      yyextra->blockName=&yytext[1];
466                                      yyextra->lastCommentContext = YY_START;
467                                      BEGIN(Verbatim);
468                                    }
469 <Scan>"\\\""                       { /* escaped double quote */
470                                      copyToOutput(yyscanner,yytext,(int)yyleng);
471                                    }
472 <Scan>"\\\\"                       { /* escaped backslash */
473                                      copyToOutput(yyscanner,yytext,(int)yyleng);
474                                    }
475 <Scan>.                            { /* any other character */
476                                      copyToOutput(yyscanner,yytext,(int)yyleng);
477                                    }
478 <Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
479                                      copyToOutput(yyscanner,yytext,(int)yyleng);
480                                      if (&yytext[1]==yyextra->blockName) // end of formula
481                                      {
482                                        BEGIN(yyextra->lastCommentContext);
483                                      }
484                                      else if (&yytext[4]==yyextra->blockName)
485                                      {
486                                        BEGIN(yyextra->lastCommentContext);
487                                      }
488                                    }
489 <VerbatimCode>"{"                  {
490                                      if (yyextra->javaBlock==0)
491                                      {
492                                        REJECT;
493                                      }
494                                      else
495                                      {
496                                        yyextra->javaBlock++;
497                                        copyToOutput(yyscanner,yytext,(int)yyleng);
498                                      }
499                                    }
500 <VerbatimCode>"}"                  {
501                                      if (yyextra->javaBlock==0)
502                                      {
503                                        REJECT;
504                                      }
505                                      else
506                                      {
507                                        yyextra->javaBlock--;
508                                        if (yyextra->javaBlock==0)
509                                        {
510                                          copyToOutput(yyscanner," @endcode ",10);
511                                          BEGIN(yyextra->lastCommentContext);
512                                        }
513                                        else
514                                        {
515                                          copyToOutput(yyscanner,yytext,(int)yyleng);
516                                        }
517                                      }
518                                    }
519 <VerbatimCode>("```"[`]*|"~~~"[~]*) { /* end of markdown code block */
520                                      copyToOutput(yyscanner,yytext,(int)yyleng);
521                                      if (yytext[0]==yyextra->blockName[0])
522                                      {
523                                        BEGIN(yyextra->lastCommentContext);
524                                      }
525                                    }
526 <VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */
527                                      copyToOutput(yyscanner,yytext,(int)yyleng);
528                                      if (&yytext[4]==yyextra->blockName)
529                                      {
530                                        BEGIN(yyextra->lastCommentContext);
531                                      }
532                                    }
533 <VerbatimCode>^[ \t]*{CPPC}[\!\/]?   { /* skip leading comments */
534                                      if (!yyextra->inSpecialComment)
535                                      {
536                                        copyToOutput(yyscanner,yytext,(int)yyleng); 
537                                      }
538                                      else
539                                      {
540                                        int l=0;
541                                        while (yytext[l]==' ' || yytext[l]=='\t')
542                                        {
543                                          l++;
544                                        }
545                                        copyToOutput(yyscanner,yytext,l);
546                                        if (yyleng-l==3) // ends with //! or ///
547                                        {
548                                          copyToOutput(yyscanner," * ",3);
549                                        }
550                                        else // ends with //
551                                        {
552                                          copyToOutput(yyscanner,"//",2);
553                                        }
554                                      }
555                                    }
556 <Verbatim,VerbatimCode>[^`~@\/\\\n{}]* { /* any character not a backslash or new line or } */
557                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
558                                    }
559 <Verbatim,VerbatimCode>\n          { /* new line in verbatim block */
560                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
561                                    }
562 <Verbatim>^[ \t]*{CPPC}[/!]          {
563                                      if (yyextra->blockName=="dot" || yyextra->blockName=="msc" || yyextra->blockName=="uml" || yyextra->blockName.at(0)=='f')
564                                      {
565                                        // see bug 487871, strip /// from dot images and formulas.
566                                        int l=0;
567                                        while (yytext[l]==' ' || yytext[l]=='\t')
568                                        {
569                                          l++;
570                                        }
571                                        copyToOutput(yyscanner,yytext,l);
572                                        copyToOutput(yyscanner,"   ",3);
573                                      }
574                                      else // even slashes are verbatim (e.g. \verbatim, \code)
575                                      {
576                                        REJECT;
577                                      }
578                                    }
579 <Verbatim,VerbatimCode>.           { /* any other character */
580                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
581                                    }
582 <SkipString>\\.                    { /* escaped character in string */
583                                      if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
584                                      {
585                                        unput(yytext[1]);
586                                        copyToOutput(yyscanner,yytext,1);
587                                      }
588                                      else
589                                      {
590                                        copyToOutput(yyscanner,yytext,(int)yyleng);
591                                      }
592                                    }
593 <SkipString>"\""                   { /* end of string */ 
594                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
595                                      BEGIN(yyextra->stringContext); 
596                                    }
597 <SkipString>.                      { /* any other string character */ 
598                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
599                                    }
600 <SkipString>\n                     { /* new line inside string (illegal for some compilers) */ 
601                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
602                                    }
603 <SkipChar>\\.                      { /* escaped character */
604                                      if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
605                                      {
606                                        unput(yytext[1]);
607                                        copyToOutput(yyscanner,yytext,1);
608                                      }
609                                      else
610                                      {
611                                        copyToOutput(yyscanner,yytext,(int)yyleng);
612                                      }
613                                    }
614 <SkipChar>'                        { /* end of character literal */ 
615                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
616                                      BEGIN(yyextra->charContext);
617                                    }
618 <SkipChar>.                        { /* any other string character */ 
619                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
620                                    }
621 <SkipChar>\n                       { /* new line character */
622                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
623                                    }
624
625 <CComment,CNComment>[^ `~<\\!@*\n{\"\/]*     { /* anything that is not a '*' or command */ 
626                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
627                                    }
628 <CComment,CNComment>"*"+[^*\/\\@\n{\"]*      { /* stars without slashes */
629                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
630                                    }
631 <CComment>"\"\"\""                 { /* end of Python docstring */
632                                      if (yyextra->lang!=SrcLangExt_Python)
633                                      {
634                                        REJECT;
635                                      }
636                                      else
637                                      {
638                                        yyextra->nestingCount--;
639                                        yyextra->pythonDocString = FALSE;
640                                        copyToOutput(yyscanner,yytext,(int)yyleng);
641                                        BEGIN(Scan);
642                                      }
643                                    }
644 <CComment,CNComment>\n                       { /* new line in comment */
645                                      copyToOutput(yyscanner,yytext,(int)yyleng);
646                                      /* in case of Fortran always end of comment */
647                                      if (yyextra->lang==SrcLangExt_Fortran)
648                                      {
649                                        BEGIN(Scan);
650                                      }
651                                    }
652 <CComment,CNComment>"/"+"*"                  { /* nested C comment */
653                                      if (yyextra->lang==SrcLangExt_Python ||
654                                          yyextra->lang==SrcLangExt_Markdown)
655                                      {
656                                        REJECT;
657                                      }
658                                      yyextra->nestingCount++;
659                                      yyextra->commentStack.push(yyextra->lineNr);
660                                      copyToOutput(yyscanner,yytext,(int)yyleng);
661                                    }
662 <CComment,CNComment>"*"+"/"                  { /* end of C comment */
663                                      if (yyextra->lang==SrcLangExt_Python ||
664                                          yyextra->lang==SrcLangExt_Markdown)
665                                      {
666                                        REJECT;
667                                      }
668                                      else
669                                      {
670                                        copyToOutput(yyscanner,yytext,(int)yyleng);
671                                        yyextra->nestingCount--;
672                                        if (yyextra->nestingCount<=0)
673                                        {
674                                          BEGIN(Scan);
675                                        }
676                                        else
677                                        {
678                                          //yyextra->nestingCount--;
679                                          yyextra->commentStack.pop();
680                                        }
681                                      }
682                                    }
683   /* Python an VHDL share CComment,CNComment, so special attention for ending comments is required */
684 <CComment,CNComment>"\n"/[ \t]*"#"         {
685                                      if (yyextra->lang!=SrcLangExt_VHDL)
686                                      {
687                                        REJECT;
688                                      }
689                                      else
690                                      {
691                                        if (yyextra->vhdl) // inside --! comment
692                                        {
693                                          yyextra->vhdl = FALSE;
694                                          copyToOutput(yyscanner,yytext,(int)yyleng);
695                                          BEGIN(Scan);
696                                        }
697                                        else // C-type comment
698                                        {
699                                          REJECT;
700                                        }
701                                      }
702                                    }
703 <CComment,CNComment>"\n"/[ \t]*"-"         {
704                                      if (yyextra->lang!=SrcLangExt_Python || yyextra->pythonDocString)
705                                      {
706                                        REJECT;
707                                      }
708                                      else
709                                      {
710                                        copyToOutput(yyscanner,yytext,(int)yyleng);
711                                        BEGIN(Scan);
712                                      }
713                                    }
714 <CComment,CNComment>"\n"/[ \t]*[^ \t#\-]           {
715                                      if (yyextra->lang==SrcLangExt_Python)
716                                      {
717                                        if (yyextra->pythonDocString)
718                                        {
719                                          REJECT;
720                                        }
721                                        else
722                                        {
723                                          copyToOutput(yyscanner,yytext,(int)yyleng);
724                                          BEGIN(Scan);
725                                        }
726                                      }
727                                      else if (yyextra->lang==SrcLangExt_VHDL)
728                                      {
729                                        if (yyextra->vhdl) // inside --! comment
730                                        {
731                                          yyextra->vhdl = FALSE;
732                                          copyToOutput(yyscanner,yytext,(int)yyleng);
733                                          BEGIN(Scan);
734                                        }
735                                        else // C-type comment
736                                        {
737                                          REJECT;
738                                        }
739                                      }
740                                      else
741                                      {
742                                        REJECT;
743                                      }
744                                    }
745    /* removed for bug 674842 (bug was introduced in rev 768)
746 <CComment,CNComment>"'"                    {
747                                      yyextra->charContext = YY_START;
748                                      copyToOutput(yyscanner,yytext,(int)yyleng);
749                                      BEGIN(SkipChar);
750                                    }
751 <CComment,CNComment>"\""                           {
752                                      yyextra->stringContext = YY_START;
753                                      copyToOutput(yyscanner,yytext,(int)yyleng);
754                                      BEGIN(SkipString);
755                                    }
756    */
757 <CComment,CNComment>.                      {
758                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
759                                    }
760 <SComment>^[ \t]*{CPPC}"/"{SLASHopt}/\n     {
761                                      replaceComment(yyscanner,0);
762                                    }
763 <SComment>\n[ \t]*{CPPC}"/"{SLASHopt}/\n    {
764                                      replaceComment(yyscanner,1); 
765                                    }
766 <SComment>^[ \t]*{CPPC}"/"[^\/\n]/.*\n { 
767                                      replaceComment(yyscanner,0);
768                                      yyextra->readLineCtx=YY_START;
769                                      BEGIN(ReadLine);
770                                    }
771 <SComment>\n[ \t]*{CPPC}[\/!]("<")?[ \t]*[\\@]"}".*\n {   
772                                      /* See Bug 752712: end the multiline comment when finding a @} or \} command */
773                                      copyToOutput(yyscanner," */",3); 
774                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
775                                      yyextra->inSpecialComment=FALSE;
776                                      yyextra->inRoseComment=FALSE;
777                                      BEGIN(Scan); 
778                                    }
779 <SComment>\n[ \t]*{CPPC}"/"[^\/\n]/.*\n  { 
780                                      replaceComment(yyscanner,1); 
781                                      yyextra->readLineCtx=YY_START;
782                                      BEGIN(ReadLine);
783                                    }
784 <SComment>^[ \t]*{CPPC}"!"             |    // just //!
785 <SComment>^[ \t]*{CPPC}"!<"/.*\n       |    // or   //!< something
786 <SComment>^[ \t]*{CPPC}"!"[^<]/.*\n    {    // or   //!something
787                                      replaceComment(yyscanner,0);
788                                      yyextra->readLineCtx=YY_START;
789                                      BEGIN(ReadLine);
790                                    }
791 <SComment>\n[ \t]*{CPPC}"!"            |
792 <SComment>\n[ \t]*{CPPC}"!<"/.*\n      |
793 <SComment>\n[ \t]*{CPPC}"!"[^<\n]/.*\n { 
794                                      replaceComment(yyscanner,1); 
795                                      yyextra->readLineCtx=YY_START;
796                                      BEGIN(ReadLine);
797                                    }
798 <SComment>^[ \t]*{CPPC}"##"/.*\n       {
799                                      if (!yyextra->inRoseComment)
800                                      {
801                                        REJECT;
802                                      }
803                                      else
804                                      {
805                                        replaceComment(yyscanner,0);
806                                        yyextra->readLineCtx=YY_START;
807                                        BEGIN(ReadLine);
808                                      }
809                                    }
810 <SComment>\n[ \t]*{CPPC}"##"/.*\n      {
811                                      if (!yyextra->inRoseComment)
812                                      {
813                                        REJECT;
814                                      }
815                                      else
816                                      {
817                                        replaceComment(yyscanner,1); 
818                                        yyextra->readLineCtx=YY_START;
819                                        BEGIN(ReadLine);
820                                      }
821                                    }
822 <SComment>\n                       { /* end of special comment */
823                                      copyToOutput(yyscanner," */",3); 
824                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
825                                      yyextra->inSpecialComment=FALSE;
826                                      yyextra->inRoseComment=FALSE;
827                                      BEGIN(Scan); 
828                                    }
829 <ReadLine>{CCS}"*"                    {
830                                      copyToOutput(yyscanner,"/&zwj;**",8);
831                                    }
832 <ReadLine>{CCE}                     {
833                                      copyToOutput(yyscanner,"*&zwj;/",7);
834                                    }
835 <ReadLine>"*"                      {
836                                      copyToOutput(yyscanner,yytext,(int)yyleng);
837                                    }
838 <ReadLine>{RLopt}                  {
839                                      copyToOutput(yyscanner,yytext,(int)yyleng);
840                                    }
841 <ReadLine>{RLopt}/\n               {
842                                      copyToOutput(yyscanner,yytext,(int)yyleng);
843                                      BEGIN(yyextra->readLineCtx);
844                                    }
845 <CComment,CNComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
846                                      copyToOutput(yyscanner,yytext,(int)yyleng);
847                                    }
848 <CComment,ReadLine>[\\@]"cond"/[^a-z_A-Z0-9]       { // conditional section
849                                      yyextra->condCtx = YY_START; 
850                                      BEGIN(CondLine);
851                                    }
852 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
853                                      bool oldSkip=yyextra->skip;
854                                      endCondSection(yyscanner);
855                                      if (YY_START==CComment && oldSkip && !yyextra->skip) 
856                                      {
857                                        //printf("** Adding start of comment!\n");
858                                        if (yyextra->lang!=SrcLangExt_Python &&
859                                            yyextra->lang!=SrcLangExt_VHDL &&
860                                            yyextra->lang!=SrcLangExt_Markdown &&
861                                            yyextra->lang!=SrcLangExt_Fortran)
862                                        {
863                                          ADDCHAR('/');
864                                          ADDCHAR('*');
865                                          if (yyextra->specialComment)
866                                          {
867                                            ADDCHAR('*');
868                                          }
869                                        }
870                                      }
871                                     }
872 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
873                                      handleCondSectionId(yyscanner,yytext);
874                                    }
875 <CComment,ReadLine>[\\@]"cond"{WSopt}/\n {
876                                      yyextra->condCtx=YY_START;
877                                      handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
878                                    }
879 <CondLine>.                        { // forgot section id?
880                                      handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
881                                      if (*yytext=='\n') yyextra->lineNr++;
882                                    }
883 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*  { // expand alias without arguments
884                                      replaceAliases(yyscanner,QCString(yytext));
885                                    }
886 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
887                                      yyextra->lastBlockContext=YY_START;
888                                      yyextra->blockCount=1;
889                                      yyextra->aliasString=yytext;
890                                      yyextra->lastEscaped=0;
891                                      BEGIN( ReadAliasArgs );
892                                    }
893 <ReadAliasArgs>^[ \t]*{CPPC}[/!]/[^\n]+   { // skip leading special comments (see bug 618079)
894                                    }
895 <ReadAliasArgs>{CCE}               { // oops, end of comment in the middle of an alias?
896                                      if (yyextra->lang==SrcLangExt_Python)
897                                      {
898                                        REJECT;
899                                      }
900                                      else // abort the alias, restart scanning
901                                      {
902                                        copyToOutput(yyscanner,yyextra->aliasString.data(),yyextra->aliasString.length());
903                                        copyToOutput(yyscanner,yytext,(int)yyleng);
904                                        BEGIN(Scan);
905                                      }
906                                    }
907 <ReadAliasArgs>[^{}\n\\\*]+        {
908                                      yyextra->aliasString+=yytext;
909                                      yyextra->lastEscaped=FALSE;
910                                    }
911 <ReadAliasArgs>"\\"                {
912                                      if (yyextra->lastEscaped)  yyextra->lastEscaped=FALSE;
913                                      else                yyextra->lastEscaped=TRUE;
914                                      yyextra->aliasString+=yytext;
915                                    }
916 <ReadAliasArgs>\n                  {
917                                      yyextra->aliasString+=yytext;
918                                      yyextra->lineNr++;
919                                      yyextra->lastEscaped=FALSE;
920                                    }
921 <ReadAliasArgs>"{"                 {
922                                      yyextra->aliasString+=yytext;
923                                      if (!yyextra->lastEscaped) yyextra->blockCount++;
924                                      yyextra->lastEscaped=FALSE;
925                                    }
926 <ReadAliasArgs>"}"                 {
927                                      yyextra->aliasString+=yytext;
928                                      if (!yyextra->lastEscaped) yyextra->blockCount--;
929                                      if (yyextra->blockCount==0)
930                                      {
931                                        replaceAliases(yyscanner,yyextra->aliasString);
932                                        BEGIN( yyextra->lastBlockContext );
933                                      }
934                                      yyextra->lastEscaped=FALSE;
935                                    }
936 <ReadAliasArgs>.                   {
937                                      yyextra->aliasString+=yytext;
938                                      yyextra->lastEscaped=FALSE;
939                                    }
940 <ReadLine>.                        {
941                                      copyToOutput(yyscanner,yytext,(int)yyleng);
942                                    }
943
944 <*>.                               {
945                                      copyToOutput(yyscanner,yytext,(int)yyleng);
946                                    }
947 %%
948
949 static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len)
950 {
951   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
952   const char *p=s;
953   char c;
954   // copy leading blanks
955   while ((c=*p) && (c==' ' || c=='\t' || c=='\n')) 
956   {
957     ADDCHAR(c);
958     yyextra->lineNr += c=='\n';
959     p++;
960   }
961   // replace start of comment marker by blanks and the last character by a *
962   int blanks=0;
963   while ((c=*p) && (c=='/' || c=='!' || c=='#')) 
964   {
965     blanks++;
966     p++;
967     if (*p=='<') // comment-after-item marker 
968     { 
969       blanks++;
970       p++; 
971     }
972     if (c=='!') // end after first !
973     {
974       break;
975     }
976   }
977   if (blanks>0)
978   {
979     while (blanks>2)
980     {
981       ADDCHAR(' ');
982       blanks--;
983     }
984     if (blanks>1) ADDCHAR('*');
985     ADDCHAR(' ');
986   }
987   // copy comment line to output
988   ADDARRAY(p,len-(int)(p-s));
989 }
990
991 static inline int computeIndent(const char *s)
992 {
993   int col=0;
994   static int tabSize=Config_getInt(TAB_SIZE);
995   const char *p=s;
996   char c;
997   while ((c=*p++))
998   {
999     if (c==' ') col++;
1000     else if (c=='\t') col+=tabSize-(col%tabSize); 
1001     else break;
1002   }
1003   return col;
1004 }
1005
1006 static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len)
1007 {
1008   int tabSize=Config_getInt(TAB_SIZE);
1009   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1010   int i;
1011   if (yyextra->skip) // only add newlines.
1012   {
1013     for (i=0;i<len;i++)
1014     {
1015       switch(s[i])
1016       {
1017         case '\n':
1018           ADDCHAR('\n');
1019           yyextra->lineNr++;
1020           yyextra->col=0;
1021           break;
1022         case '\t':
1023           yyextra->col+=tabSize-(yyextra->col%tabSize);
1024           break;
1025         default:
1026           yyextra->col++;
1027           break;
1028       }
1029     }
1030   }
1031   else if (len>0)
1032   {
1033     ADDARRAY(s,len);
1034     for (i=0;i<len;i++) 
1035     {
1036       switch (s[i])
1037       {
1038         case '\n': yyextra->col=0; 
1039                    //fprintf(stderr,"---> copy %d\n",g_lineNr);
1040                    yyextra->lineNr++; break;
1041         case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1042         default:   yyextra->col++; break;
1043       }
1044     }
1045   }
1046 }
1047
1048 static void clearCommentStack(yyscan_t yyscanner)
1049 {
1050   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1051   while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
1052 }
1053
1054 static void startCondSection(yyscan_t yyscanner,const QCString &sectId)
1055 {
1056   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1057   //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1058   CondParser prs;
1059   bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1060   yyextra->condStack.push(CondCtx(yyextra->lineNr,sectId,yyextra->skip));
1061   if (!expResult) // not enabled
1062   {
1063     yyextra->skip=TRUE;
1064   }
1065 }
1066
1067 static void endCondSection(yyscan_t yyscanner)
1068 {
1069   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1070   if (yyextra->condStack.empty())
1071   {
1072     warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1073     yyextra->skip=FALSE;
1074   }
1075   else
1076   {
1077     const CondCtx &ctx = yyextra->condStack.top();
1078     yyextra->skip=ctx.skip;
1079     yyextra->condStack.pop();
1080   }
1081   //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1082 }
1083
1084 static void handleCondSectionId(yyscan_t yyscanner,const char *expression)
1085 {
1086   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1087   bool oldSkip=yyextra->skip;
1088   startCondSection(yyscanner,QCString(expression));
1089   if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) && 
1090       !oldSkip && yyextra->skip) 
1091   {
1092     if (yyextra->lang!=SrcLangExt_Python &&
1093         yyextra->lang!=SrcLangExt_VHDL &&
1094         yyextra->lang!=SrcLangExt_Markdown &&
1095         yyextra->lang!=SrcLangExt_Fortran)
1096     {
1097       ADDCHAR('*');
1098       ADDCHAR('/');
1099     }
1100   }
1101   if (yyextra->readLineCtx==SComment)
1102   {
1103     BEGIN(SComment);
1104   }
1105   else
1106   {
1107     BEGIN(yyextra->condCtx);
1108   }
1109 }
1110
1111 /** copies string \a s with length \a len to the output, while 
1112  *  replacing any alias commands found in the string.
1113  */
1114 static void replaceAliases(yyscan_t yyscanner,const QCString &s)
1115 {
1116   QCString result = resolveAliasCmd(s);
1117   //printf("replaceAliases(%s)->'%s'\n",s,result.data());
1118   copyToOutput(yyscanner,result.data(),result.length());
1119 }
1120
1121
1122 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
1123 {
1124   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1125   yy_size_t bytesInBuf = yyextra->inBuf->curPos()-yyextra->inBufPos;
1126   yy_size_t bytesToCopy = std::min(max_size,bytesInBuf);
1127   memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
1128   yyextra->inBufPos+=bytesToCopy;
1129   return bytesToCopy;
1130 }
1131
1132 static void replaceComment(yyscan_t yyscanner,int offset)
1133 {
1134   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1135   if (yyextra->mlBrief || yyextra->skip)
1136   {
1137     copyToOutput(yyscanner,yytext,(int)yyleng);
1138   }
1139   else
1140   {
1141     //printf("replaceComment(%s)\n",yytext);
1142     int i=computeIndent(&yytext[offset]);
1143     if (i==yyextra->blockHeadCol)
1144     {
1145       replaceCommentMarker(yyscanner,yytext,(int)yyleng);
1146     }
1147     else
1148     {
1149       copyToOutput(yyscanner," */",3);
1150       for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1151       yyextra->inSpecialComment=FALSE;
1152       BEGIN(Scan);
1153     }
1154   }
1155 }
1156
1157 /*! This function does three things:
1158  *  -# It converts multi-line C++ style comment blocks (that are aligned)
1159  *     to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
1160  *  -# It replaces aliases with their definition (see ALIASES)
1161  *  -# It handles conditional sections (cond...endcond blocks)
1162  */
1163 void convertCppComments(BufStr *inBuf,BufStr *outBuf,const QCString &fileName)
1164 {
1165   yyscan_t yyscanner;
1166   commentcnvYY_state extra;
1167   commentcnvYYlex_init_extra(&extra,&yyscanner);
1168 #ifdef FLEX_DEBUG
1169   commentcnvYYset_debug(1,yyscanner);
1170 #endif
1171   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1172   //printf("convertCppComments(%s)\n",fileName);
1173   yyextra->inBuf    = inBuf;
1174   yyextra->outBuf   = outBuf;
1175   yyextra->inBufPos = 0;
1176   yyextra->col      = 0;
1177   yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
1178   yyextra->skip     = FALSE;
1179   yyextra->fileName = fileName;
1180   yyextra->lang = getLanguageFromFileName(fileName);
1181   yyextra->pythonDocString = FALSE;
1182   yyextra->lineNr   = 1;
1183   while (!yyextra->condStack.empty()) yyextra->condStack.pop();
1184   clearCommentStack(yyscanner);
1185   yyextra->vhdl = FALSE;
1186
1187   printlex(yy_flex_debug, TRUE, __FILE__, qPrint(fileName));
1188   yyextra->isFixedForm = FALSE;
1189   if (yyextra->lang==SrcLangExt_Fortran)
1190   {
1191     FortranFormat fmt = convertFileNameFortranParserCode(fileName);
1192     yyextra->isFixedForm = recognizeFixedForm(QCString(inBuf->data()),fmt);
1193   }
1194
1195   if (yyextra->lang==SrcLangExt_Markdown)
1196   {
1197     yyextra->nestingCount=0;
1198     BEGIN(CComment);
1199     yyextra->commentStack.push(yyextra->lineNr);
1200   }
1201   else
1202   {
1203     BEGIN(Scan);
1204   }
1205   yylex(yyscanner);
1206   while (!yyextra->condStack.empty())
1207   {
1208     const CondCtx &ctx = yyextra->condStack.top();
1209     QCString sectionInfo(" ");
1210     if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
1211     warn(yyextra->fileName,ctx.lineNr,"Conditional section%sdoes not have "
1212         "a corresponding \\endcond command within this file.",sectionInfo.data());
1213     yyextra->condStack.pop();
1214   }
1215   if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown && yyextra->lang!=SrcLangExt_Fortran)
1216   {
1217     QCString tmp("(probable line reference: ");
1218     bool first = TRUE;
1219     while (!yyextra->commentStack.empty())
1220     {
1221       int lineNr = yyextra->commentStack.top();
1222       if (!first) tmp += ", ";
1223       tmp += QCString().setNum(lineNr);
1224       first = FALSE;
1225       yyextra->commentStack.pop();
1226     }
1227     tmp += ")";
1228     warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
1229         "Nesting level %d %s",yyextra->nestingCount,tmp.data());
1230   }
1231   yyextra->nestingCount = 0;
1232   if (Debug::isFlagSet(Debug::CommentCnv))
1233   {
1234     yyextra->outBuf->at(yyextra->outBuf->curPos())='\0';
1235     Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: %s\n"
1236                  "output=[\n%s]\n-----------\n",qPrint(fileName),yyextra->outBuf->data()
1237                 );
1238   }
1239   printlex(yy_flex_debug, FALSE, __FILE__, qPrint(fileName));
1240   commentcnvYYlex_destroy(yyscanner);
1241 }
1242
1243
1244 //----------------------------------------------------------------------------
1245
1246 #if USE_STATE2STRING
1247 #include "commentcnv.l.h"
1248 #endif