summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--addon/doxyparse/CMakeLists.txt11
-rw-r--r--addon/doxyparse/README5
-rw-r--r--addon/doxyparse/doxyparse.cpp59
-rw-r--r--cmake/FindLibClang.cmake55
-rw-r--r--cmake/lang_cfg.cmake10
-rw-r--r--doc/preprocessing.doc2
-rw-r--r--src/CMakeLists.txt22
-rw-r--r--src/clangparser.cpp35
-rw-r--r--src/code.l54
-rw-r--r--src/commentcnv.l70
-rw-r--r--src/config.xml14
-rw-r--r--src/index.cpp6
-rw-r--r--src/memberdef.cpp11
-rw-r--r--src/memberdef.h6
-rw-r--r--src/pagedef.cpp7
-rw-r--r--src/portable.cpp1
-rw-r--r--src/vhdldocgen.cpp4
18 files changed, 269 insertions, 115 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4d75659..ed63320 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,14 +35,20 @@ set(clang "0" CACHE INTERNAL "used in settings.h")
if (use_sqlite3)
set(sqlite3 "1" CACHE INTERNAL "used in settings.h")
endif()
+
+set(MACOS_VERSION_MIN 10.5)
if (use_libclang)
set(clang "1" CACHE INTERNAL "used in settings.h")
- find_package(LibClang REQUIRED)
+ find_package(LLVM CONFIG REQUIRED)
+ find_package(Clang CONFIG REQUIRED)
+ if (${CMAKE_SYSTEM} MATCHES "Darwin")
+ set(MACOS_VERSION_MIN 10.11)
+ endif()
endif()
if (${CMAKE_SYSTEM} MATCHES "Darwin")
- set(CMAKE_CXX_FLAGS "-Wno-deprecated-register -mmacosx-version-min=10.5 ${CMAKE_CXX_FLAGS}")
- set(CMAKE_C_FLAGS "-Wno-deprecated-register -mmacosx-version-min=10.5 ${CMAKE_C_FLAGS}")
+ set(CMAKE_CXX_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_CXX_FLAGS}")
+ set(CMAKE_C_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_C_FLAGS}")
find_library(CORESERVICES_LIB CoreServices)
set(EXTRA_LIBS ${CORESERVICES_LIB})
endif()
diff --git a/addon/doxyparse/CMakeLists.txt b/addon/doxyparse/CMakeLists.txt
index 24f98cb..e4f9021 100644
--- a/addon/doxyparse/CMakeLists.txt
+++ b/addon/doxyparse/CMakeLists.txt
@@ -1,11 +1,21 @@
if (build_parse)
+# configvalues.h
+add_custom_command(
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -maph ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC}/configvalues.h
+ DEPENDS ${CMAKE_SOURCE_DIR}/src/config.xml ${CMAKE_SOURCE_DIR}/src/configgen.py
+ OUTPUT ${GENERATED_SRC}/configvalues.h
+)
+set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1)
+
find_package(Iconv)
include_directories(
${CMAKE_SOURCE_DIR}/src
+ ${GENERATED_SRC}
${CMAKE_SOURCE_DIR}/qtools
${ICONV_INCLUDE_DIR}
+ ${CLANG_INCLUDEDIR}
)
add_executable(doxyparse
@@ -21,6 +31,7 @@ ${ICONV_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${SQLITE3_LIBRARIES}
${EXTRA_LIBS}
+${CLANG_LIBS}
)
install(TARGETS doxyparse DESTINATION bin)
diff --git a/addon/doxyparse/README b/addon/doxyparse/README
index 7cbc8ff..9f7429c 100644
--- a/addon/doxyparse/README
+++ b/addon/doxyparse/README
@@ -5,6 +5,11 @@ This directory contains an "source parsing engine" based on doxyapp code.
More info and source code repository: https://github.com/analizo/doxygen
+## build
+
+ cmake -G "Unix Makefiles" -Dbuild_parse=ON
+ make
+
AUTHORS
=======
diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp
index ec1bdae..ee34e3b 100644
--- a/addon/doxyparse/doxyparse.cpp
+++ b/addon/doxyparse/doxyparse.cpp
@@ -103,7 +103,7 @@ static void findXRefSymbols(FileDef *fd)
static bool ignoreStaticExternalCall(MemberDef *context, MemberDef *md) {
if (md->isStatic()) {
if(md->getFileDef()) {
- if(md->getFileDef()->getFileBase() == context->getFileDef()->getFileBase())
+ if(md->getFileDef()->getOutputFileBase() == context->getFileDef()->getOutputFileBase())
// TODO ignore prefix of file
return false;
else
@@ -159,6 +159,9 @@ static void printReferenceTo(std::string type, std::string signature, std::strin
printf(" type: %s\n", type.c_str());
printf(" defined_in: %s\n", defined_in.c_str());
}
+static void printNumberOfConditionalPaths(MemberDef* md) {
+ printf(" conditional_paths: %d\n", md->numberOfFlowKeyWords());
+}
static int isPartOfCStruct(MemberDef * md) {
return is_c_code && md->getClassDef() != NULL;
@@ -188,7 +191,7 @@ static void referenceTo(MemberDef* md) {
std::string signature = "";
if (isPartOfCStruct(md)) {
signature = md->getClassDef()->name().data() + std::string("::") + functionSignature(md);
- defined_in = md->getClassDef()->getFileDef()->getFileBase().data();
+ defined_in = md->getClassDef()->getFileDef()->getOutputFileBase().data();
}
else {
signature = functionSignature(md);
@@ -196,7 +199,7 @@ static void referenceTo(MemberDef* md) {
defined_in = md->getClassDef()->name().data();
}
else if (md->getFileDef()) {
- defined_in = md->getFileDef()->getFileBase().data();
+ defined_in = md->getFileDef()->getOutputFileBase().data();
}
}
printReferenceTo(type, signature, defined_in);
@@ -221,6 +224,7 @@ void functionInformation(MemberDef* md) {
printNumberOfLines(size);
ArgumentList *argList = md->argumentList();
printNumberOfArguments(argList->count());
+ printNumberOfConditionalPaths(md);
MemberSDict *defDict = md->getReferencesMembers();
if (defDict) {
MemberSDict::Iterator msdi(*defDict);
@@ -329,7 +333,7 @@ static void listSymbols() {
printFile(fd->absFilePath().data());
MemberList *ml = fd->getMemberList(MemberListType_allMembersList);
if (ml && ml->count() > 0) {
- printModule(fd->getFileBase().data());
+ printModule(fd->getOutputFileBase().data());
listMembers(ml);
}
@@ -355,37 +359,40 @@ int main(int argc,char **argv) {
// initialize data structures
initDoxygen();
+ // check and finalize the configuration
+ checkConfiguration();
+ adjustConfiguration();
+
// setup the non-default configuration options
// we need a place to put intermediate files
std::ostringstream tmpdir;
tmpdir << "/tmp/doxyparse-" << getpid();
- Config_getString("OUTPUT_DIRECTORY")= tmpdir.str().c_str();
-
+ Config_getString(OUTPUT_DIRECTORY)= tmpdir.str().c_str();
// enable HTML (fake) output to omit warning about missing output format
- Config_getBool("GENERATE_HTML")=TRUE;
+ Config_getBool(GENERATE_HTML)=TRUE;
// disable latex output
- Config_getBool("GENERATE_LATEX")=FALSE;
+ Config_getBool(GENERATE_LATEX)=FALSE;
// be quiet
- Config_getBool("QUIET")=TRUE;
+ Config_getBool(QUIET)=TRUE;
// turn off warnings
- Config_getBool("WARNINGS")=FALSE;
- Config_getBool("WARN_IF_UNDOCUMENTED")=FALSE;
- Config_getBool("WARN_IF_DOC_ERROR")=FALSE;
+ Config_getBool(WARNINGS)=FALSE;
+ Config_getBool(WARN_IF_UNDOCUMENTED)=FALSE;
+ Config_getBool(WARN_IF_DOC_ERROR)=FALSE;
// Extract as much as possible
- Config_getBool("EXTRACT_ALL")=TRUE;
- Config_getBool("EXTRACT_STATIC")=TRUE;
- Config_getBool("EXTRACT_PRIVATE")=TRUE;
- Config_getBool("EXTRACT_LOCAL_METHODS")=TRUE;
+ Config_getBool(EXTRACT_ALL)=TRUE;
+ Config_getBool(EXTRACT_STATIC)=TRUE;
+ Config_getBool(EXTRACT_PRIVATE)=TRUE;
+ Config_getBool(EXTRACT_LOCAL_METHODS)=TRUE;
// Extract source browse information, needed
// to make doxygen gather the cross reference info
- Config_getBool("SOURCE_BROWSER")=TRUE;
+ Config_getBool(SOURCE_BROWSER)=TRUE;
// find functions call between modules
- Config_getBool("CALL_GRAPH")=TRUE;
+ Config_getBool(CALL_GRAPH)=TRUE;
// loop recursive over input files
- Config_getBool("RECURSIVE")=TRUE;
+ Config_getBool(RECURSIVE)=TRUE;
// set the input
- Config_getList("INPUT").clear();
+ Config_getList(INPUT).clear();
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-") == 0) {
char filename[1024];
@@ -394,20 +401,16 @@ int main(int argc,char **argv) {
if (feof(stdin)) {
break;
}
- Config_getList("INPUT").append(filename);
+ Config_getList(INPUT).append(filename);
}
} else {
- Config_getList("INPUT").append(argv[i]);
+ Config_getList(INPUT).append(argv[i]);
}
}
- if (Config_getList("INPUT").isEmpty()) {
+ if (Config_getList(INPUT).isEmpty()) {
exit(0);
}
- // check and finalize the configuration
- checkConfiguration();
- adjustConfiguration();
-
// parse the files
parseInput();
@@ -429,7 +432,7 @@ int main(int argc,char **argv) {
if (!Doxygen::objDBFileName.isEmpty()) unlink(Doxygen::objDBFileName);
if (!Doxygen::entryDBFileName.isEmpty()) unlink(Doxygen::entryDBFileName);
// clean up after us
- rmdir(Config_getString("OUTPUT_DIRECTORY"));
+ rmdir(Config_getString(OUTPUT_DIRECTORY));
listSymbols();
diff --git a/cmake/FindLibClang.cmake b/cmake/FindLibClang.cmake
deleted file mode 100644
index e7462d4..0000000
--- a/cmake/FindLibClang.cmake
+++ /dev/null
@@ -1,55 +0,0 @@
-if (NOT CLANG_ROOT)
- set(CLANG_ROOT $ENV{CLANG_ROOT})
-endif ()
-
-if (NOT LLVM_CONFIG)
- set(LLVM_CONFIG $ENV{LLVM_CONFIG})
- if (NOT LLVM_CONFIG)
- set(llvm_config_names llvm-config)
- foreach(minor RANGE 9 1)
- list(APPEND llvm_config_names "llvm-config3${minor}" "llvm-config-3.${minor}" "llvm-config-mp-3.${minor}")
- endforeach ()
- find_program(LLVM_CONFIG NAMES ${llvm_config_names})
- endif ()
-endif ()
-
-if (LLVM_CONFIG)
- message(STATUS "llvm-config found at: ${LLVM_CONFIG}")
-else ()
- message(FATAL_ERROR "Could NOT find llvm-config executable.")
-endif ()
-
-if (NOT EXISTS ${CLANG_INCLUDEDIR})
- execute_process(COMMAND ${LLVM_CONFIG} --includedir OUTPUT_VARIABLE CLANG_INCLUDEDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (NOT EXISTS ${CLANG_INCLUDEDIR})
- message(FATAL_ERROR "Could NOT find clang includedir. You can fix this by setting CLANG_INCLUDEDIR in your shell or as a cmake variable.")
- endif ()
-endif ()
-
-if (NOT EXISTS ${CLANG_LIBDIR})
- execute_process(COMMAND ${LLVM_CONFIG} --libdir OUTPUT_VARIABLE CLANG_LIBDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (NOT EXISTS ${CLANG_LIBDIR})
- message(FATAL_ERROR "Could NOT find clang libdir. You can fix this by setting CLANG_LIBDIR in your shell or as a cmake variable.")
- endif ()
-endif ()
-
-if (NOT CLANG_LIBS)
- find_library(CLANG_LIB_HACK_CMAKECACHE_DOT_TEXT_BULLSHIT NAMES clang libclang ${CLANG_ROOT}/lib ${CLANG_LIBDIR} NO_DEFAULT_PATH)
- if (NOT EXISTS ${CLANG_CLANG_LIB_HACK_CMAKECACHE_DOT_TEXT_BULLSHIT})
- find_library(CLANG_LIBS NAMES clang libclang)
- if (NOT EXISTS ${CLANG_LIBS})
- if (MSVC)
- set (CLANG_LIBS "${CLANG_LIBDIR}/libclang.lib")
- else()
- set (CLANG_LIBS "-L${CLANG_LIBDIR}" "-lclang" "-Wl,-rpath,${CLANG_LIBDIR}")
- endif()
- endif ()
- else ()
- set(CLANG_LIBS "${CLANG_LIB_HACK_CMAKECACHE_DOT_TEXT_BULLSHIT}")
- endif ()
-endif ()
-
-execute_process(COMMAND ${LLVM_CONFIG} --version OUTPUT_VARIABLE CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
-message("-- Using Clang ${CLANG_VERSION} from ${CLANG_LIBDIR} with LIBS ${CLANG_LIBS} and CXXFLAGS ${CLANG_CXXFLAGS}")
-
-
diff --git a/cmake/lang_cfg.cmake b/cmake/lang_cfg.cmake
index c57d3ed..86c2d9a 100644
--- a/cmake/lang_cfg.cmake
+++ b/cmake/lang_cfg.cmake
@@ -1,10 +1,10 @@
-if(${CMAKE_ARGC} GREATER 1)
- if ("${CMAKE_ARGV3}" STREQUAL "ENONLY")
- message("#define ENGLISH_ONLY")
+if(${CMAKE_ARGC} GREATER 2)
+ if ("${CMAKE_ARGV4}" STREQUAL "ENONLY")
+ file(APPEND ${CMAKE_ARGV3} " #define ENGLISH_ONLY")
else()
math(EXPR UPTO ${CMAKE_ARGC}-1)
- foreach(i RANGE 3 ${UPTO})
- message("#define LANG_${CMAKE_ARGV${i}}")
+ foreach(i RANGE 4 ${UPTO})
+ file(APPEND ${CMAKE_ARGV3} " #define LANG_${CMAKE_ARGV${i}}")
endforeach()
endif()
endif()
diff --git a/doc/preprocessing.doc b/doc/preprocessing.doc
index d62bbb3..30d4cf3 100644
--- a/doc/preprocessing.doc
+++ b/doc/preprocessing.doc
@@ -62,7 +62,7 @@ to \c YES. Then the result after preprocessing becomes:
#define VERSION
#define CONST_STRING
- static const char * version = "1.xx";
+ static const char * version = "2.xx";
\endverbatim
Note that doxygen will now expand \e all macro definitions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 08c8439..2218e82 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -73,7 +73,7 @@ set_source_files_properties(${GENERATED_SRC}/ce_parse.h PROPERTIES GENERATED 1)
# lang_cfg.h
add_custom_command(
COMMENT "Generating ${GENERATED_SRC}/lang_cfg.h"
- COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/lang_cfg.cmake ${LANG_CODES} 2> ${GENERATED_SRC}/lang_cfg.h
+ COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/lang_cfg.cmake ${GENERATED_SRC}/lang_cfg.h ${LANG_CODES}
DEPENDS ${LANGUAGE_FILES}
OUTPUT ${GENERATED_SRC}/lang_cfg.h
)
@@ -244,6 +244,26 @@ add_library(_doxygen STATIC
)
add_executable(doxygen main.cpp)
+
+if (use_libclang)
+ find_package(LLVM REQUIRED CONFIG)
+ find_package(Clang REQUIRED CONFIG)
+ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
+ target_compile_features(_doxygen PRIVATE cxx_alignof)
+ target_compile_features(doxygen PRIVATE cxx_alignof)
+ target_compile_options(_doxygen PRIVATE -stdlib=libc++ -std=c++11)
+ target_compile_options(doxygen PRIVATE -stdlib=libc++ -std=c++11)
+ elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
+ target_compile_options(_doxygen PRIVATE -std=c++11)
+ target_compile_options(doxygen PRIVATE -std=c++11)
+ endif()
+ include_directories(${LLVM_INCLUDE_DIRS})
+ add_definitions(${LLVM_DEFINITIONS})
+ llvm_map_components_to_libnames(llvm_libs support core option)
+ target_compile_definitions(doxygen PRIVATE ${LLVM_DEFINITIONS})
+ set(CLANG_LIBS libclang clangTooling ${llvm_libs})
+endif()
+
target_link_libraries(doxygen
_doxygen
doxycfg
diff --git a/src/clangparser.cpp b/src/clangparser.cpp
index 67e754b..77151d6 100644
--- a/src/clangparser.cpp
+++ b/src/clangparser.cpp
@@ -4,6 +4,7 @@
#if USE_LIBCLANG
#include <clang-c/Index.h>
+#include "clang/Tooling/Tooling.h"
#include <qfileinfo.h>
#include <stdlib.h>
#include "message.h"
@@ -160,15 +161,46 @@ void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit)
static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
static QStrList &includePath = Config_getList(INCLUDE_PATH);
static QStrList clangOptions = Config_getList(CLANG_OPTIONS);
+ static QCString clangCompileDatabase = Config_getList(CLANG_COMPILATION_DATABASE_PATH);
if (!clangAssistedParsing) return;
//printf("ClangParser::start(%s)\n",fileName);
p->fileName = fileName;
p->index = clang_createIndex(0, 0);
p->curLine = 1;
p->curToken = 0;
- char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()));
QDictIterator<void> di(Doxygen::inputPaths);
int argc=0;
+ std::string error;
+ // load a clang compilation database (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
+ // this only needs to be loaded once, and could be refactored to a higher level function
+ static std::unique_ptr<clang::tooling::CompilationDatabase> db =
+ clang::tooling::CompilationDatabase::loadFromDirectory(clangCompileDatabase.data(), error);
+ int clang_option_len = 0;
+ std::vector<clang::tooling::CompileCommand> command;
+ if (strcmp(clangCompileDatabase, "0") != 0) {
+ if (db == nullptr) {
+ // user specified a path, but DB file was not found
+ err("%s using clang compilation database path of: \"%s\"\n", error.c_str(),
+ clangCompileDatabase.data());
+ } else {
+ // check if the file we are parsing is in the DB
+ command = db->getCompileCommands(fileName);
+ if (!command.empty() ) {
+ // it's possible to have multiple entries for the same file, so use the last entry
+ clang_option_len = command[command.size()-1].CommandLine.size();
+ }
+ }
+ }
+ char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()+clang_option_len));
+ if (!command.empty() ) {
+ std::vector<std::string> options = command[command.size()-1].CommandLine;
+ // copy each compiler option used from the database. Skip the first which is compiler exe.
+ for (auto option = options.begin()+1; option != options.end(); option++) {
+ argv[argc++] = strdup(option->c_str());
+ }
+ // this extra addition to argv is accounted for as we are skipping the first entry in
+ argv[argc++]=strdup("-w"); // finally, turn off warnings.
+ } else {
// add include paths for input files
for (di.toFirst();di.current();++di,++argc)
{
@@ -230,6 +262,7 @@ void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit)
// provide the input and and its dependencies as unsaved files so we can
// pass the filtered versions
argv[argc++]=strdup(fileName);
+ }
static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
//printf("source %s ----------\n%s\n-------------\n\n",
// fileName,p->source.data());
diff --git a/src/code.l b/src/code.l
index b2564e9..fc511a0 100644
--- a/src/code.l
+++ b/src/code.l
@@ -126,6 +126,7 @@ static bool g_lexInit = FALSE;
static QStack<int> g_classScopeLengthStack;
+static int g_prefixed_with_this_keyword = FALSE;
static Definition *g_searchCtx;
static bool g_collectXRefs;
@@ -963,7 +964,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
bool isLocal=FALSE;
//printf("generateClassOrGlobalLink(className=%s)\n",className.data());
- if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable
+ if (!g_prefixed_with_this_keyword || (lcd=g_theVarContext.findVariable(className))==0) // not a local variable
{
Definition *d = g_currentDefinition;
//printf("d=%s g_sourceFileDef=%s\n",d?d->name().data():"<none>",g_sourceFileDef?g_sourceFileDef->name().data():"<none>");
@@ -1019,6 +1020,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
isLocal=TRUE;
DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
}
+ g_prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls
+
if (cd && cd->isLinkable()) // is it a linkable class
{
DBG_CTX((stderr,"is linkable class %s\n",clName));
@@ -1821,7 +1824,8 @@ SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|{KEYWORD_OBJC})
-FLOWKW ("break"|"case"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"for"|"foreach"|"for each"|"goto"|"if"|"return"|"switch"|"throw"|"throws"|"try"|"while"|"@try"|"@catch"|"@finally")
+FLOWKW ("break"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"return"|"switch"|"throw"|"throws"|"@catch"|"@finally")
+FLOWCONDITION ("case"|"for"|"foreach"|"for each"|"goto"|"if"|"try"|"while"|"@try")
TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
@@ -2408,6 +2412,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
<UsingName>\n { codifyLines(yytext); BEGIN(Body); }
<UsingName>. { codifyLines(yytext); BEGIN(Body); }
<Body,FuncCall>"$"?"this"("->"|".") { g_code->codify(yytext); // this-> for C++, this. for C#
+ g_prefixed_with_this_keyword = TRUE;
}
<Body>{KEYWORD}/([^a-z_A-Z0-9]) {
startFontClass("keyword");
@@ -2449,6 +2454,18 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0);
BEGIN(FuncCall);
}
+<Body>{FLOWCONDITION}/{BN}*"(" {
+ if (g_currentMemberDef && g_currentMemberDef->isFunction())
+ {
+ g_currentMemberDef->addFlowKeyWord();
+ }
+ startFontClass("keywordflow");
+ codifyLines(yytext);
+ endFontClass();
+ g_name.resize(0);g_type.resize(0);
+ g_inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0);
+ BEGIN(FuncCall);
+ }
<Body>{FLOWKW}/([^a-z_A-Z0-9]) {
startFontClass("keywordflow");
codifyLines(yytext);
@@ -2458,11 +2475,33 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_inFunctionTryBlock=FALSE;
}
}
+<Body>{FLOWCONDITION}/([^a-z_A-Z0-9]) {
+ if (g_currentMemberDef && g_currentMemberDef->isFunction())
+ {
+ g_currentMemberDef->addFlowKeyWord();
+ }
+ startFontClass("keywordflow");
+ codifyLines(yytext);
+ endFontClass();
+ if (g_inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0))
+ {
+ g_inFunctionTryBlock=FALSE;
+ }
+ }
<Body>{FLOWKW}/{B}* {
startFontClass("keywordflow");
codifyLines(yytext);
endFontClass();
}
+<Body>{FLOWCONDITION}/{B}* {
+ if (g_currentMemberDef && g_currentMemberDef->isFunction())
+ {
+ g_currentMemberDef->addFlowKeyWord();
+ }
+ startFontClass("keywordflow");
+ codifyLines(yytext);
+ endFontClass();
+ }
<Body>"*"{B}*")" { // end of cast?
g_code->codify(yytext);
g_theCallContext.popScope();
@@ -2963,6 +3002,17 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_code->codify(yytext);
endFontClass();
}
+<MemberCall2,FuncCall>{FLOWCONDITION}/([^a-z_A-Z0-9]) {
+ if (g_currentMemberDef && g_currentMemberDef->isFunction())
+ {
+ g_currentMemberDef->addFlowKeyWord();
+ }
+ addParmType();
+ g_parmName=yytext;
+ startFontClass("keywordflow");
+ g_code->codify(yytext);
+ endFontClass();
+ }
<MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
addParmType();
g_parmName=yytext;
diff --git a/src/commentcnv.l b/src/commentcnv.l
index 6fea6c9..ebee914 100644
--- a/src/commentcnv.l
+++ b/src/commentcnv.l
@@ -89,6 +89,8 @@ static int g_lastBlockContext;
static bool g_pythonDocString;
static int g_nestingCount;
+static bool g_vhdl; // for VHDL old style --! comment
+
static SrcLangExt g_lang;
static bool isFixedForm; // For Fortran
@@ -250,7 +252,7 @@ void replaceComment(int offset);
%%
-<Scan>[^"'!\/\n\\#-,]* { /* eat anything that is not " / , or \n */
+<Scan>[^"'!\/\n\\#,\-]* { /* eat anything that is not " / , or \n */
copyToOutput(yytext,(int)yyleng);
}
<Scan>[,] { /* eat , so we have a nice separator in long initialization lines */
@@ -425,6 +427,7 @@ void replaceComment(int offset);
}
else
{
+ g_vhdl = TRUE;
copyToOutput(yytext,(int)yyleng);
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
@@ -664,7 +667,27 @@ void replaceComment(int offset);
}
}
}
-<CComment>"\n"/[ \t]*[^#] { /* end of Python comment */
+ /* Python an VHDL share CComment, so special attention for ending commments is required */
+<CComment>"\n"/[ \t]*"#" {
+ if (g_lang!=SrcLangExt_VHDL)
+ {
+ REJECT;
+ }
+ else
+ {
+ if (g_vhdl) // inside --! comment
+ {
+ g_vhdl = FALSE;
+ copyToOutput(yytext,(int)yyleng);
+ BEGIN(Scan);
+ }
+ else // C-type comment
+ {
+ REJECT;
+ }
+ }
+ }
+<CComment>"\n"/[ \t]*"-" {
if (g_lang!=SrcLangExt_Python || g_pythonDocString)
{
REJECT;
@@ -674,18 +697,38 @@ void replaceComment(int offset);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
- }
-<CComment>"\n"/[ \t]*[^\-] { /* end of VHDL comment */
- if (g_lang!=SrcLangExt_VHDL)
- {
+ }
+<CComment>"\n"/[ \t]*[^ \t#\-] {
+ if (g_lang==SrcLangExt_Python)
+ {
+ if (g_pythonDocString)
+ {
+ REJECT;
+ }
+ else
+ {
+ copyToOutput(yytext,(int)yyleng);
+ BEGIN(Scan);
+ }
+ }
+ else if (g_lang==SrcLangExt_VHDL)
+ {
+ if (g_vhdl) // inside --! comment
+ {
+ g_vhdl = FALSE;
+ copyToOutput(yytext,(int)yyleng);
+ BEGIN(Scan);
+ }
+ else // C-type comment
+ {
+ REJECT;
+ }
+ }
+ else
+ {
REJECT;
- }
- else
- {
- copyToOutput(yytext,(int)yyleng);
- BEGIN(Scan);
- }
- }
+ }
+ }
/* removed for bug 674842 (bug was introduced in rev 768)
<CComment>"'" {
g_charContext = YY_START;
@@ -1001,6 +1044,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
g_condStack.setAutoDelete(TRUE);
g_commentStack.clear();
g_commentStack.setAutoDelete(TRUE);
+ g_vhdl = FALSE;
printlex(yy_flex_debug, TRUE, __FILE__, fileName);
isFixedForm = FALSE;
diff --git a/src/config.xml b/src/config.xml
index 8bb6add..6cd7997 100644
--- a/src/config.xml
+++ b/src/config.xml
@@ -1637,6 +1637,20 @@ to disable this feature.
]]>
</docs>
</option>
+ <option type='string' id='CLANG_COMPILATION_DATABASE_PATH' setting='USE_LIBCLANG' defval='0'>
+ <docs>
+<![CDATA[
+ If clang assisted parsing is enabled you can provide the clang parser with the
+ path to the <a href="http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html">
+ compilation database</a> used when the files were built. This is equivalent to
+ specifying the "-p" option to a clang tool, such as clang-check. These options
+ will then be pased to the parser.
+
+ @note The availability of this option depends on whether or not doxygen
+ was generated with the `-Duse-libclang=ON` option for CMake.
+ ]]>
+ </docs>
+ </option>
</group>
<group name='Index' docs='Configuration options related to the alphabetical class index'>
<option type='bool' id='ALPHABETICAL_INDEX' defval='1'>
diff --git a/src/index.cpp b/src/index.cpp
index 921ab51..3a17c29 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -4122,7 +4122,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
{
if (documentedNamespaces>0 && addToIndex)
{
- Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0);
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
Doxygen::indexList->incContentsDepth();
needsClosing=TRUE;
}
@@ -4151,7 +4151,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
case LayoutNavEntry::Classes:
if (annotatedClasses>0 && addToIndex)
{
- Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,"annotated",0);
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
Doxygen::indexList->incContentsDepth();
needsClosing=TRUE;
}
@@ -4189,7 +4189,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
{
if (documentedHtmlFiles>0 && addToIndex)
{
- Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0);
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
Doxygen::indexList->incContentsDepth();
needsClosing=TRUE;
}
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 26001a1..8403374 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -750,6 +750,7 @@ MemberDef::MemberDef(const char *df,int dl,int dc,
//printf("MemberDef::MemberDef(%s)\n",na);
m_impl = new MemberDefImpl;
m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al);
+ number_of_flowkw = 1;
m_isLinkableCached = 0;
m_isConstructorCached = 0;
m_isDestructorCached = 0;
@@ -4910,6 +4911,16 @@ void MemberDef::invalidateCachedArgumentTypes()
invalidateCachedTypesInArgumentList(m_impl->declArgList);
}
+void MemberDef::addFlowKeyWord()
+{
+ number_of_flowkw++;
+}
+
+int MemberDef::numberOfFlowKeyWords()
+{
+ return number_of_flowkw;
+}
+
//----------------
QCString MemberDef::displayName(bool) const
diff --git a/src/memberdef.h b/src/memberdef.h
index c0825b2..bf7ea9a 100644
--- a/src/memberdef.h
+++ b/src/memberdef.h
@@ -178,6 +178,7 @@ class MemberDef : public Definition
bool isStrongEnumValue() const;
bool livesInsideEnum() const;
+ int numberOfFlowKeyWords();
// derived getters
bool isFriendToHide() const;
bool isNotFriend() const;
@@ -272,6 +273,8 @@ class MemberDef : public Definition
// ---- setters -----
//-----------------------------------------------------------------------------------
+ void addFlowKeyWord();
+
// set functions
void setMemberType(MemberType t);
void setDefinition(const char *d);
@@ -424,6 +427,9 @@ class MemberDef : public Definition
void _addToSearchIndex();
static int s_indentLevel;
+
+ int number_of_flowkw;
+
// disable copying of member defs
MemberDef(const MemberDef &);
MemberDef &operator=(const MemberDef &);
diff --git a/src/pagedef.cpp b/src/pagedef.cpp
index 1210305..e797b050 100644
--- a/src/pagedef.cpp
+++ b/src/pagedef.cpp
@@ -169,6 +169,11 @@ void PageDef::writeDocumentation(OutputList &ol)
ol.endTitleHead(manPageName, manPageName);
if (si)
{
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.writeString(" - ");
+ ol.popGeneratorState();
+
ol.generateDoc(docFile(),docLine(),this,0,si->title,TRUE,FALSE,0,TRUE,FALSE);
ol.endSection(si->label,si->type);
}
@@ -230,7 +235,7 @@ void PageDef::writePageDocumentation(OutputList &ol)
ol.startTextBlock();
QCString docStr = documentation()+inbodyDocumentation();
- if (!docStr.isEmpty())
+ if (hasBriefDescription() && !Doxygen::sectionDict->find(name()))
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Man);
diff --git a/src/portable.cpp b/src/portable.cpp
index 1983fe7..4ad88a4 100644
--- a/src/portable.cpp
+++ b/src/portable.cpp
@@ -180,6 +180,7 @@ int portable_system(const char *command,const char *args,bool commandHasConsole)
}
}
#endif
+ return 1; // we should never get here
}
diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp
index d09de09..7883327 100644
--- a/src/vhdldocgen.cpp
+++ b/src/vhdldocgen.cpp
@@ -3995,10 +3995,10 @@ void FlowChart::createSVG()
//if (m)
// fprintf(stderr,"\n creating flowchart : %s %s in file %s \n",VhdlDocGen::trTypeString(m->getMemberSpecifiers()),m->name().data(),m->getFileDef()->name().data());
- QCString dir=" -o "+ov+qcs;
+ QCString dir=" -o \""+ov+qcs+"\"";
ov+="/flow_design.dot";
- QCString vlargs="-Tsvg "+ov+dir ;
+ QCString vlargs="-Tsvg \""+ov+"\" "+dir ;
if (portable_system("dot",vlargs)!=0)
{