diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/classdef.cpp | 4 | ||||
-rw-r--r-- | src/commentscan.h | 13 | ||||
-rw-r--r-- | src/commentscan.l | 52 | ||||
-rw-r--r-- | src/config.xml | 13 | ||||
-rw-r--r-- | src/debug.cpp | 1 | ||||
-rw-r--r-- | src/debug.h | 3 | ||||
-rw-r--r-- | src/docbookvisitor.cpp | 4 | ||||
-rw-r--r-- | src/docparser.cpp | 2 | ||||
-rw-r--r-- | src/doxygen.cpp | 5 | ||||
-rw-r--r-- | src/fortranscanner.l | 7 | ||||
-rw-r--r-- | src/growbuf.h | 10 | ||||
-rw-r--r-- | src/htmldocvisitor.cpp | 118 | ||||
-rw-r--r-- | src/latexdocvisitor.cpp | 6 | ||||
-rw-r--r-- | src/markdown.cpp | 9 | ||||
-rw-r--r-- | src/memberdef.cpp | 19 | ||||
-rw-r--r-- | src/plantuml.cpp | 398 | ||||
-rw-r--r-- | src/plantuml.h | 65 | ||||
-rw-r--r-- | src/pyscanner.l | 5 | ||||
-rw-r--r-- | src/rtfdocvisitor.cpp | 4 | ||||
-rw-r--r-- | src/scanner.l | 19 | ||||
-rw-r--r-- | src/tclscanner.l | 19 | ||||
-rw-r--r-- | src/util.cpp | 32 | ||||
-rw-r--r-- | src/util.h | 2 | ||||
-rw-r--r-- | src/vhdldocgen.cpp | 4 | ||||
-rw-r--r-- | src/vhdljjparser.cpp | 7 | ||||
-rw-r--r-- | src/xmldocvisitor.cpp | 6 |
26 files changed, 624 insertions, 203 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp index e9d39d5..a48df76 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -620,6 +620,10 @@ void ClassDef::internalInsertMember(MemberDef *md, { addMemberToList(MemberListType_relatedMembers,md,FALSE); } + else if (md->isFunction() && md->protection()==Private && md->virtualness()!=Normal && Config_getBool(EXTRACT_PRIV_VIRTUAL)) + { + addMemberToList(MemberListType_functionMembers,md,FALSE); + } else { switch (md->memberType()) diff --git a/src/commentscan.h b/src/commentscan.h index d324969..75cd99f 100644 --- a/src/commentscan.h +++ b/src/commentscan.h @@ -24,6 +24,19 @@ class ParserInterface; /** @file * @brief Interface for the comment block parser */ +/** Invokes the comment block parser with the request to preprocess a + * single comment block. + * @param[in] comment A string representing the actual comment block. + * Note that leading *'s are already 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 prepocessed comment block + */ +QCString preprocessCommentBlock(const QCString &comment, + const QCString &fileName, + int lineNr); + /** Invokes the comment block parser with the request to parse a * single comment block. * @param[in] parser The language parse that invoked this function. diff --git a/src/commentscan.l b/src/commentscan.l index 235cd7c..7fab755 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -277,6 +277,8 @@ static DocCmdMap docCmdMap[] = { "verbinclude", 0, FALSE }, { "version", 0, TRUE }, { "warning", 0, TRUE }, + { "snippet", 0, TRUE }, + { "snippetlineno", 0, TRUE }, { 0, 0, FALSE } }; @@ -1191,6 +1193,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } } <Comment>{B}*{CMD}"f{"[^}\n]+"}"("{"?) { // start of a formula with custom environment + setOutput(OutputDoc); formulaText="\\begin"; formulaEnv=QString(yytext).stripWhiteSpace().data()+2; if (formulaEnv.at(formulaEnv.length()-1)=='{') @@ -1208,6 +1211,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" BEGIN(ReadFormulaShort); } <Comment>{B}*{CMD}"f[" { // start of a block formula + setOutput(OutputDoc); formulaText="\\["; formulaNewLines=0; BEGIN(ReadFormulaLong); @@ -3074,6 +3078,33 @@ static void checkFormula() //---------------------------------------------------------------------------- +QCString preprocessCommentBlock(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; + } +} + bool parseCommentBlock(/* in */ ParserInterface *parser, /* in */ Entry *curEntry, /* in */ const QCString &comment, @@ -3096,26 +3127,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, langParser = parser; current = curEntry; if (comment.isEmpty()) return FALSE; // avoid empty strings - if (Doxygen::markdownSupport) - { - inputString = processMarkdown(fileName,lineNr,NULL,comment); - const char *p = inputString.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>inputString.data()) - { - // strip part of the input - inputString = inputString.mid(p-inputString.data()); - } - } - else - { - inputString = comment; - } + inputString = comment; inputString.append(" "); inputPosition = position; yyLineNr = lineNr; diff --git a/src/config.xml b/src/config.xml index fdc562d..a62040b 100644 --- a/src/config.xml +++ b/src/config.xml @@ -838,6 +838,14 @@ Go to the <a href="commands.html">next</a> section or return to the ]]> </docs> </option> + <option type='bool' id='EXTRACT_PRIV_VIRTUAL' defval='0'> + <docs> +<![CDATA[ + If the \c EXTRACT_PRIV_VIRTUAL tag is set to \c YES, documented private + virtual methods of a class will be included in the documentation. +]]> + </docs> + </option> <option type='bool' id='EXTRACT_PACKAGE' defval='0'> <docs> <![CDATA[ @@ -2594,11 +2602,12 @@ EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... ]]> </docs> </option> - <option type='string' id='LATEX_MAKEINDEX_CMD' defval='\makeindex' depends='GENERATE_LATEX'> + <option type='string' id='LATEX_MAKEINDEX_CMD' defval='makeindex' depends='GENERATE_LATEX'> <docs> <![CDATA[ The \c LATEX_MAKEINDEX_CMD tag can be used to specify the command name to - generate index for \f$\mbox{\LaTeX}\f$. + generate index for \f$\mbox{\LaTeX}\f$. In case there is no backslash (`\`) as first character it + will be automatically added in the \f$\mbox{\LaTeX}\f$ code. @note This tag is used in the generated output file (`.tex`). \sa \ref cfg_makeindex_cmd_name "MAKEINDEX_CMD_NAME" for the part in the `Makefile` / `make.bat`. diff --git a/src/debug.cpp b/src/debug.cpp index c81a1af..2f343ac 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -48,6 +48,7 @@ static LabelMap s_labels[] = { "markdown", Debug::Markdown }, { "filteroutput", Debug::FilterOutput }, { "lex", Debug::Lex }, + { "plantuml", Debug::Plantuml }, { 0, (Debug::DebugMask)0 } }; diff --git a/src/debug.h b/src/debug.h index 8a28c7a..9a2070c 100644 --- a/src/debug.h +++ b/src/debug.h @@ -37,7 +37,8 @@ class Debug ExtCmd = 0x00000400, Markdown = 0x00000800, FilterOutput = 0x00001000, - Lex = 0x00002000 + Lex = 0x00002000, + Plantuml = 0x00004000 }; static void print(DebugMask mask,int prio,const char *fmt,...); static int setFlag(const char *label); diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 99df99c..3988390 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -353,7 +353,7 @@ DB_VIS_C case DocVerbatim::PlantUML: { static QCString docbookOutput = Config_getString(DOCBOOK_OUTPUT); - QCString baseName = writePlantUMLSource(docbookOutput,s->exampleFile(),s->text()); + QCString baseName = PlantumlManager::instance()->writePlantUMLSource(docbookOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_BITMAP); QCString shortName = baseName; int i; if ((i=shortName.findRev('/'))!=-1) @@ -1642,7 +1642,7 @@ DB_VIS_C shortName=shortName.right(shortName.length()-i-1); } QCString outDir = Config_getString(DOCBOOK_OUTPUT); - generatePlantUMLOutput(baseName,outDir,PUML_BITMAP); + PlantumlManager::instance()->generatePlantUMLOutput(baseName,outDir,PlantumlManager::PUML_BITMAP); visitPreStart(m_t, s->children(), s->hasCaption(), s->relPath() + shortName + ".png", s->width(),s->height()); visitCaption(s->children()); visitPostEnd(m_t, s->hasCaption()); diff --git a/src/docparser.cpp b/src/docparser.cpp index c91dcde..20ee1f0 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -422,7 +422,7 @@ static void checkArgumentName(const QCString &name,bool isParam) argName=argName.stripWhiteSpace(); //printf("argName=`%s' aName=%s\n",argName.data(),aName.data()); if (argName.right(3)=="...") argName=argName.left(argName.length()-3); - if (aName==argName) + if (aName==argName && isParam) { g_paramsFound.insert(aName,(void *)(0x8)); found=TRUE; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 2d55ae6..26f7637 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -104,6 +104,7 @@ #include "context.h" #include "fileparser.h" #include "emoji.h" +#include "plantuml.h" // provided by the generated file resources.cpp extern void initResources(); @@ -11924,6 +11925,10 @@ void generateOutput() g_s.end(); } + g_s.begin("Running plantuml with JAVA...\n"); + PlantumlManager::instance()->run(); + g_s.end(); + if (Config_getBool(HAVE_DOT)) { g_s.begin("Running dot...\n"); diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 5f10669..1f0c356 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -2411,9 +2411,7 @@ static void startCommentBlock(bool brief) static void handleCommentBlock(const QCString &doc,bool brief) { - bool needsEntry = FALSE; static bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); - int position=0; if (docBlockInBody && hideInBodyDocs) { docBlockInBody = FALSE; @@ -2421,10 +2419,13 @@ static void handleCommentBlock(const QCString &doc,bool brief) } DBG_CTX((stderr,"call parseCommentBlock [%s]\n",doc.data())); int lineNr = brief ? current->briefLine : current->docLine; + int position=0; + bool needsEntry = FALSE; + QCString processedDoc = preprocessCommentBlock(doc,yyFileName,lineNr); while (parseCommentBlock( g_thisParser, docBlockInBody ? subrCurrent.getFirst() : current, - doc, // text + processedDoc, // text yyFileName, // file lineNr, docBlockInBody ? FALSE : brief, diff --git a/src/growbuf.h b/src/growbuf.h index bc8e4b5..4c49dce 100644 --- a/src/growbuf.h +++ b/src/growbuf.h @@ -11,11 +11,21 @@ class GrowBuf { public: GrowBuf() : str(0), pos(0), len(0) {} + GrowBuf(int initialSize) : pos(0), len(initialSize) { str=(char*)malloc(len); } ~GrowBuf() { free(str); str=0; pos=0; len=0; } void clear() { pos=0; } void addChar(char c) { if (pos>=len) { len+=GROW_AMOUNT; str = (char*)realloc(str,len); } str[pos++]=c; } + void addStr(const QCString &s) { + if (!s.isEmpty()) + { + int l=s.length(); + if (pos+l>=len) { len+=l+GROW_AMOUNT; str = (char*)realloc(str,len); } + strcpy(&str[pos],s.data()); + pos+=l; + } + } void addStr(const char *s) { if (s) { diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index f89f79e..25166bc 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -126,7 +126,6 @@ static bool mustBeOutsideParagraph(DocNode *n) case DocNode::Kind_Internal: /* <div> */ case DocNode::Kind_Include: - case DocNode::Kind_Image: case DocNode::Kind_SecRefList: /* <hr> */ case DocNode::Kind_HorRuler: @@ -152,6 +151,8 @@ static bool mustBeOutsideParagraph(DocNode *n) ((DocStyleChange*)n)->style()==DocStyleChange::Center; case DocNode::Kind_Formula: return !((DocFormula*)n)->isInline(); + case DocNode::Kind_Image: + return !((DocImage*)n)->isInlineImage(); default: break; } @@ -210,29 +211,31 @@ static bool isInvisibleNode(DocNode *node) ; } -static QString htmlAttribsToString(const HtmlAttribList &attribs, bool img_tag = FALSE) +static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAltValue = 0) { - QString result; + QCString result; HtmlAttribListIterator li(attribs); HtmlAttrib *att; - bool alt_set = FALSE; - for (li.toFirst();(att=li.current());++li) { if (!att->value.isEmpty()) // ignore attribute without values as they // are not XHTML compliant, with the exception // of the alt attribute with the img tag { - result+=" "; - result+=att->name; - result+="=\""+convertToXML(att->value)+"\""; - if (att->name == "alt") alt_set = TRUE; + if (att->name=="alt" && pAltValue) // optionally return the value of alt separately + // need to convert <img> to <object> for SVG images, + // which do not support the alt attribute + { + *pAltValue = att->value; + } + else + { + result+=" "; + result+=att->name; + result+="=\""+convertToXML(att->value)+"\""; + } } } - if (!alt_set && img_tag) - { - result+=" alt=\"\""; - } return result; } @@ -588,9 +591,14 @@ void HtmlDocVisitor::visit(DocVerbatim *s) case DocVerbatim::PlantUML: { forceEndParagraph(s); - static QCString htmlOutput = Config_getString(HTML_OUTPUT); - QCString baseName = writePlantUMLSource(htmlOutput,s->exampleFile(),s->text()); + QCString imgExt = getDotImageExtension(); + PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP + if (imgExt=="svg") + { + format = PlantumlManager::PUML_SVG; + } + QCString baseName = PlantumlManager::instance()->writePlantUMLSource(htmlOutput,s->exampleFile(),s->text(),format); m_t << "<div class=\"plantumlgraph\">" << endl; writePlantUMLFile(baseName,s->relPath(),s->context()); visitPreCaption(m_t, s); @@ -1205,6 +1213,10 @@ void HtmlDocVisitor::visitPre(DocPara *p) void HtmlDocVisitor::visitPost(DocPara *p) { + + //printf("DocPara::visitPost: parent of kind %d ", + // p->parent() ? p->parent()->kind() : -1); + bool needsTag = FALSE; if (p->parent()) { @@ -1577,7 +1589,7 @@ void HtmlDocVisitor::visitPre(DocHRef *href) else { QCString url = correctURL(href->url(),href->relPath()); - m_t << "<a href=\"" << convertToXML(url) << "\"" + m_t << "<a href=\"" << convertToHtml(url) << "\"" << htmlAttribsToString(href->attribs()) << ">"; } } @@ -1635,62 +1647,40 @@ void HtmlDocVisitor::visitPre(DocImage *img) sizeAttribs+=" height=\""+img->height()+"\""; } // 16 cases: url.isEmpty() | typeSVG | inlineImage | img->hasCaption() + QCString alt; + QCString attrs = htmlAttribsToString(img->attribs(),&alt); + QCString src; if (url.isEmpty()) { - if (typeSVG) + src = img->relPath()+img->name(); + } + else + { + src = correctURL(url,img->relPath()); + } + if (typeSVG) + { + m_t << "<object type=\"image/svg+xml\" style=\"pointer-events: none;\" data=\"" << src + << "\"" << sizeAttribs << attrs; + if (inlineImage) { - m_t << "<object type=\"image/svg+xml\" style=\"pointer-events: none;\" data=\"" << img->relPath() << img->name() - << "\"" << sizeAttribs << htmlAttribsToString(img->attribs()); - if (inlineImage) - { - // skip closing tag - } - else - { - m_t << "></object>" << endl; - } + // skip closing tag } else { - m_t << "<img src=\"" << img->relPath() << img->name() << "\" alt=\"" - << baseName << "\"" << sizeAttribs << htmlAttribsToString(img->attribs()); - if (inlineImage) - { - m_t << " class=\"inline\""; - } - else - { - m_t << "/>\n"; - } + m_t << ">" << alt << "</object>" << endl; } } - else // link to URL + else { - if (typeSVG) + m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs; + if (inlineImage) { - m_t << "<object type=\"image/svg+xml\" style=\"pointer-events: none;\" data=\"" << correctURL(url,img->relPath()) - << "\"" << sizeAttribs << htmlAttribsToString(img->attribs()); - if (inlineImage) - { - // skip closing > - } - else - { - m_t << "></object>" << endl; - } + m_t << " class=\"inline\""; } else { - m_t << "<img src=\"" << correctURL(url,img->relPath()) << "\"" - << sizeAttribs << htmlAttribsToString(img->attribs(), TRUE); - if (inlineImage) - { - m_t << " class=\"inline\""; // skip closing > - } - else - { - m_t << "/>\n"; - } + m_t << "/>\n"; } } if (img->hasCaption()) @@ -1709,7 +1699,7 @@ void HtmlDocVisitor::visitPre(DocImage *img) { if (typeSVG) { - m_t << "></object>"; + m_t << ">" << alt << "</object>"; } else { @@ -1736,7 +1726,9 @@ void HtmlDocVisitor::visitPost(DocImage *img) { if (img->isSVG()) { - m_t << "\"></object>"; + QCString alt; + QCString attrs = htmlAttribsToString(img->attribs(),&alt); + m_t << "\">" << alt << "</object>"; } else { @@ -2318,7 +2310,7 @@ void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, QCString imgExt = getDotImageExtension(); if (imgExt=="svg") { - generatePlantUMLOutput(fileName,outDir,PUML_SVG); + PlantumlManager::instance()->generatePlantUMLOutput(fileName,outDir,PlantumlManager::PUML_SVG); //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />" << endl; //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>"; //m_t << "</iframe>" << endl; @@ -2326,7 +2318,7 @@ void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, } else { - generatePlantUMLOutput(fileName,outDir,PUML_BITMAP); + PlantumlManager::instance()->generatePlantUMLOutput(fileName,outDir,PlantumlManager::PUML_BITMAP); m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />" << endl; } } diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index 5be3fc9..463eedf 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -280,7 +280,7 @@ void LatexDocVisitor::visit(DocLineBreak *) void LatexDocVisitor::visit(DocHorRuler *) { if (m_hide) return; - m_t << "\n\n"; + m_t << "\\DoxyHorRuler\n"; } void LatexDocVisitor::visit(DocStyleChange *s) @@ -428,7 +428,7 @@ void LatexDocVisitor::visit(DocVerbatim *s) case DocVerbatim::PlantUML: { QCString latexOutput = Config_getString(LATEX_OUTPUT); - QCString baseName = writePlantUMLSource(latexOutput,s->exampleFile(),s->text()); + QCString baseName = PlantumlManager::instance()->writePlantUMLSource(latexOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_EPS); writePlantUMLFile(baseName, s); } @@ -1927,7 +1927,7 @@ void LatexDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim *s shortName=shortName.right(shortName.length()-i-1); } QCString outDir = Config_getString(LATEX_OUTPUT); - generatePlantUMLOutput(baseName,outDir,PUML_EPS); + PlantumlManager::instance()->generatePlantUMLOutput(baseName,outDir,PlantumlManager::PUML_EPS); visitPreStart(m_t, s->hasCaption(), shortName, s->width(), s->height()); visitCaption(this, s->children()); visitPostEnd(m_t, s->hasCaption()); diff --git a/src/markdown.cpp b/src/markdown.cpp index b00070e..5253333 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -2451,8 +2451,8 @@ static QCString extractPageTitle(QCString &docs,QCString &id) static QCString detab(const QCString &s,int &refIndent) { static int tabSize = Config_getInt(TAB_SIZE); - GrowBuf out; int size = s.length(); + GrowBuf out(size); const char *data = s.data(); int i=0; int col=0; @@ -2601,19 +2601,20 @@ void MarkdownFileParser::parseInput(const char *fileName, } } int lineNr=1; - int position=0; // even without markdown support enabled, we still // parse markdown files as such bool markdownEnabled = Doxygen::markdownSupport; Doxygen::markdownSupport = TRUE; - bool needsEntry = FALSE; Protection prot=Public; + bool needsEntry = FALSE; + int position=0; + QCString processedDocs = preprocessCommentBlock(docs,fileName,lineNr); while (parseCommentBlock( this, current, - docs, + processedDocs, fileName, lineNr, FALSE, // isBrief diff --git a/src/memberdef.cpp b/src/memberdef.cpp index a2fcf69..bcef5ac 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -1080,6 +1080,7 @@ QCString MemberDef::anchor() const void MemberDef::_computeLinkableInProject() { static bool extractStatic = Config_getBool(EXTRACT_STATIC); + static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL); m_isLinkableCached = 2; // linkable //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data()); if (isHidden()) @@ -1133,7 +1134,8 @@ void MemberDef::_computeLinkableInProject() m_isLinkableCached = 1; // in file (and not in namespace) but file not linkable return; } - if (!protectionLevelVisible(m_impl->prot) && m_impl->mtype!=MemberType_Friend) + if ((!protectionLevelVisible(m_impl->prot) && m_impl->mtype!=MemberType_Friend) && + !(m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual)) { //printf("private and invisible!\n"); m_isLinkableCached = 1; // hidden due to protection @@ -1315,6 +1317,7 @@ ClassDef *MemberDef::getClassDefOfAnonymousType() bool MemberDef::isBriefSectionVisible() const { static bool extractStatic = Config_getBool(EXTRACT_STATIC); + static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL); static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); static bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC); static bool repeatBrief = Config_getBool(REPEAT_BRIEF); @@ -1365,9 +1368,12 @@ bool MemberDef::isBriefSectionVisible() const ); // only include members that are non-private unless EXTRACT_PRIVATE is - // set to YES or the member is part of a group + // set to YES or the member is part of a group. And as a special case, + // private *documented* virtual members are shown if EXTRACT_PRIV_VIRTUAL + // is set to YES bool visibleIfPrivate = (protectionLevelVisible(protection()) || - m_impl->mtype==MemberType_Friend + m_impl->mtype==MemberType_Friend || + (m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual && hasDocs) ); // hide member if it overrides a member in a superclass and has no @@ -1639,11 +1645,12 @@ void MemberDef::writeDeclaration(OutputList &ol, if (!name().isEmpty() && name().at(0)!='@') // hide anonymous stuff { static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); + static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL); static bool extractStatic = Config_getBool(EXTRACT_STATIC); //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d hasDocumentation=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable(),hasDocumentation()); if (!(name().isEmpty() || name().at(0)=='@') && // name valid (hasDocumentation() || isReference()) && // has docs - !(m_impl->prot==Private && !extractPrivate && m_impl->mtype!=MemberType_Friend) && // hidden due to protection + !(m_impl->prot==Private && !extractPrivate && (m_impl->virt==Normal || !extractPrivateVirtual) && m_impl->mtype!=MemberType_Friend) && // hidden due to protection !(isStatic() && m_impl->classDef==0 && !extractStatic) // hidden due to static-ness ) { @@ -1896,6 +1903,7 @@ bool MemberDef::isDetailedSectionLinkable() const static bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC); static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); static bool extractStatic = Config_getBool(EXTRACT_STATIC); + static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL); // the member has details documentation for any of the following reasons bool docFilter = @@ -1933,7 +1941,8 @@ bool MemberDef::isDetailedSectionLinkable() const // only include members that are non-private unless EXTRACT_PRIVATE is // set to YES or the member is part of a group - bool privateFilter = protectionLevelVisible(protection()) || m_impl->mtype==MemberType_Friend; + bool privateFilter = protectionLevelVisible(protection()) || m_impl->mtype==MemberType_Friend || + (m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual); // member is part of an anonymous scope that is the type of // another member in the list. diff --git a/src/plantuml.cpp b/src/plantuml.cpp index ada035b..ff4ebd3 100644 --- a/src/plantuml.cpp +++ b/src/plantuml.cpp @@ -14,23 +14,32 @@ */ #include "plantuml.h" +#include "util.h" #include "portable.h" #include "config.h" #include "doxygen.h" #include "index.h" #include "message.h" +#include "debug.h" #include <qdir.h> +#include <qdict.h> +#include <qlist.h> -static const int maxCmdLine = 40960; -QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content) +QCString PlantumlManager::writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content,OutputFormat format) { - QCString baseName(4096); + QCString baseName; + QCString puName; + QCString imgName; static int umlindex=1; + Debug::print(Debug::Plantuml,0,"*** %s fileName: %s\n","writePlantUMLSource",qPrint(fileName)); + Debug::print(Debug::Plantuml,0,"*** %s outDir: %s\n","writePlantUMLSource",qPrint(outDir)); + if (fileName.isEmpty()) // generate name { + puName = "inline_umlgraph_"+QCString().setNum(umlindex); baseName = outDir+"/inline_umlgraph_"+QCString().setNum(umlindex++); } else // user specified name @@ -38,29 +47,158 @@ QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,con baseName = fileName; int i=baseName.findRev('.'); if (i!=-1) baseName = baseName.left(i); + puName = baseName; baseName.prepend(outDir+"/"); } - QFile file(baseName+".pu"); - if (!file.open(IO_WriteOnly)) + + switch (format) { - err("Could not open file %s for writing\n",baseName.data()); + case PUML_BITMAP: + imgName =puName+".png"; + break; + case PUML_EPS: + imgName =puName+".eps"; + break; + case PUML_SVG: + imgName =puName+".svg"; + break; } - QCString text = "@startuml\n"; + + Debug::print(Debug::Plantuml,0,"*** %s baseName: %s\n","writePlantUMLSource",qPrint(baseName)); + Debug::print(Debug::Plantuml,0,"*** %s puName: %s\n","writePlantUMLSource",qPrint(puName)); + Debug::print(Debug::Plantuml,0,"*** %s imgName: %s\n","writePlantUMLSource",qPrint(imgName)); + + QCString text = "@startuml "+imgName+"\n"; text+=content; text+="\n@enduml\n"; - file.writeBlock( text, text.length() ); - file.close(); + + QCString qcOutDir(outDir); + uint pos = qcOutDir.findRev("/"); + QCString generateType(qcOutDir.right(qcOutDir.length() - (pos + 1)) ); + Debug::print(Debug::Plantuml,0,"*** %s generateType: %s\n","writePlantUMLSource",qPrint(generateType)); + PlantumlManager::instance()->insert(generateType,puName,format,text); + Debug::print(Debug::Plantuml,0,"*** %s generateType: %s\n","writePlantUMLSource",qPrint(generateType)); + return baseName; } -void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format) +void PlantumlManager::generatePlantUMLOutput(const char *baseName,const char *outDir,OutputFormat format) +{ + QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); + QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE); + QCString dotPath = Config_getString(DOT_PATH); + + QCString imgName = baseName; + // The basename contains path, we need to strip the path from the filename in order + // to create the image file name which should be included in the index.qhp (Qt help index file). + int i; + if ((i=imgName.findRev('/'))!=-1) // strip path + { + imgName=imgName.right(imgName.length()-i-1); + } + switch (format) + { + case PUML_BITMAP: + imgName+=".png"; + break; + case PUML_EPS: + imgName+=".eps"; + break; + case PUML_SVG: + imgName+=".svg"; + break; + } + + Doxygen::indexList->addImageFile(imgName); +} + +//-------------------------------------------------------------------- + +PlantumlManager *PlantumlManager::m_theInstance = 0; + +PlantumlManager *PlantumlManager::instance() +{ + if (!m_theInstance) + { + m_theInstance = new PlantumlManager; + QCString outputFilename = Config_getString(OUTPUT_DIRECTORY) + "/" + CACHE_FILENAME; + QFileInfo fi(outputFilename); + if (fi.exists()) + { + m_theInstance->m_cachedPlantumlAllContent = fileToString(outputFilename); + } + else + { + m_theInstance->m_cachedPlantumlAllContent = ""; + } + Debug::print(Debug::Plantuml,0,"*** instance() : m_cachedPlantumlAllContent = [%s]\n",qPrint(m_theInstance->m_cachedPlantumlAllContent)); + m_theInstance->m_pngPlantumlContent.clear(); + m_theInstance->m_svgPlantumlContent.clear(); + m_theInstance->m_epsPlantumlContent.clear(); + } + return m_theInstance; +} + +PlantumlManager::PlantumlManager() { - static QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); - static QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE); - static QCString dotPath = Config_getString(DOT_PATH); +} + +PlantumlManager::~PlantumlManager() +{ + { + QDictIterator< QList<QCString> > it( m_pngPlantumlFiles); // See QDictIterator + QList<QCString> *list; + for (it.toFirst();(list=it.current());++it) + { + (*list).clear(); + } + m_pngPlantumlFiles.clear(); + m_pngPlantumlContent.clear(); + } + { + QDictIterator< QList<QCString> > it( m_epsPlantumlFiles); // See QDictIterator + QList<QCString> *list; + for (it.toFirst();(list=it.current());++it) + { + (*list).clear(); + } + m_epsPlantumlFiles.clear(); + m_epsPlantumlContent.clear(); + } + { + QDictIterator< QList<QCString> > it( m_svgPlantumlFiles); // See QDictIterator + QList<QCString> *list; + for (it.toFirst();(list=it.current());++it) + { + (*list).clear(); + } + m_svgPlantumlFiles.clear(); + m_svgPlantumlContent.clear(); + } +} + +static void runPlantumlContent(const QDict< QList <QCString> > &plantumlFiles, + const QDict< QCString > &plantumlContent, + PlantumlManager::OutputFormat format) +{ + /* example : running: java -Djava.awt.headless=true + -jar "/usr/local/bin/plantuml.jar" + -o "test_doxygen/DOXYGEN_OUTPUT/html" + -tpng + "test_doxygen/DOXYGEN_OUTPUT/html/A.pu" + -charset UTF-8 + outDir:test_doxygen/DOXYGEN_OUTPUT/html + test_doxygen/DOXYGEN_OUTPUT/html/A + */ + int exitCode; + QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); + QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE); + QCString dotPath = Config_getString(DOT_PATH); QCString pumlExe = "java"; QCString pumlArgs = ""; + QCString pumlType = ""; + QCString pumlOutDir = ""; QStrList &pumlIncludePathList = Config_getList(PLANTUML_INCLUDE_PATH); char *s=pumlIncludePathList.first(); @@ -92,61 +230,211 @@ void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutp pumlArgs += portable_commandExtension(); pumlArgs += "\" "; } - pumlArgs+="-o \""; - pumlArgs+=outDir; - pumlArgs+="\" "; - QCString imgName = baseName; - // The basename contains path, we need to strip the path from the filename in order - // to create the image file name which should be included in the index.qhp (Qt help index file). - int i; - if ((i=imgName.findRev('/'))!=-1) // strip path - { - imgName=imgName.right(imgName.length()-i-1); - } switch (format) { - case PUML_BITMAP: - pumlArgs+="-tpng"; - imgName+=".png"; + case PlantumlManager::PUML_BITMAP: + pumlType="png"; break; - case PUML_EPS: - pumlArgs+="-teps"; - imgName+=".eps"; + case PlantumlManager::PUML_EPS: + pumlType="eps"; break; - case PUML_SVG: - pumlArgs+="-tsvg"; - imgName+=".svg"; + case PlantumlManager::PUML_SVG: + pumlType="svg"; break; } - pumlArgs+=" \""; - pumlArgs+=baseName; - pumlArgs+=".pu\" "; - pumlArgs+="-charset UTF-8 "; - int exitCode; - //printf("*** running: %s %s outDir:%s %s\n",pumlExe.data(),pumlArgs.data(),outDir,baseName); - msg("Running PlantUML on generated file %s.pu\n",baseName); - portable_sysTimerStart(); - if ((exitCode=portable_system(pumlExe,pumlArgs,TRUE))!=0) + { - err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n", - plantumlJarPath.data(),exitCode); + QDictIterator< QCString > it( plantumlContent); // See QDictIterator + QCString *nb; + for (it.toFirst();(nb=it.current());++it) + { + QCString pumlArguments(pumlArgs); + msg("Generating PlantUML %s Files in %s\n",qPrint(pumlType),qPrint(it.currentKey())); + pumlArguments+="-o \""; + pumlArguments+=Config_getString(OUTPUT_DIRECTORY); + pumlArguments+="/"; + pumlArguments+=it.currentKey(); + pumlArguments+="\" "; + pumlArguments+="-charset UTF-8 -t"; + pumlArguments+=pumlType; + pumlArguments+=" "; + + QCString puFileName(""); + puFileName+=Config_getString(OUTPUT_DIRECTORY); + puFileName+="/"; + puFileName+=it.currentKey(); + puFileName+="/"; + pumlOutDir=puFileName; + puFileName+="inline_umlgraph_"; + puFileName+=pumlType; + puFileName+=it.currentKey(); + puFileName+=".pu"; + + pumlArguments+="\""; + pumlArguments+=puFileName; + pumlArguments+="\" "; + + QFile file(puFileName); + if (!file.open(IO_WriteOnly)) + { + err("Could not open file %s for writing\n",puFileName.data()); + } + file.writeBlock( *nb, nb->length() ); + file.close(); + Debug::print(Debug::Plantuml,0,"*** %s Running Plantuml arguments:%s\n","PlantumlManager::runPlantumlContent",qPrint(pumlArguments)); + + portable_sysTimerStart(); + if ((exitCode=portable_system(pumlExe,pumlArguments,TRUE))!=0) + { + err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n", + plantumlJarPath.data(),exitCode); + } + else if (Config_getBool(DOT_CLEANUP)) + { + Debug::print(Debug::Plantuml,0,"*** %s Remove %s file\n","PlantumlManager::runPlantumlContent",qPrint(puFileName)); + file.remove(); + } + portable_sysTimerStop(); + + if ( (format==PlantumlManager::PUML_EPS) && (Config_getBool(USE_PDFLATEX)) ) + { + Debug::print(Debug::Plantuml,0,"*** %s Running epstopdf\n","PlantumlManager::runPlantumlContent"); + QList<QCString> *list = plantumlFiles[it.currentKey()]; + if (list) + { + QListIterator<QCString> li(*list); + QCString *nb; + for (li.toFirst();(nb=li.current());++li) + { + const int maxCmdLine = 40960; + QCString epstopdfArgs(maxCmdLine); + epstopdfArgs.sprintf("\"%s%s.eps\" --outfile=\"%s%s.pdf\"",qPrint(pumlOutDir),qPrint(*nb),qPrint(pumlOutDir),qPrint(*nb)); + portable_sysTimerStart(); + if ((exitCode=portable_system("epstopdf",epstopdfArgs))!=0) + { + err("Problems running epstopdf. Check your TeX installation! Exit code: %d\n",exitCode); + } + portable_sysTimerStop(); + } + } + } + } } - else if (Config_getBool(DOT_CLEANUP)) +} + +void PlantumlManager::run() +{ + Debug::print(Debug::Plantuml,0,"*** %s\n","PlantumlManager::run"); + if (m_currentPlantumlAllContent.isEmpty()) return; + runPlantumlContent(m_pngPlantumlFiles, m_pngPlantumlContent, PUML_BITMAP); + runPlantumlContent(m_svgPlantumlFiles, m_svgPlantumlContent, PUML_SVG); + runPlantumlContent(m_epsPlantumlFiles, m_epsPlantumlContent, PUML_EPS); + QCString outputFilename = Config_getString(OUTPUT_DIRECTORY) + "/" + CACHE_FILENAME; + QFile file(outputFilename); + if (!file.open(IO_WriteOnly)) { - QFile(QCString(baseName)+".pu").remove(); + err("Could not open file %s for writing\n",CACHE_FILENAME); } - portable_sysTimerStop(); - if ( (format==PUML_EPS) && (Config_getBool(USE_PDFLATEX)) ) + file.writeBlock( m_currentPlantumlAllContent, m_currentPlantumlAllContent.length() ); + file.close(); +} + +static void print(const QDict< QList <QCString> > &plantumlFiles) +{ + if (Debug::isFlagSet(Debug::Plantuml)) { - QCString epstopdfArgs(maxCmdLine); - epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",baseName,baseName); - portable_sysTimerStart(); - if ((exitCode=portable_system("epstopdf",epstopdfArgs))!=0) + QDictIterator< QList<QCString> > it( plantumlFiles); // See QDictIterator + QList<QCString> *list; + for (it.toFirst();(list=it.current());++it) { - err("Problems running epstopdf. Check your TeX installation! Exit code: %d\n",exitCode); + Debug::print(Debug::Plantuml,0,"*** %s PlantumlFiles key:%s size:%d\n","PlantumlManager::print Files",qPrint(it.currentKey()),(*list).count()); + QListIterator<QCString> li(*list); + QCString *nb; + for (li.toFirst();(nb=li.current());++li) + { + Debug::print(Debug::Plantuml,0,"*** %s list:%s\n","PlantumlManager::print",qPrint(*nb)); + } } - portable_sysTimerStop(); } - Doxygen::indexList->addImageFile(imgName); } +static void print(const QDict<QCString> &plantumlContent) +{ + if (Debug::isFlagSet(Debug::Plantuml)) + { + QDictIterator< QCString > it( plantumlContent); // See QDictIterator + QCString *nb; + for (it.toFirst();(nb=it.current());++it) + { + Debug::print(Debug::Plantuml,0,"*** %s PlantumlContent key:%s\n","PlantumlManager::print Content",qPrint(it.currentKey())); + Debug::print(Debug::Plantuml,0,"*** %s Content :%s\n","PlantumlManager::print",qPrint(*nb)); + } + } +} + +static void addPlantumlFiles(QDict< QList<QCString> > &plantumlFiles, + const QCString &key , const QCString &value) +{ + QList<QCString> *list = plantumlFiles.find(key); + if (list==0) + { + list = new QList<QCString>; + plantumlFiles.insert(key,list); + } + list->append(new QCString(value)); +} + +static void addPlantumlContent(QDict< QCString > &plantumlContent, + const QCString &key, const QCString &puContent) +{ + QCString* content = plantumlContent.find(key); + if (content == 0) + { + content = new QCString(""); + plantumlContent.insert(key,content); + } + (*content)+=puContent; +} + + + +void PlantumlManager::insert(const QCString &key, const QCString &value, + OutputFormat format,const QCString &puContent) +{ + int find; + + Debug::print(Debug::Plantuml,0,"*** %s key:%s ,value:%s\n","PlantumlManager::insert",qPrint(key),qPrint(value)); + + m_currentPlantumlAllContent+=puContent; + + find = m_cachedPlantumlAllContent.find(puContent); + Debug::print(Debug::Plantuml,0,"*** %s find: %d\n","PlantumlManager::addPlantumlContent",find); + if (find >=0) + { // matched in cache. so we skip to run java for this plantuml + return ; + } + + switch (format) + { + case PUML_BITMAP: + addPlantumlFiles(m_pngPlantumlFiles,key,value); + print(m_pngPlantumlFiles); + addPlantumlContent(m_pngPlantumlContent,key,puContent); + print(m_pngPlantumlContent); + break; + case PUML_EPS: + addPlantumlFiles(m_epsPlantumlFiles,key,value); + print(m_epsPlantumlFiles); + addPlantumlContent(m_epsPlantumlContent,key,puContent); + print(m_epsPlantumlContent); + break; + case PUML_SVG: + addPlantumlFiles(m_svgPlantumlFiles,key,value); + print(m_svgPlantumlFiles); + addPlantumlContent(m_svgPlantumlContent,key,puContent); + print(m_svgPlantumlContent); + break; + } +} + +//-------------------------------------------------------------------- diff --git a/src/plantuml.h b/src/plantuml.h index 54ab8a2..6c99eba 100644 --- a/src/plantuml.h +++ b/src/plantuml.h @@ -16,25 +16,60 @@ #ifndef PLANTUML_H #define PLANTUML_H +#include <qdict.h> +#include <qlist.h> + +#define CACHE_FILENAME "inline_umlgraph_cache_all.pu" +#define DIVIDE_COUNT 4 +#define MIN_PLANTUML_COUNT 8 + class QCString; -/** Plant UML output image formats */ -enum PlantUMLOutputFormat { PUML_BITMAP, PUML_EPS, PUML_SVG }; +/** Singleton that manages plantuml relation actions */ +class PlantumlManager +{ + public: + /** Plant UML output image formats */ + enum OutputFormat { PUML_BITMAP, PUML_EPS, PUML_SVG }; -/** Write a PlantUML compatible file. - * @param[in] outDir the output directory to write the file to. - * @param[in] fileName the name of the file. If empty a name will be chosen automatically. - * @param[in] content the contents of the PlantUML file. - * @returns The name of the generated file. - */ -QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content); + static PlantumlManager *instance(); -/** Convert a PlantUML file to an image. - * @param[in] baseName the name of the generated file (as returned by writePlantUMLSource()) - * @param[in] outDir the directory to write the resulting image into. - * @param[in] format the image format to generate. - */ -void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format); + /** Run plant UML tool for all images */ + void run(); + + /** Write a PlantUML compatible file. + * @param[in] outDir the output directory to write the file to. + * @param[in] fileName the name of the file. If empty a name will be chosen automatically. + * @param[in] content the contents of the PlantUML file. + * @param[in] format the image format to generate. + * @returns The name of the generated file. + */ + QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content, OutputFormat format); + + /** Convert a PlantUML file to an image. + * @param[in] baseName the name of the generated file (as returned by writePlantUMLSource()) + * @param[in] outDir the directory to write the resulting image into. + * @param[in] format the image format to generate. + */ + void generatePlantUMLOutput(const char *baseName,const char *outDir,OutputFormat format); + + private: + PlantumlManager(); + ~PlantumlManager(); + void insert(const QCString &key, + const QCString &value, + OutputFormat format, + const QCString &puContent); + static PlantumlManager *m_theInstance; + QDict< QList<QCString> > m_pngPlantumlFiles; + QDict< QList<QCString> > m_svgPlantumlFiles; + QDict< QList<QCString> > m_epsPlantumlFiles; + QDict< QCString > m_pngPlantumlContent; // use circular queue for using multi-proecessor (multi threading) + QDict< QCString > m_svgPlantumlContent; + QDict< QCString > m_epsPlantumlContent; + QCString m_cachedPlantumlAllContent; // read from CACHE_FILENAME file + QCString m_currentPlantumlAllContent; // processing plantuml then write it into CACHE_FILENAME to reuse the next time as cache information +}; #endif diff --git a/src/pyscanner.l b/src/pyscanner.l index 1596b9d..655b6e2 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -324,11 +324,12 @@ static void handleCommentBlock(const QCString &doc,bool brief) int position = 0; bool needsEntry; int lineNr = brief ? current->briefLine : current->docLine; + QCString processedDoc = preprocessCommentBlock(doc,yyFileName,lineNr); while (parseCommentBlock( g_thisParser, (docBlockInBody && previous) ? previous : current, - doc, // text - yyFileName, // file + processedDoc, // text + yyFileName, // file lineNr, docBlockInBody ? FALSE : brief, docBlockJavaStyle, // javadoc style // or FALSE, diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index f2edf8b..1e2bb89 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -383,7 +383,7 @@ void RTFDocVisitor::visit(DocVerbatim *s) case DocVerbatim::PlantUML: { static QCString rtfOutput = Config_getString(RTF_OUTPUT); - QCString baseName = writePlantUMLSource(rtfOutput,s->exampleFile(),s->text()); + QCString baseName = PlantumlManager::instance()->writePlantUMLSource(rtfOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_BITMAP); writePlantUMLFile(baseName, s->hasCaption()); visitCaption(this, s->children()); @@ -1868,6 +1868,6 @@ void RTFDocVisitor::writePlantUMLFile(const QCString &fileName, bool hasCaption) baseName=baseName.right(baseName.length()-i-1); } QCString outDir = Config_getString(RTF_OUTPUT); - generatePlantUMLOutput(fileName,outDir,PUML_BITMAP); + PlantumlManager::instance()->generatePlantUMLOutput(fileName,outDir,PlantumlManager::PUML_BITMAP); includePicturePreRTF(baseName + ".png", true, hasCaption); } diff --git a/src/scanner.l b/src/scanner.l index 7559e0b..ee04dd9 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -2438,6 +2438,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { current->protection = Protected; } + else if ((insideCS || insideD || insidePHP || insideJS) && qstrcmp(yytext,"internal")==0) + { + current->protection = Package; + } else if (javaLike && qstrcmp(yytext,"private")==0) { current->protection = Private; @@ -6908,12 +6912,10 @@ static void newEntry() static void handleCommentBlock(const QCString &doc,bool brief) { static bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); - int position=0; - bool needsEntry=FALSE; if (docBlockInBody && hideInBodyDocs) return; //printf("parseCommentBlock [%s] brief=%d\n",doc.data(),brief); int lineNr = brief ? current->briefLine : current->docLine; // line of block start - + // fill in inbodyFile && inbodyLine the first time, see bug 633891 Entry *docEntry = docBlockInBody && previous ? previous : current; if (docBlockInBody && docEntry && docEntry->inbodyLine==-1) @@ -6922,12 +6924,15 @@ static void handleCommentBlock(const QCString &doc,bool brief) docEntry->inbodyLine = lineNr; } + int position=0; + bool needsEntry=FALSE; + QCString processedDoc = preprocessCommentBlock(stripIndentation(doc),yyFileName,lineNr); while (parseCommentBlock( g_thisParser, docBlockInBody && previous ? previous : current, - stripIndentation(doc), // text - yyFileName, // file - lineNr, // line of block start + processedDoc, // text + yyFileName, // file + lineNr, // line of block start docBlockInBody ? FALSE : brief, // isBrief docBlockInBody ? FALSE : docBlockAutoBrief, // isJavaDocStyle docBlockInBody, // isInBody @@ -6935,7 +6940,7 @@ static void handleCommentBlock(const QCString &doc,bool brief) position, needsEntry ) - ) + ) { //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position); if (needsEntry) diff --git a/src/tclscanner.l b/src/tclscanner.l index ca5294b..88714ce 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -1507,6 +1507,7 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); myO.shrink(myO.curPos()-2); myO.addChar('\0'); QCString myDoc = myO.data(); + QCString processedDoc; if (what==99) { // inbody comment file or namespace or class or proc/method int myPos0; @@ -1526,14 +1527,16 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); myPos0=myPos; myLine0=myLine; - while (parseCommentBlock(tcl.this_parser, &myEntry0, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine); + while (parseCommentBlock(tcl.this_parser, &myEntry0, processedDoc, tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew)) { if (myNew) { // we need a new entry in this case myNew=0; myEntry = tcl_entry_new(); - parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); tcl.entry_inside->addSubEntry(myEntry); } @@ -1543,7 +1546,8 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); { myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); } - parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry1, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); } myPos0=myPos; @@ -1553,7 +1557,8 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); { // we need a new entry myNew=0; myEntry = tcl_entry_new(); - parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); tcl.entry_inside->addSubEntry(myEntry); } @@ -1563,14 +1568,16 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); { myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); } - parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry1, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); } } else { // new entry tcl.entry_current = tcl_entry_new(); - while (parseCommentBlock(tcl.this_parser, tcl.entry_current, myDoc, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine); + while (parseCommentBlock(tcl.this_parser, tcl.entry_current, processedDoc, tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew)) { diff --git a/src/util.cpp b/src/util.cpp index 24e8898..9a0e513 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -5444,6 +5444,7 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor static bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES); static GrowBuf growBuf; growBuf.clear(); + if (name==0) return ""; char c; const char *p=name; while ((c=*p++)!=0) @@ -5914,7 +5915,7 @@ QCString convertToId(const char *s) } /*! Converts a string to an XML-encoded string */ -QCString convertToXML(const char *s) +QCString convertToXML(const char *s, bool keepEntities) { static GrowBuf growBuf; growBuf.clear(); @@ -5927,7 +5928,30 @@ QCString convertToXML(const char *s) { case '<': growBuf.addStr("<"); break; case '>': growBuf.addStr(">"); break; - case '&': growBuf.addStr("&"); break; + case '&': if (keepEntities) + { + const char *e=p; + char ce; + while ((ce=*e++)) + { + if (ce==';' || (!(isId(ce) || ce=='#'))) break; + } + if (ce==';') // found end of an entity + { + // copy entry verbatim + growBuf.addChar(c); + while (p<e) growBuf.addChar(*p++); + } + else + { + growBuf.addStr("&"); + } + } + else + { + growBuf.addStr("&"); + } + break; case '\'': growBuf.addStr("'"); break; case '"': growBuf.addStr("""); break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: @@ -6939,6 +6963,7 @@ void filterLatexString(FTextStream &t,const char *str, QCString latexEscapeLabelName(const char *s) { + if (s==0) return ""; QGString result; QCString tmp(qstrlen(s)+1); FTextStream t(&result); @@ -6976,6 +7001,7 @@ QCString latexEscapeLabelName(const char *s) QCString latexEscapeIndexChars(const char *s) { + if (s==0) return ""; QGString result; QCString tmp(qstrlen(s)+1); FTextStream t(&result); @@ -7014,6 +7040,7 @@ QCString latexEscapeIndexChars(const char *s) QCString latexEscapePDFString(const char *s) { + if (s==0) return ""; QGString result; FTextStream t(&result); const char *p=s; @@ -7038,6 +7065,7 @@ QCString latexEscapePDFString(const char *s) QCString latexFilterURL(const char *s) { + if (s==0) return ""; QGString result; FTextStream t(&result); const char *p=s; @@ -284,7 +284,7 @@ QCString convertToHtml(const char *s,bool keepEntities=TRUE); QCString convertToLaTeX(const QCString &s,bool insideTabbing=FALSE,bool keepSpaces=FALSE); -QCString convertToXML(const char *s); +QCString convertToXML(const char *s, bool keepEntities=FALSE); QCString convertToDocBook(const char *s); diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index b18bd3f..808b32b 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -3774,8 +3774,8 @@ void FlowChart::printUmlTree() QCString n=convertNameToFileName(); QCString tmp=htmlOutDir; - n=writePlantUMLSource(tmp,n,qcs); - generatePlantUMLOutput(n.data(),tmp.data(),PUML_SVG); + n=PlantumlManager::instance()->writePlantUMLSource(tmp,n,qcs,PlantumlManager::PUML_SVG); + PlantumlManager::instance()->generatePlantUMLOutput(n.data(),tmp.data(),PlantumlManager::PUML_SVG); } QCString FlowChart::convertNameToFileName() diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 81a7ca1..4a312bd 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -244,7 +244,6 @@ void VhdlParser::handleFlowComment(const char* doc) void VhdlParser::handleCommentBlock(const char* doc1,bool brief) { - int position=0; QCString doc; doc.append(doc1); // fprintf(stderr,"\n %s",doc.data()); @@ -258,7 +257,6 @@ void VhdlParser::handleCommentBlock(const char* doc1,bool brief) VhdlDocGen::prepareComment(doc); - bool needsEntry=FALSE; Protection protection=Public; if (oldEntry==current) @@ -290,10 +288,13 @@ void VhdlParser::handleCommentBlock(const char* doc1,bool brief) current->stat=true; } + int position=0; + bool needsEntry=FALSE; + QCString processedDoc = preprocessCommentBlock(doc,yyFileName,iDocLine); while (parseCommentBlock( g_thisParser, current, - doc, // text + processedDoc, // text yyFileName, // file iDocLine, // line of block start brief, diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index e464088..01e0a6d 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -60,7 +60,7 @@ static void visitPreStart(FTextStream &t, const char *cmd, bool doCaption, } if (!name.isEmpty()) { - t << " name=\"" << name << "\""; + t << " name=\"" << convertToXML(name, TRUE) << "\""; } if (!width.isEmpty()) { @@ -770,9 +770,7 @@ void XmlDocVisitor::visitPost(DocInternal *) void XmlDocVisitor::visitPre(DocHRef *href) { if (m_hide) return; - m_t << "<ulink url=\""; - filter(href->url()); - m_t << "\">"; + m_t << "<ulink url=\"" << convertToXML(href->url(), TRUE) << "\">"; } void XmlDocVisitor::visitPost(DocHRef *) |