summaryrefslogtreecommitdiffstats
path: root/src/doxygen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/doxygen.cpp')
-rw-r--r--src/doxygen.cpp186
1 files changed, 132 insertions, 54 deletions
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index d551292..d442857 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -32,6 +32,7 @@
#include <algorithm>
#include <unordered_map>
#include <memory>
+#include <cinttypes>
#include "version.h"
#include "doxygen.h"
@@ -145,7 +146,7 @@ QDict<DefinitionIntf> *Doxygen::symbolMap = 0;
QDict<Definition> *Doxygen::clangUsrMap = 0;
bool Doxygen::outputToWizard=FALSE;
QDict<int> * Doxygen::htmlDirMap = 0;
-QCache<LookupInfo> *Doxygen::lookupCache;
+Cache<std::string,LookupInfo> *Doxygen::lookupCache;
DirSDict *Doxygen::directories;
SDict<DirRelation> Doxygen::dirRelations(257);
ParserManager *Doxygen::parserManager = 0;
@@ -164,7 +165,7 @@ DefinesPerFileList Doxygen::macroDefinitions;
bool Doxygen::clangAssistedParsing = FALSE;
// locally accessible globals
-static std::unordered_map< std::string, const Entry* > g_classEntries;
+static std::map< std::string, const Entry* > g_classEntries;
static StringVector g_inputFiles;
static QDict<void> g_compoundKeywordDict(7); // keywords recognised as compounds
static OutputList *g_outputList = 0; // list of output generating objects
@@ -7513,8 +7514,9 @@ static void generateFileSources()
{
msg("Generating code for file %s...\n",fd->docName().data());
clangParser->parse();
- fd->writeSource(*g_outputList,clangParser.get());
-
+ fd->writeSourceHeader(*g_outputList);
+ fd->writeSourceBody(*g_outputList,clangParser.get());
+ fd->writeSourceFooter(*g_outputList);
}
else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
// we needed to parse the sources even if we do not show them
@@ -7538,7 +7540,9 @@ static void generateFileSources()
if (ifd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output
{
msg(" Generating code for file %s...\n",ifd->docName().data());
- ifd->writeSource(*g_outputList,clangParser.get());
+ ifd->writeSourceHeader(*g_outputList);
+ ifd->writeSourceBody(*g_outputList,clangParser.get());
+ ifd->writeSourceFooter(*g_outputList);
}
else if (!ifd->isReference() && Doxygen::parseSourcesNeeded)
// we needed to parse the sources even if we do not show them
@@ -7566,15 +7570,18 @@ static void generateFileSources()
{
msg("Generating code for file %s...\n",fd->docName().data());
clangParser->parse();
- fd->writeSource(*g_outputList,clangParser.get());
-
+ fd->writeSourceHeader(*g_outputList);
+ fd->writeSourceBody(*g_outputList,clangParser.get());
+ fd->writeSourceFooter(*g_outputList);
}
else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
// we needed to parse the sources even if we do not show them
{
msg("Parsing code for file %s...\n",fd->docName().data());
clangParser->parse();
- fd->parseSource(clangParser.get());
+ fd->writeSourceHeader(*g_outputList);
+ fd->writeSourceBody(*g_outputList,clangParser.get());
+ fd->writeSourceFooter(*g_outputList);
}
}
}
@@ -7583,6 +7590,66 @@ static void generateFileSources()
else
#endif
{
+#define MULTITHREADED_SOURCE_GENERATOR 0 // not ready to be enabled yet
+#if MULTITHREADED_SOURCE_GENERATOR
+ std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
+ if (numThreads==0)
+ {
+ numThreads = std::thread::hardware_concurrency();
+ }
+ msg("Generating code files using %zu threads.\n",numThreads);
+ struct SourceContext
+ {
+ SourceContext(FileDef *fd_,bool gen_,OutputList ol_)
+ : fd(fd_), generateSourceFile(gen_), ol(ol_) {}
+ FileDef *fd;
+ bool generateSourceFile;
+ OutputList ol;
+ };
+ ThreadPool threadPool(numThreads);
+ std::vector< std::future< std::shared_ptr<SourceContext> > > results;
+ for (const auto &fn : *Doxygen::inputNameLinkedMap)
+ {
+ for (const auto &fd : *fn)
+ {
+ bool generateSourceFile = fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate;
+ auto ctx = std::make_shared<SourceContext>(fd.get(),generateSourceFile,*g_outputList);
+ if (generateSourceFile)
+ {
+ msg("Generating code for file %s...\n",fd->docName().data());
+ fd->writeSourceHeader(ctx->ol);
+ }
+ else
+ {
+ msg("Parsing code for file %s...\n",fd->docName().data());
+ }
+ auto processFile = [ctx]() {
+ StringVector filesInSameTu;
+ ctx->fd->getAllIncludeFilesRecursively(filesInSameTu);
+ if (ctx->generateSourceFile) // sources need to be shown in the output
+ {
+ ctx->fd->writeSourceBody(ctx->ol,nullptr);
+ }
+ else if (!ctx->fd->isReference() && Doxygen::parseSourcesNeeded)
+ // we needed to parse the sources even if we do not show them
+ {
+ ctx->fd->parseSource(nullptr);
+ }
+ return ctx;
+ };
+ results.emplace_back(threadPool.queue(processFile));
+ }
+ }
+ for (auto &f : results)
+ {
+ std::shared_ptr<SourceContext> ctx = f.get();
+ if (ctx->generateSourceFile)
+ {
+ ctx->fd->writeSourceFooter(ctx->ol);
+ }
+ }
+
+#else // single threaded version
for (const auto &fn : *Doxygen::inputNameLinkedMap)
{
for (const auto &fd : *fn)
@@ -7592,7 +7659,9 @@ static void generateFileSources()
if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output
{
msg("Generating code for file %s...\n",fd->docName().data());
- fd->writeSource(*g_outputList,nullptr);
+ fd->writeSourceHeader(*g_outputList);
+ fd->writeSourceBody(*g_outputList,nullptr);
+ fd->writeSourceFooter(*g_outputList);
}
else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
// we needed to parse the sources even if we do not show them
@@ -7602,6 +7671,7 @@ static void generateFileSources()
}
}
}
+#endif
}
}
}
@@ -8047,15 +8117,20 @@ static void flushCachedTemplateRelations()
// as there can be new template instances in the inheritance path
// to this class. Optimization: only remove those classes that
// have inheritance instances as direct or indirect sub classes.
- QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache);
- LookupInfo *li=0;
- for (ci.toFirst();(li=ci.current());++ci)
+ StringVector elementsToRemove;
+ for (const auto &ci : *Doxygen::lookupCache)
{
- if (li->classDef)
+ const LookupInfo &li = ci.second;
+ if (li.classDef)
{
- Doxygen::lookupCache->remove(ci.currentKey());
+ elementsToRemove.push_back(ci.first);
}
}
+ for (const auto &k : elementsToRemove)
+ {
+ Doxygen::lookupCache->remove(k);
+ }
+
// remove all cached typedef resolutions whose target is a
// template class as this may now be a template instance
// for each global function name
@@ -8099,16 +8174,20 @@ static void flushUnresolvedRelations()
// class A { class I {} };
// class B : public A {};
// class C : public B::I {};
- //
- QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache);
- LookupInfo *li=0;
- for (ci.toFirst();(li=ci.current());++ci)
+
+ StringVector elementsToRemove;
+ for (const auto &ci : *Doxygen::lookupCache)
{
- if (li->classDef==0 && li->typeDef==0)
+ const LookupInfo &li = ci.second;
+ if (li.classDef==0 && li.typeDef==0)
{
- Doxygen::lookupCache->remove(ci.currentKey());
+ elementsToRemove.push_back(ci.first);
}
}
+ for (const auto &k : elementsToRemove)
+ {
+ Doxygen::lookupCache->remove(k);
+ }
// for each global function name
for (const auto &fn : *Doxygen::functionNameLinkedMap)
@@ -8624,8 +8703,8 @@ static void generateExampleDocs()
for (pdi.toFirst();(pd=pdi.current());++pdi)
{
msg("Generating docs for example %s...\n",pd->name().data());
- CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type
- intf.resetCodeParserState();
+ auto intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type
+ intf->resetCodeParserState();
QCString n=pd->getOutputFileBase();
startFile(*g_outputList,n,n,pd->name());
startTitle(*g_outputList,n);
@@ -9473,7 +9552,7 @@ static int readDir(QFileInfo *fi,
{
if (errorIfNotExist)
{
- warn_uncond("source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data());
+ warn_uncond("source '%s' is not a readable file or directory... skipping.\n",cfi->absFilePath().data());
}
}
else if (cfi->isFile() &&
@@ -9553,7 +9632,7 @@ int readFileOrDirectory(const char *s,
{
if (errorIfNotExist)
{
- warn_uncond("source %s is not a readable file or directory... skipping.\n",s);
+ warn_uncond("source '%s' is not a readable file or directory... skipping.\n",s);
}
}
else if (!Config_getBool(EXCLUDE_SYMLINKS) || !fi.isSymLink())
@@ -9825,7 +9904,7 @@ class NullOutlineParser : public OutlineParserInterface
};
-template<class T> std::function< std::unique_ptr<T>() > make_output_parser_factory()
+template<class T> std::function< std::unique_ptr<T>() > make_parser_factory()
{
return []() { return std::make_unique<T>(); };
}
@@ -9842,26 +9921,26 @@ void initDoxygen()
Portable::correct_path();
Debug::startTimer();
- Doxygen::parserManager = new ParserManager( make_output_parser_factory<NullOutlineParser>(),
- std::make_unique<FileCodeParser>());
- Doxygen::parserManager->registerParser("c", make_output_parser_factory<COutlineParser>(),
- std::make_unique<CCodeParser>());
- Doxygen::parserManager->registerParser("python", make_output_parser_factory<PythonOutlineParser>(),
- std::make_unique<PythonCodeParser>());
- Doxygen::parserManager->registerParser("fortran", make_output_parser_factory<FortranOutlineParser>(),
- std::make_unique<FortranCodeParser>());
- Doxygen::parserManager->registerParser("fortranfree", make_output_parser_factory<FortranOutlineParserFree>(),
- std::make_unique<FortranCodeParserFree>());
- Doxygen::parserManager->registerParser("fortranfixed", make_output_parser_factory<FortranOutlineParserFixed>(),
- std::make_unique<FortranCodeParserFixed>());
- Doxygen::parserManager->registerParser("vhdl", make_output_parser_factory<VHDLOutlineParser>(),
- std::make_unique<VHDLCodeParser>());
- Doxygen::parserManager->registerParser("xml", make_output_parser_factory<NullOutlineParser>(),
- std::make_unique<XMLCodeParser>());
- Doxygen::parserManager->registerParser("sql", make_output_parser_factory<NullOutlineParser>(),
- std::make_unique<SQLCodeParser>());
- Doxygen::parserManager->registerParser("md", make_output_parser_factory<MarkdownOutlineParser>(),
- std::make_unique<FileCodeParser>());
+ Doxygen::parserManager = new ParserManager( make_parser_factory<NullOutlineParser>(),
+ make_parser_factory<FileCodeParser>());
+ Doxygen::parserManager->registerParser("c", make_parser_factory<COutlineParser>(),
+ make_parser_factory<CCodeParser>());
+ Doxygen::parserManager->registerParser("python", make_parser_factory<PythonOutlineParser>(),
+ make_parser_factory<PythonCodeParser>());
+ Doxygen::parserManager->registerParser("fortran", make_parser_factory<FortranOutlineParser>(),
+ make_parser_factory<FortranCodeParser>());
+ Doxygen::parserManager->registerParser("fortranfree", make_parser_factory<FortranOutlineParserFree>(),
+ make_parser_factory<FortranCodeParserFree>());
+ Doxygen::parserManager->registerParser("fortranfixed", make_parser_factory<FortranOutlineParserFixed>(),
+ make_parser_factory<FortranCodeParserFixed>());
+ Doxygen::parserManager->registerParser("vhdl", make_parser_factory<VHDLOutlineParser>(),
+ make_parser_factory<VHDLCodeParser>());
+ Doxygen::parserManager->registerParser("xml", make_parser_factory<NullOutlineParser>(),
+ make_parser_factory<XMLCodeParser>());
+ Doxygen::parserManager->registerParser("sql", make_parser_factory<NullOutlineParser>(),
+ make_parser_factory<SQLCodeParser>());
+ Doxygen::parserManager->registerParser("md", make_parser_factory<MarkdownOutlineParser>(),
+ make_parser_factory<FileCodeParser>());
// register any additional parsers here...
@@ -10037,15 +10116,15 @@ void readConfiguration(int argc, char **argv)
debugLabel=getArg(argc,argv,optind);
if (!debugLabel)
{
- err("option \"-d\" is missing debug specifier.\n");
devUsage();
cleanUpDoxygen();
- exit(1);
+ exit(0);
}
retVal = Debug::setFlag(debugLabel);
if (!retVal)
{
err("option \"-d\" has unknown debug specifier: \"%s\".\n",debugLabel);
+ devUsage();
cleanUpDoxygen();
exit(1);
}
@@ -10838,14 +10917,14 @@ void parseInput()
if (!dir.mkdir(outputDirectory))
{
err("tag OUTPUT_DIRECTORY: Output directory '%s' does not "
- "exist and cannot be created\n",outputDirectory.data());
+ "exist and cannot be created\n",outputDirectory.data());
cleanUpDoxygen();
exit(1);
}
else
{
- msg("Notice: Output directory '%s' does not exist. "
- "I have created it for you.\n", outputDirectory.data());
+ msg("Notice: Output directory '%s' does not exist. "
+ "I have created it for you.\n", outputDirectory.data());
}
dir.cd(outputDirectory);
}
@@ -10861,8 +10940,7 @@ void parseInput()
if (cacheSize<0) cacheSize=0;
if (cacheSize>9) cacheSize=9;
uint lookupSize = 65536 << cacheSize;
- Doxygen::lookupCache = new QCache<LookupInfo>(lookupSize,lookupSize);
- Doxygen::lookupCache->setAutoDelete(TRUE);
+ Doxygen::lookupCache = new Cache<std::string,LookupInfo>(lookupSize);
#ifdef HAS_SIGNALS
signal(SIGINT, stopDoxygen);
@@ -11691,9 +11769,9 @@ void generateOutput()
}
int cacheParam;
- msg("lookup cache used %d/%d hits=%d misses=%d\n",
- Doxygen::lookupCache->count(),
+ msg("lookup cache used %zu/%zu hits=%" PRIu64 " misses=%" PRIu64 "\n",
Doxygen::lookupCache->size(),
+ Doxygen::lookupCache->capacity(),
Doxygen::lookupCache->hits(),
Doxygen::lookupCache->misses());
cacheParam = computeIdealCacheParam(Doxygen::lookupCache->misses()*2/3); // part of the cache is flushed, hence the 2/3 correction factor