summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri van Heesch <doxygen@gmail.com>2020-06-13 18:48:05 (GMT)
committerDimitri van Heesch <doxygen@gmail.com>2020-06-13 18:48:05 (GMT)
commit12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1 (patch)
tree1b5e18df7e97929fb2d453a92156354991da2cd3
parent07dd4ae9033c9872d70d68ff1d83ec46f1db7cb4 (diff)
parent65bf92c94f2118b0f6e6c19e62993c6e27ebbef9 (diff)
downloadDoxygen-12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1.zip
Doxygen-12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1.tar.gz
Doxygen-12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1.tar.bz2
Merge branch 'master' of github.com:doxygen/doxygen
-rw-r--r--doc/CMakeLists.txt10
-rw-r--r--doc/customize.doc3
-rw-r--r--libmscgen/mscgen_api.c1
-rw-r--r--src/cite.cpp6
-rw-r--r--src/context.cpp2
-rw-r--r--src/dirdef.cpp2
-rw-r--r--src/dirdef.h4
-rw-r--r--src/dotfilepatcher.cpp2
-rw-r--r--src/dotgraph.cpp2
-rw-r--r--src/latexgen.cpp10
-rw-r--r--src/markdown.cpp7
-rw-r--r--src/memberdef.cpp7
-rw-r--r--src/template.cpp6
-rw-r--r--src/translator.h5
-rw-r--r--src/translator_gr.h24
-rw-r--r--src/util.cpp20
-rw-r--r--src/util.h1
-rw-r--r--src/xmlgen.cpp7
-rw-r--r--templates/xml/compound.xsd2
-rw-r--r--testing/037/037__msc_8cpp.xml27
-rw-r--r--testing/037/class_receiver.xml4
-rw-r--r--testing/037/class_sender.xml4
-rw-r--r--testing/037_msc.cpp18
-rwxr-xr-xtesting/runtests.py68
24 files changed, 200 insertions, 42 deletions
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 537089b..df9c2a6 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -212,12 +212,22 @@ install(FILES
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
)
+install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf\")
+ message(FATAL_ERROR \"\nTerminating:\n documentation has not been generated, \n create documentation by using the 'docs' target followed by an 'install'\n\")
+endif()"
+)
+
install(FILES
"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)
if (build_doc_chm)
+install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm\")
+ message(FATAL_ERROR \"\nTerminating:\n CHM documentation has not been generated, \n create CHM documentation by using the 'docs_chm' target followed by an 'install'\n\")
+endif()"
+)
+
install(FILES
"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
diff --git a/doc/customize.doc b/doc/customize.doc
index 7b2729d..52f8d7a 100644
--- a/doc/customize.doc
+++ b/doc/customize.doc
@@ -372,7 +372,8 @@ generated output!
If the above two methods still do not provide enough flexibility, you
can also use the XML output produced by doxygen as a basis to
-generate the output you like. To do this set GENERATE_XML to YES.
+generate the output you like. To do this set
+\ref cfg_generate_xml "GENERATE_XML" to \c YES.
The XML output consists of an index file named \c index.xml which
lists all items extracted by doxygen with references to the other XML files
diff --git a/libmscgen/mscgen_api.c b/libmscgen/mscgen_api.c
index 376b9d8..e2cdcb9 100644
--- a/libmscgen/mscgen_api.c
+++ b/libmscgen/mscgen_api.c
@@ -457,6 +457,7 @@ static RowInfo *computeCanvasSize(Context *ctx,
nextYmin = ymin = ctx->opts.entityHeadGap;
yskipmax = 0;
+ ymax = 0;
MscResetArcIterator(m);
do
{
diff --git a/src/cite.cpp b/src/cite.cpp
index 4adf6f2..82f9e6d 100644
--- a/src/cite.cpp
+++ b/src/cite.cpp
@@ -203,7 +203,11 @@ void CitationManager::generatePage()
QCString bibOutputDir = outputDir+"/"+bibTmpDir;
QCString bibOutputFiles = "";
QDir thisDir;
- thisDir.mkdir(bibOutputDir);
+ if (!thisDir.exists(bibOutputDir) && !thisDir.mkdir(bibOutputDir))
+ {
+ err("Failed to create temorary output directory '%s', skiping citations\n",bibOutputDir.data());
+ return;
+ }
int i = 0;
for (const auto &bibdata : citeDataList)
{
diff --git a/src/context.cpp b/src/context.cpp
index d21b1d0..3d71706 100644
--- a/src/context.cpp
+++ b/src/context.cpp
@@ -10343,7 +10343,7 @@ void generateTemplateFiles(const char *templateDir)
QCString outDir = QCString(templateDir)+"/html";
if (!thisDir.exists(outDir) && !thisDir.mkdir(outDir))
{
- err("Failed to create output directory '%s'\n",templateDir);
+ err("Failed to create output directory '%s'\n",outDir.data());
return;
}
ResourceMgr::instance().writeCategory("html",outDir);
diff --git a/src/dirdef.cpp b/src/dirdef.cpp
index 7f0b524..dd8444e 100644
--- a/src/dirdef.cpp
+++ b/src/dirdef.cpp
@@ -750,7 +750,7 @@ int FilePairDict::compareValues(const FilePair *left,const FilePair *right) cons
//----------------------------------------------------------------------
-UsedDir::UsedDir(DirDef *dir,bool inherited) :
+UsedDir::UsedDir(const DirDef *dir,bool inherited) :
m_dir(dir), m_filePairs(7), m_inherited(inherited)
{
m_filePairs.setAutoDelete(TRUE);
diff --git a/src/dirdef.h b/src/dirdef.h
index 399e0c2..468901d 100644
--- a/src/dirdef.h
+++ b/src/dirdef.h
@@ -104,7 +104,7 @@ class FilePairDict : public SDict<FilePair>
class UsedDir
{
public:
- UsedDir(DirDef *dir,bool inherited);
+ UsedDir(const DirDef *dir,bool inherited);
virtual ~UsedDir();
void addFileDep(FileDef *srcFd,FileDef *dstFd);
FilePair *findFilePair(const char *name);
@@ -114,7 +114,7 @@ class UsedDir
void sort();
private:
- DirDef *m_dir;
+ const DirDef *m_dir;
FilePairDict m_filePairs;
bool m_inherited;
};
diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp
index 20ce4c1..17f8cb7 100644
--- a/src/dotfilepatcher.cpp
+++ b/src/dotfilepatcher.cpp
@@ -460,7 +460,7 @@ bool DotFilePatcher::run() const
convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context);
if (!result.isEmpty())
{
- t << "<map name=\"" << map->label << "\" id=\"" << map->label << "\">" << endl;
+ t << "<map name=\"" << map->label << "\" id=\"" << correctId(map->label) << "\">" << endl;
t << result;
t << "</map>" << endl;
}
diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp
index c0cc4fd..1ad85e1 100644
--- a/src/dotgraph.cpp
+++ b/src/dotgraph.cpp
@@ -236,7 +236,7 @@ void DotGraph::generateCode(FTextStream &t)
else // add link to bitmap file with image map
{
if (!m_noDivTag) t << "<div class=\"center\">";
- t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#" << getMapLabel() << "\" alt=\"" << getImgAltText() << "\"/>";
+ t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#" << correctId(getMapLabel()) << "\" alt=\"" << getImgAltText() << "\"/>";
if (!m_noDivTag) t << "</div>";
t << endl;
if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel()))
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index f3cce3e..cb42863 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -560,11 +560,13 @@ static void writeDefaultHeaderPart1(FTextStream &t)
{
t << "\\usepackage[" << fontenc << "]{fontenc}\n";
}
- t << "\\usepackage[scaled=.90]{helvet}\n"
- "\\usepackage{courier}\n"
- "\\usepackage{amssymb}\n"
+ QCString font = theTranslator->latexFont();
+ if (!font.isEmpty())
+ {
+ t << font;
+ }
+ t << "\\usepackage{amssymb}\n"
"\\usepackage{sectsty}\n"
- "\\renewcommand{\\familydefault}{\\sfdefault}\n"
"\\allsectionsfont{%\n"
" \\fontseries{bc}\\selectfont%\n"
" \\color{darkgray}%\n"
diff --git a/src/markdown.cpp b/src/markdown.cpp
index c4dd9fb..06b714a 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -1501,8 +1501,11 @@ static bool isFencedCodeBlock(const char *data,int size,int refIndent,
while (i<size && data[i]==' ') i++;
if (i==size || data[i]=='\n')
{
- offset=i;
- return endTildes==startTildes;
+ if (endTildes==startTildes)
+ {
+ offset=i;
+ return TRUE;
+ }
}
}
i++;
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index d857fa6..1d7909b 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -2733,7 +2733,7 @@ void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const
isFriend() || isRelated() ||
(isInline() && inlineInfo) ||
isSignal() || isSlot() ||
- isStatic() ||
+ isStatic() || isExternal() ||
(getClassDef() && getClassDef()!=container && container->definitionType()==TypeClass) ||
(m_impl->memSpec & ~Entry::Inline)!=0
)
@@ -2745,7 +2745,7 @@ void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const
//ol.docify(" [");
SrcLangExt lang = getLanguage();
bool optVhdl = lang==SrcLangExt_VHDL;
- bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
+ static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
if (optVhdl)
{
sl.append(theTranslator->trVhdlType(getMemberSpecifiers(),TRUE));
@@ -2756,7 +2756,8 @@ void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const
else if (isRelated()) sl.append("related");
else
{
- if (Config_getBool(INLINE_INFO) && isInline()) sl.append("inline");
+ if (isExternal()) sl.append("extern");
+ if (inlineInfo && isInline()) sl.append("inline");
if (isExplicit()) sl.append("explicit");
if (isMutable()) sl.append("mutable");
if (isStatic()) sl.append("static");
diff --git a/src/template.cpp b/src/template.cpp
index 1763eec..c836c6b 100644
--- a/src/template.cpp
+++ b/src/template.cpp
@@ -2843,7 +2843,11 @@ template<class T> class TemplateNodeCreator : public TemplateNode
if (d.exists())
{
bool ok = d.mkdir(fileName.mid(j,i-j));
- if (!ok) break;
+ if (!ok)
+ {
+ err("Failed to create directory '%s'\n",(fileName.mid(j,i-j)).data());
+ break;
+ }
QCString dirName = outputDir+'/'+fileName.left(i);
d = QDir(dirName);
j = i+1;
diff --git a/src/translator.h b/src/translator.h
index 188b775..991e637 100644
--- a/src/translator.h
+++ b/src/translator.h
@@ -50,6 +50,11 @@ class Translator
* can be returned.
*/
virtual QCString latexFontenc() { return "T1"; }
+ virtual QCString latexFont() {
+ return "\\usepackage[scaled=.90]{helvet}\n"
+ "\\usepackage{courier}\n"
+ "\\renewcommand{\\familydefault}{\\sfdefault}\n";
+ }
/*!
* Sets the commands to be inserted directly after the `\\begin{document}`
* in the LaTeX document.
diff --git a/src/translator_gr.h b/src/translator_gr.h
index 6ed43db..854a956 100644
--- a/src/translator_gr.h
+++ b/src/translator_gr.h
@@ -59,8 +59,18 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15
virtual QCString latexLanguageSupportCommand()
{
- return "\\usepackage[greek,english]{babel}\n"
- "\\usepackage{alphabeta}\n";
+ return "\\usepackage{fontspec}\n"
+ "\\usepackage[greek]{babel}\n";
+ }
+
+ virtual QCString latexFontenc()
+ {
+ return "";
+ }
+ virtual QCString latexFont()
+ {
+ return "\\setmainfont{Libertinus Sans}\n"
+ "\\setmonofont{Courier New}\n";
}
// --- Language translation methods -------------------
@@ -1159,6 +1169,16 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15
return "1253";
}
+ virtual QCString latexCommandName()
+ {
+ QCString latex_command = Config_getString(LATEX_CMD_NAME);
+ if (latex_command.isEmpty()) latex_command = "latex";
+ if (Config_getBool(USE_PDFLATEX))
+ {
+ if (latex_command == "latex") latex_command = "xelatex";
+ }
+ return latex_command;
+ }
/*! Used as ansicpg for RTF fcharset
*/
diff --git a/src/util.cpp b/src/util.cpp
index 7006f26..a298ace 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -5022,10 +5022,16 @@ void createSubDirs(QDir &d)
int l1,l2;
for (l1=0;l1<16;l1++)
{
- d.mkdir(QCString().sprintf("d%x",l1));
+ if (!d.mkdir(QCString().sprintf("d%x",l1)))
+ {
+ term("Failed to create output directory '%s'\n",(QCString().sprintf("d%x",l1)).data());
+ }
for (l2=0;l2<256;l2++)
{
- d.mkdir(QCString().sprintf("d%x/d%02x",l1,l2));
+ if (!d.mkdir(QCString().sprintf("d%x/d%02x",l1,l2)))
+ {
+ term("Failed to create output directory '%s'\n",(QCString().sprintf("d%x/d%02x",l1,l2)).data());
+ }
}
}
}
@@ -5272,6 +5278,16 @@ QCString convertToId(const char *s)
return growBuf.get();
}
+/*! Some strings have been corrected but the requirement regarding the fact
+ * that an id cannot have a digit at the first position. To overcome problems
+ * with double labels we always place an "a" in front
+ */
+QCString correctId(QCString s)
+{
+ if (s.isEmpty()) return s;
+ return "a" + s;
+}
+
/*! Converts a string to an XML-encoded string */
QCString convertToXML(const char *s, bool keepEntities)
{
diff --git a/src/util.h b/src/util.h
index a93220c..65d164a 100644
--- a/src/util.h
+++ b/src/util.h
@@ -278,6 +278,7 @@ QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &te
QCString stripScope(const char *name);
QCString convertToId(const char *s);
+QCString correctId(QCString s);
QCString convertToHtml(const char *s,bool keepEntities=TRUE);
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
index 3a649e9..593f69a 100644
--- a/src/xmlgen.cpp
+++ b/src/xmlgen.cpp
@@ -1150,7 +1150,8 @@ static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t)
if (!nd->isHidden() && !nd->isAnonymous())
{
t << " <innernamespace refid=\"" << nd->getOutputFileBase()
- << "\">" << convertToXML(nd->name()) << "</innernamespace>" << endl;
+ << "\"" << (nd->isInline() ? " inline=\"yes\"" : "")
+ << ">" << convertToXML(nd->name()) << "</innernamespace>" << endl;
}
}
}
@@ -1458,7 +1459,9 @@ static void generateXMLForNamespace(const NamespaceDef *nd,FTextStream &ti)
writeXMLHeader(t);
t << " <compounddef id=\"" << nd->getOutputFileBase()
- << "\" kind=\"namespace\" language=\""
+ << "\" kind=\"namespace\" "
+ << (nd->isInline()?"inline=\"yes\" ":"")
+ << "language=\""
<< langToString(nd->getLanguage()) << "\">" << endl;
t << " <compoundname>";
writeXMLString(t,nd->name());
diff --git a/templates/xml/compound.xsd b/templates/xml/compound.xsd
index e17d2fa..4df19ce 100644
--- a/templates/xml/compound.xsd
+++ b/templates/xml/compound.xsd
@@ -43,6 +43,7 @@
<xsd:attribute name="language" type="DoxLanguage" use="optional"/>
<xsd:attribute name="prot" type="DoxProtectionKind" />
<xsd:attribute name="final" type="DoxBool" use="optional"/>
+ <xsd:attribute name="inline" type="DoxBool" use="optional"/>
<xsd:attribute name="sealed" type="DoxBool" use="optional"/>
<xsd:attribute name="abstract" type="DoxBool" use="optional"/>
</xsd:complexType>
@@ -104,6 +105,7 @@
<xsd:extension base="xsd:string">
<xsd:attribute name="refid" type="xsd:string" />
<xsd:attribute name="prot" type="DoxProtectionKind" use="optional"/>
+ <xsd:attribute name="inline" type="DoxBool" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
diff --git a/testing/037/037__msc_8cpp.xml b/testing/037/037__msc_8cpp.xml
new file mode 100644
index 0000000..3de730d
--- /dev/null
+++ b/testing/037/037__msc_8cpp.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="">
+ <compounddef id="037__msc_8cpp" kind="file" language="C++">
+ <compoundname>037_msc.cpp</compoundname>
+ <innerclass refid="class_sender" prot="public">Sender</innerclass>
+ <innerclass refid="class_receiver" prot="public">Receiver</innerclass>
+ <briefdescription>
+ </briefdescription>
+ <detaileddescription>
+ <para>A bit more complex msc diagram, with also parallel events. <msc>
+Sender_1,Receiver_1,Sender1_1,
+Sender,Receiver,Sender1,
+Sender_2,Receiver_2,Sender1_2;
+
+Sender_1-&gt;Receiver_1 [label="Command()", URL="nref Receiver::Command()"],
+Sender1_1&lt;-Receiver_1 [label="Ack()", URL="nref Ack()", ID="1"];
+
+Sender-&gt;Receiver [label="Command()", URL="nref Receiver::Command()"];
+Sender1&lt;-Receiver [label="Ack()", URL="nref Ack()", ID="1"];
+Sender_2-&gt;Receiver_2 [label="Command()", URL="nref Receiver::Command()"],
+Sender1_2&lt;-Receiver_2 [label="Ack()", URL="nref Ack()", ID="1"];
+</msc>
+ </para>
+ </detaileddescription>
+ <location file="037_msc.cpp"/>
+ </compounddef>
+</doxygen>
diff --git a/testing/037/class_receiver.xml b/testing/037/class_receiver.xml
index 24e82fd..b3c9c5a 100644
--- a/testing/037/class_receiver.xml
+++ b/testing/037/class_receiver.xml
@@ -19,7 +19,7 @@
</detaileddescription>
<inbodydescription>
</inbodydescription>
- <location file="037_msc.cpp" line="32" column="10"/>
+ <location file="037_msc.cpp" line="50" column="10"/>
</memberdef>
</sectiondef>
<briefdescription>
@@ -32,7 +32,7 @@
</msc>
</para>
</detaileddescription>
- <location file="037_msc.cpp" line="28" column="1" bodyfile="037_msc.cpp" bodystart="29" bodyend="33"/>
+ <location file="037_msc.cpp" line="46" column="1" bodyfile="037_msc.cpp" bodystart="47" bodyend="51"/>
<listofallmembers>
<member refid="class_receiver_1a162099741e0324e6254c9bc570566e40" prot="public" virt="non-virtual">
<scope>Receiver</scope>
diff --git a/testing/037/class_sender.xml b/testing/037/class_sender.xml
index 525ab0a..14f29d1 100644
--- a/testing/037/class_sender.xml
+++ b/testing/037/class_sender.xml
@@ -19,7 +19,7 @@
</detaileddescription>
<inbodydescription>
</inbodydescription>
- <location file="037_msc.cpp" line="17" column="10"/>
+ <location file="037_msc.cpp" line="35" column="10"/>
</memberdef>
</sectiondef>
<briefdescription>
@@ -32,7 +32,7 @@
</msc>
</para>
</detaileddescription>
- <location file="037_msc.cpp" line="13" column="1" bodyfile="037_msc.cpp" bodystart="14" bodyend="18"/>
+ <location file="037_msc.cpp" line="31" column="1" bodyfile="037_msc.cpp" bodystart="32" bodyend="36"/>
<listofallmembers>
<member refid="class_sender_1a8ad2c6f9baa4e798868fe4a4d45f8fda" prot="public" virt="non-virtual">
<scope>Sender</scope>
diff --git a/testing/037_msc.cpp b/testing/037_msc.cpp
index 84ffc55..a3c0e4b 100644
--- a/testing/037_msc.cpp
+++ b/testing/037_msc.cpp
@@ -1,6 +1,24 @@
// objective: test the \msc and \endmsc commands
// check: class_sender.xml
// check: class_receiver.xml
+// check: 037__msc_8cpp.xml
+
+/** \file
+ * A bit more complex msc diagram, with also parallel events.
+ * \msc
+ * Sender_1,Receiver_1,Sender1_1,
+ * Sender,Receiver,Sender1,
+ * Sender_2,Receiver_2,Sender1_2;
+ *
+ * Sender_1->Receiver_1 [label="Command()", URL="nref Receiver::Command()"],
+ * Sender1_1<-Receiver_1 [label="Ack()", URL="nref Ack()", ID="1"];
+ *
+ * Sender->Receiver [label="Command()", URL="nref Receiver::Command()"];
+ * Sender1<-Receiver [label="Ack()", URL="nref Ack()", ID="1"];
+ * Sender_2->Receiver_2 [label="Command()", URL="nref Receiver::Command()"],
+ * Sender1_2<-Receiver_2 [label="Ack()", URL="nref Ack()", ID="1"];
+ * \endmsc
+ */
/** Sender class. Can be used to send a command to the server.
* The receiver will acknowledge the command by calling Ack().
diff --git a/testing/runtests.py b/testing/runtests.py
index 7896cdd..5d5cee1 100755
--- a/testing/runtests.py
+++ b/testing/runtests.py
@@ -150,11 +150,11 @@ class Tester:
if (self.args.clang):
print('CLANG_ASSISTED_PARSING=YES', file=f)
if (self.args.cfgs):
- for cfg in list(itertools.chain.from_iterable(self.args.cfgs)):
- if cfg.find('=') == -1:
+ for cfg in self.args.cfgs:
+ if cfg[0].find('=') == -1:
print("Not a doxygen configuration item, missing '=' sign: '%s'."%cfg)
sys.exit(1)
- print(cfg, file=f)
+ print(cfg[0], file=f)
if 'check' not in self.config or not self.config['check']:
print('Test doesn\'t specify any files to check')
@@ -183,7 +183,7 @@ class Tester:
# check if the file we need to check is actually generated
if not os.path.isfile(check_file):
print('Non-existing file %s after \'check:\' statement' % check_file)
- return
+ return False
# convert output to canonical form
data = xpopen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file))
if data:
@@ -191,12 +191,13 @@ class Tester:
data = re.sub(r'xsd" version="[0-9.-]+"','xsd" version=""',data).rstrip('\n')
else:
print('Failed to run %s on the doxygen output file %s' % (self.args.xmllint,self.test_out))
- return
+ return False
out_file='%s/%s' % (self.test_out,check)
with xopen(out_file,'w') as f:
print(data,file=f)
shutil.rmtree(self.test_out+'/out',ignore_errors=True)
os.remove(self.test_out+'/Doxyfile')
+ return True
# check the relevant files of a doxygen run with the reference material
def perform_test(self,testmgr):
@@ -401,17 +402,22 @@ class Tester:
if failed_xml or failed_html or failed_latex or failed_docbook or failed_rtf or failed_xmlxsd:
testmgr.ok(False,self.test_name,msg)
- return
+ return False
testmgr.ok(True,self.test_name)
if not self.args.keep:
shutil.rmtree(self.test_out,ignore_errors=True)
+ return True
def run(self,testmgr):
if self.update:
- self.update_test(testmgr)
+ return self.update_test(testmgr)
else:
- self.perform_test(testmgr)
+ return self.perform_test(testmgr)
+
+def do_generation_work(test):
+ tester = Tester(test[0].args,test[1])
+ return tester.run(test[0])
class TestManager:
def __init__(self,args,tests):
@@ -426,10 +432,10 @@ class TestManager:
def ok(self,result,test_name,msg='Ok'):
if result:
- print('ok %s - %s' % (self.count,test_name))
+ print('ok - %s' % (test_name))
self.passed = self.passed + 1
else:
- print('not ok %s - %s' % (self.count,test_name))
+ print('not ok - %s' % (test_name))
print('-------------------------------------')
for o in msg:
print(o)
@@ -444,9 +450,20 @@ class TestManager:
return 0 if self.passed==self.num_tests else 1
def perform_tests(self):
- for test in self.tests:
- tester = Tester(self.args,test)
- tester.run(self)
+ if (self.args.pool == 1):
+ passed = 0
+ for test in self.tests:
+ tester = Tester(self.args,test)
+ passed += tester.run(self)
+ self.passed = passed
+ else:
+ dl = []
+ for test in self.tests:
+ dl += [(self, test)]
+ import multiprocessing as mp
+ p = mp.Pool(processes=self.args.pool)
+ passed = p.map(do_generation_work, dl)
+ self.passed = sum(passed)
res=self.result()
if self.args.xhtml and self.args.inputdir!='.' and not res and not self.args.keep:
shutil.rmtree("dtd",ignore_errors=True)
@@ -457,6 +474,25 @@ class TestManager:
shutil.rmtree("dtd",ignore_errors=True)
shutil.copytree(self.args.inputdir+"/dtd", "dtd")
+def split_and_keep(s, sep):
+ if not s: return []
+
+ # Find replacement character that is not used in string
+ # i.e. just use the highest available character plus one
+ # Note: This fails if ord(max(s)) = 0x10FFFF (ValueError)
+ p=chr(ord(max(s))+1)
+
+ retVal = []
+ for val in s.replace(sep, p+sep).split(p):
+ vv = val.split(" ",1)
+ if ((len(vv) == 1) and not vv[0] == ''):
+ retVal += vv
+ if ((len(vv) == 2) and not vv[1] == ''):
+ retVal += vv
+ if ((len(vv) == 2) and vv[1] == ''):
+ retVal += [vv[0]]
+ return retVal
+
def main():
# argument handling
parser = argparse.ArgumentParser(description='run doxygen tests')
@@ -483,6 +519,8 @@ def main():
'output directory to write the doxygen output to')
parser.add_argument('--noredir',help=
'disable redirection of doxygen warnings',action="store_true")
+ parser.add_argument('--pool',nargs='?',default='1',type=int,help=
+ 'pool size of multiprocess tests')
parser.add_argument('--xml',help='create xml output and check',
action="store_true")
parser.add_argument('--rtf',help=
@@ -505,7 +543,9 @@ def main():
parser.add_argument('--cfg',nargs='+',dest='cfgs',action='append',help=
'run test with extra doxygen configuration settings '
'(the option may be specified multiple times')
- test_flags = os.getenv('TEST_FLAGS', default='').split()
+
+ test_flags = split_and_keep(os.getenv('TEST_FLAGS', default=''), '--')
+
args = parser.parse_args(test_flags + sys.argv[1:])
# sanity check