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