diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | addon/doxywizard/config_doxyw.l | 29 | ||||
-rw-r--r-- | addon/doxywizard/wizard.cpp | 5 | ||||
-rw-r--r-- | doc/arch.doc | 4 | ||||
-rw-r--r-- | doc/faq.doc | 6 | ||||
-rw-r--r-- | examples/define.h | 4 | ||||
-rw-r--r-- | examples/tclexample.tcl | 16 | ||||
-rw-r--r-- | src/code.l | 6 | ||||
-rw-r--r-- | src/commentcnv.l | 4 | ||||
-rw-r--r-- | src/commentscan.l | 56 | ||||
-rw-r--r-- | src/docparser.cpp | 32 | ||||
-rw-r--r-- | src/doctokenizer.l | 2 | ||||
-rw-r--r-- | src/doxygen.cpp | 2 | ||||
-rw-r--r-- | src/fortrancode.l | 53 | ||||
-rw-r--r-- | src/fortranscanner.l | 49 | ||||
-rw-r--r-- | src/markdown.cpp | 4 | ||||
-rw-r--r-- | src/namespacedef.cpp | 2 | ||||
-rw-r--r-- | src/scanner.l | 5 | ||||
-rw-r--r-- | src/tclscanner.l | 17 | ||||
-rw-r--r-- | src/util.cpp | 6 | ||||
-rw-r--r-- | testing/054/054__parblock_8cpp.xml | 92 | ||||
-rw-r--r-- | testing/054_parblock.cpp | 32 |
22 files changed, 321 insertions, 107 deletions
@@ -13,4 +13,4 @@ /doxygen_docs /doxygen.tag -/build +/build* diff --git a/addon/doxywizard/config_doxyw.l b/addon/doxywizard/config_doxyw.l index 7874a19..960b7cb 100644 --- a/addon/doxywizard/config_doxyw.l +++ b/addon/doxywizard/config_doxyw.l @@ -540,22 +540,34 @@ void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s) { QChar c; bool needsEscaping=false; + bool needsHashEscaping=false; // convert the string back to it original encoding //QByteArray se = codec->fromUnicode(s); t.setCodec(codec); const QChar *p=s.data(); if (!s.isEmpty() && !p->isNull()) { - while (!(c=*p++).isNull() && !needsEscaping) + if (*p != QChar::fromLatin1('"')) { - needsEscaping = (c==QChar::fromLatin1(' ') || - c==QChar::fromLatin1('\n') || - c==QChar::fromLatin1('\t') || - c==QChar::fromLatin1('"')); + while (!(c=*p++).isNull() && !needsEscaping) + { + needsEscaping = (c==QChar::fromLatin1(' ') || + c==QChar::fromLatin1('\n') || + c==QChar::fromLatin1('\t') || + c==QChar::fromLatin1('"')); + } + p=s.data(); + while (!(c=*p++).isNull() && !needsHashEscaping) + { + needsHashEscaping = (c==QChar::fromLatin1('#')); + } } - if (needsEscaping) + if (needsHashEscaping || needsEscaping) { t << "\""; + } + if (needsEscaping) + { p=s.data(); while (!p->isNull()) { @@ -564,12 +576,15 @@ void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s) if (*p ==QChar::fromLatin1('"')) t << "\\"; // escape quotes t << *p++; } - t << "\""; } else { t << s; } + if (needsHashEscaping || needsEscaping) + { + t << "\""; + } } } diff --git a/addon/doxywizard/wizard.cpp b/addon/doxywizard/wizard.cpp index b320aaa..ae8fa61 100644 --- a/addon/doxywizard/wizard.cpp +++ b/addon/doxywizard/wizard.cpp @@ -1210,18 +1210,23 @@ void Step4::setCallerGraphEnabled(int state) void Step4::init() { + int id = 0; if (getBoolOption(m_modelData,STR_HAVE_DOT)) { m_diagramModeGroup->button(2)->setChecked(true); // Dot + id = 2; } else if (getBoolOption(m_modelData,STR_CLASS_DIAGRAMS)) { m_diagramModeGroup->button(1)->setChecked(true); // Builtin diagrams + id = 1; } else { m_diagramModeGroup->button(0)->setChecked(true); // no diagrams + id = 0; } + m_dotGroup->setEnabled(id==2); m_dotClass->setChecked(getBoolOption(m_modelData,STR_CLASS_GRAPH)); m_dotCollaboration->setChecked(getBoolOption(m_modelData,STR_COLLABORATION_GRAPH)); m_dotInheritance->setChecked(getBoolOption(m_modelData,STR_GRAPHICAL_HIERARCHY)); diff --git a/doc/arch.doc b/doc/arch.doc index a19f450..03c87b9 100644 --- a/doc/arch.doc +++ b/doc/arch.doc @@ -139,8 +139,8 @@ strings and executes the commands it finds in it (this is the second pass in parsing the documentation). It writes the result directly to the output generators. -The parser is written in C++ and can be found in src/docparser.cpp. The -tokens that are eaten by the parser come from src/doctokenizer.l. +The parser is written in C++ and can be found in \c src/docparser.cpp. The +tokens that are eaten by the parser come from \c src/doctokenizer.l. Code fragments found in the comment blocks are passed on to the source parser. The main entry point for the documentation parser is \c validatingParseDoc() diff --git a/doc/faq.doc b/doc/faq.doc index bbad8c0..50dd7b1 100644 --- a/doc/faq.doc +++ b/doc/faq.doc @@ -113,7 +113,7 @@ around the blocks that should be hidden and put: in the config file then all blocks should be skipped by doxygen as long as \ref cfg_enable_preprocessing "ENABLE_PREPROCESSING" is set to `YES`. -\section faq_code_inc How can I change what is after the <code>\#include</code> in the class documentation? +\section faq_code_inc How can I change what is after the \#include in the class documentation? In most cases you can use \ref cfg_strip_from_inc_path "STRIP_FROM_INC_PATH" to strip a user defined part of a path. @@ -210,7 +210,7 @@ remove the % and keep the word unlinked. No, not as such; doxygen needs to understand the structure of what it reads. If you don't mind spending some time on it, there are several options: - If the grammar of X is close to C or C++, then it is probably not too hard to - tweak src/scanner.l a bit so the language is supported. This is done + tweak \c src/scanner.l a bit so the language is supported. This is done for all other languages directly supported by doxygen (i.e. Java, IDL, C#, PHP). - If the grammar of X is somewhat different than you can write an input @@ -219,7 +219,7 @@ If you don't mind spending some time on it, there are several options: Javascript, see http://www.stack.nl/~dimitri/doxygen/download.html#helpers). - If the grammar is completely different one could write a parser for X and write a backend that produces a similar syntax tree as is done by - src/scanner.l (and also by src/tagreader.cpp while reading tag files). + \c src/scanner.l (and also by \c src/tagreader.cpp while reading tag files). \section faq_lex Help! I get the cryptic message "input buffer overflow, can't enlarge buffer because scanner uses REJECT" diff --git a/examples/define.h b/examples/define.h index c330447..0cd7ae3 100644 --- a/examples/define.h +++ b/examples/define.h @@ -10,7 +10,9 @@ */ /*! - Computes the absolute value of its argument \a x. + \brief Computes the absolute value of its argument \a x. + \param x input value. + \returns absolute value of \a x. */ #define ABS(x) (((x)>0)?(x):-(x)) #define MAX(x,y) ((x)>(y)?(x):(y)) diff --git a/examples/tclexample.tcl b/examples/tclexample.tcl index 6edef66..e512aee 100644 --- a/examples/tclexample.tcl +++ b/examples/tclexample.tcl @@ -10,7 +10,7 @@ exec tclsh "$0" "$@" #\code namespace eval ns { ## Documented proc \c ns_proc . - # param[in] arg some argument + # \param[in] arg some argument proc ns_proc {arg} {} ## Documented var \c ns_var . # Some documentation. @@ -22,13 +22,13 @@ namespace eval ns { ## Destroy object. destructor {exit} ## Documented itcl method \c itcl_method_x . - # param[in] arg Argument + # \param[in] arg Argument private method itcl_method_x {arg} ## Documented itcl method \c itcl_method_y . - # param[in] arg Argument + # \param[in] arg Argument protected method itcl_method_y {arg} {} ## Documented itcl method \c itcl_method_z . - # param[in] arg Argument + # \param[in] arg Argument public method itcl_method_z {arg} {} ## Documented common itcl var \c itcl_Var . common itcl_Var @@ -49,13 +49,13 @@ namespace eval ns { # Defined inside class variable oo_var ## \private Documented oo method \c oo_method_x . - # param[in] arg Argument + # \param[in] arg Argument method oo_method_x {arg} {} ## \protected Documented oo method \c oo_method_y . - # param[in] arg Argument + # \param[in] arg Argument method oo_method_y {arg} {} ## \public Documented oo method \c oo_method_z . - # param[in] arg Argument + # \param[in] arg Argument method oo_method_z {arg} {} } } @@ -72,7 +72,7 @@ oo::define ns::oo_class { } ## Documented global proc \c glob_proc . -# param[in] arg Argument +# \param[in] arg Argument proc glob_proc {arg} {puts $arg} variable glob_var;#< Documented global var \c glob_var\ @@ -116,6 +116,7 @@ static int g_memCallContext; static int g_lastCContext; static int g_skipInlineInitContext; +static bool g_insideCpp; static bool g_insideObjC; static bool g_insideJava; static bool g_insideCS; @@ -2415,6 +2416,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_prefixed_with_this_keyword = TRUE; } <Body>{KEYWORD}/([^a-z_A-Z0-9]) { + if (g_insideCpp && (QCString(yytext) =="set" ||QCString(yytext) =="get")) REJECT; startFontClass("keyword"); codifyLines(yytext); if (QCString(yytext)=="typedef") @@ -2425,11 +2427,13 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" endFontClass(); } <Body>{KEYWORD}/{B}* { + if (g_insideCpp && (QCString(yytext) =="set" ||QCString(yytext) =="get")) REJECT; startFontClass("keyword"); codifyLines(yytext); endFontClass(); } <Body>{KEYWORD}/{BN}*"(" { + if (g_insideCpp && (QCString(yytext) =="set" ||QCString(yytext) =="get")) REJECT; startFontClass("keyword"); codifyLines(yytext); endFontClass(); @@ -2984,6 +2988,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) { //addParmType(); //g_parmName=yytext; + if (g_insideCpp && (QCString(yytext) =="set" ||QCString(yytext) =="get")) REJECT; startFontClass("keyword"); g_code->codify(yytext); endFontClass(); @@ -3742,6 +3747,7 @@ void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s, g_insideJava = lang==SrcLangExt_Java; g_insideCS = lang==SrcLangExt_CSharp; g_insidePHP = lang==SrcLangExt_PHP; + g_insideCpp = lang==SrcLangExt_Cpp; if (g_sourceFileDef) { setCurrentDoc("l00001"); diff --git a/src/commentcnv.l b/src/commentcnv.l index 44e2543..aca7300 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -1093,7 +1093,9 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) if (Debug::isFlagSet(Debug::CommentCnv)) { g_outBuf->at(g_outBuf->curPos())='\0'; - msg("-------------\n%s\n-------------\n",g_outBuf->data()); + Debug::print(Debug::CommentCnv,0,"-----------\nCommentCnv: %s\n" + "output=[\n%s]\n-----------\n",fileName,g_outBuf->data() + ); } printlex(yy_flex_debug, FALSE, __FILE__, fileName); } diff --git a/src/commentscan.l b/src/commentscan.l index 588d40a..07eb28f 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -563,14 +563,7 @@ static void addXRefItem(const char *listName,const char *itemTitle, RefItem *item = refList->getRefItem(lii->itemId); ASSERT(item!=0); item->text += " <p>"; - if (Doxygen::markdownSupport) - { - item->text += processMarkdown(yyFileName,yyLineNr,current,outputXRef); - } - else - { - item->text += outputXRef; - } + item->text += outputXRef; //printf("%s: text +=%s\n",listName,item->text.data()); } else // new item @@ -585,14 +578,7 @@ static void addXRefItem(const char *listName,const char *itemTitle, sprintf(anchorLabel,"_%s%06d",listName,itemId); RefItem *item = refList->getRefItem(itemId); ASSERT(item!=0); - if (Doxygen::markdownSupport) - { - item->text = processMarkdown(yyFileName,yyLineNr,current,outputXRef); - } - else - { - item->text = outputXRef; - } + item->text = outputXRef; item->listAnchor = anchorLabel; docEntry->addSpecialListItem(listName,itemId); QCString cmdString; @@ -1860,10 +1846,10 @@ RCSTAG "$"{ID}":"[^\n$]+"$" addOutput(*yytext); } <FormatBlock><<EOF>> { - QCString endTag = "@end"+blockName; + QCString endTag = "end"+blockName; if (blockName=="startuml") endTag="enduml"; warn(yyFileName,yyLineNr, - "reached end of comment while inside a @%s block; check for missing @%s tag!", + "reached end of comment while inside a \\%s block; check for missing \\%s tag!", blockName.data(),endTag.data() ); yyterminate(); @@ -1944,7 +1930,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" if (guards.isEmpty()) { warn(yyFileName,yyLineNr, - "found @endif without matching start command"); + "found \\endif without matching start command"); } else { @@ -1962,7 +1948,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" if (guards.isEmpty()) { warn(yyFileName,yyLineNr, - "found @else without matching start command"); + "found \\else without matching start command"); } else { @@ -1979,7 +1965,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" if (guards.isEmpty()) { warn(yyFileName,yyLineNr, - "found @elseif without matching start command"); + "found \\elseif without matching start command"); } else { @@ -2943,7 +2929,19 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, langParser = parser; current = curEntry; if (comment.isEmpty()) return FALSE; // avoid empty strings - inputString = comment; + if (Doxygen::markdownSupport) + { + inputString = processMarkdown(fileName,lineNr,NULL,comment); + QString qq(inputString); + while (qq.startsWith(" ")) qq = qq.mid(1); + while (qq.startsWith("\n")) qq = qq.mid(1); + if (qq.startsWith("<br>")) qq = qq.mid(4); + inputString = QCString(qq.data()); + } + else + { + inputString = comment; + } inputString.append(" "); inputPosition = position; yyLineNr = lineNr; @@ -2970,7 +2968,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, } Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\n" - "input=[\n%s]\n",qPrint(fileName),lineNr,qPrint(comment) + "input=[\n%s]\n",qPrint(fileName),lineNr,qPrint(inputString) ); commentscanYYrestart( commentscanYYin ); @@ -3008,15 +3006,9 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, openGroup(current,yyFileName,yyLineNr); } - if (Doxygen::markdownSupport) - { - current->brief = processMarkdown(fileName,lineNr,current,current->brief); - current->doc = processMarkdown(fileName,lineNr,current,current->doc); - current->inbodyDocs = processMarkdown(fileName,lineNr,current,current->inbodyDocs); - } - - Debug::print(Debug::CommentScan,0, - "brief=[line=%d\n%s]\ndocs=[line=%d\n%s]\ninbody=[line=%d\n%s]\n===========\n", + 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, current->briefLine,qPrint(current->brief), current->docLine,qPrint(current->doc), current->inbodyLine,qPrint(current->inbodyDocs) diff --git a/src/docparser.cpp b/src/docparser.cpp index 3d57c2e..0257a1e 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -451,11 +451,12 @@ static void checkArgumentName(const QCString &name,bool isParam) } /*! Checks if the parameters that have been specified using \@param are - * indeed all parameters. + * indeed all parameters and that a parameter does not have multiple + * \@param blocks. * Must be called after checkArgumentName() has been called for each * argument. */ -static void checkUndocumentedParams() +static void checkUnOrMultipleDocumentedParams() { if (g_memberDef && g_hasParamCommand && Config_getBool(WARN_IF_DOC_ERROR)) { @@ -470,18 +471,37 @@ static void checkUndocumentedParams() bool found=FALSE; for (ali.toFirst();(a=ali.current());++ali) { + int count = 0; QCString argName = g_memberDef->isDefine() ? a->type : a->name; if (lang==SrcLangExt_Fortran) argName = argName.lower(); argName=argName.stripWhiteSpace(); + QCString aName = argName; if (argName.right(3)=="...") argName=argName.left(argName.length()-3); - if (g_memberDef->getLanguage()==SrcLangExt_Python && (argName=="self" || argName=="cls")) + if (lang==SrcLangExt_Python && (argName=="self" || argName=="cls")) { // allow undocumented self / cls parameter for Python } else if (!argName.isEmpty() && g_paramsFound.find(argName)==0 && a->docs.isEmpty()) { found = TRUE; - break; + } + else + { + QDictIterator<void> it1(g_paramsFound); + void *item1; + for (;(item1=it1.current());++it1) + { + if (argName == it1.currentKey()) count++; + } + } + if (count > 1) + { + warn_doc_error(g_memberDef->getDefFileName(), + g_memberDef->getDefLine(), + "argument '" + aName + + "' from the argument list of " + + QCString(g_memberDef->qualifiedName()) + + " has muliple @param documentation sections"); } } if (found) @@ -497,7 +517,7 @@ static void checkUndocumentedParams() QCString argName = g_memberDef->isDefine() ? a->type : a->name; if (lang==SrcLangExt_Fortran) argName = argName.lower(); argName=argName.stripWhiteSpace(); - if (g_memberDef->getLanguage()==SrcLangExt_Python && (argName=="self" || argName=="cls")) + if (lang==SrcLangExt_Python && (argName=="self" || argName=="cls")) { // allow undocumented self / cls parameter for Python } @@ -7541,7 +7561,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, delete v; } - checkUndocumentedParams(); + checkUnOrMultipleDocumentedParams(); detectNoDocumentedParams(); // TODO: These should be called at the end of the program. diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 90a8c55..777e963 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -554,7 +554,7 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->indent = computeIndent(text,dotPos); return TK_ENDLIST; } -<St_Para>"{"{BLANK}*"@link" { +<St_Para>"{"{BLANK}*"@link"/{BLANK}+ { g_token->name = "javalink"; return TK_COMMAND; } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 00826d6..263b59f 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -10965,7 +10965,7 @@ void parseInput() /************************************************************************** - * Check/create output directorties * + * Check/create output directories * **************************************************************************/ QCString htmlOutput; diff --git a/src/fortrancode.l b/src/fortrancode.l index 501b492..f491acb 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -159,6 +159,9 @@ static char stringStartSymbol; // single or double quote // declared from referenced names static int bracketCount = 0; +// signal when in type / class /procedure declaration +static int inTypeDecl = 0; + static bool g_endComment; static void endFontClass() @@ -687,14 +690,14 @@ CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE) INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" -ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE) +ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|(NON_)?RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE) ACCESS_SPEC (PROTECTED|PRIVATE|PUBLIC) /* Assume that attribute statements are almost the same as attributes. */ ATTR_STMT {ATTR_SPEC}|DIMENSION FLOW (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT|GO{BS}TO) COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON) IGNORE (CALL) -PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|IMPURE|PURE|ELEMENTAL)? +PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)? /* | */ @@ -813,7 +816,8 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I unput(*yytext); yy_pop_state();YY_FTN_RESET } -<Start>"import"{BS_} { +<*>"import"{BS}/"\n" | +<*>"import"{BS_} { startFontClass("keywordtype"); codifyLines(yytext); endFontClass(); @@ -825,6 +829,11 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I generateLink(*g_code, yytext); g_insideBody=FALSE; } +<Import>("ONLY"|"NONE"|"ALL") { + startFontClass("keywordtype"); + codifyLines(yytext); + endFontClass(); + } /*-------- fortran module -----------------------------------------*/ <Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { // startScope(); @@ -836,14 +845,14 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I if (!qstricmp(yytext,"module")) currentModule="module"; } <Start>("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + startScope(); + startFontClass("keyword"); + codifyLines(yytext); + endFontClass(); yy_push_state(YY_START); - BEGIN(ClassName); - currentClass="class"; - } + BEGIN(ClassName); + currentClass="class"; + } <ClassName>{ID} { if (currentModule == "module") { @@ -876,7 +885,7 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I codifyLines(yytext); endFontClass(); } -<Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found +<Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found startFontClass("keyword"); codifyLines(yytext); endFontClass(); @@ -923,6 +932,9 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I } /*-------- variable declaration ----------------------------------*/ <Start>{TYPE_SPEC}/[,:( ] { + QCString typ = yytext; + typ = typ.lower(); + if (typ == "type" || typ == "class" || typ == "procedure") inTypeDecl = 1; yy_push_state(YY_START); BEGIN(Declaration); startFontClass("keywordtype"); @@ -946,7 +958,7 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I g_code->codify(yytext); endFontClass(); } - else if (g_currentMemberDef && ((g_currentMemberDef->isFunction() && (g_currentMemberDef->typeString() != QCString("subroutine"))) || + else if (g_currentMemberDef && ((g_currentMemberDef->isFunction() && (g_currentMemberDef->typeString() != QCString("subroutine") || inTypeDecl)) || g_currentMemberDef->isVariable())) { generateLink(*g_code, yytext); @@ -956,22 +968,23 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I g_code->codify(yytext); addLocalVar(yytext); } - } -<Declaration>{BS}("=>"|"="){BS} { // Procedure binding - BEGIN(DeclarationBinding); - g_code->codify(yytext); - } -<DeclarationBinding>{ID} { // Type bound procedure link + } +<Declaration>{BS}("=>"|"="){BS} { // Procedure binding + BEGIN(DeclarationBinding); + g_code->codify(yytext); + } +<DeclarationBinding>{ID} { // Type bound procedure link generateLink(*g_code, yytext); yy_pop_state(); - } -<Declaration>[(] { // start of array specification + } +<Declaration>[(] { // start of array or type / class specification bracketCount++; g_code->codify(yytext); } <Declaration>[)] { // end array specification bracketCount--; + if (!bracketCount) inTypeDecl = 0; g_code->codify(yytext); } diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 85b6de9..774251b 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -198,6 +198,8 @@ static SymbolModifiers currentModifiers; //! Holds program scope->symbol name->symbol modifiers. static QMap<Entry*,QMap<QCString,SymbolModifiers> > modifiers; +static Entry *global_scope = NULL; + //----------------------------------------------------------------------------- static int yyread(char *buf,int max_size); @@ -248,6 +250,7 @@ SUBPROG (subroutine|function) B [ \t] BS [ \t]* BS_ [ \t]+ +BT_ ([ \t]+|[ \t]*"(") COMMA {BS},{BS} ARGS_L0 ("("[^)]*")") ARGS_L1a [^()]*"("[^)]*")"[^)]* @@ -271,7 +274,7 @@ ATTR_STMT {ATTR_SPEC}|DIMENSION|{ACCESS_SPEC} EXTERNAL_STMT (EXTERNAL) CONTAINS CONTAINS -PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|IMPURE|PURE|ELEMENTAL)? +PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)? SCOPENAME ({ID}{BS}"::"{BS})* %option noyywrap @@ -558,7 +561,18 @@ SCOPENAME ({ID}{BS}"::"{BS})* if (!endScope(current_root)) yyterminate(); defaultProtection = Public; - yy_pop_state(); + if (global_scope) + { + if (global_scope != (Entry *) -1) + yy_push_state(Start); + else + yy_pop_state(); // cannot pop artrificial entry + } + else + { + yy_push_state(Start); + global_scope = (Entry *)-1; // signal that the global_scope has already been used. + } } <Module>{ID} { addModule(yytext, TRUE); @@ -602,7 +616,7 @@ abstract { current->spec |= Entry::AbstractClass; } extends{ARGS} { - QCString basename = extractFromParens(yytext); + QCString basename = extractFromParens(yytext).lower(); current->extends->append(new BaseInfo(basename, Public, Normal)); } public { @@ -667,7 +681,8 @@ private { addCurrentEntry(1); } {BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */ - last_entry->args = yytext; + QCString args = yytext; + last_entry->args = args.lower(); } "\n" { currentModifiers = SymbolModifiers(); @@ -773,8 +788,10 @@ private { } {ID} { } -^{BS}"type"{BS_}"is"/{BS_} { } +^{BS}"type"{BS_}"is"/{BT_} { } ^{BS}"type"{BS}"=" { } +^{BS}"class"{BS_}"is"/{BT_} { } +^{BS}"class"{BS_}"default" { } } <AttributeList>{ {COMMA} {} @@ -1098,7 +1115,6 @@ private { yy_push_state(YY_START); BEGIN(StrIgnore); debugStr="*!"; - //fprintf(stderr,"start comment %d\n",yyLineNr); } } } @@ -1552,7 +1568,10 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) } // fallthrough default: - if(column==6 && emptyLabel) { // continuation + if ((column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) { // remove numbers, i.e. labels from first 5 positions. + newContents[j]=' '; + } + else if(column==6 && emptyLabel) { // continuation if (!commented) fullCommentLine=FALSE; if (c != '0') { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3 newContents[j]=' '; @@ -2017,14 +2036,23 @@ static void startScope(Entry *scope) */ static bool endScope(Entry *scope, bool isGlobalRoot) { + if (global_scope == scope) + { + global_scope = NULL; + return TRUE; + } + if (global_scope == (Entry *) -1) + { + return TRUE; + } //cout<<"end scope: "<<scope->name<<endl; if (current_root->parent() || isGlobalRoot) { current_root= current_root->parent(); /* end substructure */ } - else + else // if (current_root != scope) { - fprintf(stderr,"parse error in end <scopename>"); + fprintf(stderr,"parse error in end <scopename>\n"); scanner_abort(); return FALSE; } @@ -2558,6 +2586,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra yyFileName = fileName; msg("Parsing file %s...\n",yyFileName.data()); + global_scope = rt; startScope(rt); // implies current_root = rt initParser(); groupEnterFile(yyFileName,yyLineNr); @@ -2579,7 +2608,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra fortranscannerYYlex(); groupLeaveFile(yyFileName,yyLineNr); - endScope(current_root, TRUE); // TRUE - global root + if (global_scope && global_scope != (Entry *) -1) endScope(current_root, TRUE); // TRUE - global root //debugCompounds(rt); //debug diff --git a/src/markdown.cpp b/src/markdown.cpp index d3ec3f1..de5805f 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -483,6 +483,8 @@ static int processNmdash(GrowBuf &out,const char *data,int off,int size) { count++; } + if (count==2 && off>=2 && qstrncmp(data-2,"<!",2)==0) return 0; // start HTML comment + if (count==2 && (data[2]=='>')) return 0; // end HTML comment if (count==2 && (off<8 || qstrncmp(data-8,"operator",8)!=0)) // -- => ndash { out.addStr("–"); @@ -2548,7 +2550,7 @@ QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,cons // 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())); + Debug::print(Debug::Markdown,0,"======== Markdown =========\n---- input ------- \n%s\n---- output -----\n%s\n=========\n",qPrint(input),qPrint(out.get())); return out.get(); } diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index c674760..d3eb0df 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -961,7 +961,7 @@ void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title, bool found=FALSE; for (ni.toFirst();(nd=ni.current()) && !found;++ni) { - if (nd->isLinkable()) + if (nd->isLinkable() && nd->hasDocumentation()) { SrcLangExt lang = nd->getLanguage(); if (SrcLangExt_IDL==lang) diff --git a/src/scanner.l b/src/scanner.l index 08a5e52..619eb5d 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -3639,7 +3639,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) current->fileName = yyFileName; current->startLine = yyLineNr; current->startColumn = yyColNr; - current->type = "@"; // enum marker + if (!(current_root->spec&Entry::Enum)) + { + current->type = "@"; // enum marker + } current->args = current->args.simplifyWhiteSpace(); current->name = current->name.stripWhiteSpace(); current->section = Entry::VARIABLE_SEC; diff --git a/src/tclscanner.l b/src/tclscanner.l index 791ecc4..56d2e3d 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -703,6 +703,7 @@ static void tcl_codify(const char *s,const char *str) } else { + if (*(p-2)==0x1A) *(p-2) = '\0'; // remove ^Z tcl.code->codify(sp); done=TRUE; } @@ -3024,11 +3025,6 @@ void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, } tcl_inf("%s (%d,%d) %d %d\n",myStr.ascii(),startLine,endLine,isExampleBlock,inlineFragment); //tcl_inf("%s\n"input.data()); - if (isExampleBlock) - { - tcl_codify(NULL,input); - return; - } tcl_init(); tcl.collectXRefs = collectXRefs; tcl.memberdef = memberDef; @@ -3047,8 +3043,15 @@ tcl_inf("%s (%d,%d) %d %d\n",myStr.ascii(),startLine,endLine,isExampleBlock,inli } tcl.file_name = ""; tcl.this_parser = NULL; - tcl.entry_main = tcl_entry_new(); - tcl_parse(myNs,myCls); + if (isExampleBlock) + { + tcl_codify(NULL,input); + } + else + { + tcl.entry_main = tcl_entry_new(); + tcl_parse(myNs,myCls); + } tcl.code->endCodeLine(); tcl.scan.clear(); tcl.ns.clear(); diff --git a/src/util.cpp b/src/util.cpp index 3af1a90..9100706 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1856,7 +1856,11 @@ QCString removeRedundantWhiteSpace(const QCString &s) case '&': if (i>0 && isId(pc)) { - *dst++=' '; + if (nc != '=') + // avoid splitting operator&= + { + *dst++=' '; + } } *dst++=c; break; diff --git a/testing/054/054__parblock_8cpp.xml b/testing/054/054__parblock_8cpp.xml index ae6e462..5567908 100644 --- a/testing/054/054__parblock_8cpp.xml +++ b/testing/054/054__parblock_8cpp.xml @@ -80,6 +80,96 @@ <parameterdescription> <para> <parblock> + <para>First paragraph of the param description.</para> + <para>Second paragraph of the param description. </para> + </parblock> + </para> + </parameterdescription> + </parameteritem> + </parameterlist> + </para> + </detaileddescription> + <inbodydescription> + </inbodydescription> + <location file="054_parblock.cpp" line="33" column="1"/> + </memberdef> + <memberdef kind="function" id="054__parblock_8cpp_1a5cded03ec9e6fd626da35ab05f624f39" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual"> + <type>void</type> + <definition>void function_2</definition> + <argsstring>(int client, int *resource, int parblock, int *test, int p)</argsstring> + <name>function_2</name> + <param> + <type>int</type> + <declname>client</declname> + </param> + <param> + <type>int *</type> + <declname>resource</declname> + </param> + <param> + <type>int</type> + <declname>parblock</declname> + </param> + <param> + <type>int *</type> + <declname>test</declname> + </param> + <param> + <type>int</type> + <declname>p</declname> + </param> + <briefdescription> + </briefdescription> + <detaileddescription> + <para>call by target-specific code to manage resources required by the client.</para> + <para> + <parameterlist kind="param"> + <parameteritem> + <parameternamelist> + <parametername direction="in">client</parametername> + </parameternamelist> + <parameterdescription> + <para>ID of client requesting resource. </para> + </parameterdescription> + </parameteritem> + <parameteritem> + <parameternamelist> + <parametername direction="out">resource</parametername> + </parameternamelist> + <parameterdescription> + <para>Requested resource </para> + </parameterdescription> + </parameteritem> + <parameteritem> + <parameternamelist> + <parametername direction="in">parblock</parametername> + </parameternamelist> + <parameterdescription> + <para> + <parblock> + <para>This is a test for the @parblock command.</para> + <para>A list if values for the parblock param:<itemizedlist><listitem><para>Item 1. This is short one-line description.</para></listitem><listitem><para>Item 2. This is a long bullet item; sometimes they wrap on multiple lines like this one.</para></listitem></itemizedlist> +</para> + <para>This is the second paragraph description for the @parblock parameter. Always end the text inside the @parblock command with an @endparblock command. </para> + </parblock> + </para> + </parameterdescription> + </parameteritem> + <parameteritem> + <parameternamelist> + <parametername direction="out">test</parametername> + </parameternamelist> + <parameterdescription> + <para>This is a test parameter for this function to see if it is included in the parameter table </para> + </parameterdescription> + </parameteritem> + <parameteritem> + <parameternamelist> + <parametername direction="in">p</parametername> + </parameternamelist> + <parameterdescription> + <para> + <parblock> <para>First paragraph of the param description. <verbatim> Second paragraph of the param description. </verbatim> </para> </parblock> @@ -91,7 +181,7 @@ </detaileddescription> <inbodydescription> </inbodydescription> - <location file="054_parblock.cpp" line="32" column="1"/> + <location file="054_parblock.cpp" line="60" column="1"/> </memberdef> </sectiondef> <briefdescription> diff --git a/testing/054_parblock.cpp b/testing/054_parblock.cpp index 186feb5..4f303c6 100644 --- a/testing/054_parblock.cpp +++ b/testing/054_parblock.cpp @@ -24,9 +24,37 @@ @endparblock @param[out] test This is a test parameter for this function to see if it is included in the parameter table + @param[in] p + @parblock First paragraph of the param description. + + Second paragraph of the param description. + @endparblock + */ +void function(int client,int *resource,int parblock,int *test,int p); +/** + call by target-specific code to manage resources required by the client. + + @param[in] client ID of client requesting resource. + @param[out] resource Requested resource + @param[in] parblock @parblock This is a test for the \@parblock + command. + + A list if values for the parblock param: + - Item 1. This is short one-line description. + - Item 2. This is a long bullet item; + sometimes they wrap on multiple lines like this + one. + + This is the second paragraph description for the + \@parblock parameter. Always end the text inside + the \@parblock command with an \@endparblock + command. + @endparblock + @param[out] test This is a test parameter for this function to see if + it is included in the parameter table @param[in] p @parblock First paragraph of the param description. Second paragraph of the param description. - @endparblock + @endparblock */ -void function(int client,int *resource,int parblock,int *test,int p); +void function_2(int client,int *resource,int parblock,int *test,int p); |