diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2020-06-15 17:25:46 (GMT) |
---|---|---|
committer | Dimitri van Heesch <doxygen@gmail.com> | 2020-06-16 19:30:41 (GMT) |
commit | e922facbb92cda058eae33f58f7640be8d1fb5b8 (patch) | |
tree | ae45b9db9d6ed339b28ba22199e75bcf16993318 | |
parent | 3040df2f0aa29a4207de5b37da1d20e3d27340bb (diff) | |
download | Doxygen-e922facbb92cda058eae33f58f7640be8d1fb5b8.zip Doxygen-e922facbb92cda058eae33f58f7640be8d1fb5b8.tar.gz Doxygen-e922facbb92cda058eae33f58f7640be8d1fb5b8.tar.bz2 |
Refactor: modernize markdown and make it thread-safe
35 files changed, 1688 insertions, 1661 deletions
diff --git a/addon/doxyapp/CMakeLists.txt b/addon/doxyapp/CMakeLists.txt index 9d74fbc..8ec4d2e 100644 --- a/addon/doxyapp/CMakeLists.txt +++ b/addon/doxyapp/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories( add_executable(doxyapp doxyapp.cpp ) +add_sanitizers(doxyapp) if (use_libclang) set(CLANG_LIBS libclang clangTooling ${llvm_libs}) diff --git a/addon/doxyparse/CMakeLists.txt b/addon/doxyparse/CMakeLists.txt index 8e0ad49..6ddc113 100644 --- a/addon/doxyparse/CMakeLists.txt +++ b/addon/doxyparse/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories( add_executable(doxyparse doxyparse.cpp ) +add_sanitizers(doxyparse) if (use_libclang) set(CLANG_LIBS libclang clangTooling ${llvm_libs}) diff --git a/src/classdef.cpp b/src/classdef.cpp index 04e057b..5dee0dc 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -1431,7 +1431,8 @@ void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag) const ol.writeString(" - "); ol.popGeneratorState(); ol.generateDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE,0, + TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.pushGeneratorState(); ol.disable(OutputGenerator::RTF); ol.writeString(" \n"); @@ -1462,7 +1463,8 @@ void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) const // repeat brief description if (!briefDescription().isEmpty() && repeatBrief) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } if (!briefDescription().isEmpty() && repeatBrief && !documentation().isEmpty()) @@ -1475,7 +1477,8 @@ void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) const // write documentation if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // write type constraints writeTypeConstraints(ol,this,m_impl->typeConstraints); @@ -2572,7 +2575,8 @@ void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *h if (!briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startMemberDescription(anchor()); diff --git a/src/commentscan.h b/src/commentscan.h index be92920..a111352 100644 --- a/src/commentscan.h +++ b/src/commentscan.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 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 + * 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. * @@ -60,6 +60,7 @@ class CommentScanner * @param[out] newEntryNeeded Boolean that is TRUE if the comment block parser * finds that a the comment block finishes the entry and a new one * needs to be started. + * @param[in] markdownEnabled Indicates if markdown specific processing should be done. * @returns TRUE if the comment requires further processing. The * parameter \a newEntryNeeded will typically be true in this case and * \a position will indicate the offset inside the \a comment string @@ -76,7 +77,8 @@ class CommentScanner bool isInbody, Protection &prot, int &position, - bool &newEntryNeeded + bool &newEntryNeeded, + bool markdownEnabled ); void initGroupInfo(Entry *entry); void enterFile(const char *fileName,int lineNr); diff --git a/src/commentscan.l b/src/commentscan.l index 309a334..f521528 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -3,8 +3,8 @@ * Copyright (C) 1997-2020 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 + * 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. * @@ -24,7 +24,7 @@ %{ /* - * includes + * includes */ #include <map> @@ -329,11 +329,11 @@ enum GuardType class GuardedSection { public: - GuardedSection(bool enabled,bool parentVisible) + GuardedSection(bool enabled,bool parentVisible) : m_enabled(enabled),m_parentVisible(parentVisible) {} bool isEnabled() const { return m_enabled; } bool parentVisible() const { return m_parentVisible; } - + private: bool m_enabled; bool m_parentVisible; @@ -341,7 +341,7 @@ class GuardedSection /* ----------------------------------------------------------------- * - * statics + * statics */ struct commentscanYY_state @@ -398,6 +398,7 @@ struct commentscanYY_state bool inInternalDocs = FALSE; int prevPosition = 0; DocGroup docGroup; + bool markdownSupport = TRUE; }; //----------------------------------------------------------------------------- @@ -428,20 +429,20 @@ static void addCite(yyscan_t yyscanner); //----------------------------------------------------------------------------- -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} /* start command character */ -CMD ("\\"|"@") -XREFCMD {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem") +CMD ("\\"|"@") +XREFCMD {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem") PRE [pP][rR][eE] -TABLE [tT][aA][bB][lL][eE] -P [pP] +TABLE [tT][aA][bB][lL][eE] +P [pP] UL [uU][lL] -OL [oO][lL] -DL [dD][lL] +OL [oO][lL] +DL [dD][lL] IMG [iI][mM][gG] HR [hH][rR] PARA [pP][aA][rR][aA] @@ -452,13 +453,13 @@ DIV [dD][iI][vV] DETAILEDHTML {CENTER}|{DIV}|{PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA} DETAILEDHTMLOPT {CODE} BN [ \t\n\r] -BL [ \t\r]*"\n" +BL [ \t\r]*"\n" B [ \t] BS ^(({B}*"//")?)(({B}*"*"+)?){B}* ATTR ({B}+[^>\n]*)? DOCNL "\n"|"\\_linebr" LC "\\"{B}*"\n" -NW [^a-z_A-Z0-9] +NW [^a-z_A-Z0-9] FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+@&#] FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+@&#] FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"") @@ -470,7 +471,7 @@ CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{C SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID}) TMPLSPEC "<"{BN}*[^>]+{BN}*">" -MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ +MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ RCSTAG "$"{ID}":"[^\n$]+"$" %option noyywrap @@ -489,34 +490,34 @@ RCSTAG "$"{ID}":"[^\n$]+"$" %x XRefItemParam3 %x FileDocArg1 %x ParamArg1 -%x EnumDocArg1 -%x NameSpaceDocArg1 -%x PackageDocArg1 -%x GroupDocArg1 -%x GroupDocArg2 -%x SectionLabel -%x SectionTitle -%x SubpageLabel -%x SubpageTitle -%x FormatBlock -%x LineParam -%x GuardParam -%x GuardParamEnd -%x SkipGuardedSection -%x SkipInternal +%x EnumDocArg1 +%x NameSpaceDocArg1 +%x PackageDocArg1 +%x GroupDocArg1 +%x GroupDocArg2 +%x SectionLabel +%x SectionTitle +%x SubpageLabel +%x SubpageTitle +%x FormatBlock +%x LineParam +%x GuardParam +%x GuardParamEnd +%x SkipGuardedSection +%x SkipInternal %x NameParam -%x InGroupParam -%x FnParam -%x OverloadParam -%x InheritParam -%x ExtendsParam +%x InGroupParam +%x FnParam +%x OverloadParam +%x InheritParam +%x ExtendsParam %x ReadFormulaShort -%x ReadFormulaLong -%x AnchorLabel +%x ReadFormulaLong +%x AnchorLabel %x HtmlComment %x SkipLang -%x CiteLabel -%x CopyDoc +%x CiteLabel +%x CopyDoc %x GuardExpr %x CdataSection %x Noop @@ -540,52 +541,52 @@ RCSTAG "$"{ID}":"[^\n$]+"$" * XML commands, <summary></summary><remarks></remarks> */ -<Comment>{CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command - addOutput(yyscanner,yytext); - } -<Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command - addOutput(yyscanner,yytext); - } -<Comment>{MAILADDR} { // mail address - addOutput(yyscanner,yytext); - } -<Comment>"\""[^"\n]*"\"" { // quoted text +<Comment>{CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command + addOutput(yyscanner,yytext); + } +<Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command + addOutput(yyscanner,yytext); + } +<Comment>{MAILADDR} { // mail address + addOutput(yyscanner,yytext); + } +<Comment>"\""[^"\n]*"\"" { // quoted text addOutput(yyscanner,yytext); - } -<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!) - addOutput(yyscanner,yytext); - } -<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description - setOutput(yyscanner,OutputDoc); - // continue with the same input + } +<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!) + addOutput(yyscanner,yytext); + } +<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description + setOutput(yyscanner,OutputDoc); + // continue with the same input REJECT; - } -<Comment>"<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML command that ends a brief description - if (yyextra->current->lang==SrcLangExt_CSharp) + } +<Comment>"<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML command that ends a brief description + if (yyextra->current->lang==SrcLangExt_CSharp) { setOutput(yyscanner,OutputDoc); } - // continue with the same input + // continue with the same input REJECT; - } -<Comment>"<summary>" { // start of a .NET XML style brief description - setOutput(yyscanner,OutputBrief); + } +<Comment>"<summary>" { // start of a .NET XML style brief description + setOutput(yyscanner,OutputBrief); addOutput(yyscanner,yytext); - } -<Comment>"<remarks>" { // start of a .NET XML style detailed description - setOutput(yyscanner,OutputDoc); + } +<Comment>"<remarks>" { // start of a .NET XML style detailed description + setOutput(yyscanner,OutputDoc); addOutput(yyscanner,yytext); - } -<Comment>"</summary>" { // start of a .NET XML style detailed description - setOutput(yyscanner,OutputBrief); + } +<Comment>"</summary>" { // start of a .NET XML style detailed description + setOutput(yyscanner,OutputBrief); addOutput(yyscanner,yytext); - setOutput(yyscanner,OutputDoc); - } -<Comment>"</remarks>" { // end of a brief or detailed description - - setOutput(yyscanner,OutputDoc); + setOutput(yyscanner,OutputDoc); + } +<Comment>"</remarks>" { // end of a brief or detailed description + + setOutput(yyscanner,OutputDoc); addOutput(yyscanner,yytext); - } + } <Comment>"<"{CAPTION}{ATTR}">" { QCString tag=yytext; int s=tag.find("id="); @@ -616,22 +617,22 @@ RCSTAG "$"{ID}":"[^\n$]+"$" setOutput(yyscanner,OutputDoc); REJECT; } -<Comment>"<!--" { +<Comment>"<!--" { BEGIN(HtmlComment); } <Comment>"<!\[CDATA\[" { BEGIN(CdataSection); } -<Comment>{B}*{CMD}"endinternal"{B}* { - addOutput(yyscanner," \\endinternal "); +<Comment>{B}*{CMD}"endinternal"{B}* { + addOutput(yyscanner," \\endinternal "); if (!yyextra->inInternalDocs) - warn(yyextra->fileName,yyextra->lineNr, + warn(yyextra->fileName,yyextra->lineNr, "found \\endinternal without matching \\internal" ); yyextra->inInternalDocs = FALSE; - } + } <Comment>{B}*{CMD}[a-z_A-Z]+"{"[a-zA-Z_,:0-9\. ]*"}"{B}* | -<Comment>{B}*{CMD}[a-z_A-Z]+{B}* { // potentially interesting command +<Comment>{B}*{CMD}[a-z_A-Z]+{B}* { // potentially interesting command // the {B}* in the front was added for bug620924 QCString fullMatch = QCString(yytext); int idx = fullMatch.find('{'); @@ -650,84 +651,84 @@ RCSTAG "$"{ID}":"[^\n$]+"$" QCString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace(); optList = QCStringList::split(',',optStr); } - auto it = docCmdMap.find(cmdName.data()); - if (it!=docCmdMap.end()) // special action is required - { + auto it = docCmdMap.find(cmdName.data()); + if (it!=docCmdMap.end()) // special action is required + { int i=0; while (yytext[i]==' ' || yytext[i]=='\t') i++; - yyextra->spaceBeforeCmd = QCString(yytext).left(i); - if (it->second.endsBrief && !(yyextra->inContext==OutputXRef && cmdName=="parblock")) - { - yyextra->briefEndsAtDot=FALSE; - // this command forces the end of brief description - setOutput(yyscanner,OutputDoc); - } + yyextra->spaceBeforeCmd = QCString(yytext).left(i); + if (it->second.endsBrief && !(yyextra->inContext==OutputXRef && cmdName=="parblock")) + { + yyextra->briefEndsAtDot=FALSE; + // this command forces the end of brief description + setOutput(yyscanner,OutputDoc); + } //if (i>0) addOutput(yyscanner,QCString(yytext).left(i)); // removed for bug 689341 - if (it->second.handler && it->second.handler(yyscanner, cmdName, optList)) - { - // implicit split of the comment block into two - // entries. Restart the next block at the start - // of this command. - yyextra->parseMore=TRUE; - - // yuk, this is probably not very portable across lex implementations, - // but we need to know the position in the input buffer where this - // rule matched. - // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE + if (it->second.handler && it->second.handler(yyscanner, cmdName, optList)) + { + // implicit split of the comment block into two + // entries. Restart the next block at the start + // of this command. + yyextra->parseMore=TRUE; + + // yuk, this is probably not very portable across lex implementations, + // but we need to know the position in the input buffer where this + // rule matched. + // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33)) - yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf); #else - yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf); #endif - yyterminate(); - } - else if (it->second.handler==0) - { - // command without handler, to be processed - // later by parsedoc.cpp - addOutput(yyscanner,yytext); - } - } - else // command not relevant - { - addOutput(yyscanner,yytext); - } - } -<Comment>{B}*({CMD}{CMD})"f"[$\[{] { // escaped formula command - addOutput(yyscanner,yytext); - } -<Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command + yyterminate(); + } + else if (it->second.handler==0) + { + // command without handler, to be processed + // later by parsedoc.cpp + addOutput(yyscanner,yytext); + } + } + else // command not relevant + { + addOutput(yyscanner,yytext); + } + } +<Comment>{B}*({CMD}{CMD})"f"[$\[{] { // escaped formula command + addOutput(yyscanner,yytext); + } +<Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command QCString langId = QCString(yytext).stripWhiteSpace().data()+2; - if (!langId.isEmpty() && - qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)!=0) - { // enable language specific section - BEGIN(SkipLang); - } - } + if (!langId.isEmpty() && + qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)!=0) + { // enable language specific section + BEGIN(SkipLang); + } + } <Comment>{B}*{CMD}"f{"[^}\n]+"}"("{"?) { // start of a formula with custom environment - setOutput(yyscanner,OutputDoc); - yyextra->formulaText="\\begin"; - yyextra->formulaEnv=QCString(yytext).stripWhiteSpace().data()+2; - if (yyextra->formulaEnv.at(yyextra->formulaEnv.length()-1)=='{') - { - // remove trailing open brace - yyextra->formulaEnv=yyextra->formulaEnv.left(yyextra->formulaEnv.length()-1); - } - yyextra->formulaText+=yyextra->formulaEnv; - yyextra->formulaNewLines=0; - BEGIN(ReadFormulaLong); - } -<Comment>{B}*{CMD}"f$" { // start of a inline formula - yyextra->formulaText="$"; - yyextra->formulaNewLines=0; - BEGIN(ReadFormulaShort); - } -<Comment>{B}*{CMD}"f[" { // start of a block formula - setOutput(yyscanner,OutputDoc); - yyextra->formulaText="\\["; - yyextra->formulaNewLines=0; - BEGIN(ReadFormulaLong); - } + setOutput(yyscanner,OutputDoc); + yyextra->formulaText="\\begin"; + yyextra->formulaEnv=QCString(yytext).stripWhiteSpace().data()+2; + if (yyextra->formulaEnv.at(yyextra->formulaEnv.length()-1)=='{') + { + // remove trailing open brace + yyextra->formulaEnv=yyextra->formulaEnv.left(yyextra->formulaEnv.length()-1); + } + yyextra->formulaText+=yyextra->formulaEnv; + yyextra->formulaNewLines=0; + BEGIN(ReadFormulaLong); + } +<Comment>{B}*{CMD}"f$" { // start of a inline formula + yyextra->formulaText="$"; + yyextra->formulaNewLines=0; + BEGIN(ReadFormulaShort); + } +<Comment>{B}*{CMD}"f[" { // start of a block formula + setOutput(yyscanner,OutputDoc); + yyextra->formulaText="\\["; + yyextra->formulaNewLines=0; + BEGIN(ReadFormulaLong); + } <Comment>{B}*{CMD}"{" { // begin of a group //yyextra->langParser->handleGroupStartCommand(yyextra->memberGroupHeader); yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr); @@ -735,51 +736,51 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <Comment>{B}*{CMD}"}" { // end of a group //yyextra->langParser->handleGroupEndCommand(); yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,TRUE); - yyextra->docGroup.clearHeader(); - yyextra->parseMore=TRUE; + yyextra->docGroup.clearHeader(); + yyextra->parseMore=TRUE; yyextra->needNewEntry = TRUE; #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33)) - yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + (int)strlen(yytext); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + (int)strlen(yytext); #else - yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf) + (int)strlen(yytext); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf) + (int)strlen(yytext); #endif - yyterminate(); - } -<Comment>{B}*{CMD}[$@\\&~<>#%] { // escaped character - addOutput(yyscanner,yytext); - } -<Comment>[a-z_A-Z]+ { // normal word - addOutput(yyscanner,yytext); - } + yyterminate(); + } +<Comment>{B}*{CMD}[$@\\&~<>#%] { // escaped character + addOutput(yyscanner,yytext); + } +<Comment>[a-z_A-Z]+ { // normal word + addOutput(yyscanner,yytext); + } <Comment>^{B}*"."{B}*/\n { // explicit end autolist: e.g " ." - addOutput(yyscanner,yytext); - } + addOutput(yyscanner,yytext); + } <Comment>^{B}*[1-9][0-9]*"."{B}+ | -<Comment>^{B}*[*+]{B}+ { // start of autolist - if (!Doxygen::markdownSupport) +<Comment>^{B}*[*+]{B}+ { // start of autolist + if (!yyextra->markdownSupport) { REJECT; } else { - if (yyextra->inContext!=OutputXRef) + if (yyextra->inContext!=OutputXRef) { yyextra->briefEndsAtDot=FALSE; setOutput(yyscanner,OutputDoc); } - addOutput(yyscanner,yytext); - } - } -<Comment>^{B}*"-"{B}+ { // start of autolist - if (yyextra->inContext!=OutputXRef) - { - yyextra->briefEndsAtDot=FALSE; - setOutput(yyscanner,OutputDoc); - } - addOutput(yyscanner,yytext); - } + addOutput(yyscanner,yytext); + } + } +<Comment>^{B}*"-"{B}+ { // start of autolist + if (yyextra->inContext!=OutputXRef) + { + yyextra->briefEndsAtDot=FALSE; + setOutput(yyscanner,OutputDoc); + } + addOutput(yyscanner,yytext); + } <Comment>^{B}*([\-:|]{B}*)*("--"|"---")({B}*[\-:|])*{B}*/\n { // horizontal line (dashed) - addOutput(yyscanner,yytext); + addOutput(yyscanner,yytext); } <Comment>{CMD}"---" { // escaped mdash addOutput(yyscanner,yytext); @@ -788,10 +789,10 @@ RCSTAG "$"{ID}":"[^\n$]+"$" addOutput(yyscanner,yytext); } <Comment>"---" { // mdash - addOutput(yyscanner,yyextra->insidePre || Doxygen::markdownSupport ? yytext : "—"); + addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "—"); } <Comment>"--" { // ndash - addOutput(yyscanner,yyextra->insidePre || Doxygen::markdownSupport ? yytext : "–"); + addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "–"); } <Comment>"-#"{B}+ { // numbered item if (yyextra->inContext!=OutputXRef) @@ -801,27 +802,27 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } addOutput(yyscanner,yytext); } -<Comment>("."+)[a-z_A-Z0-9\)] { // . at start or in the middle of a word, or ellipsis - addOutput(yyscanner,yytext); - } -<Comment>".\\"[ \t] { // . with escaped space. - addOutput(yyscanner,yytext[0]); - addOutput(yyscanner,yytext[2]); - } -<Comment>".," { // . with comma such as "e.g.," - addOutput(yyscanner,yytext); - } -<Comment>"...\\"[ \t] { // ellipsis with escaped space. - addOutput(yyscanner,"... "); - } -<Comment>".."[\.]?/[^ \t\n] { // internal ellipsis - addOutput(yyscanner,yytext); - } -<Comment>(\n|\\_linebr)({B}*(\n|\\_linebr))+ { // at least one blank line (or blank line command) - if (yyextra->inContext==OutputXRef) - { - // see bug 613024, we need to put the newlines after ending the XRef section. - if (!yyextra->insideParBlock) setOutput(yyscanner,OutputDoc); +<Comment>("."+)[a-z_A-Z0-9\)] { // . at start or in the middle of a word, or ellipsis + addOutput(yyscanner,yytext); + } +<Comment>".\\"[ \t] { // . with escaped space. + addOutput(yyscanner,yytext[0]); + addOutput(yyscanner,yytext[2]); + } +<Comment>".," { // . with comma such as "e.g.," + addOutput(yyscanner,yytext); + } +<Comment>"...\\"[ \t] { // ellipsis with escaped space. + addOutput(yyscanner,"... "); + } +<Comment>".."[\.]?/[^ \t\n] { // internal ellipsis + addOutput(yyscanner,yytext); + } +<Comment>(\n|\\_linebr)({B}*(\n|\\_linebr))+ { // at least one blank line (or blank line command) + if (yyextra->inContext==OutputXRef) + { + // see bug 613024, we need to put the newlines after ending the XRef section. + if (!yyextra->insideParBlock) setOutput(yyscanner,OutputDoc); yy_size_t i; for (i=0;i<(yy_size_t)yyleng;) { @@ -829,9 +830,9 @@ RCSTAG "$"{ID}":"[^\n$]+"$" else if (strcmp(yytext+i,"\\_linebr")==0) addOutput(yyscanner,'\n'),i+=8; else i++; } - } - else if (yyextra->inContext!=OutputBrief) - { + } + else if (yyextra->inContext!=OutputBrief) + { yy_size_t i; for (i=0;i<(yy_size_t)yyleng;) { @@ -839,47 +840,47 @@ RCSTAG "$"{ID}":"[^\n$]+"$" else if (strcmp(yytext+i,"\\_linebr")==0) addOutput(yyscanner,'\n'),i+=8; else i++; } - setOutput(yyscanner,OutputDoc); - } - else // yyextra->inContext==OutputBrief - { // only go to the detailed description if we have - // found some brief description and not just whitespace - endBrief(yyscanner,FALSE); - } - lineCount(yyscanner); - } -<Comment>"." { // potential end of a JavaDoc style comment - addOutput(yyscanner,*yytext); - if (yyextra->briefEndsAtDot) - { - setOutput(yyscanner,OutputDoc); - yyextra->briefEndsAtDot=FALSE; - } - } -<Comment>\n { // newline - addOutput(yyscanner,*yytext); - yyextra->lineNr++; - } -<Comment>. { // catch-all for anything else - addOutput(yyscanner,*yytext); - } + setOutput(yyscanner,OutputDoc); + } + else // yyextra->inContext==OutputBrief + { // only go to the detailed description if we have + // found some brief description and not just whitespace + endBrief(yyscanner,FALSE); + } + lineCount(yyscanner); + } +<Comment>"." { // potential end of a JavaDoc style comment + addOutput(yyscanner,*yytext); + if (yyextra->briefEndsAtDot) + { + setOutput(yyscanner,OutputDoc); + yyextra->briefEndsAtDot=FALSE; + } + } +<Comment>\n { // newline + addOutput(yyscanner,*yytext); + yyextra->lineNr++; + } +<Comment>. { // catch-all for anything else + addOutput(yyscanner,*yytext); + } /* -------------- Rules for handling HTML comments ----------- */ -<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); } -<HtmlComment>{DOCNL} { - if (*yytext=='\n') yyextra->lineNr++; - } -<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters - } -<HtmlComment>. { // ignore every else - } +<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); } +<HtmlComment>{DOCNL} { + if (*yytext=='\n') yyextra->lineNr++; + } +<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters + } +<HtmlComment>. { // ignore every else + } <CdataSection>"\]\]>" { BEGIN( Comment ); } -<CdataSection>{DOCNL} { +<CdataSection>{DOCNL} { addOutput(yyscanner,'\n'); if (*yytext=='\n') yyextra->lineNr++; } @@ -890,262 +891,262 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <CdataSection>[^\\\n\]<>&]+ { addOutput(yyscanner,yytext); } -<CdataSection>. { +<CdataSection>. { addOutput(yyscanner,*yytext); } /* -------------- Rules for handling formulas ---------------- */ - -<ReadFormulaShort>{CMD}"f$" { // end of inline formula - yyextra->formulaText+="$"; - addOutput(yyscanner," "+addFormula(yyscanner)); - BEGIN(Comment); - } -<ReadFormulaLong>{CMD}"f]" { // end of block formula - yyextra->formulaText+="\\]"; - addOutput(yyscanner," "+addFormula(yyscanner)); - BEGIN(Comment); - } -<ReadFormulaLong>{CMD}"f}" { // end of custom env formula - yyextra->formulaText+="\\end"; - yyextra->formulaText+=yyextra->formulaEnv; - addOutput(yyscanner," "+addFormula(yyscanner)); - BEGIN(Comment); - } + +<ReadFormulaShort>{CMD}"f$" { // end of inline formula + yyextra->formulaText+="$"; + addOutput(yyscanner," "+addFormula(yyscanner)); + BEGIN(Comment); + } +<ReadFormulaLong>{CMD}"f]" { // end of block formula + yyextra->formulaText+="\\]"; + addOutput(yyscanner," "+addFormula(yyscanner)); + BEGIN(Comment); + } +<ReadFormulaLong>{CMD}"f}" { // end of custom env formula + yyextra->formulaText+="\\end"; + yyextra->formulaText+=yyextra->formulaEnv; + addOutput(yyscanner," "+addFormula(yyscanner)); + BEGIN(Comment); + } <ReadFormulaLong,ReadFormulaShort>[^\\@\n]+ { // any non-special character - yyextra->formulaText+=yytext; - } -<ReadFormulaLong,ReadFormulaShort>\n { // new line + yyextra->formulaText+=yytext; + } +<ReadFormulaLong,ReadFormulaShort>\n { // new line yyextra->formulaNewLines++; - yyextra->formulaText+=*yytext; - yyextra->lineNr++; - } + yyextra->formulaText+=*yytext; + yyextra->lineNr++; + } <ReadFormulaLong,ReadFormulaShort>. { // any other character - yyextra->formulaText+=*yytext; - } + yyextra->formulaText+=*yytext; + } /* ------------ handle argument of enum command --------------- */ -<EnumDocArg1>{SCOPEID} { // handle argument - yyextra->current->name = yytext; - BEGIN( Comment ); - } -<EnumDocArg1>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); +<EnumDocArg1>{SCOPEID} { // handle argument + yyextra->current->name = yytext; + BEGIN( Comment ); + } +<EnumDocArg1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<EnumDocArg1>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, +<EnumDocArg1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, "missing argument after \\enum." ); - addOutput(yyscanner,'\n'); - if (*yytext=='\n') yyextra->lineNr++; - BEGIN( Comment ); - } -<EnumDocArg1>. { // ignore other stuff - } + addOutput(yyscanner,'\n'); + if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<EnumDocArg1>. { // ignore other stuff + } /* ------------ handle argument of namespace command --------------- */ -<NameSpaceDocArg1>{SCOPENAME} { // handle argument - yyextra->current->name = substitute(yytext,".","::"); - BEGIN( Comment ); - } -<NameSpaceDocArg1>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); +<NameSpaceDocArg1>{SCOPENAME} { // handle argument + yyextra->current->name = substitute(yytext,".","::"); + BEGIN( Comment ); + } +<NameSpaceDocArg1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<NameSpaceDocArg1>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, +<NameSpaceDocArg1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\namespace." + "\\namespace." ); - addOutput(yyscanner,'\n'); - if (*yytext=='\n') yyextra->lineNr++; - BEGIN( Comment ); - } -<NameSpaceDocArg1>. { // ignore other stuff - } + addOutput(yyscanner,'\n'); + if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<NameSpaceDocArg1>. { // ignore other stuff + } /* ------------ handle argument of package command --------------- */ -<PackageDocArg1>{ID}("."{ID})* { // handle argument - yyextra->current->name = yytext; - BEGIN( Comment ); - } -<PackageDocArg1>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); +<PackageDocArg1>{ID}("."{ID})* { // handle argument + yyextra->current->name = yytext; + BEGIN( Comment ); + } +<PackageDocArg1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<PackageDocArg1>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, +<PackageDocArg1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\package." + "\\package." ); - addOutput(yyscanner,'\n'); - if (*yytext=='\n') yyextra->lineNr++; - BEGIN( Comment ); - } -<PackageDocArg1>. { // ignore other stuff - } + addOutput(yyscanner,'\n'); + if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<PackageDocArg1>. { // ignore other stuff + } /* ------ handle argument of class/struct/union command --------------- */ -<ClassDocArg1>{SCOPENAME}{TMPLSPEC} { - yyextra->current->name = substitute(removeRedundantWhiteSpace(yytext),".","::"); - BEGIN( ClassDocArg2 ); - } -<ClassDocArg1>{SCOPENAME} { // first argument - yyextra->current->name = substitute(yytext,".","::"); - if (yyextra->current->section==Entry::PROTOCOLDOC_SEC) - { - yyextra->current->name+="-p"; - } - // prepend outer scope name - BEGIN( ClassDocArg2 ); - } +<ClassDocArg1>{SCOPENAME}{TMPLSPEC} { + yyextra->current->name = substitute(removeRedundantWhiteSpace(yytext),".","::"); + BEGIN( ClassDocArg2 ); + } +<ClassDocArg1>{SCOPENAME} { // first argument + yyextra->current->name = substitute(yytext,".","::"); + if (yyextra->current->section==Entry::PROTOCOLDOC_SEC) + { + yyextra->current->name+="-p"; + } + // prepend outer scope name + BEGIN( ClassDocArg2 ); + } <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" { - yyextra->current->name = substitute(yytext,".","::"); - BEGIN( ClassDocArg2 ); - } + yyextra->current->name = substitute(yytext,".","::"); + BEGIN( ClassDocArg2 ); + } <ClassDocArg1,CategoryDocArg1>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); + yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<ClassDocArg1,CategoryDocArg1>{DOCNL} { - warn(yyextra->fileName,yyextra->lineNr, +<ClassDocArg1,CategoryDocArg1>{DOCNL} { + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\%s.",YY_START==ClassDocArg1?"class":"category" + "\\%s.",YY_START==ClassDocArg1?"class":"category" ); - addOutput(yyscanner,'\n'); - if (*yytext=='\n') yyextra->lineNr++; - BEGIN( Comment ); - } -<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff - } - -<ClassDocArg2>{FILE}|"<>" { // second argument; include file - yyextra->current->includeFile = yytext; - BEGIN( ClassDocArg3 ); - } -<ClassDocArg2>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<ClassDocArg2>{DOCNL} { - addOutput(yyscanner,'\n'); - if (*yytext=='\n') yyextra->lineNr++; - BEGIN( Comment ); - } -<ClassDocArg2>. { // ignore other stuff - } - -<ClassDocArg3>[<"]?{FILE}?[">]? { // third argument; include file name - yyextra->current->includeName = yytext; - BEGIN( Comment ); - } -<ClassDocArg3>{LC} { // line continuation + addOutput(yyscanner,'\n'); + if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff + } + +<ClassDocArg2>{FILE}|"<>" { // second argument; include file + yyextra->current->includeFile = yytext; + BEGIN( ClassDocArg3 ); + } +<ClassDocArg2>{LC} { // line continuation yyextra->lineNr++; - addOutput(yyscanner,'\n'); + addOutput(yyscanner,'\n'); + } +<ClassDocArg2>{DOCNL} { + addOutput(yyscanner,'\n'); + if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); } -<ClassDocArg3>{DOCNL} { - if (*yytext=='\n') yyextra->lineNr++; - BEGIN( Comment ); - } -<ClassDocArg3>. { // ignore other stuff - } +<ClassDocArg2>. { // ignore other stuff + } + +<ClassDocArg3>[<"]?{FILE}?[">]? { // third argument; include file name + yyextra->current->includeName = yytext; + BEGIN( Comment ); + } +<ClassDocArg3>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<ClassDocArg3>{DOCNL} { + if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<ClassDocArg3>. { // ignore other stuff + } /* --------- handle arguments of {def,add,weak}group commands --------- */ -<GroupDocArg1>{LABELID}(".html"?) { // group name - yyextra->current->name = yytext; - //lastDefGroup.groupname = yytext; - //lastDefGroup.pri = yyextra->current->groupingPri(); - // the .html stuff is for Qt compatibility - if (yyextra->current->name.right(5)==".html") - { - yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-5); - } - yyextra->current->type.resize(0); - BEGIN(GroupDocArg2); - } -<GroupDocArg1>"\\"{B}*"\n" { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<GroupDocArg1>{DOCNL} { // missing argument! - warn(yyextra->fileName,yyextra->lineNr, +<GroupDocArg1>{LABELID}(".html"?) { // group name + yyextra->current->name = yytext; + //lastDefGroup.groupname = yytext; + //lastDefGroup.pri = yyextra->current->groupingPri(); + // the .html stuff is for Qt compatibility + if (yyextra->current->name.right(5)==".html") + { + yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-5); + } + yyextra->current->type.resize(0); + BEGIN(GroupDocArg2); + } +<GroupDocArg1>"\\"{B}*"\n" { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<GroupDocArg1>{DOCNL} { // missing argument! + warn(yyextra->fileName,yyextra->lineNr, "missing group name after %s", - yyextra->current->groupDocCmd() + yyextra->current->groupDocCmd() ); - addOutput(yyscanner,'\n'); - if (*yytext=='\n') yyextra->lineNr++; - BEGIN( Comment ); - } -<GroupDocArg1>. { // ignore other stuff - } -<GroupDocArg2>"\\"{B}*"\n" { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<GroupDocArg2>[^\n\\]+ { // title (stored in type) - yyextra->current->type += yytext; - yyextra->current->type = yyextra->current->type.stripWhiteSpace(); - } -<GroupDocArg2>{DOCNL} { + addOutput(yyscanner,'\n'); + if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<GroupDocArg1>. { // ignore other stuff + } +<GroupDocArg2>"\\"{B}*"\n" { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<GroupDocArg2>[^\n\\]+ { // title (stored in type) + yyextra->current->type += yytext; + yyextra->current->type = yyextra->current->type.stripWhiteSpace(); + } +<GroupDocArg2>{DOCNL} { if ( yyextra->current->groupDocType==Entry::GROUPDOC_NORMAL && - yyextra->current->type.isEmpty() - ) // defgroup requires second argument - { - warn(yyextra->fileName,yyextra->lineNr, + yyextra->current->type.isEmpty() + ) // defgroup requires second argument + { + warn(yyextra->fileName,yyextra->lineNr, "missing title after " - "\\defgroup %s", yyextra->current->name.data() + "\\defgroup %s", yyextra->current->name.data() ); - } - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } + } + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } <GroupDocArg2>. { // title (stored in type) - yyextra->current->type += yytext; - yyextra->current->type = yyextra->current->type.stripWhiteSpace(); + yyextra->current->type += yytext; + yyextra->current->type = yyextra->current->type.stripWhiteSpace(); } /* --------- handle arguments of page/mainpage command ------------------- */ -<PageDocArg1>{FILE} { // first argument; page name - yyextra->current->name = stripQuotes(yytext); - yyextra->current->args = ""; - BEGIN( PageDocArg2 ); - } -<PageDocArg1>{LC} { yyextra->lineNr++; - addOutput(yyscanner,'\n'); +<PageDocArg1>{FILE} { // first argument; page name + yyextra->current->name = stripQuotes(yytext); + yyextra->current->args = ""; + BEGIN( PageDocArg2 ); + } +<PageDocArg1>{LC} { yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<PageDocArg1>{DOCNL} { - warn(yyextra->fileName,yyextra->lineNr, +<PageDocArg1>{DOCNL} { + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\page." + "\\page." ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<PageDocArg1>. { // ignore other stuff - } -<PageDocArg2>{DOCNL} { // second argument; page title - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<PageDocArg2>{CMD}[<>] { - // bug 748927 - QCString tmp = yytext; - tmp = substitute(substitute(tmp,"@<","<"),"@>",">"); - tmp = substitute(substitute(tmp,"\\<","<"),"\\>",">"); - yyextra->current->args += tmp; - } -<PageDocArg2>. { - yyextra->current->args += yytext; + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<PageDocArg1>. { // ignore other stuff + } +<PageDocArg2>{DOCNL} { // second argument; page title + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<PageDocArg2>{CMD}[<>] { + // bug 748927 + QCString tmp = yytext; + tmp = substitute(substitute(tmp,"@<","<"),"@>",">"); + tmp = substitute(substitute(tmp,"\\<","<"),"\\>",">"); + yyextra->current->args += tmp; + } +<PageDocArg2>. { + yyextra->current->args += yytext; } /* --------- handle arguments of the param command ------------ */ <ParamArg1>{ID}/{B}*"," { @@ -1165,284 +1166,284 @@ RCSTAG "$"{ID}":"[^\n$]+"$" /* --------- handle arguments of the file/dir/example command ------------ */ -<FileDocArg1>{DOCNL} { // no file name specified - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<FileDocArg1>{FILE} { // first argument; name - yyextra->current->name = stripQuotes(yytext); - BEGIN( Comment ); - } -<FileDocArg1>{LC} { yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<FileDocArg1>. { // ignore other stuff - } +<FileDocArg1>{DOCNL} { // no file name specified + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<FileDocArg1>{FILE} { // first argument; name + yyextra->current->name = stripQuotes(yytext); + BEGIN( Comment ); + } +<FileDocArg1>{LC} { yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<FileDocArg1>. { // ignore other stuff + } /* --------- handle arguments of the xrefitem command ------------ */ -<XRefItemParam1>{LABELID} { // first argument - yyextra->newXRefItemKey=yytext; +<XRefItemParam1>{LABELID} { // first argument + yyextra->newXRefItemKey=yytext; setOutput(yyscanner,OutputXRef); - BEGIN(XRefItemParam2); - } -<XRefItemParam1>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<XRefItemParam1>{DOCNL} { // missing arguments - warn(yyextra->fileName,yyextra->lineNr, - "Missing first argument of \\xrefitem" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - yyextra->inContext = OutputDoc; - BEGIN( Comment ); - } -<XRefItemParam1>. { // ignore other stuff - } - -<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument - yyextra->xrefItemTitle = stripQuotes(yytext); - BEGIN(XRefItemParam3); - } -<XRefItemParam2>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<XRefItemParam2>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "Missing second argument of \\xrefitem" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - yyextra->inContext = OutputDoc; - BEGIN( Comment ); - } -<XRefItemParam2>. { // ignore other stuff - } - -<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument - yyextra->xrefListTitle = stripQuotes(yytext); + BEGIN(XRefItemParam2); + } +<XRefItemParam1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<XRefItemParam1>{DOCNL} { // missing arguments + warn(yyextra->fileName,yyextra->lineNr, + "Missing first argument of \\xrefitem" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam1>. { // ignore other stuff + } + +<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument + yyextra->xrefItemTitle = stripQuotes(yytext); + BEGIN(XRefItemParam3); + } +<XRefItemParam2>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<XRefItemParam2>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "Missing second argument of \\xrefitem" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam2>. { // ignore other stuff + } + +<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument + yyextra->xrefListTitle = stripQuotes(yytext); yyextra->xrefKind = XRef_Item; - BEGIN( Comment ); - } -<XRefItemParam2,XRefItemParam3>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<XRefItemParam3>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "Missing third argument of \\xrefitem" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - yyextra->inContext = OutputDoc; - BEGIN( Comment ); - } -<XRefItemParam3>. { // ignore other stuff - } + BEGIN( Comment ); + } +<XRefItemParam2,XRefItemParam3>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<XRefItemParam3>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "Missing third argument of \\xrefitem" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam3>. { // ignore other stuff + } /* ----- handle arguments of the relates(also)/memberof command ------- */ -<RelatesParam1>({ID}("::"|"."))*{ID} { // argument - yyextra->current->relates = yytext; - //if (yyextra->current->mGrpId!=DOX_NOGROUP) +<RelatesParam1>({ID}("::"|"."))*{ID} { // argument + yyextra->current->relates = yytext; + //if (yyextra->current->mGrpId!=DOX_NOGROUP) //{ // memberGroupRelates = yytext; //} - BEGIN( Comment ); - } -<RelatesParam1>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<RelatesParam1>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "Missing argument of \\relates or \\memberof command" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<RelatesParam1>. { // ignore other stuff - } + BEGIN( Comment ); + } +<RelatesParam1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<RelatesParam1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "Missing argument of \\relates or \\memberof command" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<RelatesParam1>. { // ignore other stuff + } /* ----- handle arguments of the relates(also)/addindex commands ----- */ -<LineParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<LineParam>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<LineParam>. { // ignore other stuff - addOutput(yyscanner,*yytext); - } +<LineParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<LineParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<LineParam>. { // ignore other stuff + addOutput(yyscanner,*yytext); + } /* ----- handle arguments of the section/subsection/.. commands ------- */ -<SectionLabel>{LABELID} { // first argument - yyextra->sectionLabel=yytext; +<SectionLabel>{LABELID} { // first argument + yyextra->sectionLabel=yytext; addOutput(yyscanner,yytext); - yyextra->sectionTitle.resize(0); - BEGIN(SectionTitle); - } -<SectionLabel>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "\\section command has no label" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<SectionLabel>. { // invalid character for section label - warn(yyextra->fileName,yyextra->lineNr, - "Invalid or missing section label" - ); - BEGIN(Comment); - } + yyextra->sectionTitle.resize(0); + BEGIN(SectionTitle); + } +<SectionLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\section command has no label" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<SectionLabel>. { // invalid character for section label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing section label" + ); + BEGIN(Comment); + } <SectionTitle>[^\n@\\*]*/"\n" { // end of section title - addSection(yyscanner); + addSection(yyscanner); addOutput(yyscanner,yytext); - BEGIN( Comment ); - } + BEGIN( Comment ); + } <SectionTitle>[^\n@\\]*/"\\_linebr" { // end of section title - addSection(yyscanner); + addSection(yyscanner); addOutput(yyscanner,yytext); - BEGIN( Comment ); - } -<SectionTitle>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<SectionTitle>[^\n@\\]* { // any character without special meaning - yyextra->sectionTitle+=yytext; - addOutput(yyscanner,yytext); - } -<SectionTitle>({CMD}{CMD}){ID} { // unescape escaped command - yyextra->sectionTitle+=&yytext[1]; - addOutput(yyscanner,yytext); - } -<SectionTitle>{CMD}[$@\\&~<>#%] { // unescape escaped character - yyextra->sectionTitle+=yytext[1]; - addOutput(yyscanner,yytext); - } -<SectionTitle>. { // anything else - yyextra->sectionTitle+=yytext; - addOutput(yyscanner,*yytext); - } + BEGIN( Comment ); + } +<SectionTitle>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<SectionTitle>[^\n@\\]* { // any character without special meaning + yyextra->sectionTitle+=yytext; + addOutput(yyscanner,yytext); + } +<SectionTitle>({CMD}{CMD}){ID} { // unescape escaped command + yyextra->sectionTitle+=&yytext[1]; + addOutput(yyscanner,yytext); + } +<SectionTitle>{CMD}[$@\\&~<>#%] { // unescape escaped character + yyextra->sectionTitle+=yytext[1]; + addOutput(yyscanner,yytext); + } +<SectionTitle>. { // anything else + yyextra->sectionTitle+=yytext; + addOutput(yyscanner,*yytext); + } /* ----- handle arguments of the subpage command ------- */ -<SubpageLabel>{LABELID} { // first argument +<SubpageLabel>{LABELID} { // first argument addOutput(yyscanner,yytext); - // we add subpage labels as a kind of "inheritance" relation to prevent - // needing to add another list to the Entry class. - yyextra->current->extends.push_back(BaseInfo(yytext,Public,Normal)); - BEGIN(SubpageTitle); - } -<SubpageLabel>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "\\subpage command has no label" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<SubpageTitle>{DOCNL} { // no title, end command - addOutput(yyscanner,yytext); - BEGIN( Comment ); - } -<SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command - addOutput(yyscanner,yytext); - BEGIN( Comment ); - } -<SubpageTitle>. { // no title, end of command - unput(*yytext); - BEGIN( Comment ); - } + // we add subpage labels as a kind of "inheritance" relation to prevent + // needing to add another list to the Entry class. + yyextra->current->extends.push_back(BaseInfo(yytext,Public,Normal)); + BEGIN(SubpageTitle); + } +<SubpageLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\subpage command has no label" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<SubpageTitle>{DOCNL} { // no title, end command + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<SubpageTitle>. { // no title, end of command + unput(*yytext); + BEGIN( Comment ); + } /* ----- handle arguments of the anchor command ------- */ -<AnchorLabel>{LABELID} { // found argument +<AnchorLabel>{LABELID} { // found argument addAnchor(yyscanner,yytext); - addOutput(yyscanner,yytext); - BEGIN( Comment ); - } -<AnchorLabel>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "\\anchor command has no label" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<AnchorLabel>. { // invalid character for anchor label - warn(yyextra->fileName,yyextra->lineNr, - "Invalid or missing anchor label" - ); - BEGIN(Comment); - } + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<AnchorLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\anchor command has no label" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<AnchorLabel>. { // invalid character for anchor label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing anchor label" + ); + BEGIN(Comment); + } /* ----- handle arguments of the preformatted block commands ------- */ <FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc"|"endvhdlflow")/{NW} { // possible ends - addOutput(yyscanner,yytext); - if (&yytext[4]==yyextra->blockName) // found end of the block - { - BEGIN(Comment); - } - } + addOutput(yyscanner,yytext); + if (&yytext[4]==yyextra->blockName) // found end of the block + { + BEGIN(Comment); + } + } <FormatBlock>{CMD}"enduml" { - addOutput(yyscanner,yytext); - if (yyextra->blockName=="startuml") // found end of the block - { - BEGIN(Comment); - } - } -<FormatBlock>[^ \@\*\/\\\n]* { // some word - addOutput(yyscanner,yytext); - } -<FormatBlock>{DOCNL} { // new line - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<FormatBlock>"/*" { // start of a C-comment - if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) yyextra->commentCount++; - addOutput(yyscanner,yytext); - } -<FormatBlock>"*/" { // end of a C-comment - addOutput(yyscanner,yytext); - if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) + addOutput(yyscanner,yytext); + if (yyextra->blockName=="startuml") // found end of the block + { + BEGIN(Comment); + } + } +<FormatBlock>[^ \@\*\/\\\n]* { // some word + addOutput(yyscanner,yytext); + } +<FormatBlock>{DOCNL} { // new line + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<FormatBlock>"/*" { // start of a C-comment + if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) yyextra->commentCount++; + addOutput(yyscanner,yytext); + } +<FormatBlock>"*/" { // end of a C-comment + addOutput(yyscanner,yytext); + if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) { yyextra->commentCount--; - if (yyextra->commentCount<0) - { - warn(yyextra->fileName,yyextra->lineNr, - "found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",yyextra->blockName.data(),yyextra->blockName.data()); - } - } - } -<FormatBlock>. { - addOutput(yyscanner,*yytext); - } -<FormatBlock><<EOF>> { + if (yyextra->commentCount<0) + { + warn(yyextra->fileName,yyextra->lineNr, + "found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",yyextra->blockName.data(),yyextra->blockName.data()); + } + } + } +<FormatBlock>. { + addOutput(yyscanner,*yytext); + } +<FormatBlock><<EOF>> { QCString endTag = "end"+yyextra->blockName; if (yyextra->blockName=="startuml") endTag="enduml"; warn(yyextra->fileName,yyextra->lineNr, - "reached end of comment while inside a \\%s block; check for missing \\%s tag!", - yyextra->blockName.data(),endTag.data() - ); - yyterminate(); - } + "reached end of comment while inside a \\%s block; check for missing \\%s tag!", + yyextra->blockName.data(),endTag.data() + ); + yyterminate(); + } /* ----- handle arguments of if/ifnot commands ------- */ @@ -1467,383 +1468,383 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } } <GuardExpr>\n { - warn(yyextra->fileName,yyextra->lineNr, - "invalid expression '%s' for yyextra->guards",yyextra->guardExpr.data()); + warn(yyextra->fileName,yyextra->lineNr, + "invalid expression '%s' for yyextra->guards",yyextra->guardExpr.data()); unput(*yytext); BEGIN(GuardParam); } <GuardParam>{B}*[a-z_A-Z0-9.\-]+ { // parameter of if/ifnot yyextra->guards handleGuard(yyscanner,yytext); - } -<GuardParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyextra->lineNr++; - //next line is commented out due to bug620924 - //addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<GuardParam>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<GuardParam>. { // ignore other stuff - addOutput(yyscanner,*yytext); - } -<GuardParamEnd>{B}*{DOCNL} { - lineCount(yyscanner); - yyextra->spaceBeforeIf.resize(0); - BEGIN(Comment); - } -<GuardParamEnd>{B}* { - if (!yyextra->spaceBeforeIf.isEmpty()) // needed for 665313 in combination with bug620924 - { - addOutput(yyscanner,yyextra->spaceBeforeIf); - } - yyextra->spaceBeforeIf.resize(0); - BEGIN(Comment); - } -<GuardParamEnd>. { - unput(*yytext); - BEGIN(Comment); - } + } +<GuardParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + //next line is commented out due to bug620924 + //addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<GuardParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<GuardParam>. { // ignore other stuff + addOutput(yyscanner,*yytext); + } +<GuardParamEnd>{B}*{DOCNL} { + lineCount(yyscanner); + yyextra->spaceBeforeIf.resize(0); + BEGIN(Comment); + } +<GuardParamEnd>{B}* { + if (!yyextra->spaceBeforeIf.isEmpty()) // needed for 665313 in combination with bug620924 + { + addOutput(yyscanner,yyextra->spaceBeforeIf); + } + yyextra->spaceBeforeIf.resize(0); + BEGIN(Comment); + } +<GuardParamEnd>. { + unput(*yytext); + BEGIN(Comment); + } /* ----- handle skipping of conditional sections ------- */ -<SkipGuardedSection>{CMD}"ifnot"/{NW} { +<SkipGuardedSection>{CMD}"ifnot"/{NW} { yyextra->guardType = Guard_IfNot; - BEGIN( GuardParam ); - } -<SkipGuardedSection>{CMD}"if"/{NW} { + BEGIN( GuardParam ); + } +<SkipGuardedSection>{CMD}"if"/{NW} { yyextra->guardType = Guard_If; - BEGIN( GuardParam ); - } -<SkipGuardedSection>{CMD}"endif"/{NW} { - if (yyextra->guards.empty()) - { - warn(yyextra->fileName,yyextra->lineNr, - "found \\endif without matching start command"); - } - else - { - GuardedSection s = yyextra->guards.top(); + BEGIN( GuardParam ); + } +<SkipGuardedSection>{CMD}"endif"/{NW} { + if (yyextra->guards.empty()) + { + warn(yyextra->fileName,yyextra->lineNr, + "found \\endif without matching start command"); + } + else + { + GuardedSection s = yyextra->guards.top(); yyextra->guards.pop(); bool parentVisible = s.parentVisible(); if (parentVisible) { - yyextra->enabledSectionFound=TRUE; - BEGIN( GuardParamEnd ); + yyextra->enabledSectionFound=TRUE; + BEGIN( GuardParamEnd ); } - } - } -<SkipGuardedSection>{CMD}"else"/{NW} { - if (yyextra->guards.empty()) - { - warn(yyextra->fileName,yyextra->lineNr, - "found \\else without matching start command"); - } - else - { - if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible()) - { - yyextra->guards.pop(); - yyextra->guards.push(GuardedSection(TRUE,TRUE)); - yyextra->enabledSectionFound=TRUE; - BEGIN( GuardParamEnd ); - } - } - } + } + } +<SkipGuardedSection>{CMD}"else"/{NW} { + if (yyextra->guards.empty()) + { + warn(yyextra->fileName,yyextra->lineNr, + "found \\else without matching start command"); + } + else + { + if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible()) + { + yyextra->guards.pop(); + yyextra->guards.push(GuardedSection(TRUE,TRUE)); + yyextra->enabledSectionFound=TRUE; + BEGIN( GuardParamEnd ); + } + } + } <SkipGuardedSection>{CMD}"elseif"/{NW} { - if (yyextra->guards.empty()) - { - warn(yyextra->fileName,yyextra->lineNr, - "found \\elseif without matching start command"); - } - else - { - if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible()) - { + if (yyextra->guards.empty()) + { + warn(yyextra->fileName,yyextra->lineNr, + "found \\elseif without matching start command"); + } + else + { + if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible()) + { yyextra->guardType=Guard_If; - yyextra->guards.pop(); - BEGIN( GuardParam ); - } - } - } -<SkipGuardedSection>{DOCNL} { // skip line - if (*yytext=='\n') yyextra->lineNr++; - //addOutput(yyscanner,'\n'); - } -<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters - } -<SkipGuardedSection>. { // any other character - } + yyextra->guards.pop(); + BEGIN( GuardParam ); + } + } + } +<SkipGuardedSection>{DOCNL} { // skip line + if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + } +<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters + } +<SkipGuardedSection>. { // any other character + } /* ----- handle skipping of internal section ------- */ -<SkipInternal>{DOCNL} { // skip line - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<SkipInternal>[@\\]"if"/[ \t] { +<SkipInternal>{DOCNL} { // skip line + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<SkipInternal>[@\\]"if"/[ \t] { yyextra->condCount++; - } -<SkipInternal>[@\\]"ifnot"/[ \t] { + } +<SkipInternal>[@\\]"ifnot"/[ \t] { yyextra->condCount++; - } -<SkipInternal>[@\\]/"endif" { + } +<SkipInternal>[@\\]/"endif" { yyextra->condCount--; - if (yyextra->condCount<0) // handle conditional section around of \internal, see bug607743 - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"section"[ \t] { - if (yyextra->sectionLevel>0) - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"subsection"[ \t] { - if (yyextra->sectionLevel>1) - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"subsubsection"[ \t] { - if (yyextra->sectionLevel>2) - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"paragraph"[ \t] { - if (yyextra->sectionLevel>3) - { - unput('\\'); - BEGIN(Comment); - } - } + if (yyextra->condCount<0) // handle conditional section around of \internal, see bug607743 + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"section"[ \t] { + if (yyextra->sectionLevel>0) + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"subsection"[ \t] { + if (yyextra->sectionLevel>1) + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"subsubsection"[ \t] { + if (yyextra->sectionLevel>2) + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"paragraph"[ \t] { + if (yyextra->sectionLevel>3) + { + unput('\\'); + BEGIN(Comment); + } + } <SkipInternal>[@\\]"endinternal"[ \t]* { - BEGIN(Comment); - } -<SkipInternal>[^ \\@\n]+ { // skip non-special characters - } -<SkipInternal>. { // any other character - } + BEGIN(Comment); + } +<SkipInternal>[^ \\@\n]+ { // skip non-special characters + } +<SkipInternal>. { // any other character + } /* ----- handle argument of name command ------- */ -<NameParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<NameParam>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - yyextra->docGroup.appendHeader(' '); - } -<NameParam>. { // ignore other stuff - yyextra->docGroup.appendHeader(*yytext); - yyextra->current->name+=*yytext; - } +<NameParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<NameParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->docGroup.appendHeader(' '); + } +<NameParam>. { // ignore other stuff + yyextra->docGroup.appendHeader(*yytext); + yyextra->current->name+=*yytext; + } /* ----- handle argument of noop command ------- */ -<Noop>{DOCNL} { // end of argument - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<Noop>. { // ignore other stuff - } +<Noop>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<Noop>. { // ignore other stuff + } /* ----- handle argument of ingroup command ------- */ -<InGroupParam>{LABELID} { // group id - yyextra->current->groups.push_back( - Grouping(yytext, Grouping::GROUPING_INGROUP) - ); - yyextra->inGroupParamFound=TRUE; - } -<InGroupParam>{DOCNL} { // missing argument - if (!yyextra->inGroupParamFound) - { - warn(yyextra->fileName,yyextra->lineNr, - "Missing group name for \\ingroup command" - ); - } - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<InGroupParam>{LC} { // line continuation - yyextra->lineNr++; - addOutput(yyscanner,'\n'); - } -<InGroupParam>. { // ignore other stuff - addOutput(yyscanner,*yytext); - } +<InGroupParam>{LABELID} { // group id + yyextra->current->groups.push_back( + Grouping(yytext, Grouping::GROUPING_INGROUP) + ); + yyextra->inGroupParamFound=TRUE; + } +<InGroupParam>{DOCNL} { // missing argument + if (!yyextra->inGroupParamFound) + { + warn(yyextra->fileName,yyextra->lineNr, + "Missing group name for \\ingroup command" + ); + } + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<InGroupParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<InGroupParam>. { // ignore other stuff + addOutput(yyscanner,*yytext); + } /* ----- handle argument of fn command ------- */ -<FnParam>{DOCNL} { // end of argument - if (yyextra->braceCount==0) - { - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - yyextra->langParser->parsePrototype(yyextra->functionProto); - BEGIN( Comment ); - } - } -<FnParam>{LC} { // line continuation - yyextra->lineNr++; - yyextra->functionProto+=' '; - } -<FnParam>[^@\\\n()]+ { // non-special characters +<FnParam>{DOCNL} { // end of argument + if (yyextra->braceCount==0) + { + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->langParser->parsePrototype(yyextra->functionProto); + BEGIN( Comment ); + } + } +<FnParam>{LC} { // line continuation + yyextra->lineNr++; + yyextra->functionProto+=' '; + } +<FnParam>[^@\\\n()]+ { // non-special characters yyextra->functionProto+=yytext; - } -<FnParam>"(" { + } +<FnParam>"(" { yyextra->functionProto+=yytext; - yyextra->braceCount++; - } -<FnParam>")" { + yyextra->braceCount++; + } +<FnParam>")" { yyextra->functionProto+=yytext; - yyextra->braceCount--; - } -<FnParam>. { // add other stuff + yyextra->braceCount--; + } +<FnParam>. { // add other stuff yyextra->functionProto+=*yytext; - } + } /* ----- handle argument of overload command ------- */ -<OverloadParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyextra->lineNr++; - if (yyextra->functionProto.stripWhiteSpace().isEmpty()) - { // plain overload command - addOutput(yyscanner,getOverloadDocs()); - addOutput(yyscanner,'\n'); - } - else // overload declaration - { +<OverloadParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + if (yyextra->functionProto.stripWhiteSpace().isEmpty()) + { // plain overload command + addOutput(yyscanner,getOverloadDocs()); + addOutput(yyscanner,'\n'); + } + else // overload declaration + { makeStructuralIndicator(yyscanner,Entry::OVERLOADDOC_SEC); - yyextra->langParser->parsePrototype(yyextra->functionProto); - } - BEGIN( Comment ); - } -<OverloadParam>{LC} { // line continuation - yyextra->lineNr++; - yyextra->functionProto+=' '; - } -<OverloadParam>. { // add other stuff + yyextra->langParser->parsePrototype(yyextra->functionProto); + } + BEGIN( Comment ); + } +<OverloadParam>{LC} { // line continuation + yyextra->lineNr++; + yyextra->functionProto+=' '; + } +<OverloadParam>. { // add other stuff yyextra->functionProto+=*yytext; - } + } /* ----- handle argument of inherit command ------- */ -<InheritParam>({ID}("::"|"."))*{ID} { // found argument - yyextra->current->extends.push_back( - BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) - ); - BEGIN( Comment ); - } -<InheritParam>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "\\inherit command has no argument" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<InheritParam>. { // invalid character for anchor label - warn(yyextra->fileName,yyextra->lineNr, - "Invalid or missing name for \\inherit command" - ); - BEGIN(Comment); - } +<InheritParam>({ID}("::"|"."))*{ID} { // found argument + yyextra->current->extends.push_back( + BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) + ); + BEGIN( Comment ); + } +<InheritParam>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\inherit command has no argument" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<InheritParam>. { // invalid character for anchor label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing name for \\inherit command" + ); + BEGIN(Comment); + } /* ----- handle argument of extends and implements commands ------- */ -<ExtendsParam>({ID}("::"|"."))*{ID} { // found argument - yyextra->current->extends.push_back( - BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) - ); - BEGIN( Comment ); - } -<ExtendsParam>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "\\extends or \\implements command has no argument" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<ExtendsParam>. { // ignore other stuff - } +<ExtendsParam>({ID}("::"|"."))*{ID} { // found argument + yyextra->current->extends.push_back( + BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) + ); + BEGIN( Comment ); + } +<ExtendsParam>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\extends or \\implements command has no argument" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<ExtendsParam>. { // ignore other stuff + } /* ----- handle language specific sections ------- */ <SkipLang>[\\@]"~"[a-zA-Z-]* { /* language switch */ QCString langId = &yytext[2]; - if (langId.isEmpty() || - qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)==0) - { // enable language specific section - BEGIN(Comment); - } + if (langId.isEmpty() || + qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)==0) + { // enable language specific section + BEGIN(Comment); + } } -<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */ +<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */ } -<SkipLang>{DOCNL} { /* new line in verbatim block */ - if (*yytext=='\n') yyextra->lineNr++; +<SkipLang>{DOCNL} { /* new line in verbatim block */ + if (*yytext=='\n') yyextra->lineNr++; } -<SkipLang>. { /* any other character */ +<SkipLang>. { /* any other character */ } /* ----- handle arguments of the cite command ------- */ -<CiteLabel>{CITEID} { // found argument - addCite(yyscanner); +<CiteLabel>{CITEID} { // found argument + addCite(yyscanner); addOutput(yyscanner,yytext); - BEGIN(Comment); - } -<CiteLabel>{DOCNL} { // missing argument - warn(yyextra->fileName,yyextra->lineNr, - "\\cite command has no label" - ); - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - BEGIN( Comment ); - } -<CiteLabel>. { // invalid character for cite label - warn(yyextra->fileName,yyextra->lineNr, - "Invalid or missing cite label" - ); - BEGIN(Comment); - } + BEGIN(Comment); + } +<CiteLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\cite command has no label" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<CiteLabel>. { // invalid character for cite label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing cite label" + ); + BEGIN(Comment); + } /* ----- handle argument of the copydoc command ------- */ -<CopyDoc><<EOF>> | -<CopyDoc>{DOCNL} { - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); - setOutput(yyscanner,OutputDoc); +<CopyDoc><<EOF>> | +<CopyDoc>{DOCNL} { + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + setOutput(yyscanner,OutputDoc); addOutput(yyscanner," \\copydetails "); - addOutput(yyscanner,yyextra->copyDocArg); - addOutput(yyscanner,"\n"); - BEGIN(Comment); - } -<CopyDoc>[^\n\\]+ { - yyextra->copyDocArg+=yytext; - addOutput(yyscanner,yytext); - } -<CopyDoc>. { - yyextra->copyDocArg+=yytext; - addOutput(yyscanner,yytext); - } + addOutput(yyscanner,yyextra->copyDocArg); + addOutput(yyscanner,"\n"); + BEGIN(Comment); + } +<CopyDoc>[^\n\\]+ { + yyextra->copyDocArg+=yytext; + addOutput(yyscanner,yytext); + } +<CopyDoc>. { + yyextra->copyDocArg+=yytext; + addOutput(yyscanner,yytext); + } %% @@ -1940,7 +1941,7 @@ static bool handleClass(yyscan_t yyscanner,const QCString &, const QCStringList { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::CLASSDOC_SEC); - BEGIN( ClassDocArg1 ); + BEGIN( ClassDocArg1 ); return stop; } @@ -1955,7 +1956,7 @@ static bool handleProtocol(yyscan_t yyscanner,const QCString &, const QCStringLi { // Obj-C protocol struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::PROTOCOLDOC_SEC); - BEGIN( ClassDocArg1 ); + BEGIN( ClassDocArg1 ); return stop; } @@ -1963,7 +1964,7 @@ static bool handleCategory(yyscan_t yyscanner,const QCString &, const QCStringLi { // Obj-C category struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::CATEGORYDOC_SEC); - BEGIN( CategoryDocArg1 ); + BEGIN( CategoryDocArg1 ); return stop; } @@ -1971,7 +1972,7 @@ static bool handleUnion(yyscan_t yyscanner,const QCString &, const QCStringList { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::UNIONDOC_SEC); - BEGIN( ClassDocArg1 ); + BEGIN( ClassDocArg1 ); return stop; } @@ -1979,7 +1980,7 @@ static bool handleStruct(yyscan_t yyscanner,const QCString &, const QCStringList { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::STRUCTDOC_SEC); - BEGIN( ClassDocArg1 ); + BEGIN( ClassDocArg1 ); return stop; } @@ -1987,7 +1988,7 @@ static bool handleInterface(yyscan_t yyscanner,const QCString &, const QCStringL { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::INTERFACEDOC_SEC); - BEGIN( ClassDocArg1 ); + BEGIN( ClassDocArg1 ); return stop; } @@ -1995,7 +1996,7 @@ static bool handleIdlException(yyscan_t yyscanner,const QCString &, const QCStri { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::EXCEPTIONDOC_SEC); - BEGIN( ClassDocArg1 ); + BEGIN( ClassDocArg1 ); return stop; } @@ -2012,7 +2013,7 @@ static bool handleMainpage(yyscan_t yyscanner,const QCString &, const QCStringLi struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::MAINPAGEDOC_SEC); yyextra->current->name = ""; - if (!stop) + if (!stop) { yyextra->current->name = "mainpage"; } @@ -2024,7 +2025,7 @@ static bool handleFile(yyscan_t yyscanner,const QCString &, const QCStringList & { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool stop=makeStructuralIndicator(yyscanner,Entry::FILEDOC_SEC); - if (!stop) + if (!stop) { yyextra->current->name = yyextra->fileName; } @@ -2074,7 +2075,7 @@ static bool handleExample(yyscan_t yyscanner,const QCString &cmd, const QCString else { warn(yyextra->fileName,yyextra->lineNr, - "unsupported option '%s' for command '\\%s'",qPrint(opt),qPrint(cmd)); + "unsupported option '%s' for command '\\%s'",qPrint(opt),qPrint(cmd)); } } bool stop=makeStructuralIndicator(yyscanner,section); @@ -2168,9 +2169,9 @@ static bool handleParBlock(yyscan_t yyscanner,const QCString &, const QCStringLi if (yyextra->insideParBlock) { warn(yyextra->fileName,yyextra->lineNr, - "found \\parblock command while already in a parblock!"); + "found \\parblock command while already in a parblock!"); } - if (!yyextra->spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); yyextra->spaceBeforeCmd.resize(0); @@ -2186,7 +2187,7 @@ static bool handleEndParBlock(yyscan_t yyscanner,const QCString &, const QCStrin if (!yyextra->insideParBlock) { warn(yyextra->fileName,yyextra->lineNr, - "found \\endparblock command without matching \\parblock!"); + "found \\endparblock command without matching \\parblock!"); } addOutput(yyscanner,"@endparblock"); setOutput(yyscanner,OutputDoc); // to end a parblock inside a xrefitem like context @@ -2200,7 +2201,7 @@ static bool handleRelated(yyscan_t yyscanner,const QCString &, const QCStringLis if (!yyextra->current->relates.isEmpty()) { warn(yyextra->fileName,yyextra->lineNr, - "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); + "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); } yyextra->current->relatesType = Simple; BEGIN(RelatesParam1); @@ -2213,7 +2214,7 @@ static bool handleRelatedAlso(yyscan_t yyscanner,const QCString &, const QCStrin if (!yyextra->current->relates.isEmpty()) { warn(yyextra->fileName,yyextra->lineNr, - "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); + "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); } yyextra->current->relatesType = Duplicate; BEGIN(RelatesParam1); @@ -2226,7 +2227,7 @@ static bool handleMemberOf(yyscan_t yyscanner,const QCString &, const QCStringLi if (!yyextra->current->relates.isEmpty()) { warn(yyextra->fileName,yyextra->lineNr, - "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); + "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); } yyextra->current->relatesType = MemberOf; BEGIN(RelatesParam1); @@ -2257,15 +2258,15 @@ static bool handleSection(yyscan_t yyscanner,const QCString &s, const QCStringLi static bool handleSubpage(yyscan_t yyscanner,const QCString &s, const QCStringList &) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->current->section!=Entry::EMPTY_SEC && + if (yyextra->current->section!=Entry::EMPTY_SEC && yyextra->current->section!=Entry::PAGEDOC_SEC && yyextra->current->section!=Entry::MAINPAGEDOC_SEC ) { warn(yyextra->fileName,yyextra->lineNr, - "found \\subpage command in a comment block that is not marked as a page!"); + "found \\subpage command in a comment block that is not marked as a page!"); } - if (!yyextra->spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); yyextra->spaceBeforeCmd.resize(0); @@ -2286,7 +2287,7 @@ static bool handleAnchor(yyscan_t yyscanner,const QCString &s, const QCStringLis static bool handleCite(yyscan_t yyscanner,const QCString &s, const QCStringList &) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (!yyextra->spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); yyextra->spaceBeforeCmd.resize(0); @@ -2348,7 +2349,7 @@ static bool handleElseIf(yyscan_t yyscanner,const QCString &, const QCStringList if (yyextra->guards.empty()) { warn(yyextra->fileName,yyextra->lineNr, - "found \\else without matching start command"); + "found \\else without matching start command"); } else { @@ -2365,7 +2366,7 @@ static bool handleElse(yyscan_t yyscanner,const QCString &, const QCStringList & if (yyextra->guards.empty()) { warn(yyextra->fileName,yyextra->lineNr, - "found \\else without matching start command"); + "found \\else without matching start command"); } else { @@ -2381,14 +2382,14 @@ static bool handleEndIf(yyscan_t yyscanner,const QCString &, const QCStringList if (yyextra->guards.empty()) { warn(yyextra->fileName,yyextra->lineNr, - "found \\endif without matching start command"); + "found \\endif without matching start command"); } else { yyextra->guards.pop(); } yyextra->enabledSectionFound=FALSE; - if (!yyextra->spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); yyextra->spaceBeforeCmd.resize(0); @@ -2408,7 +2409,7 @@ static bool handleIngroup(yyscan_t yyscanner,const QCString &, const QCStringLis static bool handleNoSubGrouping(yyscan_t yyscanner,const QCString &, const QCStringList &) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->current->subGrouping = FALSE; + yyextra->current->subGrouping = FALSE; return FALSE; } @@ -2490,7 +2491,7 @@ static bool handleInternal(yyscan_t yyscanner,const QCString &, const QCStringLi // make sure some whitespace before a \internal command // is not treated as "documentation" if (yyextra->current->doc.stripWhiteSpace().isEmpty()) - { + { yyextra->current->doc.resize(0); } yyextra->condCount=0; @@ -2499,7 +2500,7 @@ static bool handleInternal(yyscan_t yyscanner,const QCString &, const QCStringLi else { // re-enabled for bug640828 - addOutput(yyscanner," \\internal "); + addOutput(yyscanner," \\internal "); yyextra->inInternalDocs = TRUE; } return FALSE; @@ -2515,7 +2516,7 @@ static bool handleStatic(yyscan_t yyscanner,const QCString &, const QCStringList { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endBrief(yyscanner); - yyextra->current->stat = TRUE; + yyextra->current->stat = TRUE; return FALSE; } @@ -2523,7 +2524,7 @@ static bool handlePure(yyscan_t yyscanner,const QCString &, const QCStringList & { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endBrief(yyscanner); - yyextra->current->virt = Pure; + yyextra->current->virt = Pure; return FALSE; } @@ -2572,7 +2573,7 @@ static bool handlePublicSection(yyscan_t yyscanner,const QCString &, const QCStr static bool handleToc(yyscan_t yyscanner,const QCString &, const QCStringList &optList) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->current->section==Entry::PAGEDOC_SEC || + if (yyextra->current->section==Entry::PAGEDOC_SEC || yyextra->current->section==Entry::MAINPAGEDOC_SEC) { QCStringList::ConstIterator it; @@ -2653,7 +2654,7 @@ static bool handleCopyBrief(yyscan_t yyscanner,const QCString &, const QCStringL // otherwise it will be copied inline (see bug691315 & bug700788) setOutput(yyscanner,OutputBrief); } - if (!yyextra->spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); yyextra->spaceBeforeCmd.resize(0); @@ -2666,7 +2667,7 @@ static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const QCStrin { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; setOutput(yyscanner,OutputDoc); - if (!yyextra->spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); yyextra->spaceBeforeCmd.resize(0); @@ -2679,7 +2680,7 @@ static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const QCStringLis { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; setOutput(yyscanner,OutputBrief); - if (!yyextra->spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); yyextra->spaceBeforeCmd.resize(0); @@ -2727,7 +2728,7 @@ static bool getDocSectionName(int s) case Entry::EXAMPLE_SEC: case Entry::MEMBERGRP_SEC: return TRUE; - default: + default: return FALSE; } } @@ -2789,7 +2790,7 @@ static void addXRefItem(yyscan_t yyscanner, RefItem *item = 0; for (RefItem *i : yyextra->current->sli) { - if (i && qstrcmp(i->list()->listName(),listName)==0) + if (i && qstrcmp(i->list()->listName(),listName)==0) { //printf("found %s lii->type=%s\n",listName,lii->type); item = i; @@ -2861,7 +2862,7 @@ static QCString addFormula(yyscan_t yyscanner) int id = FormulaManager::instance().addFormula(fText); formLabel.sprintf("\\_form#%d",id); for (int i=0;i<yyextra->formulaNewLines;i++) formLabel+="@_fakenl"; // add fake newlines to - // keep the warnings + // keep the warnings // correctly aligned. return formLabel; } @@ -2927,7 +2928,7 @@ static void stripTrailingWhiteSpace(QCString &s) int i = (int)len-1; char c; while (i>=0 && ((c = s.at(i))==' ' || c=='\t' || c=='\r')) i--; - if (i!=(int)len-1) + if (i!=(int)len-1) { s.resize(i+2); // string up to and including char at pos i and \0 terminator } @@ -2942,8 +2943,8 @@ static inline void setOutput(yyscan_t yyscanner,OutputContext ctx) yyextra->xrefAppendFlag = !yyextra->inBody && yyextra->inContext==OutputXRef && ctx==OutputXRef && // two consecutive xref items yyextra->newXRefKind==yyextra->xrefKind && // of the same kind - (yyextra->xrefKind!=XRef_Item || - yyextra->newXRefItemKey==yyextra->xrefItemKey); // with the same key if \xrefitem + (yyextra->xrefKind!=XRef_Item || + yyextra->newXRefItemKey==yyextra->xrefItemKey); // with the same key if \xrefitem //printf("%d && %d && %d && (%d || %d)\n", // yyextra->inContext==OutputXRef, // ctx==OutputXRef, @@ -2951,10 +2952,10 @@ static inline void setOutput(yyscan_t yyscanner,OutputContext ctx) // yyextra->xrefKind!=XRef_Item, // yyextra->newXRefItemKey==yyextra->xrefItemKey); //printf("refKind=%d yyextra->newXRefKind=%d xrefAppendToPrev=%d yyextra->xrefAppendFlag=%d\n", - // yyextra->xrefKind,yyextra->newXRefKind,xrefAppendToPrev,yyextra->xrefAppendFlag); + // yyextra->xrefKind,yyextra->newXRefKind,xrefAppendToPrev,yyextra->xrefAppendFlag); //printf("setOutput(yyscanner,yyextra->inContext=%d ctx=%d)\n",yyextra->inContext,ctx); - if (yyextra->inContext==OutputXRef) // end of XRef section => add the item + if (yyextra->inContext==OutputXRef) // end of XRef section => add the item { // See if we can append this new xref item to the previous one. // We know this at the start of the next item of the same @@ -3156,15 +3157,16 @@ CommentScanner::~CommentScanner() bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *parser, /* in */ Entry *curEntry, /* in */ const QCString &comment, - /* in */ const QCString &fileName, - /* in,out */ int &lineNr, - /* in */ bool isBrief, - /* in */ bool isAutoBriefOn, - /* in */ bool isInbody, - /* in,out */ Protection &prot, - /* in,out */ int &position, - /* out */ bool &newEntryNeeded - ) + /* in */ const QCString &fileName, + /* in,out */ int &lineNr, + /* in */ bool isBrief, + /* in */ bool isAutoBriefOn, + /* in */ bool isInbody, + /* in,out */ Protection &prot, + /* in,out */ int &position, + /* out */ bool &newEntryNeeded, + /* in */ bool markdownSupport + ) { yyscan_t yyscanner = p->yyscanner; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -3179,8 +3181,8 @@ bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *pars yyextra->inputString = comment; yyextra->inputString.append(" "); yyextra->inputPosition = position; - yyextra->lineNr = lineNr; - yyextra->fileName = fileName; + yyextra->lineNr = lineNr; + yyextra->fileName = fileName; yyextra->protection = prot; yyextra->needNewEntry = FALSE; yyextra->xrefKind = XRef_None; @@ -3188,6 +3190,7 @@ bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *pars yyextra->insidePre = FALSE; yyextra->parseMore = FALSE; yyextra->inBody = isInbody; + yyextra->markdownSupport= markdownSupport; yyextra->outputXRef.resize(0); if (!isBrief && !isAutoBriefOn && !yyextra->current->doc.isEmpty()) { // add newline separator between detailed comment blocks @@ -3209,7 +3212,7 @@ bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *pars Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\n" "input=[\n%s]\n",qPrint(fileName),lineNr,qPrint(yyextra->inputString) ); - + commentscanYYrestart( 0, yyscanner ); BEGIN( Comment ); commentscanYYlex(yyscanner); @@ -3228,7 +3231,7 @@ bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *pars if (yyextra->insideParBlock) { warn(yyextra->fileName,yyextra->lineNr, - "Documentation block ended while inside a \\parblock. Missing \\endparblock"); + "Documentation block ended while inside a \\parblock. Missing \\endparblock"); } yyextra->current->doc=stripLeadingAndTrailingEmptyLines(yyextra->current->doc,yyextra->current->docLine); @@ -3248,14 +3251,14 @@ bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *pars Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\noutput=[\n" "brief=[line=%d\n%s]\ndocs=[line=%d\n%s]\ninbody=[line=%d\n%s]\n]\n===========\n", qPrint(fileName),lineNr, - yyextra->current->briefLine,qPrint(yyextra->current->brief), + yyextra->current->briefLine,qPrint(yyextra->current->brief), yyextra->current->docLine,qPrint(yyextra->current->doc), yyextra->current->inbodyLine,qPrint(yyextra->current->inbodyDocs) ); - + checkFormula(yyscanner); prot = yyextra->protection; - + yyextra->docGroup.addDocs(curEntry); newEntryNeeded = yyextra->needNewEntry; @@ -3285,7 +3288,7 @@ static void handleGuard(yyscan_t yyscanner,const QCString &expr) if (parentEnabled) { if ( - (sectionEnabled && yyextra->guardType==Guard_If) || + (sectionEnabled && yyextra->guardType==Guard_If) || (!sectionEnabled && yyextra->guardType==Guard_IfNot) ) // section is visible { diff --git a/src/context.cpp b/src/context.cpp index 3d71706..f0b697a 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1262,7 +1262,8 @@ static TemplateVariant parseDoc(const Definition *def,const QCString &file,int l const QCString &relPath,const QCString &docStr,bool isBrief) { TemplateVariant result; - DocRoot *root = validatingParseDoc(file,line,def,0,docStr,TRUE,FALSE,0,isBrief,FALSE); + DocRoot *root = validatingParseDoc(file,line,def,0,docStr,TRUE,FALSE, + 0,isBrief,FALSE,Config_getBool(MARKDOWN_SUPPORT)); QGString docs; { FTextStream ts(&docs); diff --git a/src/dirdef.cpp b/src/dirdef.cpp index dd8444e..b058f86 100644 --- a/src/dirdef.cpp +++ b/src/dirdef.cpp @@ -223,7 +223,8 @@ void DirDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) // repeat brief description if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // separator between brief and details if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && @@ -243,7 +244,8 @@ void DirDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) // write documentation if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } } @@ -253,7 +255,8 @@ void DirDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc( - briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE); + briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startParagraph(); @@ -341,7 +344,8 @@ void DirDefImpl::writeSubDirList(OutputList &ol) FALSE, // isExample 0, // exampleName TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); ol.endMemberDescription(); } @@ -412,7 +416,8 @@ void DirDefImpl::writeFileList(OutputList &ol) FALSE, // isExample 0, // exampleName TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); ol.endMemberDescription(); } diff --git a/src/docparser.cpp b/src/docparser.cpp index 0ed7f50..73131f6 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -114,6 +114,7 @@ static uint g_includeFileOffset; static uint g_includeFileLength; static int g_includeFileLine; static bool g_includeFileShowLineNo; +static bool g_markdownSupport; /** Parser's context to store all global variables. @@ -1799,7 +1800,7 @@ static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children, if (doc.isEmpty()) return retval; - doctokenizerYYinit(doc,g_fileName); + doctokenizerYYinit(doc,g_fileName,g_markdownSupport); // first parse any number of paragraphs bool isFirst=TRUE; @@ -7565,7 +7566,8 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef *md, const char *input,bool indexWords, bool isExample, const char *exampleName, - bool singleLine, bool linkFromIndex) + bool singleLine, bool linkFromIndex, + bool markdownSupport) { //printf("validatingParseDoc(%s,%s)=[%s]\n",ctx?ctx->name().data():"<none>", // md?md->name().data():"<none>", @@ -7722,6 +7724,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, g_retvalsFound.clear(); g_paramsFound.setAutoDelete(FALSE); g_paramsFound.clear(); + g_markdownSupport = markdownSupport; //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine); doctokenizerYYlineno=startLine; @@ -7732,7 +7735,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, inpStr+='\n'; } //printf("processCopyDoc(in='%s' out='%s')\n",input,inpStr.data()); - doctokenizerYYinit(inpStr,g_fileName); + doctokenizerYYinit(inpStr,g_fileName,markdownSupport); // build abstract syntax tree DocRoot *root = new DocRoot(md!=0,singleLine); @@ -7800,7 +7803,7 @@ DocText *validatingParseText(const char *input) if (input) { doctokenizerYYlineno=1; - doctokenizerYYinit(input,g_fileName); + doctokenizerYYinit(input,g_fileName,Config_getBool(MARKDOWN_SUPPORT)); // build abstract syntax tree txt->parse(); diff --git a/src/docparser.h b/src/docparser.h index d05dea9..1dc6b3f 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 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 + * 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. * @@ -52,7 +52,7 @@ QCString getJsDirEmbeddingChar(QString::Direction textDir); * @param md Member definition to which the documentation belongs. * Can be 0. * @param input String representation of the documentation block. - * @param indexWords Indicates whether or not words should be put in the + * @param indexWords Indicates whether or not words should be put in the * search index. * @param isExample TRUE if the documentation belongs to an example. * @param exampleName Base name of the example file (0 if isExample is FALSE). @@ -61,16 +61,19 @@ QCString getJsDirEmbeddingChar(QString::Direction textDir); * @param linkFromIndex TRUE if the documentation is generated from an * index page. In this case context is not used to determine * the relative path when making a link. + * @param markdownSupport TRUE if the input needs to take markdown markup into + * account. * @returns Root node of the abstract syntax tree. Ownership of the * pointer is handed over to the caller. */ DocRoot *validatingParseDoc(const char *fileName,int startLine, const Definition *context, const MemberDef *md, const char *input,bool indexWords, - bool isExample,const char *exampleName=0, - bool singleLine=FALSE,bool linkFromIndex=FALSE); + bool isExample,const char *exampleName, + bool singleLine,bool linkFromIndex, + bool markdownSupport); -/*! Main entry point for parsing simple text fragments. These +/*! Main entry point for parsing simple text fragments. These * fragments are limited to words, whitespace and symbols. */ DocText *validatingParseText(const char *input); @@ -87,11 +90,11 @@ class DocNode { public: /*! Available node types. */ - enum Kind { Kind_Root = 0, - Kind_Word = 1, - Kind_WhiteSpace = 2, - Kind_Para = 3, - Kind_AutoList = 4, + enum Kind { Kind_Root = 0, + Kind_Word = 1, + Kind_WhiteSpace = 2, + Kind_Para = 3, + Kind_AutoList = 4, Kind_AutoListItem = 5, Kind_Symbol = 6, Kind_URL = 7, @@ -158,7 +161,7 @@ class DocNode /*! Sets a new parent for this node. */ void setParent(DocNode *parent) { m_parent = parent; } - /*! Acceptor function for node visitors. Part of the visitor pattern. + /*! Acceptor function for node visitors. Part of the visitor pattern. * @param v Abstract visitor. */ virtual void accept(DocVisitor *v) = 0; @@ -185,14 +188,14 @@ template<class T> class CompAccept : public DocNode { public: CompAccept() { m_children.setAutoDelete(TRUE); } - void accept(DocVisitor *v) + void accept(DocVisitor *v) { T *obj = dynamic_cast<T *>(this); - v->visitPre(obj); + v->visitPre(obj); QListIterator<DocNode> cli(m_children); DocNode *n; for (cli.toFirst();(n=cli.current());++cli) n->accept(v); - v->visitPost(obj); + v->visitPost(obj); } const QList<DocNode> &children() const { return m_children; } QList<DocNode> &children() { return m_children; } @@ -228,13 +231,13 @@ template<class T> class CompAccept : public DocNode { return getTextBasicDir(0); } - + protected: QList<DocNode> m_children; }; -/** Node representing a word +/** Node representing a word */ class DocWord : public DocNode { @@ -282,7 +285,7 @@ class DocLinkedWord : public DocNode class DocURL : public DocNode { public: - DocURL(DocNode *parent,const QCString &url,bool isEmail) : + DocURL(DocNode *parent,const QCString &url,bool isEmail) : m_url(url), m_isEmail(isEmail) { m_parent=parent; } QCString url() const { return m_url; } Kind kind() const { return Kind_URL; } @@ -482,7 +485,7 @@ class DocSymbol : public DocNode const char *symb; const PerlType type; }PerlSymb; - DocSymbol(DocNode *parent,SymType s) : + DocSymbol(DocNode *parent,SymType s) : m_symbol(s) { m_parent = parent; } SymType symbol() const { return m_symbol; } Kind kind() const { return Kind_Symbol; } @@ -512,7 +515,7 @@ class DocEmoji : public DocNode class DocWhiteSpace : public DocNode { public: - DocWhiteSpace(DocNode *parent,const QCString &chars) : + DocWhiteSpace(DocNode *parent,const QCString &chars) : m_chars(chars) { m_parent = parent; } Kind kind() const { return Kind_WhiteSpace; } QCString chars() const { return m_chars; } @@ -625,7 +628,7 @@ class DocIncOperator : public DocNode public: enum Type { Line, SkipLine, Skip, Until }; DocIncOperator(DocNode *parent,Type t,const QCString &pat, - const QCString &context,bool isExample,const QCString &exampleFile) : + const QCString &context,bool isExample,const QCString &exampleFile) : m_type(t), m_pattern(pat), m_context(context), m_isFirst(FALSE), m_isLast(FALSE), m_isExample(isExample), m_exampleFile(exampleFile) { m_parent = parent; } @@ -695,7 +698,7 @@ class DocFormula : public DocNode class DocIndexEntry : public DocNode { public: - DocIndexEntry(DocNode *parent,const Definition *scope,const MemberDef *md) + DocIndexEntry(DocNode *parent,const Definition *scope,const MemberDef *md) : m_scope(scope), m_member(md){ m_parent = parent; } Kind kind() const { return Kind_IndexEntry; } int parse(); @@ -962,7 +965,7 @@ class DocHRef : public CompAccept<DocHRef> { public: DocHRef(DocNode *parent,const HtmlAttribList &attribs,const QCString &url, - const QCString &relPath) : + const QCString &relPath) : m_attribs(attribs), m_url(url), m_relPath(relPath) { m_parent = parent; } int parse(); QCString url() const { return m_url; } @@ -980,7 +983,7 @@ class DocHRef : public CompAccept<DocHRef> class DocHtmlHeader : public CompAccept<DocHtmlHeader> { public: - DocHtmlHeader(DocNode *parent,const HtmlAttribList &attribs,int level) : + DocHtmlHeader(DocNode *parent,const HtmlAttribList &attribs,int level) : m_level(level), m_attribs(attribs) { m_parent = parent; } int level() const { return m_level; } Kind kind() const { return Kind_HtmlHeader; } @@ -996,7 +999,7 @@ class DocHtmlHeader : public CompAccept<DocHtmlHeader> class DocHtmlDescTitle : public CompAccept<DocHtmlDescTitle> { public: - DocHtmlDescTitle(DocNode *parent,const HtmlAttribList &attribs) : + DocHtmlDescTitle(DocNode *parent,const HtmlAttribList &attribs) : m_attribs(attribs) { m_parent = parent; } Kind kind() const { return Kind_HtmlDescTitle; } const HtmlAttribList &attribs() const { return m_attribs; } @@ -1025,7 +1028,7 @@ class DocSection : public CompAccept<DocSection> { public: DocSection(DocNode *parent,int level,const QCString &id) : - m_level(level), m_id(id) { m_parent = parent; } + m_level(level), m_id(id) { m_parent = parent; } Kind kind() const { return Kind_Section; } int level() const { return m_level; } QCString title() const { return m_title; } @@ -1046,7 +1049,7 @@ class DocSection : public CompAccept<DocSection> class DocSecRefItem : public CompAccept<DocSecRefItem> { public: - DocSecRefItem(DocNode *parent,const QCString &target) : + DocSecRefItem(DocNode *parent,const QCString &target) : m_target(target) { m_parent = parent; } Kind kind() const { return Kind_SecRefItem; } QCString target() const { return m_target; } @@ -1110,7 +1113,7 @@ class DocHtmlList : public CompAccept<DocHtmlList> { public: enum Type { Unordered, Ordered }; - DocHtmlList(DocNode *parent,const HtmlAttribList &attribs,Type t) : + DocHtmlList(DocNode *parent,const HtmlAttribList &attribs,Type t) : m_type(t), m_attribs(attribs) { m_parent = parent; } Kind kind() const { return Kind_HtmlList; } Type type() const { return m_type; } @@ -1127,8 +1130,8 @@ class DocHtmlList : public CompAccept<DocHtmlList> class DocSimpleSect : public CompAccept<DocSimpleSect> { public: - enum Type - { + enum Type + { Unknown, See, Return, Author, Authors, Version, Since, Date, Note, Warning, Copyright, Pre, Post, Invar, Remark, Attention, User, Rcs }; @@ -1150,7 +1153,7 @@ class DocSimpleSect : public CompAccept<DocSimpleSect> }; /** Node representing a separator between two simple sections of the - * same type. + * same type. */ class DocSimpleSectSep : public DocNode { @@ -1167,16 +1170,16 @@ class DocParamSect : public CompAccept<DocParamSect> { friend class DocParamList; public: - enum Type - { + enum Type + { Unknown, Param, RetVal, Exception, TemplateParam }; enum Direction { In=1, Out=2, InOut=3, Unspecified=0 }; - DocParamSect(DocNode *parent,Type t) - : m_type(t), m_hasInOutSpecifier(FALSE), m_hasTypeSpecifier(FALSE) + DocParamSect(DocNode *parent,Type t) + : m_type(t), m_hasInOutSpecifier(FALSE), m_hasTypeSpecifier(FALSE) { m_parent = parent; } int parse(const QCString &cmdName,bool xmlContext,Direction d); Kind kind() const { return Kind_ParamSect; } @@ -1194,7 +1197,7 @@ class DocParamSect : public CompAccept<DocParamSect> class DocPara : public CompAccept<DocPara> { public: - DocPara(DocNode *parent) : + DocPara(DocNode *parent) : m_isFirst(FALSE), m_isLast(FALSE) { m_parent = parent; } int parse(); Kind kind() const { return Kind_Para; } @@ -1241,12 +1244,12 @@ class DocPara : public CompAccept<DocPara> class DocParamList : public DocNode { public: - DocParamList(DocNode *parent,DocParamSect::Type t,DocParamSect::Direction d) + DocParamList(DocNode *parent,DocParamSect::Type t,DocParamSect::Direction d) : m_type(t), m_dir(d), m_isFirst(TRUE), m_isLast(TRUE) - { m_paragraphs.setAutoDelete(TRUE); - m_params.setAutoDelete(TRUE); + { m_paragraphs.setAutoDelete(TRUE); + m_params.setAutoDelete(TRUE); m_paramTypes.setAutoDelete(TRUE); - m_parent = parent; + m_parent = parent; } virtual ~DocParamList() { } Kind kind() const { return Kind_ParamList; } @@ -1259,12 +1262,12 @@ class DocParamList : public DocNode bool isFirst() const { return m_isFirst; } bool isLast() const { return m_isLast; } void accept(DocVisitor *v) - { - v->visitPre(this); + { + v->visitPre(this); QListIterator<DocPara> cli(m_paragraphs); DocNode *n; for (cli.toFirst();(n=cli.current());++cli) n->accept(v); - v->visitPost(this); + v->visitPost(this); } int parse(const QCString &cmdName); int parseXml(const QCString ¶mName); @@ -1290,9 +1293,9 @@ class DocSimpleListItem : public DocNode Kind kind() const { return Kind_SimpleListItem; } void accept(DocVisitor *v) { - v->visitPre(this); + v->visitPre(this); m_paragraph->accept(v); - v->visitPost(this); + v->visitPost(this); } private: @@ -1303,7 +1306,7 @@ class DocSimpleListItem : public DocNode class DocHtmlListItem : public CompAccept<DocHtmlListItem> { public: - DocHtmlListItem(DocNode *parent,const HtmlAttribList &attribs,int num) : + DocHtmlListItem(DocNode *parent,const HtmlAttribList &attribs,int num) : m_attribs(attribs), m_itemNum(num) { m_parent = parent; } Kind kind() const { return Kind_HtmlListItem; } int itemNumber() const { return m_itemNum; } @@ -1335,7 +1338,7 @@ class DocHtmlCell : public CompAccept<DocHtmlCell> friend class DocHtmlTable; public: enum Alignment { Left, Right, Center }; - DocHtmlCell(DocNode *parent,const HtmlAttribList &attribs,bool isHeading) : + DocHtmlCell(DocNode *parent,const HtmlAttribList &attribs,bool isHeading) : m_isHeading(isHeading), m_attribs(attribs) { m_parent = parent; } bool isHeading() const { return m_isHeading; } bool isFirst() const { return m_isFirst; } @@ -1387,7 +1390,7 @@ class DocHtmlRow : public CompAccept<DocHtmlRow> { friend class DocHtmlTable; public: - DocHtmlRow(DocNode *parent,const HtmlAttribList &attribs) : + DocHtmlRow(DocNode *parent,const HtmlAttribList &attribs) : m_attribs(attribs) { m_parent = parent; } Kind kind() const { return Kind_HtmlRow; } uint numCells() const { return m_children.count(); } @@ -1422,7 +1425,7 @@ class DocHtmlRow : public CompAccept<DocHtmlRow> class DocHtmlTable : public CompAccept<DocHtmlTable> { public: - DocHtmlTable(DocNode *parent,const HtmlAttribList &attribs) + DocHtmlTable(DocNode *parent,const HtmlAttribList &attribs) : m_attribs(attribs) { m_caption=0; m_numCols=0; m_parent = parent; } ~DocHtmlTable() { delete m_caption; } Kind kind() const { return Kind_HtmlTable; } diff --git a/src/doctokenizer.h b/src/doctokenizer.h index e01f045..f43cd07 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -6,8 +6,8 @@ * Copyright (C) 1997-2015 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 + * 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. * @@ -78,7 +78,7 @@ struct TokenInfo QCString text; // comment blocks - + // list token info bool isEnumList = false; int indent = 0; @@ -124,7 +124,7 @@ const char *tokToString(int token); // operations on the scanner void doctokenizerYYFindSections(const char *input,const Definition *d, const char *fileName); -void doctokenizerYYinit(const char *input,const char *fileName); +void doctokenizerYYinit(const char *input,const char *fileName,bool markdownSupport); void doctokenizerYYcleanup(); void doctokenizerYYpushContext(); bool doctokenizerYYpopContext(); diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 5317de5..b1aa82f 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -60,6 +60,7 @@ static const char *g_inputString; static QCString g_fileName; static bool g_insidePre; static int g_sharpCount=0; +static bool g_markdownSupport=TRUE; // context for section finding phase static const Definition *g_definition; @@ -487,7 +488,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } <St_Para>^{MLISTITEM} { /* list item */ - if (!Doxygen::markdownSupport || g_insidePre) + if (!g_markdownSupport || g_insidePre) { REJECT; } @@ -503,7 +504,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } <St_Para>^{OLISTITEM} { /* numbered list item */ - if (!Doxygen::markdownSupport || g_insidePre) + if (!g_markdownSupport || g_insidePre) { REJECT; } @@ -529,7 +530,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } <St_Para>{BLANK}*\n{MLISTITEM} { /* list item on next line */ - if (!Doxygen::markdownSupport || g_insidePre) + if (!g_markdownSupport || g_insidePre) { REJECT; } @@ -546,7 +547,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } <St_Para>{BLANK}*\n{OLISTITEM} { /* list item on next line */ - if (!Doxygen::markdownSupport || g_insidePre) + if (!g_markdownSupport || g_insidePre) { REJECT; } @@ -768,13 +769,13 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } <St_Para>({BLANK}*\n)+{BLANK}*\n/{MLISTITEM} { /* skip trailing paragraph followed by new list item */ - if (!Doxygen::markdownSupport || g_insidePre || g_autoListLevel==0) + if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } } <St_Para>({BLANK}*\n)+{BLANK}*\n/{OLISTITEM} { /* skip trailing paragraph followed by new list item */ - if (!Doxygen::markdownSupport || g_insidePre || g_autoListLevel==0) + if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } @@ -1405,13 +1406,14 @@ void doctokenizerYYFindSections(const char *input,const Definition *d, printlex(yy_flex_debug, FALSE, __FILE__, fileName); } -void doctokenizerYYinit(const char *input,const char *fileName) +void doctokenizerYYinit(const char *input,const char *fileName,bool markdownSupport) { g_autoListLevel = 0; g_inputString = input; g_inputPos = 0; g_fileName = fileName; g_insidePre = FALSE; + g_markdownSupport = markdownSupport; BEGIN(St_Para); } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index f20756e..188d920 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -158,7 +158,7 @@ int Doxygen::subpageNestingLevel = 0; bool Doxygen::userComments = FALSE; QCString Doxygen::spaces; bool Doxygen::generatingXmlOutput = FALSE; -bool Doxygen::markdownSupport = TRUE; +//bool Doxygen::markdownSupport = TRUE; GenericsSDict *Doxygen::genericsDict; DefineList Doxygen::macroDefinitions; @@ -8632,7 +8632,10 @@ static void generateExampleDocs() pd->documentation()+"\n\n\\include"+lineNoOptStr+" "+pd->name(), // docs TRUE, // index words TRUE, // is example - pd->name() + pd->name(), + FALSE, + FALSE, + Config_getBool(MARKDOWN_SUPPORT) ); endFile(*g_outputList); // contains g_outputList->endContents() } @@ -10296,7 +10299,7 @@ void adjustConfiguration() Config_getBool(REFERENCES_RELATION) || Config_getBool(REFERENCED_BY_RELATION); - Doxygen::markdownSupport = Config_getBool(MARKDOWN_SUPPORT); + //Doxygen::markdownSupport = Config_getBool(MARKDOWN_SUPPORT); /************************************************************************** * Add custom extension mappings diff --git a/src/doxygen.h b/src/doxygen.h index 557c871..0746bbd 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -148,7 +148,7 @@ class Doxygen static int subpageNestingLevel; static QCString spaces; static bool generatingXmlOutput; - static bool markdownSupport; + //static bool markdownSupport; static GenericsSDict *genericsDict; static DefineList macroDefinitions; }; diff --git a/src/filedef.cpp b/src/filedef.cpp index 919ce2b..91a7835 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -477,7 +477,8 @@ void FileDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) ol.startTextBlock(); if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && !documentation().isEmpty()) @@ -494,7 +495,8 @@ void FileDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) } if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } //printf("Writing source ref for file %s\n",name().data()); if (Config_getBool(SOURCE_BROWSER)) @@ -542,7 +544,8 @@ void FileDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 852c4d9..195293f 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -2514,7 +2514,8 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine; int position=0; bool needsEntry = FALSE; - QCString processedDoc = processMarkdownForCommentBlock(doc,yyextra->fileName,lineNr); + Markdown markdown(yyextra->fileName,lineNr); + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc) : doc; while (yyextra->commentScanner.parseCommentBlock( yyextra->thisParser, yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(), @@ -2526,8 +2527,9 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief yyextra->docBlockInBody, yyextra->defaultProtection, position, - needsEntry - )) + needsEntry, + Config_getBool(MARKDOWN_SUPPORT) + )) { DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry)); if (needsEntry) addCurrentEntry(yyscanner,false); diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index d5a5703..6fc14bf 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -348,7 +348,8 @@ static void generateBriefDoc(FTextStream &t,const Definition *def) if (!brief.isEmpty()) { DocNode *root = validatingParseDoc(def->briefFile(),def->briefLine(), - def,0,brief,FALSE,FALSE,0,TRUE,TRUE); + def,0,brief,FALSE,FALSE, + 0,TRUE,TRUE,Config_getBool(MARKDOWN_SUPPORT)); QCString relPath = relativePathToRoot(def->getOutputFileBase()); HtmlCodeGenerator htmlGen(t,relPath); HtmlDocVisitor *visitor = new HtmlDocVisitor(t,htmlGen,def); diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 3b4d537..e4cb180 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -834,7 +834,8 @@ void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title // repeat brief description if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // write separator between brief and details if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && @@ -854,13 +855,15 @@ void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title // write detailed documentation if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // write inbody documentation if (!inbodyDocumentation().isEmpty()) { - ol.generateDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE); + ol.generateDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } } @@ -870,7 +873,8 @@ void GroupDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startParagraph(); @@ -944,7 +948,8 @@ void GroupDefImpl::writeFiles(OutputList &ol,const QCString &title) if (!fd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(fd->getOutputFileBase()); - ol.generateDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); @@ -999,7 +1004,8 @@ void GroupDefImpl::writeNestedGroups(OutputList &ol,const QCString &title) if (!gd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(gd->getOutputFileBase()); - ol.generateDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); @@ -1030,7 +1036,8 @@ void GroupDefImpl::writeDirs(OutputList &ol,const QCString &title) if (!dd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(dd->getOutputFileBase()); - ol.generateDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); @@ -1068,7 +1075,8 @@ void GroupDefImpl::writePageDocumentation(OutputList &ol) ol.endSection(si->label(),SectionType::Subsection); } ol.startTextBlock(); - ol.generateDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE,0,TRUE,FALSE); + ol.generateDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endTextBlock(); } } diff --git a/src/growbuf.h b/src/growbuf.h index cd6a67b..2f8075b 100644 --- a/src/growbuf.h +++ b/src/growbuf.h @@ -13,6 +13,7 @@ class GrowBuf GrowBuf() : m_str(0), m_pos(0), m_len(0) {} GrowBuf(uint initialSize) : m_pos(0), m_len(initialSize) { m_str=(char*)malloc(m_len); } ~GrowBuf() { free(m_str); } + void reserve(uint size) { if (m_len<size) { m_len = size; m_str = (char*)realloc(m_str,m_len); } } void clear() { m_pos=0; } void addChar(char c) { if (m_pos>=m_len) { m_len+=GROW_AMOUNT; m_str = (char*)realloc(m_str,m_len); } m_str[m_pos++]=c; diff --git a/src/index.cpp b/src/index.cpp index 04d6ce4..12f35f2 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -1396,7 +1396,8 @@ static void writeSingleFileIndex(OutputList &ol,FileDef *fd) FALSE, // isExample 0, // example name TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); //ol.docify(")"); } @@ -1768,7 +1769,8 @@ static void writeNamespaceIndex(OutputList &ol) FALSE, // isExample 0, // example name TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); //ol.docify(")"); } @@ -1902,7 +1904,8 @@ static void writeAnnotatedClassList(OutputList &ol,ClassDef::CompoundType ct) FALSE, // isExample 0, // example name TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); } ol.endIndexValue(cd->getOutputFileBase(),hasBrief); @@ -3932,7 +3935,8 @@ void writeGraphInfo(OutputList &ol) //printf("legendDocs=%s\n",legendDocs.data()); } FileDef *fd = createFileDef("","graph_legend.dox"); - ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE); + ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE, + 0,FALSE,FALSE,FALSE); delete fd; // restore config settings @@ -4496,8 +4500,8 @@ static void writeIndex(OutputList &ol) ol.startHeaderSection(); ol.startTitleHead(0); ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->docLine(), - Doxygen::mainPage,0,Doxygen::mainPage->title(), - TRUE,FALSE,0,TRUE,FALSE); + Doxygen::mainPage,0,Doxygen::mainPage->title(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); headerWritten = TRUE; } } @@ -4533,7 +4537,8 @@ static void writeIndex(OutputList &ol) ol.startTextBlock(); ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0, - Doxygen::mainPage->documentation(),TRUE,FALSE); + Doxygen::mainPage->documentation(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endTextBlock(); ol.endPageDoc(); @@ -4570,7 +4575,8 @@ static void writeIndex(OutputList &ol) if (!Config_getString(PROJECT_NUMBER).isEmpty()) { ol.startProjectNumber(); - ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0,Config_getString(PROJECT_NUMBER),FALSE,FALSE); + ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0,Config_getString(PROJECT_NUMBER),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endProjectNumber(); } ol.endIndexSection(isTitlePageStart); @@ -4783,7 +4789,8 @@ static void writeIndex(OutputList &ol) ol.startContents(); ol.startTextBlock(); ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0, - Doxygen::mainPage->documentation(),FALSE,FALSE + Doxygen::mainPage->documentation(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT) ); ol.endTextBlock(); endFile(ol); diff --git a/src/markdown.cpp b/src/markdown.cpp index 06b714a..2cf4e0a 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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 @@ -35,11 +35,9 @@ #include <qglobal.h> #include <qregexp.h> #include <qfileinfo.h> -#include <qdict.h> -#include <qvector.h> -//#define USE_ORIGINAL_TABLES -#include <atomic> +#include <unordered_map> +#include <functional> #include "markdown.h" #include "growbuf.h" @@ -48,7 +46,6 @@ #include "doxygen.h" #include "commentscan.h" #include "entry.h" -#include "bufstr.h" #include "commentcnv.h" #include "config.h" #include "section.h" @@ -84,13 +81,6 @@ //---------- -struct LinkRef -{ - LinkRef(const QCString &l,const QCString &t) : link(l), title(t) {} - QCString link; - QCString title; -}; - struct TableCell { TableCell() : colSpan(false) {} @@ -98,26 +88,35 @@ struct TableCell bool colSpan; }; -typedef int (*action_t)(GrowBuf &out,const char *data,int offset,int size); +Markdown::Markdown(const char *fileName,int lineNr,int indentLevel) + : m_fileName(fileName), m_lineNr(lineNr), m_indentLevel(indentLevel) +{ + using namespace std::placeholders; + // setup callback table for special characters + m_actions[(unsigned int)'_'] = std::bind(&Markdown::processEmphasis, this,_1,_2,_3); + m_actions[(unsigned int)'*'] = std::bind(&Markdown::processEmphasis, this,_1,_2,_3); + m_actions[(unsigned int)'~'] = std::bind(&Markdown::processEmphasis, this,_1,_2,_3); + m_actions[(unsigned int)'`'] = std::bind(&Markdown::processCodeSpan, this,_1,_2,_3); + m_actions[(unsigned int)'\\']= std::bind(&Markdown::processSpecialCommand,this,_1,_2,_3); + m_actions[(unsigned int)'@'] = std::bind(&Markdown::processSpecialCommand,this,_1,_2,_3); + m_actions[(unsigned int)'['] = std::bind(&Markdown::processLink, this,_1,_2,_3); + m_actions[(unsigned int)'!'] = std::bind(&Markdown::processLink, this,_1,_2,_3); + m_actions[(unsigned int)'<'] = std::bind(&Markdown::processHtmlTag, this,_1,_2,_3); + m_actions[(unsigned int)'-'] = std::bind(&Markdown::processNmdash, this,_1,_2,_3); + m_actions[(unsigned int)'"'] = std::bind(&Markdown::processQuoted, this,_1,_2,_3); + (void)m_lineNr; // not used yet +} enum Alignment { AlignNone, AlignLeft, AlignCenter, AlignRight }; -//---------- - -static QDict<LinkRef> g_linkRefs(257); -static action_t g_actions[256]; -static Entry *g_current; -static QCString g_fileName; -static int g_lineNr; -static int g_indentLevel=0; // 0 is outside markdown, -1=page level -static const uchar g_utf8_nbsp[3] = { 0xc2, 0xa0, 0}; // UTF-8 nbsp -static const char *g_doxy_nsbp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp -//---------- - +//---------- contants ------- +// +const uchar g_utf8_nbsp[3] = { 0xc2, 0xa0, 0}; // UTF-8 nbsp +const char *g_doxy_nsbp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp const int codeBlockIndent = 4; -static void processInline(GrowBuf &out,const char *data,int size); +//---------- helpers ------- // escape characters that have a special meaning later on. static QCString escapeSpecialChars(const QCString &s) @@ -196,7 +195,7 @@ static Alignment markersToAlignment(bool leftMarker,bool rightMarker) // \xmlonly..\endxmlonly // \rtfonly..\endrtfonly // \manonly..\endmanonly -static QCString isBlockCommand(const char *data,int offset,int size) +QCString Markdown::isBlockCommand(const char *data,int offset,int size) { bool openBracket = offset>0 && data[-1]=='{'; bool isEscaped = offset>0 && (data[-1]=='\\' || data[-1]=='@'); @@ -250,7 +249,7 @@ static QCString isBlockCommand(const char *data,int offset,int size) /** looks for the next emph char, skipping other constructs, and * stopping when either it is found, or we are at the end of a paragraph. */ -static int findEmphasisChar(const char *data, int size, char c, int c_size) +int Markdown::findEmphasisChar(const char *data, int size, char c, int c_size) { int i = 1; @@ -348,7 +347,7 @@ static int findEmphasisChar(const char *data, int size, char c, int c_size) } /** process single emphasis */ -static int processEmphasis1(GrowBuf &out, const char *data, int size, char c) +int Markdown::processEmphasis1(const char *data, int size, char c) { int i = 0, len; @@ -369,9 +368,9 @@ static int processEmphasis1(GrowBuf &out, const char *data, int size, char c) } if (data[i]==c && data[i-1]!=' ' && data[i-1]!='\n') { - out.addStr("<em>"); - processInline(out,data,i); - out.addStr("</em>"); + m_out.addStr("<em>"); + processInline(data,i); + m_out.addStr("</em>"); return i+1; } } @@ -379,7 +378,7 @@ static int processEmphasis1(GrowBuf &out, const char *data, int size, char c) } /** process double emphasis */ -static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) +int Markdown::processEmphasis2(const char *data, int size, char c) { int i = 0, len; @@ -395,11 +394,11 @@ static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) data[i-1]!='\n' ) { - if (c == '~') out.addStr("<strike>"); - else out.addStr("<strong>"); - processInline(out,data,i); - if (c == '~') out.addStr("</strike>"); - else out.addStr("</strong>"); + if (c == '~') m_out.addStr("<strike>"); + else m_out.addStr("<strong>"); + processInline(data,i); + if (c == '~') m_out.addStr("</strike>"); + else m_out.addStr("</strong>"); return i + 2; } i++; @@ -410,7 +409,7 @@ static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) /** Parsing triple emphasis. * Finds the first closing tag, and delegates to the other emph */ -static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) +int Markdown::processEmphasis3(const char *data, int size, char c) { int i = 0, len; @@ -431,15 +430,15 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) if (i+2<size && data[i+1]==c && data[i+2]==c) { - out.addStr("<em><strong>"); - processInline(out,data,i); - out.addStr("</strong></em>"); + m_out.addStr("<em><strong>"); + processInline(data,i); + m_out.addStr("</strong></em>"); return i+3; } else if (i+1<size && data[i+1]==c) { // double symbol found, handing over to emph1 - len = processEmphasis1(out, data-2, size+2, c); + len = processEmphasis1(data-2, size+2, c); if (len==0) { return 0; @@ -452,7 +451,7 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) else { // single symbol found, handing over to emph2 - len = processEmphasis2(out, data-1, size+1, c); + len = processEmphasis2(data-1, size+1, c); if (len==0) { return 0; @@ -467,7 +466,7 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) } /** Process ndash and mdashes */ -static int processNmdash(GrowBuf &out,const char *data,int off,int size) +int Markdown::processNmdash(const char *data,int off,int size) { // precondition: data[0]=='-' int i=1; @@ -488,12 +487,12 @@ static int processNmdash(GrowBuf &out,const char *data,int off,int size) if (count==2 && (data[2]=='>')) return 0; // end HTML comment if (count==2 && (off<8 || qstrncmp(data-8,"operator",8)!=0)) // -- => ndash { - out.addStr("–"); + m_out.addStr("–"); return 2; } else if (count==3) // --- => ndash { - out.addStr("—"); + m_out.addStr("—"); return 3; } // not an ndash or mdash @@ -501,7 +500,7 @@ static int processNmdash(GrowBuf &out,const char *data,int off,int size) } /** Process quoted section "...", can contain one embedded newline */ -static int processQuoted(GrowBuf &out,const char *data,int,int size) +int Markdown::processQuoted(const char *data,int,int size) { int i=1; int nl=0; @@ -512,7 +511,7 @@ static int processQuoted(GrowBuf &out,const char *data,int,int size) } if (i<size && data[i]=='"' && nl<2) { - out.addStr(data,i+1); + m_out.addStr(data,i+1); return i+1; } // not a quoted section @@ -522,7 +521,7 @@ static int processQuoted(GrowBuf &out,const char *data,int,int size) /** Process a HTML tag. Note that <pre>..</pre> are treated specially, in * the sense that all code inside is written unprocessed */ -static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size,bool doWrite) +int Markdown::processHtmlTagWrite(const char *data,int offset,int size,bool doWrite) { if (offset>0 && data[-1]=='\\') return 0; // escaped < @@ -545,7 +544,7 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size tolower(data[i+2])=='p' && tolower(data[i+3])=='r' && tolower(data[i+4])=='e' && tolower(data[i+5])=='>') { // found </pre> tag, copy from start to end of tag - if (doWrite) out.addStr(data,i+6); + if (doWrite) m_out.addStr(data,i+6); //printf("found <pre>..</pre> [%d..%d]\n",0,i+6); return i+6; } @@ -568,13 +567,13 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size if (data[i]=='/' && i<size-1 && data[i+1]=='>') // <bla/> { //printf("Found htmlTag={%s}\n",QCString(data).left(i+2).data()); - if (doWrite) out.addStr(data,i+2); + if (doWrite) m_out.addStr(data,i+2); return i+2; } else if (data[i]=='>') // <bla> { //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data()); - if (doWrite) out.addStr(data,i+1); + if (doWrite) m_out.addStr(data,i+1); return i+1; } else if (data[i]==' ') // <bla attr=... @@ -594,7 +593,7 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size else if (!insideAttr && data[i]=='>') // found end of tag { //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data()); - if (doWrite) out.addStr(data,i+1); + if (doWrite) m_out.addStr(data,i+1); return i+1; } i++; @@ -605,12 +604,13 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size //printf("Not a valid html tag\n"); return 0; } -static int processHtmlTag(GrowBuf &out,const char *data,int offset,int size) + +int Markdown::processHtmlTag(const char *data,int offset,int size) { - return processHtmlTagWrite(out,data,offset,size,true); + return processHtmlTagWrite(data,offset,size,true); } -static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) +int Markdown::processEmphasis(const char *data,int offset,int size) { if ((offset>0 && !isOpenEmphChar(-1)) || // invalid char before * or _ (size>1 && data[0]!=data[1] && !(isIdChar(1) || extraChar(1) || data[1]=='[')) || // invalid char after * or _ @@ -625,7 +625,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) { // whitespace cannot follow an opening emphasis if (data[1]==' ' || data[1]=='\n' || - (ret = processEmphasis1(out, data+1, size-1, c)) == 0) + (ret = processEmphasis1(data+1, size-1, c)) == 0) { return 0; } @@ -634,7 +634,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) if (size>3 && data[1]==c && data[2]!=c) // __bla or **bla { if (data[2]==' ' || data[2]=='\n' || - (ret = processEmphasis2(out, data+2, size-2, c)) == 0) + (ret = processEmphasis2(data+2, size-2, c)) == 0) { return 0; } @@ -643,7 +643,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) if (size>4 && c!='~' && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla { if (data[3]==' ' || data[3]=='\n' || - (ret = processEmphasis3(out, data+3, size-3, c)) == 0) + (ret = processEmphasis3(data+3, size-3, c)) == 0) { return 0; } @@ -652,28 +652,30 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) return 0; } -static void writeMarkdownImage(GrowBuf &out, const char *fmt, bool explicitTitle, QCString title, QCString content, QCString link, FileDef *fd) +void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle, + const QCString &title, const QCString &content, + const QCString &link, const FileDef *fd) { - out.addStr("@image{inline} "); - out.addStr(fmt); - out.addStr(" "); - out.addStr(link.mid(fd ? 0 : 5)); + m_out.addStr("@image{inline} "); + m_out.addStr(fmt); + m_out.addStr(" "); + m_out.addStr(link.mid(fd ? 0 : 5)); if (!explicitTitle && !content.isEmpty()) { - out.addStr(" \""); - out.addStr(content); - out.addStr("\""); + m_out.addStr(" \""); + m_out.addStr(content); + m_out.addStr("\""); } else if ((content.isEmpty() || explicitTitle) && !title.isEmpty()) { - out.addStr(" \""); - out.addStr(title); - out.addStr("\""); + m_out.addStr(" \""); + m_out.addStr(title); + m_out.addStr("\""); } - out.addStr("\n"); + m_out.addStr("\n"); } -static int processLink(GrowBuf &out,const char *data,int,int size) +int Markdown::processLink(const char *data,int,int size) { QCString content; QCString link; @@ -828,11 +830,12 @@ static int processLink(GrowBuf &out,const char *data,int,int size) link=content; } // lookup reference - LinkRef *lr = g_linkRefs.find(link.lower()); - if (lr) // found it + QCString link_lower = link.lower(); + auto lr_it=m_linkRefs.find(link_lower.str()); + if (lr_it!=m_linkRefs.end()) // found it { - link = lr->link; - title = lr->title; + link = lr_it->second.link; + title = lr_it->second.title; //printf("processLink: ref: link={%s} title={%s}\n",link.data(),title.data()); } else // reference not found! @@ -844,12 +847,13 @@ static int processLink(GrowBuf &out,const char *data,int,int size) } else if (i<size && data[i]!=':' && !content.isEmpty()) // minimal link ref notation [some id] { - LinkRef *lr = g_linkRefs.find(content.lower()); + QCString content_lower = content.lower(); + auto lr_it = m_linkRefs.find(content_lower.str()); //printf("processLink: minimal link {%s} lr=%p",content.data(),lr); - if (lr) // found it + if (lr_it!=m_linkRefs.end()) // found it { - link = lr->link; - title = lr->title; + link = lr_it->second.link; + title = lr_it->second.title; explicitTitle=TRUE; i=contentEnd; } @@ -873,9 +877,9 @@ static int processLink(GrowBuf &out,const char *data,int,int size) int toc_level = Config_getInt(TOC_INCLUDE_HEADINGS); if (toc_level > 0 && toc_level <=5) { - out.addStr("@tableofcontents{html:"); - out.addStr(QCString().setNum(toc_level)); - out.addStr("}"); + m_out.addStr("@tableofcontents{html:"); + m_out.addStr(QCString().setNum(toc_level)); + m_out.addStr("}"); } } else if (isImageLink) @@ -886,25 +890,25 @@ static int processLink(GrowBuf &out,const char *data,int,int size) (fd=findFileDef(Doxygen::imageNameLinkedMap,link,ambig))) // assume doxygen symbol link or local image link { - writeMarkdownImage(out, "html", explicitTitle, title, content, link, fd); - writeMarkdownImage(out, "latex", explicitTitle, title, content, link, fd); - writeMarkdownImage(out, "rtf", explicitTitle, title, content, link, fd); - writeMarkdownImage(out, "docbook", explicitTitle, title, content, link, fd); + writeMarkdownImage("html", explicitTitle, title, content, link, fd); + writeMarkdownImage("latex", explicitTitle, title, content, link, fd); + writeMarkdownImage("rtf", explicitTitle, title, content, link, fd); + writeMarkdownImage("docbook", explicitTitle, title, content, link, fd); } else { - out.addStr("<img src=\""); - out.addStr(link); - out.addStr("\" alt=\""); - out.addStr(content); - out.addStr("\""); + m_out.addStr("<img src=\""); + m_out.addStr(link); + m_out.addStr("\" alt=\""); + m_out.addStr(content); + m_out.addStr("\""); if (!title.isEmpty()) { - out.addStr(" title=\""); - out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); - out.addStr("\""); + m_out.addStr(" title=\""); + m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); + m_out.addStr("\""); } - out.addStr("/>"); + m_out.addStr("/>"); } } else @@ -916,14 +920,14 @@ static int processLink(GrowBuf &out,const char *data,int,int size) { if (lp==-1) // link to markdown page { - out.addStr("@ref "); + m_out.addStr("@ref "); if (!(Portable::isAbsolutePath(link) || isURL(link))) { QFileInfo forg(link); if (!(forg.exists() && forg.isReadable())) { - QFileInfo fi(g_fileName); - QCString mdFile = g_fileName.left(g_fileName.length()-fi.fileName().length()) + link; + QFileInfo fi(m_fileName); + QCString mdFile = m_fileName.left(m_fileName.length()-fi.fileName().length()) + link; QFileInfo fmd(mdFile); if (fmd.exists() && fmd.isReadable()) { @@ -932,33 +936,33 @@ static int processLink(GrowBuf &out,const char *data,int,int size) } } } - out.addStr(link); - out.addStr(" \""); + m_out.addStr(link); + m_out.addStr(" \""); if (explicitTitle && !title.isEmpty()) { - out.addStr(title); + m_out.addStr(title); } else { - out.addStr(content); + m_out.addStr(content); } - out.addStr("\""); + m_out.addStr("\""); } else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1) { // file/url link - out.addStr("<a href=\""); - out.addStr(link); - out.addStr("\""); + m_out.addStr("<a href=\""); + m_out.addStr(link); + m_out.addStr("\""); if (!title.isEmpty()) { - out.addStr(" title=\""); - out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); - out.addStr("\""); + m_out.addStr(" title=\""); + m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); + m_out.addStr("\""); } - out.addStr(">"); + m_out.addStr(">"); content = content.simplifyWhiteSpace(); - processInline(out,content,content.length()); - out.addStr("</a>"); + processInline(content,content.length()); + m_out.addStr("</a>"); } else // avoid link to e.g. F[x](y) { @@ -970,7 +974,7 @@ static int processLink(GrowBuf &out,const char *data,int,int size) } /** '`' parsing a code span (assuming codespan != 0) */ -static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int size) +int Markdown::processCodeSpan(const char *data, int /*offset*/, int size) { int end, nb = 0, i, f_begin, f_end; @@ -998,9 +1002,9 @@ static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int s { // look for quoted strings like 'some word', but skip strings like `it's cool` QCString textFragment; convertStringFragment(textFragment,data+nb,end-nb); - out.addStr("‘"); - out.addStr(textFragment); - out.addStr("’"); + m_out.addStr("‘"); + m_out.addStr(textFragment); + m_out.addStr("’"); return end+1; } else @@ -1036,27 +1040,27 @@ static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int s { QCString codeFragment; convertStringFragment(codeFragment,data+f_begin,f_end-f_begin); - out.addStr("<tt>"); - //out.addStr(convertToHtml(codeFragment,TRUE)); - out.addStr(escapeSpecialChars(codeFragment)); - out.addStr("</tt>"); + m_out.addStr("<tt>"); + //m_out.addStr(convertToHtml(codeFragment,TRUE)); + m_out.addStr(escapeSpecialChars(codeFragment)); + m_out.addStr("</tt>"); } return end; } -static void addStrEscapeUtf8Nbsp(GrowBuf &out,const char *s,int len) +void Markdown::addStrEscapeUtf8Nbsp(const char *s,int len) { if (Portable::strnstr(s,g_doxy_nsbp,len)==0) // no escape needed -> fast { - out.addStr(s,len); + m_out.addStr(s,len); } else // escape needed -> slow { - out.addStr(substitute(QCString(s).left(len),g_doxy_nsbp,(const char *)g_utf8_nbsp)); + m_out.addStr(substitute(QCString(s).left(len),g_doxy_nsbp,(const char *)g_utf8_nbsp)); } } -static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int size) +int Markdown::processSpecialCommand(const char *data, int offset, int size) { int i=1; QCString endBlockName = isBlockCommand(data,offset,size); @@ -1071,7 +1075,7 @@ static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int if (qstrncmp(&data[i+1],endBlockName,l)==0) { //printf("found end at %d\n",i); - addStrEscapeUtf8Nbsp(out,data,i+1+l); + addStrEscapeUtf8Nbsp(data,i+1+l); return i+1+l; } } @@ -1083,34 +1087,34 @@ static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int char c=data[1]; if (c=='[' || c==']' || c=='*' || c=='!' || c=='(' || c==')' || c=='`' || c=='_') { - out.addChar(data[1]); + m_out.addChar(data[1]); return 2; } else if (c=='-' && size>3 && data[2]=='-' && data[3]=='-') // \--- { - out.addStr(&data[1],3); + m_out.addStr(&data[1],3); return 4; } else if (c=='-' && size>2 && data[2]=='-') // \-- { - out.addStr(&data[1],2); + m_out.addStr(&data[1],2); return 3; } } return 0; } -static void processInline(GrowBuf &out,const char *data,int size) +void Markdown::processInline(const char *data,int size) { int i=0, end=0; - action_t action = 0; + Action_t action; while (i<size) { - while (end<size && ((action=g_actions[(uchar)data[end]])==0)) end++; - out.addStr(data+i,end-i); + while (end<size && ((action=m_actions[(uchar)data[end]])==0)) end++; + m_out.addStr(data+i,end-i); if (end>=size) break; i=end; - end = action(out,data+i,i,size-i); + end = action(data+i,i,size-i); if (end<=0) { end=i+1-end; @@ -1124,7 +1128,7 @@ static void processInline(GrowBuf &out,const char *data,int size) } /** returns whether the line is a setext-style hdr underline */ -static int isHeaderline(const char *data, int size, bool allowAdjustLevel) +int Markdown::isHeaderline(const char *data, int size, bool allowAdjustLevel) { int i=0, c=0; while (i<size && data[i]==' ') i++; @@ -1135,29 +1139,29 @@ static int isHeaderline(const char *data, int size, bool allowAdjustLevel) while (i<size && data[i]=='=') i++,c++; while (i<size && data[i]==' ') i++; int level = (c>1 && (i>=size || data[i]=='\n')) ? 1 : 0; - if (allowAdjustLevel && level==1 && g_indentLevel==-1) + if (allowAdjustLevel && level==1 && m_indentLevel==-1) { // In case a page starts with a header line we use it as title, promoting it to @page. // We set g_indentLevel to -1 to promoting the other sections if they have a deeper // nesting level than the page header, i.e. @section..@subsection becomes @page..@section. // In case a section at the same level is found (@section..@section) however we need // to undo this (and the result will be @page..@section). - g_indentLevel=0; + m_indentLevel=0; } - return g_indentLevel+level; + return m_indentLevel+level; } // test of level 2 header if (data[i]=='-') { while (i<size && data[i]=='-') i++,c++; while (i<size && data[i]==' ') i++; - return (c>1 && (i>=size || data[i]=='\n')) ? g_indentLevel+2 : 0; + return (c>1 && (i>=size || data[i]=='\n')) ? m_indentLevel+2 : 0; } return 0; } /** returns TRUE if this line starts a block quote */ -static bool isBlockQuote(const char *data,int size,int indent) +bool isBlockQuote(const char *data,int size,int indent) { int i = 0; while (i<size && data[i]==' ') i++; @@ -1325,7 +1329,7 @@ static QCString extractTitleId(QCString &title, int level) } -static int isAtxHeader(const char *data,int size, +int Markdown::isAtxHeader(const char *data,int size, QCString &header,QCString &id,bool allowAdjustLevel) { int i = 0, end; @@ -1359,7 +1363,7 @@ static int isAtxHeader(const char *data,int size, header=header.left(i+1); } - if (allowAdjustLevel && level==1 && g_indentLevel==-1) + if (allowAdjustLevel && level==1 && m_indentLevel==-1) { // in case we find a `# Section` on a markdown page that started with the same level // header, we no longer need to artificially decrease the paragraph level. @@ -1379,9 +1383,9 @@ static int isAtxHeader(const char *data,int size, // @section autotoc_md1 Heading 2 // ------------------- - g_indentLevel=0; + m_indentLevel=0; } - return level+g_indentLevel; + return level+m_indentLevel; } static int isEmptyLine(const char *data,int size) @@ -1666,7 +1670,7 @@ static bool isTableBlock(const char *data,int size) return cc1==cc2; } -static int writeTableBlock(GrowBuf &out,const char *data,int size) +int Markdown::writeTableBlock(const char *data,int size) { int i=0,j,k; int columns,start,end,cc; @@ -1676,17 +1680,10 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) int headerStart = start; int headerEnd = end; -#ifdef USE_ORIGINAL_TABLES - out.addStr("<table>"); - - // write table header, in range [start..end] - out.addStr("<tr>"); -#endif - // read cell alignments int ret = findTableColumns(data+i,size-i,start,end,cc); k=0; - Alignment *columnAlignment = new Alignment[columns]; + std::vector<int> columnAlignment(columns); bool leftMarker=FALSE,rightMarker=FALSE; bool startFound=FALSE; @@ -1723,100 +1720,27 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) // proceed to next line i+=ret; -#ifdef USE_ORIGINAL_TABLES - - int m=headerStart; - for (k=0;k<columns;k++) - { - out.addStr("<th"); - switch (columnAlignment[k]) - { - case AlignLeft: out.addStr(" align=\"left\""); break; - case AlignRight: out.addStr(" align=\"right\""); break; - case AlignCenter: out.addStr(" align=\"center\""); break; - case AlignNone: break; - } - out.addStr(">"); - while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\'))) - { - out.addChar(data[m++]); - } - m++; - } - out.addStr("\n</th>\n"); - - // write table cells - while (i<size) - { - int ret = findTableColumns(data+i,size-i,start,end,cc); - //printf("findTableColumns cc=%d\n",cc); - if (cc!=columns) break; // end of table - - out.addStr("<tr>"); - j=start+i; - int columnStart=j; - k=0; - while (j<=end+i) - { - if (j==columnStart) - { - out.addStr("<td"); - switch (columnAlignment[k]) - { - case AlignLeft: out.addStr(" align=\"left\""); break; - case AlignRight: out.addStr(" align=\"right\""); break; - case AlignCenter: out.addStr(" align=\"center\""); break; - case AlignNone: break; - } - out.addStr(">"); - } - if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) - { - columnStart=j+1; - k++; - } - else - { - out.addChar(data[j]); - } - j++; - } - out.addChar('\n'); - - // proceed to next line - i+=ret; - } - - out.addStr("</table> "); -#else // Store the table cell information by row then column. This // allows us to handle row spanning. - QVector<QVector<TableCell> > tableContents; - tableContents.setAutoDelete(TRUE); + std::vector<std::vector<TableCell> > tableContents; int m=headerStart; - QVector<TableCell> *headerContents = new QVector<TableCell>(columns); - headerContents->setAutoDelete(TRUE); + std::vector<TableCell> headerContents(columns); for (k=0;k<columns;k++) { - headerContents->insert(k, new TableCell); while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\'))) { - headerContents->at(k)->cellText += data[m++]; + headerContents[k].cellText += data[m++]; } m++; // do the column span test before stripping white space // || is spanning columns, | | is not - headerContents->at(k)->colSpan = headerContents->at(k)->cellText.isEmpty(); - headerContents->at(k)->cellText = headerContents->at(k)->cellText.stripWhiteSpace(); + headerContents[k].colSpan = headerContents[k].cellText.isEmpty(); + headerContents[k].cellText = headerContents[k].cellText.stripWhiteSpace(); } - // qvector doesn't have an append like std::vector, so we gotta do - // extra work - tableContents.resize(1); - tableContents.insert(0, headerContents); + tableContents.push_back(headerContents); // write table cells - int rowNum = 1; while (i<size) { ret = findTableColumns(data+i,size-i,start,end,cc); @@ -1824,41 +1748,34 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) j=start+i; k=0; - QVector<TableCell> *rowContents = new QVector<TableCell>(columns); - rowContents->setAutoDelete(TRUE); - rowContents->insert(k, new TableCell); + std::vector<TableCell> rowContents(columns); while (j<=end+i) { if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) { // do the column span test before stripping white space // || is spanning columns, | | is not - rowContents->at(k)->colSpan = rowContents->at(k)->cellText.isEmpty(); - rowContents->at(k)->cellText = rowContents->at(k)->cellText.stripWhiteSpace(); + rowContents[k].colSpan = rowContents[k].cellText.isEmpty(); + rowContents[k].cellText = rowContents[k].cellText.stripWhiteSpace(); k++; - rowContents->insert(k, new TableCell); } // if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) else { - rowContents->at(k)->cellText += data[j]; + rowContents[k].cellText += data[j]; } // else { if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) } j++; } // while (j<=end+i) // do the column span test before stripping white space // || is spanning columns, | | is not - rowContents->at(k)->colSpan = rowContents->at(k)->cellText.isEmpty(); - rowContents->at(k)->cellText = rowContents->at(k)->cellText.stripWhiteSpace(); - // qvector doesn't have an append like std::vector, so we gotta do - // extra work - tableContents.resize(tableContents.size()+1); - tableContents.insert(rowNum++, rowContents); + rowContents[k].colSpan = rowContents[k].cellText.isEmpty(); + rowContents[k].cellText = rowContents[k].cellText.stripWhiteSpace(); + tableContents.push_back(rowContents); // proceed to next line i+=ret; } - - out.addStr("<table class=\"markdownTable\">"); + m_out.addStr("<table class=\"markdownTable\">"); QCString cellTag("th"), cellClass("class=\"markdownTableHead"); for (unsigned row = 0; row < tableContents.size(); row++) { @@ -1866,58 +1783,57 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) { if (row % 2) { - out.addStr("<tr class=\"markdownTableRowOdd\">"); + m_out.addStr("<tr class=\"markdownTableRowOdd\">"); } else { - out.addStr("<tr class=\"markdownTableRowEven\">"); + m_out.addStr("<tr class=\"markdownTableRowEven\">"); } } else { - out.addStr(" <tr class=\"markdownTableHead\">"); + m_out.addStr(" <tr class=\"markdownTableHead\">"); } for (int c = 0; c < columns; c++) { // save the cell text for use after column span computation - QCString cellText(tableContents[row]->at(c)->cellText); + QCString cellText(tableContents[row][c].cellText); // Row span handling. Spanning rows will contain a caret ('^'). // If the current cell contains just a caret, this is part of an // earlier row's span and the cell should not be added to the // output. - if (tableContents[row]->at(c)->cellText == "^") + if (tableContents[row][c].cellText == "^") continue; unsigned rowSpan = 1, spanRow = row+1; while ((spanRow < tableContents.size()) && - (tableContents[spanRow]->at(c)->cellText == "^")) + (tableContents[spanRow][c].cellText == "^")) { spanRow++; rowSpan++; } - out.addStr(" <" + cellTag + " " + cellClass); + m_out.addStr(" <" + cellTag + " " + cellClass); // use appropriate alignment style switch (columnAlignment[c]) { - case AlignLeft: out.addStr("Left\""); break; - case AlignRight: out.addStr("Right\""); break; - case AlignCenter: out.addStr("Center\""); break; - case AlignNone: out.addStr("None\""); break; + case AlignLeft: m_out.addStr("Left\""); break; + case AlignRight: m_out.addStr("Right\""); break; + case AlignCenter: m_out.addStr("Center\""); break; + case AlignNone: m_out.addStr("None\""); break; } if (rowSpan > 1) { QCString spanStr; spanStr.setNum(rowSpan); - out.addStr(" rowspan=\"" + spanStr + "\""); + m_out.addStr(" rowspan=\"" + spanStr + "\""); } // Column span handling, assumes that column spans will have // empty strings, which would indicate the sequence "||", used // to signify spanning columns. unsigned colSpan = 1; - while ((c < columns-1) && - tableContents[row]->at(c+1)->colSpan) + while ((c < columns-1) && tableContents[row][c+1].colSpan) { c++; colSpan++; @@ -1926,20 +1842,18 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) { QCString spanStr; spanStr.setNum(colSpan); - out.addStr(" colspan=\"" + spanStr + "\""); + m_out.addStr(" colspan=\"" + spanStr + "\""); } // need at least one space on either side of the cell text in // order for doxygen to do other formatting - out.addStr("> " + cellText + "</" + cellTag + ">"); + m_out.addStr("> " + cellText + "</" + cellTag + ">"); } cellTag = "td"; cellClass = "class=\"markdownTableBody"; - out.addStr(" </tr>\n"); + m_out.addStr(" </tr>\n"); } - out.addStr("</table>\n"); -#endif + m_out.addStr("</table>\n"); - delete[] columnAlignment; return i; } @@ -1960,14 +1874,14 @@ static int hasLineBreak(const char *data,int size) } -void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size) +void Markdown::writeOneLineHeaderOrRuler(const char *data,int size) { int level; QCString header; QCString id; if (isHRuler(data,size)) { - out.addStr("\n<hr>\n"); + m_out.addStr("\n<hr>\n"); } else if ((level=isAtxHeader(data,size,header,id,TRUE))) { @@ -1976,43 +1890,43 @@ void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size) { switch(level) { - case 1: out.addStr("@section "); + case 1: m_out.addStr("@section "); break; - case 2: out.addStr("@subsection "); + case 2: m_out.addStr("@subsection "); break; - case 3: out.addStr("@subsubsection "); + case 3: m_out.addStr("@subsubsection "); break; - default: out.addStr("@paragraph "); + default: m_out.addStr("@paragraph "); break; } - out.addStr(id); - out.addStr(" "); - out.addStr(header); - out.addStr("\n"); + m_out.addStr(id); + m_out.addStr(" "); + m_out.addStr(header); + m_out.addStr("\n"); } else { if (!id.isEmpty()) { - out.addStr("\\anchor "+id+"\n"); + m_out.addStr("\\anchor "+id+"\n"); } hTag.sprintf("h%d",level); - out.addStr("<"+hTag+">"); - out.addStr(header); - out.addStr("</"+hTag+">\n"); + m_out.addStr("<"+hTag+">"); + m_out.addStr(header); + m_out.addStr("</"+hTag+">\n"); } } else // nothing interesting -> just output the line { - out.addStr(data,size); + m_out.addStr(data,size); if (hasLineBreak(data,size)) { - out.addStr("<br>\n"); + m_out.addStr("<br>\n"); } } } -static int writeBlockQuote(GrowBuf &out,const char *data,int size) +int Markdown::writeBlockQuote(const char *data,int size) { int l; int i=0; @@ -2043,36 +1957,36 @@ static int writeBlockQuote(GrowBuf &out,const char *data,int size) { for (l=curLevel;l<level;l++) { - out.addStr("<blockquote>\n"); + m_out.addStr("<blockquote>\n"); } } else if (level<curLevel) // quote level decreased => add end markers { for (l=level;l<curLevel;l++) { - out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>\n"); } } curLevel=level; if (level==0) break; // end of quote block // copy line without quotation marks - out.addStr(data+indent,end-indent); + m_out.addStr(data+indent,end-indent); // proceed with next line i=end; } // end of comment within blockquote => add end markers for (l=0;l<curLevel;l++) { - out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>\n"); } return i; } -static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) +int Markdown::writeCodeBlock(const char *data,int size,int refIndent) { int i=0,end; //printf("writeCodeBlock: data={%s}\n",QCString(data).left(size).data()); - out.addStr("@verbatim\n"); + m_out.addStr("@verbatim\n"); int emptyLines=0; while (i<size) { @@ -2094,11 +2008,11 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) while (emptyLines>0) // write skipped empty lines { // add empty line - out.addStr("\n"); + m_out.addStr("\n"); emptyLines--; } // add code line minus the indent - out.addStr(data+i+refIndent+codeBlockIndent,end-i-refIndent-codeBlockIndent); + m_out.addStr(data+i+refIndent+codeBlockIndent,end-i-refIndent-codeBlockIndent); i=end; } else // end of code block @@ -2106,11 +2020,11 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) break; } } - out.addStr("@endverbatim\n"); + m_out.addStr("@endverbatim\n"); while (emptyLines>0) // write skipped empty lines { // add empty line - out.addStr("\n"); + m_out.addStr("\n"); emptyLines--; } //printf("i=%d\n",i); @@ -2119,7 +2033,7 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) // start searching for the end of the line start at offset \a i // keeping track of possible blocks that need to be skipped. -static void findEndOfLine(GrowBuf &out,const char *data,int size, +void Markdown::findEndOfLine(const char *data,int size, int &pi,int&i,int &end) { // find end of the line @@ -2147,7 +2061,7 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size, if (qstrncmp(&data[end+1],endBlockName,l)==0) { // found end marker, skip over this block - //printf("feol.block out={%s}\n",QCString(data+i).left(end+l+1-i).data()); + //printf("feol.block m_out={%s}\n",QCString(data+i).left(end+l+1-i).data()); end = end + l + 2; break; } @@ -2163,7 +2077,7 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size, tolower(data[end+2])=='e' && data[end+3]=='>') // <pre> tag { // skip part until including </pre> - end = end + processHtmlTagWrite(out,data+end-1,end-1,size-end+1,false) + 2; + end = end + processHtmlTagWrite(data+end-1,end-1,size-end+1,false) + 2; break; } else @@ -2189,24 +2103,24 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size, //printf("findEndOfLine pi=%d i=%d end=%d {%s}\n",pi,i,end,QCString(data+i).left(end-i).data()); } -static void writeFencedCodeBlock(GrowBuf &out,const char *data,const char *lng, +void Markdown::writeFencedCodeBlock(const char *data,const char *lng, int blockStart,int blockEnd) { QCString lang = lng; if (!lang.isEmpty() && lang.at(0)=='.') lang=lang.mid(1); - out.addStr("@code"); + m_out.addStr("@code"); if (!lang.isEmpty()) { - out.addStr("{"+lang+"}"); + m_out.addStr("{"+lang+"}"); } - addStrEscapeUtf8Nbsp(out,data+blockStart,blockEnd-blockStart); - out.addStr("\n"); - out.addStr("@endcode\n"); + addStrEscapeUtf8Nbsp(data+blockStart,blockEnd-blockStart); + m_out.addStr("\n"); + m_out.addStr("@endcode\n"); } -static QCString processQuotations(const QCString &s,int refIndent) +QCString Markdown::processQuotations(const QCString &s,int refIndent) { - GrowBuf out; + m_out.clear(); const char *data = s.data(); int size = s.length(); int i=0,end=0,pi=-1; @@ -2214,14 +2128,14 @@ static QCString processQuotations(const QCString &s,int refIndent) QCString lang; while (i<size) { - findEndOfLine(out,data,size,pi,i,end); + findEndOfLine(data,size,pi,i,end); // line is now found at [i..end) if (pi!=-1) { if (isFencedCodeBlock(data+pi,size-pi,refIndent,lang,blockStart,blockEnd,blockOffset)) { - writeFencedCodeBlock(out,data+pi,lang,blockStart,blockEnd); + writeFencedCodeBlock(data+pi,lang,blockStart,blockEnd); i=pi+blockOffset; pi=-1; end=i+1; @@ -2229,15 +2143,15 @@ static QCString processQuotations(const QCString &s,int refIndent) } else if (isBlockQuote(data+pi,i-pi,refIndent)) { - i = pi+writeBlockQuote(out,data+pi,size-pi); + i = pi+writeBlockQuote(data+pi,size-pi); pi=-1; end=i+1; continue; } else { - //printf("quote out={%s}\n",QCString(data+pi).left(i-pi).data()); - out.addStr(data+pi,i-pi); + //printf("quote m_out={%s}\n",QCString(data+pi).left(i-pi).data()); + m_out.addStr(data+pi,i-pi); } } pi=i; @@ -2247,24 +2161,24 @@ static QCString processQuotations(const QCString &s,int refIndent) { if (isBlockQuote(data+pi,size-pi,refIndent)) { - writeBlockQuote(out,data+pi,size-pi); + writeBlockQuote(data+pi,size-pi); } else { - out.addStr(data+pi,size-pi); + m_out.addStr(data+pi,size-pi); } } - out.addChar(0); + m_out.addChar(0); //printf("Process quotations\n---- input ----\n%s\n---- output ----\n%s\n------------\n", - // s.data(),out.get()); + // s.data(),m_out.get()); - return out.get(); + return m_out.get(); } -static QCString processBlocks(const QCString &s,int indent) +QCString Markdown::processBlocks(const QCString &s,int indent) { - GrowBuf out; + m_out.clear(); const char *data = s.data(); int size = s.length(); int i=0,end=0,pi=-1,ref,level; @@ -2280,14 +2194,14 @@ static QCString processBlocks(const QCString &s,int indent) end++; } -#if 0 // commented out, since starting with a comment block is probably a usage error +#if 0 // commented m_out, since starting with a comment block is probably a usage error // see also http://stackoverflow.com/q/20478611/784672 // special case when the documentation starts with a code block // since the first line is skipped when looking for a code block later on. if (end>codeBlockIndent && isCodeBlock(data,0,end,blockIndent)) { - i=writeCodeBlock(out,data,size,blockIndent); + i=writeCodeBlock(m_out,data,size,blockIndent); end=i+1; pi=-1; } @@ -2296,7 +2210,7 @@ static QCString processBlocks(const QCString &s,int indent) // process each line while (i<size) { - findEndOfLine(out,data,size,pi,i,end); + findEndOfLine(data,size,pi,i,end); // line is now found at [i..end) //printf("findEndOfLine: pi=%d i=%d end=%d\n",pi,i,end); @@ -2319,22 +2233,22 @@ static QCString processBlocks(const QCString &s,int indent) { if (!id.isEmpty()) { - out.addStr(level==1?"@section ":"@subsection "); - out.addStr(id); - out.addStr(" "); - out.addStr(header); - out.addStr("\n\n"); + m_out.addStr(level==1?"@section ":"@subsection "); + m_out.addStr(id); + m_out.addStr(" "); + m_out.addStr(header); + m_out.addStr("\n\n"); } else { - out.addStr(level==1?"<h1>":"<h2>"); - out.addStr(header); - out.addStr(level==1?"\n</h1>\n":"\n</h2>\n"); + m_out.addStr(level==1?"<h1>":"<h2>"); + m_out.addStr(header); + m_out.addStr(level==1?"\n</h1>\n":"\n</h2>\n"); } } else { - out.addStr("\n<hr>\n"); + m_out.addStr("\n<hr>\n"); } pi=-1; i=end; @@ -2345,7 +2259,7 @@ static QCString processBlocks(const QCString &s,int indent) { //printf("found link ref: id='%s' link='%s' title='%s'\n", // id.data(),link.data(),title.data()); - g_linkRefs.insert(id.lower(),new LinkRef(link,title)); + m_linkRefs.insert({id.lower().str(),LinkRef(link,title)}); i=ref+pi; pi=-1; end=i+1; @@ -2354,7 +2268,7 @@ static QCString processBlocks(const QCString &s,int indent) { //printf("Found FencedCodeBlock lang='%s' start=%d end=%d code={%s}\n", // lang.data(),blockStart,blockEnd,QCString(data+pi+blockStart).left(blockEnd-blockStart).data()); - writeFencedCodeBlock(out,data+pi,lang,blockStart,blockEnd); + writeFencedCodeBlock(data+pi,lang,blockStart,blockEnd); i=pi+blockOffset; pi=-1; end=i+1; @@ -2363,21 +2277,21 @@ static QCString processBlocks(const QCString &s,int indent) else if (isCodeBlock(data+i,i,end-i,blockIndent)) { // skip previous line (it is empty anyway) - i+=writeCodeBlock(out,data+i,size-i,blockIndent); + i+=writeCodeBlock(data+i,size-i,blockIndent); pi=-1; end=i+1; continue; } else if (isTableBlock(data+pi,size-pi)) { - i=pi+writeTableBlock(out,data+pi,size-pi); + i=pi+writeTableBlock(data+pi,size-pi); pi=-1; end=i+1; continue; } else { - writeOneLineHeaderOrRuler(out,data+pi,i-pi); + writeOneLineHeaderOrRuler(data+pi,i-pi); } } pi=i; @@ -2390,16 +2304,16 @@ static QCString processBlocks(const QCString &s,int indent) { //printf("found link ref: id='%s' link='%s' title='%s'\n", // id.data(),link.data(),title.data()); - g_linkRefs.insert(id.lower(),new LinkRef(link,title)); + m_linkRefs.insert({id.lower().str(),LinkRef(link,title)}); } else { - writeOneLineHeaderOrRuler(out,data+pi,size-pi); + writeOneLineHeaderOrRuler(data+pi,size-pi); } } - out.addChar(0); - return out.get(); + m_out.addChar(0); + return m_out.get(); } /** returns TRUE if input string docs starts with \@page or \@mainpage command */ @@ -2425,7 +2339,7 @@ static bool isExplicitPage(const QCString &docs) return FALSE; } -static QCString extractPageTitle(QCString &docs,QCString &id) +QCString Markdown::extractPageTitle(QCString &docs,QCString &id) { int ln=0; // first first non-empty line @@ -2472,11 +2386,12 @@ static QCString extractPageTitle(QCString &docs,QCString &id) return title; } -static QCString detab(const QCString &s,int &refIndent) +QCString Markdown::detab(const QCString &s,int &refIndent) { int tabSize = Config_getInt(TAB_SIZE); int size = s.length(); - GrowBuf out(size); + m_out.clear(); + m_out.reserve(size); const char *data = s.data(); int i=0; int col=0; @@ -2492,15 +2407,15 @@ static QCString detab(const QCString &s,int &refIndent) int stop = tabSize - (col%tabSize); //printf("expand at %d stop=%d\n",col,stop); col+=stop; - while (stop--) out.addChar(' '); + while (stop--) m_out.addChar(' '); } break; case '\n': // reset column counter - out.addChar(c); + m_out.addChar(c); col=0; break; case ' ': // increment column counter - out.addChar(c); + m_out.addChar(c); col++; break; default: // non-whitespace => update minIndent @@ -2509,84 +2424,79 @@ static QCString detab(const QCString &s,int &refIndent) // special handling of the UTF-8 nbsp character 0xC2 0xA0 if ((uchar)c == 0xC2 && (uchar)(data[i]) == 0xA0) { - out.addStr(g_doxy_nsbp); + m_out.addStr(g_doxy_nsbp); i++; } else { - out.addChar(c); - out.addChar(data[i++]); // >= 2 bytes + m_out.addChar(c); + m_out.addChar(data[i++]); // >= 2 bytes if (((uchar)c&0xE0)==0xE0 && i<size) { - out.addChar(data[i++]); // 3 bytes + m_out.addChar(data[i++]); // 3 bytes } if (((uchar)c&0xF0)==0xF0 && i<size) { - out.addChar(data[i++]); // 4 byres + m_out.addChar(data[i++]); // 4 byres } } } else { - out.addChar(c); + m_out.addChar(c); } if (col<minIndent) minIndent=col; col++; } } if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0; - out.addChar(0); + m_out.addChar(0); //printf("detab refIndent=%d\n",refIndent); - return out.get(); + return m_out.get(); } //--------------------------------------------------------------------------- -QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,const QCString &input) +QCString Markdown::process(const QCString &input) { - static AtomicBool init { FALSE }; - if (!init) - { - // setup callback table for special characters - g_actions[(unsigned int)'_']=processEmphasis; - g_actions[(unsigned int)'*']=processEmphasis; - g_actions[(unsigned int)'~']=processEmphasis; - g_actions[(unsigned int)'`']=processCodeSpan; - g_actions[(unsigned int)'\\']=processSpecialCommand; - g_actions[(unsigned int)'@']=processSpecialCommand; - g_actions[(unsigned int)'[']=processLink; - g_actions[(unsigned int)'!']=processLink; - g_actions[(unsigned int)'<']=processHtmlTag; - g_actions[(unsigned int)'-']=processNmdash; - g_actions[(unsigned int)'"']=processQuoted; - init=TRUE; - } - - g_linkRefs.setAutoDelete(TRUE); - g_linkRefs.clear(); - g_current = e; - g_fileName = fileName; - g_lineNr = lineNr; - GrowBuf out; if (input.isEmpty()) return input; - out.clear(); int refIndent; + // for replace tabs by spaces QCString s = input; if (s.at(s.length()-1)!='\n') s += "\n"; // see PR #6766 s = detab(s,refIndent); //printf("======== DeTab =========\n---- output -----\n%s\n---------\n",s.data()); + // then process quotation blocks (as these may contain other blocks) s = processQuotations(s,refIndent); //printf("======== Quotations =========\n---- output -----\n%s\n---------\n",s.data()); + // then process block items (headers, rules, and code blocks, references) s = processBlocks(s,refIndent); //printf("======== Blocks =========\n---- output -----\n%s\n---------\n",s.data()); + // finally process the inline markup (links, emphasis and code spans) - processInline(out,s,s.length()); - out.addChar(0); - Debug::print(Debug::Markdown,0,"======== Markdown =========\n---- input ------- \n%s\n---- output -----\n%s\n=========\n",qPrint(input),qPrint(out.get())); - return substitute(out.get(),g_doxy_nsbp," "); + m_out.clear(); + processInline(s,s.length()); + m_out.addChar(0); + Debug::print(Debug::Markdown,0,"======== Markdown =========\n---- input ------- \n%s\n---- output -----\n%s\n=========\n",qPrint(input),qPrint(m_out.get())); + + // post processing + QCString result = substitute(m_out.get(),g_doxy_nsbp," "); + const char *p = result.data(); + if (p) + { + while (*p==' ') p++; // skip over spaces + while (*p=='\n') p++; // skip over newlines + if (qstrncmp(p,"<br>",4)==0) p+=4; // skip over <br> + } + if (p>result.data()) + { + // strip part of the input + result = result.mid(p-result.data()); + } + return result; } //--------------------------------------------------------------------------- @@ -2602,35 +2512,6 @@ QCString markdownFileNameToId(const QCString &fileName) //--------------------------------------------------------------------------- -QCString processMarkdownForCommentBlock(const QCString &comment, - const QCString &fileName, - int lineNr) -{ - if (!comment.isEmpty() && Doxygen::markdownSupport) - { - QCString result = processMarkdown(fileName,lineNr,0,comment); - const char *p = result.data(); - if (p) - { - while (*p==' ') p++; // skip over spaces - while (*p=='\n') p++; // skip over newlines - if (qstrncmp(p,"<br>",4)==0) p+=4; // skip over <br> - } - if (p>result.data()) - { - // strip part of the input - result = result.mid(p-result.data()); - } - return result; - } - else - { - return comment; - } -} - -//--------------------------------------------------------------------------- - struct MarkdownOutlineParser::Private { CommentScanner commentScanner; @@ -2657,9 +2538,11 @@ void MarkdownOutlineParser::parseInput(const char *fileName, current->docLine = 1; QCString docs = fileBuf; QCString id; - QCString title=extractPageTitle(docs,id).stripWhiteSpace(); + Markdown markdown(fileName,1,0); + QCString title=markdown.extractPageTitle(docs,id).stripWhiteSpace(); if (id.startsWith("autotoc_md")) id = ""; - g_indentLevel=title.isEmpty() ? 0 : -1; + int indentLevel=title.isEmpty() ? 0 : -1; + markdown.setIndentLevel(indentLevel); QCString titleFn = QFileInfo(fileName).baseName().utf8(); QCString fn = QFileInfo(fileName).fileName().utf8(); QCString mdfileAsMainPage = Config_getString(USE_MDFILE_AS_MAINPAGE); @@ -2693,13 +2576,13 @@ void MarkdownOutlineParser::parseInput(const char *fileName, // even without markdown support enabled, we still // parse markdown files as such - bool markdownEnabled = Doxygen::markdownSupport; - Doxygen::markdownSupport = TRUE; + //bool markdownEnabled = Doxygen::markdownSupport; + //Doxygen::markdownSupport = TRUE; Protection prot=Public; bool needsEntry = FALSE; int position=0; - QCString processedDocs = processMarkdownForCommentBlock(docs,fileName,lineNr); + QCString processedDocs = markdown.process(docs); while (p->commentScanner.parseCommentBlock( this, current.get(), @@ -2711,7 +2594,8 @@ void MarkdownOutlineParser::parseInput(const char *fileName, FALSE, // inBodyDocs prot, // protection position, - needsEntry)) + needsEntry, + true)) { if (needsEntry) { @@ -2728,8 +2612,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName, } // restore setting - Doxygen::markdownSupport = markdownEnabled; - g_indentLevel=0; + //Doxygen::markdownSupport = markdownEnabled; } void MarkdownOutlineParser::parsePrototype(const char *text) diff --git a/src/markdown.h b/src/markdown.h index bc1e9bb..6ac59cb 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 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 + * 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. * @@ -16,26 +16,77 @@ #ifndef MARKDOWN_H #define MARKDOWN_H +#include <functional> + #include <qcstring.h> #include "parserintf.h" +#include "growbuf.h" class Entry; /** processes string \a s and converts markdown into doxygen/html commands. */ -QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,const QCString &s); +//QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,const QCString &s); QCString markdownFileNameToId(const QCString &fileName); -/** Performs markdown processing for a comment block if markdown processing is enabled. - * @param[in] comment A string representing the actual comment block. - * Note that leading *'s should already be stripped from the comment block. - * @param[in] fileName The name of the file in which the comment is found. - * Mainly used for producing warnings. - * @param[in] lineNr The line number at which the comment block was found. - * @returns The processed comment block - */ -QCString processMarkdownForCommentBlock(const QCString &comment, - const QCString &fileName, - int lineNr); +/// Helper class to process markdown formatted text +class Markdown +{ + public: + Markdown(const char *fileName,int lineNr,int indentLevel=0); + QCString process(const QCString &input); + QCString extractPageTitle(QCString &docs,QCString &id); + void setIndentLevel(int level) { m_indentLevel = level; } + + private: + QCString detab(const QCString &s,int &refIndent); + QCString processQuotations(const QCString &s,int refIndent); + QCString processBlocks(const QCString &s,int indent); + QCString isBlockCommand(const char *data,int offset,int size); + void findEndOfLine(const char *data,int size,int &pi,int&i,int &end); + int processHtmlTagWrite(const char *data,int offset,int size,bool doWrite); + int processHtmlTag(const char *data,int offset,int size); + int processEmphasis(const char *data,int offset,int size); + int processEmphasis1(const char *data, int size, char c); + int processEmphasis2(const char *data, int size, char c); + int processEmphasis3(const char *data, int size, char c); + int processNmdash(const char *data,int off,int size); + int processQuoted(const char *data,int,int size); + int processCodeSpan(const char *data, int /*offset*/, int size); + void addStrEscapeUtf8Nbsp(const char *s,int len); + int processSpecialCommand(const char *data, int offset, int size); + int processLink(const char *data,int,int size); + int findEmphasisChar(const char *data, int size, char c, int c_size); + void processInline(const char *data,int size); + void writeMarkdownImage(const char *fmt, bool explicitTitle, + const QCString &title, const QCString &content, + const QCString &link, const FileDef *fd); + int isHeaderline(const char *data, int size, bool allowAdjustLevel); + int isAtxHeader(const char *data,int size, + QCString &header,QCString &id,bool allowAdjustLevel); + void writeOneLineHeaderOrRuler(const char *data,int size); + void writeFencedCodeBlock(const char *data,const char *lng, + int blockStart,int blockEnd); + int writeBlockQuote(const char *data,int size); + int writeCodeBlock(const char *data,int size,int refIndent); + int writeTableBlock(const char *data,int size); + + private: + struct LinkRef + { + LinkRef(const char *l,const char *t) : link(l), title(t) {} + QCString link; + QCString title; + }; + using Action_t = std::function<int(const char *,int,int)>; + + std::unordered_map<std::string,LinkRef> m_linkRefs; + QCString m_fileName; + int m_lineNr = 0; + int m_indentLevel=0; // 0 is outside markdown, -1=page level + GrowBuf m_out; + Markdown::Action_t m_actions[256]; +}; + class MarkdownOutlineParser : public OutlineParserInterface { @@ -44,8 +95,8 @@ class MarkdownOutlineParser : public OutlineParserInterface virtual ~MarkdownOutlineParser(); void startTranslationUnit(const char *) {} void finishTranslationUnit() {} - void parseInput(const char *fileName, - const char *fileBuf, + void parseInput(const char *fileName, + const char *fileBuf, const std::shared_ptr<Entry> &root, bool sameTranslationUnit, QStrList &filesInSameTranslationUnit); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 1d7909b..2b8bbbc 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -2606,8 +2606,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(), - getOuterScope()?getOuterScope():d,this,briefDescription(), - TRUE,FALSE,0,TRUE,FALSE); + getOuterScope()?getOuterScope():d,this,briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { @@ -3147,7 +3147,8 @@ void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, { ol.generateDoc(fmd->briefFile(),fmd->briefLine(), getOuterScope()?getOuterScope():container, - fmd,fmd->briefDescription(),TRUE,FALSE); + fmd,fmd->briefDescription(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // FIXME:PARA //if (!fmd->briefDescription().isEmpty() && @@ -3159,7 +3160,8 @@ void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, { ol.generateDoc(fmd->docFile(),fmd->docLine(), getOuterScope()?getOuterScope():container, - fmd,fmd->documentation()+"\n",TRUE,FALSE); + fmd,fmd->documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } ol.endDescTableData(); ol.endDescTableRow(); @@ -3707,7 +3709,8 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, ol.startParagraph(); ol.generateDoc(briefFile(),briefLine(), scopedContainer,this, - brief,FALSE,FALSE,0,TRUE,FALSE); + brief,FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endParagraph(); } @@ -3723,14 +3726,16 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, } else { - ol.generateDoc(docFile(),docLine(),scopedContainer,this,detailed+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),scopedContainer,this,detailed+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } if (!inbodyDocumentation().isEmpty()) { ol.generateDoc(inbodyFile(),inbodyLine(), - scopedContainer,this, - inbodyDocumentation()+"\n",TRUE,FALSE); + scopedContainer,this, + inbodyDocumentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } else if (!brief.isEmpty() && (Config_getBool(REPEAT_BRIEF) || @@ -3738,7 +3743,8 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { if (!inbodyDocumentation().isEmpty()) { - ol.generateDoc(inbodyFile(),inbodyLine(),scopedContainer,this,inbodyDocumentation()+"\n",TRUE,FALSE); + ol.generateDoc(inbodyFile(),inbodyLine(),scopedContainer,this,inbodyDocumentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } @@ -3765,7 +3771,8 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, this, // memberDef paramDocs, // docStr TRUE, // indexWords - FALSE // isExample + FALSE, // isExample + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT) ); } @@ -3959,7 +3966,8 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *conta { ol.generateDoc(briefFile(),briefLine(), getOuterScope()?getOuterScope():container,this, - brief,FALSE,FALSE,0,TRUE,FALSE); + brief,FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } /* write detailed description */ @@ -3967,7 +3975,8 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *conta { ol.generateDoc(docFile(),docLine(), getOuterScope()?getOuterScope():container,this, - detailed+"\n",FALSE,FALSE,0,FALSE,FALSE); + detailed+"\n",FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } diff --git a/src/memberlist.cpp b/src/memberlist.cpp index b5377a4..b8e5e89 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -517,7 +517,8 @@ void MemberList::writePlainDeclarations(OutputList &ol, md->briefFile(),md->briefLine(), cd,md, md->briefDescription(), - TRUE,FALSE,0,TRUE,FALSE + TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT) ); if (rootNode && !rootNode->isEmpty()) { @@ -684,7 +685,8 @@ void MemberList::writeDeclarations(OutputList &ol, if (!st.isEmpty()) { ol.startMemberSubtitle(); - ol.generateDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE,0,FALSE,FALSE); + ol.generateDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberSubtitle(); } } @@ -727,7 +729,8 @@ void MemberList::writeDeclarations(OutputList &ol, { //printf("Member group has docs!\n"); ol.startMemberGroupDocs(); - ol.generateDoc(mg->docFile(),mg->docLine(),ctx,0,mg->documentation()+"\n",FALSE,FALSE); + ol.generateDoc(mg->docFile(),mg->docLine(),ctx,0,mg->documentation()+"\n",FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberGroupDocs(); } ol.startMemberGroup(); diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 51454e0..6e0b45c 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -698,7 +698,8 @@ void NamespaceDefImpl::writeDetailedDescription(OutputList &ol,const QCString &t ol.startTextBlock(); if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && !documentation().isEmpty()) @@ -715,7 +716,8 @@ void NamespaceDefImpl::writeDetailedDescription(OutputList &ol,const QCString &t } if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } ol.endTextBlock(); } @@ -726,7 +728,8 @@ void NamespaceDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startParagraph(); @@ -1440,7 +1443,8 @@ void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title, if (!nd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(nd->getOutputFileBase()); - ol.generateDoc(nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription(),FALSE,FALSE,0,TRUE); + ol.generateDoc(nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); diff --git a/src/outputlist.cpp b/src/outputlist.cpp index 07d6491..e942465 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -115,7 +115,8 @@ void OutputList::generateDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef * md, const QCString &docStr,bool indexWords, bool isExample,const char *exampleName, - bool singleLine,bool linkFromIndex) + bool singleLine,bool linkFromIndex, + bool markdownSupport) { int count=0; if (docStr.isEmpty()) return; @@ -132,7 +133,7 @@ void OutputList::generateDoc(const char *fileName,int startLine, DocRoot *root=0; root = validatingParseDoc(fileName,startLine, ctx,md,docStr,indexWords,isExample,exampleName, - singleLine,linkFromIndex); + singleLine,linkFromIndex,markdownSupport); if (count>0) writeDoc(root,ctx,md); delete root; } diff --git a/src/outputlist.h b/src/outputlist.h index 58e4425..9393a59 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -59,8 +59,9 @@ class OutputList : public OutputDocInterface void generateDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef *md,const QCString &docStr, - bool indexWords,bool isExample,const char *exampleName=0, - bool singleLine=FALSE,bool linkFromIndex=FALSE); + bool indexWords,bool isExample,const char *exampleName /*=0*/, + bool singleLine /*=FALSE*/,bool linkFromIndex /*=FALSE*/, + bool markdownSupport /*=FALSE*/); void writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md); void parseText(const QCString &textStr); diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 011b647..823e87d 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 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 + * 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. * @@ -102,18 +102,18 @@ void PageDefImpl::findSectionsInDocumentation() docFindSections(documentation(),this,docFile()); } -GroupDef *PageDefImpl::getGroupDef() const -{ +GroupDef *PageDefImpl::getGroupDef() const +{ GroupList *groups = partOfGroups(); - return groups!=0 ? groups->getFirst() : 0; + return groups!=0 ? groups->getFirst() : 0; } -QCString PageDefImpl::getOutputFileBase() const -{ - if (getGroupDef()) +QCString PageDefImpl::getOutputFileBase() const +{ + if (getGroupDef()) return getGroupDef()->getOutputFileBase(); - else - return m_fileName; + else + return m_fileName; } void PageDefImpl::setFileName(const char *name) @@ -142,7 +142,7 @@ void PageDefImpl::addInnerCompound(const Definition *const_def) bool PageDefImpl::hasParentPage() const { - return getOuterScope() && + return getOuterScope() && getOuterScope()->definitionType()==Definition::TypePage; } @@ -180,9 +180,9 @@ void PageDefImpl::writeDocumentation(OutputList &ol) //printf("PageDefImpl::writeDocumentation: %s\n",getOutputFileBase().data()); ol.pushGeneratorState(); - //1.{ + //1.{ - if (m_nestingLevel>0 + if (m_nestingLevel>0 //&& // a sub page //(Doxygen::mainPage==0 || getOuterScope()!=Doxygen::mainPage) // and not a subpage of the mainpage ) @@ -195,14 +195,14 @@ void PageDefImpl::writeDocumentation(OutputList &ol) } ol.pushGeneratorState(); - //2.{ + //2.{ ol.disableAllBut(OutputGenerator::Man); startFile(ol,getOutputFileBase(),manPageName,title(),HLI_Pages,!generateTreeView); ol.enableAll(); ol.disable(OutputGenerator::Man); startFile(ol,getOutputFileBase(),pageName,title(),HLI_Pages,!generateTreeView); ol.popGeneratorState(); - //2.} + //2.} if (!generateTreeView) { @@ -229,7 +229,8 @@ void PageDefImpl::writeDocumentation(OutputList &ol) if (si->title() != manPageName) { - ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE,0,TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endSection(si->label(),si->type()); } } @@ -248,7 +249,8 @@ void PageDefImpl::writeDocumentation(OutputList &ol) ol.startPageDoc(si->title()); //ol.startSection(si->label,si->title,si->type); startTitle(ol,getOutputFileBase(),this); - ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE,0,TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); //stringToSearchIndex(getOutputFileBase(), // theTranslator->trPage(TRUE,TRUE)+" "+si->title, // si->title); @@ -288,11 +290,11 @@ void PageDefImpl::writeDocumentation(OutputList &ol) void PageDefImpl::writePageDocumentation(OutputList &ol) { - bool markdownEnabled = Doxygen::markdownSupport; - if (getLanguage()==SrcLangExt_Markdown) - { - Doxygen::markdownSupport = TRUE; - } + //bool markdownEnabled = Doxygen::markdownSupport; + //if (getLanguage()==SrcLangExt_Markdown) + //{ + // Doxygen::markdownSupport = TRUE; + //} ol.startTextBlock(); QCString docStr = documentation()+inbodyDocumentation(); @@ -310,11 +312,15 @@ void PageDefImpl::writePageDocumentation(OutputList &ol) 0, // memberdef docStr, // docStr TRUE, // index words - FALSE // not an example + FALSE, // not an example + 0, // exampleName + FALSE, // singleLine + FALSE, // linkFromIndex + TRUE // markdown support ); ol.endTextBlock(); - Doxygen::markdownSupport = markdownEnabled; + //Doxygen::markdownSupport = markdownEnabled; if (hasSubPages()) { @@ -357,16 +363,16 @@ bool PageDefImpl::visibleInIndex() const { static bool externalPages = Config_getBool(EXTERNAL_PAGES); return // not part of a group - !getGroupDef() && + !getGroupDef() && // not an externally defined page - (!isReference() || externalPages) + (!isReference() || externalPages) ; } bool PageDefImpl::documentedPage() const { return // not part of a group - !getGroupDef() && + !getGroupDef() && // not an externally defined page !isReference(); } diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index 843341f..a6e9f22 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -1463,7 +1463,8 @@ static void addPerlModDocBlock(PerlModOutput &output, if (stext.isEmpty()) output.addField(name).add("{}"); else { - DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,stext,FALSE,0); + DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,stext,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); output.openHash(name); PerlModDocVisitor *visitor = new PerlModDocVisitor(output); root->accept(visitor); diff --git a/src/pyscanner.l b/src/pyscanner.l index ed76c75..a3dbaba 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -1630,7 +1630,8 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief int position = 0; bool needsEntry; int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine; - QCString processedDoc = processMarkdownForCommentBlock(doc,yyextra->yyFileName,lineNr); + Markdown markdown(yyextra->yyFileName,lineNr); + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc) : doc; while (yyextra->commentScanner.parseCommentBlock( yyextra->thisParser, (yyextra->docBlockInBody && yyextra->previous) ? yyextra->previous.get() : yyextra->current.get(), @@ -1642,7 +1643,8 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief yyextra->docBlockInBody, yyextra->protection, position, - needsEntry) + needsEntry, + Config_getBool(MARKDOWN_SUPPORT)) ) // need to start a new entry { if (needsEntry) diff --git a/src/scanner.l b/src/scanner.l index 384b088..4f64503 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -7016,7 +7016,9 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief int position=0; bool needsEntry=FALSE; - QCString processedDoc = processMarkdownForCommentBlock(stripIndentation(doc),yyextra->yyFileName,lineNr); + Markdown markdown(yyextra->yyFileName,lineNr); + QCString strippedDoc = stripIndentation(doc); + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc) : strippedDoc; while (yyextra->commentScanner.parseCommentBlock( yyextra->thisParser, yyextra->docBlockInBody && yyextra->previous ? yyextra->previous.get() : yyextra->current.get(), @@ -7028,7 +7030,8 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief yyextra->docBlockInBody, // isInBody yyextra->protection, position, - needsEntry + needsEntry, + Config_getBool(MARKDOWN_SUPPORT) ) ) { @@ -7087,9 +7090,10 @@ static void handleParametersCommentBlocks(yyscan_t yyscanner,ArgumentList &al) FALSE, yyextra->protection, position, - needsEntry + needsEntry, + Config_getBool(MARKDOWN_SUPPORT) ) - ) + ) { //printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position); if (needsEntry) newEntry(yyscanner); diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index f767eab..70c6561 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -1424,7 +1424,11 @@ QCString getSQLDocBlock(const Definition *scope, dynamic_cast<const MemberDef*>(def), doc, FALSE, - FALSE + FALSE, + 0, + FALSE, + FALSE, + Config_getBool(MARKDOWN_SUPPORT) ); XMLCodeGenerator codeGen(t); // create a parse tree visitor for XML diff --git a/src/util.cpp b/src/util.cpp index a298ace..a571ffe 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -6983,7 +6983,8 @@ QCString parseCommentAsText(const Definition *scope,const MemberDef *md, if (doc.isEmpty()) return s.data(); FTextStream t(&s); DocNode *root = validatingParseDoc(fileName,lineNr, - (Definition*)scope,(MemberDef*)md,doc,FALSE,FALSE); + (Definition*)scope,(MemberDef*)md,doc,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); TextDocVisitor *visitor = new TextDocVisitor(t); root->accept(visitor); delete visitor; @@ -7329,7 +7330,8 @@ void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList linkifyText(TextGeneratorOLImpl(ol),d,0,0,a.type); ol.endConstraintType(); ol.startConstraintDocs(); - ol.generateDoc(d->docFile(),d->docLine(),d,0,a.docs,TRUE,FALSE); + ol.generateDoc(d->docFile(),d->docLine(),d,0,a.docs,TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endConstraintDocs(); } ol.endConstraintList(); diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 3f63cf0..ff96331 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -2165,8 +2165,9 @@ void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, QCString s=mdef->briefDescription(); ol.startMemberDescription(mdef->anchor(), NULL, mm == VhdlDocGen::PORT); ol.generateDoc(mdef->briefFile(),mdef->briefLine(), - mdef->getOuterScope()?mdef->getOuterScope():d, - mdef,s.data(),TRUE,FALSE,0,TRUE,FALSE); + mdef->getOuterScope()?mdef->getOuterScope():d, + mdef,s.data(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (detailsVisible) { ol.pushGeneratorState(); @@ -2270,7 +2271,8 @@ void VhdlDocGen::writeVHDLDeclarations(const MemberList* ml,OutputList &ol, if (subtitle && subtitle[0]!=0) { ol.startMemberSubtitle(); - ol.generateDoc("[generated]",-1,0,0,subtitle,FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc("[generated]",-1,0,0,subtitle,FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberSubtitle(); } //printf("memberGroupList=%p\n",memberGroupList); @@ -2296,7 +2298,8 @@ void VhdlDocGen::writeVHDLDeclarations(const MemberList* ml,OutputList &ol, { //printf("Member group has docs!\n"); ol.startMemberGroupDocs(); - ol.generateDoc("[generated]",-1,0,0,mg->documentation()+"\n",FALSE,FALSE); + ol.generateDoc("[generated]",-1,0,0,mg->documentation()+"\n",FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberGroupDocs(); } ol.startMemberGroup(); diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 38aa641..aa566ae 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -271,7 +271,7 @@ int VHDLOutlineParser::checkInlineCode(QCString &doc) QRegExp cend("[\\s ]*[\\\\@]endcode"); QRegExp cbrief("[\\\\@]brief"); int index = doc.find(cs); - + if (doc.contains(cend) > 0) return 1; @@ -284,16 +284,16 @@ int VHDLOutlineParser::checkInlineCode(QCString &doc) int com = p->inputString.find(p->strComment.data()); int ref = p->inputString.find(cend, p->code + 1); int len = p->strComment.size(); - + int ll = com + len; int diff = ref - ll - 3; QCString code = p->inputString.mid(ll, diff); - int iLine = 0; + int iLine = 0; code = stripLeadingAndTrailingEmptyLines(code, iLine); int val = code.contains('\n'); VhdlDocGen::prepareComment(p->strComment); QCStringList ql = QCStringList::split('\n', p->strComment); - + QCString co; QCString na; for (QCString qcs : ql) @@ -406,8 +406,9 @@ void VHDLOutlineParser::handleCommentBlock(const char *doc1, bool brief) //int position=0; - QCString processedDoc = processMarkdownForCommentBlock(doc, p->yyFileName, p->iDocLine); - + Markdown markdown(p->yyFileName,p->iDocLine); + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc) : doc; + while (p->commentScanner.parseCommentBlock( p->thisParser, s->current.get(), @@ -419,7 +420,8 @@ void VHDLOutlineParser::handleCommentBlock(const char *doc1, bool brief) FALSE, protection, position, - needsEntry)) + needsEntry, + Config_getBool(MARKDOWN_SUPPORT))) { if (needsEntry) newEntry(); diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 593f69a..b04297f 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -401,7 +401,8 @@ static void writeXMLDocBlock(FTextStream &t, QCString stext = text.stripWhiteSpace(); if (stext.isEmpty()) return; // convert the documentation string into an abstract syntax tree - DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE); + DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); // create a code generator XMLCodeGenerator *xmlCodeGen = new XMLCodeGenerator(t); // create a parse tree visitor for XML |