1 /******************************************************************************
3 * Copyright (C) 1997-2021 by Dimitri van Heesch.
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.
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
16 %option never-interactive
17 %option prefix="lexcodeYY"
20 %option extra-type="struct lexcodeYY_state *"
23 // forward declare yyscan_t to improve type safety
24 #define YY_TYPEDEF_YY_SCANNER_T
26 typedef yyguts_t *yyscan_t;
35 #include "outputgen.h"
41 #define YY_NEVER_INTERACTIVE 1
43 #define YY_NO_UNISTD_H 1
45 #define USE_STATE2STRING 0
47 struct lexcodeYY_state
49 CodeOutputInterface * code;
50 CCodeParser ccodeParser;
51 const char *inputString; //!< the code fragment as text
52 yy_size_t inputPosition; //!< read offset during parsing
53 int inputLines; //!< number of line in the code fragment
54 int yyLineNr; //!< current line number
55 bool needsTermination;
57 bool lineNumbers = FALSE;
58 const Definition *searchCtx;
59 bool collectXRefs = FALSE;
63 int lastStringContext = 0;
64 int docBlockContext = 0;
65 int lastPreLineCtrlContext = 0;
66 int lastRawStringContext = 0;
69 QCString rulesPatternBuffer;
71 int startCCodeLine = -1;
73 bool insideCode = FALSE;
75 QCString docBlockName;
77 bool nestedComment = false;
83 const FileDef *sourceFileDef;
84 const Definition *currentDefinition;
85 const MemberDef *currentMemberDef;
86 bool includeCodeFragment;
87 const char *currentFontClass;
91 static const char *stateToString(int state);
94 static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor);
95 static void startCodeLine(yyscan_t yyscanner);
96 static void endFontClass(yyscan_t yyscanner);
97 static void endCodeLine(yyscan_t yyscanner);
98 static void nextCodeLine(yyscan_t yyscanner);
99 static void codifyLines(yyscan_t yyscanner,const QCString &text);
100 static void startFontClass(yyscan_t yyscanner,const char *s);
101 static int countLines(yyscan_t yyscanner);
102 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
103 static void lineCount(yyscan_t yyscanner);
104 static void handleCCode(yyscan_t yyscanner);
107 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
116 LiteralStart "%{"{nl}
120 RulesSharp "<"[^>\n]*">"
121 RulesCurly "{"[^{}\n]*"}"
126 EscapeRulesCharOpen "\\["|"\<"|"\\{"|"\\("|"\\\""|"\\ "|"\\\\"
127 EscapeRulesCharClose "\\]"|"\>"|"\\}"|"\\)"
128 EscapeRulesChar {EscapeRulesCharOpen}|{EscapeRulesCharClose}
135 ID [$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*
137 CODE [cC][oO][dD][eE]
138 RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
139 RAWEND ")"[^ \t\(\)\\]{0,16}\"
140 CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
143 /* no comment start / end signs inside square brackets */
151 // doxygen start comment
152 DCOMM ("/\*!"|"/\**"|"/\/!"|"/\/\/")
154 // Optional any character
156 // Optional all but newline
191 <DefSection>^{TopStart} {
192 handleCCode(yyscanner);
193 codifyLines(yyscanner,yytext);
194 yyextra->lastContext = YY_START;
195 yyextra->startCCodeLine=yyextra->yyLineNr;
198 <DefSection>^{LiteralStart} {
199 handleCCode(yyscanner);
200 codifyLines(yyscanner,yytext);
201 yyextra->lastContext = YY_START;
202 yyextra->startCCodeLine=yyextra->yyLineNr;
203 BEGIN (LiteralSection);
205 <TopSection>^{TopEnd} {
206 handleCCode(yyscanner);
207 codifyLines(yyscanner,yytext);
208 BEGIN( yyextra->lastContext ) ;
211 yyextra->CCodeBuffer += yytext;
214 <LiteralSection>^{LiteralEnd} {
215 handleCCode(yyscanner);
216 codifyLines(yyscanner,yytext);
217 BEGIN( yyextra->lastContext ) ;
219 <LiteralSection>.*{nl} {
220 yyextra->CCodeBuffer += yytext;
223 <DefSection>{CPPC}.*{nl} {
224 yyextra->CCodeBuffer += yytext;
227 <DefSection>^{ws}*{CCS} {
228 yyextra->CCodeBuffer += yytext;
229 yyextra->lastContext = YY_START;
232 <COMMENT>{CCE}{ws}*{nl} {
233 yyextra->CCodeBuffer+=yytext;
235 handleCCode(yyscanner);
236 BEGIN(yyextra->lastContext);
239 yyextra->CCodeBuffer+=yytext;
240 handleCCode(yyscanner);
241 BEGIN(yyextra->lastContext);
244 yyextra->CCodeBuffer += yytext;
246 <COMMENT>{CPPC}|{CCS} {
247 yyextra->CCodeBuffer += yytext;
250 yyextra->CCodeBuffer += yytext;
254 yyextra->CCodeBuffer += yytext;
257 handleCCode(yyscanner);
258 codifyLines(yyscanner,yytext);
259 yyextra->startCCodeLine=yyextra->yyLineNr;
261 <DefSection>^{ws}.*{nl} {
262 yyextra->CCodeBuffer += yytext;
265 <DefSection>^{RulesStart} {
266 handleCCode(yyscanner);
267 codifyLines(yyscanner,yytext);
268 yyextra->startCCodeLine=yyextra->yyLineNr;
269 BEGIN (RulesSectionInit);
272 handleCCode(yyscanner);
273 codifyLines(yyscanner,yytext);
274 BEGIN(DefSectionLine);
276 <DefSectionLine>.*{nl} {
277 codifyLines(yyscanner,yytext);
278 yyextra->startCCodeLine=yyextra->yyLineNr;
281 <RulesSectionInit,RulesPattern>^{RulesEnd} {
282 handleCCode(yyscanner);
283 codifyLines(yyscanner,yytext);
284 yyextra->startCCodeLine=yyextra->yyLineNr;
287 <RulesSectionInit>^{nws} {
288 handleCCode(yyscanner);
292 <RulesSectionInit>{nl} {
293 yyextra->CCodeBuffer += yytext;
296 <RulesSectionInit>^{ws}.*{nl} {
297 yyextra->CCodeBuffer += yytext;
300 <RulesPattern>"<<EOF>>" {
301 yyextra->rulesPatternBuffer += yytext;
303 <RulesPattern>{EscapeRulesChar} {
304 yyextra->rulesPatternBuffer += yytext;
306 <RulesPattern>{RulesSharp} {
307 yyextra->rulesPatternBuffer += yytext;
309 <RulesPattern>{RulesCurly} {
310 yyextra->rulesPatternBuffer += yytext;
312 <RulesPattern>{StartDouble} {
313 yyextra->rulesPatternBuffer += yytext;
314 yyextra->lastContext = YY_START;
317 <RulesDouble,RulesRoundDouble>"\\\\" {
318 yyextra->rulesPatternBuffer += yytext;
320 <RulesDouble,RulesRoundDouble>"\\\"" {
321 yyextra->rulesPatternBuffer += yytext;
324 yyextra->rulesPatternBuffer += yytext;
325 BEGIN( yyextra->lastContext ) ;
327 <RulesRoundDouble>"\"" {
328 yyextra->rulesPatternBuffer += yytext;
331 <RulesDouble,RulesRoundDouble>. {
332 yyextra->rulesPatternBuffer += yytext;
334 <RulesPattern>{StartSquare} {
335 yyextra->rulesPatternBuffer += yytext;
336 yyextra->lastContext = YY_START;
339 <RulesSquare,RulesRoundSquare>{CHARCE} {
340 yyextra->rulesPatternBuffer += yytext;
342 <RulesSquare,RulesRoundSquare>"\\[" |
343 <RulesSquare,RulesRoundSquare>"\\]" {
344 yyextra->rulesPatternBuffer += yytext;
347 yyextra->rulesPatternBuffer += yytext;
348 BEGIN(RulesPattern) ;
350 <RulesRoundSquare>"]" {
351 yyextra->rulesPatternBuffer += yytext;
354 <RulesSquare,RulesRoundSquare>"\\\\" {
355 yyextra->rulesPatternBuffer += yytext;
357 <RulesSquare,RulesRoundSquare>. {
358 yyextra->rulesPatternBuffer += yytext;
360 <RulesPattern>{StartRoundQuest} {
361 yyextra->rulesPatternBuffer += yytext;
362 yyextra->lastContext = YY_START;
363 BEGIN(RulesRoundQuest);
365 <RulesRoundQuest>{nl} {
366 yyextra->rulesPatternBuffer += yytext;
367 if (!yyextra->rulesPatternBuffer.isEmpty())
369 startFontClass(yyscanner,"stringliteral");
370 codifyLines(yyscanner,yyextra->rulesPatternBuffer.data());
371 yyextra->rulesPatternBuffer.resize(0);
372 endFontClass(yyscanner);
375 <RulesRoundQuest>[^)] {
376 yyextra->rulesPatternBuffer += yytext;
378 <RulesRoundQuest>")" {
379 yyextra->rulesPatternBuffer += yytext;
380 BEGIN(yyextra->lastContext);
382 <RulesPattern>{StartRound} {
383 yyextra->roundCount++;
384 yyextra->rulesPatternBuffer += yytext;
385 yyextra->lastContext = YY_START;
388 <RulesRound>{RulesCurly} {
389 yyextra->rulesPatternBuffer += yytext;
391 <RulesRound>{StartSquare} {
392 yyextra->rulesPatternBuffer += yytext;
393 BEGIN(RulesRoundSquare);
395 <RulesRound>{StartDouble} {
396 yyextra->rulesPatternBuffer += yytext;
397 BEGIN(RulesRoundDouble);
399 <RulesRound>{EscapeRulesChar} {
400 yyextra->rulesPatternBuffer += yytext;
403 yyextra->roundCount++;
404 yyextra->rulesPatternBuffer += yytext;
407 yyextra->roundCount--;
408 yyextra->rulesPatternBuffer += yytext;
409 if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ;
412 yyextra->rulesPatternBuffer += yytext;
416 yyextra->rulesPatternBuffer += yytext;
419 yyextra->rulesPatternBuffer += yytext;
421 <RulesPattern>{ws}+"|" {
422 if (!yyextra->rulesPatternBuffer.isEmpty())
424 startFontClass(yyscanner,"stringliteral");
425 codifyLines(yyscanner,yyextra->rulesPatternBuffer);
426 yyextra->rulesPatternBuffer.resize(0);
427 endFontClass(yyscanner);
429 codifyLines(yyscanner,yytext);
430 yyextra->startCCodeLine=yyextra->yyLineNr;
431 yyextra->curlyCount = 0;
434 <RulesPattern>^{ws}*{nl} {
435 codifyLines(yyscanner,"\n");
437 <RulesPattern>^{ws}+ {
438 codifyLines(yyscanner,yytext);
440 <RulesPattern>({ws}|{nl}) {
442 if (!yyextra->rulesPatternBuffer.isEmpty())
444 startFontClass(yyscanner,"stringliteral");
445 codifyLines(yyscanner,yyextra->rulesPatternBuffer);
446 yyextra->rulesPatternBuffer.resize(0);
447 endFontClass(yyscanner);
449 yyextra->startCCodeLine=yyextra->yyLineNr;
450 yyextra->curlyCount = 0;
453 <RulesPattern>"\\\\" {
454 yyextra->rulesPatternBuffer += yytext;
456 <RulesPattern>{CCS} {
457 if (!yyextra->rulesPatternBuffer.isEmpty())
459 startFontClass(yyscanner,"stringliteral");
460 codifyLines(yyscanner,yyextra->rulesPatternBuffer);
461 yyextra->rulesPatternBuffer.resize(0);
462 endFontClass(yyscanner);
464 yyextra->CCodeBuffer += yytext;
465 yyextra->lastContext = YY_START;
469 yyextra->rulesPatternBuffer += yytext;
471 <SkipCurly>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */
472 yyextra->CCodeBuffer += yytext;
473 yyextra->lastPreLineCtrlContext = YY_START;
474 BEGIN( PreLineCtrl );
476 <PreLineCtrl>"\""[^\n\"]*"\"" {
477 yyextra->CCodeBuffer += yytext;
480 yyextra->CCodeBuffer += yytext;
483 yyextra->CCodeBuffer += yytext;
485 BEGIN( yyextra->lastPreLineCtrlContext );
488 yyextra->CCodeBuffer += yytext;
489 ++yyextra->curlyCount ;
491 <SkipCurly>"}"/{BN}*{DCOMM}"<!--" | /* see bug710917 */
493 yyextra->CCodeBuffer += yytext;
494 lineCount(yyscanner);
495 if( yyextra->curlyCount )
497 --yyextra->curlyCount ;
500 <SkipCurly>"}"{BN}*{DCOMM}"<" {
501 yyextra->CCodeBuffer += yytext;
502 lineCount(yyscanner);
503 if ( yyextra->curlyCount )
505 --yyextra->curlyCount ;
509 yyextra->docBlockContext = SkipCurlyEndDoc;
510 if (yytext[yyleng-3]=='/')
521 yyextra->CCodeBuffer += yytext;
522 yyextra->lastStringContext=SkipCurly;
525 <SkipCurly>^{B}*"#" {
526 yyextra->CCodeBuffer += yytext;
527 yyextra->lastPreLineCtrlContext = YY_START;
528 BEGIN( PreLineCtrl );
530 <SkipCurly>{B}*{RAWBEGIN} {
531 QCString raw=QCString(yytext).stripWhiteSpace();
532 yyextra->delimiter = raw.mid(2);
533 yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1);
534 yyextra->lastRawStringContext = YY_START;
535 yyextra->CCodeBuffer += yytext;
538 <SkipCurly>[^\n#"'@\\/{}<]+ {
539 yyextra->CCodeBuffer += yytext;
542 yyextra->CCodeBuffer += yytext;
543 yyextra->lastCContext = YY_START;
547 yyextra->CCodeBuffer += yytext;
548 yyextra->lastCContext = YY_START;
549 BEGIN(SkipCxxComment);
551 <SkipCurly>{CHARLIT} {
552 yyextra->CCodeBuffer += yytext;
555 yyextra->CCodeBuffer += yytext;
558 yyextra->CCodeBuffer += yytext;
560 <SkipCurly>({CPPC}{B}*)?{CCS}"!" {
561 yyextra->CCodeBuffer += yytext;
562 yyextra->docBlockContext = YY_START;
565 <SkipCurly>{CCS}"*"[*]+{BL} {
566 bool javadocBanner = Config_getBool(JAVADOC_BANNER);
567 yyextra->CCodeBuffer += yytext;
571 yyextra->docBlockContext = YY_START;
579 <SkipCurly>({CPPC}{B}*)?{CCS}"*"/{NCOMM} {
580 yyextra->CCodeBuffer += yytext;
581 yyextra->docBlockContext = YY_START;
584 <SkipCurly>{CPPC}"!" {
585 yyextra->CCodeBuffer += yytext;
586 yyextra->docBlockContext = YY_START;
589 <SkipCurly>{CPPC}"/"/[^/] {
590 yyextra->CCodeBuffer += yytext;
591 yyextra->docBlockContext = YY_START;
596 yyextra->CCodeBuffer += yytext;
598 if (yyextra->curlyCount<=0)
600 handleCCode(yyscanner);
605 yyextra->CCodeBuffer += yytext;
608 yyextra->CCodeBuffer += yytext;
609 BEGIN( yyextra->lastStringContext );
611 <SkipString>{CCS}|{CCE}|{CPPC} {
612 yyextra->CCodeBuffer += yytext;
615 yyextra->CCodeBuffer += yytext;
619 yyextra->CCodeBuffer += yytext;
621 <SkipCxxComment>.*"\\\n" { // line continuation
622 yyextra->CCodeBuffer += yytext;
625 <SkipCxxComment>{ANYopt}/\n {
626 yyextra->CCodeBuffer += yytext;
627 BEGIN( yyextra->lastCContext ) ;
630 yyextra->CCodeBuffer += yytext ;
631 lineCount(yyscanner);
633 <Comment>{CCS} { yyextra->CCodeBuffer += yytext ; }
634 <Comment>{CPPC} { yyextra->CCodeBuffer += yytext ; }
635 <Comment>{CMD}("code"|"verbatim") {
636 yyextra->insideCode=TRUE;
637 yyextra->CCodeBuffer += yytext ;
639 <Comment>{CMD}("endcode"|"endverbatim") {
640 yyextra->insideCode=FALSE;
641 yyextra->CCodeBuffer += yytext ;
643 <Comment>[^ \.\t\r\n\/\*]+ { yyextra->CCodeBuffer += yytext ; }
645 yyextra->CCodeBuffer += yytext ;
646 if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ;
648 <Comment>. { yyextra->CCodeBuffer += *yytext ; }
650 <SkipComment>{CPPC}|{CCS} {
651 yyextra->CCodeBuffer += yytext;
653 <SkipComment>[^\*\n]+ {
654 yyextra->CCodeBuffer += yytext;
657 yyextra->CCodeBuffer += yytext;
660 <SkipComment>{B}*{CCE} {
661 yyextra->CCodeBuffer += yytext;
662 BEGIN( yyextra->lastCContext );
665 yyextra->CCodeBuffer += yytext;
667 <RawString>{RAWEND} {
668 yyextra->CCodeBuffer += yytext;
669 QCString delimiter = yytext+1;
670 delimiter=delimiter.left(delimiter.length()-1);
671 if (delimiter==yyextra->delimiter)
673 BEGIN(yyextra->lastRawStringContext);
677 yyextra->CCodeBuffer += yytext;
680 yyextra->CCodeBuffer += yytext;
683 yyextra->CCodeBuffer += yytext;
688 /* ---- Single line comments ------ */
689 <DocLine>[^\n]*"\n"[ \t]*{CPPC}[/!][<]? { // continuation of multiline C++-style comment
690 yyextra->CCodeBuffer += yytext;
691 lineCount(yyscanner);
693 <DocLine>{B}*{CPPC}"/"[/]+{Bopt}/"\n" { // ignore marker line (see bug700345)
694 yyextra->CCodeBuffer += yytext;
695 BEGIN( yyextra->docBlockContext );
697 <DocLine>{NONLopt}/"\n"{B}*{CPPC}[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712
698 yyextra->CCodeBuffer += yytext;
699 BEGIN( yyextra->docBlockContext );
701 <DocLine>{NONLopt}/"\n" { // whole line
702 yyextra->CCodeBuffer += yytext;
703 BEGIN( yyextra->docBlockContext );
706 /* ---- Comments blocks ------ */
708 <DocBlock>"*"*{CCE} { // end of comment block
709 yyextra->CCodeBuffer += yytext;
710 BEGIN(yyextra->docBlockContext);
712 <DocBlock>^{B}*"*"+/[^/] {
713 yyextra->CCodeBuffer += yytext;
715 <DocBlock>^{B}*({CPPC})?{B}*"*"+/[^/a-z_A-Z0-9*] { // start of a comment line
716 yyextra->CCodeBuffer += yytext;
718 <DocBlock>^{B}*({CPPC}){B}* { // strip embedded C++ comments if at the start of a line
719 yyextra->CCodeBuffer += yytext;
721 <DocBlock>{CPPC} { // slashes in the middle of a comment block
722 yyextra->CCodeBuffer += yytext;
724 <DocBlock>{CCS} { // start of a new comment in the
725 // middle of a comment block
726 yyextra->CCodeBuffer += yytext;
728 <DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
729 yyextra->CCodeBuffer += yytext;
731 <DocBlock>{CMD}("f$"|"f["|"f{"|"f(") {
732 yyextra->CCodeBuffer += yytext;
733 yyextra->docBlockName=&yytext[1];
734 if (yyextra->docBlockName.at(1)=='[')
736 yyextra->docBlockName.at(1)=']';
738 if (yyextra->docBlockName.at(1)=='{')
740 yyextra->docBlockName.at(1)='}';
742 if (yyextra->docBlockName.at(1)=='(')
744 yyextra->docBlockName.at(1)=')';
746 yyextra->fencedSize=0;
747 yyextra->nestedComment=FALSE;
750 <DocBlock>{B}*"<"{PRE}">" {
751 yyextra->CCodeBuffer += yytext;
752 yyextra->docBlockName="<pre>";
753 yyextra->fencedSize=0;
754 yyextra->nestedComment=FALSE;
757 <DocBlock>{CMD}"startuml"/[^a-z_A-Z0-9\-] { // verbatim type command (which could contain nested comments!)
758 yyextra->CCodeBuffer += yytext;
759 yyextra->docBlockName="uml";
760 yyextra->fencedSize=0;
761 yyextra->nestedComment=FALSE;
764 <DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
765 yyextra->CCodeBuffer += yytext;
766 yyextra->docBlockName=&yytext[1];
767 yyextra->fencedSize=0;
768 yyextra->nestedComment=FALSE;
771 <DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
772 yyextra->CCodeBuffer += yytext;
773 QCString pat = substitute(yytext,"*"," ");
774 yyextra->docBlockName="~~~";
775 yyextra->fencedSize=pat.stripWhiteSpace().length();
776 yyextra->nestedComment=FALSE;
779 <DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* {
780 yyextra->CCodeBuffer += yytext;
781 QCString pat = substitute(yytext,"*"," ");
782 yyextra->docBlockName="```";
783 yyextra->fencedSize=pat.stripWhiteSpace().length();
784 yyextra->nestedComment=FALSE;
787 <DocBlock>{B}*"<code>" {
790 <DocBlock>[^@*~\/\\\n]+ { // any character that isn't special
791 yyextra->CCodeBuffer += yytext;
793 <DocBlock>\n { // newline
794 yyextra->CCodeBuffer += yytext;
795 lineCount(yyscanner);
797 <DocBlock>. { // command block
798 yyextra->CCodeBuffer += yytext;
800 /* ---- Copy verbatim sections ------ */
802 <DocCopyBlock>"</"{PRE}">" { // end of a <pre> block
803 yyextra->CCodeBuffer += yytext;
804 if (yyextra->docBlockName=="<pre>")
809 <DocCopyBlock>"</"{CODE}">" { // end of a <code> block
810 yyextra->CCodeBuffer += yytext;
811 if (yyextra->docBlockName=="<code>")
816 <DocCopyBlock>[\\@]("f$"|"f]"|"f}"|"f)") {
817 yyextra->CCodeBuffer += yytext;
818 if (yyextra->docBlockName==&yytext[1])
823 <DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
824 yyextra->CCodeBuffer += yytext;
825 if (&yytext[4]==yyextra->docBlockName)
830 <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line
831 yyextra->CCodeBuffer += yytext;
832 if (yyextra->docBlockName=="verbatim")
836 else if (yyextra->docBlockName=="code")
842 yyextra->CCodeBuffer += yytext;
845 <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s
846 if (yyextra->docBlockName=="code")
848 yyextra->CCodeBuffer += yytext;
855 <DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516)
856 if (yyextra->docBlockName=="code")
858 yyextra->CCodeBuffer += yytext;
865 <DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one *
866 if (yyextra->docBlockName=="code")
868 if (yyextra->nestedComment) // keep * it is part of the code
870 yyextra->CCodeBuffer += yytext;
872 else // remove * it is part of the comment block
874 yyextra->CCodeBuffer += yytext;
882 <DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
883 yyextra->CCodeBuffer += yytext;
884 QCString pat = substitute(yytext,"*"," ");
885 if (yyextra->fencedSize==pat.stripWhiteSpace().length())
890 <DocCopyBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* {
891 yyextra->CCodeBuffer += yytext;
892 QCString pat = substitute(yytext,"*"," ");
893 if (yyextra->fencedSize==pat.stripWhiteSpace().length())
898 <DocCopyBlock>[^<@/\*\]~\$\\\n]+ { // any character that is not special
899 yyextra->CCodeBuffer += yytext;
901 <DocCopyBlock>{CCS}|{CCE}|{CPPC} {
904 yyextra->nestedComment=TRUE;
906 else if (yytext[0]=='*')
908 yyextra->nestedComment=FALSE;
910 yyextra->CCodeBuffer += yytext;
912 <DocCopyBlock>\n { // newline
913 yyextra->CCodeBuffer += yytext;
914 lineCount(yyscanner);
916 <DocCopyBlock>. { // any other character
917 yyextra->CCodeBuffer += yytext;
919 <SkipCurlyEndDoc>"}"{BN}*{DCOMM}"<" { // desc is followed by another one
920 yyextra->docBlockContext = SkipCurlyEndDoc;
921 yyextra->CCodeBuffer += yytext;
922 if (yytext[yyleng-3]=='/')
931 <SkipCurlyEndDoc>"}" {
932 yyextra->CCodeBuffer += yytext;
936 <UserSection>.*{nl} {
937 yyextra->CCodeBuffer += yytext;
941 <*>. { fprintf(stderr,"Lex code scanner Def rule for %s: #%s#\n",stateToString(YY_START),yytext);}
942 <*>{nl} { fprintf(stderr,"Lex code scanner Def rule for newline %s: #%s#\n",stateToString(YY_START),yytext); yyextra->yyLineNr++;}
945 handleCCode(yyscanner);
950 static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor)
952 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
953 if (Doxygen::searchIndex)
955 if (yyextra->searchCtx)
957 yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false);
961 yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true);
966 /*! start a new line of code, inserting a line number if yyextra->sourceFileDef
967 * is true. If a definition starts at the current line, then the line
968 * number is linked to the documentation of that definition.
970 static void startCodeLine(yyscan_t yyscanner)
972 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
973 if (yyextra->sourceFileDef && yyextra->lineNumbers)
975 const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
977 if (!yyextra->includeCodeFragment && d)
979 yyextra->currentDefinition = d;
980 yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
981 yyextra->classScope = d->name();
983 lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
984 if (yyextra->currentMemberDef)
986 yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
987 yyextra->currentMemberDef->getOutputFileBase(),
988 yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
989 !yyextra->includeCodeFragment);
990 setCurrentDoc(yyscanner,lineAnchor);
994 yyextra->code->writeLineNumber(d->getReference(),
995 d->getOutputFileBase(),
996 QCString(),yyextra->yyLineNr,
997 !yyextra->includeCodeFragment);
998 setCurrentDoc(yyscanner,lineAnchor);
1003 yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
1004 !yyextra->includeCodeFragment);
1008 yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers);
1010 if (yyextra->currentFontClass)
1012 yyextra->code->startFontClass(yyextra->currentFontClass);
1016 static void endFontClass(yyscan_t yyscanner)
1018 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1019 if (yyextra->currentFontClass)
1021 yyextra->code->endFontClass();
1022 yyextra->currentFontClass=0;
1026 static void endCodeLine(yyscan_t yyscanner)
1028 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1029 endFontClass(yyscanner);
1030 yyextra->code->endCodeLine();
1033 static void nextCodeLine(yyscan_t yyscanner)
1035 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1036 const char *fc = yyextra->currentFontClass;
1037 endCodeLine(yyscanner);
1038 if (yyextra->yyLineNr<yyextra->inputLines)
1040 yyextra->currentFontClass = fc;
1041 startCodeLine(yyscanner);
1045 static void codifyLines(yyscan_t yyscanner,const QCString &text)
1047 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1048 if (text.isEmpty()) return;
1049 const char *p=text.data(),*sp=p;
1055 while ((c=*p++) && c!='\n') { }
1058 yyextra->yyLineNr++;
1059 int l = (int)(p-sp-1);
1060 char *tmp = (char*)malloc(l+1);
1063 yyextra->code->codify(tmp);
1064 nextCodeLine(yyscanner);
1069 yyextra->code->codify(sp);
1073 yyextra->startCCodeLine = yyextra->yyLineNr;
1076 static void startFontClass(yyscan_t yyscanner,const char *s)
1078 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1079 endFontClass(yyscanner);
1080 if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s))
1082 endFontClass(yyscanner);
1083 yyextra->code->startFontClass(s);
1084 yyextra->currentFontClass=s;
1088 /*! counts the number of lines in the input */
1089 static int countLines(yyscan_t yyscanner)
1091 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1092 const char *p=yyextra->inputString;
1098 if (c=='\n') count++;
1100 if (p>yyextra->inputString && *(p-1)!='\n')
1101 { // last line does not end with a \n, so we add an extra
1102 // line and explicitly terminate the line after parsing.
1104 yyextra->needsTermination=true;
1109 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
1111 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1112 yy_size_t inputPosition = yyextra->inputPosition;
1113 const char *s = yyextra->inputString + inputPosition;
1115 while( c < max_size && *s )
1120 yyextra->inputPosition += c;
1124 static void lineCount(yyscan_t yyscanner)
1126 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1128 for (p = yytext ; *p ; ++p )
1132 yyextra->yyLineNr++;
1137 static void handleCCode(yyscan_t yyscanner)
1139 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1140 if (yyextra->CCodeBuffer.isEmpty()) return;
1142 yyextra->ccodeParser.setStartCodeLine(false);
1143 yyextra->ccodeParser.parseCode(*yyextra->code,
1144 yyextra->classScope,
1145 yyextra->CCodeBuffer,
1147 yyextra->exampleBlock,
1148 yyextra->exampleName,
1149 yyextra->sourceFileDef,
1150 yyextra->startCCodeLine,
1151 -1, /* endLine will be calculated in called routine */
1152 yyextra->includeCodeFragment,
1153 yyextra->currentMemberDef,
1154 yyextra->lineNumbers,
1156 yyextra->collectXRefs
1158 yyextra->CCodeBuffer.resize(0);
1159 yyextra->ccodeParser.setStartCodeLine(true);
1160 yyextra->yyLineNr--;
1161 codifyLines(yyscanner,"\n");
1165 // public interface -----------------------------------------------------------
1167 struct LexCodeParser::Private
1170 lexcodeYY_state state;
1173 LexCodeParser::LexCodeParser() : p(std::make_unique<Private>())
1175 lexcodeYYlex_init_extra(&p->state, &p->yyscanner);
1177 lexcodeYYset_debug(1,p->yyscanner);
1179 resetCodeParserState();
1182 LexCodeParser::~LexCodeParser()
1184 lexcodeYYlex_destroy(p->yyscanner);
1187 void LexCodeParser::resetCodeParserState()
1189 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
1190 yyextra->currentDefinition = 0;
1191 yyextra->currentMemberDef = 0;
1194 void LexCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
1195 const QCString &scopeName,
1196 const QCString &input,
1198 bool isExampleBlock,
1199 const QCString &exampleName,
1200 const FileDef *fileDef,
1203 bool inlineFragment,
1204 const MemberDef *memberDef,
1205 bool showLineNumbers,
1206 const Definition *searchCtx,
1210 yyscan_t yyscanner = p->yyscanner;
1211 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1213 if (input.isEmpty()) return;
1215 printlex(yy_flex_debug, true, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL);
1217 yyextra->code = &codeOutIntf;
1218 yyextra->inputString = input.data();
1219 yyextra->inputPosition = 0;
1220 yyextra->currentFontClass = 0;
1221 yyextra->needsTermination = false;
1223 yyextra->classScope=scopeName;
1224 yyextra->currentMemberDef=memberDef;
1225 yyextra->searchCtx=searchCtx;
1226 yyextra->collectXRefs=collectXRefs;
1229 yyextra->yyLineNr = startLine;
1231 yyextra->yyLineNr = 1;
1234 yyextra->inputLines = endLine+1;
1236 yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1;
1238 yyextra->startCCodeLine = yyextra->yyLineNr;
1239 yyextra->exampleBlock = isExampleBlock;
1240 yyextra->exampleName = exampleName;
1241 yyextra->sourceFileDef = fileDef;
1242 yyextra->lineNumbers = fileDef!=0 && showLineNumbers;
1244 bool cleanupSourceDef = false;
1246 if (isExampleBlock && fileDef==0)
1248 // create a dummy filedef for the example
1249 yyextra->sourceFileDef = createFileDef(QCString(),!exampleName.isEmpty() ? exampleName : QCString("generated"));
1250 cleanupSourceDef = true;
1253 if (yyextra->sourceFileDef)
1255 setCurrentDoc(yyscanner,"l00001");
1258 yyextra->includeCodeFragment = inlineFragment;
1259 // Starts line 1 on the output
1260 startCodeLine(yyscanner);
1262 lexcodeYYrestart( 0, yyscanner );
1263 BEGIN( DefSection );
1264 lexcodeYYlex(yyscanner);
1266 if (yyextra->needsTermination)
1268 endCodeLine(yyscanner);
1270 if (cleanupSourceDef)
1272 // delete the temporary file definition used for this example
1273 delete yyextra->sourceFileDef;
1274 yyextra->sourceFileDef=0;
1277 printlex(yy_flex_debug, false, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL);
1280 //---------------------------------------------------------------------------------
1282 #if USE_STATE2STRING
1283 #include "lexcode.l.h"