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