diff options
-rw-r--r-- | Doxyfile | 4 | ||||
-rw-r--r-- | doc/features.doc | 2 | ||||
-rw-r--r-- | doc/starting.doc | 4 | ||||
-rw-r--r-- | src/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/code.h | 1 | ||||
-rw-r--r-- | src/code.l | 14 | ||||
-rw-r--r-- | src/config.xml | 3 | ||||
-rw-r--r-- | src/context.cpp | 1 | ||||
-rw-r--r-- | src/defargs.l | 4 | ||||
-rw-r--r-- | src/docsets.cpp | 1 | ||||
-rw-r--r-- | src/doxygen.cpp | 4 | ||||
-rw-r--r-- | src/lexcode.h | 57 | ||||
-rw-r--r-- | src/lexcode.l | 1223 | ||||
-rw-r--r-- | src/lexscanner.h | 43 | ||||
-rw-r--r-- | src/lexscanner.l | 938 | ||||
-rw-r--r-- | src/memberdef.cpp | 11 | ||||
-rw-r--r-- | src/pre.l | 275 | ||||
-rw-r--r-- | src/scanner.l | 5 | ||||
-rw-r--r-- | src/types.h | 3 | ||||
-rw-r--r-- | src/util.cpp | 6 |
20 files changed, 2459 insertions, 146 deletions
@@ -106,10 +106,12 @@ WARN_LOGFILE = warnings.log # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = src \ - vhdlparser + vhdlparser \ + xml INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h \ *.cpp \ + *.l \ *.md RECURSIVE = NO EXCLUDE = diff --git a/doc/features.doc b/doc/features.doc index e746ac3..9c42d5b 100644 --- a/doc/features.doc +++ b/doc/features.doc @@ -28,7 +28,7 @@ output even from undocumented code. <li>Generates structured XML output for parsed sources, which can be used by external tools. -<li>Supports C/C++, Java, (Corba and Microsoft) Java, Python, VHDL, PHP +<li>Supports C/C++, Lex, Java, (Corba and Microsoft) Java, Python, VHDL, PHP IDL, C#, Fortran, Objective-C 2.0, and to some extent D sources. <li>Supports documentation of files, namespaces, packages, classes, structs, unions, templates, variables, functions, typedefs, enums and diff --git a/doc/starting.doc b/doc/starting.doc index ad34af3..44f2a92 100644 --- a/doc/starting.doc +++ b/doc/starting.doc @@ -37,7 +37,7 @@ tries to be complete): \section step0 Step 0: Check if doxygen supports your programming language First, assure that your programming language has a reasonable chance of being -recognized by doxygen. These languages are supported by default: C, C++, C#, +recognized by doxygen. These languages are supported by default: C, C++, Lex, C#, Objective-C, IDL, Java, VHDL, PHP, Python, Fortran and D. It is possible to configure certain file type extensions to use certain parsers: see the \ref cfg_extension_mapping "Configuration/ExtensionMappings" for details. @@ -120,7 +120,7 @@ Extension | Language | Extension | Language | Extension | Language .ixx |C / C++ | .php5 |PHP | .vhdl |VHDL .ipp |C / C++ | .inc |PHP | .ucf |VHDL .i++ |C / C++ | .phtml |PHP | .qsf |VHDL -.inl |C / C++ | .m |Objective-C | | +.inl |C / C++ | .m |Objective-C | .l |Lex .h |C / C++ | .M |Objective-C | .md |Markdown .H |C / C++ | .py |Python | .markdown |Markdown .hh |C / C++ | .pyw |Python | .ice |Slice diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6af813..e85d8f2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -117,6 +117,8 @@ set(LEX_FILES scanner constexp xmlcode sqlcode + lexcode + lexscanner configimpl) # unfortunately ${LEX_FILES_H} and ${LEX_FILES_CPP} don't work in older versions of CMake (like 3.6.2) for add_library @@ -184,6 +186,8 @@ add_library(doxymain STATIC ${GENERATED_SRC}/doctokenizer.l.h ${GENERATED_SRC}/fortrancode.l.h ${GENERATED_SRC}/fortranscanner.l.h + ${GENERATED_SRC}/lexcode.l.h + ${GENERATED_SRC}/lexscanner.l.h ${GENERATED_SRC}/pre.l.h ${GENERATED_SRC}/pycode.l.h ${GENERATED_SRC}/pyscanner.l.h @@ -199,6 +203,8 @@ add_library(doxymain STATIC ${GENERATED_SRC}/doctokenizer.cpp ${GENERATED_SRC}/fortrancode.cpp ${GENERATED_SRC}/fortranscanner.cpp + ${GENERATED_SRC}/lexcode.cpp + ${GENERATED_SRC}/lexscanner.cpp ${GENERATED_SRC}/pre.cpp ${GENERATED_SRC}/pycode.cpp ${GENERATED_SRC}/pyscanner.cpp @@ -46,6 +46,7 @@ class CCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + void setStartCodeLine(const bool inp); private: struct Private; std::unique_ptr<Private> p; @@ -98,6 +98,11 @@ struct codeYY_state QCString parmType; QCString parmName; + bool beginCodeLine = true; //!< signals whether or not we should with the first line + //!< write a start line code or not. Essential + //!< when this code parser is called from another + //!< code parser. + const char * inputString = 0; //!< the code fragment as text yy_size_t inputPosition = 0; //!< read offset during parsing int inputLines = 0; //!< number of line in the code fragment @@ -3788,6 +3793,12 @@ void CCodeParser::resetCodeParserState() yyextra->anchorCount = 0; } +void CCodeParser::setStartCodeLine(const bool inp) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->beginCodeLine = inp; +} + void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const QCString &s, SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, @@ -3862,7 +3873,8 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const } yyextra->includeCodeFragment = inlineFragment; //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment); - startCodeLine(yyscanner); + + if (yyextra->beginCodeLine) startCodeLine(yyscanner); yyextra->type.resize(0); yyextra->name.resize(0); yyextra->args.resize(0); diff --git a/src/config.xml b/src/config.xml index d9b29aa..8526a2b 100644 --- a/src/config.xml +++ b/src/config.xml @@ -647,7 +647,7 @@ Go to the <a href="commands.html">next</a> section or return to the With this tag you can assign which parser to use for a given extension. Doxygen has a built-in mapping, but you can override or extend it using this tag. The format is <code>ext=language</code>, where \c ext is a file extension, and language is one of - the parsers supported by doxygen: IDL, Java, JavaScript, Csharp (C#), C, C++, D, PHP, + the parsers supported by doxygen: IDL, Java, JavaScript, Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: Fortran. In the later case the parser tries to guess whether the code is fixed or free @@ -1434,6 +1434,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" <value name='*.hxx'/> <value name='*.hpp'/> <value name='*.h++'/> + <value name='*.l'/> <value name='*.cs'/> <value name='*.d'/> <value name='*.php'/> diff --git a/src/context.cpp b/src/context.cpp index d2cfa9e..e0017fb 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1540,6 +1540,7 @@ class DefinitionContext case SrcLangExt_SQL: result="sql"; break; case SrcLangExt_Markdown: result="markdown"; break; case SrcLangExt_Slice: result="slice"; break; + case SrcLangExt_Lex: result="lex"; break; } return result; } diff --git a/src/defargs.l b/src/defargs.l index e25c1fe..76d07ec 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -27,12 +27,12 @@ * The Argument list as a whole can be pure, constant or volatile. * * Examples of input strings are: - * \code + * \verbatim * "(int a,int b) const" * "(const char *s="hello world",int=5) = 0" * "<class T,class N>" * "(char c,const char)" - * \endcode + * \endverbatim * * Note: It is not always possible to distinguish between the name and * type of an argument. In case of doubt the name is added to the diff --git a/src/docsets.cpp b/src/docsets.cpp index 4f04623..9c29818 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -328,6 +328,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, case SrcLangExt_SQL: lang="sql"; break; // Sql case SrcLangExt_Markdown:lang="markdown"; break; // Markdown case SrcLangExt_Slice: lang="slice"; break; // Slice + case SrcLangExt_Lex: lang="lex"; break; // Lex case SrcLangExt_Unknown: lang="unknown"; break; // should not happen! } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index f5a280b..c268f26 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -77,6 +77,8 @@ #include "fortranscanner.h" #include "xmlcode.h" #include "sqlcode.h" +#include "lexcode.h" +#include "lexscanner.h" #include "code.h" #include "portable.h" #include "vhdljjparser.h" @@ -10058,6 +10060,8 @@ void initDoxygen() make_parser_factory<SQLCodeParser>()); Doxygen::parserManager->registerParser("md", make_parser_factory<MarkdownOutlineParser>(), make_parser_factory<FileCodeParser>()); + Doxygen::parserManager->registerParser("lex", make_parser_factory<LexOutlineParser>(), + make_parser_factory<LexCodeParser>()); // register any additional parsers here... diff --git a/src/lexcode.h b/src/lexcode.h new file mode 100644 index 0000000..38aec50 --- /dev/null +++ b/src/lexcode.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2021 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + + +#ifndef LEXCODE_H +#define LEXCODE_H + +#include "parserintf.h" + +class CodeOutputInterface; +class FileDef; +class MemberDef; +class QCString; +class Definition; + +/** LEX code scanner. + */ +class LexCodeParser : public CodeParserInterface +{ + public: + LexCodeParser(); + virtual ~LexCodeParser(); + void parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName=0, + FileDef *fileDef=0, + int startLine=-1, + int endLine=-1, + bool inlineFragment=FALSE, + const MemberDef *memberDef=0, + bool showLineNumbers=TRUE, + const Definition *searchCtx=0, + bool collectXRefs=TRUE + ); + void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; +}; + + +#endif diff --git a/src/lexcode.l b/src/lexcode.l new file mode 100644 index 0000000..d6b41b0 --- /dev/null +++ b/src/lexcode.l @@ -0,0 +1,1223 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2021 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +%option never-interactive +%option prefix="lexcodeYY" +%option noyywrap +%option reentrant +%option extra-type="struct lexcodeYY_state *" +%top{ +#include <stdint.h> +} + +%{ + +#include <stdio.h> + +#include "config.h" +#include "doxygen.h" +#include "outputgen.h" +#include "code.h" +#include "lexcode.h" +#include "filedef.h" +#include "message.h" + +#define YY_NEVER_INTERACTIVE 1 +#define YY_NO_INPUT 1 +#define YY_NO_UNISTD_H 1 + +#define USE_STATE2STRING 0 + +struct lexcodeYY_state +{ + CodeOutputInterface * code; + CCodeParser ccodeParser; + const char *inputString; //!< the code fragment as text + yy_size_t inputPosition; //!< read offset during parsing + int inputLines; //!< number of line in the code fragment + int yyLineNr; //!< current line number + bool needsTermination; + + bool lineNumbers = FALSE; + const Definition *searchCtx; + bool collectXRefs = FALSE; + + int lastContext = 0; + int lastCContext = 0; + int lastStringContext = 0; + int docBlockContext = 0; + int lastPreLineCtrlContext = 0; + int lastRawStringContext = 0; + int curlyCount = 0; + + QCString rulesPatternBuffer; + QCString CCodeBuffer; + int startCCodeLine = -1; + int roundCount = 0; + int squareCount = 0; + bool insideCode = FALSE; + QCString delimiter; + QCString docBlockName; + uint fencedSize = 0; + bool nestedComment = false; + + bool exampleBlock; + QCString exampleName; + QCString classScope; + + FileDef *sourceFileDef; + const Definition *currentDefinition; + const MemberDef *currentMemberDef; + bool includeCodeFragment; + const char *currentFontClass; +}; + +#if USE_STATE2STRING +static const char *stateToString(int state); +#endif + +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static void startCodeLine(yyscan_t yyscanner); +static void endFontClass(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); +static int countLines(yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void lineCount(yyscan_t yyscanner); +static void handleCCode(yyscan_t yyscanner); + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + +nl (\r\n|\r|\n) +ws [ \t] +nws [^ \t\n] +TopStart "%top{"{nl} +TopEnd "}"{nl} +LiteralStart "%{"{nl} +LiteralEnd "%}"{nl} +RulesStart "%%"{nl} +RulesEnd "%%"{nl} +RulesSharp "<"[^>]*">" +RulesCurly "{"[^{}\n]*"}" +StartSquare "[" +StartDouble "\"" +StartRound "(" +EscapeRulesCharOpen "\\["|"\\<"|"\\{"|"\\("|"\\\""|"\\{"|"\\ " +EscapeRulesCharClose "\\]"|"\\>"|"\\}"|"\\)" +EscapeRulesChar {EscapeRulesCharOpen}|{EscapeRulesCharClose} + +CMD ("\\"|"@") +BN [ \t\n\r] +BL [ \t\r]*"\n" +B [ \t] +ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* +PRE [pP][rR][eE] +CODE [cC][oO][dD][eE] +RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" +RAWEND ")"[^ \t\(\)\\]{0,16}\" +CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) + +%x DefSection +%x DefSectionLine +%x RulesSectionInit +%x RulesPattern +%x RulesDouble +%x RulesRoundDouble +%x RulesSquare +%x RulesRoundSquare +%x RulesRound +%x UserSection + +%x TopSection +%x LiteralSection + +%x COMMENT + +%x SkipCurly +%x SkipCurlyEndDoc +%x PreLineCtrl +%x DocLine +%x DocBlock +%x DocCopyBlock +%x SkipString +%x RawString +%x SkipComment +%x SkipCxxComment +%x Comment + +%% + +<*>\x0d +<DefSection>^{TopStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->lastContext = YY_START; + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (TopSection); + } +<DefSection>^{LiteralStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->lastContext = YY_START; + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (LiteralSection); + } +<TopSection>^{TopEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN( yyextra->lastContext ) ; + } +<TopSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<LiteralSection>^{LiteralEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN( yyextra->lastContext ) ; + } +<LiteralSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<DefSection>"//".*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<DefSection>^{ws}*"/*" { + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +<COMMENT>"*/"{ws}*{nl} { + yyextra->CCodeBuffer+=yytext; + yyextra->yyLineNr++; + handleCCode(yyscanner); + BEGIN(yyextra->lastContext); + } +<COMMENT>"*/" { + yyextra->CCodeBuffer+=yytext; + handleCCode(yyscanner); + BEGIN(yyextra->lastContext); + } +<COMMENT>[^*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>"//"|"/*" { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<COMMENT>. { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{nl} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + } +<DefSection>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<DefSection>^{RulesStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (RulesSectionInit); + } +<DefSection>^{nws} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN(DefSectionLine); + } +<DefSectionLine>.*{nl} { + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN(DefSection); + } +<RulesSectionInit,RulesPattern>^{RulesEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (UserSection); + } +<RulesSectionInit>^{nws} { + handleCCode(yyscanner); + unput(*yytext); + BEGIN(RulesPattern); + } +<RulesSectionInit>{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<RulesSectionInit>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<RulesPattern>"<<EOF>>" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{EscapeRulesChar} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{RulesSharp} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{RulesCurly} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{StartDouble} { + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesDouble); + } +<RulesDouble,RulesRoundDouble>"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesDouble,RulesRoundDouble>"\\\"" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesDouble>"\"" { + yyextra->rulesPatternBuffer += yytext; + BEGIN( yyextra->lastContext ) ; + } +<RulesRoundDouble>"\"" { + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRound) ; + } +<RulesDouble,RulesRoundDouble>. { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{StartSquare} { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesSquare); + } +<RulesSquare,RulesRoundSquare>"\\[" | +<RulesSquare,RulesRoundSquare>"\\]" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesSquare,RulesRoundSquare>"[" { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + } +<RulesSquare>"]" { + yyextra->squareCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->squareCount) BEGIN(RulesPattern) ; + } +<RulesRoundSquare>"]" { + yyextra->squareCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->squareCount) BEGIN(RulesRound) ; + } +<RulesSquare,RulesRoundSquare>"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesSquare,RulesRoundSquare>. { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{StartRound} { + yyextra->roundCount++; + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesRound); + } +<RulesRound>{RulesCurly} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesRound>{StartSquare} { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRoundSquare); + } +<RulesRound>{StartDouble} { + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRoundDouble); + } +<RulesRound>"\\(" | +<RulesRound>"\\)" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesRound>"(" { + yyextra->roundCount++; + yyextra->rulesPatternBuffer += yytext; + } +<RulesRound>")" { + yyextra->roundCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ; + } +<RulesRound>. { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{ws}+"|" { + if (!yyextra->rulesPatternBuffer.isEmpty()) + { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->rulesPatternBuffer.data()); + yyextra->rulesPatternBuffer.resize(0); + endFontClass(yyscanner); + } + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +<RulesPattern>^{ws}*{nl} { + codifyLines(yyscanner,"\n"); + } +<RulesPattern>^{ws}+ { + codifyLines(yyscanner,yytext); + } +<RulesPattern>({ws}|{nl}) { + unput(*yytext); + if (!yyextra->rulesPatternBuffer.isEmpty()) + { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->rulesPatternBuffer.data()); + yyextra->rulesPatternBuffer.resize(0); + endFontClass(yyscanner); + } + yyextra->startCCodeLine=yyextra->yyLineNr; + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +<RulesPattern>"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>"/*" { + if (!yyextra->rulesPatternBuffer.isEmpty()) + { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->rulesPatternBuffer.data()); + yyextra->rulesPatternBuffer.resize(0); + endFontClass(yyscanner); + } + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +<RulesPattern>. { + yyextra->rulesPatternBuffer += yytext; + } +<SkipCurly>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<PreLineCtrl>"\""[^\n\"]*"\"" { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>. { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + BEGIN( yyextra->lastPreLineCtrlContext ); + } +<SkipCurly>"{" { + yyextra->CCodeBuffer += yytext; + ++yyextra->curlyCount ; + } +<SkipCurly>"}"/{BN}*("/*!"|"/**"|"//!"|"///")"<!--" | /* see bug710917 */ +<SkipCurly>"}" { + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + } +<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + if ( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else + { + yyextra->docBlockContext = SkipCurlyEndDoc; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } + } +<SkipCurly>\" { + yyextra->CCodeBuffer += yytext; + yyextra->lastStringContext=SkipCurly; + BEGIN( SkipString ); + } +<SkipCurly>^{B}*"#" { + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<SkipCurly>{B}*{RAWBEGIN} { + QCString raw=QCString(yytext).stripWhiteSpace(); + yyextra->delimiter = raw.data()+2; + yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); + yyextra->lastRawStringContext = YY_START; + yyextra->CCodeBuffer += yytext; + BEGIN(RawString); + } +<SkipCurly>[^\n#"'@\\/{}<]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>"/*" { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipComment); + } +<SkipCurly>"//" { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } +<SkipCurly>{CHARLIT} { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>\' { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>("//"{B}*)?"/*!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>"/**"[*]+{BL} { + bool javadocBanner = Config_getBool(JAVADOC_BANNER); + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + if( javadocBanner ) + { + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } + else + { + BEGIN( Comment ) ; + } + } +<SkipCurly>("//"{B}*)?"/**"/[^/*] { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>"//!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } +<SkipCurly>"///"/[^/] { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } + +<SkipCurly>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + if (yyextra->curlyCount<=0) + { + handleCCode(yyscanner); + BEGIN(RulesPattern); + } + } +<SkipString>\\. { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\" { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastStringContext ); + } +<SkipString>"/*"|"*/"|"//" { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<SkipString>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCxxComment>.*"\\\n" { // line continuation + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<SkipCxxComment>.*/\n { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ) ; + } +<Comment>{BN}+ { + yyextra->CCodeBuffer += yytext ; + lineCount(yyscanner); + } +<Comment>"/*" { yyextra->CCodeBuffer += yytext ; } +<Comment>"//" { yyextra->CCodeBuffer += yytext ; } +<Comment>{CMD}("code"|"verbatim") { + yyextra->insideCode=TRUE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>{CMD}("endcode"|"endverbatim") { + yyextra->insideCode=FALSE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>[^ \.\t\r\n\/\*]+ { yyextra->CCodeBuffer += yytext ; } +<Comment>"*/" { + yyextra->CCodeBuffer += yytext ; + if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; + } +<Comment>. { yyextra->CCodeBuffer += *yytext ; } + +<SkipComment>"//"|"/*" { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>[^\*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<SkipComment>{B}*"*/" { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ); + } +<SkipComment>"*" { + yyextra->CCodeBuffer += yytext; + } +<RawString>{RAWEND} { + yyextra->CCodeBuffer += yytext; + QCString delimiter = yytext+1; + delimiter=delimiter.left(delimiter.length()-1); + if (delimiter==yyextra->delimiter) + { + BEGIN(yyextra->lastRawStringContext); + } + } +<RawString>[^)\n]+ { + yyextra->CCodeBuffer += yytext; + } +<RawString>. { + yyextra->CCodeBuffer += yytext; + } +<RawString>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } + + + /* ---- Single line comments ------ */ +<DocLine>[^\n]*"\n"[ \t]*"//"[/!][<]? { // continuation of multiline C++-style comment + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + } +<DocLine>{B}*"///"[/]+{B}*/"\n" { // ignore marker line (see bug700345) + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n"{B}*"//"[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n" { // whole line + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } + + /* ---- Comments blocks ------ */ + +<DocBlock>"*"*"*/" { // end of comment block + yyextra->CCodeBuffer += yytext; + BEGIN(yyextra->docBlockContext); + } +<DocBlock>^{B}*"*"+/[^/] { + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>"//" { // slashes in the middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>"/*" { // start of a new comment in the + // middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CMD}("f$"|"f["|"f{") { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<"{PRE}">" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName="<pre>"; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="~~~"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="```"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<code>" { + REJECT; + } +<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special + yyextra->CCodeBuffer += yytext; + } +<DocBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + } +<DocBlock>. { // command block + yyextra->CCodeBuffer += yytext; + } + /* ---- Copy verbatim sections ------ */ + +<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<pre>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>"</"{CODE}">" { // end of a <code> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<code>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[\\@]("f$"|"f]"|"f}") { + yyextra->CCodeBuffer += yytext; + BEGIN(DocBlock); + } +<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block + yyextra->CCodeBuffer += yytext; + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="verbatim") + { + REJECT; + } + else if (yyextra->docBlockName=="code") + { + REJECT; + } + else + { + yyextra->CCodeBuffer += yytext; + } + } +<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * + if (yyextra->docBlockName=="code") + { + if (yyextra->nestedComment) // keep * it is part of the code + { + yyextra->CCodeBuffer += yytext; + } + else // remove * it is part of the comment block + { + yyextra->CCodeBuffer += yytext; + } + } + else + { + REJECT; + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[^\<@/*\]~\$\\\n]+ { // any character that is not special + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>"/*"|"*/"|"//" { + if (yytext[1]=='*') + { + yyextra->nestedComment=TRUE; + } + else if (yytext[0]=='*') + { + yyextra->nestedComment=FALSE; + } + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + } +<DocCopyBlock>. { // any other character + yyextra->CCodeBuffer += yytext; + } +<SkipCurlyEndDoc>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { // desc is followed by another one + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->CCodeBuffer += yytext; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } +<SkipCurlyEndDoc>"}" { + yyextra->CCodeBuffer += yytext; + BEGIN(SkipCurly); + } + +<UserSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } + /* +<*>. { fprintf(stderr,"Lex code scanner Def rule for %s: #%s#\n",stateToString(YY_START),yytext);} + */ +<*><<EOF>> { + handleCCode(yyscanner); + yyterminate(); + } +%% + +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (Doxygen::searchIndex) + { + if (yyextra->searchCtx) + { + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); + } + else + { + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); + } + } +} + +/*! start a new line of code, inserting a line number if yyextra->sourceFileDef + * is true. If a definition starts at the current line, then the line + * number is linked to the documentation of that definition. + */ +static void startCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->sourceFileDef && yyextra->lineNumbers) + { + const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + + if (!yyextra->includeCodeFragment && d) + { + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + yyextra->classScope = d->name().copy(); + QCString lineAnchor; + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) + { + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); + } + else + { + yyextra->code->writeLineNumber(d->getReference(), + d->getOutputFileBase(), + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); + } + } + else + { + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); + } + } + + yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); + + if (yyextra->currentFontClass) + { + yyextra->code->startFontClass(yyextra->currentFontClass); + } +} + +static void endFontClass(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) + { + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; + } +} + +static void endCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->endCodeLine(); +} + +static void nextCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNr<yyextra->inputLines) + { + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); + } +} + +static void codifyLines(yyscan_t yyscanner,const char *text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=text,*sp=p; + char c; + bool done=false; + while (!done) + { + sp=p; + while ((c=*p++) && c!='\n') { } + if (c=='\n') + { + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + if (p) + { + nextCodeLine(yyscanner); + } + else + { + endCodeLine(yyscanner); + done=true; + } + free(tmp); + } + else + { + yyextra->code->codify(sp); + done=true; + } + } + yyextra->startCCodeLine = yyextra->yyLineNr; +} + +static void startFontClass(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s)) + { + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; + } +} + +/*! counts the number of lines in the input */ +static int countLines(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->inputString; + char c; + int count=1; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; + } + if (p>yyextra->inputString && *(p-1)!='\n') + { // last line does not end with a \n, so we add an extra + // line and explicitly terminate the line after parsing. + count++, + yyextra->needsTermination=true; + } + return count; +} + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s ) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void lineCount(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p; + for (p = yytext ; *p ; ++p ) + { + if (*p=='\n') + { + yyextra->yyLineNr++; + } + } +} + +static void handleCCode(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->CCodeBuffer.isEmpty()) return; + + yyextra->ccodeParser.setStartCodeLine(false); + yyextra->ccodeParser.parseCode(*yyextra->code, + yyextra->classScope, + yyextra->CCodeBuffer, + SrcLangExt_Cpp, + yyextra->exampleBlock, + yyextra->exampleName, + yyextra->sourceFileDef, + yyextra->startCCodeLine, + -1, /* endLine will be calculated in called routine */ + yyextra->includeCodeFragment, + yyextra->currentMemberDef, + yyextra->lineNumbers, + yyextra->searchCtx, + yyextra->collectXRefs + ); + yyextra->CCodeBuffer.resize(0); + yyextra->ccodeParser.setStartCodeLine(true); + yyextra->yyLineNr--; + codifyLines(yyscanner,"\n"); + return; +} + +// public interface ----------------------------------------------------------- + +struct LexCodeParser::Private +{ + yyscan_t yyscanner; + lexcodeYY_state state; +}; + +LexCodeParser::LexCodeParser() : p(std::make_unique<Private>()) +{ + lexcodeYYlex_init_extra(&p->state, &p->yyscanner); +#ifdef FLEX_DEBUG + lexcodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); +} + +LexCodeParser::~LexCodeParser() +{ + lexcodeYYlex_destroy(p->yyscanner); +} + +void LexCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; +} + +void LexCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + + if (input.isEmpty()) return; + + printlex(yy_flex_debug, true, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = false; + + yyextra->classScope=scopeName; + yyextra->currentMemberDef=memberDef; + yyextra->searchCtx=searchCtx; + yyextra->collectXRefs=collectXRefs; + + if (startLine!=-1) + yyextra->yyLineNr = startLine; + else + yyextra->yyLineNr = 1; + + if (endLine!=-1) + yyextra->inputLines = endLine+1; + else + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; + + yyextra->startCCodeLine = yyextra->yyLineNr; + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + yyextra->lineNumbers = fileDef!=0 && showLineNumbers; + + bool cleanupSourceDef = false; + + if (isExampleBlock && fileDef==0) + { + // create a dummy filedef for the example + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); + cleanupSourceDef = true; + } + + if (yyextra->sourceFileDef) + { + setCurrentDoc(yyscanner,"l00001"); + } + + yyextra->includeCodeFragment = inlineFragment; + // Starts line 1 on the output + startCodeLine(yyscanner); + + lexcodeYYrestart( 0, yyscanner ); + BEGIN( DefSection ); + lexcodeYYlex(yyscanner); + + if (yyextra->needsTermination) + { + endCodeLine(yyscanner); + } + if (cleanupSourceDef) + { + // delete the temporary file definition used for this example + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; + } + + printlex(yy_flex_debug, false, __FILE__, fileDef ? fileDef->fileName().data(): NULL); +} + +//--------------------------------------------------------------------------------- + +#if USE_STATE2STRING +#include "lexcode.l.h" +#endif diff --git a/src/lexscanner.h b/src/lexscanner.h new file mode 100644 index 0000000..11bf25e --- /dev/null +++ b/src/lexscanner.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2021 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef SCANNER_LEL_H +#define SCANNER_LEX_H + +#include "parserintf.h" + +/** \brief Lex language parser using state-based lexical scanning. + * + * This is the Lex language parser for doxygen. + */ +class LexOutlineParser : public OutlineParserInterface +{ + public: + LexOutlineParser(); + ~LexOutlineParser(); + void parseInput(const char *fileName, + const char *fileBuf, + const std::shared_ptr<Entry> &root, + ClangTUParser *clangParser); + bool needsPreprocessing(const QCString &extension) const { return TRUE; }; + void parsePrototype(const char *text){} + + private: + struct Private; + std::unique_ptr<Private> p; +}; +#endif diff --git a/src/lexscanner.l b/src/lexscanner.l new file mode 100644 index 0000000..e0f3a92 --- /dev/null +++ b/src/lexscanner.l @@ -0,0 +1,938 @@ +/***************************************************************************** + * + * + * + * Copyright (C) 1997-2021 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ +%option never-interactive +%option prefix="lexscannerYY" +%option reentrant +%option extra-type="struct lexscannerYY_state *" +%option noyywrap + +%top{ +#include <stdint.h> +} + +%{ + +/* + * includes + */ + +#include <algorithm> +#include <vector> +#include <utility> + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <ctype.h> + +#include "config.h" +#include "lexscanner.h" +#include "entry.h" +#include "message.h" +#include "util.h" +#include "scanner.h" + +#define YY_NO_INPUT 1 +#define YY_NO_UNISTD_H 1 + +#define USE_STATE2STRING 0 + +#define repeatChar(chr, cnt) std::string(cnt, chr).c_str() + +struct lexscannerYY_state +{ + COutlineParser cOutlineParser; + const char * inputString = 0; + int inputPosition = 0; + + int lastContext = 0; + int lastCContext = 0; + int lastStringContext = 0; + int docBlockContext = 0; + int lastPreLineCtrlContext = 0; + int lastRawStringContext = 0; + int curlyCount = 0; + + bool insideCode = FALSE; + QCString delimiter; + QCString docBlockName; + uint fencedSize = 0; + bool nestedComment = false; + + QCString prefix = "yy"; + QCString CCodeBuffer; + int roundCount = 0; + int squareCount = 0; + + QCString yyFileName; + ClangTUParser *clangParser = 0; + + std::shared_ptr<Entry> current; + std::shared_ptr<Entry> current_root; + SrcLangExt language; +}; + +#if USE_STATE2STRING +static const char *stateToString(int state); +#endif +//----------------------------------------------------------------------------- + +// forward declarations for statefull functions +static void handleCCode(yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); + +/* ----------------------------------------------------------------- */ +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + +nl (\r\n|\r|\n) +ws [ \t] +nws [^ \t\n] +TopStart "%top{"{nl} +TopEnd "}"{nl} +LiteralStart "%{"{nl} +LiteralEnd "%}"{nl} +OptPrefix "%option"{ws}+"prefix"{ws}*"="{ws}* +RulesStart "%%"{nl} +RulesEnd "%%"{nl} +RulesSharp "<"[^>]*">" +RulesCurly "{"[^{}\n]*"}" +StartSquare "[" +StartDouble "\"" +StartRound "(" +EscapeRulesCharOpen "\\["|"\\<"|"\\{"|"\\("|"\\\""|"\\{"|"\\ " +EscapeRulesCharClose "\\]"|"\\>"|"\\}"|"\\)" +EscapeRulesChar {EscapeRulesCharOpen}|{EscapeRulesCharClose} + +CMD ("\\"|"@") +BN [ \t\n\r] +BL [ \t\r]*"\n" +B [ \t] +ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* +PRE [pP][rR][eE] +CODE [cC][oO][dD][eE] +RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" +RAWEND ")"[^ \t\(\)\\]{0,16}\" +CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) + +%x DefSection +%x OptPrefix +%x DefSectionLine +%x RulesSectionInit +%x RulesPattern +%x RulesDouble +%x RulesRoundDouble +%x RulesSquare +%x RulesRoundSquare +%x RulesRound +%x UserSection + +%x TopSection +%x LiteralSection + +%x COMMENT + +%x SkipCurly +%x SkipCurlyEndDoc +%x PreLineCtrl +%x DocLine +%x DocBlock +%x DocCopyBlock +%x SkipString +%x RawString +%x SkipComment +%x SkipCxxComment +%x Comment + +%% + +<*>\x0d +<DefSection>{OptPrefix} { + BEGIN (OptPrefix); + } +<OptPrefix>"\""[^\"]*"\"" { + yyextra->prefix = yytext; + yyextra->prefix = yyextra->prefix.mid(1,yyleng-2); + } +<OptPrefix>{nl} { + yyextra->CCodeBuffer += yytext; + BEGIN (DefSection); + } +<DefSection>^{RulesStart} { + yyextra->CCodeBuffer += "int " + yyextra->prefix + "lex (yyscan_t yyscanner) {\n"; + BEGIN (RulesSectionInit); + } +<DefSection>^{TopStart} { + yyextra->CCodeBuffer += "\n"; + yyextra->lastContext = YY_START; + BEGIN (TopSection); + } +<DefSection>^{LiteralStart} { + yyextra->CCodeBuffer += "\n"; + yyextra->lastContext = YY_START; + BEGIN (LiteralSection); + } +<TopSection>^{TopEnd} { + yyextra->CCodeBuffer += "\n"; + BEGIN( yyextra->lastContext ) ; + } +<TopSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<LiteralSection>^{LiteralEnd} { + yyextra->CCodeBuffer += "\n"; + BEGIN( yyextra->lastContext ) ; + } +<LiteralSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{nws} { + BEGIN(DefSectionLine); + } +<DefSection>"//".*{nl} { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{ws}*"/*" { + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +<COMMENT>"*/"{ws}*{nl} { + yyextra->CCodeBuffer+=yytext; + BEGIN(yyextra->lastContext); + } +<COMMENT>"*/" { + yyextra->CCodeBuffer+=yytext; + BEGIN(yyextra->lastContext); + } +<COMMENT>[^*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>"//"|"/*" { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>{nl} { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>. { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{nl} { + yyextra->CCodeBuffer += "\n"; + } +<DefSection>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<DefSectionLine>.*{nl} { + yyextra->CCodeBuffer += "\n"; + BEGIN(DefSection); + } +<RulesSectionInit,RulesPattern>^{RulesEnd} { + yyextra->CCodeBuffer += "}\n"; + BEGIN (UserSection); + } +<RulesSectionInit>^{nws} { + unput(*yytext); + BEGIN(RulesPattern); + } +<RulesSectionInit>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<RulesSectionInit>^{nl} { + yyextra->CCodeBuffer += yytext; + } +<RulesPattern>"<<EOF>>" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{EscapeRulesChar} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{RulesSharp} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{RulesCurly} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{StartDouble} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->lastContext = YY_START; + BEGIN(RulesDouble); + } +<RulesDouble,RulesRoundDouble>"\\\\" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesDouble,RulesRoundDouble>"\\\"" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesDouble>"\"" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN( yyextra->lastContext ) ; + } +<RulesRoundDouble>"\"" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN(RulesRound) ; + } +<RulesDouble,RulesRoundDouble>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{StartSquare} { + yyextra->squareCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->lastContext = YY_START; + BEGIN(RulesSquare); + } +<RulesSquare,RulesRoundSquare>"\\[" | +<RulesSquare,RulesRoundSquare>"\\]" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesSquare,RulesRoundSquare>"[" { + yyextra->squareCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesSquare>"]" { + yyextra->squareCount--; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + if (!yyextra->squareCount) BEGIN(RulesPattern); + } +<RulesRoundSquare>"]" { + yyextra->squareCount--; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + if (!yyextra->squareCount) BEGIN(RulesRound) ; + } +<RulesSquare,RulesRoundSquare>"\\\\" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesSquare,RulesRoundSquare>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{StartRound} { + yyextra->roundCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->lastContext = YY_START; + BEGIN(RulesRound); + } +<RulesRound>{RulesCurly} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesRound>{StartSquare} { + yyextra->squareCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN(RulesRoundSquare); + } +<RulesRound>{StartDouble} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN(RulesRoundDouble); + } +<RulesRound>"\\(" | +<RulesRound>"\\)" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesRound>"(" { + yyextra->roundCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesRound>")" { + yyextra->roundCount--; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ; + } +<RulesRound>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{ws}+"|" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +<RulesPattern>^{ws}*{nl} { + yyextra->CCodeBuffer += "\n"; + } +<RulesPattern>^{ws}+ { + } + +<RulesPattern>({ws}|{nl}) { + unput(*yytext); + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +<RulesPattern>"\\\\" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>"/*" { + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +<RulesPattern>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<SkipCurly>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<PreLineCtrl>"\""[^\n\"]*"\"" { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>. { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>\n { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastPreLineCtrlContext ); + } +<SkipCurly>"{" { + yyextra->CCodeBuffer += yytext; + ++yyextra->curlyCount ; + } +<SkipCurly>"}"/{BN}*("/*!"|"/**"|"//!"|"///")"<!--" | /* see bug710917 */ +<SkipCurly>"}" { + yyextra->CCodeBuffer += yytext; + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + } +<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { + yyextra->CCodeBuffer += yytext; + if ( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else + { + yyextra->docBlockContext = SkipCurlyEndDoc; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } + } +<SkipCurly>\" { + yyextra->CCodeBuffer += yytext; + yyextra->lastStringContext=SkipCurly; + BEGIN( SkipString ); + } +<SkipCurly>^{B}*"#" { + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<SkipCurly>{B}*{RAWBEGIN} { + QCString raw=QCString(yytext).stripWhiteSpace(); + yyextra->delimiter = raw.data()+2; + yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); + yyextra->lastRawStringContext = YY_START; + yyextra->CCodeBuffer += yytext; + BEGIN(RawString); + } +<SkipCurly>[^\n#"'@\\/{}<]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>"/*" { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipComment); + } +<SkipCurly>"//" { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } +<SkipCurly>{CHARLIT} { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>\' { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>("//"{B}*)?"/*!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>"/**"[*]+{BL} { + bool javadocBanner = Config_getBool(JAVADOC_BANNER); + yyextra->CCodeBuffer += yytext; + if( javadocBanner ) + { + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } + else + { + BEGIN( Comment ) ; + } + } +<SkipCurly>("//"{B}*)?"/**"/[^/*] { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>"//!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } +<SkipCurly>"///"/[^/] { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } + +<SkipCurly>\n { + yyextra->CCodeBuffer += yytext; + if (yyextra->curlyCount<=0) + { + BEGIN(RulesPattern); + } + } +<SkipString>\\. { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\" { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastStringContext ); + } +<SkipString>"/*"|"*/"|"//" { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\n { + yyextra->CCodeBuffer += yytext; + } +<SkipString>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCxxComment>.*"\\\n" { // line continuation + yyextra->CCodeBuffer += yytext; + } +<SkipCxxComment>.*/\n { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ) ; + } +<Comment>{BN}+ { + yyextra->CCodeBuffer += yytext ; + } +<Comment>"/*" { yyextra->CCodeBuffer += yytext ; } +<Comment>"//" { yyextra->CCodeBuffer += yytext ; } +<Comment>{CMD}("code"|"verbatim") { + yyextra->insideCode=TRUE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>{CMD}("endcode"|"endverbatim") { + yyextra->insideCode=FALSE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>[^ \.\t\r\n\/\*]+ { yyextra->CCodeBuffer += yytext ; } +<Comment>"*/" { yyextra->CCodeBuffer += yytext ; + if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; + } +<Comment>. { yyextra->CCodeBuffer += *yytext ; } + +<SkipComment>"//"|"/*" { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>[^\*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>\n { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>{B}*"*/" { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ); + } +<SkipComment>"*" { + yyextra->CCodeBuffer += yytext; + } +<RawString>{RAWEND} { + yyextra->CCodeBuffer += yytext; + QCString delimiter = yytext+1; + delimiter=delimiter.left(delimiter.length()-1); + if (delimiter==yyextra->delimiter) + { + BEGIN(yyextra->lastRawStringContext); + } + } +<RawString>[^)\n]+ { + yyextra->CCodeBuffer += yytext; + } +<RawString>. { + yyextra->CCodeBuffer += yytext; + } +<RawString>\n { + yyextra->CCodeBuffer += yytext; + } + + + /* ---- Single line comments ------ */ +<DocLine>[^\n]*"\n"[ \t]*"//"[/!][<]? { // continuation of multiline C++-style comment + yyextra->CCodeBuffer += yytext; + } +<DocLine>{B}*"///"[/]+{B}*/"\n" { // ignore marker line (see bug700345) + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n"{B}*"//"[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n" { // whole line + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } + + /* ---- Comments blocks ------ */ + +<DocBlock>"*"*"*/" { // end of comment block + yyextra->CCodeBuffer += yytext; + BEGIN(yyextra->docBlockContext); + } +<DocBlock>^{B}*"*"+/[^/] { + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>"//" { // slashes in the middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>"/*" { // start of a new comment in the + // middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CMD}("f$"|"f["|"f{") { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<"{PRE}">" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName="<pre>"; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="~~~"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="```"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<code>" { + REJECT; + } +<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special + yyextra->CCodeBuffer += yytext; + } +<DocBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + } +<DocBlock>. { // command block + yyextra->CCodeBuffer += yytext; + } + /* ---- Copy verbatim sections ------ */ + +<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<pre>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>"</"{CODE}">" { // end of a <code> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<code>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[\\@]("f$"|"f]"|"f}") { + yyextra->CCodeBuffer += yytext; + BEGIN(DocBlock); + } +<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block + yyextra->CCodeBuffer += yytext; + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="verbatim") + { + REJECT; + } + else if (yyextra->docBlockName=="code") + { + REJECT; + } + else + { + yyextra->CCodeBuffer += yytext; + } + } +<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * + if (yyextra->docBlockName=="code") + { + if (yyextra->nestedComment) // keep * it is part of the code + { + yyextra->CCodeBuffer += yytext; + } + else // remove * it is part of the comment block + { + yyextra->CCodeBuffer += yytext; + } + } + else + { + REJECT; + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[^\<@/*\]~\$\\\n]+ { // any character that is not special + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>"/*"|"*/"|"//" { + if (yytext[1]=='*') + { + yyextra->nestedComment=TRUE; + } + else if (yytext[0]=='*') + { + yyextra->nestedComment=FALSE; + } + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>. { // any other character + yyextra->CCodeBuffer += yytext; + } +<SkipCurlyEndDoc>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { // desc is followed by another one + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->CCodeBuffer += yytext; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } +<SkipCurlyEndDoc>"}" { + yyextra->CCodeBuffer += yytext; + BEGIN(SkipCurly); + } + +<UserSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + } + + /* +<*>. { fprintf(stderr,"Lex scanner Def rule for %s: #%s#\n",stateToString(YY_START),yytext);} + */ +<*><<EOF>> { + handleCCode(yyscanner); + yyterminate(); + } +%% + +//---------------------------------------------------------------------------- +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t c=0; + while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + { + *buf = yyextra->inputString[yyextra->inputPosition++] ; + //printf("%d (%c)\n",*buf,*buf); + c++; buf++; + } + return c; +} + +//----------------------------------------------------------------------------- + +static void parseMain(yyscan_t yyscanner, + const char *fileName, + const char *fileBuf, + const std::shared_ptr<Entry> &rt, + ClangTUParser *clangParser) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + + yyextra->inputString = fileBuf; + yyextra->inputPosition = 0; + lexscannerYYrestart(0,yyscanner); + + yyextra->current_root = rt; + yyextra->yyFileName = fileName; + yyextra->clangParser = clangParser; + yyextra->language = getLanguageFromFileName(yyextra->yyFileName); + rt->lang = yyextra->language; + msg("Parsing file %s...\n",yyextra->yyFileName.data()); + + yyextra->current_root = rt; + yyextra->current = std::make_shared<Entry>(); + int sec=guessSection(yyextra->yyFileName); + if (sec) + { + yyextra->current->name = yyextra->yyFileName; + yyextra->current->section = sec; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + } + yyextra->current->reset(); + BEGIN( DefSection ); + + lexscannerYYlex(yyscanner); + + rt->program.resize(0); +} + +//---------------------------------------------------------------------------- + + +static void handleCCode(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + + if (yyextra->CCodeBuffer.isEmpty()) return; + yyextra->cOutlineParser.parseInput(yyextra->yyFileName, + yyextra->CCodeBuffer, + yyextra->current_root, + yyextra->clangParser); + // SrcLangExt_Cpp, + yyextra->CCodeBuffer.resize(0); + return; +} +//---------------------------------------------------------------------------- + +struct LexOutlineParser::Private +{ + yyscan_t yyscanner; + lexscannerYY_state state; +}; + +LexOutlineParser::LexOutlineParser() : p(std::make_unique<LexOutlineParser::Private>()) +{ + lexscannerYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + lexscannerYYset_debug(1,p->yyscanner); +#endif +} + +LexOutlineParser::~LexOutlineParser() +{ + lexscannerYYlex_destroy(p->yyscanner); +} + +void LexOutlineParser::parseInput(const char *fileName, + const char *fileBuf, + const std::shared_ptr<Entry> &root, + ClangTUParser *clangParser) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + + printlex(yy_flex_debug, TRUE, __FILE__, fileName); + + ::parseMain(p->yyscanner,fileName,fileBuf,root,clangParser); + + printlex(yy_flex_debug, FALSE, __FILE__, fileName); +} + + +//---------------------------------------------------------------------------- + +#if USE_STATE2STRING +#include "lexscanner.l.h" +#endif diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 7e58331..4eeacc6 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -3512,10 +3512,17 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, else ol.parseText(theTranslator->trInitialValue()); ol.endBold(); - auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + QCString langCorrected = getDefFileExtension(); + SrcLangExt srcLangExt = getLanguageFromFileName(getDefFileExtension()); + if (srcLangExt == SrcLangExt_Lex) + { + langCorrected = ".doxygen_lex_c"; + srcLangExt = SrcLangExt_Cpp; + } + auto intf = Doxygen::parserManager->getCodeParser(langCorrected); intf->resetCodeParserState(); ol.startCodeFragment("DoxyCode"); - intf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), + intf->parseCode(ol,scopeName,m_impl->initializer,srcLangExt,FALSE,0,const_cast<FileDef*>(getFileDef()), -1,-1,TRUE,this,FALSE,this); ol.endCodeFragment("DoxyCode"); } @@ -111,8 +111,8 @@ struct PreIncludeInfo /** A dictionary of managed Define objects. */ typedef std::map< std::string, Define > DefineMap; -/** @brief Class that manages the defines available while - * preprocessing files. +/** @brief Class that manages the defines available while + * preprocessing files. */ class DefineManager { @@ -122,7 +122,7 @@ class DefineManager { public: /** Creates an empty container for defines */ - DefinesPerFile(DefineManager *parent) + DefinesPerFile(DefineManager *parent) : m_parent(parent) { } @@ -353,6 +353,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) %x SkipLine %x SkipString %x CopyLine +%x LexCopyLine %x CopyString %x CopyStringCs %x CopyStringFtn @@ -396,9 +397,14 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) unput(resolveTrigraph(yytext[2])); } <Start>^{B}*"#" { BEGIN(Command); yyextra->yyColNr+=(int)yyleng; yyextra->yyMLines=0;} +<Start>^("%top{"|"%{") { + if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Lex) REJECT + outputArray(yyscanner,yytext,(int)yyleng); + BEGIN(LexCopyLine); + } <Start>^{B}*/[^#] { outputArray(yyscanner,yytext,(int)yyleng); - BEGIN(CopyLine); + BEGIN(CopyLine); } <Start>^{B}*[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]+{B}*"("[^\)\n]*")"/{BN}{1,10}*[:{] { // constructors? int i; @@ -439,46 +445,49 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(CopyLine); } } -<CopyLine>"extern"{BN}{0,80}"\"C\""*{BN}{0,80}"{" { +<CopyLine,LexCopyLine>"extern"{BN}{0,80}"\"C\""*{BN}{0,80}"{" { QCString text=yytext; yyextra->yyLineNr+=text.contains('\n'); outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>{RAWBEGIN} { +<CopyLine,LexCopyLine>{RAWBEGIN} { yyextra->delimiter = yytext+2; yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); outputArray(yyscanner,yytext,(int)yyleng); BEGIN(CopyRawString); } -<CopyLine>"{" { // count brackets inside the main file - if (yyextra->includeStack.empty()) +<CopyLine,LexCopyLine>"{" { // count brackets inside the main file + if (yyextra->includeStack.empty()) { yyextra->curlyCount++; } outputChar(yyscanner,*yytext); } -<CopyLine>"}" { // count brackets inside the main file - if (yyextra->includeStack.empty() && yyextra->curlyCount>0) +<LexCopyLine>^"%}" { + outputArray(yyscanner,yytext,(int)yyleng); + } +<CopyLine,LexCopyLine>"}" { // count brackets inside the main file + if (yyextra->includeStack.empty() && yyextra->curlyCount>0) { yyextra->curlyCount--; } outputChar(yyscanner,*yytext); } -<CopyLine>"'"\\[0-7]{1,3}"'" { +<CopyLine,LexCopyLine>"'"\\[0-7]{1,3}"'" { outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>"'"\\."'" { +<CopyLine,LexCopyLine>"'"\\."'" { outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>"'"."'" { +<CopyLine,LexCopyLine>"'"."'" { outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>@\" { +<CopyLine,LexCopyLine>@\" { if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_CSharp) REJECT; outputArray(yyscanner,yytext,(int)yyleng); BEGIN( CopyStringCs ); } -<CopyLine>\" { +<CopyLine,LexCopyLine>\" { outputChar(yyscanner,*yytext); if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) { @@ -489,7 +498,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN( CopyStringFtnDouble ); } } -<CopyLine>\' { +<CopyLine,LexCopyLine>\' { if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT; outputChar(yyscanner,*yytext); BEGIN( CopyStringFtn ); @@ -542,7 +551,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <CopyRawString>. { outputChar(yyscanner,*yytext); } -<CopyLine>{ID}/{BN}{0,80}"(" { +<CopyLine,LexCopyLine>{ID}/{BN}{0,80}"(" { yyextra->expectGuard = FALSE; Define *def=0; //def=yyextra->globalDefineDict->find(yytext); @@ -579,9 +588,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); } } -<CopyLine>{ID} { +<CopyLine,LexCopyLine>{ID} { Define *def=0; - if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) && + if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) && yyextra->macroExpansion && (def=isDefined(yyscanner,yytext)) && def->nargs==-1 && @@ -589,7 +598,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) (!yyextra->expandOnlyPredef || def->isPredefined) ) { - QCString result=def->isPredefined ? def->definition : expandMacro(yyscanner,yytext); + QCString result=def->isPredefined ? def->definition : expandMacro(yyscanner,yytext); outputArray(yyscanner,result,result.length()); } else @@ -597,13 +606,13 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); } } -<CopyLine>"\\"\r?/\n { // strip line continuation characters +<CopyLine,LexCopyLine>"\\"\r?/\n { // strip line continuation characters if (getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran) outputChar(yyscanner,*yytext); } -<CopyLine>. { +<CopyLine,LexCopyLine>. { outputChar(yyscanner,*yytext); } -<CopyLine>\n { +<CopyLine,LexCopyLine>\n { outputChar(yyscanner,'\n'); BEGIN(Start); yyextra->yyLineNr++; @@ -672,12 +681,12 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->defArgsStr+=yytext; BEGIN(FindDefineArgs); } -<ArgCopyCComment>\n { +<ArgCopyCComment>\n { yyextra->defArgsStr+=' '; yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } -<ArgCopyCComment>. { +<ArgCopyCComment>. { yyextra->defArgsStr+=yytext; } <ReadString>"\"" { @@ -703,20 +712,20 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <Command>("include"|"import"){B}+/{ID} { yyextra->isImported = yytext[1]=='m'; - if (yyextra->macroExpansion) + if (yyextra->macroExpansion) BEGIN(IncludeID); } -<Command>("include"|"import"){B}*[<"] { +<Command>("include"|"import"){B}*[<"] { yyextra->isImported = yytext[1]=='m'; char c[2]; c[0]=yytext[yyleng-1];c[1]='\0'; yyextra->incName=c; - BEGIN(Include); + BEGIN(Include); } -<Command>("cmake")?"define"{B}+ { - //printf("!!!DefName\n"); +<Command>("cmake")?"define"{B}+ { + //printf("!!!DefName\n"); yyextra->yyColNr+=(int)yyleng; - BEGIN(DefName); + BEGIN(DefName); } <Command>"ifdef"/{B}*"(" { incrLevel(yyscanner); @@ -748,7 +757,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) if (!otherCaseDone(yyscanner)) { yyextra->guardExpr.resize(0); - BEGIN(Guard); + BEGIN(Guard); } else { @@ -765,7 +774,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) else { setCaseDone(yyscanner,TRUE); - } + } } <Command>"undef"{B}+ { BEGIN(UndefName); @@ -800,7 +809,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <Command>. {yyextra->yyColNr+=(int)yyleng;} <UndefName>{ID} { Define *def; - if ((def=isDefined(yyscanner,yytext)) + if ((def=isDefined(yyscanner,yytext)) /*&& !def->isPredefined*/ && !def->nonRecursive ) @@ -833,7 +842,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) if (guard) { BEGIN(Start); - } + } else { yyextra->ifcount=0; @@ -859,7 +868,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefinedExpr1,DefinedExpr2>\n { // should not happen, handle anyway yyextra->yyLineNr++; yyextra->ifcount=0; - BEGIN(SkipCPPBlock); + BEGIN(SkipCPPBlock); } <DefinedExpr2>")" { BEGIN(Guard); @@ -869,9 +878,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <SkipCPPBlock>^{B}*/[^#] { BEGIN(SkipLine); } <SkipCPPBlock>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } <SkipCPPBlock>. -<SkipCommand>"if"(("n")?("def"))?/[ \t(!] { +<SkipCommand>"if"(("n")?("def"))?/[ \t(!] { incrLevel(yyscanner); - yyextra->ifcount++; + yyextra->ifcount++; //printf("#if... depth=%d\n",yyextra->ifcount); } <SkipCommand>"else" { @@ -884,7 +893,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } } <SkipCommand>("elif"|"else"{B}*"if")/[ \t(!] { - if (yyextra->ifcount==0) + if (yyextra->ifcount==0) { if (!otherCaseDone(yyscanner)) { @@ -898,7 +907,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } } } -<SkipCommand>"endif" { +<SkipCommand>"endif" { yyextra->expectGuard = FALSE; decrLevel(yyscanner); if (--yyextra->ifcount<0) @@ -907,13 +916,13 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(Start); } } -<SkipCommand>\n { +<SkipCommand>\n { outputChar(yyscanner,'\n'); - yyextra->yyLineNr++; + yyextra->yyLineNr++; BEGIN(SkipCPPBlock); } -<SkipCommand>{ID} { // unknown directive - BEGIN(SkipLine); +<SkipCommand>{ID} { // unknown directive + BEGIN(SkipLine); } <SkipCommand>. <SkipLine>[^'"/\n]+ @@ -922,13 +931,13 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(SkipString); } <SkipLine>. -<SkipString>"//"/[^\n]* { +<SkipString>"//"/[^\n]* { } <SkipLine,SkipCommand,SkipCPPBlock>"//"[^\n]* { yyextra->lastCPPContext=YY_START; BEGIN(RemoveCPPComment); } -<SkipString>"/*"/[^\n]* { +<SkipString>"/*"/[^\n]* { } <SkipLine,SkipCommand,SkipCPPBlock>"/*"/[^\n]* { yyextra->lastCContext=YY_START; @@ -936,7 +945,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <SkipLine>\n { outputChar(yyscanner,'\n'); - yyextra->yyLineNr++; + yyextra->yyLineNr++; BEGIN(SkipCPPBlock); } <SkipString>[^"\\\n]+ { } @@ -957,7 +966,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) readIncludeFile(yyscanner,expandMacro(yyscanner,yytext)); BEGIN(Start); } -<Include>[^\">\n]+[\">] { +<Include>[^\">\n]+[\">] { yyextra->incName+=yytext; readIncludeFile(yyscanner,yyextra->incName); if (yyextra->isImported) @@ -972,7 +981,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <EndImport>[^\\\n]*/\n { BEGIN(Start); } -<EndImport>\\[\r]?"\n" { +<EndImport>\\[\r]?"\n" { outputChar(yyscanner,'\n'); yyextra->yyLineNr++; } @@ -1007,9 +1016,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->quoteArg=FALSE; yyextra->insideComment=FALSE; yyextra->lastGuardName.resize(0); - yyextra->defText="1"; - yyextra->defLitText="1"; - BEGIN(DefineText); + yyextra->defText="1"; + yyextra->defLitText="1"; + BEGIN(DefineText); } else // define is a guard => hide { @@ -1061,7 +1070,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,tmp.data(),tmp.length()); yyextra->quoteArg=FALSE; yyextra->insideComment=FALSE; - BEGIN(DefineText); + BEGIN(DefineText); } <DefineArg>"\\\n" { yyextra->defExtraSpacing+="\n"; @@ -1070,7 +1079,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefineArg>","{B}* { yyextra->defArgsStr+=yytext; } <DefineArg>"("{B}* { yyextra->defArgsStr+=yytext; } <DefineArg>{B}*")"{B}* { - yyextra->defArgsStr+=yytext; + yyextra->defArgsStr+=yytext; QCString tmp=(QCString)"#define "+yyextra->defName+yyextra->defArgsStr+yyextra->defExtraSpacing; outputArray(yyscanner,tmp.data(),tmp.length()); yyextra->quoteArg=FALSE; @@ -1126,13 +1135,13 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputChar(yyscanner,'*');outputChar(yyscanner,'/'); if (--yyextra->commentCount<=0) { - if (yyextra->lastCContext==Start) + if (yyextra->lastCContext==Start) // small hack to make sure that ^... rule will // match when going to Start... Example: "/*...*/ some stuff..." { YY_CURRENT_BUFFER->yy_at_bol=1; } - BEGIN(yyextra->lastCContext); + BEGIN(yyextra->lastCContext); } } <SkipCComment>"//"("/")* { @@ -1196,12 +1205,12 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); } <SkipCPPComment>[\\@]"cond"[ \t]+ { // conditional section - yyextra->ccomment=TRUE; + yyextra->ccomment=TRUE; yyextra->condCtx=YY_START; BEGIN(CondLineCpp); } <SkipCComment>[\\@]"cond"[ \t]+ { // conditional section - yyextra->ccomment=FALSE; + yyextra->ccomment=FALSE; yyextra->condCtx=YY_START; BEGIN(CondLineC); } @@ -1274,7 +1283,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); } } -<SkipCond>[\\@]"endcond"/[^a-z_A-Z0-9\x80-\xFF] { +<SkipCond>[\\@]"endcond"/[^a-z_A-Z0-9\x80-\xFF] { bool oldSkip = yyextra->skip; endCondSection(yyscanner); if (oldSkip && !yyextra->skip) @@ -1289,7 +1298,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <SkipCComment,SkipCPPComment>[\\@]"endcond"/[^a-z_A-Z0-9\x80-\xFF] { bool oldSkip = yyextra->skip; endCondSection(yyscanner); - if (oldSkip && !yyextra->skip) + if (oldSkip && !yyextra->skip) { BEGIN(yyextra->condCtx); } @@ -1325,7 +1334,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <SkipCComment,SkipVerbatim>[^*\\@\x06~`\n\/]+ { outputArray(yyscanner,yytext,(int)yyleng); } -<SkipCComment,SkipVerbatim>\n { +<SkipCComment,SkipVerbatim>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } @@ -1347,7 +1356,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->defText+=yytext; BEGIN(yyextra->lastCContext); } -<CopyCComment>\n { +<CopyCComment>\n { yyextra->yyLineNr++; yyextra->defLitText+=yytext; yyextra->defText+=' '; @@ -1447,7 +1456,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputChar(yyscanner,'\n'); Define *def=0; //printf("Define name='%s' text='%s' litTexti='%s'\n",yyextra->defName.data(),yyextra->defText.data(),yyextra->defLitText.data()); - if (yyextra->includeStack.empty() || yyextra->curlyCount>0) + if (yyextra->includeStack.empty() || yyextra->curlyCount>0) { addMacroDefinition(yyscanner); } @@ -1468,7 +1477,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) def->name = yyextra->defName; def->definition = yyextra->defText.stripWhiteSpace(); def->nargs = yyextra->defArgs; - def->fileName = yyextra->yyFileName.copy(); + def->fileName = yyextra->yyFileName.copy(); def->lineNr = yyextra->yyLineNr-yyextra->yyMLines; def->columnNr = yyextra->yyColNr; } @@ -1486,16 +1495,16 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefineText>{B}* { yyextra->defText += ' '; yyextra->defLitText+=yytext; } <DefineText>{B}*"##"{B}* { yyextra->defText += "##"; yyextra->defLitText+=yytext; } <DefineText>"@" { yyextra->defText += "@@"; yyextra->defLitText+=yytext; } -<DefineText>\" { - yyextra->defText += *yytext; - yyextra->defLitText+=yytext; +<DefineText>\" { + yyextra->defText += *yytext; + yyextra->defLitText+=yytext; if (!yyextra->insideComment) { BEGIN(SkipDoubleQuote); } } <DefineText>\' { yyextra->defText += *yytext; - yyextra->defLitText+=yytext; + yyextra->defLitText+=yytext; if (!yyextra->insideComment) { BEGIN(SkipSingleQuote); @@ -1504,7 +1513,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <SkipDoubleQuote>"//"[/]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } <SkipDoubleQuote>"/*"[*]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } <SkipDoubleQuote>\" { - yyextra->defText += *yytext; yyextra->defLitText+=yytext; + yyextra->defText += *yytext; yyextra->defLitText+=yytext; BEGIN(DefineText); } <SkipSingleQuote,SkipDoubleQuote>\\. { @@ -1541,7 +1550,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) setFileName(yyscanner,fs->fileName); DBG_CTX((stderr,"######## FileName %s\n",yyextra->yyFileName.data())); - // Deal with file changes due to + // Deal with file changes due to // #include's within { .. } blocks QCString lineStr(15+yyextra->yyFileName.length()); lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,yyextra->yyFileName.data()); @@ -1593,7 +1602,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); yyextra->lastCContext=YY_START; yyextra->commentCount=1; - if (yyleng==3) + if (yyleng==3) { yyextra->isSpecialComment = true; yyextra->lastGuardName.resize(0); // reset guard in case the #define is documented! @@ -1626,9 +1635,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(SkipCPPComment); } } -<*>\n { +<*>\n { outputChar(yyscanner,'\n'); - yyextra->yyLineNr++; + yyextra->yyLineNr++; } <*>. { yyextra->expectGuard = FALSE; @@ -1845,23 +1854,23 @@ static QCString extractTrailingComment(const char *s) { i--; while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--; - if (i==0) + if (i==0) { i++; } // only /*!< or /**< are treated as a comment for the macro name, // otherwise the comment is treated as part of the macro definition - return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : ""; + return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : ""; } else { return ""; } - } + } break; // whitespace or line-continuation case ' ': - case '\t': + case '\t': case '\r': case '\n': case '\\': @@ -1935,7 +1944,7 @@ static QCString stringize(const QCString &s) while (i<s.length() && inString) { c=s.at(i++); - if (c=='"') + if (c=='"') { result+="\\\""; inString= pc=='\\'; @@ -1952,15 +1961,15 @@ static QCString stringize(const QCString &s) return result; } -/*! Execute all ## operators in expr. - * If the macro name before or after the operator contains a no-rescan +/*! Execute all ## operators in expr. + * If the macro name before or after the operator contains a no-rescan * marker (@-) then this is removed (before the concatenated macro name * may be expanded again. */ static void processConcatOperators(QCString &expr) { //printf("processConcatOperators: in='%s'\n",expr.data()); - QRegExp r("[ \\t\\n]*##[ \\t\\n]*"); + QRegExp r("[ \\t\\n]*##[ \\t\\n]*"); int l,n,i=0; if (expr.isEmpty()) return; while ((n=r.match(expr,i,&l))!=-1) @@ -1975,7 +1984,7 @@ static void processConcatOperators(QCString &expr) // remove the ## operator and the surrounding whitespace expr=expr.left(n)+expr.right(expr.length()-n-l); int k=n-1; - while (k>=0 && isId(expr.at(k))) k--; + while (k>=0 && isId(expr.at(k))) k--; if (k>0 && expr.at(k)=='-' && expr.at(k-1)=='@') { // remove no-rescan marker before ID @@ -2006,12 +2015,12 @@ static inline void addTillEndOfString(yyscan_t yyscanner,const QCString &expr,QC } /*! replaces the function macro \a def whose argument list starts at - * \a pos in expression \a expr. + * \a pos in expression \a expr. * Notice that this routine may scan beyond the \a expr string if needed. * In that case the characters will be read from the input file. - * The replacement string will be returned in \a result and the + * The replacement string will be returned in \a result and the * length of the (unexpanded) argument list is stored in \a len. - */ + */ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCString *rest,int pos,int &len,const Define *def,QCString &result,int level) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); @@ -2020,15 +2029,15 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin len=0; result.resize(0); int cc; - while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && isspace(cc)) - { - len++; - getNextChar(yyscanner,expr,rest,j); + while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && isspace(cc)) + { + len++; + getNextChar(yyscanner,expr,rest,j); } - if (cc!='(') - { - unputChar(yyscanner,expr,rest,j,(char)cc); - return FALSE; + if (cc!='(') + { + unputChar(yyscanner,expr,rest,j,(char)cc); + return FALSE; } getNextChar(yyscanner,expr,rest,j); // eat the '(' character @@ -2048,7 +2057,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin } else { - while (!done && (argCount<def->nargs || def->varArgs) && + while (!done && (argCount<def->nargs || def->varArgs) && ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0) ) { @@ -2102,21 +2111,21 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin done=TRUE; } } - } + } else if (c=='\"') // append literal strings { - arg+=c; + arg+=c; bool found=FALSE; while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0) { found = cc=='"'; if (cc=='\\') { - c=(char)cc; + c=(char)cc; arg+=c; if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break; } - c=(char)cc; + c=(char)cc; arg+=c; } } @@ -2129,14 +2138,14 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin found = cc=='\''; if (cc=='\\') { - c=(char)cc; + c=(char)cc; arg+=c; if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break; } c=(char)cc; arg+=c; } - } + } else if (c=='/') // possible start of a comment { char prevChar = '\0'; @@ -2196,7 +2205,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin k++; // scan the number while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++); - if (!hash) + if (!hash) { // search for ## forward l=k; @@ -2220,7 +2229,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin { //printf("'%s'=stringize('%s')\n",stringize(*subst).data(),subst->data()); - // if the marker is inside a string (because a # was put + // if the marker is inside a string (because a # was put // before the macro name) we must escape " and \ characters resExpr+=stringize(substArg); } @@ -2244,7 +2253,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin } else // no marker, just copy { - if (!inString && d.at(k)=='\"') + if (!inString && d.at(k)=='\"') { inString=TRUE; // entering a literal string } @@ -2284,13 +2293,13 @@ static int getNextId(const QCString &expr,int p,int *l) n=p-1; while (p<(int)expr.length() && isId(expr.at(p))) p++; *l=p-n; - return n; + return n; } else if (c=='"') // skip string { char ppc=0,pc=c; if (p<(int)expr.length()) c=expr.at(p); - while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\'))) + while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\'))) // continue as long as no " is found, but ignoring \", but not \\" { ppc=pc; @@ -2304,11 +2313,11 @@ static int getNextId(const QCString &expr,int p,int *l) { //printf("Found C comment at p=%d\n",p); char pc=c; - if (p<(int)expr.length()) + if (p<(int)expr.length()) { c=expr.at(p); if (c=='*') // Start of C comment - { + { p++; while (p<(int)expr.length() && !(pc=='*' && c=='/')) { @@ -2369,7 +2378,7 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in //printf("found defined inside macro definition '%s'\n",expr.right(expr.length()-p).data()); definedTest=TRUE; } - else if (definedTest) // macro name was found after defined + else if (definedTest) // macro name was found after defined { if (def) expMacro = " 1 "; else expMacro = " 0 "; replaced=TRUE; @@ -2527,7 +2536,7 @@ static QCString removeIdsAndMarkers(const char *s) { if (*(p+1)=='@') { - result+=c; + result+=c; } else if (*(p+1)=='E') { @@ -2547,7 +2556,7 @@ static QCString removeIdsAndMarkers(const char *s) } else if (c=='d' && !inNum) // identifier starting with a 'd' { - if (qstrncmp(p,"defined ",8)==0 || qstrncmp(p,"defined(",8)==0) + if (qstrncmp(p,"defined ",8)==0 || qstrncmp(p,"defined(",8)==0) // defined keyword { p+=7; // skip defined @@ -2599,7 +2608,7 @@ static QCString removeIdsAndMarkers(const char *s) char pc=c; c=*++p; if (c=='*') // start of C comment - { + { while (*p && !(pc=='*' && c=='/')) // search end of comment { pc=c; @@ -2613,7 +2622,7 @@ static QCString removeIdsAndMarkers(const char *s) goto nextChar; } } - else + else { nextChar: result+=c; @@ -2628,7 +2637,7 @@ nextChar: } /*! replaces all occurrences of @@ in \a s by @ - * \par assumption: + * \par assumption: * \a s only contains pairs of @@'s */ static QCString removeMarkers(const char *s) @@ -2646,7 +2655,7 @@ static QCString removeMarkers(const char *s) { if (*(p+1)=='@') { - result+=c; + result+=c; } p+=2; } @@ -2657,12 +2666,12 @@ static QCString removeMarkers(const char *s) char pc=c; c=*++p; if (c=='*') // start of C comment - { + { while (*p && !(pc=='*' && c=='/')) // search end of comment { - if (*p=='@' && *(p+1)=='@') + if (*p=='@' && *(p+1)=='@') result+=c,p++; - else + else result+=c; pc=c; c=*++p; @@ -2727,7 +2736,7 @@ static void addDefine(yyscan_t yyscanner) def.name = state->defName; def.definition = state->defText.stripWhiteSpace(); def.nargs = state->defArgs; - def.fileName = state->yyFileName; + def.fileName = state->yyFileName; def.fileDef = state->yyFileDef; def.lineNr = state->yyLineNr-state->yyMLines; def.columnNr = state->yyColNr; @@ -2735,7 +2744,7 @@ static void addDefine(yyscan_t yyscanner) //printf("newDefine: %s %s file: %s\n",def.name.data(),def.definition.data(), // def.fileDef ? def.fileDef->name().data() : def.fileName.data()); //printf("newDefine: '%s'->'%s'\n",def.name.data(),def.definition.data()); - if (!def.name.isEmpty() && + if (!def.name.isEmpty() && Doxygen::expandAsDefinedSet.find(def.name.str())!=Doxygen::expandAsDefinedSet.end()) { def.isPredefined=TRUE; @@ -2751,7 +2760,7 @@ static void addDefine(yyscan_t yyscanner) static void addMacroDefinition(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - if (state->skip) return; // do not add this define as it is inside a + if (state->skip) return; // do not add this define as it is inside a // conditional section (cond command) that is disabled. Define define; @@ -2892,7 +2901,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) //printf("Found include file!\n"); if (Debug::isFlagSet(Debug::Preprocessor)) { - for (i=0;i<state->includeStack.size();i++) + for (i=0;i<state->includeStack.size();i++) { Debug::print(Debug::Preprocessor,0," "); } @@ -2927,7 +2936,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) state->includeStack.emplace_back(fs); // set the scanner to the include file - // Deal with file changes due to + // Deal with file changes due to // #include's within { .. } blocks QCString lineStr(state->yyFileName.length()+20); lineStr.sprintf("# 1 \"%s\" 1\n",state->yyFileName.data()); @@ -2968,7 +2977,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) if (Debug::isFlagSet(Debug::Preprocessor)) { - for (i=0;i<state->includeStack.size();i++) + for (i=0;i<state->includeStack.size();i++) { Debug::print(Debug::Preprocessor,0," "); } @@ -3089,7 +3098,7 @@ static int getNextChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,ui return cc; } } - + static int getCurrentChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,uint pos) { //printf("getCurrentChar(%s,%s,%d)\n",expr.data(),rest ? rest->data() : 0,pos); @@ -3185,8 +3194,8 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) continue; // no define name } - if (i_obrace<i_equals && i_cbrace<i_equals && - i_obrace!=-1 && i_cbrace!=-1 && + if (i_obrace<i_equals && i_cbrace<i_equals && + i_obrace!=-1 && i_cbrace!=-1 && i_obrace<i_cbrace ) // predefined function macro definition { @@ -3205,7 +3214,7 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) { //printf("predefined function macro '%s'\n",qPrint(ds.mid(i_obrace+1,i_cbrace-i_obrace-1))); i=i_obrace+1; - // gather the formal arguments in a dictionary + // gather the formal arguments in a dictionary while (i<i_cbrace && (pi=reId.match(ds,i,&l))) { if (l>0) // see bug375037 @@ -3224,7 +3233,7 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) QCString tmp=ds.right(ds.length()-i_equals-1); QCString definition; i=0; - // substitute all occurrences of formal arguments by their + // substitute all occurrences of formal arguments by their // corresponding markers while ((pi=reId.match(tmp,i,&l))!=-1) { @@ -3355,20 +3364,20 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output state->inputFileDef = state->yyFileDef; //yyextra->defineManager.startContext(state->yyFileName); - + initPredefined(yyscanner,fileName); - + state->yyLineNr = 1; state->yyColNr = 1; state->ifcount = 0; BEGIN( Start ); - + state->expectGuard = guessSection(fileName)==Entry::HEADER_SEC; state->guardName.resize(0); state->lastGuardName.resize(0); state->guardExpr.resize(0); - + preYYlex(yyscanner); while (!state->condStack.empty()) @@ -3391,7 +3400,7 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output Debug::print(Debug::Preprocessor,0,"Preprocessor output of %s (size: %d bytes):\n",fileName,newPos-orgPos); int line=1; Debug::print(Debug::Preprocessor,0,"---------\n00001 "); - while (orgPos<newPos) + while (orgPos<newPos) { putchar(*orgPos); if (*orgPos=='\n') Debug::print(Debug::Preprocessor,0,"%05d ",++line); diff --git a/src/scanner.l b/src/scanner.l index 6970d3e..7edfc9b 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -6842,7 +6842,8 @@ static void setContext(yyscan_t yyscanner) yyextra->insideObjC = yyextra->language==SrcLangExt_ObjC; yyextra->insideJS = yyextra->language==SrcLangExt_JS; yyextra->insideSlice = yyextra->language==SrcLangExt_Slice; - yyextra->insideCpp = yyextra->language==SrcLangExt_Cpp; + yyextra->insideCpp = (yyextra->language==SrcLangExt_Cpp || + yyextra->language==SrcLangExt_Lex); //printf("setContext(%s) yyextra->insideIDL=%d yyextra->insideJava=%d yyextra->insideCS=%d " // "yyextra->insideD=%d yyextra->insidePHP=%d yyextra->insideObjC=%d\n", // yyextra->yyFileName.data(),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC @@ -7458,7 +7459,7 @@ bool COutlineParser::needsPreprocessing(const QCString &extension) const { QCString fe=extension.lower(); SrcLangExt lang = getLanguageFromFileName(extension); - return (SrcLangExt_Cpp == lang) || + return (SrcLangExt_Cpp == lang) || (SrcLangExt_Lex == lang) || !( fe==".java" || fe==".as" || fe==".d" || fe==".php" || fe==".php4" || fe==".inc" || fe==".phtml"|| fe==".php5" ); diff --git a/src/types.h b/src/types.h index d34444c..3667f3d 100644 --- a/src/types.h +++ b/src/types.h @@ -57,7 +57,8 @@ enum SrcLangExt //SrcLangExt_Tcl = 0x08000, // no longer supported SrcLangExt_Markdown = 0x10000, SrcLangExt_SQL = 0x20000, - SrcLangExt_Slice = 0x40000 + SrcLangExt_Slice = 0x40000, + SrcLangExt_Lex = 0x100000 }; /** Grouping info */ diff --git a/src/util.cpp b/src/util.cpp index 3bf349a..ad6b208 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -325,6 +325,7 @@ int guessSection(const char *name) n.right(4)==".i++" || n.right(4)==".inl" || n.right(4)==".xml" || + n.right(4)==".lex" || n.right(4)==".sql" ) return Entry::SOURCE_SEC; if (n.right(2)==".h" || // header @@ -5483,6 +5484,7 @@ g_lang2extMap[] = { "xml", "xml", SrcLangExt_XML }, { "sql", "sql", SrcLangExt_SQL }, { "md", "md", SrcLangExt_Markdown }, + { "lex", "lex", SrcLangExt_Lex }, { 0, 0, (SrcLangExt)0 } }; @@ -5580,6 +5582,9 @@ void initDefaultExtensionMapping() updateLanguageMapping(".md", "md"); updateLanguageMapping(".markdown", "md"); updateLanguageMapping(".ice", "slice"); + updateLanguageMapping(".l", "lex"); + updateLanguageMapping(".doxygen_lex_c", "c"); // this is a placeholder so we can map initializations + // in the lex scanning to cpp } void addCodeOnlyMappings() @@ -6592,6 +6597,7 @@ QCString langToString(SrcLangExt lang) case SrcLangExt_SQL: return "SQL"; case SrcLangExt_Markdown: return "Markdown"; case SrcLangExt_Slice: return "Slice"; + case SrcLangExt_Lex: return "Lex"; } return "Unknown"; } |