1 /*****************************************************************************
5 * Copyright (C) 1997-2015 by Dimitri van Heesch.
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.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
17 %option never-interactive
18 %option prefix="commentcnvYY"
20 %option extra-type="struct commentcnvYY_state *"
33 #include <qtextstream.h>
42 #include "condparser.h"
47 #define YY_NO_UNISTD_H 1
49 #define ADDCHAR(c) yyextra->outBuf->addChar(c)
50 #define ADDARRAY(a,s) yyextra->outBuf->addArray(a,s)
52 #define USE_STATE2STRING 0
56 CondCtx(int line,QCString id,bool b)
57 : lineNr(line),sectionId(id), skip(b) {}
70 struct commentcnvYY_state
74 yy_size_t inBufPos = 0;
83 QStack<CondCtx> condStack;
84 QStack<CommentCtx> commentStack;
86 int lastCommentContext = 0;
87 bool inSpecialComment = FALSE;
88 bool inRoseComment= FALSE;
89 int stringContext = 0;
92 bool specialComment = FALSE;
96 bool lastEscaped = FALSE;
97 int lastBlockContext= 0;
98 bool pythonDocString = FALSE;
101 bool vhdl = FALSE; // for VHDL old style --! comment
103 SrcLangExt lang = SrcLangExt_Unknown;
104 bool isFixedForm = FALSE; // For Fortran
108 static const char *stateToString(int state);
110 static inline int computeIndent(const char *s);
112 static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len);
113 static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len);
114 static void startCondSection(yyscan_t yyscanner,const char *sectId);
115 static void endCondSection(yyscan_t yyscanner);
116 static void handleCondSectionId(yyscan_t yyscanner,const char *expression);
117 static void replaceAliases(yyscan_t yyscanner,const char *s);
118 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
119 static void replaceComment(yyscan_t yyscanner,int offset);
125 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
130 MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
145 //- start: NUMBER -------------------------------------------------------------------------
146 // Note same defines in code.l: keep in sync
147 DECIMAL_INTEGER [1-9][0-9']*[0-9]?[uU]?[lL]?[lL]?
148 HEXADECIMAL_INTEGER "0"[xX][0-9a-zA-Z']+[0-9a-zA-Z]?
149 OCTAL_INTEGER "0"[0-7][0-7']+[0-7]?
150 BINARY_INTEGER "0"[bB][01][01']*[01]?
151 INTEGER_NUMBER {DECIMAL_INTEGER}|{HEXADECIMAL_INTEGER}|{OCTAL_INTEGER}|{BINARY_INTEGER}
155 DIGIT_SEQ [0-9][0-9']*[0-9]?
156 FRAC_CONST {DIGIT_SEQ}"."|{DIGIT_SEQ}?"."{DIGIT_SEQ}
157 FP_EXP [eE][+-]?{DIGIT_SEQ}
158 DEC_FP1 {FRAC_CONST}{FP_EXP}?{FP_SUF}?
159 DEC_FP2 {DIGIT_SEQ}{FP_EXP}{FP_SUF}
161 HEX_DIGIT_SEQ [0-9a-fA-F][0-9a-fA-F']*[0-9a-fA-F]?
162 HEX_FRAC_CONST {HEX_DIGIT_SEQ}"."|{HEX_DIGIT_SEQ}?"."{HEX_DIGIT_SEQ}
163 BIN_EXP [pP][+-]?{DIGIT_SEQ}
164 HEX_FP1 "0"[xX]{HEX_FRAC_CONST}{BIN_EXP}{FP_SUF}?
165 HEX_FP2 "0"[xX]{HEX_DIGIT_SEQ}{BIN_EXP}{FP_SUF}?
167 FLOAT_DECIMAL {DEC_FP1}|{DEC_FP2}
168 FLOAT_HEXADECIMAL {HEX_FP1}|{HEX_FP2}
169 FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL}
170 NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER}
171 //- end: NUMBER ---------------------------------------------------------------------------
175 <Scan>{NUMBER} { //Note similar code in code.l
176 if (yyextra->lang!=SrcLangExt_Cpp) REJECT;
177 copyToOutput(yyscanner,yytext,(int)yyleng);
179 <Scan>[^"'!\/\n\\#,\-=; \t]* { /* eat anything that is not " / , or \n */
180 copyToOutput(yyscanner,yytext,(int)yyleng);
182 <Scan>[,= ;\t] { /* eat , so we have a nice separator in long initialization lines */
183 copyToOutput(yyscanner,yytext,(int)yyleng);
185 <Scan>"\"\"\""! { /* start of python long comment */
186 if (yyextra->lang!=SrcLangExt_Python)
192 yyextra->pythonDocString = TRUE;
193 yyextra->nestingCount=1;
194 yyextra->commentStack.clear(); /* to be on the save side */
195 copyToOutput(yyscanner,yytext,(int)yyleng);
197 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
201 if (yyextra->lang!=SrcLangExt_Fortran)
207 copyToOutput(yyscanner,yytext,(int)yyleng);
208 yyextra->nestingCount=0; // Fortran doesn't have an end comment
209 yyextra->commentStack.clear(); /* to be on the save side */
211 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
214 <Scan>[Cc\*][><!]/.*\n {
215 if (yyextra->lang!=SrcLangExt_Fortran)
221 /* check for fixed format; we might have some conditional as part of multiline if like C<5 .and. & */
222 if (yyextra->isFixedForm && (yyextra->col == 0))
224 copyToOutput(yyscanner,yytext,(int)yyleng);
225 yyextra->nestingCount=0; // Fortran doesn't have an end comment
226 yyextra->commentStack.clear(); /* to be on the safe side */
228 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
237 if (yyextra->lang!=SrcLangExt_Fortran)
243 copyToOutput(yyscanner,yytext,(int)yyleng);
247 if (yyextra->lang!=SrcLangExt_Fortran)
253 if (yyextra->col == 0)
255 copyToOutput(yyscanner,yytext,(int)yyleng);
263 <Scan>"\"" { /* start of a string */
264 copyToOutput(yyscanner,yytext,(int)yyleng);
265 yyextra->stringContext = YY_START;
269 copyToOutput(yyscanner,yytext,(int)yyleng);
270 yyextra->charContext = YY_START;
271 if (yyextra->lang!=SrcLangExt_VHDL)
276 <Scan>\n { /* new line */
277 copyToOutput(yyscanner,yytext,(int)yyleng);
279 <Scan>"//!"/.*\n[ \t]*"//"[\/!][^\/] | /* start C++ style special comment block */
280 <Scan>("///"[/]*)/[^/].*\n[ \t]*"//"[\/!][^\/] { /* start C++ style special comment block */
281 if (yyextra->mlBrief)
283 REJECT; // bail out if we do not need to convert
290 while (i<(int)yyleng && yytext[i]=='/') i++;
292 yyextra->blockHeadCol=yyextra->col;
293 copyToOutput(yyscanner,"/**",3);
294 replaceAliases(yyscanner,yytext+i);
295 yyextra->inSpecialComment=TRUE;
297 yyextra->readLineCtx=SComment;
301 <Scan>"//##Documentation".*/\n { /* Start of Rational Rose ANSI C++ comment block */
302 if (yyextra->mlBrief) REJECT;
303 int i=17; //=strlen("//##Documentation");
304 yyextra->blockHeadCol=yyextra->col;
305 copyToOutput(yyscanner,"/**",3);
306 replaceAliases(yyscanner,yytext+i);
307 yyextra->inRoseComment=TRUE;
310 <Scan>"//"[!\/]/.*\n[ \t]*"//"[|\/][ \t]*[@\\]"}" { // next line contains an end marker, see bug 752712
311 yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
312 copyToOutput(yyscanner,yytext,(int)yyleng);
313 yyextra->readLineCtx=YY_START;
316 <Scan>"//"/.*\n { /* one line C++ comment */
317 yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
318 copyToOutput(yyscanner,yytext,(int)yyleng);
319 yyextra->readLineCtx=YY_START;
322 <Scan>"/**/" { /* avoid matching next rule for empty C comment, see bug 711723 */
323 copyToOutput(yyscanner,yytext,(int)yyleng);
325 <Scan>"/*"[*!]? { /* start of a C comment */
326 if (yyextra->lang==SrcLangExt_Python)
330 yyextra->specialComment=(int)yyleng==3;
331 yyextra->nestingCount=1;
332 yyextra->commentStack.clear(); /* to be on the save side */
333 copyToOutput(yyscanner,yytext,(int)yyleng);
335 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
338 if (yyextra->lang!=SrcLangExt_Python)
344 copyToOutput(yyscanner,yytext,(int)yyleng);
345 yyextra->nestingCount=0; // Python doesn't have an end comment for #
346 yyextra->commentStack.clear(); /* to be on the save side */
348 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
351 <Scan>"--"[^!][^\n]* {
352 if (yyextra->lang!=SrcLangExt_VHDL)
358 copyToOutput(yyscanner,yytext,(int)yyleng);
362 if (yyextra->lang!=SrcLangExt_VHDL)
368 yyextra->vhdl = TRUE;
369 copyToOutput(yyscanner,yytext,(int)yyleng);
370 yyextra->nestingCount=0; // VHDL doesn't have an end comment
371 yyextra->commentStack.clear(); /* to be on the save side */
373 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
377 if (yyextra->lang!=SrcLangExt_Fortran)
383 copyToOutput(yyscanner,yytext,(int)yyleng);
384 yyextra->nestingCount=0; // Fortran doesn't have an end comment
385 yyextra->commentStack.clear(); /* to be on the save side */
387 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
390 <CComment,ReadLine>{MAILADR} |
391 <CComment,ReadLine>"<"{MAILADR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block
392 copyToOutput(yyscanner,yytext,(int)yyleng);
394 <CComment>"{@code"/[ \t\n] {
395 copyToOutput(yyscanner,"@code",5);
396 yyextra->lastCommentContext = YY_START;
397 yyextra->javaBlock=1;
398 yyextra->blockName=&yytext[1];
401 <CComment,ReadLine>^[ \t]*("```"[`]*|"~~~"[~]*) { /* start of markdown code block */
402 if (!Config_getBool(MARKDOWN_SUPPORT))
406 copyToOutput(yyscanner,yytext,(int)yyleng);
407 yyextra->lastCommentContext = YY_START;
408 yyextra->javaBlock=0;
409 yyextra->blockName=QCString(yytext).stripWhiteSpace().left(3);
412 <CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */
413 copyToOutput(yyscanner,yytext,(int)yyleng);
414 yyextra->lastCommentContext = YY_START;
415 yyextra->javaBlock=0;
416 if (qstrcmp(&yytext[1],"startuml")==0)
418 yyextra->blockName="uml";
422 yyextra->blockName=&yytext[1];
426 <CComment,ReadLine>[\\@]("f$"|"f["|"f{") {
427 copyToOutput(yyscanner,yytext,(int)yyleng);
428 yyextra->blockName=&yytext[1];
429 if (yyextra->blockName.at(1)=='[')
431 yyextra->blockName.at(1)=']';
433 else if (yyextra->blockName.at(1)=='{')
435 yyextra->blockName.at(1)='}';
437 yyextra->lastCommentContext = YY_START;
440 <CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
441 copyToOutput(yyscanner,yytext,(int)yyleng);
442 yyextra->blockName=&yytext[1];
443 yyextra->lastCommentContext = YY_START;
446 <Scan>. { /* any other character */
447 copyToOutput(yyscanner,yytext,(int)yyleng);
449 <Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}") { /* end of verbatim block */
450 copyToOutput(yyscanner,yytext,(int)yyleng);
451 if (&yytext[1]==yyextra->blockName) // end of formula
453 BEGIN(yyextra->lastCommentContext);
455 else if (&yytext[4]==yyextra->blockName)
457 BEGIN(yyextra->lastCommentContext);
461 if (yyextra->javaBlock==0)
467 yyextra->javaBlock++;
468 copyToOutput(yyscanner,yytext,(int)yyleng);
472 if (yyextra->javaBlock==0)
478 yyextra->javaBlock--;
479 if (yyextra->javaBlock==0)
481 copyToOutput(yyscanner," @endcode ",10);
482 BEGIN(yyextra->lastCommentContext);
486 copyToOutput(yyscanner,yytext,(int)yyleng);
490 <VerbatimCode>("```"[`]*|"~~~"[~]*) { /* end of markdown code block */
491 copyToOutput(yyscanner,yytext,(int)yyleng);
492 if (yytext[0]==yyextra->blockName[0])
494 BEGIN(yyextra->lastCommentContext);
497 <VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */
498 copyToOutput(yyscanner,yytext,(int)yyleng);
499 if (&yytext[4]==yyextra->blockName)
501 BEGIN(yyextra->lastCommentContext);
504 <VerbatimCode>^[ \t]*"//"[\!\/]? { /* skip leading comments */
505 if (!yyextra->inSpecialComment)
507 copyToOutput(yyscanner,yytext,(int)yyleng);
512 while (yytext[l]==' ' || yytext[l]=='\t')
516 copyToOutput(yyscanner,yytext,l);
517 if (yyleng-l==3) // ends with //! or ///
519 copyToOutput(yyscanner," * ",3);
523 copyToOutput(yyscanner,"//",2);
527 <Verbatim,VerbatimCode>[^`~@\/\\\n{}]* { /* any character not a backslash or new line or } */
528 copyToOutput(yyscanner,yytext,(int)yyleng);
530 <Verbatim,VerbatimCode>\n { /* new line in verbatim block */
531 copyToOutput(yyscanner,yytext,(int)yyleng);
533 <Verbatim>^[ \t]*"//"[/!] {
534 if (yyextra->blockName=="dot" || yyextra->blockName=="msc" || yyextra->blockName=="uml" || yyextra->blockName.at(0)=='f')
536 // see bug 487871, strip /// from dot images and formulas.
538 while (yytext[l]==' ' || yytext[l]=='\t')
542 copyToOutput(yyscanner,yytext,l);
543 copyToOutput(yyscanner," ",3);
545 else // even slashes are verbatim (e.g. \verbatim, \code)
550 <Verbatim,VerbatimCode>. { /* any other character */
551 copyToOutput(yyscanner,yytext,(int)yyleng);
553 <SkipString>\\. { /* escaped character in string */
554 if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
557 copyToOutput(yyscanner,yytext,1);
561 copyToOutput(yyscanner,yytext,(int)yyleng);
564 <SkipString>"\"" { /* end of string */
565 copyToOutput(yyscanner,yytext,(int)yyleng);
566 BEGIN(yyextra->stringContext);
568 <SkipString>. { /* any other string character */
569 copyToOutput(yyscanner,yytext,(int)yyleng);
571 <SkipString>\n { /* new line inside string (illegal for some compilers) */
572 copyToOutput(yyscanner,yytext,(int)yyleng);
574 <SkipChar>\\. { /* escaped character */
575 if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
578 copyToOutput(yyscanner,yytext,1);
582 copyToOutput(yyscanner,yytext,(int)yyleng);
585 <SkipChar>' { /* end of character literal */
586 copyToOutput(yyscanner,yytext,(int)yyleng);
587 BEGIN(yyextra->charContext);
589 <SkipChar>. { /* any other string character */
590 copyToOutput(yyscanner,yytext,(int)yyleng);
592 <SkipChar>\n { /* new line character */
593 copyToOutput(yyscanner,yytext,(int)yyleng);
596 <CComment>[^ `~<\\!@*\n{\"\/]* { /* anything that is not a '*' or command */
597 copyToOutput(yyscanner,yytext,(int)yyleng);
599 <CComment>"*"+[^*/\\@\n{\"]* { /* stars without slashes */
600 copyToOutput(yyscanner,yytext,(int)yyleng);
602 <CComment>"\"\"\"" { /* end of Python docstring */
603 if (yyextra->lang!=SrcLangExt_Python)
609 yyextra->nestingCount--;
610 yyextra->pythonDocString = FALSE;
611 copyToOutput(yyscanner,yytext,(int)yyleng);
615 <CComment>\n { /* new line in comment */
616 copyToOutput(yyscanner,yytext,(int)yyleng);
617 /* in case of Fortran always end of comment */
618 if (yyextra->lang==SrcLangExt_Fortran)
623 <CComment>"/"+"*" { /* nested C comment */
624 if (yyextra->lang==SrcLangExt_Python ||
625 yyextra->lang==SrcLangExt_Markdown)
629 yyextra->nestingCount++;
630 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
631 copyToOutput(yyscanner,yytext,(int)yyleng);
633 <CComment>"*"+"/" { /* end of C comment */
634 if (yyextra->lang==SrcLangExt_Python ||
635 yyextra->lang==SrcLangExt_Markdown)
641 copyToOutput(yyscanner,yytext,(int)yyleng);
642 yyextra->nestingCount--;
643 if (yyextra->nestingCount<=0)
649 //yyextra->nestingCount--;
650 delete yyextra->commentStack.pop();
654 /* Python an VHDL share CComment, so special attention for ending comments is required */
655 <CComment>"\n"/[ \t]*"#" {
656 if (yyextra->lang!=SrcLangExt_VHDL)
662 if (yyextra->vhdl) // inside --! comment
664 yyextra->vhdl = FALSE;
665 copyToOutput(yyscanner,yytext,(int)yyleng);
668 else // C-type comment
674 <CComment>"\n"/[ \t]*"-" {
675 if (yyextra->lang!=SrcLangExt_Python || yyextra->pythonDocString)
681 copyToOutput(yyscanner,yytext,(int)yyleng);
685 <CComment>"\n"/[ \t]*[^ \t#\-] {
686 if (yyextra->lang==SrcLangExt_Python)
688 if (yyextra->pythonDocString)
694 copyToOutput(yyscanner,yytext,(int)yyleng);
698 else if (yyextra->lang==SrcLangExt_VHDL)
700 if (yyextra->vhdl) // inside --! comment
702 yyextra->vhdl = FALSE;
703 copyToOutput(yyscanner,yytext,(int)yyleng);
706 else // C-type comment
716 /* removed for bug 674842 (bug was introduced in rev 768)
718 yyextra->charContext = YY_START;
719 copyToOutput(yyscanner,yytext,(int)yyleng);
723 yyextra->stringContext = YY_START;
724 copyToOutput(yyscanner,yytext,(int)yyleng);
729 copyToOutput(yyscanner,yytext,(int)yyleng);
731 <SComment>^[ \t]*"///"[\/]*/\n {
732 replaceComment(yyscanner,0);
734 <SComment>\n[ \t]*"///"[\/]*/\n {
735 replaceComment(yyscanner,1);
737 <SComment>^[ \t]*"///"[^\/\n]/.*\n {
738 replaceComment(yyscanner,0);
739 yyextra->readLineCtx=YY_START;
742 <SComment>\n[ \t]*"//"[\/!]("<")?[ \t]*[\\@]"}".*\n {
743 /* See Bug 752712: end the multiline comment when finding a @} or \} command */
744 copyToOutput(yyscanner," */",3);
745 copyToOutput(yyscanner,yytext,(int)yyleng);
746 yyextra->inSpecialComment=FALSE;
747 yyextra->inRoseComment=FALSE;
750 <SComment>\n[ \t]*"///"[^\/\n]/.*\n {
751 replaceComment(yyscanner,1);
752 yyextra->readLineCtx=YY_START;
755 <SComment>^[ \t]*"//!" | // just //!
756 <SComment>^[ \t]*"//!<"/.*\n | // or //!< something
757 <SComment>^[ \t]*"//!"[^<]/.*\n { // or //!something
758 replaceComment(yyscanner,0);
759 yyextra->readLineCtx=YY_START;
762 <SComment>\n[ \t]*"//!" |
763 <SComment>\n[ \t]*"//!<"/.*\n |
764 <SComment>\n[ \t]*"//!"[^<\n]/.*\n {
765 replaceComment(yyscanner,1);
766 yyextra->readLineCtx=YY_START;
769 <SComment>^[ \t]*"//##"/.*\n {
770 if (!yyextra->inRoseComment)
776 replaceComment(yyscanner,0);
777 yyextra->readLineCtx=YY_START;
781 <SComment>\n[ \t]*"//##"/.*\n {
782 if (!yyextra->inRoseComment)
788 replaceComment(yyscanner,1);
789 yyextra->readLineCtx=YY_START;
793 <SComment>\n { /* end of special comment */
794 copyToOutput(yyscanner," */",3);
795 copyToOutput(yyscanner,yytext,(int)yyleng);
796 yyextra->inSpecialComment=FALSE;
797 yyextra->inRoseComment=FALSE;
801 copyToOutput(yyscanner,"/‍**",8);
804 copyToOutput(yyscanner,"*‍/",7);
807 copyToOutput(yyscanner,yytext,(int)yyleng);
809 <ReadLine>[^\\@\n\*/]* {
810 copyToOutput(yyscanner,yytext,(int)yyleng);
812 <ReadLine>[^\\@\n\*/]*/\n {
813 copyToOutput(yyscanner,yytext,(int)yyleng);
814 BEGIN(yyextra->readLineCtx);
816 <CComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
817 copyToOutput(yyscanner,yytext,(int)yyleng);
819 <CComment,ReadLine>[\\@]"cond"/[^a-z_A-Z0-9] { // conditional section
820 yyextra->condCtx = YY_START;
823 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
824 bool oldSkip=yyextra->skip;
825 endCondSection(yyscanner);
826 if (YY_START==CComment && oldSkip && !yyextra->skip)
828 //printf("** Adding start of comment!\n");
829 if (yyextra->lang!=SrcLangExt_Python &&
830 yyextra->lang!=SrcLangExt_VHDL &&
831 yyextra->lang!=SrcLangExt_Markdown &&
832 yyextra->lang!=SrcLangExt_Fortran)
836 if (yyextra->specialComment)
843 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
844 handleCondSectionId(yyscanner,yytext);
846 <CComment,ReadLine>[\\@]"cond"[ \t\r]*/\n {
847 yyextra->condCtx=YY_START;
848 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
850 <CondLine>. { // forgot section id?
851 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
852 if (*yytext=='\n') yyextra->lineNr++;
854 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias without arguments
855 replaceAliases(yyscanner,yytext);
857 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
858 yyextra->lastBlockContext=YY_START;
859 yyextra->blockCount=1;
860 yyextra->aliasString=yytext;
861 yyextra->lastEscaped=0;
862 BEGIN( ReadAliasArgs );
864 <ReadAliasArgs>^[ \t]*"//"[/!]/[^\n]+ { // skip leading special comments (see bug 618079)
866 <ReadAliasArgs>"*/" { // oops, end of comment in the middle of an alias?
867 if (yyextra->lang==SrcLangExt_Python)
871 else // abort the alias, restart scanning
873 copyToOutput(yyscanner,yyextra->aliasString,yyextra->aliasString.length());
874 copyToOutput(yyscanner,yytext,(int)yyleng);
878 <ReadAliasArgs>[^{}\n\\\*]+ {
879 yyextra->aliasString+=yytext;
880 yyextra->lastEscaped=FALSE;
882 <ReadAliasArgs>"\\" {
883 if (yyextra->lastEscaped) yyextra->lastEscaped=FALSE;
884 else yyextra->lastEscaped=TRUE;
885 yyextra->aliasString+=yytext;
888 yyextra->aliasString+=yytext;
890 yyextra->lastEscaped=FALSE;
893 yyextra->aliasString+=yytext;
894 if (!yyextra->lastEscaped) yyextra->blockCount++;
895 yyextra->lastEscaped=FALSE;
898 yyextra->aliasString+=yytext;
899 if (!yyextra->lastEscaped) yyextra->blockCount--;
900 if (yyextra->blockCount==0)
902 replaceAliases(yyscanner,yyextra->aliasString);
903 BEGIN( yyextra->lastBlockContext );
905 yyextra->lastEscaped=FALSE;
908 yyextra->aliasString+=yytext;
909 yyextra->lastEscaped=FALSE;
912 copyToOutput(yyscanner,yytext,(int)yyleng);
916 copyToOutput(yyscanner,yytext,(int)yyleng);
920 static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len)
922 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
925 // copy leading blanks
926 while ((c=*p) && (c==' ' || c=='\t' || c=='\n'))
929 yyextra->lineNr += c=='\n';
932 // replace start of comment marker by blanks and the last character by a *
934 while ((c=*p) && (c=='/' || c=='!' || c=='#'))
938 if (*p=='<') // comment-after-item marker
943 if (c=='!') // end after first !
955 if (blanks>1) ADDCHAR('*');
958 // copy comment line to output
959 ADDARRAY(p,len-(int)(p-s));
962 static inline int computeIndent(const char *s)
965 static int tabSize=Config_getInt(TAB_SIZE);
971 else if (c=='\t') col+=tabSize-(col%tabSize);
977 static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len)
979 int tabSize=Config_getInt(TAB_SIZE);
980 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
982 if (yyextra->skip) // only add newlines.
994 yyextra->col+=tabSize-(yyextra->col%tabSize);
1009 case '\n': yyextra->col=0;
1010 //fprintf(stderr,"---> copy %d\n",g_lineNr);
1011 yyextra->lineNr++; break;
1012 case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1013 default: yyextra->col++; break;
1019 static void startCondSection(yyscan_t yyscanner,const char *sectId)
1021 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1022 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1024 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1025 yyextra->condStack.push(new CondCtx(yyextra->lineNr,sectId,yyextra->skip));
1026 if (!expResult) // not enabled
1032 static void endCondSection(yyscan_t yyscanner)
1034 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1035 if (yyextra->condStack.isEmpty())
1037 warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1038 yyextra->skip=FALSE;
1042 CondCtx *ctx = yyextra->condStack.pop();
1043 yyextra->skip=ctx->skip;
1045 //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1048 static void handleCondSectionId(yyscan_t yyscanner,const char *expression)
1050 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1051 bool oldSkip=yyextra->skip;
1052 startCondSection(yyscanner,expression);
1053 if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
1054 !oldSkip && yyextra->skip)
1056 if (yyextra->lang!=SrcLangExt_Python &&
1057 yyextra->lang!=SrcLangExt_VHDL &&
1058 yyextra->lang!=SrcLangExt_Markdown &&
1059 yyextra->lang!=SrcLangExt_Fortran)
1065 if (yyextra->readLineCtx==SComment)
1071 BEGIN(yyextra->condCtx);
1075 /** copies string \a s with length \a len to the output, while
1076 * replacing any alias commands found in the string.
1078 static void replaceAliases(yyscan_t yyscanner,const char *s)
1080 QCString result = resolveAliasCmd(s);
1081 //printf("replaceAliases(%s)->'%s'\n",s,result.data());
1082 copyToOutput(yyscanner,result,result.length());
1086 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
1088 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1089 yy_size_t bytesInBuf = yyextra->inBuf->curPos()-yyextra->inBufPos;
1090 yy_size_t bytesToCopy = QMIN(max_size,bytesInBuf);
1091 memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
1092 yyextra->inBufPos+=bytesToCopy;
1096 static void replaceComment(yyscan_t yyscanner,int offset)
1098 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1099 if (yyextra->mlBrief || yyextra->skip)
1101 copyToOutput(yyscanner,yytext,(int)yyleng);
1105 //printf("replaceComment(%s)\n",yytext);
1106 int i=computeIndent(&yytext[offset]);
1107 if (i==yyextra->blockHeadCol)
1109 replaceCommentMarker(yyscanner,yytext,(int)yyleng);
1113 copyToOutput(yyscanner," */",3);
1114 for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1115 yyextra->inSpecialComment=FALSE;
1121 /*! This function does three things:
1122 * -# It converts multi-line C++ style comment blocks (that are aligned)
1123 * to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
1124 * -# It replaces aliases with their definition (see ALIASES)
1125 * -# It handles conditional sections (cond...endcond blocks)
1127 void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
1130 commentcnvYY_state extra;
1131 commentcnvYYlex_init_extra(&extra,&yyscanner);
1133 commentcnvYYset_debug(1,yyscanner);
1135 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1136 //printf("convertCppComments(%s)\n",fileName);
1137 yyextra->inBuf = inBuf;
1138 yyextra->outBuf = outBuf;
1139 yyextra->inBufPos = 0;
1141 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
1142 yyextra->skip = FALSE;
1143 yyextra->fileName = fileName;
1144 yyextra->lang = getLanguageFromFileName(fileName);
1145 yyextra->pythonDocString = FALSE;
1146 yyextra->lineNr = 1;
1147 yyextra->condStack.clear();
1148 yyextra->condStack.setAutoDelete(TRUE);
1149 yyextra->commentStack.clear();
1150 yyextra->commentStack.setAutoDelete(TRUE);
1151 yyextra->vhdl = FALSE;
1153 printlex(yy_flex_debug, TRUE, __FILE__, fileName);
1154 yyextra->isFixedForm = FALSE;
1155 if (yyextra->lang==SrcLangExt_Fortran)
1157 FortranFormat fmt = convertFileNameFortranParserCode(fileName);
1158 yyextra->isFixedForm = recognizeFixedForm(inBuf->data(),fmt);
1161 if (yyextra->lang==SrcLangExt_Markdown)
1163 yyextra->nestingCount=0;
1165 yyextra->commentStack.push(new CommentCtx(yyextra->lineNr));
1172 while (!yyextra->condStack.isEmpty())
1174 CondCtx *ctx = yyextra->condStack.pop();
1175 QCString sectionInfo = " ";
1176 if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx->sectionId.stripWhiteSpace().data());
1177 warn(yyextra->fileName,ctx->lineNr,"Conditional section%sdoes not have "
1178 "a corresponding \\endcond command within this file.",sectionInfo.data());
1180 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown && yyextra->lang!=SrcLangExt_Fortran)
1182 QCString tmp= "(probable line reference: ";
1184 while (!yyextra->commentStack.isEmpty())
1186 CommentCtx *ctx = yyextra->commentStack.pop();
1187 if (!first) tmp += ", ";
1188 tmp += QCString().setNum(ctx->lineNr);
1193 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
1194 "Nesting level %d %s",yyextra->nestingCount,tmp.data());
1196 yyextra->commentStack.clear();
1197 yyextra->nestingCount = 0;
1198 if (Debug::isFlagSet(Debug::CommentCnv))
1200 yyextra->outBuf->at(yyextra->outBuf->curPos())='\0';
1201 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: %s\n"
1202 "output=[\n%s]\n-----------\n",fileName,yyextra->outBuf->data()
1205 printlex(yy_flex_debug, FALSE, __FILE__, fileName);
1206 commentcnvYYlex_destroy(yyscanner);
1210 //----------------------------------------------------------------------------
1212 #if USE_STATE2STRING
1213 #include "commentcnv.l.h"