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 *"
39 #include "condparser.h"
44 #define YY_NO_UNISTD_H 1
46 #define ADDCHAR(c) yyextra->outBuf->addChar(c)
47 #define ADDARRAY(a,s) yyextra->outBuf->addArray(a,s)
49 #define USE_STATE2STRING 0
53 CondCtx(int line,QCString id,bool b)
54 : lineNr(line),sectionId(id), skip(b) {}
67 struct commentcnvYY_state
71 yy_size_t inBufPos = 0;
80 std::stack<CondCtx> condStack;
81 std::stack<int> commentStack;
83 int lastCommentContext = 0;
84 bool inSpecialComment = FALSE;
85 bool inRoseComment= FALSE;
86 int stringContext = 0;
89 bool specialComment = FALSE;
93 bool lastEscaped = FALSE;
94 int lastBlockContext= 0;
95 bool pythonDocString = FALSE;
98 bool vhdl = FALSE; // for VHDL old style --! comment
100 SrcLangExt lang = SrcLangExt_Unknown;
101 bool isFixedForm = FALSE; // For Fortran
105 static const char *stateToString(int state);
107 static inline int computeIndent(const char *s);
109 static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len);
110 static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len);
111 static void startCondSection(yyscan_t yyscanner,const QCString §Id);
112 static void endCondSection(yyscan_t yyscanner);
113 static void handleCondSectionId(yyscan_t yyscanner,const char *expression);
114 static void replaceAliases(yyscan_t yyscanner,const QCString &s);
115 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
116 static void replaceComment(yyscan_t yyscanner,int offset);
117 static void clearCommentStack(yyscan_t yyscanner);
123 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
128 MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
144 //- start: NUMBER -------------------------------------------------------------------------
145 // Note same defines in code.l: keep in sync
146 DECIMAL_INTEGER [1-9][0-9']*[0-9]?[uU]?[lL]?[lL]?
147 HEXADECIMAL_INTEGER "0"[xX][0-9a-zA-Z']+[0-9a-zA-Z]?
148 OCTAL_INTEGER "0"[0-7][0-7']+[0-7]?
149 BINARY_INTEGER "0"[bB][01][01']*[01]?
150 INTEGER_NUMBER {DECIMAL_INTEGER}|{HEXADECIMAL_INTEGER}|{OCTAL_INTEGER}|{BINARY_INTEGER}
154 DIGIT_SEQ [0-9][0-9']*[0-9]?
155 FRAC_CONST {DIGIT_SEQ}"."|{DIGIT_SEQ}?"."{DIGIT_SEQ}
156 FP_EXP [eE][+-]?{DIGIT_SEQ}
157 DEC_FP1 {FRAC_CONST}{FP_EXP}?{FP_SUF}?
158 DEC_FP2 {DIGIT_SEQ}{FP_EXP}{FP_SUF}
160 HEX_DIGIT_SEQ [0-9a-fA-F][0-9a-fA-F']*[0-9a-fA-F]?
161 HEX_FRAC_CONST {HEX_DIGIT_SEQ}"."|{HEX_DIGIT_SEQ}?"."{HEX_DIGIT_SEQ}
162 BIN_EXP [pP][+-]?{DIGIT_SEQ}
163 HEX_FP1 "0"[xX]{HEX_FRAC_CONST}{BIN_EXP}{FP_SUF}?
164 HEX_FP2 "0"[xX]{HEX_DIGIT_SEQ}{BIN_EXP}{FP_SUF}?
166 FLOAT_DECIMAL {DEC_FP1}|{DEC_FP2}
167 FLOAT_HEXADECIMAL {HEX_FP1}|{HEX_FP2}
168 FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL}
169 NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER}
170 //- end: NUMBER ---------------------------------------------------------------------------
179 // Optional any character
182 // Optional white space
184 // readline non special
191 <Scan>{NUMBER} { //Note similar code in code.l
192 if (yyextra->lang!=SrcLangExt_Cpp) REJECT;
193 copyToOutput(yyscanner,yytext,(int)yyleng);
195 <Scan>[^"'!\/\n\\#,\-=; \t]* { /* eat anything that is not " / , or \n */
196 copyToOutput(yyscanner,yytext,(int)yyleng);
198 <Scan>[,= ;\t] { /* eat , so we have a nice separator in long initialization lines */
199 copyToOutput(yyscanner,yytext,(int)yyleng);
201 <Scan>"\"\"\""! { /* start of python long comment */
202 if (yyextra->lang!=SrcLangExt_Python)
208 yyextra->pythonDocString = TRUE;
209 yyextra->nestingCount=1;
210 clearCommentStack(yyscanner); /* to be on the save side */
211 copyToOutput(yyscanner,yytext,(int)yyleng);
213 yyextra->commentStack.push(yyextra->lineNr);
217 if (yyextra->lang!=SrcLangExt_Fortran)
223 copyToOutput(yyscanner,yytext,(int)yyleng);
224 yyextra->nestingCount=0; // Fortran doesn't have an end comment
225 clearCommentStack(yyscanner); /* to be on the save side */
227 yyextra->commentStack.push(yyextra->lineNr);
230 <Scan>[Cc\*][><!]/.*\n {
231 if (yyextra->lang!=SrcLangExt_Fortran)
237 /* check for fixed format; we might have some conditional as part of multiline if like C<5 .and. & */
238 if (yyextra->isFixedForm && (yyextra->col == 0))
240 copyToOutput(yyscanner,yytext,(int)yyleng);
241 yyextra->nestingCount=0; // Fortran doesn't have an end comment
242 clearCommentStack(yyscanner); /* to be on the save side */
244 yyextra->commentStack.push(yyextra->lineNr);
253 if (yyextra->lang!=SrcLangExt_Fortran)
259 copyToOutput(yyscanner,yytext,(int)yyleng);
263 if (yyextra->lang!=SrcLangExt_Fortran)
269 if (yyextra->col == 0)
271 copyToOutput(yyscanner,yytext,(int)yyleng);
279 <Scan>"\"" { /* start of a string */
280 copyToOutput(yyscanner,yytext,(int)yyleng);
281 yyextra->stringContext = YY_START;
285 copyToOutput(yyscanner,yytext,(int)yyleng);
286 yyextra->charContext = YY_START;
287 if (yyextra->lang!=SrcLangExt_VHDL)
292 <Scan>\n { /* new line */
293 copyToOutput(yyscanner,yytext,(int)yyleng);
295 <Scan>{CPPC}"!"/.*\n[ \t]*{CPPC}[\/!][^\/] | /* start C++ style special comment block */
296 <Scan>({CPPC}"/"[/]*)/[^/].*\n[ \t]*{CPPC}[\/!][^\/] { /* start C++ style special comment block */
297 if (yyextra->mlBrief)
299 REJECT; // bail out if we do not need to convert
306 while (i<(int)yyleng && yytext[i]=='/') i++;
308 yyextra->blockHeadCol=yyextra->col;
309 copyToOutput(yyscanner,"/**",3);
310 replaceAliases(yyscanner,QCString(yytext+i));
311 yyextra->inSpecialComment=TRUE;
313 yyextra->readLineCtx=SComment;
317 <Scan>{CPPC}"##Documentation"{ANYopt}/\n { /* Start of Rational Rose ANSI C++ comment block */
318 if (yyextra->mlBrief) REJECT;
319 int i=17; //=strlen("//##Documentation");
320 yyextra->blockHeadCol=yyextra->col;
321 copyToOutput(yyscanner,"/**",3);
322 replaceAliases(yyscanner,QCString(yytext+i));
323 yyextra->inRoseComment=TRUE;
326 <Scan>{CPPC}[!\/]/.*\n[ \t]*{CPPC}[|\/][ \t]*[@\\]"}" { // next line contains an end marker, see bug 752712
327 yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
328 copyToOutput(yyscanner,yytext,(int)yyleng);
329 yyextra->readLineCtx=YY_START;
332 <Scan>{CPPC}/.*\n { /* one line C++ comment */
333 yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!';
334 copyToOutput(yyscanner,yytext,(int)yyleng);
335 yyextra->readLineCtx=YY_START;
338 <Scan>{CCS}{CCE} { /* avoid matching next rule for empty C comment, see bug 711723 */
339 copyToOutput(yyscanner,yytext,(int)yyleng);
341 <Scan>{CCS}[*!]? { /* start of a C comment */
342 if (yyextra->lang==SrcLangExt_Python)
346 yyextra->specialComment=(int)yyleng==3;
347 yyextra->nestingCount=1;
348 clearCommentStack(yyscanner); /* to be on the save side */
349 copyToOutput(yyscanner,yytext,(int)yyleng);
350 if (yyextra->specialComment)
354 yyextra->commentStack.push(yyextra->lineNr);
357 if (yyextra->lang!=SrcLangExt_Python)
363 copyToOutput(yyscanner,yytext,(int)yyleng);
364 yyextra->nestingCount=0; // Python doesn't have an end comment for #
365 clearCommentStack(yyscanner); /* to be on the save side */
367 yyextra->commentStack.push(yyextra->lineNr);
370 <Scan>"--"[^!][^\n]* {
371 if (yyextra->lang!=SrcLangExt_VHDL)
377 copyToOutput(yyscanner,yytext,(int)yyleng);
381 if (yyextra->lang!=SrcLangExt_VHDL)
387 yyextra->vhdl = TRUE;
388 copyToOutput(yyscanner,yytext,(int)yyleng);
389 yyextra->nestingCount=0; // VHDL doesn't have an end comment
390 clearCommentStack(yyscanner); /* to be on the save side */
392 yyextra->commentStack.push(yyextra->lineNr);
396 if (yyextra->lang!=SrcLangExt_Fortran)
402 copyToOutput(yyscanner,yytext,(int)yyleng);
403 yyextra->nestingCount=0; // Fortran doesn't have an end comment
404 clearCommentStack(yyscanner); /* to be on the save side */
406 yyextra->commentStack.push(yyextra->lineNr);
409 <CComment,CNComment,ReadLine>{MAILADR} |
410 <CComment,CNComment,ReadLine>"<"{MAILADR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block
411 copyToOutput(yyscanner,yytext,(int)yyleng);
413 <CComment>"{@code"/[ \t\n] {
414 copyToOutput(yyscanner,"@code",5);
415 yyextra->lastCommentContext = YY_START;
416 yyextra->javaBlock=1;
417 yyextra->blockName=&yytext[1];
420 <CComment,ReadLine>^[ \t]*("```"[`]*|"~~~"[~]*) { /* start of markdown code block */
421 if (!Config_getBool(MARKDOWN_SUPPORT))
425 copyToOutput(yyscanner,yytext,(int)yyleng);
426 yyextra->lastCommentContext = YY_START;
427 yyextra->javaBlock=0;
428 yyextra->blockName=QCString(yytext).stripWhiteSpace().left(3);
431 <CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */
432 copyToOutput(yyscanner,yytext,(int)yyleng);
433 yyextra->lastCommentContext = YY_START;
434 yyextra->javaBlock=0;
435 if (qstrcmp(&yytext[1],"startuml")==0)
437 yyextra->blockName="uml";
441 yyextra->blockName=&yytext[1];
445 <CComment,ReadLine>[\\@]("f$"|"f["|"f{"|"f(") {
446 copyToOutput(yyscanner,yytext,(int)yyleng);
447 yyextra->blockName=&yytext[1];
448 if (yyextra->blockName.at(1)=='[')
450 yyextra->blockName.at(1)=']';
452 else if (yyextra->blockName.at(1)=='{')
454 yyextra->blockName.at(1)='}';
456 else if (yyextra->blockName.at(1)=='(')
458 yyextra->blockName.at(1)=')';
460 yyextra->lastCommentContext = YY_START;
463 <CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
464 copyToOutput(yyscanner,yytext,(int)yyleng);
465 yyextra->blockName=&yytext[1];
466 yyextra->lastCommentContext = YY_START;
469 <Scan>"\\\"" { /* escaped double quote */
470 copyToOutput(yyscanner,yytext,(int)yyleng);
472 <Scan>"\\\\" { /* escaped backslash */
473 copyToOutput(yyscanner,yytext,(int)yyleng);
475 <Scan>. { /* any other character */
476 copyToOutput(yyscanner,yytext,(int)yyleng);
478 <Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
479 copyToOutput(yyscanner,yytext,(int)yyleng);
480 if (&yytext[1]==yyextra->blockName) // end of formula
482 BEGIN(yyextra->lastCommentContext);
484 else if (&yytext[4]==yyextra->blockName)
486 BEGIN(yyextra->lastCommentContext);
490 if (yyextra->javaBlock==0)
496 yyextra->javaBlock++;
497 copyToOutput(yyscanner,yytext,(int)yyleng);
501 if (yyextra->javaBlock==0)
507 yyextra->javaBlock--;
508 if (yyextra->javaBlock==0)
510 copyToOutput(yyscanner," @endcode ",10);
511 BEGIN(yyextra->lastCommentContext);
515 copyToOutput(yyscanner,yytext,(int)yyleng);
519 <VerbatimCode>("```"[`]*|"~~~"[~]*) { /* end of markdown code block */
520 copyToOutput(yyscanner,yytext,(int)yyleng);
521 if (yytext[0]==yyextra->blockName[0])
523 BEGIN(yyextra->lastCommentContext);
526 <VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */
527 copyToOutput(yyscanner,yytext,(int)yyleng);
528 if (&yytext[4]==yyextra->blockName)
530 BEGIN(yyextra->lastCommentContext);
533 <VerbatimCode>^[ \t]*{CPPC}[\!\/]? { /* skip leading comments */
534 if (!yyextra->inSpecialComment)
536 copyToOutput(yyscanner,yytext,(int)yyleng);
541 while (yytext[l]==' ' || yytext[l]=='\t')
545 copyToOutput(yyscanner,yytext,l);
546 if (yyleng-l==3) // ends with //! or ///
548 copyToOutput(yyscanner," * ",3);
552 copyToOutput(yyscanner,"//",2);
556 <Verbatim,VerbatimCode>[^`~@\/\\\n{}]* { /* any character not a backslash or new line or } */
557 copyToOutput(yyscanner,yytext,(int)yyleng);
559 <Verbatim,VerbatimCode>\n { /* new line in verbatim block */
560 copyToOutput(yyscanner,yytext,(int)yyleng);
562 <Verbatim>^[ \t]*{CPPC}[/!] {
563 if (yyextra->blockName=="dot" || yyextra->blockName=="msc" || yyextra->blockName=="uml" || yyextra->blockName.at(0)=='f')
565 // see bug 487871, strip /// from dot images and formulas.
567 while (yytext[l]==' ' || yytext[l]=='\t')
571 copyToOutput(yyscanner,yytext,l);
572 copyToOutput(yyscanner," ",3);
574 else // even slashes are verbatim (e.g. \verbatim, \code)
579 <Verbatim,VerbatimCode>. { /* any other character */
580 copyToOutput(yyscanner,yytext,(int)yyleng);
582 <SkipString>\\. { /* escaped character in string */
583 if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
586 copyToOutput(yyscanner,yytext,1);
590 copyToOutput(yyscanner,yytext,(int)yyleng);
593 <SkipString>"\"" { /* end of string */
594 copyToOutput(yyscanner,yytext,(int)yyleng);
595 BEGIN(yyextra->stringContext);
597 <SkipString>. { /* any other string character */
598 copyToOutput(yyscanner,yytext,(int)yyleng);
600 <SkipString>\n { /* new line inside string (illegal for some compilers) */
601 copyToOutput(yyscanner,yytext,(int)yyleng);
603 <SkipChar>\\. { /* escaped character */
604 if (yyextra->lang==SrcLangExt_Fortran || yyextra->lang==SrcLangExt_VHDL)
607 copyToOutput(yyscanner,yytext,1);
611 copyToOutput(yyscanner,yytext,(int)yyleng);
614 <SkipChar>' { /* end of character literal */
615 copyToOutput(yyscanner,yytext,(int)yyleng);
616 BEGIN(yyextra->charContext);
618 <SkipChar>. { /* any other string character */
619 copyToOutput(yyscanner,yytext,(int)yyleng);
621 <SkipChar>\n { /* new line character */
622 copyToOutput(yyscanner,yytext,(int)yyleng);
625 <CComment,CNComment>[^ `~<\\!@*\n{\"\/]* { /* anything that is not a '*' or command */
626 copyToOutput(yyscanner,yytext,(int)yyleng);
628 <CComment,CNComment>"*"+[^*\/\\@\n{\"]* { /* stars without slashes */
629 copyToOutput(yyscanner,yytext,(int)yyleng);
631 <CComment>"\"\"\"" { /* end of Python docstring */
632 if (yyextra->lang!=SrcLangExt_Python)
638 yyextra->nestingCount--;
639 yyextra->pythonDocString = FALSE;
640 copyToOutput(yyscanner,yytext,(int)yyleng);
644 <CComment,CNComment>\n { /* new line in comment */
645 copyToOutput(yyscanner,yytext,(int)yyleng);
646 /* in case of Fortran always end of comment */
647 if (yyextra->lang==SrcLangExt_Fortran)
652 <CComment,CNComment>"/"+"*" { /* nested C comment */
653 if (yyextra->lang==SrcLangExt_Python ||
654 yyextra->lang==SrcLangExt_Markdown)
658 yyextra->nestingCount++;
659 yyextra->commentStack.push(yyextra->lineNr);
660 copyToOutput(yyscanner,yytext,(int)yyleng);
662 <CComment,CNComment>"*"+"/" { /* end of C comment */
663 if (yyextra->lang==SrcLangExt_Python ||
664 yyextra->lang==SrcLangExt_Markdown)
670 copyToOutput(yyscanner,yytext,(int)yyleng);
671 yyextra->nestingCount--;
672 if (yyextra->nestingCount<=0)
678 //yyextra->nestingCount--;
679 yyextra->commentStack.pop();
683 /* Python an VHDL share CComment,CNComment, so special attention for ending comments is required */
684 <CComment,CNComment>"\n"/[ \t]*"#" {
685 if (yyextra->lang!=SrcLangExt_VHDL)
691 if (yyextra->vhdl) // inside --! comment
693 yyextra->vhdl = FALSE;
694 copyToOutput(yyscanner,yytext,(int)yyleng);
697 else // C-type comment
703 <CComment,CNComment>"\n"/[ \t]*"-" {
704 if (yyextra->lang!=SrcLangExt_Python || yyextra->pythonDocString)
710 copyToOutput(yyscanner,yytext,(int)yyleng);
714 <CComment,CNComment>"\n"/[ \t]*[^ \t#\-] {
715 if (yyextra->lang==SrcLangExt_Python)
717 if (yyextra->pythonDocString)
723 copyToOutput(yyscanner,yytext,(int)yyleng);
727 else if (yyextra->lang==SrcLangExt_VHDL)
729 if (yyextra->vhdl) // inside --! comment
731 yyextra->vhdl = FALSE;
732 copyToOutput(yyscanner,yytext,(int)yyleng);
735 else // C-type comment
745 /* removed for bug 674842 (bug was introduced in rev 768)
746 <CComment,CNComment>"'" {
747 yyextra->charContext = YY_START;
748 copyToOutput(yyscanner,yytext,(int)yyleng);
751 <CComment,CNComment>"\"" {
752 yyextra->stringContext = YY_START;
753 copyToOutput(yyscanner,yytext,(int)yyleng);
757 <CComment,CNComment>. {
758 copyToOutput(yyscanner,yytext,(int)yyleng);
760 <SComment>^[ \t]*{CPPC}"/"{SLASHopt}/\n {
761 replaceComment(yyscanner,0);
763 <SComment>\n[ \t]*{CPPC}"/"{SLASHopt}/\n {
764 replaceComment(yyscanner,1);
766 <SComment>^[ \t]*{CPPC}"/"[^\/\n]/.*\n {
767 replaceComment(yyscanner,0);
768 yyextra->readLineCtx=YY_START;
771 <SComment>\n[ \t]*{CPPC}[\/!]("<")?[ \t]*[\\@]"}".*\n {
772 /* See Bug 752712: end the multiline comment when finding a @} or \} command */
773 copyToOutput(yyscanner," */",3);
774 copyToOutput(yyscanner,yytext,(int)yyleng);
775 yyextra->inSpecialComment=FALSE;
776 yyextra->inRoseComment=FALSE;
779 <SComment>\n[ \t]*{CPPC}"/"[^\/\n]/.*\n {
780 replaceComment(yyscanner,1);
781 yyextra->readLineCtx=YY_START;
784 <SComment>^[ \t]*{CPPC}"!" | // just //!
785 <SComment>^[ \t]*{CPPC}"!<"/.*\n | // or //!< something
786 <SComment>^[ \t]*{CPPC}"!"[^<]/.*\n { // or //!something
787 replaceComment(yyscanner,0);
788 yyextra->readLineCtx=YY_START;
791 <SComment>\n[ \t]*{CPPC}"!" |
792 <SComment>\n[ \t]*{CPPC}"!<"/.*\n |
793 <SComment>\n[ \t]*{CPPC}"!"[^<\n]/.*\n {
794 replaceComment(yyscanner,1);
795 yyextra->readLineCtx=YY_START;
798 <SComment>^[ \t]*{CPPC}"##"/.*\n {
799 if (!yyextra->inRoseComment)
805 replaceComment(yyscanner,0);
806 yyextra->readLineCtx=YY_START;
810 <SComment>\n[ \t]*{CPPC}"##"/.*\n {
811 if (!yyextra->inRoseComment)
817 replaceComment(yyscanner,1);
818 yyextra->readLineCtx=YY_START;
822 <SComment>\n { /* end of special comment */
823 copyToOutput(yyscanner," */",3);
824 copyToOutput(yyscanner,yytext,(int)yyleng);
825 yyextra->inSpecialComment=FALSE;
826 yyextra->inRoseComment=FALSE;
830 copyToOutput(yyscanner,"/‍**",8);
833 copyToOutput(yyscanner,"*‍/",7);
836 copyToOutput(yyscanner,yytext,(int)yyleng);
839 copyToOutput(yyscanner,yytext,(int)yyleng);
841 <ReadLine>{RLopt}/\n {
842 copyToOutput(yyscanner,yytext,(int)yyleng);
843 BEGIN(yyextra->readLineCtx);
845 <CComment,CNComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
846 copyToOutput(yyscanner,yytext,(int)yyleng);
848 <CComment,ReadLine>[\\@]"cond"/[^a-z_A-Z0-9] { // conditional section
849 yyextra->condCtx = YY_START;
852 <CComment,ReadLine>[\\@]"endcond"/[^a-z_A-Z0-9] { // end of conditional section
853 bool oldSkip=yyextra->skip;
854 endCondSection(yyscanner);
855 if (YY_START==CComment && oldSkip && !yyextra->skip)
857 //printf("** Adding start of comment!\n");
858 if (yyextra->lang!=SrcLangExt_Python &&
859 yyextra->lang!=SrcLangExt_VHDL &&
860 yyextra->lang!=SrcLangExt_Markdown &&
861 yyextra->lang!=SrcLangExt_Fortran)
865 if (yyextra->specialComment)
872 <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
873 handleCondSectionId(yyscanner,yytext);
875 <CComment,ReadLine>[\\@]"cond"{WSopt}/\n {
876 yyextra->condCtx=YY_START;
877 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
879 <CondLine>. { // forgot section id?
880 handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
881 if (*yytext=='\n') yyextra->lineNr++;
883 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias without arguments
884 replaceAliases(yyscanner,QCString(yytext));
886 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
887 yyextra->lastBlockContext=YY_START;
888 yyextra->blockCount=1;
889 yyextra->aliasString=yytext;
890 yyextra->lastEscaped=0;
891 BEGIN( ReadAliasArgs );
893 <ReadAliasArgs>^[ \t]*{CPPC}[/!]/[^\n]+ { // skip leading special comments (see bug 618079)
895 <ReadAliasArgs>{CCE} { // oops, end of comment in the middle of an alias?
896 if (yyextra->lang==SrcLangExt_Python)
900 else // abort the alias, restart scanning
902 copyToOutput(yyscanner,yyextra->aliasString.data(),yyextra->aliasString.length());
903 copyToOutput(yyscanner,yytext,(int)yyleng);
907 <ReadAliasArgs>[^{}\n\\\*]+ {
908 yyextra->aliasString+=yytext;
909 yyextra->lastEscaped=FALSE;
911 <ReadAliasArgs>"\\" {
912 if (yyextra->lastEscaped) yyextra->lastEscaped=FALSE;
913 else yyextra->lastEscaped=TRUE;
914 yyextra->aliasString+=yytext;
917 yyextra->aliasString+=yytext;
919 yyextra->lastEscaped=FALSE;
922 yyextra->aliasString+=yytext;
923 if (!yyextra->lastEscaped) yyextra->blockCount++;
924 yyextra->lastEscaped=FALSE;
927 yyextra->aliasString+=yytext;
928 if (!yyextra->lastEscaped) yyextra->blockCount--;
929 if (yyextra->blockCount==0)
931 replaceAliases(yyscanner,yyextra->aliasString);
932 BEGIN( yyextra->lastBlockContext );
934 yyextra->lastEscaped=FALSE;
937 yyextra->aliasString+=yytext;
938 yyextra->lastEscaped=FALSE;
941 copyToOutput(yyscanner,yytext,(int)yyleng);
945 copyToOutput(yyscanner,yytext,(int)yyleng);
949 static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len)
951 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
954 // copy leading blanks
955 while ((c=*p) && (c==' ' || c=='\t' || c=='\n'))
958 yyextra->lineNr += c=='\n';
961 // replace start of comment marker by blanks and the last character by a *
963 while ((c=*p) && (c=='/' || c=='!' || c=='#'))
967 if (*p=='<') // comment-after-item marker
972 if (c=='!') // end after first !
984 if (blanks>1) ADDCHAR('*');
987 // copy comment line to output
988 ADDARRAY(p,len-(int)(p-s));
991 static inline int computeIndent(const char *s)
994 static int tabSize=Config_getInt(TAB_SIZE);
1000 else if (c=='\t') col+=tabSize-(col%tabSize);
1006 static inline void copyToOutput(yyscan_t yyscanner,const char *s,int len)
1008 int tabSize=Config_getInt(TAB_SIZE);
1009 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1011 if (yyextra->skip) // only add newlines.
1023 yyextra->col+=tabSize-(yyextra->col%tabSize);
1038 case '\n': yyextra->col=0;
1039 //fprintf(stderr,"---> copy %d\n",g_lineNr);
1040 yyextra->lineNr++; break;
1041 case '\t': yyextra->col+=tabSize-(yyextra->col%tabSize); break;
1042 default: yyextra->col++; break;
1048 static void clearCommentStack(yyscan_t yyscanner)
1050 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1051 while (!yyextra->commentStack.empty()) yyextra->commentStack.pop();
1054 static void startCondSection(yyscan_t yyscanner,const QCString §Id)
1056 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1057 //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1059 bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
1060 yyextra->condStack.push(CondCtx(yyextra->lineNr,sectId,yyextra->skip));
1061 if (!expResult) // not enabled
1067 static void endCondSection(yyscan_t yyscanner)
1069 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1070 if (yyextra->condStack.empty())
1072 warn(yyextra->fileName,yyextra->lineNr,"Found \\endcond command without matching \\cond");
1073 yyextra->skip=FALSE;
1077 const CondCtx &ctx = yyextra->condStack.top();
1078 yyextra->skip=ctx.skip;
1079 yyextra->condStack.pop();
1081 //printf("endCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
1084 static void handleCondSectionId(yyscan_t yyscanner,const char *expression)
1086 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1087 bool oldSkip=yyextra->skip;
1088 startCondSection(yyscanner,QCString(expression));
1089 if ((yyextra->condCtx==CComment || yyextra->readLineCtx==SComment) &&
1090 !oldSkip && yyextra->skip)
1092 if (yyextra->lang!=SrcLangExt_Python &&
1093 yyextra->lang!=SrcLangExt_VHDL &&
1094 yyextra->lang!=SrcLangExt_Markdown &&
1095 yyextra->lang!=SrcLangExt_Fortran)
1101 if (yyextra->readLineCtx==SComment)
1107 BEGIN(yyextra->condCtx);
1111 /** copies string \a s with length \a len to the output, while
1112 * replacing any alias commands found in the string.
1114 static void replaceAliases(yyscan_t yyscanner,const QCString &s)
1116 QCString result = resolveAliasCmd(s);
1117 //printf("replaceAliases(%s)->'%s'\n",s,result.data());
1118 copyToOutput(yyscanner,result.data(),result.length());
1122 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
1124 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1125 yy_size_t bytesInBuf = yyextra->inBuf->curPos()-yyextra->inBufPos;
1126 yy_size_t bytesToCopy = std::min(max_size,bytesInBuf);
1127 memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy);
1128 yyextra->inBufPos+=bytesToCopy;
1132 static void replaceComment(yyscan_t yyscanner,int offset)
1134 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1135 if (yyextra->mlBrief || yyextra->skip)
1137 copyToOutput(yyscanner,yytext,(int)yyleng);
1141 //printf("replaceComment(%s)\n",yytext);
1142 int i=computeIndent(&yytext[offset]);
1143 if (i==yyextra->blockHeadCol)
1145 replaceCommentMarker(yyscanner,yytext,(int)yyleng);
1149 copyToOutput(yyscanner," */",3);
1150 for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
1151 yyextra->inSpecialComment=FALSE;
1157 /*! This function does three things:
1158 * -# It converts multi-line C++ style comment blocks (that are aligned)
1159 * to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO).
1160 * -# It replaces aliases with their definition (see ALIASES)
1161 * -# It handles conditional sections (cond...endcond blocks)
1163 void convertCppComments(BufStr *inBuf,BufStr *outBuf,const QCString &fileName)
1166 commentcnvYY_state extra;
1167 commentcnvYYlex_init_extra(&extra,&yyscanner);
1169 commentcnvYYset_debug(1,yyscanner);
1171 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1172 //printf("convertCppComments(%s)\n",fileName);
1173 yyextra->inBuf = inBuf;
1174 yyextra->outBuf = outBuf;
1175 yyextra->inBufPos = 0;
1177 yyextra->mlBrief = Config_getBool(MULTILINE_CPP_IS_BRIEF);
1178 yyextra->skip = FALSE;
1179 yyextra->fileName = fileName;
1180 yyextra->lang = getLanguageFromFileName(fileName);
1181 yyextra->pythonDocString = FALSE;
1182 yyextra->lineNr = 1;
1183 while (!yyextra->condStack.empty()) yyextra->condStack.pop();
1184 clearCommentStack(yyscanner);
1185 yyextra->vhdl = FALSE;
1187 printlex(yy_flex_debug, TRUE, __FILE__, qPrint(fileName));
1188 yyextra->isFixedForm = FALSE;
1189 if (yyextra->lang==SrcLangExt_Fortran)
1191 FortranFormat fmt = convertFileNameFortranParserCode(fileName);
1192 yyextra->isFixedForm = recognizeFixedForm(QCString(inBuf->data()),fmt);
1195 if (yyextra->lang==SrcLangExt_Markdown)
1197 yyextra->nestingCount=0;
1199 yyextra->commentStack.push(yyextra->lineNr);
1206 while (!yyextra->condStack.empty())
1208 const CondCtx &ctx = yyextra->condStack.top();
1209 QCString sectionInfo(" ");
1210 if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
1211 warn(yyextra->fileName,ctx.lineNr,"Conditional section%sdoes not have "
1212 "a corresponding \\endcond command within this file.",sectionInfo.data());
1213 yyextra->condStack.pop();
1215 if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown && yyextra->lang!=SrcLangExt_Fortran)
1217 QCString tmp("(probable line reference: ");
1219 while (!yyextra->commentStack.empty())
1221 int lineNr = yyextra->commentStack.top();
1222 if (!first) tmp += ", ";
1223 tmp += QCString().setNum(lineNr);
1225 yyextra->commentStack.pop();
1228 warn(yyextra->fileName,yyextra->lineNr,"Reached end of file while still inside a (nested) comment. "
1229 "Nesting level %d %s",yyextra->nestingCount,tmp.data());
1231 yyextra->nestingCount = 0;
1232 if (Debug::isFlagSet(Debug::CommentCnv))
1234 yyextra->outBuf->at(yyextra->outBuf->curPos())='\0';
1235 Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: %s\n"
1236 "output=[\n%s]\n-----------\n",qPrint(fileName),yyextra->outBuf->data()
1239 printlex(yy_flex_debug, FALSE, __FILE__, qPrint(fileName));
1240 commentcnvYYlex_destroy(yyscanner);
1244 //----------------------------------------------------------------------------
1246 #if USE_STATE2STRING
1247 #include "commentcnv.l.h"