diff options
Diffstat (limited to 'src')
218 files changed, 21453 insertions, 24386 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23460d0..cb28911 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,11 @@ include_directories( file(MAKE_DIRECTORY ${GENERATED_SRC}) -file(GLOB LANGUAGE_FILES "${CMAKE_SOURCE_DIR}/src/translator_??.h") +if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0") + file(GLOB LANGUAGE_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/translator_??.h") +else() + file(GLOB LANGUAGE_FILES "${CMAKE_CURRENT_LIST_DIR}/translator_??.h") +endif() # instead of increasebuffer.py add_definitions(-DYY_BUF_SIZE=${enlarge_lex_buffers} -DYY_READ_BUF_SIZE=${enlarge_lex_buffers}) @@ -35,8 +39,8 @@ set_source_files_properties(${GENERATED_SRC}/settings.h PROPERTIES GENERATED 1) # 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 + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/configgen.py -maph ${CMAKE_CURRENT_LIST_DIR}/config.xml > ${GENERATED_SRC}/configvalues.h + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/config.xml ${CMAKE_CURRENT_LIST_DIR}/configgen.py OUTPUT ${GENERATED_SRC}/configvalues.h ) set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1) @@ -47,16 +51,16 @@ add_custom_target( # configvalues.cpp add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -maps ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC}/configvalues.cpp - DEPENDS ${CMAKE_SOURCE_DIR}/src/config.xml ${CMAKE_SOURCE_DIR}/src/configgen.py + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/configgen.py -maps ${CMAKE_CURRENT_LIST_DIR}/config.xml > ${GENERATED_SRC}/configvalues.cpp + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/config.xml ${CMAKE_CURRENT_LIST_DIR}/configgen.py OUTPUT ${GENERATED_SRC}/configvalues.cpp ) set_source_files_properties(${GENERATED_SRC}/configvalues.cpp PROPERTIES GENERATED 1) # configoptions.cpp add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -cpp ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC}/configoptions.cpp - DEPENDS ${CMAKE_SOURCE_DIR}/src/config.xml ${CMAKE_SOURCE_DIR}/src/configgen.py + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/configgen.py -cpp ${CMAKE_CURRENT_LIST_DIR}/config.xml > ${GENERATED_SRC}/configoptions.cpp + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/config.xml ${CMAKE_CURRENT_LIST_DIR}/configgen.py OUTPUT ${GENERATED_SRC}/configoptions.cpp ) set_source_files_properties(${GENERATED_SRC}/configoptions.cpp PROPERTIES GENERATED 1) @@ -64,8 +68,8 @@ set_source_files_properties(${GENERATED_SRC}/configoptions.cpp PROPERTIES GENERA # ce_parse.h add_custom_command( - COMMAND ${BISON_EXECUTABLE} -l -d -p ce_parsexpYY ${CMAKE_SOURCE_DIR}/src/constexp.y -o ce_parse.c - DEPENDS ${CMAKE_SOURCE_DIR}/src/constexp.y + COMMAND ${BISON_EXECUTABLE} -l -d -p ce_parsexpYY ${CMAKE_CURRENT_LIST_DIR}/constexp.y -o ce_parse.c + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/constexp.y OUTPUT ${GENERATED_SRC}/ce_parse.h WORKING_DIRECTORY ${GENERATED_SRC} ) @@ -81,21 +85,25 @@ add_custom_command( set_source_files_properties(${GENERATED_SRC}/lang_cfg.h PROPERTIES GENERATED 1) # all resource files -file(GLOB RESOURCES ${CMAKE_SOURCE_DIR}/templates/*/*) +if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0") + file(GLOB RESOURCES CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/templates/*/*) +else() + file(GLOB RESOURCES ${CMAKE_SOURCE_DIR}/templates/*/*) +endif() # resources.cpp add_custom_command( COMMENT "Generating ${GENERATED_SRC}/resources.cpp" - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/res2cc_cmd.py ${CMAKE_SOURCE_DIR}/templates ${GENERATED_SRC}/resources.cpp - DEPENDS ${RESOURCES} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py ${CMAKE_SOURCE_DIR}/templates ${GENERATED_SRC}/resources.cpp + DEPENDS ${RESOURCES} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py OUTPUT ${GENERATED_SRC}/resources.cpp ) set_source_files_properties(${GENERATED_SRC}/resources.cpp PROPERTIES GENERATED 1) # layout_default.xml add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/to_c_cmd.py < ${CMAKE_SOURCE_DIR}/src/layout_default.xml > ${GENERATED_SRC}/layout_default.xml.h - DEPENDS ${CMAKE_SOURCE_DIR}/src/layout_default.xml + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/to_c_cmd.py < ${CMAKE_CURRENT_LIST_DIR}/layout_default.xml > ${GENERATED_SRC}/layout_default.xml.h + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/layout_default.xml ${CMAKE_CURRENT_LIST_DIR}/to_c_cmd.py OUTPUT ${GENERATED_SRC}/layout_default.xml.h ) set_source_files_properties(${GENERATED_SRC}/layout_default.xml.h PROPERTIES GENERATED 1) @@ -107,7 +115,6 @@ set(LEX_FILES scanner fortranscanner fortrancode vhdlcode - tclscanner pre declinfo defargs @@ -124,17 +131,35 @@ foreach(lex_file ${LEX_FILES}) set(LEX_FILES_H ${LEX_FILES_H} " " ${GENERATED_SRC}/${lex_file}.l.h CACHE INTERNAL "Stores generated files") set(LEX_FILES_CPP ${LEX_FILES_CPP} " " ${GENERATED_SRC}/${lex_file}.cpp CACHE INTERNAL "Stores generated files") add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/src/${lex_file}.l > ${GENERATED_SRC}/${lex_file}.l.h - DEPENDS ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/src/${lex_file}.l + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scan_states.py ${CMAKE_CURRENT_LIST_DIR}/${lex_file}.l > ${GENERATED_SRC}/${lex_file}.l.h + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/scan_states.py ${CMAKE_CURRENT_LIST_DIR}/${lex_file}.l OUTPUT ${GENERATED_SRC}/${lex_file}.l.h ) set_source_files_properties(${GENERATED_SRC}/${lex_file}.l.h PROPERTIES GENERATED 1) + # for code coverage we need the flex sources in the build src directory + add_custom_command( + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/${lex_file}.l ${CMAKE_BINARY_DIR}/src/${lex_file}.l + DEPENDS ${CMAKE_SOURCE_DIR}/src/${lex_file}.l + OUTPUT ${CMAKE_BINARY_DIR}/src/${lex_file}.l + ) - FLEX_TARGET(${lex_file} ${lex_file}.l ${GENERATED_SRC}/${lex_file}.cpp COMPILE_FLAGS "${LEX_FLAGS}") + FLEX_TARGET(${lex_file} + ${CMAKE_CURRENT_LIST_DIR}/${lex_file}.l + ${GENERATED_SRC}/${lex_file}.cpp + COMPILE_FLAGS "${LEX_FLAGS}") endforeach() -BISON_TARGET(constexp constexp.y ${GENERATED_SRC}/ce_parse.cpp COMPILE_FLAGS "${YACC_FLAGS}") +BISON_TARGET(constexp + ${CMAKE_CURRENT_LIST_DIR}/constexp.y + ${GENERATED_SRC}/ce_parse.cpp + COMPILE_FLAGS "${YACC_FLAGS}") + +add_custom_command( + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/constexp.y ${CMAKE_BINARY_DIR}/src + DEPENDS ${CMAKE_SOURCE_DIR}/src/constexp.y + OUTPUT ${CMAKE_BINARY_DIR}/src/constexp.y +) add_library(doxycfg STATIC ${GENERATED_SRC}/lang_cfg.h @@ -143,25 +168,23 @@ add_library(doxycfg STATIC ${GENERATED_SRC}/configimpl.l.h ${GENERATED_SRC}/configoptions.cpp ${GENERATED_SRC}/configvalues.cpp + ${GENERATED_SRC}/settings.h portable.cpp portable_c.c + ftextstream.cpp + message.cpp + debug.cpp ) +add_sanitizers(doxycfg) -add_library(_doxygen STATIC - # custom generated files - ${GENERATED_SRC}/lang_cfg.h - ${GENERATED_SRC}/settings.h - ${GENERATED_SRC}/layout_default.xml.h - ${GENERATED_SRC}/ce_parse.h - ${GENERATED_SRC}/configvalues.h - ${GENERATED_SRC}/resources.cpp +add_library(doxymain STATIC # generated for/by flex/bison #${LEX_FILES_H} #unfortunately doesn't work in older versions of CMake (like 3.6.2) #${LEX_FILES_CPP} #unfortunately doesn't work in older versions of CMake (like 3.6.2) ${GENERATED_SRC}/code.l.h ${GENERATED_SRC}/commentcnv.l.h ${GENERATED_SRC}/commentscan.l.h - ${GENERATED_SRC}/configimpl.l.h + ${GENERATED_SRC}/constexp.cpp ${GENERATED_SRC}/constexp.l.h ${GENERATED_SRC}/declinfo.l.h ${GENERATED_SRC}/defargs.l.h @@ -173,14 +196,11 @@ add_library(_doxygen STATIC ${GENERATED_SRC}/pyscanner.l.h ${GENERATED_SRC}/scanner.l.h ${GENERATED_SRC}/sqlcode.l.h - ${GENERATED_SRC}/tclscanner.l.h ${GENERATED_SRC}/vhdlcode.l.h ${GENERATED_SRC}/xmlcode.l.h ${GENERATED_SRC}/code.cpp ${GENERATED_SRC}/commentcnv.cpp ${GENERATED_SRC}/commentscan.cpp - ${GENERATED_SRC}/configimpl.cpp - ${GENERATED_SRC}/constexp.cpp ${GENERATED_SRC}/declinfo.cpp ${GENERATED_SRC}/defargs.cpp ${GENERATED_SRC}/doctokenizer.cpp @@ -191,11 +211,15 @@ add_library(_doxygen STATIC ${GENERATED_SRC}/pyscanner.cpp ${GENERATED_SRC}/scanner.cpp ${GENERATED_SRC}/sqlcode.cpp - ${GENERATED_SRC}/tclscanner.cpp ${GENERATED_SRC}/vhdlcode.cpp ${GENERATED_SRC}/xmlcode.cpp # ${GENERATED_SRC}/ce_parse.cpp + # custom generated files + ${GENERATED_SRC}/lang_cfg.h + ${GENERATED_SRC}/layout_default.xml.h + ${GENERATED_SRC}/ce_parse.h + ${GENERATED_SRC}/resources.cpp # arguments.cpp cite.cpp @@ -206,9 +230,7 @@ add_library(_doxygen STATIC condparser.cpp context.cpp cppvalue.cpp - debug.cpp defgen.cpp - define.cpp definition.cpp dia.cpp diagram.cpp @@ -235,10 +257,8 @@ add_library(_doxygen STATIC emoji.cpp entry.cpp filedef.cpp - filename.cpp fileparser.cpp formula.cpp - ftextstream.cpp ftvhelp.cpp groupdef.cpp htags.cpp @@ -258,11 +278,8 @@ add_library(_doxygen STATIC memberdef.cpp membergroup.cpp memberlist.cpp - membername.cpp - message.cpp msc.cpp namespacedef.cpp - objcache.cpp outputgen.cpp outputlist.cpp pagedef.cpp @@ -288,35 +305,49 @@ add_library(_doxygen STATIC xmldocvisitor.cpp xmlgen.cpp ) +add_sanitizers(doxymain) + +# LLVM/clang headers give a lot of warnings with -Wshadow and -Wcast-align so we disable them for +# the one file that includes them + +if (NOT MSVC) +set_source_files_properties(clangparser.cpp PROPERTIES COMPILE_FLAGS "-Wno-shadow -Wno-cast-align") +endif() ##foreach(lex_file ${LEX_FILES}) -##add_library(_doxygen STATIC ${GENERATED_SRC}/${lex_file}.l.h) +##add_library(doxymain STATIC ${GENERATED_SRC}/${lex_file}.l.h) ##endforeach() -add_executable(doxygen main.cpp) +add_executable(doxygen + main.cpp +) +add_sanitizers(doxygen) if (use_libclang) find_package(LLVM REQUIRED CONFIG) find_package(Clang REQUIRED CONFIG) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") cmake_minimum_required(VERSION 3.1) - target_compile_features(_doxygen PRIVATE cxx_alignof) + target_compile_features(doxymain PRIVATE cxx_alignof) target_compile_features(doxygen PRIVATE cxx_alignof) - target_compile_options(_doxygen PRIVATE -stdlib=libc++) - target_compile_options(doxygen PRIVATE -stdlib=libc++) - elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - target_compile_options(_doxygen PRIVATE -std=c++11) - target_compile_options(doxygen PRIVATE -std=c++11) + if (use_libc++) + target_compile_options(doxymain PRIVATE -stdlib=libc++) + target_compile_options(doxygen PRIVATE -stdlib=libc++) + endif() endif() include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) - llvm_map_components_to_libnames(llvm_libs support core option) + if (static_libclang) + set(CLANG_LIBS libclang clangTooling) + else() # dynamically linked version of clang + llvm_config(doxymain USE_SHARED support) + set(CLANG_LIBS libclang clang-cpp) + endif() target_compile_definitions(doxygen PRIVATE ${LLVM_DEFINITIONS}) - set(CLANG_LIBS libclang clangTooling ${llvm_libs}) endif() -target_link_libraries(doxygen - _doxygen +target_link_libraries(doxygen PRIVATE + doxymain doxycfg qtools md5 @@ -329,6 +360,19 @@ target_link_libraries(doxygen ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_LIBS} ${CLANG_LIBS} + ${COVERAGE_LINKER_FLAGS} + ${DOXYGEN_EXTRA_LINK_OPTIONS} ) +set_project_warnings(doxycfg) +set_project_warnings(doxymain) +set_project_warnings(doxygen) + +set_project_coverage(qtools) +set_project_coverage(doxycfg) +set_project_coverage(doxymain) +set_project_coverage(doxygen) + + install(TARGETS doxygen DESTINATION bin) + diff --git a/src/arguments.h b/src/arguments.h index 3464def..181a8d3 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -50,48 +50,91 @@ enum RefQualifierType RefQualifierRValue }; -/*! \brief This class represents an function or template argument list. +/*! \brief This class represents an function or template argument list. * * This class also stores some information about member that is typically - * put after the argument list, such as whether the member is const, + * put after the argument list, such as whether the member is const, * volatile or pure virtual. */ -class ArgumentList : public std::vector<Argument> +class ArgumentList { public: + using Vec = std::vector<Argument>; + using iterator = typename Vec::iterator; + using const_iterator = typename Vec::const_iterator; + /*! Does any argument of this list have documentation? */ bool hasDocumentation() const; /*! Does this list have zero or more parameters */ bool hasParameters() const { - return !empty() || noParameters; + return !empty() || m_noParameters; } void reset() { clear(); - constSpecifier = FALSE; - volatileSpecifier = FALSE; - pureSpecifier = FALSE; - trailingReturnType.resize(0); - isDeleted = FALSE; - refQualifier = RefQualifierNone; - noParameters = FALSE; + m_constSpecifier = FALSE; + m_volatileSpecifier = FALSE; + m_pureSpecifier = FALSE; + m_trailingReturnType.resize(0); + m_isDeleted = FALSE; + m_refQualifier = RefQualifierNone; + m_noParameters = FALSE; } + // make vector accessible + iterator begin() { return m_args.begin(); } + iterator end() { return m_args.end(); } + const_iterator begin() const { return m_args.cbegin(); } + const_iterator end() const { return m_args.cend(); } + const_iterator cbegin() const { return m_args.cbegin(); } + const_iterator cend() const { return m_args.cend(); } + bool empty() const { return m_args.empty(); } + size_t size() const { return m_args.size(); } + void clear() { m_args.clear(); } + void push_back(const Argument &a) { m_args.push_back(a); } + Argument &back() { return m_args.back(); } + const Argument &back() const { return m_args.back(); } + Argument &front() { return m_args.front(); } + const Argument &front() const { return m_args.front(); } + Argument &at(size_t i) { return m_args.at(i); } + const Argument &at(size_t i) const { return m_args.at(i); } + + // getters for list wide attributes + bool constSpecifier() const { return m_constSpecifier; } + bool volatileSpecifier() const { return m_volatileSpecifier; } + bool pureSpecifier() const { return m_pureSpecifier; } + QCString trailingReturnType() const { return m_trailingReturnType; } + bool isDeleted() const { return m_isDeleted; } + RefQualifierType refQualifier() const { return m_refQualifier; } + bool noParameters() const { return m_noParameters; } + + void setConstSpecifier(bool b) { m_constSpecifier = b; } + void setVolatileSpecifier(bool b) { m_volatileSpecifier = b; } + void setPureSpecifier(bool b) { m_pureSpecifier = b; } + void setTrailingReturnType(const QCString &s) { m_trailingReturnType = s; } + void setIsDeleted(bool b) { m_isDeleted = b; } + void setRefQualifier(RefQualifierType t) { m_refQualifier = t; } + void setNoParameters(bool b) { m_noParameters = b; } + + private: + std::vector<Argument> m_args; /*! Does the member modify the state of the class? */ - bool constSpecifier = FALSE; + bool m_constSpecifier = FALSE; /*! Is the member volatile? */ - bool volatileSpecifier = FALSE; + bool m_volatileSpecifier = FALSE; /*! Is this a pure virtual member? */ - bool pureSpecifier = FALSE; + bool m_pureSpecifier = FALSE; /*! C++11 style Trailing return type? */ - QCString trailingReturnType; + QCString m_trailingReturnType; /*! method with =delete */ - bool isDeleted = FALSE; + bool m_isDeleted = FALSE; /*! C++11 ref qualifier */ - RefQualifierType refQualifier = RefQualifierNone; + RefQualifierType m_refQualifier = RefQualifierNone; /*! is it an explicit empty list */ - bool noParameters = FALSE; + bool m_noParameters = FALSE; }; +using ArgumentLists = std::vector<ArgumentList>; + #endif diff --git a/src/bufstr.h b/src/bufstr.h index 331def2..e64a049 100644 --- a/src/bufstr.h +++ b/src/bufstr.h @@ -30,7 +30,7 @@ class BufStr { public: - BufStr(int size) + BufStr(uint size) : m_size(size), m_writeOffset(0), m_spareRoom(10240), m_buf(0) { m_buf = (char *)calloc(size,1); @@ -44,7 +44,7 @@ class BufStr makeRoomFor(1); m_buf[m_writeOffset++]=c; } - void addArray(const char *a,int len) + void addArray(const char *a,uint len) { makeRoomFor(len); memcpy(m_buf+m_writeOffset,a,len); @@ -74,7 +74,7 @@ class BufStr memset(m_buf+oldsize,0,m_size-oldsize); } } - int size() const + uint size() const { return m_size; } @@ -115,7 +115,7 @@ class BufStr } uint m_size; uint m_writeOffset; - const int m_spareRoom; // 10Kb extra room to avoid frequent resizing + const uint m_spareRoom; // 10Kb extra room to avoid frequent resizing char *m_buf; }; diff --git a/src/cite.cpp b/src/cite.cpp index 797881f..03bdb02 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -1,11 +1,11 @@ /****************************************************************************** * - * Copyright (C) 2011 by Dimitri van Heesch + * Copyright (C) 2020 by Dimitri van Heesch * Based on a patch by David Munger * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -15,178 +15,246 @@ */ #include "cite.h" -#include "portable.h" #include "config.h" -#include "message.h" -#include "util.h" -#include "language.h" #include "ftextstream.h" +#include "language.h" +#include "message.h" +#include "portable.h" #include "resourcemgr.h" -#include "doxygen.h" +#include "util.h" +#include "debug.h" + +#include <qfile.h> +#include <qfileinfo.h> #include <qdir.h> -//-------------------------------------------------------------------------- +#include <map> +#include <string> + +const char *bibTmpFile = "bibTmpFile_"; +const char *bibTmpDir = "bibTmpDir/"; + +class CiteInfoImpl : public CiteInfo +{ + public: + CiteInfoImpl(const char *label, const char *text=0) + : m_label(label), m_text(text) { } -const QCString CiteConsts::fileName("citelist"); -/* when changing this also take doxygen.bst into account */ -const QCString CiteConsts::anchorPrefix("CITEREF_"); -const QCString bibTmpFile("bibTmpFile_"); -const QCString bibTmpDir("bibTmpDir/"); + virtual QCString label() const { return m_label; } + virtual QCString text() const { return m_text; } -//-------------------------------------------------------------------------- + void setText(const char *s) { m_text = s; } -CiteDict::CiteDict(int size) : m_entries(size, FALSE) -{ - m_entries.setAutoDelete(TRUE); + private: + QCString m_label; + QCString m_text; +}; + +struct CitationManager::Private +{ + std::map< std::string,std::unique_ptr<CiteInfoImpl> > entries; +}; + +CitationManager &CitationManager::instance() +{ + static CitationManager ct; + return ct; } -void CiteDict::writeLatexBibliography(FTextStream &t) +CitationManager::CitationManager() : p(new Private) { - if (m_entries.isEmpty()) - return; +} - QCString style = Config_getString(LATEX_BIB_STYLE); - if (style.isEmpty()) - style="plain"; - QCString unit; - if (Config_getBool(COMPACT_LATEX)) - unit = "section"; - else - unit = "chapter"; - t << "% Bibliography\n" - "\\newpage\n" - "\\phantomsection\n"; - bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - if (!pdfHyperlinks) - { - t << "\\clearemptydoublepage\n"; - t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n"; - } - t << "\\bibliographystyle{" << style << "}\n" - "\\bibliography{"; - QStrList &citeDataList = Config_getList(CITE_BIB_FILES); - int i = 0; - const char *bibdata = citeDataList.first(); - while (bibdata) - { - QCString bibFile = bibdata; - // Note: file can now have multiple dots - if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; - QFileInfo fi(bibFile); - if (fi.exists()) - { - if (!bibFile.isEmpty()) - { - if (i) t << ","; - i++; - t << bibTmpFile << QCString().setNum(i); - } - } - bibdata = citeDataList.next(); - } - t << "}\n"; - if (pdfHyperlinks) +void CitationManager::insert(const char *label) +{ + p->entries.insert( + std::make_pair( + std::string(label), + std::make_unique<CiteInfoImpl>(label) + )); +} + +const CiteInfo *CitationManager::find(const char *label) const +{ + auto it = p->entries.find(label); + if (it!=p->entries.end()) { - t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n"; + return it->second.get(); } - t << "\n"; + return 0; } -void CiteDict::insert(const char *label) +void CitationManager::clear() { - m_entries.insert(label,new CiteInfo(label)); + p->entries.clear(); } -CiteInfo *CiteDict::find(const char *label) const +bool CitationManager::isEmpty() const { - return label ? m_entries.find(label) : 0; + size_t numFiles = Config_getList(CITE_BIB_FILES).size(); + return (numFiles==0 || p->entries.empty()); } -void CiteDict::clear() +const char *CitationManager::fileName() const { - m_entries.clear(); + return "citelist"; } -bool CiteDict::isEmpty() const +const char *CitationManager::anchorPrefix() const { - QStrList &citeBibFiles = Config_getList(CITE_BIB_FILES); - return (citeBibFiles.count()==0 || m_entries.isEmpty()); + return "CITEREF_"; } -void CiteDict::generatePage() const +void CitationManager::insertCrossReferencesForBibFile(const QCString &bibFile) { - //printf("** CiteDict::generatePage() count=%d\n",m_ordering.count()); + // sanity checks + if (bibFile.isEmpty()) + { + return; + } + QFileInfo fi(bibFile); + if (!fi.exists()) + { + err("bib file %s not found!\n",bibFile.data()); + return; + } + QFile f(bibFile); + if (!f.open(IO_ReadOnly)) + { + err("could not open file %s for reading\n",bibFile.data()); + return; + } - // do not generate an empty citations page - if (isEmpty()) return; // nothing to cite + // convert file to string + QCString doc; + QCString input(fi.size()+1); + f.readBlock(input.rawData(),fi.size()); + f.close(); + input.at(fi.size())='\0'; - // 0. add cross references from the bib files to the cite dictionary - QFile f; - QStrList &citeDataList = Config_getList(CITE_BIB_FILES); - const char *bibdata = citeDataList.first(); - while (bibdata) + int pos=0; + int s; + + // helper lambda function to get the next line of input and update pos accordingly + auto get_next_line = [&input,&pos,&s]() { - QCString bibFile = bibdata; - if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; - QFileInfo fi(bibFile); - if (fi.exists()) + uint prevPos = (uint)pos; + pos=s+1; + return input.mid(prevPos,(uint)(s-prevPos)); + }; + + // helper lambda function to return if the end of the input has reached + auto end_of_input = [&s]() + { + return s==-1; + }; + + // helper lambda function to proceed to the next line in the input, and update s + // to point to the start of the line. Return true as long as there is a new line. + auto has_next_line = [&input,&pos,&s]() + { + s=input.find('\n',pos); + return s!=-1; + }; + + // search for citation cross references + QCString citeName; + while (has_next_line()) + { + QCString line = get_next_line(); + + int i; + if (line.stripWhiteSpace().startsWith("@")) { - if (!bibFile.isEmpty()) + // assumption entry like: "@book { name," or "@book { name" (spaces optional) + int j = line.find('{'); + // when no {, go hunting for it + while (j==-1 && has_next_line()) { - f.setName(bibFile); - if (!f.open(IO_ReadOnly)) - { - err("could not open file %s for reading\n",bibFile.data()); - } - QCString doc; - QFileInfo fi(bibFile); - QCString input(fi.size()+1); - f.readBlock(input.rawData(),fi.size()); - f.close(); - input.at(fi.size())='\0'; - int p=0,s; - while ((s=input.find('\n',p))!=-1) + line = get_next_line(); + j = line.find('{'); + } + // search for the name + citeName = ""; + if (!end_of_input() && j!=-1) // to prevent something like "@manual ," and no { found + { + int k = line.find(',',j); + j++; + // found a line "@....{.....,...." or "@.....{....." + // ^=j ^=k ^=j k=-1 + while (!end_of_input() && citeName.isEmpty()) { - QCString line = input.mid(p,s-p); - p=s+1; - - int i; - if ((i = line.find("crossref")) != -1) /* assumption cross reference is on one line and the only item */ + if (k!=-1) + { + citeName = line.mid((uint)(j),(uint)(k-j)); + } + else + { + citeName = line.mid((uint)(j)); + } + citeName = citeName.stripWhiteSpace(); + j = 0; + if (citeName.isEmpty() && has_next_line()) { - int j=line.find("{",i); - int k=line.find("}",i); - if (j!=-1 && k!=-1) - { - QCString label = line.mid(j+1,k-j-1); - if (!m_entries.find(label)) Doxygen::citeDict->insert(label.data()); - } + line = get_next_line(); + k = line.find(','); } } } + //printf("citeName = #%s#\n",citeName.data()); } - else if (!fi.exists()) + else if ((i=line.find("crossref"))!=-1 && !citeName.isEmpty()) /* assumption cross reference is on one line and the only item */ { - err("bib file %s not found!\n",bibFile.data()); + int j = line.find('{',i); + int k = line.find('}',i); + if (j>i && k>j) + { + QCString crossrefName = line.mid((uint)(j+1),(uint)(k-j-1)); + // check if the reference with the cross reference is used + // insert cross reference when cross reference has not yet been added. + if ((p->entries.find(citeName.data())!=p->entries.end()) && + (p->entries.find(crossrefName.data())==p->entries.end())) // not found yet + { + insert(crossrefName); + } + } } - bibdata = citeDataList.next(); + } +} + +void CitationManager::generatePage() +{ + //printf("** CitationManager::generatePage() count=%d\n",m_ordering.count()); + + // do not generate an empty citations page + if (isEmpty()) return; // nothing to cite + + bool citeDebug = Debug::isFlagSet(Debug::Cite); + + // 0. add cross references from the bib files to the cite dictionary + QFile f; + const StringVector &citeDataList = Config_getList(CITE_BIB_FILES); + for (const auto &bibdata : citeDataList) + { + QCString bibFile = bibdata.c_str(); + if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; + insertCrossReferencesForBibFile(bibFile); } // 1. generate file with markers and citations to OUTPUT_DIRECTORY QCString outputDir = Config_getString(OUTPUT_DIRECTORY); QCString citeListFile = outputDir+"/citelist.doc"; f.setName(citeListFile); - if (!f.open(IO_WriteOnly)) + if (!f.open(IO_WriteOnly)) { err("could not open file %s for writing\n",citeListFile.data()); } FTextStream t(&f); t << "<!-- BEGIN CITATIONS -->" << endl; t << "<!--" << endl; - QDictIterator<CiteInfo> it(m_entries); - CiteInfo *ci; - for (it.toFirst();(ci=it.current());++it) + for (const auto &it : p->entries) { - t << "\\citation{" << ci->label << "}" << endl; + t << "\\citation{" << it.second->label() << "}" << endl; } t << "-->" << endl; t << "<!-- END CITATIONS -->" << endl; @@ -209,12 +277,15 @@ void CiteDict::generatePage() const QCString bibOutputDir = outputDir+"/"+bibTmpDir; QCString bibOutputFiles = ""; QDir thisDir; - thisDir.mkdir(bibOutputDir); - bibdata = citeDataList.first(); + if (!thisDir.exists(bibOutputDir) && !thisDir.mkdir(bibOutputDir)) + { + err("Failed to create temporary output directory '%s', skipping citations\n",bibOutputDir.data()); + return; + } int i = 0; - while (bibdata) + for (const auto &bibdata : citeDataList) { - QCString bibFile = bibdata; + QCString bibFile = bibdata.c_str(); if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; QFileInfo fi(bibFile); if (fi.exists()) @@ -226,7 +297,6 @@ void CiteDict::generatePage() const bibOutputFiles = bibOutputFiles + " " + bibTmpDir + bibTmpFile + QCString().setNum(i) + ".bib"; } } - bibdata = citeDataList.next(); } QString oldDir = QDir::currentDirPath(); @@ -237,7 +307,7 @@ void CiteDict::generatePage() const int exitCode; Portable::sysTimerStop(); if ((exitCode=Portable::system("perl","\""+bib2xhtmlFile+"\" "+bibOutputFiles+" \""+ - citeListFile+"\"")) != 0) + citeListFile+"\"" + (citeDebug ? " -d" : ""))) != 0) { err("Problems running bibtex. Verify that the command 'perl --version' works from the command line. Exit code: %d\n", exitCode); @@ -248,29 +318,29 @@ void CiteDict::generatePage() const // 6. read back the file f.setName(citeListFile); - if (!f.open(IO_ReadOnly)) + if (!f.open(IO_ReadOnly)) { err("could not open file %s for reading\n",citeListFile.data()); } - bool insideBib=FALSE; - + QCString doc; QFileInfo fi(citeListFile); QCString input(fi.size()+1); f.readBlock(input.rawData(),fi.size()); f.close(); input.at(fi.size())='\0'; - int p=0,s; + + bool insideBib=FALSE; + int pos=0,s; //printf("input=[%s]\n",input.data()); - while ((s=input.find('\n',p))!=-1) + while ((s=input.find('\n',pos))!=-1) { - QCString line = input.mid(p,s-p); - //printf("p=%d s=%d line=[%s]\n",p,s,line.data()); - p=s+1; + QCString line = input.mid((uint)pos,(uint)(s-pos)); + //printf("pos=%d s=%d line=[%s]\n",pos,s,line.data()); + pos=s+1; if (line.find("<!-- BEGIN BIBLIOGRAPHY")!=-1) insideBib=TRUE; else if (line.find("<!-- END BIBLIOGRAPH")!=-1) insideBib=FALSE; - int i; // determine text to use at the location of the @cite command if (insideBib && (i=line.find("name=\"CITEREF_"))!=-1) { @@ -278,15 +348,18 @@ void CiteDict::generatePage() const int k=line.find("]</a>"); if (j!=-1 && k!=-1) { - QCString label = line.mid(i+14,j-i-14); - QCString number = line.mid(j+2,k-j-1); + uint ui=(uint)i; + uint uj=(uint)j; + uint uk=(uint)k; + QCString label = line.mid(ui+14,uj-ui-14); + QCString number = line.mid(uj+2,uk-uj-1); label = substitute(substitute(label,"–","--"),"—","---"); - CiteInfo *ci = m_entries.find(label); - //printf("label='%s' number='%s' => %p\n",label.data(),number.data(),ci); - line = line.left(i+14) + label + line.right(line.length()-j); - if (ci) + line = line.left(ui+14) + label + line.right(line.length()-uj); + auto it = p->entries.find(label.data()); + //printf("label='%s' number='%s' => %p\n",label.data(),number.data(),it->second.get()); + if (it!=p->entries.end()) { - ci->text = number; + it->second->setText(number); } } } @@ -295,24 +368,21 @@ void CiteDict::generatePage() const //printf("doc=[%s]\n",doc.data()); // 7. add it as a page - addRelatedPage(CiteConsts::fileName, - theTranslator->trCiteReferences(),doc,CiteConsts::fileName,1); + addRelatedPage(fileName(),theTranslator->trCiteReferences(),doc,fileName(),1); - // 8. for latex we just copy the bib files to the output and let + // 8. for latex we just copy the bib files to the output and let // latex do this work. if (Config_getBool(GENERATE_LATEX)) { // copy bib files to the latex output dir - QStrList &citeDataList = Config_getList(CITE_BIB_FILES); QCString latexOutputDir = Config_getString(LATEX_OUTPUT)+"/"; - int i = 0; - const char *bibdata = citeDataList.first(); - while (bibdata) + i = 0; + for (const auto &bibdata : citeDataList) { - QCString bibFile = bibdata; + QCString bibFile = bibdata.c_str(); // Note: file can now have multiple dots if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; - QFileInfo fi(bibFile); + fi.setFile(bibFile); if (fi.exists()) { if (!bibFile.isEmpty()) @@ -327,21 +397,78 @@ void CiteDict::generatePage() const { err("bib file %s not found!\n",bibFile.data()); } - bibdata = citeDataList.next(); } } // 9. Remove temporary files - thisDir.remove(citeListFile); - thisDir.remove(doxygenBstFile); - thisDir.remove(bib2xhtmlFile); - // we might try to remove too many files as empty files didn't get a corresponding new file - // but the remove function does not emit an error for it and we don't catch the error return - // so no problem. - for (unsigned int j = 1; j <= citeDataList.count(); j++) + if (!citeDebug) + { + thisDir.remove(citeListFile); + thisDir.remove(doxygenBstFile); + thisDir.remove(bib2xhtmlFile); + // we might try to remove too many files as empty files didn't get a corresponding new file + // but the remove function does not emit an error for it and we don't catch the error return + // so no problem. + for (size_t j = 1; j <= citeDataList.size(); j++) + { + thisDir.remove(bibOutputDir + bibTmpFile + QCString().setNum(static_cast<ulong>(j)) + ".bib"); + } + thisDir.rmdir(bibOutputDir); + } +} + +void CitationManager::writeLatexBibliography(FTextStream &t) const +{ + if (p->entries.empty()) return; + + QCString style = Config_getString(LATEX_BIB_STYLE); + if (style.isEmpty()) + { + style="plain"; + } + QCString unit; + if (Config_getBool(COMPACT_LATEX)) + { + unit = "section"; + } + else + { + unit = "chapter"; + } + t << "% Bibliography\n" + "\\newpage\n" + "\\phantomsection\n"; + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + if (!pdfHyperlinks) + { + t << "\\clearemptydoublepage\n"; + t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n"; + } + t << "\\bibliographystyle{" << style << "}\n" + "\\bibliography{"; + const StringVector &citeDataList = Config_getList(CITE_BIB_FILES); + int i = 0; + for (const auto &bibdata : citeDataList) + { + QCString bibFile = bibdata.c_str(); + // Note: file can now have multiple dots + if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; + QFileInfo fi(bibFile); + if (fi.exists()) + { + if (!bibFile.isEmpty()) + { + if (i) t << ","; + i++; + t << bibTmpFile << QCString().setNum(i); + } + } + } + t << "}\n"; + if (pdfHyperlinks) { - thisDir.remove(bibOutputDir + bibTmpFile + QCString().setNum(j) + ".bib"); + t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n"; } - thisDir.rmdir(bibOutputDir); + t << "\n"; } @@ -1,13 +1,11 @@ /****************************************************************************** * - * - * - * Copyright (C) 2011 by Dimitri van Heesch + * Copyright (C) 2020 by Dimitri van Heesch * Based on a patch by David Munger * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,83 +14,65 @@ * */ -#ifndef CITEDB_H -#define CITEDB_H +#ifndef CITE_H +#define CITE_H -#include <qdict.h> +#include <memory> -class FTextStream; +#include <qcstring.h> -/// String constants for citations -struct CiteConsts -{ - static const QCString fileName; - static const QCString anchorPrefix; -}; +class FTextStream; /// Citation-related data. struct CiteInfo { - CiteInfo(const char *label_, const char *text_=0, const char *fullText_=0, - const char *ref_=0) : - label(label_), text(text_), fullText(fullText_), ref(ref_) - { } - - CiteInfo(const CiteInfo &o) - { label=o.label.copy(); text=o.text.copy(); fullText=o.fullText.copy(); ref=o.ref.copy(); } - - QCString label; - QCString text; - QCString fullText; - QCString ref; - + virtual ~CiteInfo() {} + virtual QCString label() const = 0; + virtual QCString text() const = 0; }; /** - * @brief Cite database access class. - * @details This class provides access do the database of bibliographic + * @brief Citation manager class. + * @details This class provides access do the database of bibliographic * references through the bibtex backend. */ -class CiteDict +class CitationManager { public: - /** Create the database, with an expected maximum of \a size entries */ - CiteDict(int size); - -// /** Resolve references to citations */ -// void resolve(); + static CitationManager &instance(); /** Insert a citation identified by \a label into the database */ void insert(const char *label); - /** Return the citation info for a given \a label */ - CiteInfo *find(const char *label) const; + /** Return the citation info for a given \a label. + * Ownership of the info stays with the manager. + */ + const CiteInfo *find(const char *label) const; /** Generate the citations page */ - void generatePage() const; + void generatePage(); /** clears the database */ void clear(); - /** return TRUE if there are no citations. - * Only valid after calling resolve() + /** return TRUE if there are no citations. */ bool isEmpty() const; - /** writes the latex code for the standard bibliography - * section to text stream \a t + /** writes the latex code for the standard bibliography + * section to text stream \a t */ - void writeLatexBibliography(FTextStream &t); + void writeLatexBibliography(FTextStream &t) const; + + const char *fileName() const; + const char *anchorPrefix() const; private: -// bool writeAux(); -// bool writeBst(); -// bool execute(); -// void parse(); -// void clean(); - QDict<CiteInfo> m_entries; -// QList<QCString> m_ordering; - QCString m_baseFileName; + /** Create the database, with an expected maximum of \a size entries */ + CitationManager(); + void insertCrossReferencesForBibFile(const QCString &bibFile); + struct Private; + std::unique_ptr<Private> p; }; -#endif +#endif // CITE_H diff --git a/src/clangparser.cpp b/src/clangparser.cpp index f6020dd..1ac9138 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -1,6 +1,7 @@ #include "clangparser.h" #include "settings.h" #include <stdio.h> +#include <mutex> #if USE_LIBCLANG #include <clang-c/Index.h> @@ -20,17 +21,15 @@ #include "membername.h" #include "filename.h" #include "tooltip.h" - -static Definition *g_currentDefinition=0; -static MemberDef *g_currentMemberDef=0; -static uint g_currentLine=0; -static bool g_searchForBody=FALSE; -static bool g_insideBody=FALSE; -static uint g_bracketCount=0; #endif +//-------------------------------------------------------------------------- + +std::mutex g_clangMutex; + ClangParser *ClangParser::instance() { + std::lock_guard<std::mutex> lock(g_clangMutex); if (!s_instance) s_instance = new ClangParser; return s_instance; } @@ -40,29 +39,7 @@ ClangParser *ClangParser::s_instance = 0; //-------------------------------------------------------------------------- #if USE_LIBCLANG -class ClangParser::Private -{ - public: - enum DetectedLang { Detected_Cpp, Detected_ObjC, Detected_ObjCpp }; - Private() : tu(0), tokens(0), numTokens(0), cursors(0), - ufs(0), sources(0), numFiles(0), fileMapping(257), - detectedLang(Detected_Cpp) - { fileMapping.setAutoDelete(TRUE); } - int getCurrentTokenLine(); - CXIndex index; - CXTranslationUnit tu; - QCString fileName; - CXToken *tokens; - uint numTokens; - CXCursor *cursors; - uint curLine; - uint curToken; - CXUnsavedFile *ufs; - QCString *sources; - uint numFiles; - QDict<uint> fileMapping; - DetectedLang detectedLang; -}; +enum class DetectedLang { Cpp, ObjC, ObjCpp }; static QCString detab(const QCString &s) { @@ -84,7 +61,7 @@ static QCString detab(const QCString &s) int stop = tabSize - (col%tabSize); //printf("expand at %d stop=%d\n",col,stop); col+=stop; - while (stop--) out.addChar(' '); + while (stop--) out.addChar(' '); } break; case '\n': // reset column counter @@ -118,116 +95,136 @@ static QCString detab(const QCString &s) return out.get(); } -/** Callback function called for each include in a translation unit */ -static void inclusionVisitor(CXFile includedFile, - CXSourceLocation* /*inclusionStack*/, - unsigned /*includeLen*/, - CXClientData clientData) +static QCString keywordToType(const char *keyword) { - QDict<void> *fileDict = (QDict<void> *)clientData; - CXString incFileName = clang_getFileName(includedFile); - //printf("--- file %s includes %s\n",fileName,clang_getCString(incFileName)); - fileDict->insert(clang_getCString(incFileName),(void*)0x8); - clang_disposeString(incFileName); + static const StringUnorderedSet flowKeywords({ + "break", "case", "catch", "continue", "default", "do", + "else", "finally", "for", "foreach", "for each", "goto", + "if", "return", "switch", "throw", "throws", "try", + "while", "@try", "@catch", "@finally" }); + static const StringUnorderedSet typeKeywords({ + "bool", "char", "double", "float", "int", "long", "object", + "short", "signed", "unsigned", "void", "wchar_t", "size_t", + "boolean", "id", "SEL", "string", "nullptr" }); + if (flowKeywords.find(keyword)!=flowKeywords.end()) return "keywordflow"; + if (typeKeywords.find(keyword)!=typeKeywords.end()) return "keywordtype"; + return "keyword"; } -/** filter the \a files and only keep those that are found as include files - * within the current translation unit. - * @param[in,out] files The list of files to filter. - */ -void ClangParser::determineInputFilesInSameTu(QStrList &files) + +//-------------------------------------------------------------------------- + +class ClangTUParser::Private { - // put the files in this translation unit in a dictionary - QDict<void> incFound(257); - clang_getInclusions(p->tu, - inclusionVisitor, - (CXClientData)&incFound - ); - // create a new filtered file list - QStrList resultIncludes; - QStrListIterator it2(files); - for (it2.toFirst();it2.current();++it2) - { - if (incFound.find(it2.current())) - { - resultIncludes.append(it2.current()); - } - } - // replace the original list - files=resultIncludes; + public: + Private(const ClangParser &p,const FileDef *fd) + : parser(p), fileDef(fd) {} + const ClangParser &parser; + const FileDef *fileDef; + CXIndex index = 0; + uint curToken = 0; + DetectedLang detectedLang = DetectedLang::Cpp; + uint numFiles = 0; + std::vector<QCString> sources; + std::vector<CXUnsavedFile> ufs; + std::vector<CXCursor> cursors; + std::unordered_map<std::string,uint> fileMapping; + CXTranslationUnit tu; + CXToken *tokens = 0; + uint numTokens = 0; + StringVector filesInSameTU; + + // state while parsing sources + MemberDef *currentMemberDef=0; + uint currentLine=0; + bool searchForBody=FALSE; + bool insideBody=FALSE; + uint bracketCount=0; +}; + +ClangTUParser::ClangTUParser(const ClangParser &parser,const FileDef *fd) + : p(std::make_unique<Private>(parser,fd)) +{ + //printf("ClangTUParser::ClangTUParser() this=%p\n",this); } -void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit) +StringVector ClangTUParser::filesInSameTU() const { - 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_getString(CLANG_DATABASE_PATH); + return p->filesInSameTU; +} + +void ClangTUParser::parse() +{ + //printf("ClangTUParser::parse() this=%p\n",this); + QCString fileName = p->fileDef->absFilePath(); + p->fileDef->getAllIncludeFilesRecursively(p->filesInSameTU); + //printf("ClangTUParser::ClangTUParser(fileName=%s,#filesInSameTU=%d)\n", + // qPrint(fileName),(int)p->filesInSameTU.size()); + bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); + bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); + const StringVector &includePath = Config_getList(INCLUDE_PATH); + const StringVector &clangOptions = Config_getList(CLANG_OPTIONS); if (!clangAssistedParsing) return; //printf("ClangParser::start(%s)\n",fileName); - p->fileName = fileName; + assert(p->index==0); + assert(p->tokens==0); + assert(p->numTokens==0); p->index = clang_createIndex(0, 0); - p->curLine = 1; p->curToken = 0; - QDictIterator<void> di(Doxygen::inputPaths); + p->cursors.clear(); 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; + size_t clang_option_len = 0; std::vector<clang::tooling::CompileCommand> command; - if (qstrcmp(clangCompileDatabase, "0") != 0) + if (p->parser.database()!=nullptr) { - 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(); - } - } + // check if the file we are parsing is in the DB + command = p->parser.database()->getCompileCommands(fileName.data()); + 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)); + char **argv = (char**)malloc(sizeof(char*)* + (4+Doxygen::inputPaths.size()+ + includePath.size()+ + clangOptions.size()+ + 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++] = qstrdup(option->c_str()); - } - // this extra addition to argv is accounted for as we are skipping the first entry in - argv[argc++]=qstrdup("-w"); // finally, turn off warnings. + 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++] = qstrdup(option->c_str()); + } + // user specified options + for (size_t i=0;i<clangOptions.size();i++) + { + argv[argc++]=qstrdup(clangOptions[i].c_str()); + } + // this extra addition to argv is accounted for as we are skipping the first entry in + argv[argc++]=qstrdup("-w"); // finally, turn off warnings. } else { // add include paths for input files - for (di.toFirst();di.current();++di,++argc) + for (const std::string &path : Doxygen::inputPaths) { - QCString inc = QCString("-I")+di.currentKey(); - argv[argc]=qstrdup(inc.data()); + QCString inc = QCString("-I")+path.data(); + argv[argc++]=qstrdup(inc.data()); //printf("argv[%d]=%s\n",argc,argv[argc]); } // add external include paths - for (uint i=0;i<includePath.count();i++) + for (size_t i=0;i<includePath.size();i++) { - QCString inc = QCString("-I")+includePath.at(i); + QCString inc = QCString("-I")+includePath[i].c_str(); argv[argc++]=qstrdup(inc.data()); } // user specified options - for (uint i=0;i<clangOptions.count();i++) + for (size_t i=0;i<clangOptions.size();i++) { - argv[argc++]=qstrdup(clangOptions.at(i)); + argv[argc++]=qstrdup(clangOptions[i].c_str()); } // extra options argv[argc++]=qstrdup("-ferror-limit=0"); @@ -238,188 +235,148 @@ void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit) // we use the source file to detected the language. Detection will fail if you // pass a bunch of .h files containing ObjC code, and no sources :-( SrcLangExt lang = getLanguageFromFileName(fileName); - if (lang==SrcLangExt_ObjC || p->detectedLang!=ClangParser::Private::Detected_Cpp) + if (lang==SrcLangExt_ObjC || p->detectedLang!=DetectedLang::Cpp) { QCString fn = fileName; - if (p->detectedLang==ClangParser::Private::Detected_Cpp && + if (p->detectedLang!=DetectedLang::Cpp && (fn.right(4).lower()==".cpp" || fn.right(4).lower()==".cxx" || fn.right(3).lower()==".cc" || fn.right(2).lower()==".c")) { // fall back to C/C++ once we see an extension that indicates this - p->detectedLang = ClangParser::Private::Detected_Cpp; + p->detectedLang = DetectedLang::Cpp; } else if (fn.right(3).lower()==".mm") // switch to Objective C++ { - p->detectedLang = ClangParser::Private::Detected_ObjCpp; + p->detectedLang = DetectedLang::ObjCpp; } else if (fn.right(2).lower()==".m") // switch to Objective C { - p->detectedLang = ClangParser::Private::Detected_ObjC; + p->detectedLang = DetectedLang::ObjC; } } - switch(p->detectedLang) + switch (p->detectedLang) { - case ClangParser::Private::Detected_Cpp: - argv[argc++]=qstrdup("c++"); - break; - case ClangParser::Private::Detected_ObjC: - argv[argc++]=qstrdup("objective-c"); - break; - case ClangParser::Private::Detected_ObjCpp: - argv[argc++]=qstrdup("objective-c++"); - break; + case DetectedLang::Cpp: argv[argc++]=qstrdup("c++"); break; + case DetectedLang::ObjC: argv[argc++]=qstrdup("objective-c"); break; + case DetectedLang::ObjCpp: argv[argc++]=qstrdup("objective-c++"); break; } // provide the input and and its dependencies as unsaved files so we can // pass the filtered versions argv[argc++]=qstrdup(fileName); } - static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); //printf("source %s ----------\n%s\n-------------\n\n", // fileName,p->source.data()); - uint numUnsavedFiles = filesInTranslationUnit.count()+1; + int numUnsavedFiles = static_cast<int>(p->filesInSameTU.size()+1); p->numFiles = numUnsavedFiles; - p->sources = new QCString[numUnsavedFiles]; - p->ufs = new CXUnsavedFile[numUnsavedFiles]; + p->sources.resize(numUnsavedFiles); + p->ufs.resize(numUnsavedFiles); p->sources[0] = detab(fileToString(fileName,filterSourceFiles,TRUE)); p->ufs[0].Filename = qstrdup(fileName); p->ufs[0].Contents = p->sources[0].data(); p->ufs[0].Length = p->sources[0].length(); - QStrListIterator it(filesInTranslationUnit); - uint i=1; - for (it.toFirst();it.current() && i<numUnsavedFiles;++it,i++) - { - p->fileMapping.insert(it.current(),new uint(i)); - p->sources[i] = detab(fileToString(it.current(),filterSourceFiles,TRUE)); - p->ufs[i].Filename = qstrdup(it.current()); + p->fileMapping.insert({fileName.data(),0}); + int i=1; + for (auto it = p->filesInSameTU.begin(); + it != p->filesInSameTU.end() && i<numUnsavedFiles; + ++it, i++) + { + p->fileMapping.insert({it->c_str(),static_cast<uint>(i)}); + p->sources[i] = detab(fileToString(it->c_str(),filterSourceFiles,TRUE)); + p->ufs[i].Filename = qstrdup(it->c_str()); p->ufs[i].Contents = p->sources[i].data(); p->ufs[i].Length = p->sources[i].length(); } // let libclang do the actual parsing p->tu = clang_parseTranslationUnit(p->index, 0, - argv, argc, p->ufs, numUnsavedFiles, + argv, argc, p->ufs.data(), numUnsavedFiles, CXTranslationUnit_DetailedPreprocessingRecord); + //printf(" tu=%p\n",p->tu); // free arguments - for (int i=0;i<argc;++i) + for (i=0;i<argc;++i) { - free(argv[i]); + delete[](argv[i]); } free(argv); if (p->tu) { - // filter out any includes not found by the clang parser - determineInputFilesInSameTu(filesInTranslationUnit); - // show any warnings that the compiler produced - for (uint i=0, n=clang_getNumDiagnostics(p->tu); i!=n; ++i) + int n=clang_getNumDiagnostics(p->tu); + for (i=0; i!=n; ++i) { - CXDiagnostic diag = clang_getDiagnostic(p->tu, i); + CXDiagnostic diag = clang_getDiagnostic(p->tu, i); CXString string = clang_formatDiagnostic(diag, - clang_defaultDiagnosticDisplayOptions()); + clang_defaultDiagnosticDisplayOptions()); err("%s [clang]\n",clang_getCString(string)); clang_disposeString(string); clang_disposeDiagnostic(diag); } - - // create a source range for the given file - QFileInfo fi(fileName); - CXFile f = clang_getFile(p->tu, fileName); - CXSourceLocation fileBegin = clang_getLocationForOffset(p->tu, f, 0); - CXSourceLocation fileEnd = clang_getLocationForOffset(p->tu, f, p->ufs[0].Length); - CXSourceRange fileRange = clang_getRange(fileBegin, fileEnd); - - // produce a token stream for the file - clang_tokenize(p->tu,fileRange,&p->tokens,&p->numTokens); - - // produce cursors for each token in the stream - p->cursors=new CXCursor[p->numTokens]; - clang_annotateTokens(p->tu,p->tokens,p->numTokens,p->cursors); } else { + err("clang: Failed to parse translation unit %s\n",qPrint(fileName)); + } +} + +ClangTUParser::~ClangTUParser() +{ + //printf("ClangTUParser::~ClangTUParser() this=%p\n",this); + static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); + if (!clangAssistedParsing) return; + if (p->tu) + { + p->cursors.clear(); + clang_disposeTokens(p->tu,p->tokens,p->numTokens); + clang_disposeTranslationUnit(p->tu); + clang_disposeIndex(p->index); + p->fileMapping.clear(); p->tokens = 0; p->numTokens = 0; - p->cursors = 0; - err("clang: Failed to parse translation unit %s\n",fileName); } + for (uint i=0;i<p->numFiles;i++) + { + delete[] p->ufs[i].Filename; + } + p->ufs.clear(); + p->sources.clear(); + p->numFiles = 0; + p->tu = 0; } -void ClangParser::switchToFile(const char *fileName) +void ClangTUParser::switchToFile(FileDef *fd) { + //printf("ClangTUParser::switchToFile(%s) this=%p\n",qPrint(fd->absFilePath()),this); if (p->tu) { - delete[] p->cursors; + p->cursors.clear(); clang_disposeTokens(p->tu,p->tokens,p->numTokens); p->tokens = 0; p->numTokens = 0; - p->cursors = 0; - QFileInfo fi(fileName); - CXFile f = clang_getFile(p->tu, fileName); - uint *pIndex=p->fileMapping.find(fileName); - if (pIndex && *pIndex<p->numFiles) + CXFile f = clang_getFile(p->tu, fd->absFilePath()); + auto it = p->fileMapping.find(fd->absFilePath().data()); + if (it!=p->fileMapping.end() && it->second < p->numFiles) { - uint i=*pIndex; + uint i = it->second; //printf("switchToFile %s: len=%ld\n",fileName,p->ufs[i].Length); CXSourceLocation fileBegin = clang_getLocationForOffset(p->tu, f, 0); CXSourceLocation fileEnd = clang_getLocationForOffset(p->tu, f, p->ufs[i].Length); CXSourceRange fileRange = clang_getRange(fileBegin, fileEnd); clang_tokenize(p->tu,fileRange,&p->tokens,&p->numTokens); - p->cursors=new CXCursor[p->numTokens]; - clang_annotateTokens(p->tu,p->tokens,p->numTokens,p->cursors); - - p->curLine = 1; + p->cursors.resize(p->numTokens); + clang_annotateTokens(p->tu,p->tokens,p->numTokens,p->cursors.data()); p->curToken = 0; } else { - err("clang: Failed to find input file %s in mapping\n",fileName); + err("clang: Failed to find input file %s in mapping\n",qPrint(fd->absFilePath())); } } } -void ClangParser::finish() -{ - static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); - if (!clangAssistedParsing) return; - if (p->tu) - { - //printf("ClangParser::finish()\n"); - delete[] p->cursors; - clang_disposeTokens(p->tu,p->tokens,p->numTokens); - clang_disposeTranslationUnit(p->tu); - clang_disposeIndex(p->index); - p->fileMapping.clear(); - p->tokens = 0; - p->numTokens = 0; - p->cursors = 0; - } - for (uint i=0;i<p->numFiles;i++) - { - free((void *)p->ufs[i].Filename); - } - delete[] p->ufs; - delete[] p->sources; - p->ufs = 0; - p->sources = 0; - p->numFiles = 0; - p->tu = 0; -} - -int ClangParser::Private::getCurrentTokenLine() -{ - uint l, c; - if (numTokens==0) return 1; - // guard against filters that reduce the number of lines - if (curToken>=numTokens) curToken=numTokens-1; - CXSourceLocation start = clang_getTokenLocation(tu,tokens[curToken]); - clang_getSpellingLocation(start, 0, &l, &c, 0); - return l; -} - -QCString ClangParser::lookup(uint line,const char *symbol) +QCString ClangTUParser::lookup(uint line,const char *symbol) { //printf("ClangParser::lookup(%d,%s)\n",line,symbol); QCString result; @@ -427,19 +384,30 @@ QCString ClangParser::lookup(uint line,const char *symbol) static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); if (!clangAssistedParsing) return result; + auto getCurrentTokenLine = [=]() -> uint + { + uint l, c; + if (p->numTokens==0) return 1; + // guard against filters that reduce the number of lines + if (p->curToken>=p->numTokens) p->curToken=p->numTokens-1; + CXSourceLocation start = clang_getTokenLocation(p->tu,p->tokens[p->curToken]); + clang_getSpellingLocation(start, 0, &l, &c, 0); + return l; + }; + int sl = strlen(symbol); - uint l = p->getCurrentTokenLine(); + uint l = getCurrentTokenLine(); while (l>=line && p->curToken>0) { if (l==line) // already at the right line { p->curToken--; // linear search to start of the line - l = p->getCurrentTokenLine(); + l = getCurrentTokenLine(); } - else + else { p->curToken/=2; // binary search backward - l = p->getCurrentTokenLine(); + l = getCurrentTokenLine(); } } bool found=FALSE; @@ -464,7 +432,7 @@ QCString ClangParser::lookup(uint line,const char *symbol) { break; // end of token stream } - l = p->getCurrentTokenLine(); + l = getCurrentTokenLine(); clang_disposeString(tokenString); tokenString = clang_getTokenSpelling(p->tu, p->tokens[p->curToken]); ts = clang_getCString(tokenString); @@ -501,7 +469,7 @@ QCString ClangParser::lookup(uint line,const char *symbol) p->curToken++; if (p->curToken<p->numTokens) { - l = p->getCurrentTokenLine(); + l = getCurrentTokenLine(); } } //if (!found) @@ -515,78 +483,23 @@ QCString ClangParser::lookup(uint line,const char *symbol) return result; } -static QCString keywordToType(const char *keyword) -{ - static bool init=TRUE; - static QDict<void> flowKeywords(47); - static QDict<void> typeKeywords(47); - if (init) - { - flowKeywords.insert("break",(void*)0x8); - flowKeywords.insert("case",(void*)0x8); - flowKeywords.insert("catch",(void*)0x8); - flowKeywords.insert("continue",(void*)0x8); - flowKeywords.insert("default",(void*)0x8); - flowKeywords.insert("do",(void*)0x8); - flowKeywords.insert("else",(void*)0x8); - flowKeywords.insert("finally",(void*)0x8); - flowKeywords.insert("for",(void*)0x8); - flowKeywords.insert("foreach",(void*)0x8); - flowKeywords.insert("for each",(void*)0x8); - flowKeywords.insert("goto",(void*)0x8); - flowKeywords.insert("if",(void*)0x8); - flowKeywords.insert("return",(void*)0x8); - flowKeywords.insert("switch",(void*)0x8); - flowKeywords.insert("throw",(void*)0x8); - flowKeywords.insert("throws",(void*)0x8); - flowKeywords.insert("try",(void*)0x8); - flowKeywords.insert("while",(void*)0x8); - flowKeywords.insert("@try",(void*)0x8); - flowKeywords.insert("@catch",(void*)0x8); - flowKeywords.insert("@finally",(void*)0x8); - - typeKeywords.insert("bool",(void*)0x8); - typeKeywords.insert("char",(void*)0x8); - typeKeywords.insert("double",(void*)0x8); - typeKeywords.insert("float",(void*)0x8); - typeKeywords.insert("int",(void*)0x8); - typeKeywords.insert("long",(void*)0x8); - typeKeywords.insert("object",(void*)0x8); - typeKeywords.insert("short",(void*)0x8); - typeKeywords.insert("signed",(void*)0x8); - typeKeywords.insert("unsigned",(void*)0x8); - typeKeywords.insert("void",(void*)0x8); - typeKeywords.insert("wchar_t",(void*)0x8); - typeKeywords.insert("size_t",(void*)0x8); - typeKeywords.insert("boolean",(void*)0x8); - typeKeywords.insert("id",(void*)0x8); - typeKeywords.insert("SEL",(void*)0x8); - typeKeywords.insert("string",(void*)0x8); - typeKeywords.insert("nullptr",(void*)0x8); - init=FALSE; - } - if (flowKeywords[keyword]) return "keywordflow"; - if (typeKeywords[keyword]) return "keywordtype"; - return "keyword"; -} -static void writeLineNumber(CodeOutputInterface &ol,FileDef *fd,uint line) +void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,FileDef *fd,uint line) { Definition *d = fd ? fd->getSourceDefinition(line) : 0; if (d && d->isLinkable()) { - g_currentDefinition=d; - g_currentLine=line; + p->currentLine=line; MemberDef *md = fd->getSourceMember(line); if (md && md->isLinkable()) // link to member { - if (g_currentMemberDef!=md) // new member, start search for body + if (p->currentMemberDef!=md) // new member, start search for body { - g_searchForBody=TRUE; - g_insideBody=FALSE; - g_bracketCount=0; + p->searchForBody=TRUE; + p->insideBody=FALSE; + p->bracketCount=0; } - g_currentMemberDef=md; + p->currentMemberDef=md; ol.writeLineNumber(md->getReference(), md->getOutputFileBase(), md->anchor(), @@ -594,7 +507,7 @@ static void writeLineNumber(CodeOutputInterface &ol,FileDef *fd,uint line) } else // link to compound { - g_currentMemberDef=0; + p->currentMemberDef=0; ol.writeLineNumber(d->getReference(), d->getOutputFileBase(), d->anchor(), @@ -617,8 +530,8 @@ static void writeLineNumber(CodeOutputInterface &ol,FileDef *fd,uint line) //printf("writeLineNumber(%d) g_searchForBody=%d\n",line,g_searchForBody); } -static void codifyLines(CodeOutputInterface &ol,FileDef *fd,const char *text, - uint &line,uint &column,const char *fontClass=0) +void ClangTUParser::codifyLines(CodeOutputInterface &ol,FileDef *fd,const char *text, + uint &line,uint &column,const char *fontClass) { if (fontClass) ol.startFontClass(fontClass); const char *p=text,*sp=p; @@ -653,7 +566,7 @@ static void codifyLines(CodeOutputInterface &ol,FileDef *fd,const char *text, if (fontClass) ol.endFontClass(); } -static void writeMultiLineCodeLink(CodeOutputInterface &ol, +void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol, FileDef *fd,uint &line,uint &column, Definition *d, const char *text) @@ -694,7 +607,7 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, } } -void ClangParser::linkInclude(CodeOutputInterface &ol,FileDef *fd, +void ClangTUParser::linkInclude(CodeOutputInterface &ol,FileDef *fd, uint &line,uint &column,const char *text) { QCString incName = text; @@ -702,17 +615,19 @@ void ClangParser::linkInclude(CodeOutputInterface &ol,FileDef *fd, FileDef *ifd=0; if (!incName.isEmpty()) { - FileName *fn = Doxygen::inputNameDict->find(incName); + FileName *fn = Doxygen::inputNameLinkedMap->find(incName); if (fn) { - bool found=false; - FileNameIterator fni(*fn); - // for each include name - for (fni.toFirst();!found && (ifd=fni.current());++fni) + // see if this source file actually includes the file + auto it = std::find_if(fn->begin(), + fn->end(), + [&fd](const auto &ifd) + { return fd->isIncluded(ifd->absFilePath()); }); + bool found = it!=fn->end(); + if (found) { - // see if this source file actually includes the file - found = fd->isIncluded(ifd->absFilePath()); - //printf(" include file %s found=%d\n",ifd->absFilePath().data(),found); + //printf(" include file %s found=%d\n",(*it)->absFilePath().data(),found); + ifd = it->get(); } } } @@ -726,19 +641,17 @@ void ClangParser::linkInclude(CodeOutputInterface &ol,FileDef *fd, } } -void ClangParser::linkMacro(CodeOutputInterface &ol,FileDef *fd, +void ClangTUParser::linkMacro(CodeOutputInterface &ol,FileDef *fd, uint &line,uint &column,const char *text) { - MemberName *mn=Doxygen::functionNameSDict->find(text); + MemberName *mn=Doxygen::functionNameLinkedMap->find(text); if (mn) { - MemberNameIterator mni(*mn); - MemberDef *md; - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { if (md->isDefine()) { - writeMultiLineCodeLink(ol,fd,line,column,md,text); + writeMultiLineCodeLink(ol,fd,line,column,md.get(),text); return; } } @@ -747,7 +660,7 @@ void ClangParser::linkMacro(CodeOutputInterface &ol,FileDef *fd, } -void ClangParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, +void ClangTUParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, uint &line,uint &column,const char *text,int tokenIndex) { CXCursor c = p->cursors[tokenIndex]; @@ -759,7 +672,7 @@ void ClangParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, CXCursor t = clang_getSpecializedCursorTemplate(c); if (!clang_Cursor_isNull(t) && !clang_equalCursors(t,c)) { - c=t; // link to template + c=t; // link to template } CXString usr = clang_getCursorUSR(c); const char *usrStr = clang_getCString(usr); @@ -778,11 +691,11 @@ void ClangParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, //} if (d && d->isLinkable()) { - if (g_insideBody && - g_currentMemberDef && d->definitionType()==Definition::TypeMember && - (g_currentMemberDef!=d || g_currentLine<line)) // avoid self-reference + if (p->insideBody && + p->currentMemberDef && d->definitionType()==Definition::TypeMember && + (p->currentMemberDef!=d || p->currentLine<line)) // avoid self-reference { - addDocCrossReference(g_currentMemberDef,dynamic_cast<MemberDef *>(d)); + addDocCrossReference(p->currentMemberDef,dynamic_cast<MemberDef *>(d)); } writeMultiLineCodeLink(ol,fd,line,column,d,text); } @@ -793,45 +706,44 @@ void ClangParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, clang_disposeString(usr); } -static void detectFunctionBody(const char *s) +void ClangTUParser::detectFunctionBody(const char *s) { //printf("punct=%s g_searchForBody=%d g_insideBody=%d g_bracketCount=%d\n", // s,g_searchForBody,g_insideBody,g_bracketCount); - if (g_searchForBody && (qstrcmp(s,":")==0 || qstrcmp(s,"{")==0)) // start of 'body' (: is for constructor) + if (p->searchForBody && (qstrcmp(s,":")==0 || qstrcmp(s,"{")==0)) // start of 'body' (: is for constructor) { - g_searchForBody=FALSE; - g_insideBody=TRUE; + p->searchForBody=FALSE; + p->insideBody=TRUE; } - else if (g_searchForBody && qstrcmp(s,";")==0) // declaration only + else if (p->searchForBody && qstrcmp(s,";")==0) // declaration only { - g_searchForBody=FALSE; - g_insideBody=FALSE; + p->searchForBody=FALSE; + p->insideBody=FALSE; } - if (g_insideBody && qstrcmp(s,"{")==0) // increase scoping level + if (p->insideBody && qstrcmp(s,"{")==0) // increase scoping level { - g_bracketCount++; + p->bracketCount++; } - if (g_insideBody && qstrcmp(s,"}")==0) // decrease scoping level + if (p->insideBody && qstrcmp(s,"}")==0) // decrease scoping level { - g_bracketCount--; - if (g_bracketCount<=0) // got outside of function body + p->bracketCount--; + if (p->bracketCount<=0) // got outside of function body { - g_insideBody=FALSE; - g_bracketCount=0; + p->insideBody=FALSE; + p->bracketCount=0; } } } -void ClangParser::writeSources(CodeOutputInterface &ol,FileDef *fd) +void ClangTUParser::writeSources(CodeOutputInterface &ol,FileDef *fd) { // (re)set global parser state - g_currentDefinition=0; - g_currentMemberDef=0; - g_currentLine=0; - g_searchForBody=FALSE; - g_insideBody=FALSE; - g_bracketCount=0; + p->currentMemberDef=0; + p->currentLine=0; + p->searchForBody=FALSE; + p->insideBody=FALSE; + p->bracketCount=0; unsigned int line=1,column=1; QCString lineNumber,lineAnchor; @@ -843,13 +755,13 @@ void ClangParser::writeSources(CodeOutputInterface &ol,FileDef *fd) unsigned int l, c; clang_getSpellingLocation(start, 0, &l, &c, 0); if (l > line) column = 1; - while (line<l) - { - line++; + while (line<l) + { + line++; ol.endCodeLine(); ol.startCodeLine(TRUE); writeLineNumber(ol,fd,line); - } + } while (column<c) { ol.codify(" "); column++; } CXString tokenString = clang_getTokenSpelling(p->tu, p->tokens[i]); char const *s = clang_getCString(tokenString); @@ -858,7 +770,7 @@ void ClangParser::writeSources(CodeOutputInterface &ol,FileDef *fd) //printf("%d:%d %s cursorKind=%d tokenKind=%d\n",line,column,s,cursorKind,tokenKind); switch (tokenKind) { - case CXToken_Keyword: + case CXToken_Keyword: if (strcmp(s,"operator")==0) { linkIdentifier(ol,fd,line,column,s,i); @@ -870,21 +782,21 @@ void ClangParser::writeSources(CodeOutputInterface &ol,FileDef *fd) keywordToType(s)); } break; - case CXToken_Literal: + case CXToken_Literal: if (cursorKind==CXCursor_InclusionDirective) { linkInclude(ol,fd,line,column,s); } - else if (s[0]=='"' || s[0]=='\'') + else if (s[0]=='"' || s[0]=='\'') { codifyLines(ol,fd,s,line,column,"stringliteral"); } - else + else { codifyLines(ol,fd,s,line,column); } break; - case CXToken_Comment: + case CXToken_Comment: codifyLines(ol,fd,s,line,column,"comment"); break; default: // CXToken_Punctuation or CXToken_Identifier @@ -935,49 +847,79 @@ void ClangParser::writeSources(CodeOutputInterface &ol,FileDef *fd) ol.endCodeLine(); } -ClangParser::ClangParser() +//-------------------------------------------------------------------------- + +class ClangParser::Private { - p = new Private; + public: + Private() + { + std::string error; + QCString clangCompileDatabase = Config_getString(CLANG_DATABASE_PATH); + // load a clang compilation database (https://clang.llvm.org/docs/JSONCompilationDatabase.html) + db = clang::tooling::CompilationDatabase::loadFromDirectory(clangCompileDatabase.data(), error); + if (clangCompileDatabase!="0" && 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()); + } + } + + std::unique_ptr<clang::tooling::CompilationDatabase> db; +}; + +const clang::tooling::CompilationDatabase *ClangParser::database() const +{ + return p->db.get(); } -ClangParser::~ClangParser() +ClangParser::ClangParser() : p(std::make_unique<Private>()) { - delete p; } -//-------------------------------------------------------------------------- -#else // use stubbed functionality in case libclang support is disabled. +ClangParser::~ClangParser() +{ +} -void ClangParser::start(const char *,QStrList &) +std::unique_ptr<ClangTUParser> ClangParser::createTUParser(const FileDef *fd) const { + return std::make_unique<ClangTUParser>(*this,fd); } -void ClangParser::switchToFile(const char *) + +//-------------------------------------------------------------------------- +#else // use stubbed functionality in case libclang support is disabled. + +void ClangTUParser::switchToFile(FileDef *fd) { } -void ClangParser::finish() +void ClangTUParser::parse() { } -QCString ClangParser::lookup(uint,const char *) +QCString ClangTUParser::lookup(uint,const char *) { return ""; } -void ClangParser::writeSources(CodeOutputInterface &,FileDef *) +class ClangParser::Private { -} +}; -ClangParser::ClangParser() +ClangParser::ClangParser() : p(std::make_unique<Private>()) { - p = NULL; } ClangParser::~ClangParser() { } +std::unique_ptr<ClangTUParser> ClangParser::createTUParser(const FileDef *) const +{ + return nullptr; +} #endif //-------------------------------------------------------------------------- diff --git a/src/clangparser.h b/src/clangparser.h index 8bb9aba..8ee1bdb 100644 --- a/src/clangparser.h +++ b/src/clangparser.h @@ -3,39 +3,41 @@ #include <qcstring.h> #include <qstrlist.h> +#include "containers.h" +#include <memory> class CodeOutputInterface; class FileDef; +class ClangParser; +class Definition; -/** @brief Wrapper for to let libclang assisted parsing. */ -class ClangParser +namespace clang { namespace tooling { + class CompilationDatabase; +} } + +/** @brief Clang parser object for a single translation unit, which consists of a source file + * and the directly or indirectly included headers + */ +class ClangTUParser { public: - /** Returns the one and only instance of the class */ - static ClangParser *instance(); - - /** Start parsing a file. - * @param[in] fileName The name of the file to parse. - * @param[in,out] filesInTranslationUnit Other files that are - * part of the input and included by the file. - * The function will return a subset of the files, - * only including the ones that were actually found - * during parsing. + ClangTUParser(const ClangParser &parser,const FileDef *fd); + virtual ~ClangTUParser(); + + /** Parse the file given at construction time as a translation unit + * This file should already be preprocessed by doxygen preprocessor at the time of calling. */ - void start(const char *fileName,QStrList &filesInTranslationUnit); + void parse(); - /** Switches to another file within the translation unit started - * with start(). + /** Switches to another file within the translation unit started with start(). * @param[in] fileName The name of the file to switch to. */ - void switchToFile(const char *fileName); + void switchToFile(FileDef *fd); - /** Finishes parsing a translation unit. Free any resources that - * were needed for parsing. - */ - void finish(); + /** Returns the list of files for this translation unit */ + StringVector filesInSameTU() const; - /** Looks for \a symbol which should be found at \a line and + /** Looks for \a symbol which should be found at \a line. * returns a clang unique reference to the symbol. */ QCString lookup(uint line,const char *symbol); @@ -47,6 +49,13 @@ class ClangParser void writeSources(CodeOutputInterface &ol,FileDef *fd); private: + void detectFunctionBody(const char *s); + void writeLineNumber(CodeOutputInterface &ol,FileDef *fd,uint line); + void codifyLines(CodeOutputInterface &ol,FileDef *fd,const char *text, + uint &line,uint &column,const char *fontClass=0); + void writeMultiLineCodeLink(CodeOutputInterface &ol, + FileDef *fd,uint &line,uint &column, + Definition *d, const char *text); void linkIdentifier(CodeOutputInterface &ol,FileDef *fd, uint &line,uint &column, const char *text,int tokenIndex); @@ -56,9 +65,25 @@ class ClangParser void linkInclude(CodeOutputInterface &ol,FileDef *fd, uint &line,uint &column, const char *text); - void determineInputFilesInSameTu(QStrList &filesInTranslationUnit); + ClangTUParser(const ClangTUParser &) = delete; + ClangTUParser &operator=(const ClangTUParser &) = delete; + class Private; + std::unique_ptr<Private> p; +}; + +/** @brief Wrapper for to let libclang assisted parsing. */ +class ClangParser +{ + friend class ClangTUParser; + public: + /** Returns the one and only instance of the class */ + static ClangParser *instance(); + std::unique_ptr<ClangTUParser> createTUParser(const FileDef *fd) const; + + private: + const clang::tooling::CompilationDatabase *database() const; class Private; - Private *p; + std::unique_ptr<Private> p; ClangParser(); virtual ~ClangParser(); static ClangParser *s_instance; diff --git a/src/classdef.cpp b/src/classdef.cpp index 61ae528..c3cd3ee 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -15,7 +15,9 @@ * */ -#include <stdio.h> +#include <cstdio> +#include <algorithm> + #include <qfile.h> #include <qfileinfo.h> #include <qregexp.h> @@ -66,8 +68,8 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual ClassDef *resolveAlias() { return this; } virtual DefType definitionType() const { return TypeClass; } virtual QCString getOutputFileBase() const; - virtual QCString getInstanceOutputFileBase() const; - virtual QCString getSourceFileBase() const; + virtual QCString getInstanceOutputFileBase() const; + virtual QCString getSourceFileBase() const; virtual QCString getReference() const; virtual bool isReference() const; virtual bool isLocal() const; @@ -81,7 +83,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual QCString compoundTypeString() const; virtual BaseClassList *baseClasses() const; virtual BaseClassList *subClasses() const; - virtual MemberNameInfoSDict *memberNameInfoSDict() const; + virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const; virtual Protection protection() const; virtual bool isLinkableInProject() const; virtual bool isLinkable() const; @@ -104,9 +106,9 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual ConstraintClassDict *templateTypeConstraints() const; virtual bool isTemplateArgument() const; virtual Definition *findInnerCompound(const char *name) const; - virtual std::vector<ArgumentList> getTemplateParameterLists() const; + virtual ArgumentLists getTemplateParameterLists() const; virtual QCString qualifiedNameWithTemplateParameters( - const std::vector<ArgumentList> *actualParams=0,int *actualParamIndex=0) const; + const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const; virtual bool isAbstract() const; virtual bool isObjectiveC() const; virtual bool isFortran() const; @@ -149,7 +151,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0); virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0); - virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force); + virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force); virtual void insertMember(MemberDef *); virtual void insertUsedFile(FileDef *); virtual bool addExample(const char *anchor,const char *name, const char *file); @@ -201,6 +203,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual void removeMemberFromLists(MemberDef *md); virtual void setAnonymousEnumType(); virtual void countMembers(); + virtual void sortAllMembersList(); virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt, const ClassDef *inheritedFrom,const QCString &inheritId) const; @@ -319,8 +322,8 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->baseClasses(); } virtual BaseClassList *subClasses() const { return getCdAlias()->subClasses(); } - virtual MemberNameInfoSDict *memberNameInfoSDict() const - { return getCdAlias()->memberNameInfoSDict(); } + virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const + { return getCdAlias()->memberNameInfoLinkedMap(); } virtual Protection protection() const { return getCdAlias()->protection(); } virtual bool isLinkableInProject() const @@ -365,10 +368,10 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->isTemplateArgument(); } virtual Definition *findInnerCompound(const char *name) const { return getCdAlias()->findInnerCompound(name); } - virtual std::vector<ArgumentList> getTemplateParameterLists() const + virtual ArgumentLists getTemplateParameterLists() const { return getCdAlias()->getTemplateParameterLists(); } virtual QCString qualifiedNameWithTemplateParameters( - const std::vector<ArgumentList> *actualParams=0,int *actualParamIndex=0) const + const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const { return getCdAlias()->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); } virtual bool isAbstract() const { return getCdAlias()->isAbstract(); } @@ -448,37 +451,37 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef const QCString &templSpec,bool &freshInstance) const { return getCdAlias()->insertTemplateInstance(fileName,startLine,startColumn,templSpec,freshInstance); } - virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0) { } - virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) { } - virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force) {} + virtual void insertBaseClass(ClassDef *,const char *,Protection,Specifier,const char *) { } + virtual void insertSubClass(ClassDef *,Protection,Specifier,const char *) { } + virtual void setIncludeFile(FileDef *,const char *,bool,bool) {} virtual void insertMember(MemberDef *) {} virtual void insertUsedFile(FileDef *) {} - virtual bool addExample(const char *anchor,const char *name, const char *file) { return FALSE; } - virtual void mergeCategory(ClassDef *category) {} - virtual void setNamespace(NamespaceDef *nd) {} - virtual void setFileDef(FileDef *fd) {} - virtual void setSubGrouping(bool enabled) {} - virtual void setProtection(Protection p) {} - virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) {} - virtual void addInnerCompound(const Definition *d) {} - virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) {} - virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) {} - virtual void setIsStatic(bool b) {} - virtual void setCompoundType(CompoundType t) {} - virtual void setClassName(const char *name) {} - virtual void setClassSpecifier(uint64 spec) {} - virtual void setTemplateArguments(const ArgumentList &al) {} - virtual void setTemplateBaseClassNames(QDict<int> *templateNames) {} - virtual void setTemplateMaster(const ClassDef *tm) {} - virtual void setTypeConstraints(const ArgumentList &al) {} - virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) {} - virtual void makeTemplateArgument(bool b=TRUE) {} - virtual void setCategoryOf(ClassDef *cd) {} - virtual void setUsedOnly(bool b) {} - virtual void addTaggedInnerClass(ClassDef *cd) {} - virtual void setTagLessReference(ClassDef *cd) {} - virtual void setName(const char *name) {} - virtual void setMetaData(const char *md) {} + virtual bool addExample(const char *,const char *, const char *) { return FALSE; } + virtual void mergeCategory(ClassDef *) {} + virtual void setNamespace(NamespaceDef *) {} + virtual void setFileDef(FileDef *) {} + virtual void setSubGrouping(bool) {} + virtual void setProtection(Protection) {} + virtual void setGroupDefForAllMembers(GroupDef *,Grouping::GroupPri_t,const QCString &,int,bool) {} + virtual void addInnerCompound(const Definition *) {} + virtual void addUsedClass(ClassDef *,const char *,Protection) {} + virtual void addUsedByClass(ClassDef *,const char *,Protection) {} + virtual void setIsStatic(bool) {} + virtual void setCompoundType(CompoundType) {} + virtual void setClassName(const char *) {} + virtual void setClassSpecifier(uint64) {} + virtual void setTemplateArguments(const ArgumentList &) {} + virtual void setTemplateBaseClassNames(QDict<int> *) {} + virtual void setTemplateMaster(const ClassDef *) {} + virtual void setTypeConstraints(const ArgumentList &) {} + virtual void addMembersToTemplateInstance(const ClassDef *,const char *) {} + virtual void makeTemplateArgument(bool=TRUE) {} + virtual void setCategoryOf(ClassDef *) {} + virtual void setUsedOnly(bool) {} + virtual void addTaggedInnerClass(ClassDef *) {} + virtual void setTagLessReference(ClassDef *) {} + virtual void setName(const char *) {} + virtual void setMetaData(const char *) {} virtual void findSectionsInDocumentation() {} virtual void addMembersToMemberGroup() {} virtual void addListReferences() {} @@ -487,24 +490,25 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef virtual void mergeMembers() {} virtual void sortMemberLists() {} virtual void distributeMemberGroupDocumentation() {} - virtual void writeDocumentation(OutputList &ol) const {} - virtual void writeDocumentationForInnerClasses(OutputList &ol) const {} - virtual void writeMemberPages(OutputList &ol) const {} - virtual void writeMemberList(OutputList &ol) const {} - virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, - const ClassDef *inheritedFrom,const char *inheritId) const {} - virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const {} - virtual void writeSummaryLinks(OutputList &ol) const {} - virtual void reclassifyMember(MemberDef *md,MemberType t) {} - virtual void writeInlineDocumentation(OutputList &ol) const {} + virtual void writeDocumentation(OutputList &) const {} + virtual void writeDocumentationForInnerClasses(OutputList &) const {} + virtual void writeMemberPages(OutputList &) const {} + virtual void writeMemberList(OutputList &) const {} + virtual void writeDeclaration(OutputList &,const MemberDef *,bool, + const ClassDef *,const char *) const {} + virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const {} + virtual void writeSummaryLinks(OutputList &) const {} + virtual void reclassifyMember(MemberDef *,MemberType) {} + virtual void writeInlineDocumentation(OutputList &) const {} virtual void writeDeclarationLink(OutputList &ol,bool &found, const char *header,bool localNames) const { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); } - virtual void removeMemberFromLists(MemberDef *md) {} + virtual void removeMemberFromLists(MemberDef *) {} virtual void setAnonymousEnumType() {} virtual void countMembers() {} - virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt, - const ClassDef *inheritedFrom,const QCString &inheritId) const {} + virtual void sortAllMembersList() {} + virtual void addGroupedInheritedMembers(OutputList &,MemberListType, + const ClassDef *,const QCString &) const {} virtual void writeTagFile(FTextStream &) {} virtual void setVisited(bool visited) const { m_visited = visited; } @@ -516,10 +520,8 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const { return getCdAlias()->countMemberDeclarations(lt,inheritedFrom,lt2,invert,showAlways,visitedClasses); } - virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title, - const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0, - int lt2=-1,bool invert=FALSE,bool showAlways=FALSE, - QPtrDict<void> *visitedClasses=0) const {} + virtual void writeMemberDeclarations(OutputList &,MemberListType,const QCString &, + const char *,bool,const ClassDef *, int,bool,bool, QPtrDict<void> *) const {} private: mutable bool m_visited = false; @@ -580,7 +582,7 @@ class ClassDefImpl::IMPL FileDef *fileDef = 0; /*! List of all members (including inherited members) */ - MemberNameInfoSDict *allMemberNameInfoSDict = 0; + MemberNameInfoLinkedMap allMemberNameInfoLinkedMap; /*! Template arguments of this class */ ArgumentList tempArgs; @@ -703,7 +705,6 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name, exampleSDict = 0; inherits = 0; inheritedBy = 0; - allMemberNameInfoSDict = 0; incInfo=0; prot=Public; nspace=0; @@ -757,7 +758,6 @@ ClassDefImpl::IMPL::~IMPL() { delete inherits; delete inheritedBy; - delete allMemberNameInfoSDict; delete exampleSDict; delete usesImplClassDict; delete usedByImplClassDict; @@ -1195,24 +1195,9 @@ void ClassDefImpl::internalInsertMember(MemberDef *md, QCString(md->typeString())=="friend union"))) { //printf("=======> adding member %s to class %s\n",md->name().data(),name().data()); - MemberInfo *mi = new MemberInfo((MemberDef *)md, - prot,md->virtualness(),FALSE); - MemberNameInfo *mni=0; - if (m_impl->allMemberNameInfoSDict==0) - { - m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17); - m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE); - } - if ((mni=m_impl->allMemberNameInfoSDict->find(md->name()))) - { - mni->append(mi); - } - else - { - mni = new MemberNameInfo(md->name()); - mni->append(mi); - m_impl->allMemberNameInfoSDict->append(mni->memberName(),mni); - } + + MemberNameInfo *mni = m_impl->allMemberNameInfoLinkedMap.add(md->name()); + mni->push_back(std::make_unique<MemberInfo>(md,prot,md->virtualness(),FALSE)); } } @@ -1363,7 +1348,7 @@ void ClassDefImpl::setIncludeFile(FileDef *fd, //} static void searchTemplateSpecs(/*in*/ const Definition *d, - /*out*/ std::vector<ArgumentList> &result, + /*out*/ ArgumentLists &result, /*out*/ QCString &name, /*in*/ SrcLangExt lang) { @@ -1400,7 +1385,7 @@ static void searchTemplateSpecs(/*in*/ const Definition *d, static void writeTemplateSpec(OutputList &ol,const Definition *d, const QCString &type,SrcLangExt lang) { - std::vector<ArgumentList> specs; + ArgumentLists specs; QCString name; searchTemplateSpecs(d,specs,name,lang); if (!specs.empty()) // class has template scope specifiers @@ -1446,7 +1431,8 @@ void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag) const ol.writeString(" - "); ol.popGeneratorState(); ol.generateDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE,0, + TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.pushGeneratorState(); ol.disable(OutputGenerator::RTF); ol.writeString(" \n"); @@ -1477,7 +1463,8 @@ void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) const // repeat brief description if (!briefDescription().isEmpty() && repeatBrief) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } if (!briefDescription().isEmpty() && repeatBrief && !documentation().isEmpty()) @@ -1490,7 +1477,8 @@ void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) const // write documentation if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // write type constraints writeTypeConstraints(ol,this,m_impl->typeConstraints); @@ -1743,7 +1731,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.startParagraph(); //parseText(ol,theTranslator->trInherits()+" "); - QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count()); + QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits->count()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1780,7 +1768,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const } index=newIndex+matchLen; } - ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.parseText(inheritLine.right(inheritLine.length()-(uint)index)); ol.endParagraph(); } @@ -1788,7 +1776,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const if (m_impl->inheritedBy && m_impl->inheritedBy->count()>0) { ol.startParagraph(); - QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count()); + QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy->count()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1813,7 +1801,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const } index=newIndex+matchLen; } - ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.parseText(inheritLine.right(inheritLine.length()-(uint)index)); ol.endParagraph(); } @@ -1863,16 +1851,15 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const if (m_impl->incInfo) { QCString nm; - QStrList paths = Config_getList(STRIP_FROM_PATH); - if (!paths.isEmpty() && m_impl->incInfo->fileDef) + const StringVector &paths = Config_getList(STRIP_FROM_PATH); + if (!paths.empty() && m_impl->incInfo->fileDef) { QCString abs = m_impl->incInfo->fileDef->absFilePath(); - const char *s = paths.first(); QCString potential; unsigned int length = 0; - while (s) + for (const auto &s : paths) { - QFileInfo info(s); + QFileInfo info(s.c_str()); if (info.exists()) { QCString prefix = info.absFilePath().utf8(); @@ -1887,7 +1874,6 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const length = prefix.length(); potential = abs.right(abs.length() - prefix.length()); } - s = paths.next(); } } @@ -2058,27 +2044,6 @@ void ClassDefImpl::writeIncludeFiles(OutputList &ol) const } } -#if 0 -void ClassDefImpl::writeAllMembersLink(OutputList &ol) -{ - // write link to list of all members (HTML only) - if (m_impl->allMemberNameInfoSDict && - !Config_getBool(OPTIMIZE_OUTPUT_FOR_C) - ) - { - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - ol.startParagraph(); - ol.startTextLink(getMemberListFileName(),0); - ol.parseText(theTranslator->trListOfAllMembers()); - ol.endTextLink(); - ol.endParagraph(); - ol.enableAll(); - ol.popGeneratorState(); - } -} -#endif - void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline) const { // write user defined member groups @@ -2196,7 +2161,7 @@ void ClassDefImpl::writeSummaryLinks(OutputList &ol) const first=FALSE; } else if (lde->kind()==LayoutDocEntry::ClassAllMembersLink && - m_impl->allMemberNameInfoSDict && + !m_impl->allMemberNameInfoLinkedMap.empty() && !Config_getBool(OPTIMIZE_OUTPUT_FOR_C) ) { @@ -2235,7 +2200,7 @@ void ClassDefImpl::writeTagFile(FTextStream &tagFile) { if (!isLinkableInProject()) return; tagFile << " <compound kind=\""; - if (isFortran() && (compoundTypeString() == "type")) + if (isFortran() && (compoundTypeString() == "type")) tagFile << "struct"; else tagFile << compoundTypeString(); @@ -2610,7 +2575,8 @@ void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *h if (!briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startMemberDescription(anchor()); @@ -2924,39 +2890,32 @@ void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current ol.writeString(" <div class=\"navtab\">\n"); ol.writeString(" <table>\n"); - if (m_impl->allMemberNameInfoSDict) + for (auto &mni : m_impl->allMemberNameInfoLinkedMap) { - MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); - MemberNameInfo *mni; - for (;(mni=mnili.current());++mnili) + for (auto &mi : *mni) { - MemberNameInfoIterator mnii(*mni); - MemberInfo *mi; - for (mnii.toFirst();(mi=mnii.current());++mnii) + const MemberDef *md=mi->memberDef(); + if (md->getClassDef()==this && md->isLinkable() && !md->isEnumValue()) { - MemberDef *md=mi->memberDef; - if (md->getClassDef()==this && md->isLinkable() && !md->isEnumValue()) + ol.writeString(" <tr><td class=\"navtab\">"); + if (md->isLinkableInProject()) { - ol.writeString(" <tr><td class=\"navtab\">"); - if (md->isLinkableInProject()) + if (md==currentMd) // selected item => highlight { - if (md==currentMd) // selected item => highlight - { - ol.writeString("<a class=\"qindexHL\" "); - } - else - { - ol.writeString("<a class=\"qindex\" "); - } - ol.writeString("href=\""); - if (createSubDirs) ol.writeString("../../"); - ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); - ol.writeString("\">"); - ol.writeString(convertToHtml(md->name())); - ol.writeString("</a>"); + ol.writeString("<a class=\"qindexHL\" "); + } + else + { + ol.writeString("<a class=\"qindex\" "); } - ol.writeString("</td></tr>\n"); + ol.writeString("href=\""); + if (createSubDirs) ol.writeString("../../"); + ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); + ol.writeString("\">"); + ol.writeString(convertToHtml(md->name())); + ol.writeString("</a>"); } + ol.writeString("</td></tr>\n"); } } } @@ -2998,7 +2957,7 @@ void ClassDefImpl::writeMemberList(OutputList &ol) const //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - if (m_impl->allMemberNameInfoSDict==0 || cOpt) return; + if (m_impl->allMemberNameInfoLinkedMap.empty() || cOpt) return; // only for HTML ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -3052,18 +3011,13 @@ void ClassDefImpl::writeMemberList(OutputList &ol) const bool first = true; // to prevent empty table int idx=0; - //MemberNameInfo *mni=m_impl->allMemberNameInfoList->first(); - MemberNameInfoSDict::Iterator mnii(*m_impl->allMemberNameInfoSDict); - MemberNameInfo *mni; - for (mnii.toFirst();(mni=mnii.current());++mnii) + for (auto &mni : m_impl->allMemberNameInfoLinkedMap) { - MemberNameInfoIterator it(*mni); - MemberInfo *mi; - for (;(mi=it.current());++it) + for (auto &mi : *mni) { - MemberDef *md=mi->memberDef; + const MemberDef *md=mi->memberDef(); const ClassDef *cd=md->getClassDef(); - Protection prot = mi->prot; + Protection prot = mi->prot(); Specifier virt=md->virtualness(); //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n", @@ -3075,7 +3029,7 @@ void ClassDefImpl::writeMemberList(OutputList &ol) const if (cd->isLinkable() && md->isLinkable()) // create a link to the documentation { - QCString name=mi->ambiguityResolutionScope+md->name(); + QCString name=mi->ambiguityResolutionScope()+md->name(); //ol.writeListItem(); if (first) { @@ -3301,7 +3255,9 @@ bool ClassDefImpl::hasExamples() const { bool result=FALSE; if (m_impl->exampleSDict) - result = m_impl->exampleSDict->count()>0; + { + result = m_impl->exampleSDict->count()>0; + } return result; } @@ -3354,7 +3310,7 @@ void ClassDefImpl::addTypeConstraints() addTypeConstraint(typeConstraint,a.type); p=i+1; } - typeConstraint = a.typeConstraint.right(a.typeConstraint.length()-p).stripWhiteSpace(); + typeConstraint = a.typeConstraint.right(a.typeConstraint.length()-(uint)p).stripWhiteSpace(); addTypeConstraint(typeConstraint,a.type); } } @@ -3606,7 +3562,7 @@ void ClassDefImpl::mergeMembers() //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); SrcLangExt lang = getLanguage(); QCString sep=getLanguageSpecificSeparator(lang,TRUE); - int sepLen = sep.length(); + uint sepLen = sep.length(); m_impl->membersMerged=TRUE; //printf(" mergeMembers for %s\n",name().data()); @@ -3624,220 +3580,201 @@ void ClassDefImpl::mergeMembers() // merge the members in the base class of this inheritance branch first bClass->mergeMembers(); - MemberNameInfoSDict *srcMnd = bClass->memberNameInfoSDict(); - MemberNameInfoSDict *dstMnd = m_impl->allMemberNameInfoSDict; + const MemberNameInfoLinkedMap &srcMnd = bClass->memberNameInfoLinkedMap(); + MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; - if (srcMnd) + for (auto &srcMni : srcMnd) { - MemberNameInfoSDict::Iterator srcMnili(*srcMnd); - MemberNameInfo *srcMni; - for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) + //printf(" Base member name %s\n",srcMni->memberName()); + MemberNameInfo *dstMni; + if ((dstMni=dstMnd.find(srcMni->memberName()))) + // a member with that name is already in the class. + // the member may hide or reimplement the one in the sub class + // or there may be another path to the base class that is already + // visited via another branch in the class hierarchy. { - //printf(" Base member name %s\n",srcMni->memberName()); - MemberNameInfo *dstMni; - if (dstMnd!=0 && (dstMni=dstMnd->find(srcMni->memberName()))) - // a member with that name is already in the class. - // the member may hide or reimplement the one in the sub class - // or there may be another path to the base class that is already - // visited via another branch in the class hierarchy. + for (auto &srcMi : *srcMni) { - MemberNameInfoIterator srcMnii(*srcMni); - MemberInfo *srcMi; - for ( ; (srcMi=srcMnii.current()) ; ++srcMnii ) + MemberDef *srcMd = srcMi->memberDef(); + bool found=FALSE; + bool ambiguous=FALSE; + bool hidden=FALSE; + const ClassDef *srcCd = srcMd->getClassDef(); + for (auto &dstMi : *dstMni) { - MemberDef *srcMd = srcMi->memberDef; - bool found=FALSE; - bool ambiguous=FALSE; - bool hidden=FALSE; - MemberNameInfoIterator dstMnii(*dstMni); - MemberInfo *dstMi; - const ClassDef *srcCd = srcMd->getClassDef(); - for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii ) + MemberDef *dstMd = dstMi->memberDef(); + if (srcMd!=dstMd) // different members { - MemberDef *dstMd = dstMi->memberDef; - if (srcMd!=dstMd) // different members + const ClassDef *dstCd = dstMd->getClassDef(); + //printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data()); + if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) + // member is in the same or a base class { - const ClassDef *dstCd = dstMd->getClassDef(); - //printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data()); - if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) - // member is in the same or a base class - { - ArgumentList &srcAl = srcMd->argumentList(); - ArgumentList &dstAl = dstMd->argumentList(); - found=matchArguments2( - srcMd->getOuterScope(),srcMd->getFileDef(),srcAl, - dstMd->getOuterScope(),dstMd->getFileDef(),dstAl, - TRUE - ); - //printf(" Yes, matching (%s<->%s): %d\n", - // argListToString(srcMd->argumentList()).data(), - // argListToString(dstMd->argumentList()).data(), - // found); - hidden = hidden || !found; - } - else // member is in a non base class => multiple inheritance - // using the same base class. - { - //printf("$$ Existing member %s %s add scope %s\n", - // dstMi->ambiguityResolutionScope.data(), - // dstMd->name().data(), - // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); - - QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen); - if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) - dstMi->ambiguityResolutionScope.prepend(scope); - ambiguous=TRUE; - } + ArgumentList &srcAl = srcMd->argumentList(); + ArgumentList &dstAl = dstMd->argumentList(); + found=matchArguments2( + srcMd->getOuterScope(),srcMd->getFileDef(),&srcAl, + dstMd->getOuterScope(),dstMd->getFileDef(),&dstAl, + TRUE + ); + //printf(" Yes, matching (%s<->%s): %d\n", + // argListToString(srcMd->argumentList()).data(), + // argListToString(dstMd->argumentList()).data(), + // found); + hidden = hidden || !found; } - else // same members + else // member is in a non base class => multiple inheritance + // using the same base class. { - // do not add if base class is virtual or - // if scope paths are equal or - // if base class is an interface (and thus implicitly virtual). - //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt); - if ((srcMi->virt!=Normal && dstMi->virt!=Normal) || - bClass->name()+sep+srcMi->scopePath == dstMi->scopePath || - dstMd->getClassDef()->compoundType()==Interface - ) - { - found=TRUE; - } - else // member can be reached via multiple paths in the - // inheritance tree + //printf("$$ Existing member %s %s add scope %s\n", + // dstMi->ambiguityResolutionScope.data(), + // dstMd->name().data(), + // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); + + QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen); + if (scope!=dstMi->ambiguityResolutionScope().left(scope.length())) { - //printf("$$ Existing member %s %s add scope %s\n", - // dstMi->ambiguityResolutionScope.data(), - // dstMd->name().data(), - // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); - - QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen); - if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) - { - dstMi->ambiguityResolutionScope.prepend(scope); - } - ambiguous=TRUE; + dstMi->setAmbiguityResolutionScope(scope+dstMi->ambiguityResolutionScope()); } + ambiguous=TRUE; } } - //printf("member %s::%s hidden %d ambiguous %d srcMi->ambigClass=%p\n", - // srcCd->name().data(),srcMd->name().data(),hidden,ambiguous,srcMi->ambigClass); - - // TODO: fix the case where a member is hidden by inheritance - // of a member with the same name but with another prototype, - // while there is more than one path to the member in the - // base class due to multiple inheritance. In this case - // it seems that the member is not reachable by prefixing a - // scope name either (according to my compiler). Currently, - // this case is shown anyway. - if (!found && srcMd->protection()!=Private && !srcMd->isFriend()) + else // same members { - Protection prot=srcMd->protection(); - if (bcd->prot==Protected && prot==Public) prot=bcd->prot; - else if (bcd->prot==Private) prot=bcd->prot; - - if (inlineInheritedMembers) + // do not add if base class is virtual or + // if scope paths are equal or + // if base class is an interface (and thus implicitly virtual). + //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt); + if ((srcMi->virt()!=Normal && dstMi->virt()!=Normal) || + bClass->name()+sep+srcMi->scopePath() == dstMi->scopePath() || + dstMd->getClassDef()->compoundType()==Interface + ) { - if (!isStandardFunc(srcMd)) + found=TRUE; + } + else // member can be reached via multiple paths in the + // inheritance tree + { + //printf("$$ Existing member %s %s add scope %s\n", + // dstMi->ambiguityResolutionScope.data(), + // dstMd->name().data(), + // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); + + QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen); + if (scope!=dstMi->ambiguityResolutionScope().left(scope.length())) { - //printf(" insertMember '%s'\n",srcMd->name().data()); - internalInsertMember(srcMd,prot,FALSE); + dstMi->setAmbiguityResolutionScope(dstMi->ambiguityResolutionScope()+scope); } + ambiguous=TRUE; } + } + if (found) break; + } + //printf("member %s::%s hidden %d ambiguous %d srcMi->ambigClass=%p\n", + // srcCd->name().data(),srcMd->name().data(),hidden,ambiguous,srcMi->ambigClass); + + // TODO: fix the case where a member is hidden by inheritance + // of a member with the same name but with another prototype, + // while there is more than one path to the member in the + // base class due to multiple inheritance. In this case + // it seems that the member is not reachable by prefixing a + // scope name either (according to my compiler). Currently, + // this case is shown anyway. + if (!found && srcMd->protection()!=Private && !srcMd->isFriend()) + { + Protection prot=srcMd->protection(); + if (bcd->prot==Protected && prot==Public) prot=bcd->prot; + else if (bcd->prot==Private) prot=bcd->prot; - Specifier virt=srcMi->virt; - if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; - - MemberInfo *newMi = new MemberInfo(srcMd,prot,virt,TRUE); - newMi->scopePath=bClass->name()+sep+srcMi->scopePath; - if (ambiguous) + if (inlineInheritedMembers) + { + if (!isStandardFunc(srcMd)) { - //printf("$$ New member %s %s add scope %s::\n", - // srcMi->ambiguityResolutionScope.data(), - // srcMd->name().data(), - // bClass->name().data()); + //printf(" insertMember '%s'\n",srcMd->name().data()); + internalInsertMember(srcMd,prot,FALSE); + } + } - QCString scope=bClass->name()+sep; - if (scope!=srcMi->ambiguityResolutionScope.left(scope.length())) - { - newMi->ambiguityResolutionScope= - scope+srcMi->ambiguityResolutionScope.copy(); - } + Specifier virt=srcMi->virt(); + if (virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + + std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(srcMd,prot,virt,TRUE); + newMi->setScopePath(bClass->name()+sep+srcMi->scopePath()); + if (ambiguous) + { + //printf("$$ New member %s %s add scope %s::\n", + // srcMi->ambiguityResolutionScope.data(), + // srcMd->name().data(), + // bClass->name().data()); + + QCString scope=bClass->name()+sep; + if (scope!=srcMi->ambiguityResolutionScope().left(scope.length())) + { + newMi->setAmbiguityResolutionScope(scope+srcMi->ambiguityResolutionScope()); } - if (hidden) + } + if (hidden) + { + if (srcMi->ambigClass()==0) { - if (srcMi->ambigClass==0) - { - newMi->ambigClass=bClass; - newMi->ambiguityResolutionScope=bClass->name()+sep; - } - else - { - newMi->ambigClass=srcMi->ambigClass; - newMi->ambiguityResolutionScope=srcMi->ambigClass->name()+sep; - } + newMi->setAmbigClass(bClass); + newMi->setAmbiguityResolutionScope(bClass->name()+sep); + } + else + { + newMi->setAmbigClass(srcMi->ambigClass()); + newMi->setAmbiguityResolutionScope(srcMi->ambigClass()->name()+sep); } - dstMni->append(newMi); } + dstMni->push_back(std::move(newMi)); } } - else // base class has a member that is not in the sub class => copy + } + else // base class has a member that is not in the sub class => copy + { + // create a deep copy of the list (only the MemberInfo's will be + // copied, not the actual MemberDef's) + MemberNameInfo *newMni = dstMnd.add(srcMni->memberName()); + + // copy the member(s) from the base to the sub class + for (auto &mi : *srcMni) { - // create a deep copy of the list (only the MemberInfo's will be - // copied, not the actual MemberDef's) - MemberNameInfo *newMni = 0; - newMni = new MemberNameInfo(srcMni->memberName()); - - // copy the member(s) from the base to the sub class - MemberNameInfoIterator mnii(*srcMni); - MemberInfo *mi; - for (;(mi=mnii.current());++mnii) + if (!mi->memberDef()->isFriend()) // don't inherit friends { - if (!mi->memberDef->isFriend()) // don't inherit friends + Protection prot = mi->prot(); + if (bcd->prot==Protected) { - Protection prot = mi->prot; - if (bcd->prot==Protected) - { - if (prot==Public) prot=Protected; - } - else if (bcd->prot==Private) - { - prot=Private; - } - //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", - // name().data(),mi->memberDef->name().data(),mi->prot, - // bcd->prot,prot); + if (prot==Public) prot=Protected; + } + else if (bcd->prot==Private) + { + prot=Private; + } + //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", + // name().data(),mi->memberDef->name().data(),mi->prot, + // bcd->prot,prot); - if (prot!=Private || extractPrivate) - { - Specifier virt=mi->virt; - if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + if (prot!=Private || extractPrivate) + { + Specifier virt=mi->virt(); + if (virt==Normal && bcd->virt!=Normal) virt=bcd->virt; - if (inlineInheritedMembers) + if (inlineInheritedMembers) + { + if (!isStandardFunc(mi->memberDef())) { - if (!isStandardFunc(mi->memberDef)) - { - //printf(" insertMember '%s'\n",mi->memberDef->name().data()); - internalInsertMember(mi->memberDef,prot,FALSE); - } + //printf(" insertMember '%s'\n",mi->memberDef->name().data()); + internalInsertMember(mi->memberDef(),prot,FALSE); } - //printf("Adding!\n"); - MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE); - newMi->scopePath=bClass->name()+sep+mi->scopePath; - newMi->ambigClass=mi->ambigClass; - newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy(); - newMni->append(newMi); } + //printf("Adding!\n"); + std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(mi->memberDef(),prot,virt,TRUE); + newMi->setScopePath(bClass->name()+sep+mi->scopePath()); + newMi->setAmbigClass(mi->ambigClass()); + newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope()); + newMni->push_back(std::move(newMi)); } } - - if (dstMnd==0) - { - m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17); - m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE); - dstMnd = m_impl->allMemberNameInfoSDict; - } - // add it to the dictionary - dstMnd->append(newMni->memberName(),newMni); } } } @@ -3888,99 +3825,68 @@ void ClassDefImpl::mergeCategory(ClassDef *category) } } } - } // make methods private for categories defined in the .m file //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate); - MemberNameInfoSDict *srcMnd = category->memberNameInfoSDict(); - MemberNameInfoSDict *dstMnd = m_impl->allMemberNameInfoSDict; + const MemberNameInfoLinkedMap &srcMnd = category->memberNameInfoLinkedMap(); + MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; - if (srcMnd && dstMnd) + for (auto &srcMni : srcMnd) { - MemberNameInfoSDict::Iterator srcMnili(*srcMnd); - MemberNameInfo *srcMni; - for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) + MemberNameInfo *dstMni=dstMnd.find(srcMni->memberName()); + if (dstMni) // method is already defined in the class { - MemberNameInfo *dstMni=dstMnd->find(srcMni->memberName()); - if (dstMni) // method is already defined in the class + //printf("Existing member %s\n",srcMni->memberName()); + auto &dstMi = dstMni->front(); + auto &srcMi = srcMni->front(); + if (srcMi && dstMi) { - //printf("Existing member %s\n",srcMni->memberName()); - MemberInfo *dstMi = dstMni->getFirst(); - MemberInfo *srcMi = srcMni->getFirst(); - //if (dstMi) - //{ - // Protection prot = dstMi->prot; - // if (makePrivate || isExtension) - // { - // prot = Private; - // removeMemberFromLists(dstMi->memberDef); - // internalInsertMember(dstMi->memberDef,prot,FALSE); - // } - //} - if (srcMi && dstMi) - { - combineDeclarationAndDefinition(srcMi->memberDef,dstMi->memberDef); - dstMi->memberDef->setCategory(category); - dstMi->memberDef->setCategoryRelation(srcMi->memberDef); - srcMi->memberDef->setCategoryRelation(dstMi->memberDef); - } + combineDeclarationAndDefinition(srcMi->memberDef(),dstMi->memberDef()); + dstMi->memberDef()->setCategory(category); + dstMi->memberDef()->setCategoryRelation(srcMi->memberDef()); + srcMi->memberDef()->setCategoryRelation(dstMi->memberDef()); } - else // new method name + } + else // new method name + { + //printf("New member %s\n",srcMni->memberName()); + // create a deep copy of the list + MemberNameInfo *newMni = dstMnd.add(srcMni->memberName()); + + // copy the member(s) from the category to this class + for (auto &mi : *srcMni) { - //printf("New member %s\n",srcMni->memberName()); - // create a deep copy of the list - MemberNameInfo *newMni = 0; - newMni = new MemberNameInfo(srcMni->memberName()); - - // copy the member(s) from the category to this class - MemberNameInfoIterator mnii(*srcMni); - MemberInfo *mi; - for (;(mi=mnii.current());++mnii) + //printf("Adding '%s'\n",mi->memberDef->name().data()); + Protection prot = mi->prot(); + //if (makePrivate) prot = Private; + std::unique_ptr<MemberDef> newMd { mi->memberDef()->deepCopy() }; + if (newMd) { - //printf("Adding '%s'\n",mi->memberDef->name().data()); - Protection prot = mi->prot; - //if (makePrivate) prot = Private; - MemberDef *newMd = mi->memberDef->deepCopy(); - if (newMd) - { - //printf("Copying member %s\n",mi->memberDef->name().data()); - newMd->moveTo(this); + //printf("Copying member %s\n",mi->memberDef->name().data()); + newMd->moveTo(this); - MemberInfo *newMi=new MemberInfo(newMd,prot,mi->virt,mi->inherited); - newMi->scopePath=mi->scopePath; - newMi->ambigClass=mi->ambigClass; - newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope; - newMni->append(newMi); + std::unique_ptr<MemberInfo> newMi=std::make_unique<MemberInfo>(newMd.get(),prot,mi->virt(),mi->inherited()); + newMi->setScopePath(mi->scopePath()); + newMi->setAmbigClass(mi->ambigClass()); + newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope()); + newMni->push_back(std::move(newMi)); - // also add the newly created member to the global members list + // also add the newly created member to the global members list - MemberName *mn; - QCString name = newMd->name(); - if ((mn=Doxygen::memberNameSDict->find(name))) - { - mn->append(newMd); - } - else - { - mn = new MemberName(newMd->name()); - mn->append(newMd); - Doxygen::memberNameSDict->append(name,mn); - } - - newMd->setCategory(category); - newMd->setCategoryRelation(mi->memberDef); - mi->memberDef->setCategoryRelation(newMd); - if (makePrivate || isExtension) - { - newMd->makeImplementationDetail(); - } - internalInsertMember(newMd,prot,FALSE); - } - } + QCString name = newMd->name(); + MemberName *mn = Doxygen::memberNameLinkedMap->add(name); - // add it to the dictionary - dstMnd->append(newMni->memberName(),newMni); + newMd->setCategory(category); + newMd->setCategoryRelation(mi->memberDef()); + mi->memberDef()->setCategoryRelation(newMd.get()); + if (makePrivate || isExtension) + { + newMd->makeImplementationDetail(); + } + internalInsertMember(newMd.get(),prot,FALSE); + mn->push_back(std::move(newMd)); + } } } } @@ -4149,16 +4055,11 @@ void ClassDefImpl::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pr { gd->addClass(this); //printf("ClassDefImpl::setGroupDefForAllMembers(%s)\n",gd->name().data()); - if (m_impl->allMemberNameInfoSDict==0) return; - MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); - MemberNameInfo *mni; - for (;(mni=mnili.current());++mnili) + for (auto &mni : m_impl->allMemberNameInfoLinkedMap) { - MemberNameInfoIterator mnii(*mni); - MemberInfo *mi; - for (mnii.toFirst();(mi=mnii.current());++mnii) + for (auto &mi : *mni) { - MemberDef *md=mi->memberDef; + MemberDef *md=mi->memberDef(); md->setGroupDef(gd,pri,fileName,startLine,hasDocs); gd->insertMember(md,TRUE); ClassDef *innerClass = md->getClassDefOfAnonymousType(); @@ -4264,20 +4165,14 @@ QDict<int> *ClassDefImpl::getTemplateBaseClassNames() const void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) { //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec); - if (cd->memberNameInfoSDict()==0) return; - MemberNameInfoSDict::Iterator mnili(*cd->memberNameInfoSDict()); - MemberNameInfo *mni; - for (;(mni=mnili.current());++mnili) - { - MemberNameInfoIterator mnii(*mni); - MemberInfo *mi; - for (mnii.toFirst();(mi=mnii.current());++mnii) - { - ArgumentList actualArguments; - stringToArgumentList(getLanguage(),templSpec,actualArguments); - MemberDef *md = mi->memberDef; - MemberDef *imd = md->createTemplateInstanceMember( - cd->templateArguments(),actualArguments); + for (auto &mni : cd->memberNameInfoLinkedMap()) + { + for (auto &mi : *mni) + { + auto actualArguments_p = stringToArgumentList(getLanguage(),templSpec); + MemberDef *md = mi->memberDef(); + std::unique_ptr<MemberDef> imd { md->createTemplateInstanceMember( + cd->templateArguments(),actualArguments_p) }; //printf("%s->setMemberClass(%p)\n",imd->name().data(),this); imd->setMemberClass(this); imd->setTemplateMaster(md); @@ -4286,19 +4181,14 @@ void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const char *t imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); imd->setMemberSpecifiers(md->getMemberSpecifiers()); imd->setMemberGroupId(md->getMemberGroupId()); - insertMember(imd); + insertMember(imd.get()); //printf("Adding member=%s %s%s to class %s templSpec %s\n", // imd->typeString(),imd->name().data(),imd->argsString(), // imd->getClassDef()->name().data(),templSpec); // insert imd in the list of all members //printf("Adding member=%s class=%s\n",imd->name().data(),name().data()); - MemberName *mn = Doxygen::memberNameSDict->find(imd->name()); - if (mn==0) - { - mn = new MemberName(imd->name()); - Doxygen::memberNameSDict->append(imd->name(),mn); - } - mn->append(imd); + MemberName *mn = Doxygen::memberNameLinkedMap->add(imd->name()); + mn->push_back(std::move(imd)); } } } @@ -4327,9 +4217,9 @@ bool ClassDefImpl::isReference() const } } -std::vector<ArgumentList> ClassDefImpl::getTemplateParameterLists() const +ArgumentLists ClassDefImpl::getTemplateParameterLists() const { - std::vector<ArgumentList> result; + ArgumentLists result; Definition *d=getOuterScope(); while (d && d->definitionType()==Definition::TypeClass) { @@ -4344,7 +4234,7 @@ std::vector<ArgumentList> ClassDefImpl::getTemplateParameterLists() const } QCString ClassDefImpl::qualifiedNameWithTemplateParameters( - const std::vector<ArgumentList> *actualParams,int *actualParamIndex) const + const ArgumentLists *actualParams,uint *actualParamIndex) const { //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); static bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES); @@ -4380,7 +4270,7 @@ QCString ClassDefImpl::qualifiedNameWithTemplateParameters( scName+=clName; if (!templateArguments().empty()) { - if (actualParams && *actualParamIndex<(int)actualParams->size()) + if (actualParams && *actualParamIndex<actualParams->size()) { const ArgumentList &al = actualParams->at(*actualParamIndex); if (!isSpecialization) @@ -4411,7 +4301,7 @@ QCString ClassDefImpl::className() const { return m_impl->className; } -}; +} void ClassDefImpl::setClassName(const char *name) { @@ -4424,7 +4314,7 @@ void ClassDefImpl::addListReferences() if (!isLinkableInProject()) return; //printf("ClassDef(%s)::addListReferences()\n",name().data()); { - const std::vector<ListItemInfo> &xrefItems = xrefListItems(); + const RefItemVector &xrefItems = xrefListItems(); addRefItem(xrefItems, qualifiedName(), lang==SrcLangExt_Fortran ? theTranslator->trType(TRUE,TRUE) @@ -4458,26 +4348,21 @@ void ClassDefImpl::addListReferences() MemberDef *ClassDefImpl::getMemberByName(const QCString &name) const { MemberDef *xmd = 0; - if (m_impl->allMemberNameInfoSDict) - { - MemberNameInfo *mni = m_impl->allMemberNameInfoSDict->find(name); - if (mni) - { - const int maxInheritanceDepth = 100000; - int mdist=maxInheritanceDepth; - MemberNameInfoIterator mnii(*mni); - MemberInfo *mi; - for (mnii.toFirst();(mi=mnii.current());++mnii) + MemberNameInfo *mni = m_impl->allMemberNameInfoLinkedMap.find(name); + if (mni) + { + const int maxInheritanceDepth = 100000; + int mdist=maxInheritanceDepth; + for (auto &mi : *mni) + { + const ClassDef *mcd=mi->memberDef()->getClassDef(); + int m=minClassDistance(this,mcd); + //printf("found member in %s linkable=%d m=%d\n", + // mcd->name().data(),mcd->isLinkable(),m); + if (m<mdist && mcd->isLinkable()) { - const ClassDef *mcd=mi->memberDef->getClassDef(); - int m=minClassDistance(this,mcd); - //printf("found member in %s linkable=%d m=%d\n", - // mcd->name().data(),mcd->isLinkable(),m); - if (m<mdist && mcd->isLinkable()) - { - mdist=m; - xmd=mi->memberDef; - } + mdist=m; + xmd=mi->memberDef(); } } } @@ -4531,7 +4416,7 @@ void ClassDefImpl::addMemberToList(MemberListType lt,MemberDef *md,bool isBrief) ml->append(md); // for members in the declaration lists we set the section, needed for member grouping - if ((ml->listType()&MemberListType_detailedLists)==0) md->setSectionList(ml); + if ((ml->listType()&MemberListType_detailedLists)==0) md->setSectionList(this,ml); } void ClassDefImpl::sortMemberLists() @@ -4836,7 +4721,7 @@ void ClassDefImpl::writeMemberDeclarations(OutputList &ol,MemberListType lt,cons MemberList * ml = getMemberList(lt); MemberList * ml2 = getMemberList((MemberListType)lt2); if (getLanguage()==SrcLangExt_VHDL) // use specific declarations function - { + { static const ClassDef *cdef; if (cdef!=this) { // only one inline link @@ -4946,9 +4831,19 @@ BaseClassList *ClassDefImpl::subClasses() const return m_impl->inheritedBy; } -MemberNameInfoSDict *ClassDefImpl::memberNameInfoSDict() const +const MemberNameInfoLinkedMap &ClassDefImpl::memberNameInfoLinkedMap() const { - return m_impl->allMemberNameInfoSDict; + return m_impl->allMemberNameInfoLinkedMap; +} + +void ClassDefImpl::sortAllMembersList() +{ + std::sort(m_impl->allMemberNameInfoLinkedMap.begin(), + m_impl->allMemberNameInfoLinkedMap.end(), + [](const auto &m1,const auto &m2) + { + return qstricmp(m1->memberName(),m2->memberName())<0; + }); } Protection ClassDefImpl::protection() const diff --git a/src/classdef.h b/src/classdef.h index 3158c50..d413794 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -24,7 +24,9 @@ #include <qdict.h> #include <qptrdict.h> +#include "containers.h" #include "definition.h" +#include "arguments.h" struct Argument; class MemberDef; @@ -39,7 +41,7 @@ class BaseClassList; class NamespaceDef; class MemberDef; class ExampleSDict; -class MemberNameInfoSDict; +class MemberNameInfoLinkedMap; class UsesClassDict; class ConstraintClassDict; class MemberGroupSDict; @@ -49,7 +51,6 @@ class GroupDef; class StringDict; struct IncludeInfo; class ClassDefImpl; -class ArgumentList; class FTextStream; /** A abstract class representing of a compound symbol. @@ -61,8 +62,8 @@ class ClassDef : virtual public Definition { public: /** The various compound types */ - enum CompoundType { Class, //=Entry::CLASS_SEC, - Struct, //=Entry::STRUCT_SEC, + enum CompoundType { Class, //=Entry::CLASS_SEC, + Struct, //=Entry::STRUCT_SEC, Union, //=Entry::UNION_SEC, Interface, //=Entry::INTERFACE_SEC, Protocol, //=Entry::PROTOCOL_SEC, @@ -76,7 +77,7 @@ class ClassDef : virtual public Definition //----------------------------------------------------------------------------------- - // --- getters + // --- getters //----------------------------------------------------------------------------------- /** Used for RTTI, this is a class */ @@ -134,7 +135,7 @@ class ClassDef : virtual public Definition /** Returns a dictionary of all members. This includes any inherited * members. Members are sorted alphabetically. */ - virtual MemberNameInfoSDict *memberNameInfoSDict() const = 0; + virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const = 0; /** Return the protection level (Public,Protected,Private) in which * this compound was found. @@ -229,10 +230,10 @@ class ClassDef : virtual public Definition * will return a list with one ArgumentList containing one argument * with type="class" and name="T". */ - virtual std::vector<ArgumentList> getTemplateParameterLists() const = 0; + virtual ArgumentLists getTemplateParameterLists() const = 0; virtual QCString qualifiedNameWithTemplateParameters( - const std::vector<ArgumentList> *actualParams=0,int *actualParamIndex=0) const = 0; + const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const = 0; /** Returns TRUE if there is at least one pure virtual member in this * class. @@ -371,6 +372,7 @@ class ClassDef : virtual public Definition virtual void removeMemberFromLists(MemberDef *md) = 0; virtual void setAnonymousEnumType() = 0; virtual void countMembers() = 0; + virtual void sortAllMembersList() = 0; //----------------------------------------------------------------------------------- // --- write output ---- @@ -426,24 +428,21 @@ ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd); //------------------------------------------------------------------------ -/** Class that contains information about a usage relation. +/** Class that contains information about a usage relation. */ struct UsesClassDef { - UsesClassDef(ClassDef *cd) : classDef(cd) - { - accessors = new QDict<void>(17); - containment = TRUE; + UsesClassDef(ClassDef *cd) : classDef(cd) + { } ~UsesClassDef() { - delete accessors; } void addAccessor(const char *s) { - if (accessors->find(s)==0) + if (accessors.find(s)==accessors.end()) { - accessors->insert(s,(void *)666); + accessors.insert(s); } } /** Class definition that this relation uses. */ @@ -452,55 +451,54 @@ struct UsesClassDef /** Dictionary of member variable names that form the edge labels of the * usage relation. */ - QDict<void> *accessors; + StringSet accessors; /** Template arguments used for the base class */ QCString templSpecifiers; - bool containment; + bool containment = true; }; -/** Dictionary of usage relations. +/** Dictionary of usage relations. */ class UsesClassDict : public QDict<UsesClassDef> { public: - UsesClassDict(int size) : QDict<UsesClassDef>(size) {} + UsesClassDict(uint size) : QDict<UsesClassDef>(size) {} ~UsesClassDict() {} }; -/** Iterator class to iterate over a dictionary of usage relations. +/** Iterator class to iterate over a dictionary of usage relations. */ class UsesClassDictIterator : public QDictIterator<UsesClassDef> { public: - UsesClassDictIterator(const QDict<UsesClassDef> &d) + UsesClassDictIterator(const QDict<UsesClassDef> &d) : QDictIterator<UsesClassDef>(d) {} ~UsesClassDictIterator() {} }; //------------------------------------------------------------------------ -/** Class that contains information about an inheritance relation. +/** Class that contains information about an inheritance relation. */ struct BaseClassDef { - BaseClassDef(ClassDef *cd,const char *n,Protection p, - Specifier v,const char *t) : + BaseClassDef(ClassDef *cd,const char *n,Protection p, Specifier v,const char *t) : classDef(cd), usedName(n), prot(p), virt(v), templSpecifiers(t) {} /** Class definition that this relation inherits from. */ ClassDef *classDef; - /** name used in the inheritance list + /** name used in the inheritance list * (may be a typedef name instead of the class name) */ - QCString usedName; - - /** Protection level of the inheritance relation: - * Public, Protected, or Private + QCString usedName; + + /** Protection level of the inheritance relation: + * Public, Protected, or Private */ - Protection prot; + Protection prot; /** Virtualness of the inheritance relation: * Normal, or Virtual @@ -512,7 +510,7 @@ struct BaseClassDef }; /** List of base classes. - * + * * The classes are alphabetically sorted on name if inSort() is used. */ class BaseClassList : public QList<BaseClassDef> @@ -535,7 +533,7 @@ class BaseClassList : public QList<BaseClassDef> class BaseClassListIterator : public QListIterator<BaseClassDef> { public: - BaseClassListIterator(const BaseClassList &bcl) : + BaseClassListIterator(const BaseClassList &bcl) : QListIterator<BaseClassDef>(bcl) {} }; @@ -548,17 +546,15 @@ struct ConstraintClassDef { ConstraintClassDef(ClassDef *cd) : classDef(cd) { - accessors = new QDict<void>(17); } ~ConstraintClassDef() { - delete accessors; } void addAccessor(const char *s) { - if (accessors->find(s)==0) + if (accessors.find(s)==accessors.end()) { - accessors->insert(s,(void *)666); + accessors.insert(s); } } /** Class definition that this relation uses. */ @@ -567,7 +563,7 @@ struct ConstraintClassDef /** Dictionary of member types names that form the edge labels of the * constraint relation. */ - QDict<void> *accessors; + StringSet accessors; }; /** Dictionary of constraint relations. @@ -575,7 +571,7 @@ struct ConstraintClassDef class ConstraintClassDict : public QDict<ConstraintClassDef> { public: - ConstraintClassDict(int size) : QDict<ConstraintClassDef>(size) {} + ConstraintClassDict(uint size) : QDict<ConstraintClassDef>(size) {} ~ConstraintClassDict() {} }; diff --git a/src/classlist.cpp b/src/classlist.cpp index f06f744..ee4ffa4 100644 --- a/src/classlist.cpp +++ b/src/classlist.cpp @@ -166,9 +166,8 @@ void GenericsSDict::insert(const QCString &key,ClassDef *cd) { int i=key.find('<'); if (i==-1) return; - ArgumentList argList; - stringToArgumentList(SrcLangExt_CSharp, key.mid(i),argList); - int c = argList.size(); + auto argList = stringToArgumentList(SrcLangExt_CSharp, key.mid(i)); + int c = (int)argList->size(); if (c==0) return; GenericsCollection *collection = m_dict.find(key.left(i)); if (collection==0) // new name @@ -199,9 +198,8 @@ ClassDef *GenericsSDict::find(const QCString &key) GenericsCollection *collection = m_dict.find(key.left(i)); if (collection) { - ArgumentList argList; - stringToArgumentList(SrcLangExt_CSharp,key.mid(i),argList); - int c = argList.size(); + auto argList = stringToArgumentList(SrcLangExt_CSharp,key.mid(i)); + int c = (int)argList->size(); return collection->find(c); } } diff --git a/src/classlist.h b/src/classlist.h index 11c8305..6e4281f 100644 --- a/src/classlist.h +++ b/src/classlist.h @@ -48,7 +48,7 @@ class ClassListIterator : public QListIterator<ClassDef> class ClassDict : public QDict<ClassDef> { public: - ClassDict(int size) : QDict<ClassDef>(size) {} + ClassDict(uint size) : QDict<ClassDef>(size) {} ~ClassDict() {} }; @@ -56,7 +56,7 @@ class ClassDict : public QDict<ClassDef> class ClassSDict : public SDict<ClassDef> { public: - ClassSDict(int size=17) : SDict<ClassDef>(size) {} + ClassSDict(uint size=17) : SDict<ClassDef>(size) {} ~ClassSDict() {} void writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter=0, const char *header=0,bool localNames=FALSE) const; diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index e62aa4f..372ba5b 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -149,6 +149,10 @@ CommandMap cmdMap[] = { "---", CMD_MDASH }, { "_setscope", CMD_SETSCOPE }, { "emoji", CMD_EMOJI }, + { "rtfinclude", CMD_RTFINCLUDE }, + { "docbookinclude",CMD_DOCBOOKINCLUDE }, + { "maninclude", CMD_MANINCLUDE }, + { "xmlinclude", CMD_XMLINCLUDE }, { 0, 0 }, }; diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 246be9d..a86c20a 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -138,7 +138,11 @@ enum CommandType CMD_SNIPPETDOC = 108, CMD_SNIPWITHLINES= 109, CMD_EMOJI = 110, - CMD_EQUAL = 111 + CMD_EQUAL = 111, + CMD_RTFINCLUDE = 112, + CMD_DOCBOOKINCLUDE= 113, + CMD_MANINCLUDE = 114, + CMD_XMLINCLUDE = 115 }; enum HtmlTagType @@ -18,12 +18,19 @@ %option prefix="codeYY" %option reentrant %option extra-type="struct codeYY_state *" +%top{ +#include <stdint.h> +} %{ /* * includes */ + +#include <memory> +#include <algorithm> + #include <stdio.h> #include <assert.h> #include <ctype.h> @@ -57,6 +64,8 @@ #define SCOPEBLOCK (int *)8 #define INNERBLOCK (int *)12 +#define USE_STATE2STRING 0 + /* ----------------------------------------------------------------- * statics */ @@ -134,7 +143,7 @@ class VariableContext void addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name); ClassDef *findVariable(const QCString &name); - int count() const { return m_scopes.count(); } + uint count() const { return m_scopes.count(); } private: Scope m_globalScope; @@ -221,7 +230,7 @@ struct codeYY_state QCString parmName; const char * inputString = 0; //!< the code fragment as text - int inputPosition = 0; //!< read offset during parsing + yy_size_t inputPosition = 0; //!< read offset during parsing int inputLines = 0; //!< number of line in the code fragment int yyLineNr = 0; //!< current line number int yyColNr = 0; //!< current column number @@ -303,10 +312,12 @@ struct codeYY_state static bool isCastKeyword(const QCString &s); //------------------------------------------------------------------- +#if USE_STATE2STRING +static const char *stateToString(yyscan_t yyscanner,int state); +#endif static void saveObjCContext(yyscan_t yyscanner); static void restoreObjCContext(yyscan_t yyscanner); -static const char *stateToString(yyscan_t yyscanner,int state); static void addUsingDirective(yyscan_t yyscanner,const char *name); static void pushScope(yyscan_t yyscanner,const char *s); static void popScope(yyscan_t yyscanner); @@ -356,7 +367,7 @@ static QCString escapeObject(yyscan_t yyscanner,const char *s); static QCString escapeWord(yyscan_t yyscanner,const char *s); static QCString escapeComment(yyscan_t yyscanner,const char *s); static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const QCString &kw); -static int yyread(yyscan_t yyscanner,char *buf,int max_size); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); /* ----------------------------------------------------------------- @@ -385,7 +396,7 @@ CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast") CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'")) ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++" ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=" -LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!" +LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"|"<=>" BITOP "&"|"|"|"^"|"<<"|">>"|"~" OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" @@ -560,7 +571,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" // absPath = QDir::cleanDirPath(yyextra->sourceFileDef->getPath()+"/"+absPath); //} - FileDef *fd=findFileDef(Doxygen::inputNameDict,yytext,ambig); + const FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,yytext,ambig); //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd); if (fd && fd->isLinkable()) { @@ -570,17 +581,16 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" QCString name = QDir::cleanDirPath(yytext).utf8(); if (!name.isEmpty() && yyextra->sourceFileDef) { - FileName *fn = Doxygen::inputNameDict->find(name); + FileName *fn = Doxygen::inputNameLinkedMap->find(name); if (fn) { - FileNameIterator fni(*fn); - // for each include name - for (fni.toFirst();!found && (fd=fni.current());++fni) - { - // see if this source file actually includes the file - found = yyextra->sourceFileDef->isIncluded(fd->absFilePath()); - //printf(" include file %s found=%d\n",fd->absFilePath().data(),found); - } + // see if this source file actually includes the file + auto it = std::find_if(fn->begin(), + fn->end(), + [&sfd=yyextra->sourceFileDef] + (const auto &lfd) + { return sfd->isIncluded(lfd->absFilePath()); }); + found = it!=fn->end(); } } } @@ -598,7 +608,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" { yyextra->code->codify(yytext); } - char c=yyinput(yyscanner); + char c=(char)yyinput(yyscanner); QCString text; text+=c; yyextra->code->codify(text); @@ -1080,6 +1090,9 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" yyextra->parmType = yyextra->name; BEGIN(FuncCall); } +<Body>"\\)"|"\\(" { + yyextra->code->codify(yytext); + } <Body>[\\|\)\+\-\/\%\~\!] { yyextra->code->codify(yytext); yyextra->name.resize(0);yyextra->type.resize(0); @@ -1192,10 +1205,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); yyextra->name+=yytext; } -<Body>"("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() but not "if (p) ..." +<Body>"("{B}*("*"{B}*)+{SCOPENAME}+{B}*")"/{B}* { // (*p)->func() but not "if (p) ..." yyextra->code->codify(yytext); - int s=0;while (s<(int)yyleng && !isId(yytext[s])) s++; - int e=(int)yyleng-1;while (e>=0 && !isId(yytext[e])) e--; + uint s=0;while (s<(uint)yyleng && !isId(yytext[s])) s++; + uint e=(uint)yyleng-1;while (e>1 && !isId(yytext[e])) e--; QCString varname = ((QCString)yytext).mid(s,e-s+1); addType(yyscanner); yyextra->name=varname; @@ -1215,7 +1228,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} { QCString text=yytext; - int i=text.find('R'); + uint i=(uint)text.find('R'); yyextra->code->codify(text.left(i+1)); startFontClass(yyscanner,"stringliteral"); yyextra->code->codify(yytext+i+1); @@ -1764,7 +1777,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" DBG_CTX((stderr,"yyextra->name=%s\n",yyextra->name.data())); if (index!=-1) { - QCString scope = yyextra->name.left(index); + QCString scope = yyextra->name.left((uint)index); if (!yyextra->classScope.isEmpty()) scope.prepend(yyextra->classScope+"::"); const ClassDef *cd=getResolvedClass(Doxygen::globalScope,yyextra->sourceFileDef,scope); if (cd) @@ -1889,10 +1902,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); BEGIN( MemberCall2 ); } -<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") { +<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}+{B}*")"{B}*)/("."|"->") { yyextra->code->codify(yytext); - int s=0;while (!isId(yytext[s])) s++; - int e=(int)yyleng-1;while (!isId(yytext[e])) e--; + uint s=0;while (!isId(yytext[s])) s++; + uint e=(uint)yyleng-1;while (e>1 && !isId(yytext[e])) e--; yyextra->name=((QCString)yytext).mid(s,e-s+1); BEGIN( MemberCall2 ); } @@ -2104,8 +2117,8 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <*>"/*[tag:"[^\]\n]*"]*/"{B}* { // special pattern /*[tag:filename]*/ to force linking to a tag file yyextra->forceTagReference=yytext; - int s=yyextra->forceTagReference.find(':'); - int e=yyextra->forceTagReference.findRev(']'); + uint s=(uint)yyextra->forceTagReference.find(':'); + uint e=(uint)yyextra->forceTagReference.findRev(']'); yyextra->forceTagReference = yyextra->forceTagReference.mid(s+1,e-s-1); } <*>\n{B}*"/*"[!*]/[^/*] { @@ -2749,24 +2762,22 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) } // look for a global member - if ((mn=Doxygen::functionNameSDict->find(name))) + if ((mn=Doxygen::functionNameLinkedMap->find(name))) { //printf("global var '%s'\n",name.data()); - if (mn->count()==1) // global defined only once + if (mn->size()==1) // global defined only once { - MemberDef *md=mn->getFirst(); + const std::unique_ptr<MemberDef> &md=mn->front(); if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) { yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); - return md; + return md.get(); } return 0; } - else if (mn->count()>1) // global defined more than once + else if (mn->size()>1) // global defined more than once { - MemberNameIterator it(*mn); - MemberDef *md; - for (;(md=it.current());++it) + for (const auto &md : *mn) { //printf("mn=%p md=%p md->getBodyDef()=%p yyextra->sourceFileDef=%p\n", // mn,md, @@ -2781,7 +2792,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) { yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); //printf("returning member %s in source file %s\n",md->name().data(),yyextra->sourceFileDef->name().data()); - return md; + return md.get(); } } return 0; @@ -3225,7 +3236,7 @@ static void generateMemberLink(yyscan_t yyscanner, if (vcd && vcd->isLinkable()) { //printf("Found class %s for variable '%s'\n",yyextra->classScope.data(),varName.data()); - MemberName *vmn=Doxygen::memberNameSDict->find(varName); + MemberName *vmn=Doxygen::memberNameLinkedMap->find(varName); if (vmn==0) { int vi; @@ -3234,16 +3245,13 @@ static void generateMemberLink(yyscan_t yyscanner, { ClassDef *jcd = getClass(vn.left(vi)); vn=vn.right(vn.length()-vi-2); - vmn=Doxygen::memberNameSDict->find(vn); + vmn=Doxygen::memberNameLinkedMap->find(vn); //printf("Trying name '%s' scope=%s\n",vn.data(),scope.data()); if (vmn) { - MemberNameIterator vmni(*vmn); - const MemberDef *vmd; - for (;(vmd=vmni.current());++vmni) + for (const auto &vmd : *vmn) { - if (/*(vmd->isVariable() || vmd->isFunction()) && */ - vmd->getClassDef()==jcd) + if (vmd->getClassDef()==jcd) { //printf("Found variable type=%s\n",vmd->typeString()); const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); @@ -3259,12 +3267,9 @@ static void generateMemberLink(yyscan_t yyscanner, if (vmn) { //printf("There is a variable with name '%s'\n",varName); - MemberNameIterator vmni(*vmn); - const MemberDef *vmd; - for (;(vmd=vmni.current());++vmni) + for (const auto &vmd : *vmn) { - if (/*(vmd->isVariable() || vmd->isFunction()) && */ - vmd->getClassDef()==vcd) + if (vmd->getClassDef()==vcd) { //printf("Found variable type=%s\n",vmd->typeString()); const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); @@ -3667,14 +3672,14 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) if (QCString(ictx->method->typeString())=="id") { // see if the method name is unique, if so we link to it - MemberName *mn=Doxygen::memberNameSDict->find(ctx->methodName); + MemberName *mn=Doxygen::memberNameLinkedMap->find(ctx->methodName); //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n", // mn==0?-1:(int)mn->count(), // ictx->method->name().data(), // ctx->methodName.data()); - if (mn && mn->count()==1) // member name unique + if (mn && mn->size()==1) // member name unique { - ctx->method = mn->getFirst(); + ctx->method = mn->front().get(); } } else @@ -3723,7 +3728,7 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) } else // illegal marker { - ASSERT(!"invalid escape sequence"); + ASSERT("invalid escape sequence"==0); } } } @@ -3797,12 +3802,12 @@ static bool isCastKeyword(const QCString &s) return kw=="const_cast" || kw=="static_cast" || kw=="dynamic_cast" || kw=="reinterpret_cast"; } -static int yyread(yyscan_t yyscanner,char *buf,int max_size) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - int inputPosition = yyextra->inputPosition; - const char *s = yyextra->inputString + yyextra->inputPosition; - int c=0; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; while( c < max_size && *s ) { *buf++ = *s++; @@ -4004,4 +4009,6 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const return; } +#if USE_STATE2STRING #include "code.l.h" +#endif diff --git a/src/commentcnv.l b/src/commentcnv.l index f3367a4..a7d74ef 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -18,6 +18,9 @@ %option prefix="commentcnvYY" %option reentrant %option extra-type="struct commentcnvYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -45,6 +48,8 @@ #define ADDCHAR(c) yyextra->outBuf->addChar(c) #define ADDARRAY(a,s) yyextra->outBuf->addArray(a,s) + +#define USE_STATE2STRING 0 struct CondCtx { @@ -66,7 +71,7 @@ struct commentcnvYY_state { BufStr * inBuf = 0; BufStr * outBuf = 0; - int inBufPos = 0; + yy_size_t inBufPos = 0; int col = 0; int blockHeadCol = 0; bool mlBrief = FALSE; @@ -99,7 +104,9 @@ struct commentcnvYY_state bool isFixedForm = FALSE; // For Fortran }; +#if USE_STATE2STRING static const char *stateToString(int state); +#endif static inline int computeIndent(const char *s); static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len); @@ -108,7 +115,7 @@ static void startCondSection(yyscan_t yyscanner,const char *sectId); static void endCondSection(yyscan_t yyscanner); static void handleCondSectionId(yyscan_t yyscanner,const char *expression); static void replaceAliases(yyscan_t yyscanner,const char *s); -static int yyread(yyscan_t yyscanner,char *buf,int max_size); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); static void replaceComment(yyscan_t yyscanner,int offset); @@ -284,7 +291,7 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z copyToOutput(yyscanner,yytext,(int)yyleng); } <Scan>"/*"[*!]? { /* start of a C comment */ - if ((yyextra->lang==SrcLangExt_Python) || (yyextra->lang==SrcLangExt_Tcl)) + if (yyextra->lang==SrcLangExt_Python) { REJECT; } @@ -349,6 +356,17 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z yyextra->blockName=&yytext[1]; BEGIN(VerbatimCode); } +<CComment,ReadLine>^[ \t]*("```"[`]*|"~~~"[~]*) { /* start of markdown code block */ + if (!Config_getBool(MARKDOWN_SUPPORT)) + { + REJECT; + } + copyToOutput(yyscanner,yytext,(int)yyleng); + yyextra->lastCommentContext = YY_START; + yyextra->javaBlock=0; + yyextra->blockName=QCString(yytext).stripWhiteSpace().left(3); + BEGIN(VerbatimCode); + } <CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */ copyToOutput(yyscanner,yytext,(int)yyleng); yyextra->lastCommentContext = YY_START; @@ -427,6 +445,13 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z } } } +<VerbatimCode>("```"[`]*|"~~~"[~]*) { /* end of markdown code block */ + copyToOutput(yyscanner,yytext,(int)yyleng); + if (yytext[0]==yyextra->blockName[0]) + { + BEGIN(yyextra->lastCommentContext); + } + } <VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */ copyToOutput(yyscanner,yytext,(int)yyleng); if (&yytext[4]==yyextra->blockName) @@ -457,13 +482,13 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z } } } -<Verbatim,VerbatimCode>[^@\/\\\n{}]* { /* any character not a backslash or new line or } */ +<Verbatim,VerbatimCode>[^`~@\/\\\n{}]* { /* any character not a backslash or new line or } */ copyToOutput(yyscanner,yytext,(int)yyleng); } <Verbatim,VerbatimCode>\n { /* new line in verbatim block */ copyToOutput(yyscanner,yytext,(int)yyleng); } -<Verbatim>^[ \t]*"///" { +<Verbatim>^[ \t]*"//"[/!] { if (yyextra->blockName=="dot" || yyextra->blockName=="msc" || yyextra->blockName=="uml" || yyextra->blockName.at(0)=='f') { // see bug 487871, strip /// from dot images and formulas. @@ -526,7 +551,7 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z copyToOutput(yyscanner,yytext,(int)yyleng); } -<CComment>[^ <\\!@*\n{\"\/]* { /* anything that is not a '*' or command */ +<CComment>[^ `~<\\!@*\n{\"\/]* { /* anything that is not a '*' or command */ copyToOutput(yyscanner,yytext,(int)yyleng); } <CComment>"*"+[^*/\\@\n{\"]* { /* stars without slashes */ @@ -546,7 +571,7 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z } } <CComment>\n { /* new line in comment */ - copyToOutput(yyscanner,yytext,(int)yyleng); + copyToOutput(yyscanner,yytext,(int)yyleng); /* in case of Fortran always end of comment */ if (yyextra->lang==SrcLangExt_Fortran) { @@ -554,16 +579,18 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z } } <CComment>"/"+"*" { /* nested C comment */ - if ((yyextra->lang==SrcLangExt_Python) || (yyextra->lang==SrcLangExt_Tcl)) + if (yyextra->lang==SrcLangExt_Python || + yyextra->lang==SrcLangExt_Markdown) { REJECT; } yyextra->nestingCount++; yyextra->commentStack.push(new CommentCtx(yyextra->lineNr)); - copyToOutput(yyscanner,yytext,(int)yyleng); + copyToOutput(yyscanner,yytext,(int)yyleng); } <CComment>"*"+"/" { /* end of C comment */ - if ((yyextra->lang==SrcLangExt_Python) || (yyextra->lang==SrcLangExt_Tcl)) + if (yyextra->lang==SrcLangExt_Python || + yyextra->lang==SrcLangExt_Markdown) { REJECT; } @@ -843,6 +870,9 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z copyToOutput(yyscanner,yytext,(int)yyleng); } +<*>. { + copyToOutput(yyscanner,yytext,(int)yyleng); + } %% static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len) @@ -1011,11 +1041,11 @@ static void replaceAliases(yyscan_t yyscanner,const char *s) } -static int yyread(yyscan_t yyscanner,char *buf,int max_size) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - int bytesInBuf = yyextra->inBuf->curPos()-yyextra->inBufPos; - int bytesToCopy = QMIN(max_size,bytesInBuf); + yy_size_t bytesInBuf = yyextra->inBuf->curPos()-yyextra->inBufPos; + yy_size_t bytesToCopy = QMIN(max_size,bytesInBuf); memcpy(buf,yyextra->inBuf->data()+yyextra->inBufPos,bytesToCopy); yyextra->inBufPos+=bytesToCopy; return bytesToCopy; @@ -1039,7 +1069,7 @@ static void replaceComment(yyscan_t yyscanner,int offset) else { copyToOutput(yyscanner," */",3); - int i;for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); + for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); yyextra->inSpecialComment=FALSE; BEGIN(Scan); } @@ -1175,4 +1205,6 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) //---------------------------------------------------------------------------- +#if USE_STATE2STRING #include "commentcnv.l.h" +#endif diff --git a/src/commentscan.h b/src/commentscan.h index f471890..a111352 100644 --- a/src/commentscan.h +++ b/src/commentscan.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,74 +16,80 @@ #ifndef COMMENTSCAN_H #define COMMENTSCAN_H +#include <memory> #include "types.h" class Entry; class OutlineParserInterface; /** @file - * @brief Interface for the comment block parser */ + * @brief Interface for the comment block scanner */ -/** 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. - * The comment block parse may invoke - * ParserInterface::parsePrototype() in order to parse - * the argument of a @@fn command. - * @param[in] curEntry The Entry to which the comment block belongs. - * Any information (like documentation) that is found in - * the comment block will be stored in this entry. - * @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,out] lineNr The line number at which the comment block was found. - * When the function returns it will be set to the last line parsed. - * @param[in] isBrief TRUE iff this comment block represents a brief description. - * @param[in] isJavadocStyle TRUE iff this comment block is in "Javadoc" style. - * This means that it starts as a brief description until the end of - * the sentences is found and then proceeds as a detailed description. - * @param[in] isInbody TRUE iff this comment block is located in the body of - * a function. - * @param[in,out] prot The protection level in which this comment block was - * found. Commands in the comment block may override this. - * @param[in,out] position The character position within \a comment where the - * comment block starts. Typically used in case the comment block - * contains multiple structural commands. - * @param[out] newEntryNeeded Boolean that is TRUE if the comment block parser - * finds that a the comment block finishes the entry and a new one - * needs to be started. - * @returns TRUE if the comment requires further processing. The - * parameter \a newEntryNeeded will typically be true in this case and - * \a position will indicate the offset inside the \a comment string - * where to proceed parsing. FALSE indicates no further processing is - * needed. - */ -bool parseCommentBlock(OutlineParserInterface *parser, - Entry *curEntry, - const QCString &comment, - const QCString &fileName, - int &lineNr, - bool isBrief, - bool isJavadocStyle, - bool isInbody, - Protection &prot, - int &position, - bool &newEntryNeeded - ); +class CommentScanner +{ + public: + CommentScanner(); + ~CommentScanner(); + /** Invokes the comment block parser with the request to parse a + * single comment block. + * @param[in] parser The language parse that invoked this function. + * The comment block parse may invoke + * ParserInterface::parsePrototype() in order to parse + * the argument of a @@fn command. + * @param[in] curEntry The Entry to which the comment block belongs. + * Any information (like documentation) that is found in + * the comment block will be stored in this entry. + * @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,out] lineNr The line number at which the comment block was found. + * When the function returns it will be set to the last line parsed. + * @param[in] isBrief TRUE iff this comment block represents a brief description. + * @param[in] isJavadocStyle TRUE iff this comment block is in "Javadoc" style. + * This means that it starts as a brief description until the end of + * the sentences is found and then proceeds as a detailed description. + * @param[in] isInbody TRUE iff this comment block is located in the body of + * a function. + * @param[in,out] prot The protection level in which this comment block was + * found. Commands in the comment block may override this. + * @param[in,out] position The character position within \a comment where the + * comment block starts. Typically used in case the comment block + * contains multiple structural commands. + * @param[out] newEntryNeeded Boolean that is TRUE if the comment block parser + * finds that a the comment block finishes the entry and a new one + * needs to be started. + * @param[in] markdownEnabled Indicates if markdown specific processing should be done. + * @returns TRUE if the comment requires further processing. The + * parameter \a newEntryNeeded will typically be true in this case and + * \a position will indicate the offset inside the \a comment string + * where to proceed parsing. FALSE indicates no further processing is + * needed. + */ + bool parseCommentBlock(OutlineParserInterface *parser, + Entry *curEntry, + const QCString &comment, + const QCString &fileName, + int &lineNr, + bool isBrief, + bool isJavadocStyle, + bool isInbody, + Protection &prot, + int &position, + bool &newEntryNeeded, + bool markdownEnabled + ); + void initGroupInfo(Entry *entry); + void enterFile(const char *fileName,int lineNr); + void leaveFile(const char *fileName,int lineNr); + void enterCompound(const char *fileName,int line,const char *name); + void leaveCompound(const char *fileName,int line,const char *name); + void open(Entry *e,const char *fileName,int line,bool implicit=false); + void close(Entry *e,const char *fileName,int line,bool foundInline,bool implicit=false); + private: + struct Private; + std::unique_ptr<Private> p; +}; #endif diff --git a/src/commentscan.l b/src/commentscan.l index d7cf3c8..5a71b14 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -1,10 +1,10 @@ /***************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -15,342 +15,298 @@ %option never-interactive %option prefix="commentscanYY" +%option reentrant +%option extra-type="struct commentscanYY_state *" +%top{ +#include <stdint.h> +} %{ /* - * includes + * includes */ + +#include <map> +#include <stack> +#include <string> +#include <mutex> + #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <ctype.h> -#include <qarray.h> -#include <qstack.h> -#include <qregexp.h> -#include <qfile.h> +#include <qcstring.h> #include <qcstringlist.h> -#include "scanner.h" -#include "entry.h" + +#include "cite.h" +#include "commentscan.h" +#include "condparser.h" +#include "config.h" +#include "debug.h" +#include "docgroup.h" #include "doxygen.h" +#include "entry.h" +#include "formula.h" +#include "language.h" #include "message.h" -#include "config.h" +#include "parserintf.h" +#include "reflist.h" +#include "section.h" #include "util.h" -#include "index.h" -#include "defargs.h" -#include "language.h" -#include "outputlist.h" -#include "membergroup.h" #include "reflist.h" -#include "debug.h" -#include "parserintf.h" -#include "cite.h" -#include "markdown.h" -#include "condparser.h" -#include "formula.h" -#define YY_NO_INPUT 1 -#define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 // forward declarations -static bool handleBrief(const QCString &, const QCStringList &); -static bool handleFn(const QCString &, const QCStringList &); -static bool handleDef(const QCString &, const QCStringList &); -static bool handleOverload(const QCString &, const QCStringList &); -static bool handleEnum(const QCString &, const QCStringList &); -static bool handleDefGroup(const QCString &, const QCStringList &); -static bool handleAddToGroup(const QCString &, const QCStringList &); -static bool handleWeakGroup(const QCString &, const QCStringList &); -static bool handleNamespace(const QCString &, const QCStringList &); -static bool handlePackage(const QCString &, const QCStringList &); -static bool handleClass(const QCString &, const QCStringList &); -static bool handleHeaderFile(const QCString &, const QCStringList &); -static bool handleProtocol(const QCString &, const QCStringList &); -static bool handleCategory(const QCString &, const QCStringList &); -static bool handleUnion(const QCString &, const QCStringList &); -static bool handleStruct(const QCString &, const QCStringList &); -static bool handleInterface(const QCString &, const QCStringList &); -static bool handleIdlException(const QCString &, const QCStringList &); -static bool handlePage(const QCString &, const QCStringList &); -static bool handleMainpage(const QCString &, const QCStringList &); -static bool handleFile(const QCString &, const QCStringList &); -static bool handleDir(const QCString &, const QCStringList &); -static bool handleExample(const QCString &, const QCStringList &); -static bool handleDetails(const QCString &, const QCStringList &); -static bool handleNoop(const QCString &, const QCStringList &); -static bool handleName(const QCString &, const QCStringList &); -static bool handleTodo(const QCString &, const QCStringList &); -static bool handleTest(const QCString &, const QCStringList &); -static bool handleBug(const QCString &, const QCStringList &); -static bool handleSubpage(const QCString &s, const QCStringList &); -static bool handleDeprecated(const QCString &, const QCStringList &); -static bool handleXRefItem(const QCString &, const QCStringList &); -static bool handleRelated(const QCString &, const QCStringList &); -static bool handleRelatedAlso(const QCString &, const QCStringList &); -static bool handleMemberOf(const QCString &, const QCStringList &); -static bool handleRefItem(const QCString &, const QCStringList &); -static bool handleSection(const QCString &, const QCStringList &); -static bool handleAnchor(const QCString &, const QCStringList &); -static bool handleCite(const QCString &, const QCStringList &); -static bool handleFormatBlock(const QCString &, const QCStringList &); -static bool handleAddIndex(const QCString &, const QCStringList &); -static bool handleIf(const QCString &, const QCStringList &); -static bool handleIfNot(const QCString &, const QCStringList &); -static bool handleElseIf(const QCString &, const QCStringList &); -static bool handleElse(const QCString &, const QCStringList &); -static bool handleEndIf(const QCString &, const QCStringList &); -static bool handleIngroup(const QCString &, const QCStringList &); -static bool handleNoSubGrouping(const QCString &, const QCStringList &); -static bool handleShowInitializer(const QCString &, const QCStringList &); -static bool handleHideInitializer(const QCString &, const QCStringList &); -static bool handleCallgraph(const QCString &, const QCStringList &); -static bool handleHideCallgraph(const QCString &, const QCStringList &); -static bool handleCallergraph(const QCString &, const QCStringList &); -static bool handleHideCallergraph(const QCString &, const QCStringList &); -static bool handleReferencedByRelation(const QCString &, const QCStringList &); -static bool handleHideReferencedByRelation(const QCString &, const QCStringList &); -static bool handleReferencesRelation(const QCString &, const QCStringList &); -static bool handleHideReferencesRelation(const QCString &, const QCStringList &); -static bool handleInternal(const QCString &, const QCStringList &); -static bool handleLineBr(const QCString &, const QCStringList &); -static bool handleStatic(const QCString &, const QCStringList &); -static bool handlePure(const QCString &, const QCStringList &); -static bool handlePrivate(const QCString &, const QCStringList &); -static bool handlePrivateSection(const QCString &, const QCStringList &); -static bool handleProtected(const QCString &, const QCStringList &); -static bool handleProtectedSection(const QCString &, const QCStringList &); -static bool handlePublic(const QCString &s, const QCStringList &); -static bool handlePublicSection(const QCString &s, const QCStringList &); -static bool handleToc(const QCString &s, const QCStringList &); -static bool handleInherit(const QCString &, const QCStringList &); -static bool handleExtends(const QCString &, const QCStringList &); -static bool handleCopyDoc(const QCString &, const QCStringList &); -static bool handleCopyBrief(const QCString &, const QCStringList &); -static bool handleCopyDetails(const QCString &, const QCStringList &); -static bool handleParBlock(const QCString &, const QCStringList &); -static bool handleEndParBlock(const QCString &, const QCStringList &); -static bool handleParam(const QCString &, const QCStringList &); -static bool handleRetval(const QCString &, const QCStringList &); - +static bool handleBrief(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleFn(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDef(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleOverload(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleEnum(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDefGroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleAddToGroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleWeakGroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleNamespace(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePackage(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleClass(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHeaderFile(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleProtocol(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCategory(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleUnion(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleStruct(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleInterface(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIdlException(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePage(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleMainpage(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleFile(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDir(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleExample(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleDetails(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleNoop(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleName(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleTodo(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleTest(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleBug(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleSubpage(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handleDeprecated(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleXRefItem(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRelated(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRelatedAlso(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleMemberOf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRefItem(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleSection(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleAnchor(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCite(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleFormatBlock(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleAddIndex(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIfNot(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleElseIf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleElse(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleEndIf(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleIngroup(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleNoSubGrouping(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleShowInitializer(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideInitializer(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCallgraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideCallgraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCallergraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideCallergraph(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleReferencedByRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideReferencedByRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleReferencesRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleHideReferencesRelation(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleInternal(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleStatic(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePure(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePrivate(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePrivateSection(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleProtected(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleProtectedSection(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handlePublic(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handlePublicSection(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handleToc(yyscan_t yyscanner,const QCString &s, const QCStringList &); +static bool handleInherit(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleExtends(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCopyBrief(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleParBlock(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleEndParBlock(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleParam(yyscan_t yyscanner,const QCString &, const QCStringList &); +static bool handleRetval(yyscan_t yyscanner,const QCString &, const QCStringList &); + +#if USE_STATE2STRING static const char *stateToString(int state); +#endif -typedef bool (*DocCmdFunc)(const QCString &name, const QCStringList &optList); +typedef bool (*DocCmdFunc)(yyscan_t yyscanner,const QCString &name, const QCStringList &optList); + +enum class CommandSpacing +{ + Invisible, // command sets some property but does not appear in the output. + Inline, // command appears inline in the output which can be a brief description. + Block // command starts a new paragraphs / ends a brief description. +}; struct DocCmdMap { - const char *cmdName; + DocCmdMap(DocCmdFunc h,CommandSpacing s) : handler(h), spacing(s) {} DocCmdFunc handler; - bool endsBrief; + CommandSpacing spacing; }; // map of command to handler function -static DocCmdMap docCmdMap[] = -{ - // command name handler function ends brief description - { "brief", &handleBrief, FALSE }, - { "short", &handleBrief, FALSE }, - { "fn", &handleFn, TRUE }, - { "var", &handleFn, TRUE }, - { "typedef", &handleFn, TRUE }, - { "property", &handleFn, TRUE }, - { "def", &handleDef, TRUE }, - { "overload", &handleOverload, FALSE }, - { "enum", &handleEnum, TRUE }, - { "defgroup", &handleDefGroup, TRUE }, - { "addtogroup", &handleAddToGroup, TRUE }, - { "weakgroup", &handleWeakGroup, TRUE }, - { "namespace", &handleNamespace, TRUE }, - { "package", &handlePackage, TRUE }, - { "class", &handleClass, TRUE }, - { "headerfile", &handleHeaderFile, FALSE }, - { "protocol", &handleProtocol, TRUE }, - { "category", &handleCategory, TRUE }, - { "union", &handleUnion, TRUE }, - { "struct", &handleStruct, TRUE }, - { "interface", &handleInterface, TRUE }, - { "idlexcept", &handleIdlException, TRUE }, - { "page", &handlePage, TRUE }, - { "mainpage", &handleMainpage, TRUE }, - { "file", &handleFile, TRUE }, - { "dir", &handleDir, TRUE }, - { "example", &handleExample, FALSE }, - { "details", &handleDetails, TRUE }, - { "name", &handleName, FALSE }, - { "todo", &handleTodo, FALSE }, // end brief will be done differently - { "test", &handleTest, FALSE }, // end brief will be done differently - { "bug", &handleBug, FALSE }, // end brief will be done differently - { "deprecated", &handleDeprecated, FALSE }, // end brief will be done differently - { "xrefitem", &handleXRefItem, FALSE }, // end brief will be done differently - { "related", &handleRelated, TRUE }, - { "relates", &handleRelated, TRUE }, - { "relatedalso", &handleRelatedAlso, TRUE }, - { "relatesalso", &handleRelatedAlso, TRUE }, - { "parblock", &handleParBlock, TRUE }, - { "endparblock", &handleEndParBlock, TRUE }, - { "refitem", &handleRefItem, TRUE }, - { "cite", &handleCite, FALSE }, - { "subpage", &handleSubpage, TRUE }, - { "section", &handleSection, TRUE }, - { "subsection", &handleSection, TRUE }, - { "subsubsection", &handleSection, TRUE }, - { "paragraph", &handleSection, TRUE }, - { "anchor", &handleAnchor, TRUE }, - { "verbatim", &handleFormatBlock, TRUE }, - { "latexonly", &handleFormatBlock, FALSE }, - { "htmlonly", &handleFormatBlock, FALSE }, - { "xmlonly", &handleFormatBlock, FALSE }, - { "docbookonly", &handleFormatBlock, FALSE }, - { "rtfonly", &handleFormatBlock, FALSE }, - { "manonly", &handleFormatBlock, FALSE }, - { "dot", &handleFormatBlock, TRUE }, - { "msc", &handleFormatBlock, TRUE }, - { "startuml", &handleFormatBlock, TRUE }, - { "code", &handleFormatBlock, TRUE }, - { "addindex", &handleAddIndex, FALSE }, - { "if", &handleIf, FALSE }, - { "ifnot", &handleIfNot, FALSE }, - { "elseif", &handleElseIf, FALSE }, - { "else", &handleElse, FALSE }, - { "endif", &handleEndIf, FALSE }, - { "ingroup", &handleIngroup, TRUE }, - { "nosubgrouping", &handleNoSubGrouping, FALSE }, - { "showinitializer", &handleShowInitializer, FALSE }, - { "hideinitializer", &handleHideInitializer, FALSE }, - { "callgraph", &handleCallgraph, FALSE }, - { "hidecallgraph", &handleHideCallgraph, FALSE }, - { "callergraph", &handleCallergraph, FALSE }, - { "hidecallergraph", &handleHideCallergraph, FALSE }, - { "showrefby", &handleReferencedByRelation, FALSE }, - { "hiderefby", &handleHideReferencedByRelation, FALSE }, - { "showrefs", &handleReferencesRelation, FALSE }, - { "hiderefs", &handleHideReferencesRelation, FALSE }, - { "internal", &handleInternal, TRUE }, - { "_linebr", &handleLineBr, FALSE }, - { "static", &handleStatic, FALSE }, - { "pure", &handlePure, FALSE }, - { "private", &handlePrivate, FALSE }, - { "privatesection", &handlePrivateSection, FALSE }, - { "protected", &handleProtected, FALSE }, - { "protectedsection",&handleProtectedSection, FALSE }, - { "public", &handlePublic, FALSE }, - { "publicsection", &handlePublicSection, FALSE }, - { "tableofcontents", &handleToc, FALSE }, - { "inherit", &handleInherit, TRUE }, - { "extends", &handleExtends, TRUE }, - { "implements", &handleExtends, TRUE }, - { "memberof", &handleMemberOf, TRUE }, - { "arg", 0, TRUE }, - { "attention", 0, TRUE }, - { "author", 0, TRUE }, - { "authors", 0, TRUE }, - { "copydoc", &handleCopyDoc, TRUE }, - { "copybrief", &handleCopyBrief, FALSE }, - { "copydetails", &handleCopyDetails, TRUE }, - { "copyright", 0, TRUE }, - { "date", 0, TRUE }, - { "dotfile", 0, TRUE }, - { "htmlinclude", 0, FALSE }, - { "image", 0, TRUE }, - { "include", 0, TRUE }, - { "includelineno", 0, TRUE }, - { "invariant", 0, TRUE }, - { "latexinclude", 0, FALSE }, - { "li", 0, TRUE }, - { "line", 0, TRUE }, - { "note", 0, TRUE }, - { "par", 0, TRUE }, - { "param", &handleParam, TRUE }, - { "tparam", 0, TRUE }, - { "post", 0, TRUE }, - { "pre", 0, TRUE }, - { "remark", 0, TRUE }, - { "remarks", 0, TRUE }, - { "result", 0, TRUE }, - { "return", 0, TRUE }, - { "returns", 0, TRUE }, - { "exception", 0, TRUE }, - { "retval", &handleRetval, TRUE }, - { "sa", 0, TRUE }, - { "see", 0, TRUE }, - { "since", 0, TRUE }, - { "throw", 0, TRUE }, - { "throws", 0, TRUE }, - { "until", 0, TRUE }, - { "verbinclude", 0, FALSE }, - { "version", 0, TRUE }, - { "warning", 0, TRUE }, - { "snippet", 0, TRUE }, - { "snippetlineno", 0, TRUE }, - { "noop", &handleNoop, TRUE }, - { 0, 0, FALSE } -}; - -/** @brief Command mapper. - * - * Maps a command name (as found in a comment block) onto a - * specific handler function. - */ -class DocCmdMapper -{ - public: - struct Cmd - { - DocCmdFunc func; - bool endsBrief; - }; - - /** maps a command name to a handler function */ - static Cmd *map(const char *name) - { - return instance()->find(name); - } - - /** release the singleton */ - static void freeInstance() - { - delete s_instance; s_instance=0; - } - - private: - static DocCmdMapper *instance() - { - if (s_instance==0) s_instance = new DocCmdMapper; - return s_instance; - } - - DocCmdMapper() : m_map(113) - { - m_map.setAutoDelete(TRUE); - DocCmdMap *p = docCmdMap; - while (p->cmdName) - { - if (m_map.find(p->cmdName)!=0) - { - term("DocCmdMapper: command %s already added\n",p->cmdName); - } - Cmd *cmd = new Cmd; - cmd->func = p->handler; - cmd->endsBrief = p->endsBrief; - m_map.insert(p->cmdName,cmd); - p++; - } - } - - Cmd *find(const char *name) - { - return m_map.find(name); - } - QDict<Cmd> m_map; - static DocCmdMapper *s_instance; +static const std::map< std::string, DocCmdMap > docCmdMap = +{ + // command name handler function command spacing + { "addindex", { &handleAddIndex, CommandSpacing::Invisible }}, + { "addtogroup", { &handleAddToGroup, CommandSpacing::Invisible }}, + { "anchor", { &handleAnchor, CommandSpacing::Invisible }}, + { "arg", { 0, CommandSpacing::Block }}, + { "attention", { 0, CommandSpacing::Block }}, + { "author", { 0, CommandSpacing::Block }}, + { "authors", { 0, CommandSpacing::Block }}, + { "brief", { &handleBrief, CommandSpacing::Invisible }}, + { "bug", { &handleBug, CommandSpacing::Block }}, + { "callergraph", { &handleCallergraph, CommandSpacing::Invisible }}, + { "callgraph", { &handleCallgraph, CommandSpacing::Invisible }}, + { "category", { &handleCategory, CommandSpacing::Invisible }}, + { "cite", { &handleCite, CommandSpacing::Inline }}, + { "class", { &handleClass, CommandSpacing::Invisible }}, + { "code", { &handleFormatBlock, CommandSpacing::Block }}, + { "copybrief", { &handleCopyBrief, CommandSpacing::Invisible }}, + { "copydetails", { &handleCopyDetails, CommandSpacing::Block }}, + { "copydoc", { &handleCopyDoc, CommandSpacing::Block }}, + { "copyright", { 0, CommandSpacing::Block }}, + { "date", { 0, CommandSpacing::Block }}, + { "def", { &handleDef, CommandSpacing::Invisible }}, + { "defgroup", { &handleDefGroup, CommandSpacing::Invisible }}, + { "deprecated", { &handleDeprecated, CommandSpacing::Block }}, + { "details", { &handleDetails, CommandSpacing::Block }}, + { "dir", { &handleDir, CommandSpacing::Invisible }}, + { "docbookinclude", { 0, CommandSpacing::Inline }}, + { "docbookonly", { &handleFormatBlock, CommandSpacing::Invisible }}, + { "dot", { &handleFormatBlock, CommandSpacing::Block }}, + { "dotfile", { 0, CommandSpacing::Block }}, + { "else", { &handleElse, CommandSpacing::Inline }}, + { "elseif", { &handleElseIf, CommandSpacing::Inline }}, + { "endif", { &handleEndIf, CommandSpacing::Inline }}, + { "endparblock", { &handleEndParBlock, CommandSpacing::Block }}, + { "enum", { &handleEnum, CommandSpacing::Invisible }}, + { "example", { &handleExample, CommandSpacing::Invisible }}, + { "exception", { 0, CommandSpacing::Block }}, + { "extends", { &handleExtends, CommandSpacing::Invisible }}, + { "file", { &handleFile, CommandSpacing::Invisible }}, + { "fn", { &handleFn, CommandSpacing::Invisible }}, + { "headerfile", { &handleHeaderFile, CommandSpacing::Invisible }}, + { "hidecallergraph", { &handleHideCallergraph, CommandSpacing::Invisible }}, + { "hidecallgraph", { &handleHideCallgraph, CommandSpacing::Invisible }}, + { "hideinitializer", { &handleHideInitializer, CommandSpacing::Invisible }}, + { "hiderefby", { &handleHideReferencedByRelation, CommandSpacing::Invisible }}, + { "hiderefs", { &handleHideReferencesRelation, CommandSpacing::Invisible }}, + { "htmlinclude", { 0, CommandSpacing::Inline }}, + { "htmlonly", { &handleFormatBlock, CommandSpacing::Invisible }}, + { "idlexcept", { &handleIdlException, CommandSpacing::Invisible }}, + { "if", { &handleIf, CommandSpacing::Inline }}, + { "ifnot", { &handleIfNot, CommandSpacing::Inline }}, + { "image", { 0, CommandSpacing::Block }}, + { "implements", { &handleExtends, CommandSpacing::Invisible }}, + { "include", { 0, CommandSpacing::Block }}, + { "includelineno", { 0, CommandSpacing::Block }}, + { "ingroup", { &handleIngroup, CommandSpacing::Invisible }}, + { "inherit", { &handleInherit, CommandSpacing::Invisible }}, + { "interface", { &handleInterface, CommandSpacing::Invisible }}, + { "internal", { &handleInternal, CommandSpacing::Block }}, + { "invariant", { 0, CommandSpacing::Block }}, + { "latexinclude", { 0, CommandSpacing::Inline }}, + { "latexonly", { &handleFormatBlock, CommandSpacing::Invisible }}, + { "li", { 0, CommandSpacing::Block }}, + { "line", { 0, CommandSpacing::Invisible }}, + { "mainpage", { &handleMainpage, CommandSpacing::Invisible }}, + { "maninclude", { 0, CommandSpacing::Inline }}, + { "manonly", { &handleFormatBlock, CommandSpacing::Invisible }}, + { "memberof", { &handleMemberOf, CommandSpacing::Invisible }}, + { "msc", { &handleFormatBlock, CommandSpacing::Block }}, + { "name", { &handleName, CommandSpacing::Invisible }}, + { "namespace", { &handleNamespace, CommandSpacing::Invisible }}, + { "noop", { &handleNoop, CommandSpacing::Invisible }}, + { "nosubgrouping", { &handleNoSubGrouping, CommandSpacing::Invisible }}, + { "note", { 0, CommandSpacing::Block }}, + { "overload", { &handleOverload, CommandSpacing::Invisible }}, + { "package", { &handlePackage, CommandSpacing::Invisible }}, + { "page", { &handlePage, CommandSpacing::Invisible }}, + { "par", { 0, CommandSpacing::Block }}, + { "paragraph", { &handleSection, CommandSpacing::Block }}, + { "param", { &handleParam, CommandSpacing::Block }}, + { "parblock", { &handleParBlock, CommandSpacing::Block }}, + { "post", { 0, CommandSpacing::Block }}, + { "pre", { 0, CommandSpacing::Block }}, + { "private", { &handlePrivate, CommandSpacing::Invisible }}, + { "privatesection", { &handlePrivateSection, CommandSpacing::Invisible }}, + { "property", { &handleFn, CommandSpacing::Invisible }}, + { "protected", { &handleProtected, CommandSpacing::Invisible }}, + { "protectedsection",{ &handleProtectedSection, CommandSpacing::Invisible }}, + { "protocol", { &handleProtocol, CommandSpacing::Invisible }}, + { "public", { &handlePublic, CommandSpacing::Invisible }}, + { "publicsection", { &handlePublicSection, CommandSpacing::Invisible }}, + { "pure", { &handlePure, CommandSpacing::Invisible }}, + { "refitem", { &handleRefItem, CommandSpacing::Inline }}, + { "related", { &handleRelated, CommandSpacing::Invisible }}, + { "relatedalso", { &handleRelatedAlso, CommandSpacing::Invisible }}, + { "relates", { &handleRelated, CommandSpacing::Invisible }}, + { "relatesalso", { &handleRelatedAlso, CommandSpacing::Invisible }}, + { "remark", { 0, CommandSpacing::Block }}, + { "remarks", { 0, CommandSpacing::Block }}, + { "result", { 0, CommandSpacing::Block }}, + { "return", { 0, CommandSpacing::Block }}, + { "returns", { 0, CommandSpacing::Block }}, + { "retval", { &handleRetval, CommandSpacing::Block }}, + { "rtfinclude", { 0, CommandSpacing::Inline }}, + { "rtfonly", { &handleFormatBlock, CommandSpacing::Invisible }}, + { "sa", { 0, CommandSpacing::Block }}, + { "section", { &handleSection, CommandSpacing::Block }}, + { "see", { 0, CommandSpacing::Block }}, + { "short", { &handleBrief, CommandSpacing::Invisible }}, + { "showinitializer", { &handleShowInitializer, CommandSpacing::Invisible }}, + { "showrefby", { &handleReferencedByRelation, CommandSpacing::Invisible }}, + { "showrefs", { &handleReferencesRelation, CommandSpacing::Invisible }}, + { "since", { 0, CommandSpacing::Block }}, + { "snippet", { 0, CommandSpacing::Block }}, + { "snippetlineno", { 0, CommandSpacing::Block }}, + { "startuml", { &handleFormatBlock, CommandSpacing::Block }}, + { "static", { &handleStatic, CommandSpacing::Invisible }}, + { "struct", { &handleStruct, CommandSpacing::Invisible }}, + { "subpage", { &handleSubpage, CommandSpacing::Inline }}, + { "subsection", { &handleSection, CommandSpacing::Block }}, + { "subsubsection", { &handleSection, CommandSpacing::Block }}, + { "tableofcontents", { &handleToc, CommandSpacing::Invisible }}, + { "test", { &handleTest, CommandSpacing::Block }}, + { "throw", { 0, CommandSpacing::Block }}, + { "throws", { 0, CommandSpacing::Block }}, + { "todo", { &handleTodo, CommandSpacing::Block }}, + { "tparam", { 0, CommandSpacing::Block }}, + { "typedef", { &handleFn, CommandSpacing::Invisible }}, + { "union", { &handleUnion, CommandSpacing::Invisible }}, + { "until", { 0, CommandSpacing::Block }}, + { "var", { &handleFn, CommandSpacing::Invisible }}, + { "verbatim", { &handleFormatBlock, CommandSpacing::Block }}, + { "verbinclude", { 0, CommandSpacing::Inline }}, + { "version", { 0, CommandSpacing::Block }}, + { "warning", { 0, CommandSpacing::Block }}, + { "weakgroup", { &handleWeakGroup, CommandSpacing::Invisible }}, + { "xmlinclude", { 0, CommandSpacing::Inline }}, + { "xmlonly", { &handleFormatBlock, CommandSpacing::Invisible }}, + { "xrefitem", { &handleXRefItem, CommandSpacing::Block }} }; -DocCmdMapper *DocCmdMapper::s_instance=0; - -bool inInternalDocs = FALSE; - +#define YY_NO_INPUT 1 +#define YY_NO_UNISTD_H 1 #define YY_NEVER_INTERACTIVE 1 + enum XRefKind { XRef_Item, @@ -379,11 +335,11 @@ enum GuardType class GuardedSection { public: - GuardedSection(bool enabled,bool parentVisible) + GuardedSection(bool enabled,bool parentVisible) : m_enabled(enabled),m_parentVisible(parentVisible) {} bool isEnabled() const { return m_enabled; } bool parentVisible() const { return m_parentVisible; } - + private: bool m_enabled; bool m_parentVisible; @@ -391,532 +347,113 @@ class GuardedSection /* ----------------------------------------------------------------- * - * statics + * statics */ -static OutlineParserInterface *langParser; // the language parser that is calling us -static QCString inputString; // input string -static int inputPosition; // read pointer -static QCString yyFileName; // file name that is read from -static int yyLineNr; // line number in the input -static bool inBody; // was the comment found inside the body of a function? -static OutputContext inContext; // are we inside the brief, details or xref part -static bool briefEndsAtDot; // does the brief description stop at a dot? -static QCString formulaText; // Running text of a formula -static QCString formulaEnv; // environment name -static int formulaNewLines; // amount of new lines in the formula -static QCString *pOutputString; // pointer to string to which the output is appended. -static QCString outputXRef; // temp argument of todo/test/../xrefitem commands -static QCString blockName; // preformatted block name (e.g. verbatim, latexonly,...) -static XRefKind xrefKind; // kind of cross-reference command -static XRefKind newXRefKind; // -static GuardType guardType; // kind of guard for conditional section -static bool enabledSectionFound; -static QCString functionProto; // function prototype -static QStack<GuardedSection> guards; // tracks nested conditional sections (if,ifnot,..) -static Entry *current = 0; // working entry - -static bool needNewEntry; - -static QCString g_sectionLabel; -static QCString g_sectionTitle; -static int g_sectionLevel; -static QCString xrefItemKey; -static QCString newXRefItemKey; -static QCString xrefItemTitle; -static QCString xrefListTitle; -static Protection protection; - -static bool xrefAppendFlag; -static bool inGroupParamFound; -static int braceCount; -static bool insidePre; -static bool parseMore; -static int g_condCount; - -static int g_commentCount; -static QCString g_spaceBeforeCmd; -static QCString g_spaceBeforeIf; -static QCString g_copyDocArg; - -static QCString g_guardExpr; -static int g_roundCount; - -static bool g_insideParBlock; - -//----------------------------------------------------------------------------- - -static void initParser() -{ - g_sectionLabel.resize(0); - g_sectionTitle.resize(0); - Doxygen::docGroup.clearHeader(); - g_insideParBlock = FALSE; -} - -//----------------------------------------------------------------------------- - -static bool getDocSectionName(int s) -{ - switch(s) - { - case Entry::CLASSDOC_SEC: - case Entry::STRUCTDOC_SEC: - case Entry::UNIONDOC_SEC: - case Entry::EXCEPTIONDOC_SEC: - case Entry::NAMESPACEDOC_SEC: - case Entry::PROTOCOLDOC_SEC: - case Entry::CATEGORYDOC_SEC: - case Entry::ENUMDOC_SEC: - case Entry::PAGEDOC_SEC: - case Entry::VARIABLEDOC_SEC: - case Entry::MEMBERDOC_SEC: - case Entry::OVERLOADDOC_SEC: - case Entry::FILEDOC_SEC: - case Entry::DEFINEDOC_SEC: - case Entry::GROUPDOC_SEC: - case Entry::MAINPAGEDOC_SEC: - case Entry::PACKAGEDOC_SEC: - case Entry::DIRDOC_SEC: - case Entry::EXAMPLE_SEC: - case Entry::MEMBERGRP_SEC: - return TRUE; - default: - return FALSE; - } -} - -//----------------------------------------------------------------------------- - -static bool makeStructuralIndicator(Entry::Sections s) -{ - //printf("current->section=%x\n",current->section); - if (getDocSectionName(current->section)) - { - return TRUE; - } - else - { - needNewEntry = TRUE; - current->section = s; - current->fileName = yyFileName; - current->startLine = yyLineNr; - return FALSE; - } -} - -static void lineCount() -{ - for( const char* c = yytext ; *c ; ++c ) - yyLineNr += (*c == '\n') ; -} - - -static QCString stripQuotes(const char *s) -{ - QCString name; - if (s==0 || *s==0) return name; - name=s; - if (name.at(0)=='"' && name.at(name.length()-1)=='"') - { - name=name.mid(1,name.length()-2); - } - return name; -} - -//----------------------------------------------------------------- - -static void addXRefItem(const char *listName,const char *itemTitle, - const char *listTitle,bool append) -{ - if (listName==0) return; - //printf("addXRefItem(%s,%s,%s,%d)\n",listName,itemTitle,listTitle,append); - - const ListItemInfo *lii=0; - RefList *refList = Doxygen::xrefLists->find(listName); - if (refList==0) // new list - { - refList = new RefList(listName,listTitle,itemTitle); - Doxygen::xrefLists->insert(listName,refList); - //printf("new list!\n"); - } - for (const ListItemInfo &item : current->sli) - { - if (qstrcmp(item.type,listName)==0) - { - //printf("found %s lii->type=%s\n",listName,lii->type); - lii = &item; - break; - } - } - if (lii && append) // already found item of same type just before this one - { - //printf("listName=%s item id = %d existing\n",listName,lii->itemId); - RefItem *item = refList->getRefItem(lii->itemId); - ASSERT(item!=0); - item->text += " <p>"; - item->text += outputXRef; - //printf("%s: text +=%s\n",listName,item->text.data()); - } - else // new item - { - int itemId = refList->addRefItem(); - //printf("listName=%s item id = %d new current=%p\n",listName,itemId,current); - - // if we have already an item from the same list type (e.g. a second @todo) - // in the same Entry (i.e. lii!=0) then we reuse its link anchor. - char anchorLabel[1024]; - //sprintf(anchorLabel,"_%s%06d",listName,lii ? lii->itemId : itemId); - sprintf(anchorLabel,"_%s%06d",listName,itemId); - RefItem *item = refList->getRefItem(itemId); - ASSERT(item!=0); - item->text = outputXRef; - item->listAnchor = anchorLabel; - current->addSpecialListItem(listName,itemId); - QCString cmdString; - cmdString.sprintf(" \\xrefitem %s %d.",listName,itemId); - if (inBody) - { - current->inbodyDocs += cmdString; - } - else - { - current->doc += cmdString; - } - SectionInfo *si = Doxygen::sectionDict->find(anchorLabel); - if (si) - { - if (si->lineNr != -1) - { - warn(listName,yyLineNr,"multiple use of section label '%s', (first occurrence: %s, line %d)",anchorLabel,si->fileName.data(),si->lineNr); - } - else - { - warn(listName,yyLineNr,"multiple use of section label '%s', (first occurrence: %s)",anchorLabel,si->fileName.data()); - } - } - else - { - si=new SectionInfo(listName,yyLineNr,anchorLabel, - g_sectionTitle,SectionInfo::Anchor, - g_sectionLevel); - Doxygen::sectionDict->append(anchorLabel,si); - current->anchors.push_back(si); - } - } - outputXRef.resize(0); -} - -//----------------------------------------------------------------------------- - -// Adds a formula text to the list/dictionary of formulas if it was -// not already added. Returns the label of the formula. -static QCString addFormula() -{ - QCString formLabel; - QCString fText=formulaText.simplifyWhiteSpace(); - Formula *f=0; - if ((f=Doxygen::formulaDict->find(fText))==0) - { - f = new Formula(fText); - Doxygen::formulaList->append(f); - Doxygen::formulaDict->insert(fText,f); - formLabel.sprintf("\\_form#%d",f->getId()); - Doxygen::formulaNameDict->insert(formLabel,f); - } - else - { - formLabel.sprintf("\\_form#%d",f->getId()); - } - int i; - for (i=0;i<formulaNewLines;i++) formLabel+="@_fakenl"; // add fake newlines to - // keep the warnings - // correctly aligned. - return formLabel; -} - -//----------------------------------------------------------------------------- +struct commentscanYY_state +{ + OutlineParserInterface *langParser = 0; // the language parser that is calling us + QCString inputString; // input string + QCString currentCmd; // the command used + int inputPosition = 0; // read pointer + QCString fileName; // file name that is read from + int lineNr = 0; // line number in the input + bool inBody = FALSE; // was the comment found inside the body of a function? + OutputContext inContext; // are we inside the brief, details or xref part + bool briefEndsAtDot = FALSE; // does the brief description stop at a dot? + QCString formulaText; // Running text of a formula + QCString formulaEnv; // environment name + int formulaNewLines = 0; // amount of new lines in the formula + QCString *pOutputString = 0; // pointer to string to which the output is appended. + QCString outputXRef; // temp argument of todo/test/../xrefitem commands + QCString blockName; // preformatted block name (e.g. verbatim, latexonly,...) + XRefKind xrefKind = XRef_Item; // kind of cross-reference command + XRefKind newXRefKind = XRef_Item; // + GuardType guardType = Guard_If; // kind of guards for conditional section + bool enabledSectionFound = FALSE; + QCString functionProto; // function prototype + std::stack<GuardedSection> guards; // tracks nested conditional sections (if,ifnot,..) + Entry *current = 0; // working entry + + bool needNewEntry = FALSE; + + QCString sectionLabel; + QCString sectionTitle; + int sectionLevel = 0; + QCString xrefItemKey; + QCString newXRefItemKey; + QCString xrefItemTitle; + QCString xrefListTitle; + Protection protection = Public; + + bool xrefAppendFlag = FALSE; + bool inGroupParamFound = FALSE; + int braceCount = 0; + bool insidePre = FALSE; + bool parseMore = FALSE; + int condCount = 0; + + int commentCount = 0; + QCString spaceBeforeCmd; + QCString spaceBeforeIf; + QCString copyDocArg; + + QCString guardExpr; + int roundCount = 0; + + bool insideParBlock = FALSE; + bool inInternalDocs = FALSE; + int prevPosition = 0; + DocGroup docGroup; + bool markdownSupport = TRUE; +}; -static void checkFormula(); -//----------------------------------------------------------------------------- -static SectionInfo::SectionType sectionLevelToType(int level) -{ - if (level>=0 && level<5) return (SectionInfo::SectionType)level; - return SectionInfo::Anchor; -} - -static void addSection() -{ - SectionInfo *si = Doxygen::sectionDict->find(g_sectionLabel); - if (si) - { - if (si->lineNr != -1) - { - warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s, line %d)",g_sectionLabel.data(),si->fileName.data(),si->lineNr); - } - else - { - warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s)",g_sectionLabel.data(),si->fileName.data()); - } - } - else - { - // create a new section element - g_sectionTitle+=yytext; - g_sectionTitle=g_sectionTitle.stripWhiteSpace(); - si = new SectionInfo(yyFileName,yyLineNr,g_sectionLabel, - g_sectionTitle,sectionLevelToType(g_sectionLevel),g_sectionLevel); - - // add section to this entry - current->anchors.push_back(si); - - // add section to the global dictionary - Doxygen::sectionDict->append(g_sectionLabel,si); - } -} +static std::mutex g_sectionMutex; +static std::mutex g_formulaMutex; +static std::mutex g_citeMutex; //----------------------------------------------------------------------------- -static void addCite() -{ - QCString name=yytext; - if (yytext[0] =='"') - { - name=yytext+1; - name=name.left(yyleng-2); - } - Doxygen::citeDict->insert(name.data()); -} +static QCString stripQuotes(const char *s); +static bool getDocSectionName(int s); +static SectionType sectionLevelToType(int level); +static void stripTrailingWhiteSpace(QCString &s); + +static void initParser(yyscan_t yyscanner); +static bool makeStructuralIndicator(yyscan_t yyscanner,Entry::Sections s); +static void lineCount(yyscan_t yyscanner); +static void addXRefItem(yyscan_t yyscanner, + const char *listName,const char *itemTitle, + const char *listTitle,bool append); +static QCString addFormula(yyscan_t yyscanner); +static void checkFormula(yyscan_t yyscanner); +static void addSection(yyscan_t yyscanner); +static inline void setOutput(yyscan_t yyscanner,OutputContext ctx); +static void addAnchor(yyscan_t yyscanner,const char *anchor); +static inline void addOutput(yyscan_t yyscanner,const char *s); +static inline void addOutput(yyscan_t yyscanner,char c); +static void endBrief(yyscan_t yyscanner,bool addToOutput=TRUE); +static void handleGuard(yyscan_t yyscanner,const QCString &expr); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void addCite(yyscan_t yyscanner); //----------------------------------------------------------------------------- -// strip trailing whitespace (excluding newlines) from string s -static void stripTrailingWhiteSpace(QCString &s) -{ - uint len = s.length(); - int i = (int)len-1; - char c; - while (i>=0 && ((c = s.at(i))==' ' || c=='\t' || c=='\r')) i--; - if (i!=(int)len-1) - { - s.resize(i+2); // string up to and including char at pos i and \0 terminator - } -} - -// selects the output to write to -static inline void setOutput(OutputContext ctx) -{ - bool xrefAppendToPrev = xrefAppendFlag; - // determine append flag for the next item (i.e. the end of this item) - xrefAppendFlag = !inBody && - inContext==OutputXRef && ctx==OutputXRef && // two consecutive xref items - newXRefKind==xrefKind && // of the same kind - (xrefKind!=XRef_Item || - newXRefItemKey==xrefItemKey); // with the same key if \xrefitem - //printf("%d && %d && %d && (%d || %d)\n", - // inContext==OutputXRef, - // ctx==OutputXRef, - // newXRefKind==xrefKind, - // xrefKind!=XRef_Item, - // newXRefItemKey==xrefItemKey); - - //printf("refKind=%d newXRefKind=%d xrefAppendToPrev=%d xrefAppendFlag=%d\n", - // xrefKind,newXRefKind,xrefAppendToPrev,xrefAppendFlag); - - //printf("setOutput(inContext=%d ctx=%d)\n",inContext,ctx); - if (inContext==OutputXRef) // end of XRef section => add the item - { - // See if we can append this new xref item to the previous one. - // We know this at the start of the next item of the same - // type and need to remember this until the end of that item. - switch(xrefKind) - { - case XRef_Todo: - addXRefItem("todo", - theTranslator->trTodo(), - theTranslator->trTodoList(), - xrefAppendToPrev - ); - break; - case XRef_Test: - addXRefItem("test", - theTranslator->trTest(), - theTranslator->trTestList(), - xrefAppendToPrev - ); - break; - case XRef_Bug: - addXRefItem("bug", - theTranslator->trBug(), - theTranslator->trBugList(), - xrefAppendToPrev - ); - break; - case XRef_Deprecated: - addXRefItem("deprecated", - theTranslator->trDeprecated(), - theTranslator->trDeprecatedList(), - xrefAppendToPrev - ); - break; - case XRef_Item: // user defined list - addXRefItem(xrefItemKey, - xrefItemTitle, - xrefListTitle, - xrefAppendToPrev - ); - break; - case XRef_None: - ASSERT(0); - break; - } - } - xrefItemKey = newXRefItemKey; - - int oldContext = inContext; - inContext = ctx; - if (inContext!=OutputXRef && inBody) inContext=OutputInbody; - switch(inContext) - { - case OutputDoc: - if (oldContext!=inContext) - { - stripTrailingWhiteSpace(current->doc); - if (current->docFile.isEmpty()) - { - current->docFile = yyFileName; - current->docLine = yyLineNr; - } - } - pOutputString = ¤t->doc; - break; - case OutputBrief: - if (oldContext!=inContext) - { - if (current->briefFile.isEmpty()) - { - current->briefFile = yyFileName; - current->briefLine = yyLineNr; - } - } - if (current->brief.stripWhiteSpace().isEmpty()) // we only want one brief - // description even if multiple - // are given... - { - pOutputString = ¤t->brief; - } - else - { - if (!current->doc.isEmpty()) // when appending parts add a new line - { - current->doc += "\n"; - } - pOutputString = ¤t->doc; - inContext = OutputDoc; // need to switch to detailed docs, see bug 631380 - } - break; - case OutputXRef: - pOutputString = &outputXRef; - // first item found, so can't append to previous - //xrefAppendFlag = FALSE; - break; - case OutputInbody: - pOutputString = ¤t->inbodyDocs; - break; - } -} - - -static void addAnchor(const char *anchor) -{ - SectionInfo *si = Doxygen::sectionDict->find(anchor); - if (si) - { - if (si->lineNr != -1) - { - warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s, line %d)",anchor,si->fileName.data(),si->lineNr); - } - else - { - warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s)",anchor,si->fileName.data()); - } - } - else - { - si = new SectionInfo(yyFileName,yyLineNr,anchor,0,SectionInfo::Anchor,0); - Doxygen::sectionDict->append(anchor,si); - current->anchors.push_back(si); - } -} - -// add a string to the output -static inline void addOutput(const char *s) -{ - //printf("addOutput(%s)\n",s); - *pOutputString+=s; -} - -// add a character to the output -static inline void addOutput(char c) -{ - *pOutputString+=c; -} - -static void endBrief(bool addToOutput=TRUE) -{ - if (!current->brief.stripWhiteSpace().isEmpty()) - { // only go to the detailed description if we have - // found some brief description and not just whitespace - briefEndsAtDot=FALSE; - setOutput(OutputDoc); - if (addToOutput) addOutput(yytext); - } -} - -static void handleGuard(const QCString &expr); -/* ----------------------------------------------------------------- */ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static int prevPosition=0; - -static int yyread(char *buf,int max_size) -{ - prevPosition=inputPosition; - int c=0; - while( c < max_size && inputString[inputPosition] ) - { - *buf = inputString[inputPosition++] ; - //printf("%d (%c)\n",*buf,*buf); - c++; buf++; - } - return c; -} +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} /* start command character */ -CMD ("\\"|"@") -DCMD1 ("arg"|"attention"|"author"|"cite"|"code") -DCMD2 ("date"|"dot"|"msc"|"dotfile"|"example"|"startuml") -DCMD3 ("htmlinclude"|"htmlonly"|"image"|"include") -DCMD4 ("includelineno"|"internal"|"invariant") -DCMD5 ("latexinclude"|"latexonly"|"li"|"line"|"manonly"|"name") -DCMD6 ("note"|"par"|"paragraph"|"param"|"post") -DCMD7 ("pre"|"remarks"|(("relate"[sd])("also")?)) -DCMD8 ("remarks"|("return"[s]?)|"retval"|"sa"|"section") -DCMD9 ("see"|"since"|"subsection"|"subsubsection") -DCMD10 ("throw"|"until"|"verbatim") -DCMD11 ("verbinclude"|"version"|"warning") -DETAILEDCMD {CMD}({DCMD1}|{DCMD2}|{DCMD3}|{DCMD4}|{DCMD5}|{DCMD6}|{DCMD7}|{DCMD8}|{DCMD9}|{DCMD10}|{DCMD11}) -XREFCMD {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem") +CMD ("\\"|"@") +XREFCMD {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem") PRE [pP][rR][eE] -TABLE [tT][aA][bB][lL][eE] -P [pP] +TABLE [tT][aA][bB][lL][eE] +P [pP] UL [uU][lL] -OL [oO][lL] -DL [dD][lL] +OL [oO][lL] +DL [dD][lL] IMG [iI][mM][gG] HR [hH][rR] PARA [pP][aA][rR][aA] @@ -927,13 +464,13 @@ DIV [dD][iI][vV] DETAILEDHTML {CENTER}|{DIV}|{PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA} DETAILEDHTMLOPT {CODE} BN [ \t\n\r] -BL [ \t\r]*"\n" +BL [ \t\r]*"\n" B [ \t] BS ^(({B}*"//")?)(({B}*"*"+)?){B}* ATTR ({B}+[^>\n]*)? -DOCNL "\n"|"\\_linebr" +DOCNL "\n"|"\\ilinebr" LC "\\"{B}*"\n" -NW [^a-z_A-Z0-9] +NW [^a-z_A-Z0-9] FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+@&#] FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+@&#] FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"") @@ -945,7 +482,7 @@ CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{C SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID}) TMPLSPEC "<"{BN}*[^>]+{BN}*">" -MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ +MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ RCSTAG "$"{ID}":"[^\n$]+"$" %option noyywrap @@ -964,34 +501,34 @@ RCSTAG "$"{ID}":"[^\n$]+"$" %x XRefItemParam3 %x FileDocArg1 %x ParamArg1 -%x EnumDocArg1 -%x NameSpaceDocArg1 -%x PackageDocArg1 -%x GroupDocArg1 -%x GroupDocArg2 -%x SectionLabel -%x SectionTitle -%x SubpageLabel -%x SubpageTitle -%x FormatBlock -%x LineParam -%x GuardParam -%x GuardParamEnd -%x SkipGuardedSection -%x SkipInternal +%x EnumDocArg1 +%x NameSpaceDocArg1 +%x PackageDocArg1 +%x GroupDocArg1 +%x GroupDocArg2 +%x SectionLabel +%x SectionTitle +%x SubpageLabel +%x SubpageTitle +%x FormatBlock +%x LineParam +%x GuardParam +%x GuardParamEnd +%x SkipGuardedSection +%x SkipInternal %x NameParam -%x InGroupParam -%x FnParam -%x OverloadParam -%x InheritParam -%x ExtendsParam +%x InGroupParam +%x FnParam +%x OverloadParam +%x InheritParam +%x ExtendsParam %x ReadFormulaShort -%x ReadFormulaLong -%x AnchorLabel +%x ReadFormulaLong +%x AnchorLabel %x HtmlComment %x SkipLang -%x CiteLabel -%x CopyDoc +%x CiteLabel +%x CopyDoc %x GuardExpr %x CdataSection %x Noop @@ -1015,52 +552,52 @@ RCSTAG "$"{ID}":"[^\n$]+"$" * XML commands, <summary></summary><remarks></remarks> */ -<Comment>{CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command - addOutput(yytext); - } -<Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command - addOutput(yytext); - } -<Comment>{MAILADDR} { // mail address - addOutput(yytext); - } -<Comment>"\""[^"\n]*"\"" { // quoted text - addOutput(yytext); - } -<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!) - addOutput(yytext); - } -<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description - setOutput(OutputDoc); - // continue with the same input +<Comment>{CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command + addOutput(yyscanner,yytext); + } +<Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command + addOutput(yyscanner,yytext); + } +<Comment>{MAILADDR} { // mail address + addOutput(yyscanner,yytext); + } +<Comment>"\""[^"\n]*"\"" { // quoted text + addOutput(yyscanner,yytext); + } +<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!) + addOutput(yyscanner,yytext); + } +<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description + setOutput(yyscanner,OutputDoc); + // continue with the same input REJECT; - } -<Comment>"<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML command that ends a brief description - if (current->lang==SrcLangExt_CSharp) + } +<Comment>"<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML command that ends a brief description + if (yyextra->current->lang==SrcLangExt_CSharp) { - setOutput(OutputDoc); + setOutput(yyscanner,OutputDoc); } - // continue with the same input + // continue with the same input REJECT; - } -<Comment>"<summary>" { // start of a .NET XML style brief description - setOutput(OutputBrief); - addOutput(yytext); - } -<Comment>"<remarks>" { // start of a .NET XML style detailed description - setOutput(OutputDoc); - addOutput(yytext); - } -<Comment>"</summary>" { // start of a .NET XML style detailed description - setOutput(OutputBrief); - addOutput(yytext); - setOutput(OutputDoc); - } -<Comment>"</remarks>" { // end of a brief or detailed description - - setOutput(OutputDoc); - addOutput(yytext); - } + } +<Comment>"<summary>" { // start of a .NET XML style brief description + setOutput(yyscanner,OutputBrief); + addOutput(yyscanner,yytext); + } +<Comment>"<remarks>" { // start of a .NET XML style detailed description + setOutput(yyscanner,OutputDoc); + addOutput(yyscanner,yytext); + } +<Comment>"</summary>" { // start of a .NET XML style detailed description + setOutput(yyscanner,OutputBrief); + addOutput(yyscanner,yytext); + setOutput(yyscanner,OutputDoc); + } +<Comment>"</remarks>" { // end of a brief or detailed description + + setOutput(yyscanner,OutputDoc); + addOutput(yyscanner,yytext); + } <Comment>"<"{CAPTION}{ATTR}">" { QCString tag=yytext; int s=tag.find("id="); @@ -1073,40 +610,43 @@ RCSTAG "$"{ID}":"[^\n$]+"$" if (e!=-1) // found matching end { QCString id=tag.mid(s+4,e-s-4); // extract id - addAnchor(id); + addAnchor(yyscanner,id); } } } - addOutput(yytext); + addOutput(yyscanner,yytext); } <Comment>"<"{PRE}{ATTR}">" { - insidePre=TRUE; - addOutput(yytext); + yyextra->insidePre=TRUE; + addOutput(yyscanner,yytext); } <Comment>"</"{PRE}">" { - insidePre=FALSE; - addOutput(yytext); + yyextra->insidePre=FALSE; + addOutput(yyscanner,yytext); } <Comment>{RCSTAG} { // RCS tag which end a brief description - setOutput(OutputDoc); + setOutput(yyscanner,OutputDoc); REJECT; } -<Comment>"<!--" { +<Comment>"<!--" { BEGIN(HtmlComment); } <Comment>"<!\[CDATA\[" { BEGIN(CdataSection); } -<Comment>{B}*{CMD}"endinternal"{B}* { - addOutput(" \\endinternal "); - if (!inInternalDocs) - warn(yyFileName,yyLineNr, +<Comment>{B}*{CMD}"endinternal"{B}* { + addOutput(yyscanner," \\endinternal "); + if (!yyextra->inInternalDocs) + warn(yyextra->fileName,yyextra->lineNr, "found \\endinternal without matching \\internal" ); - inInternalDocs = FALSE; - } + yyextra->inInternalDocs = FALSE; + } +<Comment>{B}*"\\ilinebr"{B}* { // preserve spacing around \\ilinebr + addOutput(yyscanner,yytext); + } <Comment>{B}*{CMD}[a-z_A-Z]+"{"[a-zA-Z_,:0-9\. ]*"}"{B}* | -<Comment>{B}*{CMD}[a-z_A-Z]+{B}* { // potentially interesting command +<Comment>{B}*{CMD}[a-z_A-Z]+{B}* { // potentially interesting command // the {B}* in the front was added for bug620924 QCString fullMatch = QCString(yytext); int idx = fullMatch.find('{'); @@ -1125,512 +665,522 @@ RCSTAG "$"{ID}":"[^\n$]+"$" QCString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace(); optList = QCStringList::split(',',optStr); } - DocCmdMapper::Cmd *cmdPtr = DocCmdMapper::map(cmdName); - if (cmdPtr) // special action is required - { + auto it = docCmdMap.find(cmdName.data()); + if (it!=docCmdMap.end()) // special action is required + { int i=0; while (yytext[i]==' ' || yytext[i]=='\t') i++; - g_spaceBeforeCmd = QCString(yytext).left(i); - if (cmdPtr->endsBrief && !(inContext==OutputXRef && cmdName=="parblock")) - { - briefEndsAtDot=FALSE; - // this command forces the end of brief description - setOutput(OutputDoc); - } - //if (i>0) addOutput(QCString(yytext).left(i)); // removed for bug 689341 - if (cmdPtr->func && cmdPtr->func(cmdName, optList)) - { - // implicit split of the comment block into two - // entries. Restart the next block at the start - // of this command. - parseMore=TRUE; - - // yuk, this is probably not very portable across lex implementations, - // but we need to know the position in the input buffer where this - // rule matched. - // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE + yyextra->spaceBeforeCmd = QCString(yytext).left(i); + if (it->second.spacing==CommandSpacing::Block && !(yyextra->inContext==OutputXRef && cmdName=="parblock")) + { + yyextra->briefEndsAtDot=FALSE; + // this command forces the end of brief description + setOutput(yyscanner,OutputDoc); + } + //if (i>0) addOutput(yyscanner,QCString(yytext).left(i)); // removed for bug 689341 + if (it->second.handler && it->second.handler(yyscanner, cmdName, optList)) + { + // implicit split of the comment block into two + // entries. Restart the next block at the start + // of this command. + yyextra->parseMore=TRUE; + + // yuk, this is probably not very portable across lex implementations, + // but we need to know the position in the input buffer where this + // rule matched. + // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33)) - inputPosition=prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf); #else - inputPosition=prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf); #endif - yyterminate(); - } - else if (cmdPtr->func==0) - { - // command without handler, to be processed - // later by parsedoc.cpp - addOutput(yytext); - } - } - else // command not relevant - { - addOutput(yytext); - } - } -<Comment>{B}*({CMD}{CMD})"f"[$\[{] { // escaped formula command - addOutput(yytext); - } -<Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command + yyterminate(); + } + else if (it->second.handler==0) + { + // command without handler, to be processed + // later by parsedoc.cpp + addOutput(yyscanner,yytext); + } + } + else // command not relevant + { + addOutput(yyscanner,yytext); + } + } +<Comment>{B}*({CMD}{CMD})"f"[$\[{] { // escaped formula command + addOutput(yyscanner,yytext); + } +<Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command QCString langId = QCString(yytext).stripWhiteSpace().data()+2; - if (!langId.isEmpty() && - qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)!=0) - { // enable language specific section - BEGIN(SkipLang); - } - } + if (!langId.isEmpty() && + qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)!=0) + { // enable language specific section + BEGIN(SkipLang); + } + } <Comment>{B}*{CMD}"f{"[^}\n]+"}"("{"?) { // start of a formula with custom environment - setOutput(OutputDoc); - formulaText="\\begin"; - formulaEnv=QCString(yytext).stripWhiteSpace().data()+2; - if (formulaEnv.at(formulaEnv.length()-1)=='{') - { - // remove trailing open brace - formulaEnv=formulaEnv.left(formulaEnv.length()-1); - } - formulaText+=formulaEnv; - formulaNewLines=0; - BEGIN(ReadFormulaLong); - } -<Comment>{B}*{CMD}"f$" { // start of a inline formula - formulaText="$"; - formulaNewLines=0; - BEGIN(ReadFormulaShort); - } -<Comment>{B}*{CMD}"f[" { // start of a block formula - setOutput(OutputDoc); - formulaText="\\["; - formulaNewLines=0; - BEGIN(ReadFormulaLong); - } + setOutput(yyscanner,OutputDoc); + yyextra->formulaText="\\begin"; + yyextra->formulaEnv=QCString(yytext).stripWhiteSpace().data()+2; + if (yyextra->formulaEnv.at(yyextra->formulaEnv.length()-1)=='{') + { + // remove trailing open brace + yyextra->formulaEnv=yyextra->formulaEnv.left(yyextra->formulaEnv.length()-1); + } + yyextra->formulaText+=yyextra->formulaEnv; + yyextra->formulaNewLines=0; + BEGIN(ReadFormulaLong); + } +<Comment>{B}*{CMD}"f$" { // start of a inline formula + yyextra->formulaText="$"; + yyextra->formulaNewLines=0; + BEGIN(ReadFormulaShort); + } +<Comment>{B}*{CMD}"f[" { // start of a block formula + setOutput(yyscanner,OutputDoc); + yyextra->formulaText="\\["; + yyextra->formulaNewLines=0; + BEGIN(ReadFormulaLong); + } <Comment>{B}*{CMD}"{" { // begin of a group - //langParser->handleGroupStartCommand(g_memberGroupHeader); - Doxygen::docGroup.open(current,yyFileName,yyLineNr); + //yyextra->langParser->handleGroupStartCommand(yyextra->memberGroupHeader); + yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr); } <Comment>{B}*{CMD}"}" { // end of a group - //langParser->handleGroupEndCommand(); - Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE); - Doxygen::docGroup.clearHeader(); - parseMore=TRUE; - needNewEntry = TRUE; + //yyextra->langParser->handleGroupEndCommand(); + yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,TRUE); + yyextra->docGroup.clearHeader(); + yyextra->parseMore=TRUE; + yyextra->needNewEntry = TRUE; #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33)) - inputPosition=prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + strlen(yytext); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + (int)strlen(yytext); #else - inputPosition=prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf) + strlen(yytext); + yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf) + (int)strlen(yytext); #endif - yyterminate(); - } -<Comment>{B}*{CMD}[$@\\&~<>#%] { // escaped character - addOutput(yytext); - } -<Comment>[a-z_A-Z]+ { // normal word - addOutput(yytext); - } + yyterminate(); + } +<Comment>{B}*{CMD}[$@\\&~<>#%] { // escaped character + addOutput(yyscanner,yytext); + } +<Comment>[a-z_A-Z]+ { // normal word + addOutput(yyscanner,yytext); + } <Comment>^{B}*"."{B}*/\n { // explicit end autolist: e.g " ." - addOutput(yytext); - } + addOutput(yyscanner,yytext); + } <Comment>^{B}*[1-9][0-9]*"."{B}+ | -<Comment>^{B}*[*+]{B}+ { // start of autolist - if (!Doxygen::markdownSupport) +<Comment>^{B}*[*+]{B}+ { // start of autolist + if (!yyextra->markdownSupport) { REJECT; } else { - if (inContext!=OutputXRef) + if (yyextra->inContext!=OutputXRef) { - briefEndsAtDot=FALSE; - setOutput(OutputDoc); + yyextra->briefEndsAtDot=FALSE; + setOutput(yyscanner,OutputDoc); } - addOutput(yytext); + addOutput(yyscanner,yytext); } - } -<Comment>^{B}*"-"{B}+ { // start of autolist - if (inContext!=OutputXRef) - { - briefEndsAtDot=FALSE; - setOutput(OutputDoc); - } - addOutput(yytext); - } + } +<Comment>^{B}*"-"{B}+ { // start of autolist + if (yyextra->inContext!=OutputXRef) + { + yyextra->briefEndsAtDot=FALSE; + setOutput(yyscanner,OutputDoc); + } + addOutput(yyscanner,yytext); + } <Comment>^{B}*([\-:|]{B}*)*("--"|"---")({B}*[\-:|])*{B}*/\n { // horizontal line (dashed) - addOutput(yytext); + addOutput(yyscanner,yytext); } <Comment>{CMD}"---" { // escaped mdash - addOutput(yytext); + addOutput(yyscanner,yytext); } <Comment>{CMD}"--" { // escaped mdash - addOutput(yytext); + addOutput(yyscanner,yytext); } <Comment>"---" { // mdash - addOutput(insidePre || Doxygen::markdownSupport ? yytext : "—"); + addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "—"); } <Comment>"--" { // ndash - addOutput(insidePre || Doxygen::markdownSupport ? yytext : "–"); + addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "–"); } <Comment>"-#"{B}+ { // numbered item - if (inContext!=OutputXRef) + if (yyextra->inContext!=OutputXRef) { - briefEndsAtDot=FALSE; - setOutput(OutputDoc); + yyextra->briefEndsAtDot=FALSE; + setOutput(yyscanner,OutputDoc); } - addOutput(yytext); - } -<Comment>("."+)[a-z_A-Z0-9\)] { // . at start or in the middle of a word, or ellipsis - addOutput(yytext); - } -<Comment>".\\"[ \t] { // . with escaped space. - addOutput(yytext[0]); - addOutput(yytext[2]); - } -<Comment>".," { // . with comma such as "e.g.," - addOutput(yytext); - } -<Comment>"...\\"[ \t] { // ellipsis with escaped space. - addOutput("... "); - } -<Comment>".."[\.]?/[^ \t\n] { // internal ellipsis - addOutput(yytext); - } -<Comment>(\n|\\_linebr)({B}*(\n|\\_linebr))+ { // at least one blank line (or blank line command) - if (inContext==OutputXRef) - { - // see bug 613024, we need to put the newlines after ending the XRef section. - if (!g_insideParBlock) setOutput(OutputDoc); - int i; - for (i=0;i<yyleng;) + addOutput(yyscanner,yytext); + } +<Comment>("."+)[a-z_A-Z0-9\)] { // . at start or in the middle of a word, or ellipsis + addOutput(yyscanner,yytext); + } +<Comment>".\\"[ \t] { // . with escaped space. + addOutput(yyscanner,yytext[0]); + addOutput(yyscanner,yytext[2]); + } +<Comment>".," { // . with comma such as "e.g.," + addOutput(yyscanner,yytext); + } +<Comment>"...\\"[ \t] { // ellipsis with escaped space. + addOutput(yyscanner,"... "); + } +<Comment>".."[\.]?/[^ \t\n] { // internal ellipsis + addOutput(yyscanner,yytext); + } +<Comment>(\n|\\ilinebr)({B}*(\n|\\ilinebr))+ { // at least one blank line (or blank line command) + if (yyextra->inContext==OutputXRef) + { + // see bug 613024, we need to put the newlines after ending the XRef section. + if (!yyextra->insideParBlock) setOutput(yyscanner,OutputDoc); + yy_size_t i; + for (i=0;i<(yy_size_t)yyleng;) { - if (yytext[i]=='\n') addOutput('\n'),i++; - else if (strcmp(yytext+i,"\\_linebr")==0) addOutput('\n'),i+=8; + if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++; + else if (strcmp(yytext+i,"\\ilinebr")==0) addOutput(yyscanner,"\\ilinebr"),i+=8; else i++; } - } - else if (inContext!=OutputBrief) - { - int i; - for (i=0;i<yyleng;) + } + else if (yyextra->inContext!=OutputBrief) + { + yy_size_t i; + for (i=0;i<(yy_size_t)yyleng;) { - if (yytext[i]=='\n') addOutput('\n'),i++; - else if (strcmp(yytext+i,"\\_linebr")==0) addOutput('\n'),i+=8; + if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++; + else if (strcmp(yytext+i,"\\ilinebr")==0) addOutput(yyscanner,"\\ilinebr"),i+=8; else i++; } - setOutput(OutputDoc); - } - else // inContext==OutputBrief - { // only go to the detailed description if we have - // found some brief description and not just whitespace - endBrief(FALSE); - } - lineCount(); - } -<Comment>"." { // potential end of a JavaDoc style comment - addOutput(*yytext); - if (briefEndsAtDot) - { - setOutput(OutputDoc); - briefEndsAtDot=FALSE; - } - } -<Comment>\n { // newline - addOutput(*yytext); - yyLineNr++; - } -<Comment>. { // catch-all for anything else - addOutput(*yytext); - } + setOutput(yyscanner,OutputDoc); + } + else // yyextra->inContext==OutputBrief + { // only go to the detailed description if we have + // found some brief description and not just whitespace + endBrief(yyscanner,TRUE); + } + lineCount(yyscanner); + } +<Comment>"." { // potential end of a JavaDoc style comment + addOutput(yyscanner,*yytext); + if (yyextra->briefEndsAtDot) + { + setOutput(yyscanner,OutputDoc); + yyextra->briefEndsAtDot=FALSE; + } + } +<Comment>\n { // newline + addOutput(yyscanner,*yytext); + yyextra->lineNr++; + } +<Comment>. { // catch-all for anything else + addOutput(yyscanner,*yytext); + } /* -------------- Rules for handling HTML comments ----------- */ -<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); } -<HtmlComment>{DOCNL} { - if (*yytext=='\n') yyLineNr++; - } -<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters - } -<HtmlComment>. { // ignore every else - } +<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); } +<HtmlComment>{DOCNL} { + if (*yytext=='\n') yyextra->lineNr++; + } +<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters + } +<HtmlComment>. { // ignore every else + } <CdataSection>"\]\]>" { BEGIN( Comment ); } -<CdataSection>{DOCNL} { - addOutput('\n'); - if (*yytext=='\n') yyLineNr++; +<CdataSection>{DOCNL} { + addOutput(yyscanner,'\n'); + if (*yytext=='\n') yyextra->lineNr++; } <CdataSection>[<>&] { // the special XML characters for iwhich the CDATA section is especially used - addOutput('\\'); - addOutput(*yytext); + addOutput(yyscanner,'\\'); + addOutput(yyscanner,*yytext); } <CdataSection>[^\\\n\]<>&]+ { - addOutput(yytext); + addOutput(yyscanner,yytext); } -<CdataSection>. { - addOutput(*yytext); +<CdataSection>. { + addOutput(yyscanner,*yytext); } /* -------------- Rules for handling formulas ---------------- */ - -<ReadFormulaShort>{CMD}"f$" { // end of inline formula - formulaText+="$"; - addOutput(" "+addFormula()); - BEGIN(Comment); - } -<ReadFormulaLong>{CMD}"f]" { // end of block formula - formulaText+="\\]"; - addOutput(" "+addFormula()); - BEGIN(Comment); - } -<ReadFormulaLong>{CMD}"f}" { // end of custom env formula - formulaText+="\\end"; - formulaText+=formulaEnv; - addOutput(" "+addFormula()); - BEGIN(Comment); - } + +<ReadFormulaShort>{CMD}"f$" { // end of inline formula + yyextra->formulaText+="$"; + addOutput(yyscanner," "+addFormula(yyscanner)); + BEGIN(Comment); + } +<ReadFormulaLong>{CMD}"f]" { // end of block formula + yyextra->formulaText+="\\]"; + addOutput(yyscanner," "+addFormula(yyscanner)); + BEGIN(Comment); + } +<ReadFormulaLong>{CMD}"f}" { // end of custom env formula + yyextra->formulaText+="\\end"; + yyextra->formulaText+=yyextra->formulaEnv; + addOutput(yyscanner," "+addFormula(yyscanner)); + BEGIN(Comment); + } <ReadFormulaLong,ReadFormulaShort>[^\\@\n]+ { // any non-special character - formulaText+=yytext; - } -<ReadFormulaLong,ReadFormulaShort>\n { // new line - formulaNewLines++; - formulaText+=*yytext; - yyLineNr++; - } + yyextra->formulaText+=yytext; + } +<ReadFormulaLong,ReadFormulaShort>\n { // new line + yyextra->formulaNewLines++; + yyextra->formulaText+=*yytext; + yyextra->lineNr++; + } <ReadFormulaLong,ReadFormulaShort>. { // any other character - formulaText+=*yytext; - } + yyextra->formulaText+=*yytext; + } /* ------------ handle argument of enum command --------------- */ -<EnumDocArg1>{SCOPEID} { // handle argument - current->name = yytext; - BEGIN( Comment ); - } -<EnumDocArg1>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); +<EnumDocArg1>{SCOPEID} { // handle argument + yyextra->current->name = yytext; + BEGIN( Comment ); + } +<EnumDocArg1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<EnumDocArg1>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, +<EnumDocArg1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, "missing argument after \\enum." ); - addOutput('\n'); - if (*yytext=='\n') yyLineNr++; - BEGIN( Comment ); - } -<EnumDocArg1>. { // ignore other stuff - } + unput('\n'); + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<EnumDocArg1>. { // ignore other stuff + } /* ------------ handle argument of namespace command --------------- */ -<NameSpaceDocArg1>{SCOPENAME} { // handle argument - current->name = substitute(yytext,".","::"); - BEGIN( Comment ); - } -<NameSpaceDocArg1>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); +<NameSpaceDocArg1>{SCOPENAME} { // handle argument + yyextra->current->name = substitute(yytext,".","::"); + BEGIN( Comment ); + } +<NameSpaceDocArg1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<NameSpaceDocArg1>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, +<NameSpaceDocArg1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\namespace." + "\\namespace." ); - addOutput('\n'); - if (*yytext=='\n') yyLineNr++; - BEGIN( Comment ); - } -<NameSpaceDocArg1>. { // ignore other stuff - } + unput('\n'); + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<NameSpaceDocArg1>. { // ignore other stuff + } /* ------------ handle argument of package command --------------- */ -<PackageDocArg1>{ID}("."{ID})* { // handle argument - current->name = yytext; - BEGIN( Comment ); - } -<PackageDocArg1>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); +<PackageDocArg1>{ID}("."{ID})* { // handle argument + yyextra->current->name = yytext; + BEGIN( Comment ); } -<PackageDocArg1>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, +<PackageDocArg1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<PackageDocArg1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\package." + "\\package." ); - addOutput('\n'); - if (*yytext=='\n') yyLineNr++; - BEGIN( Comment ); - } -<PackageDocArg1>. { // ignore other stuff - } + unput('\n'); + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + BEGIN( Comment ); + } +<PackageDocArg1>. { // ignore other stuff + } /* ------ handle argument of class/struct/union command --------------- */ -<ClassDocArg1>{SCOPENAME}{TMPLSPEC} { - current->name = substitute(removeRedundantWhiteSpace(yytext),".","::"); - BEGIN( ClassDocArg2 ); - } -<ClassDocArg1>{SCOPENAME} { // first argument - current->name = substitute(yytext,".","::"); - if (current->section==Entry::PROTOCOLDOC_SEC) - { - current->name+="-p"; - } - // prepend outer scope name - BEGIN( ClassDocArg2 ); - } +<ClassDocArg1>{SCOPENAME}{TMPLSPEC} { + yyextra->current->name = substitute(removeRedundantWhiteSpace(yytext),".","::"); + BEGIN( ClassDocArg2 ); + } +<ClassDocArg1>{SCOPENAME} { // first argument + yyextra->current->name = substitute(yytext,".","::"); + if (yyextra->current->section==Entry::PROTOCOLDOC_SEC) + { + yyextra->current->name+="-p"; + } + // prepend outer scope name + BEGIN( ClassDocArg2 ); + } <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" { - current->name = substitute(yytext,".","::"); - BEGIN( ClassDocArg2 ); - } + yyextra->current->name = substitute(yytext,".","::"); + BEGIN( ClassDocArg2 ); + } <ClassDocArg1,CategoryDocArg1>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); + yyextra->lineNr++; + addOutput(yyscanner,'\n'); } -<ClassDocArg1,CategoryDocArg1>{DOCNL} { - warn(yyFileName,yyLineNr, +<ClassDocArg1,CategoryDocArg1>{DOCNL} { + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\%s.",YY_START==ClassDocArg1?"class":"category" + "'\\%s'.",yyextra->currentCmd.data() ); - addOutput('\n'); - if (*yytext=='\n') yyLineNr++; - BEGIN( Comment ); - } -<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff - } - -<ClassDocArg2>{FILE}|"<>" { // second argument; include file - current->includeFile = yytext; - BEGIN( ClassDocArg3 ); - } -<ClassDocArg2>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<ClassDocArg2>{DOCNL} { - addOutput('\n'); - if (*yytext=='\n') yyLineNr++; - BEGIN( Comment ); - } -<ClassDocArg2>. { // ignore other stuff - } - -<ClassDocArg3>[<"]?{FILE}?[">]? { // third argument; include file name - current->includeName = yytext; - BEGIN( Comment ); - } -<ClassDocArg3>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<ClassDocArg3>{DOCNL} { - if (*yytext=='\n') yyLineNr++; - BEGIN( Comment ); - } -<ClassDocArg3>. { // ignore other stuff - } + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + unput('\n'); + BEGIN( Comment ); + } +<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff + } + +<ClassDocArg2>{FILE}|"<>" { // second argument; include file + yyextra->current->includeFile = yytext; + BEGIN( ClassDocArg3 ); + } +<ClassDocArg2>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<ClassDocArg2>{DOCNL} { + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + unput('\n'); + BEGIN( Comment ); + } +<ClassDocArg2>. { // ignore other stuff + } + +<ClassDocArg3>[<"]?{FILE}?[">]? { // third argument; include file name + yyextra->current->includeName = yytext; + BEGIN( Comment ); + } +<ClassDocArg3>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<ClassDocArg3>{DOCNL} { + //if (*yytext=='\n') yyextra->lineNr++; + unput('\n'); + BEGIN( Comment ); + } +<ClassDocArg3>. { // ignore other stuff + } /* --------- handle arguments of {def,add,weak}group commands --------- */ -<GroupDocArg1>{LABELID}(".html"?) { // group name - current->name = yytext; - //lastDefGroup.groupname = yytext; - //lastDefGroup.pri = current->groupingPri(); - // the .html stuff is for Qt compatibility - if (current->name.right(5)==".html") - { - current->name=current->name.left(current->name.length()-5); - } - current->type.resize(0); - BEGIN(GroupDocArg2); - } -<GroupDocArg1>"\\"{B}*"\n" { // line continuation - yyLineNr++; - addOutput('\n'); - } -<GroupDocArg1>{DOCNL} { // missing argument! - warn(yyFileName,yyLineNr, +<GroupDocArg1>{LABELID}(".html"?) { // group name + yyextra->current->name = yytext; + //lastDefGroup.groupname = yytext; + //lastDefGroup.pri = yyextra->current->groupingPri(); + // the .html stuff is for Qt compatibility + if (yyextra->current->name.right(5)==".html") + { + yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-5); + } + yyextra->current->type.resize(0); + BEGIN(GroupDocArg2); + } +<GroupDocArg1>"\\"{B}*"\n" { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<GroupDocArg1>{DOCNL} { // missing argument! + warn(yyextra->fileName,yyextra->lineNr, "missing group name after %s", - current->groupDocCmd() + yyextra->current->groupDocCmd() ); - addOutput('\n'); - if (*yytext=='\n') yyLineNr++; - BEGIN( Comment ); - } -<GroupDocArg1>. { // ignore other stuff - } -<GroupDocArg2>"\\"{B}*"\n" { // line continuation - yyLineNr++; - addOutput('\n'); - } -<GroupDocArg2>[^\n\\]+ { // title (stored in type) - current->type += yytext; - current->type = current->type.stripWhiteSpace(); - } -<GroupDocArg2>{DOCNL} { - if ( current->groupDocType==Entry::GROUPDOC_NORMAL && - current->type.isEmpty() - ) // defgroup requires second argument - { - warn(yyFileName,yyLineNr, + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + unput('\n'); + BEGIN( Comment ); + } +<GroupDocArg1>. { // ignore other stuff + } +<GroupDocArg2>"\\"{B}*"\n" { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<GroupDocArg2>[^\n\\]+ { // title (stored in type) + yyextra->current->type += yytext; + yyextra->current->type = yyextra->current->type.stripWhiteSpace(); + } +<GroupDocArg2>{DOCNL} { + if ( yyextra->current->groupDocType==Entry::GROUPDOC_NORMAL && + yyextra->current->type.isEmpty() + ) // defgroup requires second argument + { + warn(yyextra->fileName,yyextra->lineNr, "missing title after " - "\\defgroup %s", current->name.data() + "\\defgroup %s", yyextra->current->name.data() ); - } - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } + } + unput('\n'); + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } <GroupDocArg2>. { // title (stored in type) - current->type += yytext; - current->type = current->type.stripWhiteSpace(); + yyextra->current->type += yytext; + yyextra->current->type = yyextra->current->type.stripWhiteSpace(); } /* --------- handle arguments of page/mainpage command ------------------- */ -<PageDocArg1>{FILE} { // first argument; page name - current->name = stripQuotes(yytext); - current->args = ""; - BEGIN( PageDocArg2 ); - } -<PageDocArg1>{LC} { yyLineNr++; - addOutput('\n'); +<PageDocArg1>{FILE} { // first argument; page name + yyextra->current->name = stripQuotes(yytext); + yyextra->current->args = ""; + BEGIN( PageDocArg2 ); } -<PageDocArg1>{DOCNL} { - warn(yyFileName,yyLineNr, +<PageDocArg1>{LC} { yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<PageDocArg1>{DOCNL} { + warn(yyextra->fileName,yyextra->lineNr, "missing argument after " - "\\page." + "\\page." ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<PageDocArg1>. { // ignore other stuff - } -<PageDocArg2>{DOCNL} { // second argument; page title - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<PageDocArg2>{CMD}[<>] { - // bug 748927 - QCString tmp = yytext; - tmp = substitute(substitute(tmp,"@<","<"),"@>",">"); - tmp = substitute(substitute(tmp,"\\<","<"),"\\>",">"); - current->args += tmp; - } -<PageDocArg2>. { - current->args += yytext; + unput('\n'); + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<PageDocArg1>. { // ignore other stuff + } +<PageDocArg2>{DOCNL} { // second argument; page title + unput('\n'); + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<PageDocArg2>{CMD}[<>] { + // bug 748927 + QCString tmp = yytext; + tmp = substitute(substitute(tmp,"@<","<"),"@>",">"); + tmp = substitute(substitute(tmp,"\\<","<"),"\\>",">"); + yyextra->current->args += tmp; + } +<PageDocArg2>. { + yyextra->current->args += yytext; } /* --------- handle arguments of the param command ------------ */ <ParamArg1>{ID}/{B}*"," { - addOutput(yytext); + addOutput(yyscanner,yytext); } <ParamArg1>"," { - addOutput(" , "); + addOutput(yyscanner," , "); } <ParamArg1>{ID} { - addOutput(yytext); + addOutput(yyscanner,yytext); BEGIN( Comment ); } <ParamArg1>. { @@ -1640,879 +1190,917 @@ RCSTAG "$"{ID}":"[^\n$]+"$" /* --------- handle arguments of the file/dir/example command ------------ */ -<FileDocArg1>{DOCNL} { // no file name specified - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<FileDocArg1>{FILE} { // first argument; name - current->name = stripQuotes(yytext); - BEGIN( Comment ); - } -<FileDocArg1>{LC} { yyLineNr++; - addOutput('\n'); - } -<FileDocArg1>. { // ignore other stuff - } +<FileDocArg1>{DOCNL} { // no file name specified + unput('\n'); + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<FileDocArg1>{FILE} { // first argument; name + yyextra->current->name = stripQuotes(yytext); + BEGIN( Comment ); + } +<FileDocArg1>{LC} { yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<FileDocArg1>. { // ignore other stuff + } /* --------- handle arguments of the xrefitem command ------------ */ -<XRefItemParam1>{LABELID} { // first argument - newXRefItemKey=yytext; - setOutput(OutputXRef); - BEGIN(XRefItemParam2); - } -<XRefItemParam1>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<XRefItemParam1>{DOCNL} { // missing arguments - warn(yyFileName,yyLineNr, - "Missing first argument of \\xrefitem" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - inContext = OutputDoc; - BEGIN( Comment ); - } -<XRefItemParam1>. { // ignore other stuff - } - -<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument - xrefItemTitle = stripQuotes(yytext); - BEGIN(XRefItemParam3); - } -<XRefItemParam2>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<XRefItemParam2>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "Missing second argument of \\xrefitem" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - inContext = OutputDoc; - BEGIN( Comment ); - } -<XRefItemParam2>. { // ignore other stuff - } - -<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument - xrefListTitle = stripQuotes(yytext); - xrefKind = XRef_Item; - BEGIN( Comment ); - } -<XRefItemParam2,XRefItemParam3>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<XRefItemParam3>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "Missing third argument of \\xrefitem" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - inContext = OutputDoc; - BEGIN( Comment ); - } -<XRefItemParam3>. { // ignore other stuff - } +<XRefItemParam1>{LABELID} { // first argument + yyextra->newXRefItemKey=yytext; + setOutput(yyscanner,OutputXRef); + BEGIN(XRefItemParam2); + } +<XRefItemParam1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<XRefItemParam1>{DOCNL} { // missing arguments + warn(yyextra->fileName,yyextra->lineNr, + "Missing first argument of \\xrefitem" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam1>. { // ignore other stuff + } + +<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument + yyextra->xrefItemTitle = stripQuotes(yytext); + BEGIN(XRefItemParam3); + } +<XRefItemParam2>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<XRefItemParam2>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "Missing second argument of \\xrefitem" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam2>. { // ignore other stuff + } + +<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument + yyextra->xrefListTitle = stripQuotes(yytext); + yyextra->xrefKind = XRef_Item; + BEGIN( Comment ); + } +<XRefItemParam2,XRefItemParam3>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<XRefItemParam3>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "Missing third argument of \\xrefitem" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->inContext = OutputDoc; + BEGIN( Comment ); + } +<XRefItemParam3>. { // ignore other stuff + } /* ----- handle arguments of the relates(also)/memberof command ------- */ -<RelatesParam1>({ID}("::"|"."))*{ID} { // argument - current->relates = yytext; - //if (current->mGrpId!=DOX_NOGROUP) +<RelatesParam1>({ID}("::"|"."))*{ID} { // argument + yyextra->current->relates = yytext; + //if (yyextra->current->mGrpId!=DOX_NOGROUP) //{ // memberGroupRelates = yytext; //} - BEGIN( Comment ); - } -<RelatesParam1>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<RelatesParam1>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "Missing argument of \\relates or \\memberof command" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<RelatesParam1>. { // ignore other stuff - } + BEGIN( Comment ); + } +<RelatesParam1>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<RelatesParam1>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "Missing argument of '\\%s' command",yyextra->currentCmd.data() + ); + unput('\n'); + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<RelatesParam1>. { // ignore other stuff + } /* ----- handle arguments of the relates(also)/addindex commands ----- */ -<LineParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<LineParam>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<LineParam>. { // ignore other stuff - addOutput(*yytext); - } +<LineParam>{DOCNL} { // end of argument + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + unput('\n'); + BEGIN( Comment ); + } +<LineParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<LineParam>. { // ignore other stuff + addOutput(yyscanner,*yytext); + } /* ----- handle arguments of the section/subsection/.. commands ------- */ -<SectionLabel>{LABELID} { // first argument - g_sectionLabel=yytext; - addOutput(yytext); - g_sectionTitle.resize(0); - BEGIN(SectionTitle); - } -<SectionLabel>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "\\section command has no label" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<SectionLabel>. { // invalid character for section label - warn(yyFileName,yyLineNr, - "Invalid or missing section label" - ); - BEGIN(Comment); - } +<SectionLabel>{LABELID} { // first argument + yyextra->sectionLabel=yytext; + addOutput(yyscanner,yytext); + yyextra->sectionTitle.resize(0); + BEGIN(SectionTitle); + } +<SectionLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\section command has no label" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<SectionLabel>. { // invalid character for section label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing section label" + ); + BEGIN(Comment); + } <SectionTitle>[^\n@\\*]*/"\n" { // end of section title - addSection(); - addOutput(yytext); - BEGIN( Comment ); - } -<SectionTitle>[^\n@\\]*/"\\_linebr" { // end of section title - addSection(); - addOutput(yytext); - BEGIN( Comment ); - } -<SectionTitle>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<SectionTitle>[^\n@\\]* { // any character without special meaning - g_sectionTitle+=yytext; - addOutput(yytext); - } -<SectionTitle>({CMD}{CMD}){ID} { // unescape escaped command - g_sectionTitle+=&yytext[1]; - addOutput(yytext); - } -<SectionTitle>{CMD}[$@\\&~<>#%] { // unescape escaped character - g_sectionTitle+=yytext[1]; - addOutput(yytext); - } -<SectionTitle>. { // anything else - g_sectionTitle+=yytext; - addOutput(*yytext); - } + addSection(yyscanner); + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<SectionTitle>[^\n@\\]*/"\\ilinebr" { // end of section title + addSection(yyscanner); + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<SectionTitle>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<SectionTitle>[^\n@\\]* { // any character without special meaning + yyextra->sectionTitle+=yytext; + addOutput(yyscanner,yytext); + } +<SectionTitle>({CMD}{CMD}){ID} { // unescape escaped command + yyextra->sectionTitle+=&yytext[1]; + addOutput(yyscanner,yytext); + } +<SectionTitle>{CMD}[$@\\&~<>#%] { // unescape escaped character + yyextra->sectionTitle+=yytext[1]; + addOutput(yyscanner,yytext); + } +<SectionTitle>. { // anything else + yyextra->sectionTitle+=yytext; + addOutput(yyscanner,*yytext); + } /* ----- handle arguments of the subpage command ------- */ -<SubpageLabel>{LABELID} { // first argument - addOutput(yytext); - // we add subpage labels as a kind of "inheritance" relation to prevent - // needing to add another list to the Entry class. - current->extends.push_back(BaseInfo(yytext,Public,Normal)); - BEGIN(SubpageTitle); - } -<SubpageLabel>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "\\subpage command has no label" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<SubpageTitle>{DOCNL} { // no title, end command - addOutput(yytext); - BEGIN( Comment ); - } -<SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command - addOutput(yytext); - BEGIN( Comment ); - } -<SubpageTitle>. { // no title, end of command - unput(*yytext); - BEGIN( Comment ); - } +<SubpageLabel>{LABELID} { // first argument + addOutput(yyscanner,yytext); + // we add subpage labels as a kind of "inheritance" relation to prevent + // needing to add another list to the Entry class. + yyextra->current->extends.push_back(BaseInfo(yytext,Public,Normal)); + BEGIN(SubpageTitle); + } +<SubpageLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\subpage command has no label" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<SubpageTitle>{DOCNL} { // no title, end command + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<SubpageTitle>. { // no title, end of command + unput(*yytext); + BEGIN( Comment ); + } /* ----- handle arguments of the anchor command ------- */ -<AnchorLabel>{LABELID} { // found argument - addAnchor(yytext); - addOutput(yytext); - BEGIN( Comment ); - } -<AnchorLabel>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "\\anchor command has no label" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<AnchorLabel>. { // invalid character for anchor label - warn(yyFileName,yyLineNr, - "Invalid or missing anchor label" - ); - BEGIN(Comment); - } +<AnchorLabel>{LABELID} { // found argument + addAnchor(yyscanner,yytext); + addOutput(yyscanner,yytext); + BEGIN( Comment ); + } +<AnchorLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\anchor command has no label" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<AnchorLabel>. { // invalid character for anchor label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing anchor label" + ); + BEGIN(Comment); + } /* ----- handle arguments of the preformatted block commands ------- */ <FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc"|"endvhdlflow")/{NW} { // possible ends - addOutput(yytext); - if (&yytext[4]==blockName) // found end of the block - { - BEGIN(Comment); - } - } + addOutput(yyscanner,yytext); + if (&yytext[4]==yyextra->blockName) // found end of the block + { + BEGIN(Comment); + } + } <FormatBlock>{CMD}"enduml" { - addOutput(yytext); - if (blockName=="startuml") // found end of the block - { - BEGIN(Comment); - } - } -<FormatBlock>[^ \@\*\/\\\n]* { // some word - addOutput(yytext); - } -<FormatBlock>{DOCNL} { // new line - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - } -<FormatBlock>"/*" { // start of a C-comment - if (!(blockName=="code" || blockName=="verbatim")) g_commentCount++; - addOutput(yytext); - } -<FormatBlock>"*/" { // end of a C-comment - addOutput(yytext); - if (!(blockName=="code" || blockName=="verbatim")) + addOutput(yyscanner,yytext); + if (yyextra->blockName=="startuml") // found end of the block { - g_commentCount--; - if (g_commentCount<0) - { - warn(yyFileName,yyLineNr, - "found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",blockName.data(),blockName.data()); - } - } - } -<FormatBlock>. { - addOutput(*yytext); - } -<FormatBlock><<EOF>> { - QCString endTag = "end"+blockName; - if (blockName=="startuml") endTag="enduml"; - warn(yyFileName,yyLineNr, - "reached end of comment while inside a \\%s block; check for missing \\%s tag!", - blockName.data(),endTag.data() - ); - yyterminate(); - } + BEGIN(Comment); + } + } +<FormatBlock>[^ \@\*\/\\\n]* { // some word + addOutput(yyscanner,yytext); + } +<FormatBlock>{DOCNL} { // new line + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<FormatBlock>"/*" { // start of a C-comment + if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) yyextra->commentCount++; + addOutput(yyscanner,yytext); + } +<FormatBlock>"*/" { // end of a C-comment + addOutput(yyscanner,yytext); + if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) + { + yyextra->commentCount--; + if (yyextra->commentCount<0) + { + warn(yyextra->fileName,yyextra->lineNr, + "found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",yyextra->blockName.data(),yyextra->blockName.data()); + } + } + } +<FormatBlock>. { + addOutput(yyscanner,*yytext); + } +<FormatBlock><<EOF>> { + QCString endTag = "end"+yyextra->blockName; + if (yyextra->blockName=="startuml") endTag="enduml"; + warn(yyextra->fileName,yyextra->lineNr, + "reached end of comment while inside a \\%s block; check for missing \\%s tag!", + yyextra->blockName.data(),endTag.data() + ); + yyterminate(); + } /* ----- handle arguments of if/ifnot commands ------- */ -<GuardParam>{B}*"(" { - g_guardExpr=yytext; - g_roundCount=1; +<GuardParam>{B}*"(" { + yyextra->guardExpr=yytext; + yyextra->roundCount=1; BEGIN(GuardExpr); } <GuardExpr>[^()]* { - g_guardExpr+=yytext; + yyextra->guardExpr+=yytext; } <GuardExpr>"(" { - g_guardExpr+=yytext; - g_roundCount++; + yyextra->guardExpr+=yytext; + yyextra->roundCount++; } <GuardExpr>")" { - g_guardExpr+=yytext; - g_roundCount--; - if (g_roundCount==0) + yyextra->guardExpr+=yytext; + yyextra->roundCount--; + if (yyextra->roundCount==0) { - handleGuard(g_guardExpr); + handleGuard(yyscanner,yyextra->guardExpr); } } <GuardExpr>\n { - warn(yyFileName,yyLineNr, - "invalid expression '%s' for guard",g_guardExpr.data()); + warn(yyextra->fileName,yyextra->lineNr, + "invalid expression '%s' for yyextra->guards",yyextra->guardExpr.data()); unput(*yytext); BEGIN(GuardParam); } -<GuardParam>{B}*[a-z_A-Z0-9.\-]+ { // parameter of if/ifnot guard - handleGuard(yytext); - } -<GuardParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyLineNr++; - //next line is commented out due to bug620924 - //addOutput('\n'); - BEGIN( Comment ); - } -<GuardParam>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<GuardParam>. { // ignore other stuff - addOutput(*yytext); - } -<GuardParamEnd>{B}*{DOCNL} { - lineCount(); - g_spaceBeforeIf.resize(0); - BEGIN(Comment); - } -<GuardParamEnd>{B}* { - if (!g_spaceBeforeIf.isEmpty()) // needed for 665313 in combination with bug620924 - { - addOutput(g_spaceBeforeIf); - } - g_spaceBeforeIf.resize(0); - BEGIN(Comment); - } -<GuardParamEnd>. { - unput(*yytext); - BEGIN(Comment); - } +<GuardParam>{B}*[a-z_A-Z0-9.\-]+ { // parameter of if/ifnot yyextra->guards + handleGuard(yyscanner,yytext); + } +<GuardParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + //next line is commented out due to bug620924 + //addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<GuardParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<GuardParam>. { // ignore other stuff + addOutput(yyscanner,*yytext); + } +<GuardParamEnd>{B}*{DOCNL} { + lineCount(yyscanner); + yyextra->spaceBeforeIf.resize(0); + BEGIN(Comment); + } +<GuardParamEnd>{B}* { + if (!yyextra->spaceBeforeIf.isEmpty()) // needed for 665313 in combination with bug620924 + { + addOutput(yyscanner,yyextra->spaceBeforeIf); + } + yyextra->spaceBeforeIf.resize(0); + BEGIN(Comment); + } +<GuardParamEnd>. { + unput(*yytext); + BEGIN(Comment); + } /* ----- handle skipping of conditional sections ------- */ -<SkipGuardedSection>{CMD}"ifnot"/{NW} { - guardType = Guard_IfNot; - BEGIN( GuardParam ); - } -<SkipGuardedSection>{CMD}"if"/{NW} { - guardType = Guard_If; - BEGIN( GuardParam ); - } -<SkipGuardedSection>{CMD}"endif"/{NW} { - if (guards.isEmpty()) - { - warn(yyFileName,yyLineNr, - "found \\endif without matching start command"); - } - else - { - GuardedSection *s = guards.pop(); - bool parentVisible = s->parentVisible(); - delete s; +<SkipGuardedSection>{CMD}"ifnot"/{NW} { + yyextra->guardType = Guard_IfNot; + BEGIN( GuardParam ); + } +<SkipGuardedSection>{CMD}"if"/{NW} { + yyextra->guardType = Guard_If; + BEGIN( GuardParam ); + } +<SkipGuardedSection>{CMD}"endif"/{NW} { + if (yyextra->guards.empty()) + { + warn(yyextra->fileName,yyextra->lineNr, + "found \\endif without matching start command"); + } + else + { + GuardedSection s = yyextra->guards.top(); + yyextra->guards.pop(); + bool parentVisible = s.parentVisible(); if (parentVisible) { - enabledSectionFound=TRUE; - BEGIN( GuardParamEnd ); + yyextra->enabledSectionFound=TRUE; + BEGIN( GuardParamEnd ); } - } - } -<SkipGuardedSection>{CMD}"else"/{NW} { - if (guards.isEmpty()) - { - warn(yyFileName,yyLineNr, - "found \\else without matching start command"); - } - else - { - if (!enabledSectionFound && guards.top()->parentVisible()) - { - delete guards.pop(); - guards.push(new GuardedSection(TRUE,TRUE)); - enabledSectionFound=TRUE; - BEGIN( GuardParamEnd ); - } - } - } + } + } +<SkipGuardedSection>{CMD}"else"/{NW} { + if (yyextra->guards.empty()) + { + warn(yyextra->fileName,yyextra->lineNr, + "found \\else without matching start command"); + } + else + { + if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible()) + { + yyextra->guards.pop(); + yyextra->guards.push(GuardedSection(TRUE,TRUE)); + yyextra->enabledSectionFound=TRUE; + BEGIN( GuardParamEnd ); + } + } + } <SkipGuardedSection>{CMD}"elseif"/{NW} { - if (guards.isEmpty()) - { - warn(yyFileName,yyLineNr, - "found \\elseif without matching start command"); - } - else - { - if (!enabledSectionFound && guards.top()->parentVisible()) - { - guardType=Guard_If; - delete guards.pop(); - BEGIN( GuardParam ); - } - } - } -<SkipGuardedSection>{DOCNL} { // skip line - if (*yytext=='\n') yyLineNr++; - //addOutput('\n'); - } -<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters - } -<SkipGuardedSection>. { // any other character - } + if (yyextra->guards.empty()) + { + warn(yyextra->fileName,yyextra->lineNr, + "found \\elseif without matching start command"); + } + else + { + if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible()) + { + yyextra->guardType=Guard_If; + yyextra->guards.pop(); + BEGIN( GuardParam ); + } + } + } +<SkipGuardedSection>{DOCNL} { // skip line + if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + } +<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters + } +<SkipGuardedSection>. { // any other character + } /* ----- handle skipping of internal section ------- */ -<SkipInternal>{DOCNL} { // skip line - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - } -<SkipInternal>[@\\]"if"/[ \t] { - g_condCount++; - } -<SkipInternal>[@\\]"ifnot"/[ \t] { - g_condCount++; - } -<SkipInternal>[@\\]/"endif" { - g_condCount--; - if (g_condCount<0) // handle conditional section around of \internal, see bug607743 - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"section"[ \t] { - if (g_sectionLevel>0) - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"subsection"[ \t] { - if (g_sectionLevel>1) - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"subsubsection"[ \t] { - if (g_sectionLevel>2) - { - unput('\\'); - BEGIN(Comment); - } - } -<SkipInternal>[@\\]/"paragraph"[ \t] { - if (g_sectionLevel>3) - { - unput('\\'); - BEGIN(Comment); - } - } +<SkipInternal>{DOCNL} { // skip line + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<SkipInternal>[@\\]"if"/[ \t] { + yyextra->condCount++; + } +<SkipInternal>[@\\]"ifnot"/[ \t] { + yyextra->condCount++; + } +<SkipInternal>[@\\]/"endif" { + yyextra->condCount--; + if (yyextra->condCount<0) // handle conditional section around of \internal, see bug607743 + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"section"[ \t] { + if (yyextra->sectionLevel>0) + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"subsection"[ \t] { + if (yyextra->sectionLevel>1) + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"subsubsection"[ \t] { + if (yyextra->sectionLevel>2) + { + unput('\\'); + BEGIN(Comment); + } + } +<SkipInternal>[@\\]/"paragraph"[ \t] { + if (yyextra->sectionLevel>3) + { + unput('\\'); + BEGIN(Comment); + } + } <SkipInternal>[@\\]"endinternal"[ \t]* { - BEGIN(Comment); - } -<SkipInternal>[^ \\@\n]+ { // skip non-special characters - } -<SkipInternal>. { // any other character - } + BEGIN(Comment); + } +<SkipInternal>[^ \\@\n]+ { // skip non-special characters + } +<SkipInternal>. { // any other character + } /* ----- handle argument of name command ------- */ -<NameParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<NameParam>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - Doxygen::docGroup.appendHeader(' '); - } -<NameParam>. { // ignore other stuff - Doxygen::docGroup.appendHeader(*yytext); - current->name+=*yytext; - } +<NameParam>{DOCNL} { // end of argument + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + unput('\n'); + BEGIN( Comment ); + } +<NameParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + yyextra->docGroup.appendHeader(' '); + } +<NameParam>. { // ignore other stuff + yyextra->docGroup.appendHeader(*yytext); + yyextra->current->name+=*yytext; + } /* ----- handle argument of noop command ------- */ -<Noop>{DOCNL} { // end of argument - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<Noop>. { // ignore other stuff - } +<Noop>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<Noop>. { // ignore other stuff + } /* ----- handle argument of ingroup command ------- */ -<InGroupParam>{LABELID} { // group id - current->groups.push_back( - Grouping(yytext, Grouping::GROUPING_INGROUP) - ); - inGroupParamFound=TRUE; - } -<InGroupParam>{DOCNL} { // missing argument - if (!inGroupParamFound) - { - warn(yyFileName,yyLineNr, - "Missing group name for \\ingroup command" - ); - } - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<InGroupParam>{LC} { // line continuation - yyLineNr++; - addOutput('\n'); - } -<InGroupParam>. { // ignore other stuff - addOutput(*yytext); - } +<InGroupParam>{LABELID} { // group id + yyextra->current->groups.push_back( + Grouping(yytext, Grouping::GROUPING_INGROUP) + ); + yyextra->inGroupParamFound=TRUE; + } +<InGroupParam>{DOCNL} { // missing argument + if (!yyextra->inGroupParamFound) + { + warn(yyextra->fileName,yyextra->lineNr, + "Missing group name for \\ingroup command" + ); + } + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + unput('\n'); + BEGIN( Comment ); + } +<InGroupParam>{LC} { // line continuation + yyextra->lineNr++; + addOutput(yyscanner,'\n'); + } +<InGroupParam>. { // ignore other stuff + addOutput(yyscanner,*yytext); + } /* ----- handle argument of fn command ------- */ -<FnParam>{DOCNL} { // end of argument - if (braceCount==0) - { - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - langParser->parsePrototype(functionProto); - BEGIN( Comment ); - } - } -<FnParam>{LC} { // line continuation - yyLineNr++; - functionProto+=' '; - } -<FnParam>[^@\\\n()]+ { // non-special characters - functionProto+=yytext; - } -<FnParam>"(" { - functionProto+=yytext; - braceCount++; - } -<FnParam>")" { - functionProto+=yytext; - braceCount--; - } -<FnParam>. { // add other stuff - functionProto+=*yytext; - } +<FnParam>{DOCNL} { // end of argument + if (yyextra->braceCount==0) + { + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + unput('\n'); + yyextra->langParser->parsePrototype(yyextra->functionProto); + BEGIN( Comment ); + } + } +<FnParam>{LC} { // line continuation + yyextra->lineNr++; + yyextra->functionProto+=' '; + } +<FnParam>[^@\\\n()]+ { // non-special characters + yyextra->functionProto+=yytext; + } +<FnParam>"(" { + yyextra->functionProto+=yytext; + yyextra->braceCount++; + } +<FnParam>")" { + yyextra->functionProto+=yytext; + yyextra->braceCount--; + } +<FnParam>. { // add other stuff + yyextra->functionProto+=*yytext; + } /* ----- handle argument of overload command ------- */ -<OverloadParam>{DOCNL} { // end of argument - if (*yytext=='\n') yyLineNr++; - if (functionProto.stripWhiteSpace().isEmpty()) - { // plain overload command - addOutput(getOverloadDocs()); - addOutput('\n'); - } - else // overload declaration - { - makeStructuralIndicator(Entry::OVERLOADDOC_SEC); - langParser->parsePrototype(functionProto); - } - BEGIN( Comment ); - } -<OverloadParam>{LC} { // line continuation - yyLineNr++; - functionProto+=' '; - } -<OverloadParam>. { // add other stuff - functionProto+=*yytext; - } +<OverloadParam>{DOCNL} { // end of argument + if (*yytext=='\n') yyextra->lineNr++; + if (yyextra->functionProto.stripWhiteSpace().isEmpty()) + { // plain overload command + addOutput(yyscanner,getOverloadDocs()); + addOutput(yyscanner,'\n'); + } + else // overload declaration + { + makeStructuralIndicator(yyscanner,Entry::OVERLOADDOC_SEC); + yyextra->langParser->parsePrototype(yyextra->functionProto); + } + BEGIN( Comment ); + } +<OverloadParam>{LC} { // line continuation + yyextra->lineNr++; + yyextra->functionProto+=' '; + } +<OverloadParam>. { // add other stuff + yyextra->functionProto+=*yytext; + } /* ----- handle argument of inherit command ------- */ -<InheritParam>({ID}("::"|"."))*{ID} { // found argument - current->extends.push_back( - BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) - ); - BEGIN( Comment ); - } -<InheritParam>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "\\inherit command has no argument" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<InheritParam>. { // invalid character for anchor label - warn(yyFileName,yyLineNr, - "Invalid or missing name for \\inherit command" - ); - BEGIN(Comment); - } +<InheritParam>({ID}("::"|"."))*{ID} { // found argument + yyextra->current->extends.push_back( + BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) + ); + BEGIN( Comment ); + } +<InheritParam>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\inherit command has no argument" + ); + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<InheritParam>. { // invalid character for anchor label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing name for \\inherit command" + ); + BEGIN(Comment); + } /* ----- handle argument of extends and implements commands ------- */ -<ExtendsParam>({ID}("::"|"."))*{ID} { // found argument - current->extends.push_back( - BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) - ); - BEGIN( Comment ); - } -<ExtendsParam>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "\\extends or \\implements command has no argument" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<ExtendsParam>. { // ignore other stuff - } +<ExtendsParam>({ID}("::"|"."))*{ID} { // found argument + yyextra->current->extends.push_back( + BaseInfo(removeRedundantWhiteSpace(yytext),Public,Normal) + ); + BEGIN( Comment ); + } +<ExtendsParam>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "'\\%s' command has no argument",yyextra->currentCmd.data() + ); + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + unput('\n'); + BEGIN( Comment ); + } +<ExtendsParam>. { // ignore other stuff + } /* ----- handle language specific sections ------- */ -<SkipLang>[\\@]"~"[a-zA-Z-]* { /* language switch */ - QCString langId = &yytext[2]; - if (langId.isEmpty() || - qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)==0) - { // enable language specific section - BEGIN(Comment); - } - } -<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */ - } -<SkipLang>{DOCNL} { /* new line in verbatim block */ - if (*yytext=='\n') yyLineNr++; - } -<SkipLang>. { /* any other character */ - } +<SkipLang>[\\@]"~"[a-zA-Z-]* { /* language switch */ + QCString langId = &yytext[2]; + if (langId.isEmpty() || + qstricmp(Config_getEnum(OUTPUT_LANGUAGE),langId)==0) + { // enable language specific section + BEGIN(Comment); + } + } +<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */ + } +<SkipLang>{DOCNL} { /* new line in verbatim block */ + if (*yytext=='\n') yyextra->lineNr++; + } +<SkipLang>. { /* any other character */ + } /* ----- handle arguments of the cite command ------- */ -<CiteLabel>{CITEID} { // found argument - addCite(); - addOutput(yytext); - BEGIN(Comment); - } -<CiteLabel>{DOCNL} { // missing argument - warn(yyFileName,yyLineNr, - "\\cite command has no label" - ); - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - BEGIN( Comment ); - } -<CiteLabel>. { // invalid character for cite label - warn(yyFileName,yyLineNr, - "Invalid or missing cite label" - ); - BEGIN(Comment); - } +<CiteLabel>{CITEID} { // found argument + addCite(yyscanner); + addOutput(yyscanner,yytext); + BEGIN(Comment); + } +<CiteLabel>{DOCNL} { // missing argument + warn(yyextra->fileName,yyextra->lineNr, + "\\cite command has no label" + ); + //if (*yytext=='\n') yyextra->lineNr++; + //addOutput(yyscanner,'\n'); + unput('\n'); + BEGIN( Comment ); + } +<CiteLabel>. { // invalid character for cite label + warn(yyextra->fileName,yyextra->lineNr, + "Invalid or missing cite label" + ); + BEGIN(Comment); + } /* ----- handle argument of the copydoc command ------- */ -<CopyDoc><<EOF>> | -<CopyDoc>{DOCNL} { - if (*yytext=='\n') yyLineNr++; - addOutput('\n'); - setOutput(OutputDoc); - addOutput(" \\copydetails "); - addOutput(g_copyDocArg); - addOutput("\n"); - BEGIN(Comment); - } -<CopyDoc>[^\n\\]+ { - g_copyDocArg+=yytext; - addOutput(yytext); - } -<CopyDoc>. { - g_copyDocArg+=yytext; - addOutput(yytext); - } +<CopyDoc><<EOF>> | +<CopyDoc>{DOCNL} { + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + setOutput(yyscanner,OutputDoc); + addOutput(yyscanner," \\copydetails "); + addOutput(yyscanner,yyextra->copyDocArg); + addOutput(yyscanner,"\n"); + BEGIN(Comment); + } +<CopyDoc>[^\n\\]+ { + yyextra->copyDocArg+=yytext; + addOutput(yyscanner,yytext); + } +<CopyDoc>. { + yyextra->copyDocArg+=yytext; + addOutput(yyscanner,yytext); + } %% //---------------------------------------------------------------------------- -static bool handleBrief(const QCString &, const QCStringList &) +static bool handleBrief(yyscan_t yyscanner,const QCString &, const QCStringList &) { //printf("handleBrief\n"); - setOutput(OutputBrief); + setOutput(yyscanner,OutputBrief); return FALSE; } -static bool handleFn(const QCString &, const QCStringList &) +static bool handleFn(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::MEMBERDOC_SEC); - functionProto.resize(0); - braceCount=0; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::MEMBERDOC_SEC); + yyextra->functionProto.resize(0); + yyextra->braceCount=0; BEGIN(FnParam); return stop; } -static bool handleDef(const QCString &, const QCStringList &) +static bool handleDef(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::DEFINEDOC_SEC); - functionProto.resize(0); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::DEFINEDOC_SEC); + yyextra->functionProto.resize(0); BEGIN(FnParam); return stop; } -static bool handleOverload(const QCString &, const QCStringList &) +static bool handleOverload(yyscan_t yyscanner,const QCString &, const QCStringList &) { - functionProto.resize(0); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->functionProto.resize(0); BEGIN(OverloadParam); return FALSE; } -static bool handleEnum(const QCString &, const QCStringList &) +static bool handleEnum(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::ENUMDOC_SEC); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::ENUMDOC_SEC); BEGIN(EnumDocArg1); return stop; } -static bool handleDefGroup(const QCString &, const QCStringList &) +static bool handleDefGroup(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC); - current->groupDocType = Entry::GROUPDOC_NORMAL; - setOutput(OutputBrief); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::GROUPDOC_SEC); + yyextra->current->groupDocType = Entry::GROUPDOC_NORMAL; BEGIN( GroupDocArg1 ); return stop; } -static bool handleAddToGroup(const QCString &, const QCStringList &) +static bool handleAddToGroup(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC); - current->groupDocType = Entry::GROUPDOC_ADD; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::GROUPDOC_SEC); + yyextra->current->groupDocType = Entry::GROUPDOC_ADD; BEGIN( GroupDocArg1 ); return stop; } -static bool handleWeakGroup(const QCString &, const QCStringList &) +static bool handleWeakGroup(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC); - current->groupDocType = Entry::GROUPDOC_WEAK; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::GROUPDOC_SEC); + yyextra->current->groupDocType = Entry::GROUPDOC_WEAK; BEGIN( GroupDocArg1 ); return stop; } -static bool handleNamespace(const QCString &, const QCStringList &) +static bool handleNamespace(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::NAMESPACEDOC_SEC); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::NAMESPACEDOC_SEC); BEGIN( NameSpaceDocArg1 ); return stop; } -static bool handlePackage(const QCString &, const QCStringList &) +static bool handlePackage(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::PACKAGEDOC_SEC); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::PACKAGEDOC_SEC); BEGIN( PackageDocArg1 ); return stop; } -static bool handleClass(const QCString &, const QCStringList &) +static bool handleClass(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::CLASSDOC_SEC); - BEGIN( ClassDocArg1 ); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::CLASSDOC_SEC); + yyextra->currentCmd = cmd; + BEGIN( ClassDocArg1 ); return stop; } -static bool handleHeaderFile(const QCString &, const QCStringList &) +static bool handleHeaderFile(yyscan_t yyscanner,const QCString &, const QCStringList &) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; BEGIN( ClassDocArg2 ); return FALSE; } -static bool handleProtocol(const QCString &, const QCStringList &) +static bool handleProtocol(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { // Obj-C protocol - bool stop=makeStructuralIndicator(Entry::PROTOCOLDOC_SEC); - BEGIN( ClassDocArg1 ); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::PROTOCOLDOC_SEC); + yyextra->currentCmd = cmd; + BEGIN( ClassDocArg1 ); return stop; } -static bool handleCategory(const QCString &, const QCStringList &) +static bool handleCategory(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { // Obj-C category - bool stop=makeStructuralIndicator(Entry::CATEGORYDOC_SEC); - BEGIN( CategoryDocArg1 ); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::CATEGORYDOC_SEC); + yyextra->currentCmd = cmd; + BEGIN( CategoryDocArg1 ); return stop; } -static bool handleUnion(const QCString &, const QCStringList &) +static bool handleUnion(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::UNIONDOC_SEC); - BEGIN( ClassDocArg1 ); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::UNIONDOC_SEC); + yyextra->currentCmd = cmd; + BEGIN( ClassDocArg1 ); return stop; } -static bool handleStruct(const QCString &, const QCStringList &) +static bool handleStruct(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::STRUCTDOC_SEC); - BEGIN( ClassDocArg1 ); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::STRUCTDOC_SEC); + yyextra->currentCmd = cmd; + BEGIN( ClassDocArg1 ); return stop; } -static bool handleInterface(const QCString &, const QCStringList &) +static bool handleInterface(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::INTERFACEDOC_SEC); - BEGIN( ClassDocArg1 ); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::INTERFACEDOC_SEC); + yyextra->currentCmd = cmd; + BEGIN( ClassDocArg1 ); return stop; } -static bool handleIdlException(const QCString &, const QCStringList &) +static bool handleIdlException(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::EXCEPTIONDOC_SEC); - BEGIN( ClassDocArg1 ); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::EXCEPTIONDOC_SEC); + yyextra->currentCmd = cmd; + BEGIN( ClassDocArg1 ); return stop; } -static bool handlePage(const QCString &, const QCStringList &) +static bool handlePage(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::PAGEDOC_SEC); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::PAGEDOC_SEC); BEGIN( PageDocArg1 ); return stop; } -static bool handleMainpage(const QCString &, const QCStringList &) +static bool handleMainpage(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::MAINPAGEDOC_SEC); - current->name = ""; - if (!stop) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::MAINPAGEDOC_SEC); + yyextra->current->name = ""; + if (!stop) { - current->name = "mainpage"; + yyextra->current->name = "mainpage"; } BEGIN( PageDocArg2 ); return stop; } -static bool handleFile(const QCString &, const QCStringList &) +static bool handleFile(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::FILEDOC_SEC); - if (!stop) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::FILEDOC_SEC); + if (!stop) { - current->name = yyFileName; + yyextra->current->name = yyextra->fileName; } BEGIN( FileDocArg1 ); return stop; } -static bool handleParam(const QCString &, const QCStringList &) +static bool handleParam(yyscan_t yyscanner,const QCString &, const QCStringList &) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; // we need process param and retval arguments to escape leading underscores in case of // markdown processing, see bug775493 - addOutput("@param "); + addOutput(yyscanner,"@param "); BEGIN( ParamArg1 ); return FALSE; } -static bool handleRetval(const QCString &, const QCStringList &) +static bool handleRetval(yyscan_t yyscanner,const QCString &, const QCStringList &) { - addOutput("@retval "); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + addOutput(yyscanner,"@retval "); BEGIN( ParamArg1 ); return FALSE; } -static bool handleDir(const QCString &, const QCStringList &) +static bool handleDir(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::DIRDOC_SEC); - if (!stop) current->name = yyFileName; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::DIRDOC_SEC); + if (!stop) yyextra->current->name = yyextra->fileName; BEGIN( FileDocArg1 ); return stop; } -static bool handleExample(const QCString &cmd, const QCStringList &optList) +static bool handleExample(yyscan_t yyscanner,const QCString &cmd, const QCStringList &optList) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; Entry::Sections section=Entry::EXAMPLE_SEC; QCStringList::ConstIterator it; for ( it = optList.begin(); it != optList.end(); ++it ) @@ -2524,458 +2112,501 @@ static bool handleExample(const QCString &cmd, const QCStringList &optList) } else { - warn(yyFileName,yyLineNr, - "unsupported option '%s' for command '\\%s'",qPrint(opt),qPrint(cmd)); + warn(yyextra->fileName,yyextra->lineNr, + "unsupported option '%s' for command '\\%s'",qPrint(opt),qPrint(cmd)); } } - bool stop=makeStructuralIndicator(section); - if (!stop) current->name = yyFileName; + bool stop=makeStructuralIndicator(yyscanner,section); + if (!stop) yyextra->current->name = yyextra->fileName; BEGIN( FileDocArg1 ); return stop; } -static bool handleDetails(const QCString &, const QCStringList &) +static bool handleDetails(yyscan_t yyscanner,const QCString &, const QCStringList &) { - if (inContext!=OutputBrief) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->inContext!=OutputBrief) { - addOutput("\n\n"); // treat @details outside brief description - // as a new paragraph + addOutput(yyscanner,"\\ilinebr\\ilinebr "); // treat @details outside brief description + // as a new paragraph } - setOutput(OutputDoc); + setOutput(yyscanner,OutputDoc); return FALSE; } -static bool handleNoop(const QCString &, const QCStringList &) +static bool handleNoop(yyscan_t yyscanner,const QCString &, const QCStringList &) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; BEGIN( Noop ); return FALSE; } -static bool handleName(const QCString &, const QCStringList &) +static bool handleName(yyscan_t yyscanner,const QCString &, const QCStringList &) { - bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool stop=makeStructuralIndicator(yyscanner,Entry::MEMBERGRP_SEC); if (!stop) { - Doxygen::docGroup.clearHeader(); + yyextra->docGroup.clearHeader(); BEGIN( NameParam ); - if (!Doxygen::docGroup.isEmpty()) // end of previous member group + if (!yyextra->docGroup.isEmpty()) // end of previous member group { - Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE,true); + yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,TRUE,true); } } return stop; } -static bool handleTodo(const QCString &, const QCStringList &) +static bool handleTodo(yyscan_t yyscanner,const QCString &, const QCStringList &) { - newXRefKind = XRef_Todo; - setOutput(OutputXRef); - xrefKind = XRef_Todo; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->newXRefKind = XRef_Todo; + setOutput(yyscanner,OutputXRef); + yyextra->xrefKind = XRef_Todo; return FALSE; } -static bool handleTest(const QCString &, const QCStringList &) +static bool handleTest(yyscan_t yyscanner,const QCString &, const QCStringList &) { - newXRefKind = XRef_Test; - setOutput(OutputXRef); - xrefKind = XRef_Test; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->newXRefKind = XRef_Test; + setOutput(yyscanner,OutputXRef); + yyextra->xrefKind = XRef_Test; return FALSE; } -static bool handleBug(const QCString &, const QCStringList &) +static bool handleBug(yyscan_t yyscanner,const QCString &, const QCStringList &) { - newXRefKind = XRef_Bug; - setOutput(OutputXRef); - xrefKind = XRef_Bug; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->newXRefKind = XRef_Bug; + setOutput(yyscanner,OutputXRef); + yyextra->xrefKind = XRef_Bug; return FALSE; } -static bool handleDeprecated(const QCString &, const QCStringList &) +static bool handleDeprecated(yyscan_t yyscanner,const QCString &, const QCStringList &) { - newXRefKind = XRef_Deprecated; - setOutput(OutputXRef); - xrefKind = XRef_Deprecated; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->newXRefKind = XRef_Deprecated; + setOutput(yyscanner,OutputXRef); + yyextra->xrefKind = XRef_Deprecated; return FALSE; } -static bool handleXRefItem(const QCString &, const QCStringList &) +static bool handleXRefItem(yyscan_t yyscanner,const QCString &, const QCStringList &) { - newXRefKind = XRef_Item; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->newXRefKind = XRef_Item; BEGIN(XRefItemParam1); return FALSE; } -static bool handleParBlock(const QCString &, const QCStringList &) +static bool handleParBlock(yyscan_t yyscanner,const QCString &, const QCStringList &) { - if (g_insideParBlock) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->insideParBlock) { - warn(yyFileName,yyLineNr, - "found \\parblock command while already in a parblock!"); + warn(yyextra->fileName,yyextra->lineNr, + "found \\parblock command while already in a parblock!"); } - if (!g_spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { - addOutput(g_spaceBeforeCmd); - g_spaceBeforeCmd.resize(0); + addOutput(yyscanner,yyextra->spaceBeforeCmd); + yyextra->spaceBeforeCmd.resize(0); } - addOutput("@parblock "); - g_insideParBlock = TRUE; + addOutput(yyscanner,"@parblock "); + yyextra->insideParBlock = TRUE; return FALSE; } -static bool handleEndParBlock(const QCString &, const QCStringList &) +static bool handleEndParBlock(yyscan_t yyscanner,const QCString &, const QCStringList &) { - if (!g_insideParBlock) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->insideParBlock) { - warn(yyFileName,yyLineNr, - "found \\endparblock command without matching \\parblock!"); + warn(yyextra->fileName,yyextra->lineNr, + "found \\endparblock command without matching \\parblock!"); } - addOutput("@endparblock"); - setOutput(OutputDoc); // to end a parblock inside a xrefitem like context - g_insideParBlock = FALSE; + addOutput(yyscanner,"@endparblock"); + setOutput(yyscanner,OutputDoc); // to end a parblock inside a xrefitem like context + yyextra->insideParBlock = FALSE; return FALSE; } -static bool handleRelated(const QCString &, const QCStringList &) +static bool handleRelated(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - if (!current->relates.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->current->relates.isEmpty()) { - warn(yyFileName,yyLineNr, - "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); + warn(yyextra->fileName,yyextra->lineNr, + "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); } - current->relatesType = Simple; + yyextra->current->relatesType = Simple; BEGIN(RelatesParam1); return FALSE; } -static bool handleRelatedAlso(const QCString &, const QCStringList &) +static bool handleRelatedAlso(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - if (!current->relates.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->current->relates.isEmpty()) { - warn(yyFileName,yyLineNr, - "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); + warn(yyextra->fileName,yyextra->lineNr, + "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); } - current->relatesType = Duplicate; + yyextra->current->relatesType = Duplicate; + yyextra->currentCmd = cmd; BEGIN(RelatesParam1); return FALSE; } -static bool handleMemberOf(const QCString &, const QCStringList &) +static bool handleMemberOf(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { - if (!current->relates.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->current->relates.isEmpty()) { - warn(yyFileName,yyLineNr, - "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); + warn(yyextra->fileName,yyextra->lineNr, + "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); } - current->relatesType = MemberOf; + yyextra->current->relatesType = MemberOf; + yyextra->currentCmd = cmd; BEGIN(RelatesParam1); return FALSE; } -static bool handleRefItem(const QCString &, const QCStringList &) +static bool handleRefItem(yyscan_t yyscanner,const QCString &, const QCStringList &) { - addOutput("@refitem "); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + addOutput(yyscanner,"@refitem "); BEGIN(LineParam); return FALSE; } -static bool handleSection(const QCString &s, const QCStringList &) +static bool handleSection(yyscan_t yyscanner,const QCString &s, const QCStringList &) { - setOutput(OutputDoc); - addOutput("@"+s+" "); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + setOutput(yyscanner,OutputDoc); + addOutput(yyscanner,"@"+s+" "); BEGIN(SectionLabel); - if (s=="section") g_sectionLevel=1; - else if (s=="subsection") g_sectionLevel=2; - else if (s=="subsubsection") g_sectionLevel=3; - else if (s=="paragraph") g_sectionLevel=4; + if (s=="section") yyextra->sectionLevel=1; + else if (s=="subsection") yyextra->sectionLevel=2; + else if (s=="subsubsection") yyextra->sectionLevel=3; + else if (s=="paragraph") yyextra->sectionLevel=4; return FALSE; } -static bool handleSubpage(const QCString &s, const QCStringList &) +static bool handleSubpage(yyscan_t yyscanner,const QCString &s, const QCStringList &) { - if (current->section!=Entry::EMPTY_SEC && - current->section!=Entry::PAGEDOC_SEC && - current->section!=Entry::MAINPAGEDOC_SEC + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->current->section!=Entry::EMPTY_SEC && + yyextra->current->section!=Entry::PAGEDOC_SEC && + yyextra->current->section!=Entry::MAINPAGEDOC_SEC ) { - warn(yyFileName,yyLineNr, - "found \\subpage command in a comment block that is not marked as a page!"); + warn(yyextra->fileName,yyextra->lineNr, + "found \\subpage command in a comment block that is not marked as a page!"); } - if (!g_spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { - addOutput(g_spaceBeforeCmd); - g_spaceBeforeCmd.resize(0); + addOutput(yyscanner,yyextra->spaceBeforeCmd); + yyextra->spaceBeforeCmd.resize(0); } - addOutput("@"+s+" "); + addOutput(yyscanner,"@"+s+" "); BEGIN(SubpageLabel); return FALSE; } -static bool handleAnchor(const QCString &s, const QCStringList &) +static bool handleAnchor(yyscan_t yyscanner,const QCString &s, const QCStringList &) { - addOutput("@"+s+" "); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + addOutput(yyscanner,"@"+s+" "); BEGIN(AnchorLabel); return FALSE; } -static bool handleCite(const QCString &s, const QCStringList &) +static bool handleCite(yyscan_t yyscanner,const QCString &s, const QCStringList &) { - if (!g_spaceBeforeCmd.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->spaceBeforeCmd.isEmpty()) { - addOutput(g_spaceBeforeCmd); - g_spaceBeforeCmd.resize(0); + addOutput(yyscanner,yyextra->spaceBeforeCmd); + yyextra->spaceBeforeCmd.resize(0); } - addOutput("@"+s+" "); + addOutput(yyscanner,"@"+s+" "); BEGIN(CiteLabel); return FALSE; } -static bool handleFormatBlock(const QCString &s, const QCStringList &optList) +static bool handleFormatBlock(yyscan_t yyscanner,const QCString &s, const QCStringList &optList) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (optList.isEmpty()) { - addOutput("@"+s+" "); + addOutput(yyscanner,"@"+s+" "); } else { - addOutput("@"+s+"{"+optList.join(",")+"} "); + addOutput(yyscanner,"@"+s+"{"+optList.join(",")+"} "); } //printf("handleFormatBlock(%s) with option(%s)\n",s.data(),opt.data()); - blockName=s; - g_commentCount=0; + yyextra->blockName=s; + yyextra->commentCount=0; BEGIN(FormatBlock); return FALSE; } -static bool handleAddIndex(const QCString &, const QCStringList &) +static bool handleAddIndex(yyscan_t yyscanner,const QCString &, const QCStringList &) { - addOutput("@addindex "); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + addOutput(yyscanner,"@addindex "); BEGIN(LineParam); return FALSE; } -static bool handleIf(const QCString &, const QCStringList &) +static bool handleIf(yyscan_t yyscanner,const QCString &, const QCStringList &) { - enabledSectionFound=FALSE; - guardType = Guard_If; - g_spaceBeforeIf = g_spaceBeforeCmd; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->enabledSectionFound=FALSE; + yyextra->guardType = Guard_If; + yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd; BEGIN(GuardParam); return FALSE; } -static bool handleIfNot(const QCString &, const QCStringList &) +static bool handleIfNot(yyscan_t yyscanner,const QCString &, const QCStringList &) { - enabledSectionFound=FALSE; - guardType = Guard_IfNot; - g_spaceBeforeIf = g_spaceBeforeCmd; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->enabledSectionFound=FALSE; + yyextra->guardType = Guard_IfNot; + yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd; BEGIN(GuardParam); return FALSE; } -static bool handleElseIf(const QCString &, const QCStringList &) +static bool handleElseIf(yyscan_t yyscanner,const QCString &, const QCStringList &) { - if (guards.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->guards.empty()) { - warn(yyFileName,yyLineNr, - "found \\else without matching start command"); + warn(yyextra->fileName,yyextra->lineNr, + "found \\else without matching start command"); } else { - guardType = enabledSectionFound ? Guard_Skip : Guard_If; + yyextra->guardType = yyextra->enabledSectionFound ? Guard_Skip : Guard_If; + yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd; BEGIN(GuardParam); } return FALSE; } -static bool handleElse(const QCString &, const QCStringList &) +static bool handleElse(yyscan_t yyscanner,const QCString &, const QCStringList &) { - if (guards.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->guards.empty()) { - warn(yyFileName,yyLineNr, - "found \\else without matching start command"); + warn(yyextra->fileName,yyextra->lineNr, + "found \\else without matching start command"); } else { + yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd; BEGIN( SkipGuardedSection ); } return FALSE; } -static bool handleEndIf(const QCString &, const QCStringList &) +static bool handleEndIf(yyscan_t yyscanner,const QCString &, const QCStringList &) { - if (guards.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->guards.empty()) { - warn(yyFileName,yyLineNr, - "found \\endif without matching start command"); + warn(yyextra->fileName,yyextra->lineNr, + "found \\endif without matching start command"); } else { - delete guards.pop(); + yyextra->guards.pop(); } - enabledSectionFound=FALSE; - if (!g_spaceBeforeCmd.isEmpty()) + yyextra->enabledSectionFound=FALSE; + if (!yyextra->spaceBeforeCmd.isEmpty()) { - addOutput(g_spaceBeforeCmd); - g_spaceBeforeCmd.resize(0); + addOutput(yyscanner,yyextra->spaceBeforeCmd); + yyextra->spaceBeforeCmd.resize(0); } BEGIN( GuardParamEnd ); return FALSE; } -static bool handleIngroup(const QCString &, const QCStringList &) +static bool handleIngroup(yyscan_t yyscanner,const QCString &, const QCStringList &) { - inGroupParamFound=FALSE; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->inGroupParamFound=FALSE; BEGIN( InGroupParam ); return FALSE; } -static bool handleNoSubGrouping(const QCString &, const QCStringList &) +static bool handleNoSubGrouping(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->subGrouping = FALSE; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->subGrouping = FALSE; return FALSE; } -static bool handleShowInitializer(const QCString &, const QCStringList &) +static bool handleShowInitializer(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->initLines = 100000; // ON + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->initLines = 100000; // ON return FALSE; } -static bool handleHideInitializer(const QCString &, const QCStringList &) +static bool handleHideInitializer(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->initLines = 0; // OFF + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->initLines = 0; // OFF return FALSE; } -static bool handleCallgraph(const QCString &, const QCStringList &) +static bool handleCallgraph(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->callGraph = TRUE; // ON + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->callGraph = TRUE; // ON return FALSE; } -static bool handleHideCallgraph(const QCString &, const QCStringList &) +static bool handleHideCallgraph(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->callGraph = FALSE; // OFF + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->callGraph = FALSE; // OFF return FALSE; } -static bool handleCallergraph(const QCString &, const QCStringList &) +static bool handleCallergraph(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->callerGraph = TRUE; // ON + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->callerGraph = TRUE; // ON return FALSE; } -static bool handleHideCallergraph(const QCString &, const QCStringList &) +static bool handleHideCallergraph(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->callerGraph = FALSE; // OFF + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->callerGraph = FALSE; // OFF return FALSE; } -static bool handleReferencedByRelation(const QCString &, const QCStringList &) +static bool handleReferencedByRelation(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->referencedByRelation = TRUE; // ON + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->referencedByRelation = TRUE; // ON return FALSE; } -static bool handleHideReferencedByRelation(const QCString &, const QCStringList &) +static bool handleHideReferencedByRelation(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->referencedByRelation = FALSE; // OFF + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->referencedByRelation = FALSE; // OFF return FALSE; } -static bool handleReferencesRelation(const QCString &, const QCStringList &) +static bool handleReferencesRelation(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->referencesRelation = TRUE; // ON + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->referencesRelation = TRUE; // ON return FALSE; } -static bool handleHideReferencesRelation(const QCString &, const QCStringList &) +static bool handleHideReferencesRelation(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->referencesRelation = FALSE; // OFF + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->referencesRelation = FALSE; // OFF return FALSE; } -static bool handleInternal(const QCString &, const QCStringList &) +static bool handleInternal(yyscan_t yyscanner,const QCString &, const QCStringList &) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (!Config_getBool(INTERNAL_DOCS)) { // make sure some whitespace before a \internal command // is not treated as "documentation" - if (current->doc.stripWhiteSpace().isEmpty()) - { - current->doc.resize(0); + if (yyextra->current->doc.stripWhiteSpace().isEmpty()) + { + yyextra->current->doc.resize(0); } - g_condCount=0; + yyextra->condCount=0; BEGIN( SkipInternal ); } else { // re-enabled for bug640828 - addOutput(" \\internal "); - inInternalDocs = TRUE; + addOutput(yyscanner," \\internal "); + yyextra->inInternalDocs = TRUE; } return FALSE; } -static bool handleLineBr(const QCString &, const QCStringList &) +static bool handleStatic(yyscan_t yyscanner,const QCString &, const QCStringList &) { - addOutput('\n'); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->stat = TRUE; return FALSE; } -static bool handleStatic(const QCString &, const QCStringList &) +static bool handlePure(yyscan_t yyscanner,const QCString &, const QCStringList &) { - endBrief(); - current->stat = TRUE; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->virt = Pure; return FALSE; } -static bool handlePure(const QCString &, const QCStringList &) +static bool handlePrivate(yyscan_t yyscanner,const QCString &, const QCStringList &) { - endBrief(); - current->virt = Pure; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->protection = Private; return FALSE; } -static bool handlePrivate(const QCString &, const QCStringList &) +static bool handlePrivateSection(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->protection = Private; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->protection = yyextra->protection = Private; return FALSE; } -static bool handlePrivateSection(const QCString &, const QCStringList &) +static bool handleProtected(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->protection = protection = Private; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->protection = Protected; return FALSE; } -static bool handleProtected(const QCString &, const QCStringList &) +static bool handleProtectedSection(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->protection = Protected; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->protection = yyextra->protection = Protected ; return FALSE; } -static bool handleProtectedSection(const QCString &, const QCStringList &) +static bool handlePublic(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->protection = protection = Protected ; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->protection = Public; return FALSE; } -static bool handlePublic(const QCString &, const QCStringList &) +static bool handlePublicSection(yyscan_t yyscanner,const QCString &, const QCStringList &) { - current->protection = Public; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->protection = yyextra->protection = Public; return FALSE; } -static bool handlePublicSection(const QCString &, const QCStringList &) +static bool handleToc(yyscan_t yyscanner,const QCString &, const QCStringList &optList) { - current->protection = protection = Public; - return FALSE; -} - -static bool handleToc(const QCString &, const QCStringList &optList) -{ - if (current->section==Entry::PAGEDOC_SEC || - current->section==Entry::MAINPAGEDOC_SEC) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->current->section==Entry::PAGEDOC_SEC || + yyextra->current->section==Entry::MAINPAGEDOC_SEC) { QCStringList::ConstIterator it; for ( it = optList.begin(); it != optList.end(); ++it ) @@ -2988,7 +2619,7 @@ static bool handleToc(const QCString &, const QCStringList &optList) { if (sscanf(opt.right(opt.length() - i - 1).data(),"%d%c",&level,&dum) != 1) { - warn(yyFileName,yyLineNr,"Unknown option:level specified with \\tableofcontents: '%s'", (*it).stripWhiteSpace().data()); + warn(yyextra->fileName,yyextra->lineNr,"Unknown option:level specified with \\tableofcontents: '%s'", (*it).stripWhiteSpace().data()); opt = ""; } else @@ -3002,282 +2633,785 @@ static bool handleToc(const QCString &, const QCStringList &optList) { if (opt == "html") { - current->localToc.enableHtml(level); + yyextra->current->localToc.enableHtml(level); } else if (opt == "latex") { - current->localToc.enableLatex(level); + yyextra->current->localToc.enableLatex(level); } else if (opt == "xml") { - current->localToc.enableXml(level); + yyextra->current->localToc.enableXml(level); } else if (opt == "docbook") { - current->localToc.enableDocbook(level); + yyextra->current->localToc.enableDocbook(level); } else { - warn(yyFileName,yyLineNr,"Unknown option specified with \\tableofcontents: '%s'", (*it).stripWhiteSpace().data()); + warn(yyextra->fileName,yyextra->lineNr,"Unknown option specified with \\tableofcontents: '%s'", (*it).stripWhiteSpace().data()); } } } - if (current->localToc.nothingEnabled()) + if (yyextra->current->localToc.nothingEnabled()) { // for backward compatibility - current->localToc.enableHtml(5); - current->localToc.enableXml(5); + yyextra->current->localToc.enableHtml(5); + yyextra->current->localToc.enableXml(5); } } return FALSE; } -static bool handleInherit(const QCString &, const QCStringList &) +static bool handleInherit(yyscan_t yyscanner,const QCString &, const QCStringList &) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; BEGIN(InheritParam); return FALSE; } -static bool handleExtends(const QCString &, const QCStringList &) +static bool handleExtends(yyscan_t yyscanner,const QCString &cmd, const QCStringList &) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->currentCmd = cmd; BEGIN(ExtendsParam); return FALSE; } -static bool handleCopyBrief(const QCString &, const QCStringList &) +static bool handleCopyBrief(yyscan_t yyscanner,const QCString &, const QCStringList &) { - if (current->brief.isEmpty() && current->doc.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->current->brief.isEmpty() && yyextra->current->doc.isEmpty()) { // if we don't have a brief or detailed description yet, // then the @copybrief should end up in the brief description. // otherwise it will be copied inline (see bug691315 & bug700788) - setOutput(OutputBrief); + setOutput(yyscanner,OutputBrief); } - if (!g_spaceBeforeCmd.isEmpty()) + if (!yyextra->spaceBeforeCmd.isEmpty()) { - addOutput(g_spaceBeforeCmd); - g_spaceBeforeCmd.resize(0); + addOutput(yyscanner,yyextra->spaceBeforeCmd); + yyextra->spaceBeforeCmd.resize(0); } - addOutput("\\copybrief "); + addOutput(yyscanner,"\\copybrief "); return FALSE; } -static bool handleCopyDetails(const QCString &, const QCStringList &) +static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const QCStringList &) { - setOutput(OutputDoc); - if (!g_spaceBeforeCmd.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + setOutput(yyscanner,OutputDoc); + if (!yyextra->spaceBeforeCmd.isEmpty()) { - addOutput(g_spaceBeforeCmd); - g_spaceBeforeCmd.resize(0); + addOutput(yyscanner,yyextra->spaceBeforeCmd); + yyextra->spaceBeforeCmd.resize(0); } - addOutput("\\copydetails "); + addOutput(yyscanner,"\\copydetails "); return FALSE; } -static bool handleCopyDoc(const QCString &, const QCStringList &) +static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const QCStringList &) { - setOutput(OutputBrief); - if (!g_spaceBeforeCmd.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + setOutput(yyscanner,OutputBrief); + if (!yyextra->spaceBeforeCmd.isEmpty()) { - addOutput(g_spaceBeforeCmd); - g_spaceBeforeCmd.resize(0); + addOutput(yyscanner,yyextra->spaceBeforeCmd); + yyextra->spaceBeforeCmd.resize(0); } - addOutput("\\copybrief "); - g_copyDocArg.resize(0); + addOutput(yyscanner,"\\copybrief "); + yyextra->copyDocArg.resize(0); BEGIN(CopyDoc); return FALSE; } -//---------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------- -static void checkFormula() +static void initParser(yyscan_t yyscanner) { - if (YY_START==ReadFormulaShort || YY_START==ReadFormulaLong) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->sectionLabel.resize(0); + yyextra->sectionTitle.resize(0); + yyextra->docGroup.clearHeader(); + yyextra->insideParBlock = FALSE; +} + + +static bool getDocSectionName(int s) +{ + switch(s) { - warn(yyFileName,yyLineNr,"End of comment block while inside formula."); + case Entry::CLASSDOC_SEC: + case Entry::STRUCTDOC_SEC: + case Entry::UNIONDOC_SEC: + case Entry::EXCEPTIONDOC_SEC: + case Entry::NAMESPACEDOC_SEC: + case Entry::PROTOCOLDOC_SEC: + case Entry::CATEGORYDOC_SEC: + case Entry::ENUMDOC_SEC: + case Entry::PAGEDOC_SEC: + case Entry::VARIABLEDOC_SEC: + case Entry::MEMBERDOC_SEC: + case Entry::OVERLOADDOC_SEC: + case Entry::FILEDOC_SEC: + case Entry::DEFINEDOC_SEC: + case Entry::GROUPDOC_SEC: + case Entry::MAINPAGEDOC_SEC: + case Entry::PACKAGEDOC_SEC: + case Entry::DIRDOC_SEC: + case Entry::EXAMPLE_SEC: + case Entry::MEMBERGRP_SEC: + return TRUE; + default: + return FALSE; } } -//---------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +static bool makeStructuralIndicator(yyscan_t yyscanner,Entry::Sections s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("yyextra->current->section=%x\n",yyextra->current->section); + if (getDocSectionName(yyextra->current->section)) + { + return TRUE; + } + else + { + yyextra->needNewEntry = TRUE; + yyextra->current->section = s; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->lineNr; + return FALSE; + } +} + +//----------------------------------------------------------------- + +static void lineCount(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + for( const char* c = yytext ; *c ; ++c ) + yyextra->lineNr += (*c == '\n') ; +} + +//----------------------------------------------------------------- + +static QCString stripQuotes(const char *s) +{ + QCString name; + if (s==0 || *s==0) return name; + name=s; + if (name.at(0)=='"' && name.at(name.length()-1)=='"') + { + name=name.mid(1,name.length()-2); + } + return name; +} + +//----------------------------------------------------------------- + +static void addXRefItem(yyscan_t yyscanner, + const char *listName,const char *itemTitle, + const char *listTitle,bool append) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (listName==0) return; + //printf("addXRefItem(%s,%s,%s,%d)\n",listName,itemTitle,listTitle,append); + + std::unique_lock<std::mutex> lock(g_sectionMutex); + + RefList *refList = RefListManager::instance().add(listName,listTitle,itemTitle); + RefItem *item = 0; + for (RefItem *i : yyextra->current->sli) + { + if (i && qstrcmp(i->list()->listName(),listName)==0) + { + //printf("found %s lii->type=%s\n",listName,lii->type); + item = i; + break; + } + } + if (item && append) // already found item of same type just before this one + { + //printf("listName=%s item id = %d existing\n",listName,lii->itemId); + item->setText(item->text() + " <p>" + yyextra->outputXRef); + //printf("%s: text +=%s\n",listName,item->text.data()); + } + else // new item + { + //printf("listName=%s item id = %d new yyextra->current=%p\n",listName,itemId,yyextra->current); + + // if we have already an item from the same list type (e.g. a second @todo) + // in the same Entry (i.e. lii!=0) then we reuse its link anchor. + item = refList->add(); + QCString anchorLabel; + anchorLabel.sprintf("_%s%06d",listName,item->id()); + item->setText(yyextra->outputXRef); + item->setAnchor(anchorLabel); + yyextra->current->sli.push_back(item); + QCString cmdString; + cmdString.sprintf(" \\xrefitem %s %d.",listName,item->id()); + if (yyextra->inBody) + { + yyextra->current->inbodyDocs += cmdString; + } + else + { + yyextra->current->doc += cmdString; + } + + { + SectionManager &sm = SectionManager::instance(); + const SectionInfo *si = sm.find(anchorLabel); + if (si) + { + if (si->lineNr() != -1) + { + warn(listName,yyextra->lineNr,"multiple use of section label '%s', (first occurrence: %s, line %d)",anchorLabel.data(),si->fileName().data(),si->lineNr()); + } + else + { + warn(listName,yyextra->lineNr,"multiple use of section label '%s', (first occurrence: %s)",anchorLabel.data(),si->fileName().data()); + } + } + else + { + si = sm.add(anchorLabel,listName,yyextra->lineNr, + yyextra->sectionTitle,SectionType::Anchor, + yyextra->sectionLevel); + yyextra->current->anchors.push_back(si); + } + } + } + yyextra->outputXRef.resize(0); +} + +//----------------------------------------------------------------------------- + +// Adds a formula text to the list/dictionary of formulas if it was +// not already added. Returns the label of the formula. +static QCString addFormula(yyscan_t yyscanner) +{ + std::unique_lock<std::mutex> lock(g_formulaMutex); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString formLabel; + QCString fText=yyextra->formulaText.simplifyWhiteSpace(); + int id = FormulaManager::instance().addFormula(fText); + formLabel.sprintf("\\_form#%d",id); + for (int i=0;i<yyextra->formulaNewLines;i++) formLabel+="@_fakenl"; // add fake newlines to + // keep the warnings + // correctly aligned. + return formLabel; +} + +//----------------------------------------------------------------------------- + +static SectionType sectionLevelToType(int level) +{ + if (level>=0 && level<5) return (SectionType)level; + return SectionType::Anchor; +} + +static void addSection(yyscan_t yyscanner) +{ + std::unique_lock<std::mutex> lock(g_sectionMutex); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + SectionManager &sm = SectionManager::instance(); + const SectionInfo *si = sm.find(yyextra->sectionLabel); + if (si) + { + if (si->lineNr() != -1) + { + warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s, line %d)",yyextra->sectionLabel.data(),si->fileName().data(),si->lineNr()); + } + else + { + warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s)",yyextra->sectionLabel.data(),si->fileName().data()); + } + } + else + { + // create a new section element + yyextra->sectionTitle+=yytext; + yyextra->sectionTitle=yyextra->sectionTitle.stripWhiteSpace(); + si = sm.add(yyextra->sectionLabel,yyextra->fileName,yyextra->lineNr, + yyextra->sectionTitle,sectionLevelToType(yyextra->sectionLevel), + yyextra->sectionLevel); + + // add section to this entry + yyextra->current->anchors.push_back(si); + } +} + +//----------------------------------------------------------------------------- + +static void addCite(yyscan_t yyscanner) +{ + std::unique_lock<std::mutex> lock(g_citeMutex); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString name=yytext; + if (yytext[0] =='"') + { + name=yytext+1; + name=name.left((int)yyleng-2); + } + CitationManager::instance().insert(name.data()); +} + +//----------------------------------------------------------------------------- + +// strip trailing whitespace (excluding newlines) from string s +static void stripTrailingWhiteSpace(QCString &s) +{ + uint len = s.length(); + int i = (int)len-1; + char c; + while (i>=0) + { + c = s.at(i); + if (c==' ' || c=='\t' || c=='\r') // normal whitespace + { + i--; + } + else if (c=='r' && i>=7 && qstrncmp("\\ilinebr",s.data()+i-7,8)==0) // special line break marker + { + i-=8; + } + else // non-whitespace + { + break; + } + } + //printf("stripTrailingWhitespace(%s) i=%d len=%d\n",s.data(),i,len); + if (i!=(int)len-1) + { + s.resize(i+2); // string up to and including char at pos i and \0 terminator + } +} -QCString preprocessCommentBlock(const QCString &comment, - const QCString &fileName, - int lineNr) +// selects the output to write to +static inline void setOutput(yyscan_t yyscanner,OutputContext ctx) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool xrefAppendToPrev = yyextra->xrefAppendFlag; + // determine append flag for the next item (i.e. the end of this item) + yyextra->xrefAppendFlag = !yyextra->inBody && + yyextra->inContext==OutputXRef && ctx==OutputXRef && // two consecutive xref items + yyextra->newXRefKind==yyextra->xrefKind && // of the same kind + (yyextra->xrefKind!=XRef_Item || + yyextra->newXRefItemKey==yyextra->xrefItemKey); // with the same key if \xrefitem + //printf("%d && %d && %d && (%d || %d)\n", + // yyextra->inContext==OutputXRef, + // ctx==OutputXRef, + // yyextra->newXRefKind==yyextra->xrefKind, + // yyextra->xrefKind!=XRef_Item, + // yyextra->newXRefItemKey==yyextra->xrefItemKey); + //printf("refKind=%d yyextra->newXRefKind=%d xrefAppendToPrev=%d yyextra->xrefAppendFlag=%d\n", + // yyextra->xrefKind,yyextra->newXRefKind,xrefAppendToPrev,yyextra->xrefAppendFlag); + + //printf("setOutput(yyscanner,yyextra->inContext=%d ctx=%d)\n",yyextra->inContext,ctx); + if (yyextra->inContext==OutputXRef) // end of XRef section => add the item + { + // See if we can append this new xref item to the previous one. + // We know this at the start of the next item of the same + // type and need to remember this until the end of that item. + switch(yyextra->xrefKind) + { + case XRef_Todo: + addXRefItem(yyscanner,"todo", + theTranslator->trTodo(), + theTranslator->trTodoList(), + xrefAppendToPrev + ); + break; + case XRef_Test: + addXRefItem(yyscanner,"test", + theTranslator->trTest(), + theTranslator->trTestList(), + xrefAppendToPrev + ); + break; + case XRef_Bug: + addXRefItem(yyscanner,"bug", + theTranslator->trBug(), + theTranslator->trBugList(), + xrefAppendToPrev + ); + break; + case XRef_Deprecated: + addXRefItem(yyscanner,"deprecated", + theTranslator->trDeprecated(), + theTranslator->trDeprecatedList(), + xrefAppendToPrev + ); + break; + case XRef_Item: // user defined list + addXRefItem(yyscanner,yyextra->xrefItemKey, + yyextra->xrefItemTitle, + yyextra->xrefListTitle, + xrefAppendToPrev + ); + break; + case XRef_None: + ASSERT(0); + break; + } + } + yyextra->xrefItemKey = yyextra->newXRefItemKey; + + int oldContext = yyextra->inContext; + yyextra->inContext = ctx; + if (yyextra->inContext!=OutputXRef && yyextra->inBody) yyextra->inContext=OutputInbody; + switch(yyextra->inContext) + { + case OutputDoc: + if (oldContext!=yyextra->inContext) + { + stripTrailingWhiteSpace(yyextra->current->doc); + if (yyextra->current->docFile.isEmpty()) + { + yyextra->current->docFile = yyextra->fileName; + yyextra->current->docLine = yyextra->lineNr; + } + } + yyextra->pOutputString = &yyextra->current->doc; + break; + case OutputBrief: + if (oldContext!=yyextra->inContext) + { + if (yyextra->current->briefFile.isEmpty()) + { + yyextra->current->briefFile = yyextra->fileName; + yyextra->current->briefLine = yyextra->lineNr; + } + } + if (yyextra->current->brief.stripWhiteSpace().isEmpty()) // we only want one brief + // description even if multiple + // are given... + { + yyextra->pOutputString = &yyextra->current->brief; + } + else + { + if (!yyextra->current->doc.isEmpty()) // when appending parts add a new line + { + yyextra->current->doc += "\n"; + } + yyextra->pOutputString = &yyextra->current->doc; + yyextra->inContext = OutputDoc; // need to switch to detailed docs, see bug 631380 + } + break; + case OutputXRef: + yyextra->pOutputString = &yyextra->outputXRef; + // first item found, so can't append to previous + //yyextra->xrefAppendFlag = FALSE; + break; + case OutputInbody: + yyextra->pOutputString = &yyextra->current->inbodyDocs; + break; + } +} + + +static void addAnchor(yyscan_t yyscanner,const char *anchor) { - if (!comment.isEmpty() && Doxygen::markdownSupport) + std::unique_lock<std::mutex> lock(g_sectionMutex); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + SectionManager &sm = SectionManager::instance(); + const SectionInfo *si = sm.find(anchor); + if (si) { - QCString result = processMarkdown(fileName,lineNr,0,comment); - const char *p = result.data(); - if (p) + if (si->lineNr() != -1) { - while (*p==' ') p++; // skip over spaces - while (*p=='\n') p++; // skip over newlines - if (qstrncmp(p,"<br>",4)==0) p+=4; // skip over <br> + warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s, line %d)",anchor,si->fileName().data(),si->lineNr()); } - if (p>result.data()) + else { - // strip part of the input - result = result.mid(p-result.data()); + warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s)",anchor,si->fileName().data()); } - return result; } else { - return comment; + si = sm.add(anchor,yyextra->fileName,yyextra->lineNr,nullptr,SectionType::Anchor,0); + yyextra->current->anchors.push_back(si); } } -bool parseCommentBlock(/* in */ OutlineParserInterface *parser, +// add a string to the output +static inline void addOutput(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("addOutput(yyscanner,%s)\n",s); + *yyextra->pOutputString+=s; +} + +// add a character to the output +static inline void addOutput(yyscan_t yyscanner,char c) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + *yyextra->pOutputString+=c; +} + +static void endBrief(yyscan_t yyscanner,bool addToOutput) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->current->brief.stripWhiteSpace().isEmpty()) + { // only go to the detailed description if we have + // found some brief description and not just whitespace + yyextra->briefEndsAtDot=FALSE; + setOutput(yyscanner,OutputDoc); + if (addToOutput) addOutput(yyscanner,yytext); + } +} + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->prevPosition=yyextra->inputPosition; + yy_size_t c=0; + while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + { + *buf = yyextra->inputString[yyextra->inputPosition++] ; + //printf("%d (%c)\n",*buf,*buf); + c++; buf++; + } + return c; +} + +//---------------------------------------------------------------------------- + +static void checkFormula(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (YY_START==ReadFormulaShort || YY_START==ReadFormulaLong) + { + warn(yyextra->fileName,yyextra->lineNr,"End of comment block while inside formula."); + } +} + +//---------------------------------------------------------------------------- + +struct CommentScanner::Private +{ + yyscan_t yyscanner; + commentscanYY_state extra; +}; + +CommentScanner::CommentScanner() : p(std::make_unique<Private>()) +{ + commentscanYYlex_init_extra(&p->extra,&p->yyscanner); +#ifdef FLEX_DEBUG + commentscanYYset_debug(1,p->yyscanner); +#endif +} + +CommentScanner::~CommentScanner() +{ + commentscanYYlex_destroy(p->yyscanner); +} + +bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *parser, /* in */ Entry *curEntry, /* in */ const QCString &comment, - /* in */ const QCString &fileName, - /* in,out */ int &lineNr, - /* in */ bool isBrief, - /* in */ bool isAutoBriefOn, - /* in */ bool isInbody, - /* in,out */ Protection &prot, - /* in,out */ int &position, - /* out */ bool &newEntryNeeded - ) -{ + /* in */ const QCString &fileName, + /* in,out */ int &lineNr, + /* in */ bool isBrief, + /* in */ bool isAutoBriefOn, + /* in */ bool isInbody, + /* in,out */ Protection &prot, + /* in,out */ int &position, + /* out */ bool &newEntryNeeded, + /* in */ bool markdownSupport + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("parseCommentBlock() isBrief=%d isAutoBriefOn=%d lineNr=%d\n", // isBrief,isAutoBriefOn,lineNr); - initParser(); - guards.setAutoDelete(TRUE); - guards.clear(); - langParser = parser; - current = curEntry; + initParser(yyscanner); + yyextra->guards = std::stack<GuardedSection>(); + yyextra->langParser = parser; + yyextra->current = curEntry; + yyextra->current->docLine = (lineNr > 1 ? lineNr-1: 1); if (comment.isEmpty()) return FALSE; // avoid empty strings - inputString = comment; - inputString.append(" "); - inputPosition = position; - yyLineNr = lineNr; - yyFileName = fileName; - protection = prot; - needNewEntry = FALSE; - xrefKind = XRef_None; - xrefAppendFlag = FALSE; - insidePre = FALSE; - parseMore = FALSE; - inBody = isInbody; - outputXRef.resize(0); - if (!isBrief && !isAutoBriefOn && !current->doc.isEmpty()) + yyextra->inputString = comment; + yyextra->inputString.append(" "); + yyextra->inputPosition = position; + yyextra->lineNr = lineNr; + yyextra->fileName = fileName; + yyextra->protection = prot; + yyextra->needNewEntry = FALSE; + yyextra->xrefKind = XRef_None; + yyextra->xrefAppendFlag = FALSE; + yyextra->insidePre = FALSE; + yyextra->parseMore = FALSE; + yyextra->inBody = isInbody; + yyextra->markdownSupport= markdownSupport; + yyextra->outputXRef.resize(0); + if (!isBrief && !isAutoBriefOn && !yyextra->current->doc.isEmpty()) { // add newline separator between detailed comment blocks - current->doc += '\n'; + yyextra->current->doc += '\n'; } - setOutput( isBrief || isAutoBriefOn ? OutputBrief : OutputDoc ); - briefEndsAtDot = isAutoBriefOn; - g_condCount = 0; - g_sectionLevel = 0; - g_spaceBeforeCmd.resize(0); - g_spaceBeforeIf.resize(0); + setOutput(yyscanner, isBrief || isAutoBriefOn ? OutputBrief : OutputDoc ); + yyextra->briefEndsAtDot = isAutoBriefOn; + yyextra->condCount = 0; + yyextra->sectionLevel = 0; + yyextra->spaceBeforeCmd.resize(0); + yyextra->spaceBeforeIf.resize(0); printlex(yy_flex_debug, TRUE, __FILE__, fileName ? fileName.data(): NULL); - if (!current->inbodyDocs.isEmpty() && isInbody) // separate in body fragments + if (!yyextra->current->inbodyDocs.isEmpty() && isInbody) // separate in body fragments { - current->inbodyDocs+="\n\n"; + yyextra->current->inbodyDocs+="\n\n"; } Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\n" - "input=[\n%s]\n",qPrint(fileName),lineNr,qPrint(inputString) + "input=[\n%s]\n",qPrint(fileName),lineNr,qPrint(yyextra->inputString) ); - - commentscanYYrestart( commentscanYYin ); + + commentscanYYrestart( 0, yyscanner ); BEGIN( Comment ); - commentscanYYlex(); - setOutput( OutputDoc ); + commentscanYYlex(yyscanner); + setOutput(yyscanner, OutputDoc ); if (YY_START==OverloadParam) // comment ended with \overload { - addOutput(getOverloadDocs()); + addOutput(yyscanner,getOverloadDocs()); } - if (!guards.isEmpty()) + if (!yyextra->guards.empty()) { - warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!"); + warn(yyextra->fileName,yyextra->lineNr,"Documentation block ended in the middle of a conditional section!"); } - if (g_insideParBlock) + if (yyextra->insideParBlock) { - warn(yyFileName,yyLineNr, - "Documentation block ended while inside a \\parblock. Missing \\endparblock"); + warn(yyextra->fileName,yyextra->lineNr, + "Documentation block ended while inside a \\parblock. Missing \\endparblock"); } - current->doc=stripLeadingAndTrailingEmptyLines(current->doc,current->docLine); + yyextra->current->doc=stripLeadingAndTrailingEmptyLines(yyextra->current->doc,yyextra->current->docLine); - if (current->section==Entry::FILEDOC_SEC && current->doc.isEmpty()) + if (yyextra->current->section==Entry::FILEDOC_SEC && yyextra->current->doc.isEmpty()) { // to allow a comment block with just a @file command. - current->doc="\n\n"; + yyextra->current->doc="\n\n"; } - if (current->section==Entry::MEMBERGRP_SEC && - Doxygen::docGroup.isEmpty()) // @name section but no group started yet + if (yyextra->current->section==Entry::MEMBERGRP_SEC && + yyextra->docGroup.isEmpty()) // @name section but no group started yet { - Doxygen::docGroup.open(current,yyFileName,yyLineNr,true); + yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr,true); } Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\noutput=[\n" "brief=[line=%d\n%s]\ndocs=[line=%d\n%s]\ninbody=[line=%d\n%s]\n]\n===========\n", qPrint(fileName),lineNr, - current->briefLine,qPrint(current->brief), - current->docLine,qPrint(current->doc), - current->inbodyLine,qPrint(current->inbodyDocs) + yyextra->current->briefLine,qPrint(yyextra->current->brief), + yyextra->current->docLine,qPrint(yyextra->current->doc), + yyextra->current->inbodyLine,qPrint(yyextra->current->inbodyDocs) ); - - checkFormula(); - prot = protection; - - Doxygen::docGroup.addDocs(curEntry); - newEntryNeeded = needNewEntry; + checkFormula(yyscanner); + prot = yyextra->protection; + + yyextra->docGroup.addDocs(curEntry); + + newEntryNeeded = yyextra->needNewEntry; // if we did not proceed during this call, it does not make // sense to continue, since we get stuck. See bug 567346 for situations // were this happens - if (parseMore && position==inputPosition) parseMore=FALSE; + if (yyextra->parseMore && position==yyextra->inputPosition) yyextra->parseMore=FALSE; - if (parseMore) position=inputPosition; else position=0; + if (yyextra->parseMore) position=yyextra->inputPosition; else position=0; - lineNr = yyLineNr; - //printf("position=%d parseMore=%d newEntryNeeded=%d\n", - // position,parseMore,newEntryNeeded); + lineNr = yyextra->lineNr; + //printf("position=%d yyextra->parseMore=%d newEntryNeeded=%d\n", + // position,yyextra->parseMore,newEntryNeeded); printlex(yy_flex_debug, FALSE, __FILE__, fileName ? fileName.data(): NULL); - return parseMore; + return yyextra->parseMore; } -static void handleGuard(const QCString &expr) +static void handleGuard(yyscan_t yyscanner,const QCString &expr) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; CondParser prs; - bool sectionEnabled=prs.parse(yyFileName,yyLineNr,expr.stripWhiteSpace()); + bool sectionEnabled=prs.parse(yyextra->fileName,yyextra->lineNr,expr.stripWhiteSpace()); bool parentEnabled = TRUE; - if (!guards.isEmpty()) parentEnabled = guards.top()->isEnabled(); + if (!yyextra->guards.empty()) parentEnabled = yyextra->guards.top().isEnabled(); if (parentEnabled) { if ( - (sectionEnabled && guardType==Guard_If) || - (!sectionEnabled && guardType==Guard_IfNot) + (sectionEnabled && yyextra->guardType==Guard_If) || + (!sectionEnabled && yyextra->guardType==Guard_IfNot) ) // section is visible { - guards.push(new GuardedSection(TRUE,TRUE)); - enabledSectionFound=TRUE; + yyextra->guards.push(GuardedSection(TRUE,TRUE)); + yyextra->enabledSectionFound=TRUE; BEGIN( GuardParamEnd ); } else // section is invisible { - if (guardType!=Guard_Skip) + if (yyextra->guardType!=Guard_Skip) { - guards.push(new GuardedSection(FALSE,TRUE)); + yyextra->guards.push(GuardedSection(FALSE,TRUE)); } BEGIN( SkipGuardedSection ); } } else // invisible because of parent { - guards.push(new GuardedSection(FALSE,FALSE)); + yyextra->guards.push(GuardedSection(FALSE,FALSE)); BEGIN( SkipGuardedSection ); } } +void CommentScanner::initGroupInfo(Entry *entry) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->docGroup.initGroupInfo(entry); +} + +void CommentScanner::enterFile(const char *fileName,int lineNr) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->docGroup.enterFile(fileName,lineNr); +} + +void CommentScanner::leaveFile(const char *fileName,int lineNr) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->docGroup.leaveFile(fileName,lineNr); +} + +void CommentScanner::enterCompound(const char *fileName,int lineNr,const char *name) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->docGroup.enterCompound(fileName,lineNr,name); +} + +void CommentScanner::leaveCompound(const char *fileName,int lineNr,const char *name) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->docGroup.leaveCompound(fileName,lineNr,name); +} + +void CommentScanner::open(Entry *e,const char *fileName,int lineNr,bool implicit) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->docGroup.open(e,fileName,lineNr,implicit); +} + +void CommentScanner::close(Entry *e,const char *fileName,int lineNr,bool foundInline,bool implicit) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->docGroup.close(e,fileName,lineNr,foundInline,implicit); +} + +#if USE_STATE2STRING #include "commentscan.l.h" +#endif diff --git a/src/condparser.cpp b/src/condparser.cpp index 9d7ac45..ac6ff61 100644 --- a/src/condparser.cpp +++ b/src/condparser.cpp @@ -2,8 +2,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,6 +19,8 @@ * ! NOT operator */ +#include <algorithm> + #include "condparser.h" #include "config.h" #include "message.h" @@ -27,7 +29,7 @@ /** * parses and evaluates the given expression. - * @returns + * @returns * - On error, an error message is returned. * - On success, the result of the expression is either "1" or "0". */ @@ -102,8 +104,7 @@ static bool isAlpha(const char c) static bool isAlphaNumSpec(const char c) { - return isAlpha(c) || (c>='0' && c<='9') || c=='-' || c=='.' || - (((unsigned char)c)>=0x80 && ((unsigned char)c)<=0xFF); + return isAlpha(c) || (c>='0' && c<='9') || c=='-' || c=='.' || (((unsigned char)c)>=0x80); } /** @@ -124,13 +125,13 @@ int CondParser::getOperatorId(const QCString &opName) /** * Get next token in the current string expr. - * Uses the data in m_expr pointed to by m_e to + * Uses the data in m_expr pointed to by m_e to * produce m_tokenType and m_token, set m_err in case of an error */ void CondParser::getToken() { m_tokenType = NOTHING; - m_token.resize(0); + m_token.resize(0); //printf("\tgetToken e:{%c}, ascii=%i, col=%i\n", *e, *e, e-expr); @@ -304,7 +305,7 @@ bool CondParser::evalOperator(int opId, bool lhs, bool rhs) */ bool CondParser::evalVariable(const char *varName) { - if (Config_getList(ENABLED_SECTIONS).find(varName)==-1) return FALSE; - return TRUE; + const StringVector &list = Config_getList(ENABLED_SECTIONS); + return std::find(list.begin(),list.end(),varName)!=list.end(); } diff --git a/src/config.h b/src/config.h index 1b79b1e..31be3a1 100644 --- a/src/config.h +++ b/src/config.h @@ -24,19 +24,24 @@ class FTextStream; //! @{ //! some convenience macros for accessing the config options //! mainly done like this for backward compatibility -#if DYNAMIC_LOOKUP // for debug purposes -#define Config_getString(val) (ConfigValues::instance().*((ConfigValues::InfoString*)ConfigValues::instance().get(#val))->item) -#define Config_getBool(val) (ConfigValues::instance().*((ConfigValues::InfoBool*)ConfigValues::instance().get(#val))->item) -#define Config_getInt(val) (ConfigValues::instance().*((ConfigValues::InfoInt*)ConfigValues::instance().get(#val))->item) -#define Config_getEnum(val) (ConfigValues::instance().*((ConfigValues::InfoString*)ConfigValues::instance().get(#val))->item) -#define Config_getList(val) (ConfigValues::instance().*((ConfigValues::InfoList*)ConfigValues::instance().get(#val))->item) -#else // direct access -#define Config_getString(val) (ConfigValues::instance().val) -#define Config_getBool(val) (ConfigValues::instance().val) -#define Config_getInt(val) (ConfigValues::instance().val) -#define Config_getEnum(val) (ConfigValues::instance().val) -#define Config_getList(val) (ConfigValues::instance().val) -#endif +//#if DYNAMIC_LOOKUP // for debug purposes +//#define Config_getString(val) (ConfigValues::instance().*((ConfigValues::InfoString*)ConfigValues::instance().get(#val))->item) +//#define Config_getBool(val) (ConfigValues::instance().*((ConfigValues::InfoBool*)ConfigValues::instance().get(#val))->item) +//#define Config_getInt(val) (ConfigValues::instance().*((ConfigValues::InfoInt*)ConfigValues::instance().get(#val))->item) +//#define Config_getEnum(val) (ConfigValues::instance().*((ConfigValues::InfoString*)ConfigValues::instance().get(#val))->item) +//#define Config_getList(val) (ConfigValues::instance().*((ConfigValues::InfoList*)ConfigValues::instance().get(#val))->item) +//#else // direct access +#define Config_getString(name) (ConfigValues::instance().name()) +#define Config_getBool(name) (ConfigValues::instance().name()) +#define Config_getInt(name) (ConfigValues::instance().name()) +#define Config_getEnum(name) (ConfigValues::instance().name()) +#define Config_getList(name) (ConfigValues::instance().name()) +#define Config_updateString(name,value) (ConfigValues::instance().update_##name(value)); +#define Config_updateBool(name,value) (ConfigValues::instance().update_##name(value)); +#define Config_updateInt(name,value) (ConfigValues::instance().update_##name(value)); +#define Config_updateEnum(name,value) (ConfigValues::instance().update_##name(value)); +#define Config_updateList(name,...) (ConfigValues::instance().update_##name(__VA_ARGS__)); +//#endif //! @} /** \brief Public function to deal with the configuration file. */ diff --git a/src/config.xml b/src/config.xml index f40744d..b3718be 100644 --- a/src/config.xml +++ b/src/config.xml @@ -513,6 +513,16 @@ Go to the <a href="commands.html">next</a> section or return to the ]]> </docs> </option> + <option type='bool' id='PYTHON_DOCSTRING' defval='1'> + <docs> +<![CDATA[ + By default Python docstrings are displayed as preformatted text + and doxygen's special commands cannot be used. By setting \c PYTHON_DOCSTRING to + \c NO the doxygen's special commands can be used and the contents of the docstring + documentation blocks is shown as doxygen documentation. +]]> + </docs> + </option> <option type='bool' id='INHERIT_DOCS' defval='1'> <docs> <![CDATA[ @@ -585,16 +595,6 @@ Go to the <a href="commands.html">next</a> section or return to the ]]> </docs> </option> - <option type='list' id='TCL_SUBST' format='string'> - <docs> -<![CDATA[ - This tag can be used to specify a number of word-keyword mappings (TCL only). - A mapping has the form <code>"name=value"</code>. For example adding - <code>"class=itcl::class"</code> will allow you to use the command class in the - <code>itcl::class</code> meaning. -]]> - </docs> - </option> <option type='bool' id='OPTIMIZE_OUTPUT_FOR_C' defval='0'> <docs> <![CDATA[ @@ -649,10 +649,10 @@ Go to the <a href="commands.html">next</a> section or return to the Doxygen has a built-in mapping, but you can override or extend it using this tag. The format is <code>ext=language</code>, where \c ext is a file extension, and language is one of the parsers supported by doxygen: IDL, Java, JavaScript, Csharp (C#), C, C++, D, PHP, - md (Markdown), Objective-C, Python, Slice, Fortran (fixed format Fortran: FortranFixed, + md (Markdown), Objective-C, Python, Slice, VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: Fortran. In the later case the parser tries to guess whether the code is fixed or free - formatted code, this is the default for Fortran type files), VHDL, tcl. + formatted code, this is the default for Fortran type files). For instance to make doxygen treat <code>.inc</code> files as Fortran files (default is PHP), and <code>.f</code> files as C (default is Fortran), @@ -822,6 +822,21 @@ Go to the <a href="commands.html">next</a> section or return to the ]]> </docs> </option> + <option type='int' id='NUM_PROC_THREADS' defval='1' minval='0' maxval='32'> + <docs> +<![CDATA[ + The \c NUM_PROC_THREADS specifies the number threads doxygen is allowed to use during + processing. When set to \c 0 doxygen will based this on the number of cores + available in the system. You can set it explicitly to a value larger than 0 + to get more control over the balance between CPU load and processing speed. + At this moment only the input processing can be done using multiple threads. + Since this is still an experimental feature the default is set to 1, + which efficively disables parallel processing. Please report any issues you + encounter. + Generating dot graphs in parallel is controlled by the \c DOT_NUM_THREADS setting. +]]> + </docs> + </option> </group> <group name='Build' docs='Build related configuration options'> <option type='bool' id='EXTRACT_ALL' defval='0'> @@ -960,7 +975,7 @@ Go to the <a href="commands.html">next</a> section or return to the will only generate file names in lower-case letters. If set to \c YES, upper-case letters are also allowed. This is useful if you have classes or files whose names only differ in case and if your file system - supports case sensitive file names. Windows (including Cygwin) ands + supports case sensitive file names. Windows (including Cygwin) and Mac users are advised to set this option to \c NO. ]]> </docs> @@ -1413,9 +1428,9 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" <value name='*.f95'/> <value name='*.f03'/> <value name='*.f08'/> + <value name='*.f18'/> <value name='*.f'/> <value name='*.for'/> - <value name='*.tcl'/> <value name='*.vhd'/> <value name='*.vhdl'/> <value name='*.ucf'/> @@ -1715,10 +1730,12 @@ to disable this feature. <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 passed to the parser. + path to the directory containing a file called compile_commands.json. + This file is the <a href="http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html"> + compilation database</a> containing the options used when the source files were built. + This is equivalent to specifying the "-p" option to a clang tool, such as clang-check. + These options will then be passed to the parser. Any options specified with + \ref cfg_clang_options "CLANG_OPTIONS" will be added as well. @note The availability of this option depends on whether or not doxygen was generated with the `-Duse_libclang=ON` option for CMake. @@ -2164,7 +2181,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <![CDATA[ The \c GENERATE_CHI flag controls if a separate `.chi` index file is generated (\c YES) or that - it should be included in the master `.chm` file (\c NO). + it should be included in the main `.chm` file (\c NO). ]]> </docs> </option> @@ -2357,6 +2374,18 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. ]]> </docs> </option> + <option type='enum' id='HTML_FORMULA_FORMAT' defval='png' depends='GENERATE_HTML'> + <docs> +<![CDATA[ + If the \c HTML_FORMULA_FORMAT option is set to \c svg, doxygen will use the pdf2svg + tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see https://inkscape.org) + to generate formulas as SVG images instead of + PNGs for the HTML output. These images will generally look nicer at scaled resolutions. +]]> + </docs> + <value name="png" desc="(the default)"/> + <value name="svg" desc="(looks nicer but requires the pdf2svg or inkscape tool)"/> + </option> <option type='int' id='FORMULA_FONTSIZE' minval='8' maxval='50' defval='10' depends='GENERATE_HTML'> <docs> <![CDATA[ @@ -2415,7 +2444,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <value name="NativeMML" desc="(i.e. MathML)"/> <value name="SVG"/> </option> - <option type='string' id='MATHJAX_RELPATH' format='string' defval='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/' depends='USE_MATHJAX'> + <option type='string' id='MATHJAX_RELPATH' format='string' defval='https://cdn.jsdelivr.net/npm/mathjax@2' depends='USE_MATHJAX'> <docs> <![CDATA[ When MathJax is enabled you need to specify the location relative to the @@ -2754,9 +2783,12 @@ or <option type='bool' id='USE_PDFLATEX' defval='1' depends='GENERATE_LATEX'> <docs> <![CDATA[ - If the \c USE_PDFLATEX tag is set to \c YES, doxygen will use - \c pdflatex to generate the PDF file directly from the \f$\mbox{\LaTeX}\f$ + If the \c USE_PDFLATEX tag is set to \c YES, doxygen will use the engine + as specified with \ref cfg_latex_cmd_name "LATEX_CMD_NAME" + to generate the PDF file directly from the \f$\mbox{\LaTeX}\f$ files. Set this option to \c YES, to get a higher quality PDF documentation. +<br> + See also section \ref cfg_latex_cmd_name "LATEX_CMD_NAME" for selecting the engine. ]]> </docs> </option> @@ -3027,9 +3059,8 @@ front of it. </docs> </option> </group> -<!-- - <group name='Sqlite3' docs='Configuration options related to Sqlite3 output'> - <option type='bool' id='GENERATE_SQLITE3' defval='0'> + <group name='Sqlite3' setting='USE_SQLITE3' docs='Configuration options related to Sqlite3 output'> + <option type='bool' id='GENERATE_SQLITE3' setting='USE_SQLITE3' defval='0'> <docs> <![CDATA[ If the \c GENERATE_SQLITE3 tag is set to \c YES doxygen will generate a @@ -3037,7 +3068,7 @@ If the \c GENERATE_SQLITE3 tag is set to \c YES doxygen will generate a ]]> </docs> </option> - <option type='string' id='SQLITE3_OUTPUT' format='dir' defval='sqlite3' depends='GENERATE_SQLITE3'> + <option type='string' id='SQLITE3_OUTPUT' format='dir' defval='sqlite3' setting='USE_SQLITE3' depends='GENERATE_SQLITE3'> <docs> <![CDATA[ The \c SQLITE3_OUTPUT tag is used to specify where the \c Sqlite3 database will be put. @@ -3046,9 +3077,17 @@ put in front of it. ]]> </docs> </option> + <option type='bool' id='SQLITE3_RECREATE_DB' defval='1' setting='USE_SQLITE3' depends='GENERATE_SQLITE3'> + <docs> +<![CDATA[ +The \c SQLITE3_OVERWRITE_DB tag is set to \c YES, the existing doxygen_sqlite3.db +database file will be recreated with each doxygen run. +If set to \c NO, doxygen will warn if an a database file is already found and not modify it. +]]> + </docs> + </option> </group> ---> <group name='PerlMod' docs='Configuration options related to the Perl module output'> <option type='bool' id='GENERATE_PERLMOD' defval='0'> <docs> @@ -3643,5 +3682,6 @@ remove the intermediate dot files that are used to generate the various graphs. <option type='obsolete' id='XML_DTD'/> <option type='obsolete' id='PERL_PATH'/> <option type='obsolete' id='MSCGEN_PATH'/> + <option type='obsolete' id='TCL_SUBST'/> </group> </doxygenconfig> diff --git a/src/configgen.py b/src/configgen.py index 6720116..4ffa8f8 100755 --- a/src/configgen.py +++ b/src/configgen.py @@ -345,6 +345,9 @@ def parseOption(node): def parseGroups(node): name = node.getAttribute('name') doc = node.getAttribute('docs') + setting = node.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) print("%s%s" % (" //-----------------------------------------", "----------------------------------")) print(" cfg->addInfo(\"%s\",\"%s\");" % (name, doc)) @@ -354,9 +357,40 @@ def parseGroups(node): for n in node.childNodes: if n.nodeType == Node.ELEMENT_NODE: parseOption(n) + if len(setting) > 0: + print("#endif") + + +def parseGroupMapGetter(node): + map = { 'bool':'bool', 'string':'const QCString &', 'enum':'const QCString &', 'int':'int', 'list':'const StringVector &' } + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + setting = n.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + type = n.getAttribute('type') + name = n.getAttribute('id') + if type in map: + print(" %-20s %-30s const { return m_%s; }" % (map[type],name+'()',name)) + if len(setting) > 0: + print("#endif") + +def parseGroupMapSetter(node): + map = { 'bool':'bool', 'string':'const QCString &', 'enum':'const QCString &', 'int':'int', 'list':'const StringVector &' } + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + setting = n.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + type = n.getAttribute('type') + name = n.getAttribute('id') + if type in map: + print(" %-20s update_%-46s { m_%s = v; return m_%s; }" % (map[type],name+'('+map[type]+' v)',name,name)) + if len(setting) > 0: + print("#endif") -def parseGroupMap(node): - map = { 'bool':'bool', 'string':'QCString', 'enum':'QCString', 'int':'int', 'list':'QStrList' } +def parseGroupMapVar(node): + map = { 'bool':'bool', 'string':'QCString', 'enum':'QCString', 'int':'int', 'list':'StringVector' } for n in node.childNodes: if n.nodeType == Node.ELEMENT_NODE: setting = n.getAttribute('setting') @@ -365,7 +399,7 @@ def parseGroupMap(node): type = n.getAttribute('type') name = n.getAttribute('id') if type in map: - print(" %-8s %s;" % (map[type],name)) + print(" %-12s m_%s;" % (map[type],name)) if len(setting) > 0: print("#endif") @@ -379,7 +413,7 @@ def parseGroupInit(node): type = n.getAttribute('type') name = n.getAttribute('id') if type in map: - print(" %-25s = ConfigImpl::instance()->get%s(__FILE__,__LINE__,\"%s\");" % (name,map[type],name)) + print(" %-25s = ConfigImpl::instance()->get%s(__FILE__,__LINE__,\"%s\");" % ('m_'+name,map[type],name)) if len(setting) > 0: print("#endif") @@ -393,7 +427,7 @@ def parseGroupMapInit(node): type = n.getAttribute('type') name = n.getAttribute('id') if type in map: - print(" m_map.insert(\"%s\",new Info%s(&ConfigValues::%s));" % (name,map[type],name)) + print(" { %-25s Info{ %-13s &ConfigValues::m_%s }}," % ('\"'+name+'\",','Info::'+map[type]+',',name)) if len(setting) > 0: print("#endif") @@ -652,6 +686,7 @@ def main(): print("#include <qdict.h>") print("#include <qstrlist.h>") print("#include <qcstring.h>") + print("#include \"containers.h\"") print("#include \"settings.h\"") print("") print("class ConfigValues") @@ -661,42 +696,38 @@ def main(): for n in elem.childNodes: if n.nodeType == Node.ELEMENT_NODE: if (n.nodeName == "group"): - parseGroupMap(n) + parseGroupMapGetter(n) + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroupMapSetter(n) print(" void init();") - print(" struct Info") - print(" {") - print(" enum Type { Bool, Int, String, List, Unknown };") - print(" Info(Type t) : type(t) {}") - print(" virtual ~Info() {}") - print(" Type type;") - print(" };") - print(" struct InfoBool : public Info") - print(" {") - print(" InfoBool(bool ConfigValues::*ptm) : Info(Info::Bool), item(ptm) {}") - print(" bool ConfigValues::*item;") - print(" };") - print(" struct InfoInt : public Info") - print(" {") - print(" InfoInt(int ConfigValues::*ptm) : Info(Info::Int), item(ptm) {}") - print(" int ConfigValues::*item;") - print(" };") - print(" struct InfoString : public Info") - print(" {") - print(" InfoString(QCString ConfigValues::*ptm) : Info(Info::String), item(ptm) {}") - print(" QCString ConfigValues::*item;") - print(" };") - print(" struct InfoList : public Info") - print(" {") - print(" InfoList(QStrList ConfigValues::*ptm) : Info(Info::List), item(ptm) {}") - print(" QStrList ConfigValues::*item;") - print(" };") - print(" const Info *get(const char *tag) const") - print(" {") - print(" return m_map.find(tag);") - print(" }") + print(" struct Info"); + print(" {"); + print(" enum Type { Bool, Int, String, List, Unknown };"); + print(" Info(Type t,bool ConfigValues::*b) : type(t), value(b) {}"); + print(" Info(Type t,int ConfigValues::*i) : type(t), value(i) {}"); + print(" Info(Type t,QCString ConfigValues::*s) : type(t), value(s) {}"); + print(" Info(Type t,StringVector ConfigValues::*l) : type(t), value(l) {}"); + print(" Type type;"); + print(" union Item"); + print(" {"); + print(" Item(bool ConfigValues::*v) : b(v) {}"); + print(" Item(int ConfigValues::*v) : i(v) {}"); + print(" Item(QCString ConfigValues::*v) : s(v) {}"); + print(" Item(StringVector ConfigValues::*v) : l(v) {}"); + print(" bool ConfigValues::*b;"); + print(" int ConfigValues::*i;"); + print(" QCString ConfigValues::*s;"); + print(" StringVector ConfigValues::*l;"); + print(" } value;"); + print(" };"); + print(" const Info *get(const char *tag) const;"); print(" private:") - print(" ConfigValues();") - print(" QDict<Info> m_map;") + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroupMapVar(n) print("};") print("") print("#endif") @@ -707,15 +738,20 @@ def main(): print(" */") print("#include \"configvalues.h\"") print("#include \"configimpl.h\"") + print("#include <unordered_map>") print("") - print("ConfigValues::ConfigValues() : m_map(257)") - print("{") - print(" m_map.setAutoDelete(TRUE);") + print("const ConfigValues::Info *ConfigValues::get(const char *tag) const"); + print("{"); + print(" static const std::unordered_map< std::string, Info > configMap ="); + print(" {"); for n in elem.childNodes: if n.nodeType == Node.ELEMENT_NODE: if (n.nodeName == "group"): parseGroupMapInit(n) - print("}") + print(" };"); + print(" auto it = configMap.find(tag);"); + print(" return it!=configMap.end() ? &it->second : nullptr;"); + print("}"); print("") print("void ConfigValues::init()") print("{") diff --git a/src/configimpl.h b/src/configimpl.h index 6b85d8a..a267cc6 100644 --- a/src/configimpl.h +++ b/src/configimpl.h @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -24,6 +24,7 @@ #include <qlist.h> #include <qregexp.h> #include "ftextstream.h" +#include "containers.h" /** Abstract base class for any configuration option. @@ -35,8 +36,8 @@ class ConfigOption public: /*! The type of option */ - enum OptionType - { + enum OptionType + { O_Info, //!< A section header O_List, //!< A list of items O_Enum, //!< A fixed set of items @@ -46,14 +47,14 @@ class ConfigOption O_Obsolete, //!< An obsolete option O_Disabled //!< Disabled compile time option }; - enum - { - /*! Maximum length of an option in the config file. Used for + enum + { + /*! Maximum length of an option in the config file. Used for * alignment purposes. */ - MAX_OPTION_LENGTH = 23 + MAX_OPTION_LENGTH = 23 }; - ConfigOption(OptionType t) : m_kind(t) + ConfigOption(OptionType t) : m_kind(t) { m_spaces.fill(' ',40); } @@ -81,8 +82,8 @@ class ConfigOption void writeBoolValue(FTextStream &t,bool v); void writeIntValue(FTextStream &t,int i); - void writeStringValue(FTextStream &t,QCString &s); - void writeStringList(FTextStream &t,QStrList &l); + void writeStringValue(FTextStream &t,const QCString &s); + void writeStringList(FTextStream &t,const StringVector &l); QCString m_spaces; QCString m_name; @@ -98,7 +99,7 @@ class ConfigOption class ConfigInfo : public ConfigOption { public: - ConfigInfo(const char *name,const char *doc) + ConfigInfo(const char *name,const char *doc) : ConfigOption(O_Info) { m_name = name; @@ -115,25 +116,25 @@ class ConfigList : public ConfigOption { public: enum WidgetType { String, File, Dir, FileAndDir }; - ConfigList(const char *name,const char *doc) + ConfigList(const char *name,const char *doc) : ConfigOption(O_List) { m_name = name; m_doc = doc; m_widgetType = String; } - void addValue(const char *v) { m_defaultValue.append(v); } + void addValue(const char *v) { m_defaultValue.push_back(v); } void setWidgetType(WidgetType w) { m_widgetType = w; } WidgetType widgetType() const { return m_widgetType; } - QStrList *valueRef() { return &m_value; } - QStrList getDefault() { return m_defaultValue; } + StringVector *valueRef() { return &m_value; } + StringVector getDefault() { return m_defaultValue; } void writeTemplate(FTextStream &t,bool sl,bool); void compareDoxyfile(FTextStream &t); void substEnvVars(); void init() { m_value = m_defaultValue; } private: - QStrList m_value; - QStrList m_defaultValue; + StringVector m_value; + StringVector m_defaultValue; WidgetType m_widgetType; }; @@ -142,7 +143,7 @@ class ConfigList : public ConfigOption class ConfigEnum : public ConfigOption { public: - ConfigEnum(const char *name,const char *doc,const char *defVal) + ConfigEnum(const char *name,const char *doc,const char *defVal) : ConfigOption(O_Enum) { m_name = name; @@ -151,13 +152,14 @@ class ConfigEnum : public ConfigOption m_defValue = defVal; } void addValue(const char *v) { m_valueRange.append(v); } - QStrListIterator iterator() + QStrListIterator iterator() { return QStrListIterator(m_valueRange); } QCString *valueRef() { return &m_value; } void substEnvVars(); void writeTemplate(FTextStream &t,bool sl,bool); + void convertStrToVal(); void compareDoxyfile(FTextStream &t); void init() { m_value = m_defValue.copy(); } @@ -173,7 +175,7 @@ class ConfigString : public ConfigOption { public: enum WidgetType { String, File, Dir, Image }; - ConfigString(const char *name,const char *doc) + ConfigString(const char *name,const char *doc) : ConfigOption(O_String) { m_name = name; @@ -192,7 +194,7 @@ class ConfigString : public ConfigOption void substEnvVars(); void init() { m_value = m_defValue.copy(); } void emptyValueToDefault() { if(m_value.isEmpty()) m_value=m_defValue; }; - + private: QCString m_value; QCString m_defValue; @@ -204,7 +206,7 @@ class ConfigString : public ConfigOption class ConfigInt : public ConfigOption { public: - ConfigInt(const char *name,const char *doc,int minVal,int maxVal,int defVal) + ConfigInt(const char *name,const char *doc,int minVal,int maxVal,int defVal) : ConfigOption(O_Int) { m_name = name; @@ -236,7 +238,7 @@ class ConfigInt : public ConfigOption class ConfigBool : public ConfigOption { public: - ConfigBool(const char *name,const char *doc,bool defVal) + ConfigBool(const char *name,const char *doc,bool defVal) : ConfigOption(O_Bool) { m_name = name; @@ -263,7 +265,7 @@ class ConfigBool : public ConfigOption class ConfigObsolete : public ConfigOption { public: - ConfigObsolete(const char *name) : ConfigOption(O_Obsolete) + ConfigObsolete(const char *name) : ConfigOption(O_Obsolete) { m_name = name; } void writeTemplate(FTextStream &,bool,bool); void compareDoxyfile(FTextStream &) {} @@ -275,7 +277,7 @@ class ConfigObsolete : public ConfigOption class ConfigDisabled : public ConfigOption { public: - ConfigDisabled(const char *name) : ConfigOption(O_Disabled) + ConfigDisabled(const char *name) : ConfigOption(O_Disabled) { m_name = name; } void writeTemplate(FTextStream &,bool,bool); void compareDoxyfile(FTextStream &) {} @@ -296,7 +298,7 @@ class ConfigDisabled : public ConfigOption * read from a user-supplied configuration file. * The static member instance() can be used to get * a pointer to the one and only instance. - * + * * Set all variables to their default values by * calling Config::instance()->init() * @@ -320,8 +322,8 @@ class ConfigImpl delete m_instance; m_instance=0; } - - /*! Returns an iterator that can by used to iterate over the + + /*! Returns an iterator that can by used to iterate over the * configuration options. */ QListIterator<ConfigOption> iterator() @@ -329,36 +331,36 @@ class ConfigImpl return QListIterator<ConfigOption>(*m_options); } - /*! + /*! * @name Getting configuration values. * @{ */ - /*! Returns the value of the string option with name \a fileName. + /*! Returns the value of the string option with name \a fileName. * The arguments \a num and \a name are for debugging purposes only. * There is a convenience function Config_getString() for this. */ QCString &getString(const char *fileName,int num,const char *name) const; - /*! Returns the value of the list option with name \a fileName. + /*! Returns the value of the list option with name \a fileName. * The arguments \a num and \a name are for debugging purposes only. * There is a convenience function Config_getList() for this. */ - QStrList &getList(const char *fileName,int num,const char *name) const; + StringVector &getList(const char *fileName,int num,const char *name) const; - /*! Returns the value of the enum option with name \a fileName. + /*! Returns the value of the enum option with name \a fileName. * The arguments \a num and \a name are for debugging purposes only. * There is a convenience function Config_getEnum() for this. */ QCString &getEnum(const char *fileName,int num,const char *name) const; - /*! Returns the value of the integer option with name \a fileName. + /*! Returns the value of the integer option with name \a fileName. * The arguments \a num and \a name are for debugging purposes only. * There is a convenience function Config_getInt() for this. */ int &getInt(const char *fileName,int num,const char *name) const; - /*! Returns the value of the boolean option with name \a fileName. + /*! Returns the value of the boolean option with name \a fileName. * The arguments \a num and \a name are for debugging purposes only. * There is a convenience function Config_getBool() for this. */ @@ -369,12 +371,12 @@ class ConfigImpl */ ConfigOption *get(const char *name) const { - return m_dict->find(name); + return m_dict->find(name); } /* @} */ - /*! - * @name Adding configuration options. + /*! + * @name Adding configuration options. * @{ */ @@ -401,7 +403,7 @@ class ConfigImpl } /*! Adds a new enumeration option with \a name and documentation \a doc - * and initial value \a defVal. + * and initial value \a defVal. * \returns An object representing the option. */ ConfigEnum *addEnum(const char *name, @@ -509,18 +511,18 @@ class ConfigImpl /*! Parse a configuration data in string \a str. * \returns TRUE if successful, or FALSE if the string could not be * parsed. - */ + */ //bool parseString(const char *fn,const char *str); bool parseString(const char *fn,const char *str,bool upd = FALSE); /*! Parse a configuration file with name \a fn. - * \returns TRUE if successful, FALSE if the file could not be + * \returns TRUE if successful, FALSE if the file could not be * opened or read. - */ + */ bool parse(const char *fn,bool upd = FALSE); /*! Called from the constructor, will add doxygen's default options - * to the configuration object + * to the configuration object */ void create(); diff --git a/src/configimpl.l b/src/configimpl.l index 4da1634..ed23a12 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -1,16 +1,19 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * */ %option never-interactive %option prefix="configimplYY" +%top{ +#include <stdint.h> +} %{ @@ -26,12 +29,13 @@ #include <qfileinfo.h> #include <qdir.h> -#include <qtextstream.h> #include <qregexp.h> #include <qstack.h> #include <qglobal.h> -#include <qthread.h> - + +#include <thread> +#include <algorithm> + #include "configimpl.h" #include "version.h" #include "portable.h" @@ -44,7 +48,11 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + +#if USE_STATE2STRING static const char *stateToString(int state); +#endif static const char *warning_str = "warning: "; static const char *error_str = "error: "; @@ -54,7 +62,7 @@ void config_err(const char *fmt, ...) va_list args; va_start(args, fmt); vfprintf(stderr, (QCString(error_str) + fmt).data(), args); - va_end(args); + va_end(args); } void config_term(const char *fmt, ...) { @@ -93,20 +101,27 @@ static QCString convertToComment(const QCString &s, const QCString &u) QCString tmp=s.stripWhiteSpace(); const char *p=tmp.data(); char c; - result+="#"; - if (*p && *p!='\n') - result+=" "; - while ((c=*p++)) + if (p) { - if (c=='\n') + result+="#"; + if (*p && *p!='\n') + { + result+=" "; + } + while ((c=*p++)) { - result+="\n#"; - if (*p && *p!='\n') - result+=" "; + if (c=='\n') + { + result+="\n#"; + if (*p && *p!='\n') + { + result+=" "; + } + } + else result+=c; } - else result+=c; + result+='\n'; } - result+='\n'; } if (!u.isEmpty()) { @@ -127,20 +142,20 @@ void ConfigOption::writeIntValue(FTextStream &t,int i) t << " " << i; } -void ConfigOption::writeStringValue(FTextStream &t,QCString &s) +void ConfigOption::writeStringValue(FTextStream &t,const QCString &s) { char c; bool needsEscaping=FALSE; - // convert the string back to it original encoding + // convert the string back to it original g_encoding QCString se = configStringRecode(s,"UTF-8",m_encoding); const char *p=se.data(); if (p) { t << " "; - while ((c=*p++)!=0 && !needsEscaping) + while ((c=*p++)!=0 && !needsEscaping) needsEscaping = (c==' ' || c=='\n' || c=='\t' || c=='"' || c=='#'); if (needsEscaping) - { + { t << "\""; p=se.data(); while (*p) @@ -158,19 +173,17 @@ void ConfigOption::writeStringValue(FTextStream &t,QCString &s) } } -void ConfigOption::writeStringList(FTextStream &t,QStrList &l) +void ConfigOption::writeStringList(FTextStream &t,const StringVector &l) { - const char *p = l.first(); bool first=TRUE; - while (p) + for (const auto &p : l) { - QCString s=p; + if (!first) t << " \\" << endl; + QCString s=p.c_str(); if (!first) t << " "; - first=FALSE; writeStringValue(t,s); - p = l.next(); - if (p) t << " \\" << endl; + first=FALSE; } } @@ -179,7 +192,7 @@ void ConfigOption::writeStringList(FTextStream &t,QStrList &l) ConfigImpl *ConfigImpl::m_instance = 0; -void ConfigInt::convertStrToVal() +void ConfigInt::convertStrToVal() { if (!m_valueString.isEmpty()) { @@ -202,7 +215,7 @@ void ConfigBool::convertStrToVal() QCString val = m_valueString.stripWhiteSpace().lower(); if (!val.isEmpty()) { - if (val=="yes" || val=="true" || val=="1" || val=="all") + if (val=="yes" || val=="true" || val=="1" || val=="all") { m_value=TRUE; } @@ -218,10 +231,34 @@ void ConfigBool::convertStrToVal() } } +void ConfigEnum::convertStrToVal() +{ + if (m_value.isEmpty()) + { + m_value = m_defValue; + return; + } + QCString val = m_value.stripWhiteSpace().lower(); + const char *s=m_valueRange.first(); + while (s) + { + if (QCString(s).lower() == val) + { + m_value = s; + return; + } + s = m_valueRange.next(); + } + + config_warn("argument '%s' for option %s is not a valid enum value\n" + "Using the default: %s!\n",m_value.data(),m_name.data(),m_defValue.data()); + m_value = m_defValue; +} + QCString &ConfigImpl::getString(const char *fileName,int num,const char *name) const { ConfigOption *opt = m_dict->find(name); - if (opt==0) + if (opt==0) { config_term("%s<%d>: Internal error: Requested unknown option %s!\n",fileName,num,name); } @@ -232,10 +269,10 @@ QCString &ConfigImpl::getString(const char *fileName,int num,const char *name) c return *((ConfigString *)opt)->valueRef(); } -QStrList &ConfigImpl::getList(const char *fileName,int num,const char *name) const +StringVector &ConfigImpl::getList(const char *fileName,int num,const char *name) const { ConfigOption *opt = m_dict->find(name); - if (opt==0) + if (opt==0) { config_term("%s<%d>: Internal error: Requested unknown option %s!\n",fileName,num,name); } @@ -249,7 +286,7 @@ QStrList &ConfigImpl::getList(const char *fileName,int num,const char *name) con QCString &ConfigImpl::getEnum(const char *fileName,int num,const char *name) const { ConfigOption *opt = m_dict->find(name); - if (opt==0) + if (opt==0) { config_term("%s<%d>: Internal error: Requested unknown option %s!\n",fileName,num,name); } @@ -263,7 +300,7 @@ QCString &ConfigImpl::getEnum(const char *fileName,int num,const char *name) con int &ConfigImpl::getInt(const char *fileName,int num,const char *name) const { ConfigOption *opt = m_dict->find(name); - if (opt==0) + if (opt==0) { config_term("%s<%d>: Internal error: Requested unknown option %s!\n",fileName,num,name); } @@ -277,7 +314,7 @@ int &ConfigImpl::getInt(const char *fileName,int num,const char *name) const bool &ConfigImpl::getBool(const char *fileName,int num,const char *name) const { ConfigOption *opt = m_dict->find(name); - if (opt==0) + if (opt==0) { config_term("%s<%d>: Internal error: Requested unknown option %s!\n",fileName,num,name); } @@ -320,71 +357,33 @@ void ConfigList::writeTemplate(FTextStream &t,bool sl,bool) void ConfigList::compareDoxyfile(FTextStream &t) { - const char *p = m_value.first(); - const char *q = m_defaultValue.first(); - int defCnt = 0; - int valCnt = 0; - - // count non empty elements - while (p) - { - QCString s=p; - if (!s.stripWhiteSpace().isEmpty()) valCnt += 1; - p = m_value.next(); - } - - while (q) - { - QCString s=q; - if (!s.stripWhiteSpace().isEmpty()) defCnt += 1; - q = m_defaultValue.next(); - } + auto get_stripped = [](std::string s) { return QCString(s.c_str()).stripWhiteSpace(); }; + auto is_not_empty = [get_stripped](std::string s) { return !get_stripped(s).isEmpty(); }; + int defCnt = std::count_if( m_value.begin(), m_value.end(),is_not_empty); + int valCnt = std::count_if(m_defaultValue.begin(),m_defaultValue.end(),is_not_empty); if ( valCnt != defCnt) { writeTemplate(t,TRUE,TRUE); return; } - - // get first non empry element - q = m_defaultValue.first(); - p = m_value.first(); - QCString sp = p; - while (p && sp.stripWhiteSpace().isEmpty()) + auto it1 = m_value.begin(); + auto it2 = m_defaultValue.begin(); + while (it1!=m_value.end() && it2!=m_defaultValue.end()) { - p = m_value.next(); - sp = p; - } - QCString sq = q; - while (q && sq.stripWhiteSpace().isEmpty()) - { - q = m_value.next(); - sq = q; - } - while (p) - { - // skip empty elements - sp = p; - while (p && sp.stripWhiteSpace().isEmpty()) - { - p = m_value.next(); - sp = p; - } - sq = q; - while (q && sq.stripWhiteSpace().isEmpty()) + // skip over empty values + while (it1!=m_value.end() && !is_not_empty(*it1)) { - q = m_value.next(); - sq = q; + ++it1; } - // be sure we have still an element (p and q have same number of 'filled' elements) - if (p) + if (it1!=m_value.end()) // non-empty value { - if (sp.stripWhiteSpace() != sq.stripWhiteSpace()) + if (get_stripped(*it1) != get_stripped(*it2)) // not the default, write as difference { writeTemplate(t,TRUE,TRUE); return; } - p = m_value.next(); - q = m_defaultValue.next(); + ++it1; + ++it2; } } } @@ -506,49 +505,49 @@ struct ConfigFileState YY_BUFFER_STATE oldState; YY_BUFFER_STATE newState; QCString fileName; -}; - -static const char *inputString; -static int inputPosition; -static int yyLineNr; -static QCString yyFileName; -static QCString tmpString; -static QCString *s=0; -static bool *b=0; -static QStrList *l=0; -static int lastState; -static QCString elemStr; -static QStrList includePathList; -static QStack<ConfigFileState> includeStack; -static int includeDepth; -static bool config_upd = FALSE; -static QCString encoding; -static ConfigImpl *config; +}; + +static const char *g_inputString; +static int g_inputPosition; +static int g_yyLineNr; +static QCString g_yyFileName; +static QCString g_tmpString; +static QCString *g_string=0; +static bool *g_bool=0; +static StringVector *g_list=0; +static int g_lastState; +static QCString g_elemStr; +static StringVector g_includePathList; +static QStack<ConfigFileState> g_includeStack; +static int g_includeDepth; +static bool g_configUpdate = FALSE; +static QCString g_encoding; +static ConfigImpl *g_config; /* ----------------------------------------------------------------- */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -static int yyread(char *buf,int max_size) +static yy_size_t yyread(char *buf,yy_size_t max_size) { - // no file included - if (includeStack.isEmpty()) - { - int c=0; - if (inputString==0) return c; - while( c < max_size && inputString[inputPosition] ) - { - *buf = inputString[inputPosition++] ; - c++; buf++; - } - return c; - } - else + // no file included + if (g_includeStack.isEmpty()) + { + yy_size_t c=0; + if (g_inputString==0) return c; + while( c < max_size && g_inputString[g_inputPosition] ) { - //assert(includeStack.current()->newState==YY_CURRENT_BUFFER); - return (int)fread(buf,1,max_size,includeStack.current()->filePtr); + *buf = g_inputString[g_inputPosition++] ; + c++; buf++; } + return c; + } + else + { + //assert(g_includeStack.current()->newState==YY_CURRENT_BUFFER); + return (yy_size_t)fread(buf,1,max_size,g_includeStack.current()->filePtr); + } } @@ -564,7 +563,7 @@ static QCString configStringRecode( int outputSize=inputSize*4+1; QCString output(outputSize); void *cd = portable_iconv_open(outputEncoding,inputEncoding); - if (cd==(void *)(-1)) + if (cd==(void *)(-1)) { config_term("Error: unsupported character conversion: '%s'->'%s'\n", inputEncoding.data(),outputEncoding.data()); @@ -591,8 +590,8 @@ static QCString configStringRecode( static void checkEncoding() { - ConfigString *option = (ConfigString*)config->get("DOXYFILE_ENCODING"); - encoding = *option->valueRef(); + ConfigString *option = (ConfigString*)g_config->get("DOXYFILE_ENCODING"); + g_encoding = *option->valueRef(); } static FILE *tryPath(const char *path,const char *fileName) @@ -608,7 +607,7 @@ static FILE *tryPath(const char *path,const char *fileName) return 0; } -static void substEnvVarsInStrList(QStrList &sl); +static void substEnvVarsInStrList(StringVector &sl); static void substEnvVarsInString(QCString &s); static FILE *findFile(const char *fileName) @@ -621,24 +620,22 @@ static FILE *findFile(const char *fileName) { return tryPath(NULL, fileName); } - substEnvVarsInStrList(includePathList); - char *s=includePathList.first(); - while (s) // try each of the include paths + substEnvVarsInStrList(g_includePathList); + for (const auto &s : g_includePathList) { - FILE *f = tryPath(s,fileName); + FILE *f = tryPath(s.c_str(),fileName); if (f) return f; - s=includePathList.next(); - } - // try cwd if includePathList fails + } + // try cwd if g_includePathList fails return tryPath(".",fileName); } static void readIncludeFile(const char *incName) { - if (includeDepth==MAX_INCLUDE_DEPTH) { + if (g_includeDepth==MAX_INCLUDE_DEPTH) { config_term("maximum include depth (%d) reached, %s is not included. Aborting...\n", MAX_INCLUDE_DEPTH,incName); - } + } QCString inc = incName; substEnvVarsInString(inc); @@ -655,24 +652,24 @@ static void readIncludeFile(const char *incName) { // For debugging #if SHOW_INCLUDES - for (i=0;i<includeStack.count();i++) msg(" "); + for (i=0;i<g_includeStack.count();i++) msg(" "); msg("@INCLUDE = %s: parsing...\n",inc.data()); #endif - // store the state of the old file + // store the state of the old file ConfigFileState *fs=new ConfigFileState; fs->oldState=YY_CURRENT_BUFFER; - fs->lineNr=yyLineNr; - fs->fileName=yyFileName; + fs->lineNr=g_yyLineNr; + fs->fileName=g_yyFileName; fs->filePtr=f; // push the state on the stack - includeStack.push(fs); + g_includeStack.push(fs); // set the scanner to the include file yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); fs->newState=YY_CURRENT_BUFFER; - yyFileName=inc; - includeDepth++; - } + g_yyFileName=inc; + g_includeDepth++; + } else { config_term("@INCLUDE = %s: not found!\n",inc.data()); @@ -691,6 +688,7 @@ static void readIncludeFile(const char *incName) %x GetString %x GetBool %x GetStrList +%x GetStrList1 %x GetQuotedString %x GetEnvVar %x Include @@ -698,26 +696,26 @@ static void readIncludeFile(const char *incName) %% <*>\0x0d -<PreStart>"##".*"\n" { config->appendStartComment(yytext);yyLineNr++;} +<PreStart>"##".*"\n" { g_config->appendStartComment(yytext);g_yyLineNr++;} <PreStart>. { BEGIN(Start); unput(*yytext); } -<Start,GetString,GetStrList,GetBool,SkipInvalid>"##".*"\n" { config->appendUserComment(yytext);yyLineNr++;} -<Start,GetString,GetStrList,GetBool,SkipInvalid>"#" { BEGIN(SkipComment); } +<Start,GetString,GetStrList,GetStrList1,GetBool,SkipInvalid>"##".*"\n" { g_config->appendUserComment(yytext);g_yyLineNr++;} +<Start,GetString,GetStrList,GetStrList1,GetBool,SkipInvalid>"#" { BEGIN(SkipComment); } <Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { QCString cmd=yytext; - cmd=cmd.left(cmd.length()-1).stripWhiteSpace(); - ConfigOption *option = config->get(cmd); + cmd=cmd.left(cmd.length()-1).stripWhiteSpace(); + ConfigOption *option = g_config->get(cmd); if (option==0) // oops not known { config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", - cmd.data(),yyLineNr,yyFileName.data()); + cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); } else // known tag { - option->setUserComment(config->takeUserComment()); - option->setEncoding(encoding); + option->setUserComment(g_config->takeUserComment()); + option->setEncoding(g_encoding); switch(option->kind()) { case ConfigOption::O_Info: @@ -725,56 +723,63 @@ static void readIncludeFile(const char *incName) BEGIN(SkipInvalid); break; case ConfigOption::O_List: - l = ((ConfigList *)option)->valueRef(); - l->clear(); - elemStr=""; - BEGIN(GetStrList); + g_list = ((ConfigList *)option)->valueRef(); + g_list->clear(); + g_elemStr=""; + if (cmd == "PREDEFINED") + { + BEGIN(GetStrList1); + } + else + { + BEGIN(GetStrList); + } break; case ConfigOption::O_Enum: - s = ((ConfigEnum *)option)->valueRef(); - s->resize(0); + g_string = ((ConfigEnum *)option)->valueRef(); + g_string->resize(0); BEGIN(GetString); break; case ConfigOption::O_String: - s = ((ConfigString *)option)->valueRef(); - s->resize(0); + g_string = ((ConfigString *)option)->valueRef(); + g_string->resize(0); BEGIN(GetString); break; case ConfigOption::O_Int: - s = ((ConfigInt *)option)->valueStringRef(); - s->resize(0); + g_string = ((ConfigInt *)option)->valueStringRef(); + g_string->resize(0); BEGIN(GetString); break; case ConfigOption::O_Bool: - s = ((ConfigBool *)option)->valueStringRef(); - s->resize(0); + g_string = ((ConfigBool *)option)->valueStringRef(); + g_string->resize(0); BEGIN(GetString); break; case ConfigOption::O_Obsolete: - if (config_upd) + if (g_configUpdate) { config_warn("Tag '%s' at line %d of file '%s' has become obsolete.\n" - " This tag has been removed.\n", cmd.data(),yyLineNr,yyFileName.data()); + " This tag has been removed.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); } else { config_warn("Tag '%s' at line %d of file '%s' has become obsolete.\n" " To avoid this warning please remove this line from your configuration " - "file or upgrade it using \"doxygen -u\"\n", cmd.data(),yyLineNr,yyFileName.data()); + "file or upgrade it using \"doxygen -u\"\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); } BEGIN(SkipInvalid); break; case ConfigOption::O_Disabled: - if (config_upd) + if (g_configUpdate) { config_warn("Tag '%s' at line %d of file '%s' belongs to an option that was not enabled at compile time.\n" - " This tag has been removed.\n", cmd.data(),yyLineNr,yyFileName.data()); + " This tag has been removed.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); } else { config_warn("Tag '%s' at line %d of file '%s' belongs to an option that was not enabled at compile time.\n" " To avoid this warning please remove this line from your configuration " - "file or upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", cmd.data(),yyLineNr,yyFileName.data()); + "file or upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); } BEGIN(SkipInvalid); break; @@ -782,17 +787,17 @@ static void readIncludeFile(const char *incName) } } <Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { QCString cmd=yytext; - cmd=cmd.left(cmd.length()-2).stripWhiteSpace(); - ConfigOption *option = config->get(cmd); + cmd=cmd.left(cmd.length()-2).stripWhiteSpace(); + ConfigOption *option = g_config->get(cmd); if (option==0) // oops not known { config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", - cmd.data(),yyLineNr,yyFileName.data()); + cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); } else // known tag { - option->setUserComment(config->takeUserComment()); + option->setUserComment(g_config->takeUserComment()); switch(option->kind()) { case ConfigOption::O_Info: @@ -800,135 +805,153 @@ static void readIncludeFile(const char *incName) BEGIN(SkipInvalid); break; case ConfigOption::O_List: - l = ((ConfigList *)option)->valueRef(); - elemStr=""; - BEGIN(GetStrList); + g_list = ((ConfigList *)option)->valueRef(); + g_elemStr=""; + if (cmd == "PREDEFINED") + { + BEGIN(GetStrList1); + } + else + { + BEGIN(GetStrList); + } break; case ConfigOption::O_Enum: case ConfigOption::O_String: case ConfigOption::O_Int: case ConfigOption::O_Bool: config_warn("operator += not supported for '%s'. Ignoring line at line %d, file %s\n", - yytext,yyLineNr,yyFileName.data()); + yytext,g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); break; case ConfigOption::O_Obsolete: config_warn("Tag '%s' at line %d of file %s has become obsolete.\n" "To avoid this warning please update your configuration " - "file using \"doxygen -u\"\n", cmd.data(),yyLineNr,yyFileName.data()); + "file using \"doxygen -u\"\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); break; case ConfigOption::O_Disabled: config_warn("Tag '%s' at line %d of file %s belongs to an option that was not enabled at compile time.\n" "To avoid this warning please remove this line from your configuration " - "file, upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", cmd.data(),yyLineNr,yyFileName.data()); + "file, upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); break; } } } -<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&includePathList; l->clear(); elemStr=""; } - /* include a config file */ +<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); g_list=&g_includePathList; g_list->clear(); g_elemStr=""; } + /* include a g_config file */ <Start>"@INCLUDE"[ \t]*"=" { BEGIN(Include);} -<Include>([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { - readIncludeFile(configStringRecode(yytext,encoding,"UTF-8")); +<Include>([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { + readIncludeFile(configStringRecode(yytext,g_encoding,"UTF-8")); BEGIN(Start); } <<EOF>> { //printf("End of include file\n"); //printf("Include stack depth=%d\n",g_includeStack.count()); - if (includeStack.isEmpty()) + if (g_includeStack.isEmpty()) { //printf("Terminating scanner!\n"); yyterminate(); } else { - ConfigFileState *fs=includeStack.pop(); + ConfigFileState *fs=g_includeStack.pop(); fclose(fs->filePtr); YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER; yy_switch_to_buffer( fs->oldState ); yy_delete_buffer( oldBuf ); - yyLineNr=fs->lineNr; - yyFileName=fs->fileName; + g_yyLineNr=fs->lineNr; + g_yyFileName=fs->fileName; delete fs; fs=0; - includeDepth--; + g_includeDepth--; } } -<Start>[a-z_A-Z0-9]+ { config_warn("ignoring unknown tag '%s' at line %d, file %s\n",yytext,yyLineNr,yyFileName.data()); } -<GetString,GetBool,SkipInvalid>\n { yyLineNr++; BEGIN(Start); } -<GetStrList>\n { - yyLineNr++; - if (!elemStr.isEmpty()) +<Start>[a-z_A-Z0-9]+ { config_warn("ignoring unknown tag '%s' at line %d, file %s\n",yytext,g_yyLineNr,g_yyFileName.data()); } +<GetString,GetBool,SkipInvalid>\n { g_yyLineNr++; BEGIN(Start); } +<GetStrList,GetStrList1>\n { + g_yyLineNr++; + if (!g_elemStr.isEmpty()) { - //printf("elemStr1='%s'\n",elemStr.data()); - l->append(elemStr); + //printf("elemStr1='%s'\n",g_elemStr.data()); + g_list->push_back(g_elemStr.data()); } - BEGIN(Start); + BEGIN(Start); + } +<GetStrList1>[ \t]+ { + if (!g_elemStr.isEmpty()) + { + //printf("elemStr2='%s'\n",g_elemStr.data()); + g_list->push_back(g_elemStr.data()); + } + g_elemStr.resize(0); } <GetStrList>[ \t,]+ { - if (!elemStr.isEmpty()) + if (!g_elemStr.isEmpty()) { - //printf("elemStr2='%s'\n",elemStr.data()); - l->append(elemStr); + //printf("elemStr2='%s'\n",g_elemStr.data()); + g_list->push_back(g_elemStr.data()); } - elemStr.resize(0); + g_elemStr.resize(0); } -<GetString>[^ \"\t\r\n]+ { (*s)+=configStringRecode(yytext,encoding,"UTF-8"); +<GetString>[^ \"\t\r\n]+ { (*g_string)+=configStringRecode(yytext,g_encoding,"UTF-8"); checkEncoding(); } -<GetString,GetStrList,SkipInvalid>"\"" { lastState=YY_START; - BEGIN(GetQuotedString); - tmpString.resize(0); +<GetString,GetStrList,GetStrList1,SkipInvalid>"\"" { g_lastState=YY_START; + BEGIN(GetQuotedString); + g_tmpString.resize(0); } -<GetQuotedString>"\""|"\n" { +<GetQuotedString>"\""|"\n" { // we add a bogus space to signal that the string was quoted. This space will be stripped later on. - tmpString+=" "; - //printf("Quoted String = '%s'\n",tmpString.data()); - if (lastState==GetString) + g_tmpString+=" "; + //printf("Quoted String = '%s'\n",g_tmpString.data()); + if (g_lastState==GetString) { - (*s)+=configStringRecode(tmpString,encoding,"UTF-8"); + (*g_string)+=configStringRecode(g_tmpString,g_encoding,"UTF-8"); checkEncoding(); } else { - elemStr+=configStringRecode(tmpString,encoding,"UTF-8"); + g_elemStr+=configStringRecode(g_tmpString,g_encoding,"UTF-8"); } if (*yytext=='\n') { - config_warn("Missing end quote (\") on line %d, file %s\n",yyLineNr,yyFileName.data()); - yyLineNr++; + config_warn("Missing end quote (\") on line %d, file %s\n",g_yyLineNr,g_yyFileName.data()); + g_yyLineNr++; } - BEGIN(lastState); + BEGIN(g_lastState); } <GetQuotedString>"\\\"" { - tmpString+='"'; + g_tmpString+='"'; } -<GetQuotedString>. { tmpString+=*yytext; } -<GetBool>[a-zA-Z]+ { - QCString bs=yytext; +<GetQuotedString>. { g_tmpString+=*yytext; } +<GetBool>[a-zA-Z]+ { + QCString bs=yytext; bs=bs.upper(); if (bs=="YES" || bs=="1") - *b=TRUE; + *g_bool=TRUE; else if (bs=="NO" || bs=="0") - *b=FALSE; - else + *g_bool=FALSE; + else { - *b=FALSE; + *g_bool=FALSE; config_warn("Invalid value '%s' for " "boolean tag in line %d, file %s; use YES or NO\n", - bs.data(),yyLineNr,yyFileName.data()); + bs.data(),g_yyLineNr,g_yyFileName.data()); } } +<GetStrList1>[^ \#\"\t\r\n]+ { + g_elemStr+=configStringRecode(yytext,g_encoding,"UTF-8"); + } <GetStrList>[^ \#\"\t\r\n,]+ { - elemStr+=configStringRecode(yytext,encoding,"UTF-8"); + g_elemStr+=configStringRecode(yytext,g_encoding,"UTF-8"); } -<SkipComment>\n { yyLineNr++; BEGIN(Start); } -<SkipComment>\\[ \r\t]*\n { yyLineNr++; BEGIN(Start); } -<*>\\[ \r\t]*\n { yyLineNr++; } -<*>. -<*>\n { yyLineNr++ ; } +<SkipComment>\n { g_yyLineNr++; BEGIN(Start); } +<SkipComment>\\[ \r\t]*\n { g_yyLineNr++; BEGIN(Start); } +<*>\\[ \r\t]*\n { g_yyLineNr++; } +<*>. +<*>\n { g_yyLineNr++ ; } %% @@ -940,9 +963,9 @@ void ConfigImpl::writeTemplate(FTextStream &t,bool sl,bool upd) /* print first lines of user comment that were at the beginning of the file, might have special meaning for editors */ if (m_startComment) { - t << takeStartComment() << endl; + t << takeStartComment() << endl; } - t << "# Doxyfile " << getVersion() << endl << endl; + t << "# Doxyfile " << getDoxygenVersion() << endl << endl; if (!sl) { t << convertToComment(m_header,""); @@ -963,11 +986,7 @@ void ConfigImpl::writeTemplate(FTextStream &t,bool sl,bool upd) void ConfigImpl::compareDoxyfile(FTextStream &t) { - t << "# Difference with default Doxyfile " << getVersion(); - if (strlen(getGitVersion())) - { - t << " (" << getGitVersion() << ")"; - } + t << "# Difference with default Doxyfile " << getFullVersion(); t << endl; QListIterator<ConfigOption> it = iterator(); ConfigOption *option; @@ -1018,12 +1037,12 @@ static void substEnvVarsInString(QCString &s) //printf("substEnvVarInString(%s) end\n",s.data()); } -static void substEnvVarsInStrList(QStrList &sl) +static void substEnvVarsInStrList(StringVector &sl) { - char *s = sl.first(); - while (s) + StringVector results; + for (const auto &s : sl) { - QCString result(s); + QCString result = s.c_str(); // an argument with quotes will have an extra space at the end, so wasQuoted will be TRUE. bool wasQuoted = (result.find(' ')!=-1) || (result.find('\t')!=-1); // here we strip the quote again @@ -1033,8 +1052,8 @@ static void substEnvVarsInStrList(QStrList &sl) if (!wasQuoted) /* as a result of the expansion, a single string may have expanded into a list, which we'll - add to sl. If the original string already - contained multiple elements no further + add to sl. If the original string already + contained multiple elements no further splitting is done to allow quoted items with spaces! */ { int l=result.length(); @@ -1045,7 +1064,7 @@ static void substEnvVarsInStrList(QStrList &sl) { char c=0; // skip until start of new word - while (i<l && ((c=result.at(i))==' ' || c=='\t')) i++; + while (i<l && ((c=result.at(i))==' ' || c=='\t')) i++; p=i; // p marks the start index of the word // skip until end of a word while (i<l && ((c=result.at(i))!=' ' && c!='\t' && c!='"')) i++; @@ -1059,11 +1078,9 @@ static void substEnvVarsInStrList(QStrList &sl) c=result.at(i); if (c=='"') // end quote { - // replace the string in the list and go to the next item. - sl.insert(sl.at(),result.mid(p,i-p)); // insert new item before current item. - sl.next(); // current item is now the old item + results.push_back(result.mid(p,i-p).data()); p=i+1; - break; + break; } else if (c=='\\') // skip escaped stuff { @@ -1073,33 +1090,22 @@ static void substEnvVarsInStrList(QStrList &sl) } else if (c==' ' || c=='\t') // separator { - // replace the string in the list and go to the next item. - sl.insert(sl.at(),result.mid(p,i-p)); // insert new item before current item. - sl.next(); // current item is now the old item + if (i>p) results.push_back(result.mid(p,i-p).data()); p=i+1; } } } if (p!=l) // add the leftover as a string { - // replace the string in the list and go to the next item. - sl.insert(sl.at(),result.right(l-p)); // insert new item before current item. - sl.next(); // current item is now the old item + results.push_back(result.right(l-p).data()); } } else // just goto the next element in the list { - sl.insert(sl.at(),result); - sl.next(); + if (!result.isEmpty()) results.push_back(result.data()); } - // remove the old unexpanded string from the list - int i=sl.at(); - sl.remove(); // current item index changes if the last element is removed. - if (sl.at()==i) // not last item - s = sl.current(); - else // just removed last item - s = 0; } + sl = results; } void ConfigString::substEnvVars() @@ -1166,7 +1172,7 @@ void ConfigImpl::init() void ConfigImpl::create() { - if (m_initialized) return; + if (m_initialized) return; m_initialized = TRUE; addConfigOptions(this); } @@ -1183,13 +1189,13 @@ static QCString configFileToString(const char *name) if (fileOpened) { const int bSize=4096; - QCString contents(bSize); + QCString contents(bSize+1); int totalSize=0; int size; while ((size=f.readBlock(contents.rawData()+totalSize,bSize))==bSize) { totalSize+=bSize; - contents.resize(totalSize+bSize); + contents.resize(totalSize+bSize+1); } totalSize+=size+2; contents.resize(totalSize); @@ -1214,7 +1220,7 @@ static QCString configFileToString(const char *name) QCString contents(fsize+2); f.readBlock(contents.rawData(),fsize); f.close(); - if (fsize==0 || contents[fsize-1]=='\n') + if (fsize==0 || contents[fsize-1]=='\n') contents[fsize]='\0'; else contents[fsize]='\n'; // to help the scanner @@ -1222,7 +1228,7 @@ static QCString configFileToString(const char *name) return contents; } } - if (!fileOpened) + if (!fileOpened) { config_term("cannot open file '%s' for reading\n",name); } @@ -1231,81 +1237,64 @@ static QCString configFileToString(const char *name) bool ConfigImpl::parseString(const char *fn,const char *str,bool update) { - config = ConfigImpl::instance(); - inputString = str; - inputPosition = 0; - yyFileName = fn; - yyLineNr = 1; - includeStack.setAutoDelete(TRUE); - includeStack.clear(); - includeDepth = 0; + g_config = ConfigImpl::instance(); + g_inputString = str; + g_inputPosition = 0; + g_yyFileName = fn; + g_yyLineNr = 1; + g_includeStack.setAutoDelete(TRUE); + g_includeStack.clear(); + g_includeDepth = 0; configimplYYrestart( configimplYYin ); BEGIN( PreStart ); - config_upd = update; + g_configUpdate = update; configimplYYlex(); - config_upd = FALSE; - inputString = 0; + g_configUpdate = FALSE; + g_inputString = 0; return TRUE; } bool ConfigImpl::parse(const char *fn,bool update) { int retval; - encoding = "UTF-8"; + g_encoding = "UTF-8"; printlex(yy_flex_debug, TRUE, __FILE__, fn); - retval = parseString(fn,configFileToString(fn), update); + retval = parseString(fn,configFileToString(fn), update); printlex(yy_flex_debug, FALSE, __FILE__, fn); return retval; } //---------------------------------------------------------------------- -static void cleanUpPaths(QStrList &str) +static void cleanUpPaths(StringVector &str) { - char *sfp = str.first(); - while (sfp) + for (size_t i=0;i<str.size();i++) { - char *p = sfp; - if (p) + std::string path = str[i]; + std::replace(path.begin(),path.end(),'\\','/'); + if ((path[0]!='/' && (path.size()<=2 || path[1]!=':')) || path[path.size()-1]!='/') { - char c; - while ((c=*p)) - { - if (c=='\\') *p='/'; - p++; - } - } - QCString path = sfp; - if ((path.at(0)!='/' && (path.length()<=2 || path.at(1)!=':')) || - path.at(path.length()-1)!='/' - ) - { - QFileInfo fi(path); + QFileInfo fi(path.c_str()); if (fi.exists() && fi.isDir()) { - int i = str.at(); - QCString p = fi.absFilePath().utf8(); - if (p[p.length()-1]!='/') p+='/'; - str.remove(); - if (str.at()==i) // did not remove last item - str.insert(i,p); - else - str.append(p); + path = fi.absFilePath().utf8().data(); + if (path[path.size()-1]!='/') path+='/'; } } - sfp = str.next(); + str[i]=path; } } -static void checkFileName(QCString &s,const char *optionName) +static bool checkFileName(const QCString &s,const char *optionName) { QCString val = s.stripWhiteSpace().lower(); if ((val=="yes" || val=="true" || val=="1" || val=="all") || (val=="no" || val=="false" || val=="0" || val=="none")) { err("file name expected for option %s, got %s instead. Ignoring...\n",optionName,s.data()); - s=""; // note the use of &s above: this will change the option value! + return false; } + return true; } #include "config.h" @@ -1315,12 +1304,11 @@ void Config::init() ConfigImpl::instance()->init(); } -static void checkList(QStrList &list,const char *name, bool equalRequired,bool valueRequired) +static void checkList(const StringVector &list,const char *name, bool equalRequired,bool valueRequired) { - const char *s=list.first(); - while (s) + for (const auto &s: list) { - QCString item=s; + QCString item=s.c_str(); item=item.stripWhiteSpace(); int i=item.find('='); if (i==-1 && equalRequired) @@ -1343,7 +1331,6 @@ static void checkList(QStrList &list,const char *name, bool equalRequired,bool v } } } - s=list.next(); } } @@ -1351,17 +1338,18 @@ void Config::checkAndCorrect() { ConfigValues::instance().init(); - QCString &warnFormat = Config_getString(WARN_FORMAT); + //------------------------ + // check WARN_FORMAT + QCString warnFormat = Config_getString(WARN_FORMAT); if (warnFormat.stripWhiteSpace().isEmpty()) { - warnFormat="$file:$line $text"; + Config_updateString(WARN_FORMAT,"$file:$line $text"); } else { if (warnFormat.find("$file")==-1) { warn_uncond("warning format does not contain a $file tag!\n"); - } if (warnFormat.find("$line")==-1) { @@ -1373,15 +1361,17 @@ void Config::checkAndCorrect() } } - QCString &manExtension = Config_getString(MAN_EXTENSION); - + //------------------------ // set default man page extension if non is given by the user + QCString manExtension = Config_getString(MAN_EXTENSION); if (manExtension.isEmpty()) { - manExtension=".3"; + Config_updateString(MAN_EXTENSION,".3"); } - QCString &paperType = Config_getEnum(PAPER_TYPE); + //------------------------ + // check and correct PAPER_TYPE + QCString paperType = Config_getEnum(PAPER_TYPE); paperType=paperType.lower().stripWhiteSpace(); if (paperType.isEmpty() || paperType=="a4wide") { @@ -1393,42 +1383,53 @@ void Config::checkAndCorrect() err("Unknown page type specified\n"); paperType="a4"; } + Config_updateEnum(PAPER_TYPE,paperType); - QCString &outputLanguage=Config_getEnum(OUTPUT_LANGUAGE); + //------------------------ + // check & correct OUTPUT_LANGUAGE + QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE); outputLanguage=outputLanguage.stripWhiteSpace(); if (outputLanguage.isEmpty()) { outputLanguage = "English"; } + Config_updateEnum(OUTPUT_LANGUAGE,outputLanguage); - QCString &htmlFileExtension=Config_getString(HTML_FILE_EXTENSION); + //------------------------ + // check & correct HTML_FILE_EXTENSION + QCString htmlFileExtension=Config_getString(HTML_FILE_EXTENSION); htmlFileExtension=htmlFileExtension.stripWhiteSpace(); if (htmlFileExtension.isEmpty()) { htmlFileExtension = ".html"; } + Config_updateString(HTML_FILE_EXTENSION,htmlFileExtension); - // expand the relative stripFromPath values - QStrList &stripFromPath = Config_getList(STRIP_FROM_PATH); - char *sfp = stripFromPath.first(); - if (sfp==0) // by default use the current path + //------------------------ + // check & correct STRIP_FROM_PATH + StringVector stripFromPath = Config_getList(STRIP_FROM_PATH); + if (stripFromPath.empty()) // by default use the current path { QString p = QDir::currentDirPath(); if (p.at(p.length()-1)!='/') p.append('/'); - stripFromPath.append(p.utf8()); + stripFromPath.push_back(p.utf8().data()); } else { cleanUpPaths(stripFromPath); } + Config_updateList(STRIP_FROM_PATH,stripFromPath); - // expand the relative stripFromPath values - QStrList &stripFromIncPath = Config_getList(STRIP_FROM_INC_PATH); + //------------------------ + // check & correct STRIP_FROM_INC_PATH + StringVector stripFromIncPath = Config_getList(STRIP_FROM_INC_PATH); cleanUpPaths(stripFromIncPath); + Config_updateList(STRIP_FROM_INC_PATH,stripFromIncPath); + //------------------------ // Test to see if HTML header is valid - QCString &headerFile = Config_getString(HTML_HEADER); + QCString headerFile = Config_getString(HTML_HEADER); if (!headerFile.isEmpty()) { QFileInfo fi(headerFile); @@ -1438,8 +1439,10 @@ void Config::checkAndCorrect() "does not exist\n",headerFile.data()); } } + + //------------------------ // Test to see if HTML footer is valid - QCString &footerFile = Config_getString(HTML_FOOTER); + QCString footerFile = Config_getString(HTML_FOOTER); if (!footerFile.isEmpty()) { QFileInfo fi(footerFile); @@ -1450,29 +1453,31 @@ void Config::checkAndCorrect() } } + //------------------------ // Test to see if MathJax code file is valid if (Config_getBool(USE_MATHJAX)) { - QCString &MathJaxCodefile = Config_getString(MATHJAX_CODEFILE); - if (!MathJaxCodefile.isEmpty()) + QCString mathJaxCodefile = Config_getString(MATHJAX_CODEFILE); + if (!mathJaxCodefile.isEmpty()) { - QFileInfo fi(MathJaxCodefile); + QFileInfo fi(mathJaxCodefile); if (!fi.exists()) { config_term("tag MATHJAX_CODEFILE file '%s' " - "does not exist\n",MathJaxCodefile.data()); + "does not exist\n",mathJaxCodefile.data()); } } - QCString &path = Config_getString(MATHJAX_RELPATH); + QCString path = Config_getString(MATHJAX_RELPATH); if (!path.isEmpty() && path.at(path.length()-1)!='/') { path+="/"; } - + Config_updateString(MATHJAX_RELPATH,path); } + //------------------------ // Test to see if LaTeX header is valid - QCString &latexHeaderFile = Config_getString(LATEX_HEADER); + QCString latexHeaderFile = Config_getString(LATEX_HEADER); if (!latexHeaderFile.isEmpty()) { QFileInfo fi(latexHeaderFile); @@ -1482,8 +1487,10 @@ void Config::checkAndCorrect() "does not exist\n",latexHeaderFile.data()); } } + + //------------------------ // Test to see if LaTeX footer is valid - QCString &latexFooterFile = Config_getString(LATEX_FOOTER); + QCString latexFooterFile = Config_getString(LATEX_FOOTER); if (!latexFooterFile.isEmpty()) { QFileInfo fi(latexFooterFile); @@ -1494,25 +1501,24 @@ void Config::checkAndCorrect() } } + //------------------------ // check include path - QStrList &includePath = Config_getList(INCLUDE_PATH); - char *s=includePath.first(); - while (s) + const StringVector &includePath = Config_getList(INCLUDE_PATH); + for (const auto &s : includePath) { - QFileInfo fi(s); + QFileInfo fi(s.c_str()); if (!fi.exists()) warn_uncond("tag INCLUDE_PATH: include path '%s' " - "does not exist\n",s); - s=includePath.next(); + "does not exist\n",s.c_str()); } + //------------------------ // check PREDEFINED if (Config_getBool(ENABLE_PREPROCESSING)) { - QStrList &predefList = Config_getList(PREDEFINED); - s=predefList.first(); - while (s) + const StringVector &predefList = Config_getList(PREDEFINED); + for (const auto &s : predefList) { - QCString predef=s; + QCString predef=s.c_str(); predef=predef.stripWhiteSpace(); int i_equals=predef.find('='); int i_obrace=predef.find('('); @@ -1520,79 +1526,93 @@ void Config::checkAndCorrect() { err("Illegal PREDEFINED format '%s', no define name specified\n",predef.data()); } - s=predefList.next(); } } + //------------------------ // check ALIASES - QStrList &aliasList = Config_getList(ALIASES); - s=aliasList.first(); - while (s) + const StringVector &aliasList = Config_getList(ALIASES); + for (const auto &s : aliasList) { QRegExp re1("[a-z_A-Z][a-z_A-Z0-9]*[ \t]*="); // alias without argument QRegExp re2("[a-z_A-Z][a-z_A-Z0-9]*{[0-9]+}[ \t]*="); // alias with argument - QCString alias=s; + QCString alias=s.c_str(); alias=alias.stripWhiteSpace(); if (alias.find(re1)!=0 && alias.find(re2)!=0) { err("Illegal ALIASES format '%s'. Use \"name=value\" or \"name{n}=value\", where n is the number of arguments\n", alias.data()); } - s=aliasList.next(); } + //------------------------ + // check EXTENSION_MAPPING + checkList(Config_getList(EXTENSION_MAPPING),"EXTENSION_MAPPING",TRUE,TRUE); + + //------------------------ // check FILTER_PATTERNS checkList(Config_getList(FILTER_PATTERNS),"FILTER_PATTERNS",TRUE,TRUE); + //------------------------ // check FILTER_SOURCE_PATTERNS checkList(Config_getList(FILTER_SOURCE_PATTERNS),"FILTER_SOURCE_PATTERNS",FALSE,FALSE); + //------------------------ // check TAGFILES checkList(Config_getList(TAGFILES),"TAGFILES",FALSE,TRUE); + //------------------------ // check EXTRA_SEARCH_MAPPINGS if (Config_getBool(SEARCHENGINE) && Config_getBool(GENERATE_HTML)) { checkList(Config_getList(EXTRA_SEARCH_MAPPINGS),"EXTRA_SEARCH_MAPPING",TRUE,TRUE); } - // check TCL_SUBST - checkList(Config_getList(TCL_SUBST),"TCL_SUBST",TRUE,TRUE); - + //------------------------ // check if GENERATE_TREEVIEW and GENERATE_HTMLHELP are both enabled if (Config_getBool(GENERATE_TREEVIEW) && Config_getBool(GENERATE_HTMLHELP)) { err("When enabling GENERATE_HTMLHELP the tree view (GENERATE_TREEVIEW) should be disabled. I'll do it for you.\n"); - Config_getBool(GENERATE_TREEVIEW)=FALSE; + Config_updateBool(GENERATE_TREEVIEW,FALSE); } + + //------------------------ + // check if GENERATE_HTMLHELP and HTML_FILE_EXTENSION is not .html + if (Config_getString(HTML_FILE_EXTENSION)!=".html" && Config_getBool(GENERATE_HTMLHELP)) + { + err("When enabling GENERATE_HTMLHELP the HTML_FILE_EXTENSION should be \".html\". I'll do it for you.\n"); + Config_updateString(HTML_FILE_EXTENSION,".html"); + } + + //------------------------ + // check if SEARCHENGINE and GENERATE_HTMLHELP are both enabled if (Config_getBool(SEARCHENGINE) && Config_getBool(GENERATE_HTMLHELP)) { err("When enabling GENERATE_HTMLHELP the search engine (SEARCHENGINE) should be disabled. I'll do it for you.\n"); - Config_getBool(SEARCHENGINE)=FALSE; + Config_updateBool(SEARCHENGINE,FALSE); } + //------------------------ // check if SEPARATE_MEMBER_PAGES and INLINE_GROUPED_CLASSES are both enabled if (Config_getBool(SEPARATE_MEMBER_PAGES) && Config_getBool(INLINE_GROUPED_CLASSES)) { err("When enabling INLINE_GROUPED_CLASSES the SEPARATE_MEMBER_PAGES option should be disabled. I'll do it for you.\n"); - Config_getBool(SEPARATE_MEMBER_PAGES)=FALSE; + Config_updateBool(SEPARATE_MEMBER_PAGES,FALSE); } - // check dot image format - QCString &dotImageFormat=Config_getEnum(DOT_IMAGE_FORMAT); + //------------------------ + // check and correct DOT_IMAGE_FORMAT + QCString dotImageFormat=Config_getEnum(DOT_IMAGE_FORMAT); dotImageFormat=dotImageFormat.stripWhiteSpace(); if (dotImageFormat.isEmpty()) { dotImageFormat = "png"; } - //else if (dotImageFormat!="gif" && dotImageFormat!="png" && dotImageFormat!="jpg") - //{ - // err("Invalid value for DOT_IMAGE_FORMAT: '%s'. Using the default.\n",dotImageFormat.data()); - // dotImageFormat = "png"; - //} + Config_updateEnum(DOT_IMAGE_FORMAT,dotImageFormat); + //------------------------ // correct DOT_FONTNAME if needed - QCString &dotFontName=Config_getString(DOT_FONTNAME); + QCString dotFontName=Config_getString(DOT_FONTNAME); if (dotFontName=="FreeSans" || dotFontName=="FreeSans.ttf") { warn_uncond("doxygen no longer ships with the FreeSans font.\n" @@ -1603,9 +1623,11 @@ void Config::checkAndCorrect() { dotFontName = "Helvetica"; } + Config_updateString(DOT_FONTNAME,dotFontName); + //------------------------ // clip dotFontSize against the maximum bounds - int &dotFontSize = Config_getInt(DOT_FONTSIZE); + int dotFontSize = Config_getInt(DOT_FONTSIZE); if (dotFontSize<4) { dotFontSize=4; @@ -1614,20 +1636,24 @@ void Config::checkAndCorrect() { dotFontSize=24; } + Config_updateInt(DOT_FONTSIZE,dotFontSize); + //------------------------ // clip number of threads - int &dotNumThreads = Config_getInt(DOT_NUM_THREADS); + int dotNumThreads = Config_getInt(DOT_NUM_THREADS); if (dotNumThreads>32) { dotNumThreads=32; } else if (dotNumThreads<=0) { - dotNumThreads=QMAX(2,QThread::idealThreadCount()+1); + dotNumThreads=QMAX(2,std::thread::hardware_concurrency()+1); } + Config_updateInt(DOT_NUM_THREADS,dotNumThreads); + //------------------------ // check dot path - QCString &dotPath = Config_getString(DOT_PATH); + QCString dotPath = Config_getString(DOT_PATH); if (!dotPath.isEmpty()) { QFileInfo fi(dotPath); @@ -1657,9 +1683,11 @@ void Config::checkAndCorrect() { dotPath=""; } + Config_updateString(DOT_PATH,dotPath); + //------------------------ // check plantuml path - QCString &plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); + QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); if (!plantumlJarPath.isEmpty()) { QFileInfo pu(plantumlJarPath); @@ -1688,9 +1716,11 @@ void Config::checkAndCorrect() plantumlJarPath=""; } } + Config_updateString(PLANTUML_JAR_PATH,plantumlJarPath); + //------------------------ // check dia path - QCString &diaPath = Config_getString(DIA_PATH); + QCString diaPath = Config_getString(DIA_PATH); if (!diaPath.isEmpty()) { QFileInfo dp(diaPath+"/dia"+Portable::commandExtension()); @@ -1712,52 +1742,52 @@ void Config::checkAndCorrect() { diaPath=""; } + Config_updateString(DIA_PATH,diaPath); - // check input - QStrList &inputSources=Config_getList(INPUT); - if (inputSources.count()==0) + //------------------------ + // check INPUT + StringVector inputSources=Config_getList(INPUT); + if (inputSources.empty()) { // use current dir as the default - inputSources.append(QDir::currentDirPath().utf8()); + inputSources.push_back(QDir::currentDirPath().utf8().data()); } else { - s=inputSources.first(); - while (s) + for (const auto &s : inputSources) { - QFileInfo fi(s); + QFileInfo fi(s.c_str()); if (!fi.exists()) { - warn_uncond("tag INPUT: input source '%s' does not exist\n",s); + warn_uncond("tag INPUT: input source '%s' does not exist\n",s.c_str()); } - s=inputSources.next(); } } + Config_updateList(INPUT,inputSources); + //------------------------ // add default file patterns if needed - QStrList &filePatternList = Config_getList(FILE_PATTERNS); - if (filePatternList.isEmpty()) + StringVector filePatternList = Config_getList(FILE_PATTERNS); + if (filePatternList.empty()) { ConfigOption * opt = ConfigImpl::instance()->get("FILE_PATTERNS"); if (opt->kind()==ConfigOption::O_List) { - QStrList l = ((ConfigList*)opt)->getDefault(); - const char *p = l.first(); - while (p) - { - filePatternList.append(p); - p = l.next(); - } + filePatternList = ((ConfigList*)opt)->getDefault(); } } + Config_updateList(FILE_PATTERNS,filePatternList); + //------------------------ // add default pattern if needed - QStrList &examplePatternList = Config_getList(EXAMPLE_PATTERNS); - if (examplePatternList.isEmpty()) + StringVector examplePatternList = Config_getList(EXAMPLE_PATTERNS); + if (examplePatternList.empty()) { - examplePatternList.append("*"); + examplePatternList.push_back("*"); + Config_updateList(EXAMPLE_PATTERNS,examplePatternList); } + //------------------------ // if no output format is enabled, warn the user if (!Config_getBool(GENERATE_HTML) && !Config_getBool(GENERATE_LATEX) && @@ -1774,6 +1804,7 @@ void Config::checkAndCorrect() warn_uncond("No output formats selected! Set at least one of the main GENERATE_* options to YES.\n"); } + //------------------------ // check HTMLHELP creation requirements if (!Config_getBool(GENERATE_HTML) && Config_getBool(GENERATE_HTMLHELP)) @@ -1781,36 +1812,40 @@ void Config::checkAndCorrect() warn_uncond("GENERATE_HTMLHELP=YES requires GENERATE_HTML=YES.\n"); } + //------------------------ // check QHP creation requirements if (Config_getBool(GENERATE_QHP)) { if (Config_getString(QHP_NAMESPACE).isEmpty()) { err("GENERATE_QHP=YES requires QHP_NAMESPACE to be set. Using 'org.doxygen.doc' as default!.\n"); - Config_getString(QHP_NAMESPACE)="org.doxygen.doc"; + Config_updateString(QHP_NAMESPACE,"org.doxygen.doc"); } if (Config_getString(QHP_VIRTUAL_FOLDER).isEmpty()) { err("GENERATE_QHP=YES requires QHP_VIRTUAL_FOLDER to be set. Using 'doc' as default!\n"); - Config_getString(QHP_VIRTUAL_FOLDER)="doc"; + Config_updateString(QHP_VIRTUAL_FOLDER,"doc"); } } + //------------------------ if (Config_getBool(OPTIMIZE_OUTPUT_JAVA) && Config_getBool(INLINE_INFO)) { // don't show inline info for Java output, since Java has no inline // concept. - Config_getBool(INLINE_INFO)=FALSE; + Config_updateBool(INLINE_INFO,FALSE); } - int &depth = Config_getInt(MAX_DOT_GRAPH_DEPTH); + //------------------------ + int depth = Config_getInt(MAX_DOT_GRAPH_DEPTH); if (depth==0) { - depth=1000; + Config_updateInt(MAX_DOT_GRAPH_DEPTH,1000); } - int &hue = Config_getInt(HTML_COLORSTYLE_HUE); + //------------------------ + int hue = Config_getInt(HTML_COLORSTYLE_HUE); if (hue<0) { hue=0; @@ -1819,8 +1854,10 @@ void Config::checkAndCorrect() { hue=hue%360; } + Config_updateInt(HTML_COLORSTYLE_HUE,hue); - int &sat = Config_getInt(HTML_COLORSTYLE_SAT); + //------------------------ + int sat = Config_getInt(HTML_COLORSTYLE_SAT); if (sat<0) { sat=0; @@ -1829,7 +1866,11 @@ void Config::checkAndCorrect() { sat=255; } - int &gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); + Config_updateInt(HTML_COLORSTYLE_SAT,sat); + + + //------------------------ + int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); if (gamma<40) { gamma=40; @@ -1838,32 +1879,30 @@ void Config::checkAndCorrect() { gamma=240; } + Config_updateInt(HTML_COLORSTYLE_GAMMA,gamma); + //------------------------ QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT); if (!mathJaxFormat.isEmpty() && mathJaxFormat!="HTML-CSS" && mathJaxFormat!="NativeMML" && mathJaxFormat!="SVG") { err("Unsupported value for MATHJAX_FORMAT: Should be one of HTML-CSS, NativeMML, or SVG\n"); - Config_getEnum(MATHJAX_FORMAT)="HTML-CSS"; + Config_updateEnum(MATHJAX_FORMAT,"HTML-CSS"); } + //------------------------ // add default words if needed - QStrList &annotationFromBrief = Config_getList(ABBREVIATE_BRIEF); - if (annotationFromBrief.isEmpty()) - { - annotationFromBrief.append("The $name class"); - annotationFromBrief.append("The $name widget"); - annotationFromBrief.append("The $name file"); - annotationFromBrief.append("is"); - annotationFromBrief.append("provides"); - annotationFromBrief.append("specifies"); - annotationFromBrief.append("contains"); - annotationFromBrief.append("represents"); - annotationFromBrief.append("a"); - annotationFromBrief.append("an"); - annotationFromBrief.append("the"); + const StringVector &annotationFromBrief = Config_getList(ABBREVIATE_BRIEF); + if (annotationFromBrief.empty()) + { + Config_updateList(ABBREVIATE_BRIEF, + { "The $name class", "The $name widget", + "The $name file", "is", "provides", "specifies", + "contains", "represents", "a", "an", "the" + }); } + //------------------------ // some default settings for vhdl if (Config_getBool(OPTIMIZE_OUTPUT_VHDL) && (Config_getBool(INLINE_INHERITED_MEMB) || @@ -1893,15 +1932,18 @@ void Config::checkAndCorrect() "%s%s%s%s%s%s",s1,s2,s3,s4,s5,s6 ); - Config_getBool(INLINE_INHERITED_MEMB) = FALSE; - Config_getBool(INHERIT_DOCS) = FALSE; - Config_getBool(HIDE_SCOPE_NAMES) = TRUE; - Config_getBool(EXTRACT_PRIVATE) = TRUE; - Config_getBool(ENABLE_PREPROCESSING) = FALSE; - Config_getBool(EXTRACT_PACKAGE) = TRUE; + Config_updateBool(INLINE_INHERITED_MEMB, FALSE); + Config_updateBool(INHERIT_DOCS, FALSE); + Config_updateBool(HIDE_SCOPE_NAMES, TRUE); + Config_updateBool(EXTRACT_PRIVATE, TRUE); + Config_updateBool(ENABLE_PREPROCESSING, FALSE); + Config_updateBool(EXTRACT_PACKAGE, TRUE); } - checkFileName(Config_getString(GENERATE_TAGFILE),"GENERATE_TAGFILE"); + if (!checkFileName(Config_getString(GENERATE_TAGFILE),"GENERATE_TAGFILE")) + { + Config_updateString(GENERATE_TAGFILE,""); + } #if 0 // TODO: this breaks test 25; SOURCEBROWSER = NO and SOURCE_TOOLTIPS = YES. // So this and other regressions should be analysed and fixed before this can be enabled @@ -1952,14 +1994,14 @@ void Config::postProcess(bool clearHeaderAndFooter, bool compare) if (!compare)ConfigImpl::instance()->emptyValueToDefault(); ConfigImpl::instance()->convertStrToVal(); - // avoid bootstrapping issues when the config file already + // avoid bootstrapping issues when the g_config file already // refers to the files that we are supposed to parse. if (clearHeaderAndFooter) { - Config_getString(HTML_HEADER)=""; - Config_getString(HTML_FOOTER)=""; - Config_getString(LATEX_HEADER)=""; - Config_getString(LATEX_FOOTER)=""; + Config_updateString(HTML_HEADER ,""); + Config_updateString(HTML_FOOTER ,""); + Config_updateString(LATEX_HEADER,""); + Config_updateString(LATEX_FOOTER,""); } } @@ -1968,4 +2010,6 @@ void Config::deinit() ConfigImpl::instance()->deleteInstance(); } +#if USE_STATE2STRING #include "configimpl.l.h" +#endif diff --git a/src/constexp.l b/src/constexp.l index eae8a3b..0f053bd 100644 --- a/src/constexp.l +++ b/src/constexp.l @@ -20,6 +20,9 @@ %option nounput %option reentrant bison-bridge %option extra-type="struct constexpYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -32,8 +35,13 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + +#if USE_STATE2STRING static const char *stateToString(int state); -static int yyread(char *buf,int max_size,yyscan_t yyscanner); +#endif + +static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); @@ -93,10 +101,10 @@ CONSTSUFFIX ([uU][lL]?[lL]?)|([lL][lL]?[uU]?) %% -static int yyread(char *buf,int max_size,yyscan_t yyscanner) +static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - int c=0; + yy_size_t c=0; while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) { *buf = yyextra->inputString[yyextra->inputPosition++] ; @@ -129,7 +137,7 @@ bool ConstExpressionParser::parse(const char *fileName,int lineNr,const QCString struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; #ifdef FLEX_DEBUG - yyset_debug(1,yyscanner); + constexpYYset_debug(1,p->yyscanner); #endif yyextra->constExpFileName = fileName; @@ -153,4 +161,7 @@ bool ConstExpressionParser::parse(const char *fileName,int lineNr,const QCString extern "C" { int constexpYYwrap(yyscan_t yyscanner) { return 1; } } + +#if USE_STATE2STRING #include "constexp.l.h" +#endif diff --git a/src/constexp.y b/src/constexp.y index 100614a..c4110f9 100644 --- a/src/constexp.y +++ b/src/constexp.y @@ -29,7 +29,7 @@ int constexpYYerror(yyscan_t yyscanner, const char *s) { struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); warn(yyextra->constExpFileName, yyextra->constExpLineNr, - "preprocessing issue while doing constant expression evaluation: %s",s); + "preprocessing issue while doing constant expression evaluation: %s: input='%s'",s,yyextra->inputString); return 0; } diff --git a/src/containers.h b/src/containers.h new file mode 100644 index 0000000..770f92d --- /dev/null +++ b/src/containers.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef CONTAINERS_H +#define CONTAINERS_H + +#include <vector> +#include <string> +#include <set> +#include <map> +#include <unordered_set> +#include <unordered_map> +#include <stack> + +using StringUnorderedMap = std::unordered_map<std::string,std::string>; +using StringUnorderedSet = std::unordered_set<std::string>; +using StringSet = std::set<std::string>; +using StringVector = std::vector<std::string>; +using BoolStack = std::stack<bool>; +using BoolVector = std::vector<bool>; +using IntMap = std::map<std::string,int>; +using IntVector = std::vector<int>; + +#endif diff --git a/src/context.cpp b/src/context.cpp index 5ee89cd..29a704a 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -180,14 +180,14 @@ class GenericNodeListContext : public TemplateListIntf } // TemplateListIntf methods - int count() const + uint count() const { - return (int)m_children.count(); + return m_children.count(); } - TemplateVariant at(int index) const + TemplateVariant at(uint index) const { TemplateVariant result; - if (index>=0 && index<count()) + if (index<count()) { result = *m_children.at(index); } @@ -298,18 +298,16 @@ class ConfigContext::Private public: Private() { m_cachedLists.setAutoDelete(TRUE); } virtual ~Private() { } - TemplateVariant fetchList(const QCString &name,const QStrList *list) + TemplateVariant fetchList(const QCString &name,const StringVector &list) { TemplateVariant *v = m_cachedLists.find(name); if (v==0) { TemplateList *tlist = TemplateList::alloc(); m_cachedLists.insert(name,new TemplateVariant(tlist)); - QStrListIterator li(*list); - char *s; - for (li.toFirst();(s=li.current());++li) + for (const auto &s : list) { - tlist->append(s); + tlist->append(s.c_str()); } return tlist; } @@ -345,23 +343,23 @@ TemplateVariant ConfigContext::get(const char *name) const { case ConfigValues::Info::Bool: { - bool b = ConfigValues::instance().*((ConfigValues::InfoBool*)option)->item; + bool b = ConfigValues::instance().*(option->value.b); return TemplateVariant(b); } case ConfigValues::Info::Int: { - int i = ConfigValues::instance().*((ConfigValues::InfoInt*)option)->item; + int i = ConfigValues::instance().*(option->value.i); return TemplateVariant(i); } case ConfigValues::Info::String: { - QCString s = ConfigValues::instance().*((ConfigValues::InfoString*)option)->item; + QCString s = ConfigValues::instance().*(option->value.s); return TemplateVariant(s); } case ConfigValues::Info::List: { - const QStrList &l = ConfigValues::instance().*((ConfigValues::InfoList*)option)->item; - return p->fetchList(name,&l); + const StringVector &l = ConfigValues::instance().*(option->value.l); + return p->fetchList(name,l); } default: break; @@ -380,7 +378,7 @@ class DoxygenContext::Private public: TemplateVariant version() const { - return getVersion(); + return getDoxygenVersion(); } TemplateVariant date() const { @@ -445,147 +443,147 @@ class TranslateContext::Private { public: - TemplateVariant handleGeneratedAt(const QValueList<TemplateVariant> &args) const + TemplateVariant handleGeneratedAt(const std::vector<TemplateVariant> &args) const { - if (args.count()==2) + if (args.size()==2) { return theTranslator->trGeneratedAt(args[0].toString(),args[1].toString()); } else { - err("tr.generateAt should take two arguments, got %d!\n",args.count()); + err("tr.generateAt should take two arguments, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleInheritanceDiagramFor(const QValueList<TemplateVariant> &args) const + TemplateVariant handleInheritanceDiagramFor(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trClassDiagram(args[0].toString()); } else { - err("tr.inheritanceDiagramFor should take one argument, got %d!\n",args.count()); + err("tr.inheritanceDiagramFor should take one argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleCollaborationDiagramFor(const QValueList<TemplateVariant> &args) const + TemplateVariant handleCollaborationDiagramFor(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trCollaborationDiagram(args[0].toString()); } else { - err("tr.collaborationDiagramFor should take one argument, got %d!\n",args.count()); + err("tr.collaborationDiagramFor should take one argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleDirDependencyGraphFor(const QValueList<TemplateVariant> &args) const + TemplateVariant handleDirDependencyGraphFor(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trDirDepGraph(args[0].toString()); } else { - err("tr.dirDependencyGraphFor should take one argument, got %d!\n",args.count()); + err("tr.dirDependencyGraphFor should take one argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleInheritsList(const QValueList<TemplateVariant> &args) const + TemplateVariant handleInheritsList(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trInheritsList(args[0].toInt()); } else { - err("tr.inheritsList should take one integer argument, got %d!\n",args.count()); + err("tr.inheritsList should take one integer argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleInheritedByList(const QValueList<TemplateVariant> &args) const + TemplateVariant handleInheritedByList(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trInheritedByList(args[0].toInt()); } else { - err("tr.inheritedByList should take one integer argument, got %d!\n",args.count()); + err("tr.inheritedByList should take one integer argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleWriteList(const QValueList<TemplateVariant> &args) const + TemplateVariant handleWriteList(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trWriteList(args[0].toInt()); } else { - err("tr.*List should take one integer argument, got %d!\n",args.count()); + err("tr.*List should take one integer argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleImplementedBy(const QValueList<TemplateVariant> &args) const + TemplateVariant handleImplementedBy(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trImplementedInList(args[0].toInt()); } else { - err("tr.implementedBy should take one integer argument, got %d!\n",args.count()); + err("tr.implementedBy should take one integer argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleReimplementedBy(const QValueList<TemplateVariant> &args) const + TemplateVariant handleReimplementedBy(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trReimplementedInList(args[0].toInt()); } else { - err("tr.reimplementedBy should take one integer argument, got %d!\n",args.count()); + err("tr.reimplementedBy should take one integer argument, got %zu!\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleSourceRefs(const QValueList<TemplateVariant> &args) const + TemplateVariant handleSourceRefs(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trReferences()+" "+theTranslator->trWriteList(args[0].toInt())+"."; } else { - err("tr.sourceRefs should take one integer argument, got %d\n",args.count()); + err("tr.sourceRefs should take one integer argument, got %zu\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleSourceRefBys(const QValueList<TemplateVariant> &args) const + TemplateVariant handleSourceRefBys(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trReferencedBy()+" "+theTranslator->trWriteList(args[0].toInt())+"."; } else { - err("tr.sourceRefBys should take one integer argument, got %d\n",args.count()); + err("tr.sourceRefBys should take one integer argument, got %zu\n",args.size()); } return TemplateVariant(); } - TemplateVariant handleIncludeDependencyGraph(const QValueList<TemplateVariant> &args) const + TemplateVariant handleIncludeDependencyGraph(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return theTranslator->trInclDepGraph(args[0].toString()); } else { - err("tr.includeDependencyGraph should take one string argument, got %d\n",args.count()); + err("tr.includeDependencyGraph should take one string argument, got %zu\n",args.size()); } return TemplateVariant(); } @@ -1073,7 +1071,7 @@ class TranslateContext::Private s_inst.addProperty("namespaceList", &Private::namespaceList); //%% string namespaceMembers s_inst.addProperty("namespaceMembers", &Private::namespaceMembers); - //%% srting fileList + //%% string fileList s_inst.addProperty("fileList", &Private::fileList); //%% string fileMembers s_inst.addProperty("fileMembers", &Private::fileMembers); @@ -1264,7 +1262,8 @@ static TemplateVariant parseDoc(const Definition *def,const QCString &file,int l const QCString &relPath,const QCString &docStr,bool isBrief) { TemplateVariant result; - DocRoot *root = validatingParseDoc(file,line,def,0,docStr,TRUE,FALSE,0,isBrief,FALSE); + DocRoot *root = validatingParseDoc(file,line,def,0,docStr,TRUE,FALSE, + 0,isBrief,FALSE,Config_getBool(MARKDOWN_SUPPORT)); QGString docs; { FTextStream ts(&docs); @@ -1397,6 +1396,7 @@ class DefinitionContext { assert(d!=0); } + virtual ~DefinitionContext() {} void addBaseProperties(PropertyMapper<T> &inst) { //%% string name: the name of the symbol @@ -1544,7 +1544,6 @@ class DefinitionContext case SrcLangExt_VHDL: result="vhdl"; break; case SrcLangExt_XML: result="xml"; break; case SrcLangExt_SQL: result="sql"; break; - case SrcLangExt_Tcl: result="tcl"; break; case SrcLangExt_Markdown: result="markdown"; break; case SrcLangExt_Slice: result="slice"; break; } @@ -1775,10 +1774,7 @@ class IncludeInfoListContext::Private : public GenericNodeListContext IncludeInfo *ii; for (li.toFirst();(ii=li.current());++li) { - if (!ii->indirect) - { - append(IncludeInfoContext::alloc(ii,lang)); - } + append(IncludeInfoContext::alloc(ii,lang)); } } }; @@ -1794,12 +1790,12 @@ IncludeInfoListContext::~IncludeInfoListContext() } // TemplateListIntf -int IncludeInfoListContext::count() const +uint IncludeInfoListContext::count() const { return p->count(); } -TemplateVariant IncludeInfoListContext::at(int index) const +TemplateVariant IncludeInfoListContext::at(uint index) const { return p->at(index); } @@ -2007,7 +2003,6 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> { case ContextOutputFormat_Html: { - QGString result; FTextStream tt(&result); QCString name = convertToHtml(m_classDef->displayName()); @@ -2136,7 +2131,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> return cache.inheritedByList.get(); } TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const char *title,bool detailed=FALSE) const + MemberListType type,const char *title,bool=FALSE) const { if (!list) { @@ -2504,15 +2499,8 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> Cachable &cache = getCache(); if (!cache.allMembersList) { - if (m_classDef->memberNameInfoSDict()) - { - AllMembersListContext *ml = AllMembersListContext::alloc(m_classDef->memberNameInfoSDict()); - cache.allMembersList.reset(ml); - } - else - { - cache.allMembersList.reset(AllMembersListContext::alloc()); - } + AllMembersListContext *ml = AllMembersListContext::alloc(m_classDef->memberNameInfoLinkedMap()); + cache.allMembersList.reset(ml); } return cache.allMembersList.get(); } @@ -2834,7 +2822,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri return cache.constantgroups.get(); } TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const char *title,bool detailed=FALSE) const + MemberListType type,const char *title,bool=FALSE) const { if (!list) { @@ -3293,7 +3281,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> return cache.constantgroups.get(); } TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const char *title,bool detailed=FALSE) const + MemberListType type,const char *title,bool=FALSE) const { if (!list) { @@ -3533,10 +3521,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> if (!cache.dirs) { cache.dirs.reset(TemplateList::alloc()); - const DirList &subDirs = m_dirDef->subDirs(); - QListIterator<DirDef> it(subDirs); - const DirDef *dd; - for (it.toFirst();(dd=it.current());++it) + for(const auto dd : m_dirDef->subDirs()) { DirContext *dc = new DirContext(dd); cache.dirs->append(dc); @@ -3977,7 +3962,7 @@ TemplateVariant createLinkedText(const Definition *def,const QCString &relPath,c class MemberContext::Private : public DefinitionContext<MemberContext::Private> { public: - Private(MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md) + Private(const MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md) { static bool init=FALSE; if (!init) @@ -4438,8 +4423,9 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> { scopeName = m_memberDef->getNamespaceDef()->name(); } - cache.initializer = parseCode(m_memberDef,scopeName,relPathAsString(), - m_memberDef->initializer()); + cache.initializer = parseCode(const_cast<MemberDef*>(m_memberDef), + scopeName,relPathAsString(), + m_memberDef->initializer()); cache.initializerParsed = TRUE; } return cache.initializer; @@ -4671,27 +4657,27 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> } TemplateVariant hasConstQualifier() const { - return getDefArgList().constSpecifier; + return getDefArgList().constSpecifier(); } TemplateVariant hasVolatileQualifier() const { - return getDefArgList().volatileSpecifier; + return getDefArgList().volatileSpecifier(); } TemplateVariant hasRefQualifierLValue() const { - return getDefArgList().refQualifier==RefQualifierLValue; + return getDefArgList().refQualifier()==RefQualifierLValue; } TemplateVariant hasRefQualifierRValue() const { - return getDefArgList().refQualifier==RefQualifierRValue; + return getDefArgList().refQualifier()==RefQualifierRValue; } TemplateVariant trailingReturnType() const { const ArgumentList &al = getDefArgList(); - if (!al.trailingReturnType.isEmpty()) + if (!al.trailingReturnType().isEmpty()) { return createLinkedText(m_memberDef,relPathAsString(), - al.trailingReturnType); + al.trailingReturnType()); } else { @@ -4776,12 +4762,13 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> if (m_memberDef->argumentList().hasDocumentation()) { QCString paramDocs; - for (Argument &a : m_memberDef->argumentList()) + for (const Argument &a : m_memberDef->argumentList()) { if (a.hasDocumentation()) { - QCString direction = extractDirection(a.docs); - paramDocs+="@param"+direction+" "+a.name+" "+a.docs; + QCString docs = a.docs; + QCString direction = extractDirection(docs); + paramDocs+="@param"+direction+" "+a.name+" "+docs; } } cache.paramDocs.reset(new TemplateVariant(parseDoc(m_memberDef, @@ -4983,7 +4970,9 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> { scopeName = m_memberDef->getNamespaceDef()->name(); } - cache.sourceCode = parseCode(m_memberDef,scopeName,relPathAsString(),codeFragment,startLine,endLine,TRUE); + cache.sourceCode = parseCode(const_cast<MemberDef*>(m_memberDef), + scopeName,relPathAsString(), + codeFragment,startLine,endLine,TRUE); cache.sourceCodeParsed = TRUE; } } @@ -5137,15 +5126,15 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> { return m_memberDef->typeString(); } - TemplateVariant handleDetailsVisibleFor(const QValueList<TemplateVariant> &args) const + TemplateVariant handleDetailsVisibleFor(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { return m_memberDef->isDetailedSectionVisible(args[0].toString()=="module",args[0].toString()=="file"); } else { - err(".detailsVisibleFor should take one string argument, got %d\n",args.count()); + err(".detailsVisibleFor should take one string argument, got %zu\n",args.size()); } return TemplateVariant(); } @@ -5153,9 +5142,9 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> { return TemplateVariant::Delegate::fromMethod<Private,&Private::handleDetailsVisibleFor>(this); } - TemplateVariant handleNameWithContextFor(const QValueList<TemplateVariant> &args) const + TemplateVariant handleNameWithContextFor(const std::vector<TemplateVariant> &args) const { - if (args.count()==1) + if (args.size()==1) { SrcLangExt lang = m_memberDef->getLanguage(); QCString n = m_memberDef->name(); @@ -5177,7 +5166,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> } else { - err(".nameWithContextFor should take one string argument, got %d\n",args.count()); + err(".nameWithContextFor should take one string argument, got %zu\n",args.size()); } return TemplateVariant(); } @@ -5186,10 +5175,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> return TemplateVariant::Delegate::fromMethod<Private,&Private::handleNameWithContextFor>(this); } private: - MemberDef *m_memberDef; + const MemberDef *m_memberDef; struct Cachable : public DefinitionContext<MemberContext::Private>::Cachable { - Cachable(MemberDef *md) : DefinitionContext<MemberContext::Private>::Cachable(md), + Cachable(const MemberDef *md) : DefinitionContext<MemberContext::Private>::Cachable(md), initializerParsed(FALSE), sourceCodeParsed(FALSE), declArgsParsed(FALSE), declTypeParsed(FALSE) { } SharedPtr<ArgumentListContext> templateArgs; @@ -5239,7 +5228,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> PropertyMapper<MemberContext::Private> MemberContext::Private::s_inst; -MemberContext::MemberContext(MemberDef *md) : RefCountedContext("MemberContext") +MemberContext::MemberContext(const MemberDef *md) : RefCountedContext("MemberContext") { p = new Private(md); } @@ -5464,14 +5453,9 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (!cache.dirs) { TemplateList *dirList = TemplateList::alloc(); - if (m_groupDef->getDirs()) + for(const auto dd : m_groupDef->getDirs()) { - QListIterator<DirDef> it(*m_groupDef->getDirs()); - const DirDef *dd; - for (it.toFirst();(dd=it.current());++it) - { - dirList->append(DirContext::alloc(dd)); - } + dirList->append(DirContext::alloc(dd)); } cache.dirs.reset(dirList); } @@ -5564,7 +5548,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> } TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const char *title,bool detailed=FALSE) const + MemberListType type,const char *title,bool=FALSE) const { if (!list) { @@ -5852,12 +5836,12 @@ ClassListContext::~ClassListContext() } // TemplateListIntf -int ClassListContext::count() const +uint ClassListContext::count() const { return p->count(); } -TemplateVariant ClassListContext::at(int index) const +TemplateVariant ClassListContext::at(uint index) const { return p->at(index); } @@ -6600,27 +6584,21 @@ class NestingContext::Private : public GenericNodeListContext } void addDirs(const DirList &dirList) { - QListIterator<DirDef> li(dirList); - const DirDef *dd; - for (li.toFirst();(dd=li.current());++li) + for(const auto dd : dirList) { append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE)); m_index++; } } - void addFiles(const FileNameList &fnList) + void addFiles(const FileNameLinkedMap &fnList) { - FileNameListIterator fnli(fnList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const FileNameLinkedMap::Ptr &fn : fnList) { - FileNameIterator fni(*fn); - const FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->getDirDef()==0) // top level file { - append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,fd.get(),m_index,m_level,FALSE,FALSE,FALSE)); m_index++; } } @@ -6760,12 +6738,12 @@ NestingContext::~NestingContext() } // TemplateListIntf -int NestingContext::count() const +uint NestingContext::count() const { return p->count(); } -TemplateVariant NestingContext::at(int index) const +TemplateVariant NestingContext::at(uint index) const { return p->at(index); } @@ -6795,7 +6773,7 @@ void NestingContext::addDirs(const DirList &dirs) p->addDirs(dirs); } -void NestingContext::addFiles(const FileNameList &files) +void NestingContext::addFiles(const FileNameLinkedMap &files) { p->addFiles(files); } @@ -6987,12 +6965,12 @@ NamespaceListContext::~NamespaceListContext() } // TemplateListIntf -int NamespaceListContext::count() const +uint NamespaceListContext::count() const { return p->count(); } -TemplateVariant NamespaceListContext::at(int index) const +TemplateVariant NamespaceListContext::at(uint index) const { return p->at(index); } @@ -7131,23 +7109,19 @@ TemplateVariant NamespaceTreeContext::get(const char *name) const class FileListContext::Private : public GenericNodeListContext { public: - void addFiles(const FileNameList &fnList) + void addFiles(const FileNameLinkedMap &fnMap) { // TODO: if FULL_PATH_NAMES is enabled, the ordering should be dir+file - FileNameListIterator fnli(fnList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : fnMap) { - FileNameIterator fni(*fn); - const FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { bool doc = fd->isLinkableInProject(); bool src = fd->generateSourceFile(); bool nameOk = !fd->isDocumentationFile(); if (nameOk && (doc || src) && !fd->isReference()) { - append(FileContext::alloc(fd)); + append(FileContext::alloc(fd.get())); } } } @@ -7157,7 +7131,7 @@ class FileListContext::Private : public GenericNodeListContext FileListContext::FileListContext() : RefCountedContext("FileListContext") { p = new Private; - if (Doxygen::inputNameList) p->addFiles(*Doxygen::inputNameList); + if (Doxygen::inputNameLinkedMap) p->addFiles(*Doxygen::inputNameLinkedMap); } FileListContext::~FileListContext() @@ -7166,12 +7140,12 @@ FileListContext::~FileListContext() } // TemplateListIntf -int FileListContext::count() const +uint FileListContext::count() const { return p->count(); } -TemplateVariant FileListContext::at(int index) const +TemplateVariant FileListContext::at(uint index) const { return p->at(index); } @@ -7209,12 +7183,12 @@ DirListContext::~DirListContext() } // TemplateListIntf -int DirListContext::count() const +uint DirListContext::count() const { return p->count(); } -TemplateVariant DirListContext::at(int index) const +TemplateVariant DirListContext::at(uint index) const { return p->at(index); } @@ -7257,12 +7231,12 @@ UsedFilesContext::~UsedFilesContext() } // TemplateListIntf -int UsedFilesContext::count() const +uint UsedFilesContext::count() const { return p->count(); } -TemplateVariant UsedFilesContext::at(int index) const +TemplateVariant UsedFilesContext::at(uint index) const { return p->at(index); } @@ -7292,9 +7266,9 @@ class FileTreeContext::Private { m_dirFileTree->addDirs(*Doxygen::directories); } - if (Doxygen::inputNameList) + if (Doxygen::inputNameLinkedMap) { - m_dirFileTree->addFiles(*Doxygen::inputNameList); + m_dirFileTree->addFiles(*Doxygen::inputNameLinkedMap); } //%% DirFile tree: static bool init=FALSE; @@ -7532,12 +7506,12 @@ PageListContext::~PageListContext() } // TemplateListIntf -int PageListContext::count() const +uint PageListContext::count() const { return p->count(); } -TemplateVariant PageListContext::at(int index) const +TemplateVariant PageListContext::at(uint index) const { return p->at(index); } @@ -7581,12 +7555,12 @@ ExampleListContext::~ExampleListContext() } // TemplateListIntf -int ExampleListContext::count() const +uint ExampleListContext::count() const { return p->count(); } -TemplateVariant ExampleListContext::at(int index) const +TemplateVariant ExampleListContext::at(uint index) const { return p->at(index); } @@ -7628,12 +7602,12 @@ ModuleListContext::~ModuleListContext() } // TemplateListIntf -int ModuleListContext::count() const +uint ModuleListContext::count() const { return p->count(); } -TemplateVariant ModuleListContext::at(int index) const +TemplateVariant ModuleListContext::at(uint index) const { return p->at(index); } @@ -7997,21 +7971,17 @@ class GlobalsIndexContext::Private if (!listRef) { TemplateList *list = TemplateList::alloc(); - MemberName *mn; - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); - for (fnli.toFirst();(mn=fnli.current());++fnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { const FileDef *fd=md->getFileDef(); if (fd && fd->isLinkableInProject() && !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject()) { - if (filter==0 || (md->*filter)()) + if (filter==0 || (md.get()->*filter)()) { - list->append(MemberContext::alloc(md)); + list->append(MemberContext::alloc(md.get())); } } } @@ -8154,21 +8124,17 @@ class ClassMembersIndexContext::Private if (!listRef) { TemplateList *list = TemplateList::alloc(); - MemberName *mn; - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); - for (mnli.toFirst();(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { const ClassDef *cd = md->getClassDef(); if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 && md->isLinkableInProject() && !md->name().isEmpty()) { - if (filter==0 || (md->*filter)()) + if (filter==0 || (md.get()->*filter)()) { - list->append(MemberContext::alloc(md)); + list->append(MemberContext::alloc(md.get())); } } } @@ -8313,21 +8279,17 @@ class NamespaceMembersIndexContext::Private if (!listRef) { TemplateList *list = TemplateList::alloc(); - MemberName *mn; - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); - for (fnli.toFirst();(mn=fnli.current());++fnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { const NamespaceDef *nd=md->getNamespaceDef(); if (nd && nd->isLinkableInProject() && !md->name().isEmpty() && md->isLinkableInProject()) { - if (filter==0 || (md->*filter)()) + if (filter==0 || (md.get()->*filter)()) { - list->append(MemberContext::alloc(md)); + list->append(MemberContext::alloc(md.get())); } } } @@ -8594,12 +8556,12 @@ InheritanceListContext::~InheritanceListContext() } // TemplateListIntf -int InheritanceListContext::count() const +uint InheritanceListContext::count() const { return p->count(); } -TemplateVariant InheritanceListContext::at(int index) const +TemplateVariant InheritanceListContext::at(uint index) const { return p->at(index); } @@ -8670,12 +8632,12 @@ MemberListContext::~MemberListContext() } // TemplateListIntf -int MemberListContext::count() const +uint MemberListContext::count() const { return p->count(); } -TemplateVariant MemberListContext::at(int index) const +TemplateVariant MemberListContext::at(uint index) const { return p->at(index); } @@ -8714,7 +8676,7 @@ class MemberInfoContext::Private } TemplateVariant protection() const { - switch (m_memberInfo->prot) + switch (m_memberInfo->prot()) { case ::Public: return "public"; case ::Protected: return "protected"; @@ -8725,7 +8687,7 @@ class MemberInfoContext::Private } TemplateVariant virtualness() const { - switch (m_memberInfo->virt) + switch (m_memberInfo->virt()) { case ::Normal: return "normal"; case ::Virtual: return "virtual"; @@ -8735,13 +8697,13 @@ class MemberInfoContext::Private } TemplateVariant ambiguityScope() const { - return m_memberInfo->ambiguityResolutionScope; + return m_memberInfo->ambiguityResolutionScope(); } TemplateVariant member() const { - if (!m_member && m_memberInfo->memberDef) + if (!m_member && m_memberInfo->memberDef()) { - m_member.reset(MemberContext::alloc(m_memberInfo->memberDef)); + m_member.reset(MemberContext::alloc(m_memberInfo->memberDef())); } if (m_member) { @@ -8783,31 +8745,24 @@ TemplateVariant MemberInfoContext::get(const char *name) const class AllMembersListContext::Private : public GenericNodeListContext { public: - Private(const MemberNameInfoSDict *ml) + Private(const MemberNameInfoLinkedMap &ml) { - if (ml) + static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); + for (auto &mni : ml) { - static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); - MemberNameInfoSDict::Iterator mnii(*ml); - MemberNameInfo *mni; - for (mnii.toFirst();(mni=mnii.current());++mnii) + for (auto &mi : *mni) { - MemberNameInfoIterator mnii2(*mni); - MemberInfo *mi; - for (mnii2.toFirst();(mi=mnii2.current());++mnii2) + const MemberDef *md=mi->memberDef(); + const ClassDef *cd=md->getClassDef(); + if (cd && !md->isAnonymous()) { - MemberDef *md=mi->memberDef; - const ClassDef *cd=md->getClassDef(); - if (cd && !md->isAnonymous()) + if ((cd->isLinkable() && md->isLinkable()) || + (!cd->isArtificial() && !hideUndocMembers && + (protectionLevelVisible(md->protection()) || md->isFriend()) + ) + ) { - if ((cd->isLinkable() && md->isLinkable()) || - (!cd->isArtificial() && !hideUndocMembers && - (protectionLevelVisible(md->protection()) || md->isFriend()) - ) - ) - { - append(MemberInfoContext::alloc(mi)); - } + append(MemberInfoContext::alloc(mi.get())); } } } @@ -8815,12 +8770,8 @@ class AllMembersListContext::Private : public GenericNodeListContext } }; -AllMembersListContext::AllMembersListContext() : RefCountedContext("AllMembersListContext") -{ - p = new Private(0); -} - -AllMembersListContext::AllMembersListContext(const MemberNameInfoSDict *ml) : RefCountedContext("AllMembersListContext") +AllMembersListContext::AllMembersListContext(const MemberNameInfoLinkedMap &ml) + : RefCountedContext("AllMembersListContext") { p = new Private(ml); } @@ -8831,12 +8782,12 @@ AllMembersListContext::~AllMembersListContext() } // TemplateListIntf -int AllMembersListContext::count() const +uint AllMembersListContext::count() const { return p->count(); } -TemplateVariant AllMembersListContext::at(int index) const +TemplateVariant AllMembersListContext::at(uint index) const { return p->at(index); } @@ -9013,12 +8964,12 @@ MemberGroupListContext::~MemberGroupListContext() } // TemplateListIntf -int MemberGroupListContext::count() const +uint MemberGroupListContext::count() const { return p->count(); } -TemplateVariant MemberGroupListContext::at(int index) const +TemplateVariant MemberGroupListContext::at(uint index) const { return p->at(index); } @@ -9287,7 +9238,7 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext MemberDef *md; for (li.toFirst();(md=li.current());++li) { - if (lt==md->getSectionList()->listType() && + if (lt==md->getSectionList(mg->container())->listType() && !md->isReimplementedBy(inheritedFrom) && md->isBriefSectionVisible()) { @@ -9376,12 +9327,12 @@ InheritedMemberInfoListContext::~InheritedMemberInfoListContext() } // TemplateListIntf -int InheritedMemberInfoListContext::count() const +uint InheritedMemberInfoListContext::count() const { return p->count(); } -TemplateVariant InheritedMemberInfoListContext::at(int index) const +TemplateVariant InheritedMemberInfoListContext::at(uint index) const { return p->at(index); } @@ -9458,7 +9409,7 @@ class ArgumentContext::Private TemplateVariant namePart() const { QCString result = m_argument.attrib; - int l = result.length(); + uint l = result.length(); if (l>2 && result.at(0)=='[' && result.at(l-1)==']') { result = result.mid(1,l-2); @@ -9467,7 +9418,7 @@ class ArgumentContext::Private return result; } private: - const Argument &m_argument; + Argument m_argument; const Definition *m_def; QCString m_relPath; struct Cachable @@ -9529,12 +9480,12 @@ ArgumentListContext::~ArgumentListContext() } // TemplateListIntf -int ArgumentListContext::count() const +uint ArgumentListContext::count() const { return p->count(); } -TemplateVariant ArgumentListContext::at(int index) const +TemplateVariant ArgumentListContext::at(uint index) const { return p->at(index); } @@ -9723,12 +9674,12 @@ SymbolListContext::~SymbolListContext() } // TemplateListIntf -int SymbolListContext::count() const +uint SymbolListContext::count() const { return p->count(); } -TemplateVariant SymbolListContext::at(int index) const +TemplateVariant SymbolListContext::at(uint index) const { return p->at(index); } @@ -9822,7 +9773,7 @@ class SymbolGroupListContext::Private : public GenericNodeListContext } }; -SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList *sil) +SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList *sil) : RefCountedContext("SymbolGroupListContext") { p = new Private(sil); @@ -9834,12 +9785,12 @@ SymbolGroupListContext::~SymbolGroupListContext() } // TemplateListIntf -int SymbolGroupListContext::count() const +uint SymbolGroupListContext::count() const { return p->count(); } -TemplateVariant SymbolGroupListContext::at(int index) const +TemplateVariant SymbolGroupListContext::at(uint index) const { return p->at(index); } @@ -9946,12 +9897,12 @@ SymbolIndicesContext::~SymbolIndicesContext() } // TemplateListIntf -int SymbolIndicesContext::count() const +uint SymbolIndicesContext::count() const { return p->count(); } -TemplateVariant SymbolIndicesContext::at(int index) const +TemplateVariant SymbolIndicesContext::at(uint index) const { return p->at(index); } @@ -10055,12 +10006,12 @@ SearchIndicesContext::~SearchIndicesContext() } // TemplateListIntf -int SearchIndicesContext::count() const +uint SearchIndicesContext::count() const { return p->count(); } -TemplateVariant SearchIndicesContext::at(int index) const +TemplateVariant SearchIndicesContext::at(uint index) const { return p->at(index); } @@ -10390,7 +10341,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/context.h b/src/context.h index fc1278b..7256dc6 100644 --- a/src/context.h +++ b/src/context.h @@ -20,6 +20,7 @@ #include "template.h" #include <qlist.h> #include <stdio.h> +#include "dirdef.h" class Definition; class ClassDef; @@ -32,9 +33,8 @@ class BaseClassList; class NamespaceSDict; class FileDef; class FileList; -class FileNameList; +class FileNameLinkedMap; class DirSDict; -class DirList; class DirDef; class PageSDict; class GroupSDict; @@ -46,8 +46,8 @@ class MemberSDict; class MemberDef; struct Argument; class ArgumentList; -class MemberNameInfoSDict; -struct MemberInfo; +class MemberNameInfoLinkedMap; +class MemberInfo; class MemberGroup; class MemberGroupSDict; class MemberGroupList; @@ -189,8 +189,8 @@ class UsedFilesContext : public RefCountedContext, public TemplateListIntf static UsedFilesContext *alloc(const ClassDef *cd) { return new UsedFilesContext(cd); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -234,8 +234,8 @@ class IncludeInfoListContext : public RefCountedContext, public TemplateListIntf { return new IncludeInfoListContext(list,lang); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -348,7 +348,7 @@ class PageContext : public RefCountedContext, public TemplateStructIntf class MemberContext : public RefCountedContext, public TemplateStructIntf { public: - static MemberContext *alloc(MemberDef *md) { return new MemberContext(md); } + static MemberContext *alloc(const MemberDef *md) { return new MemberContext(md); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -356,7 +356,7 @@ class MemberContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - MemberContext(MemberDef *); + MemberContext(const MemberDef *); ~MemberContext(); class Private; Private *p; @@ -390,8 +390,8 @@ class ClassListContext : public RefCountedContext, public TemplateListIntf static ClassListContext *alloc() { return new ClassListContext; } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -472,8 +472,8 @@ class ClassInheritanceContext : public RefCountedContext, public TemplateListInt static ClassInheritanceContext *alloc() { return new ClassInheritanceContext; } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -537,8 +537,8 @@ class NestingContext : public RefCountedContext, public TemplateListIntf { return new NestingContext(parent,level); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -547,7 +547,7 @@ class NestingContext : public RefCountedContext, public TemplateListIntf void addClasses(const ClassSDict &clDict,bool rootOnly); void addDirs(const DirSDict &); void addDirs(const DirList &); - void addFiles(const FileNameList &); + void addFiles(const FileNameLinkedMap &); void addFiles(const FileList &); void addPages(const PageSDict &pages,bool rootOnly); void addModules(const GroupSDict &modules); @@ -589,8 +589,8 @@ class NamespaceListContext : public RefCountedContext, public TemplateListIntf static NamespaceListContext *alloc() { return new NamespaceListContext; } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -629,8 +629,8 @@ class DirListContext : public RefCountedContext, public TemplateListIntf static DirListContext *alloc() { return new DirListContext; } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -650,8 +650,8 @@ class FileListContext : public RefCountedContext, public TemplateListIntf static FileListContext *alloc() { return new FileListContext; } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -690,8 +690,8 @@ class PageListContext : public RefCountedContext, public TemplateListIntf static PageListContext *alloc(const PageSDict *pages) { return new PageListContext(pages); } // TemplateListIntf methods - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -751,8 +751,8 @@ class ModuleListContext : public RefCountedContext, public TemplateListIntf static ModuleListContext *alloc() { return new ModuleListContext(); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -794,8 +794,8 @@ class ExampleListContext : public RefCountedContext, public TemplateListIntf static ExampleListContext *alloc() { return new ExampleListContext; } // TemplateListIntf methods - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -933,8 +933,8 @@ class InheritanceListContext : public RefCountedContext, public TemplateListIntf { return new InheritanceListContext(list,baseClasses); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -959,8 +959,8 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf { return new MemberListContext(ml,doSort); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -1007,8 +1007,8 @@ class MemberGroupListContext : public RefCountedContext, public TemplateListIntf { return new MemberGroupListContext(def,relPath,dict,subGrouping); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -1095,8 +1095,8 @@ class InheritedMemberInfoListContext : public RefCountedContext, public Template void addMemberList(const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList=TRUE); // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -1113,21 +1113,18 @@ class InheritedMemberInfoListContext : public RefCountedContext, public Template class AllMembersListContext : public RefCountedContext, public TemplateListIntf { public: - static AllMembersListContext *alloc() - { return new AllMembersListContext; } - static AllMembersListContext *alloc(const MemberNameInfoSDict *ml) + static AllMembersListContext *alloc(const MemberNameInfoLinkedMap &ml) { return new AllMembersListContext(ml); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } private: - AllMembersListContext(); - AllMembersListContext(const MemberNameInfoSDict *ml); + AllMembersListContext(const MemberNameInfoLinkedMap &ml); ~AllMembersListContext(); class Private; Private *p; @@ -1163,8 +1160,8 @@ class ArgumentListContext : public RefCountedContext, public TemplateListIntf { return new ArgumentListContext(al,def,relPath); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -1206,8 +1203,8 @@ class SymbolListContext : public RefCountedContext, public TemplateListIntf { return new SymbolListContext(sdl); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -1248,8 +1245,8 @@ class SymbolGroupListContext : public RefCountedContext, public TemplateListIntf { return new SymbolGroupListContext(sil); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -1290,8 +1287,8 @@ class SymbolIndicesContext : public RefCountedContext, public TemplateListIntf { return new SymbolIndicesContext(info); } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } @@ -1331,8 +1328,8 @@ class SearchIndicesContext : public RefCountedContext, public TemplateListIntf static SearchIndicesContext *alloc() { return new SearchIndicesContext; } // TemplateListIntf - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } diff --git a/src/debug.cpp b/src/debug.cpp index 4c7afb3..f56ef3a 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,68 +14,38 @@ */ #include <stdarg.h> +#include <algorithm> #include <stdio.h> - -#include <qdict.h> +#include <map> +#include <string> +#include <chrono> #include "debug.h" #include "message.h" //------------------------------------------------------------------------ -/** Helper struct representing a mapping from debug label to a debug ID */ -struct LabelMap -{ - const char *name; - Debug::DebugMask event; -}; - -static LabelMap s_labels[] = +static std::map< std::string, Debug::DebugMask > s_labels = { - { "findmembers", Debug::FindMembers }, - { "functions", Debug::Functions }, - { "variables", Debug::Variables }, - { "preprocessor", Debug::Preprocessor }, - { "classes", Debug::Classes }, - { "commentcnv", Debug::CommentCnv }, - { "commentscan", Debug::CommentScan }, - { "validate", Debug::Validate }, - { "printtree", Debug::PrintTree }, - { "time", Debug::Time }, - { "extcmd", Debug::ExtCmd }, - { "markdown", Debug::Markdown }, - { "filteroutput", Debug::FilterOutput }, - { "lex", Debug::Lex }, - { "plantuml", Debug::Plantuml }, + { "findmembers", Debug::FindMembers }, + { "functions", Debug::Functions }, + { "variables", Debug::Variables }, + { "preprocessor", Debug::Preprocessor }, + { "classes", Debug::Classes }, + { "commentcnv", Debug::CommentCnv }, + { "commentscan", Debug::CommentScan }, + { "validate", Debug::Validate }, + { "printtree", Debug::PrintTree }, + { "time", Debug::Time }, + { "extcmd", Debug::ExtCmd }, + { "markdown", Debug::Markdown }, + { "filteroutput", Debug::FilterOutput }, + { "lex", Debug::Lex }, + { "plantuml", Debug::Plantuml }, { "fortranfixed2free", Debug::FortranFixed2Free }, - { 0, (Debug::DebugMask)0 } -}; - -/** Class representing a mapping from debug labels to debug IDs. */ -class LabelMapper -{ - public: - LabelMapper() : m_map(17) - { - m_map.setAutoDelete(TRUE); - LabelMap *p = s_labels; - while (p->name) - { - m_map.insert(p->name,new Debug::DebugMask(p->event)); - p++; - } - } - Debug::DebugMask *find(const char *s) const - { - if (s==0) return 0; - return m_map.find(s); - } - private: - QDict<Debug::DebugMask> m_map; + { "cite", Debug::Cite } }; -static LabelMapper g_labelMapper; - //------------------------------------------------------------------------ Debug::DebugMask Debug::curMask = Debug::Quiet; @@ -94,17 +62,24 @@ void Debug::print(DebugMask mask,int prio,const char *fmt,...) } } +static char asciiToLower(char in) { + if (in <= 'Z' && in >= 'A') + return in - ('Z' - 'z'); + return in; +} + static int labelToEnumValue(const char *l) { - QCString label=l; - Debug::DebugMask *event = g_labelMapper.find(label.lower()); - if (event) return *event; else return 0; + std::string s = l; + std::transform(s.begin(),s.end(),s.begin(),asciiToLower); + auto it = s_labels.find(s); + return (it!=s_labels.end()) ? it->second : 0; } int Debug::setFlag(const char *lab) { int retVal = labelToEnumValue(lab); - curMask = (DebugMask)(curMask | labelToEnumValue(lab)); + curMask = (DebugMask)(curMask | labelToEnumValue(lab)); return retVal; } @@ -123,14 +98,42 @@ bool Debug::isFlagSet(DebugMask mask) return (curMask & mask)!=0; } -void Debug::printFlags(void) +void Debug::printFlags() { - int i; - for (i = 0; i < (int)(sizeof(s_labels)/sizeof(*s_labels)); i++) + for (const auto &v : s_labels) { - if (s_labels[i].name) - { - msg("\t%s\n",s_labels[i].name); - } + msg("\t%s\n",v.first.c_str()); } } + +//------------------------------------------------------------------------ + +class Timer +{ + public: + void start() + { + m_startTime = std::chrono::system_clock::now(); + } + double elapsedTimeS() + { + return (std::chrono::duration_cast< + std::chrono::milliseconds>( + std::chrono::system_clock::now() - m_startTime).count()) / 1000.0; + } + private: + std::chrono::time_point<std::chrono::system_clock> m_startTime; +}; + +static Timer g_runningTime; + +void Debug::startTimer() +{ + g_runningTime.start(); +} + +double Debug::elapsedTime() +{ + return g_runningTime.elapsedTimeS(); +} + diff --git a/src/debug.h b/src/debug.h index 79bc3d8..e71595f 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -24,8 +21,8 @@ class Debug { public: enum DebugMask { Quiet = 0x00000000, - FindMembers = 0x00000001, - Functions = 0x00000002, + FindMembers = 0x00000001, + Functions = 0x00000002, Variables = 0x00000004, Preprocessor = 0x00000008, Classes = 0x00000010, @@ -39,15 +36,20 @@ class Debug FilterOutput = 0x00001000, Lex = 0x00002000, Plantuml = 0x00004000, - FortranFixed2Free = 0x00008000 + FortranFixed2Free = 0x00008000, + Cite = 0x00010000 }; static void print(DebugMask mask,int prio,const char *fmt,...); + static int setFlag(const char *label); static void clearFlag(const char *label); static bool isFlagSet(DebugMask mask); - static void printFlags(void); + static void printFlags(); static void setPriority(int p); - + + static void startTimer(); + static double elapsedTime(); + private: static DebugMask curMask; static int curPrio; diff --git a/src/declinfo.l b/src/declinfo.l index af94569..2f497f9 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -20,6 +20,9 @@ %option noyywrap %option reentrant %option extra-type="struct declinfoYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -39,7 +42,9 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 #define YY_NEVER_INTERACTIVE 1 - + +#define USE_STATE2STRING 0 + /* ----------------------------------------------------------------- * * statics @@ -63,10 +68,13 @@ struct declinfoYY_state bool insidePHP; }; +#if USE_STATE2STRING static const char *stateToString(int state); +#endif + static void addType(yyscan_t yyscanner); static void addTypeName(yyscan_t yyscanner); -static int yyread(char *buf,int max_size, yyscan_t yyscanner); +static yy_size_t yyread(char *buf,yy_size_t max_size, yyscan_t yyscanner); /* ----------------------------------------------------------------- */ @@ -234,16 +242,16 @@ static void addTypeName(yyscan_t yyscanner) yyextra->name.resize(0); } -static int yyread(char *buf,int max_size, yyscan_t yyscanner) +static yy_size_t yyread(char *buf,yy_size_t max_size, yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - int c=0; - while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) - { - *buf = yyextra->inputString[yyextra->inputPosition++] ; - c++; buf++; - } - return c; + yy_size_t c=0; + while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + { + *buf = yyextra->inputString[yyextra->inputPosition++] ; + c++; buf++; + } + return c; } /*@ public interface------------------------------------------------------------ @@ -380,5 +388,6 @@ int main() } #endif - +#if USE_STATE2STRING #include "declinfo.l.h" +#endif diff --git a/src/defargs.h b/src/defargs.h index 4a38723..589eb90 100644 --- a/src/defargs.h +++ b/src/defargs.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,11 +19,13 @@ #define DEFARGS_H #include "types.h" +#include <memory> class ArgumentList; class QCString; -extern void stringToArgumentList(SrcLangExt lang, const char *argsString,ArgumentList& argList, - QCString *extraTypeChars=0); +std::unique_ptr<ArgumentList> stringToArgumentList(SrcLangExt lang, + const char *argsString, + QCString *extraTypeChars=0); #endif diff --git a/src/defargs.l b/src/defargs.l index 9745f44..6ecc7ff 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -41,6 +41,11 @@ */ %option never-interactive %option prefix="defargsYY" +%option reentrant +%option extra-type="struct defargsYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -62,81 +67,51 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 + +#define USE_STATE2STRING 0 /* ----------------------------------------------------------------- * state variables */ -static const char *g_inputString; -static int g_inputPosition; -static ArgumentList *g_argList; -static QCString *g_copyArgValue; -static QCString g_curArgTypeName; -static QCString g_curArgDefValue; -static QCString g_curArgName; -static QCString g_curArgDocs; -static QCString g_curArgAttrib; -static QCString g_curArgArray; -static QCString g_curTypeConstraint; -static QCString g_extraTypeChars; -static int g_argRoundCount; -static int g_argSharpCount; -static int g_argCurlyCount; -static int g_readArgContext; -static int g_lastDocContext; -static int g_lastDocChar; -static int g_lastExtendsContext; -static QCString g_delimiter; -static SrcLangExt g_lang; +struct defargsYY_state +{ + defargsYY_state(const char *inStr,std::unique_ptr<ArgumentList> &al,SrcLangExt l) + : inputString(inStr), argList(al), lang(l) {} + const char *inputString; + std::unique_ptr<ArgumentList> &argList; + SrcLangExt lang; + int inputPosition = 0; + QCString *copyArgValue = 0; + QCString curArgTypeName; + QCString curArgDefValue; + QCString curArgName; + QCString curArgDocs; + QCString curArgAttrib; + QCString curArgArray; + QCString curTypeConstraint; + QCString extraTypeChars; + int argRoundCount = 0; + int argSharpCount = 0; + int argCurlyCount = 0; + int readArgContext = 0; + int lastDocContext = 0; + int lastDocChar = 0; + int lastExtendsContext = 0; + QCString delimiter; +}; +#if USE_STATE2STRING static const char *stateToString(int state); +#endif + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static bool nameIsActuallyPartOfType(QCString &name); + /* ----------------------------------------------------------------- */ #undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static int yyread(char *buf,int max_size) -{ - int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); -/* bug_520975 */ -static bool nameIsActuallyPartOfType(QCString &name) -{ - static bool first=TRUE; - static QDict<void> keywords(17); - if (first) // fill keyword dict first time - { - #define DUMMY_ADDR (void*)0x8 - keywords.insert("unsigned", DUMMY_ADDR); // foo(... unsigned) - keywords.insert("signed", DUMMY_ADDR); // foo(... signed) - keywords.insert("bool", DUMMY_ADDR); // foo(... bool) - keywords.insert("char", DUMMY_ADDR); // foo(... char) - keywords.insert("char8_t", DUMMY_ADDR); // foo(... char8_t) - keywords.insert("char16_t", DUMMY_ADDR); // foo(... char16_t) - keywords.insert("char32_t", DUMMY_ADDR); // foo(... char32_t) - keywords.insert("int", DUMMY_ADDR); // foo(... int) - keywords.insert("short", DUMMY_ADDR); // foo(... short) - keywords.insert("long", DUMMY_ADDR); // foo(... long) - keywords.insert("float", DUMMY_ADDR); // foo(... float) - keywords.insert("double", DUMMY_ADDR); // foo(... double) - keywords.insert("int8_t", DUMMY_ADDR); // foo(... int8_t) - keywords.insert("uint8_t", DUMMY_ADDR); // foo(... uint8_t) - keywords.insert("int16_t", DUMMY_ADDR); // foo(... int16_t) - keywords.insert("uint16_t", DUMMY_ADDR); // foo(... uint16_t) - keywords.insert("int32_t", DUMMY_ADDR); // foo(... int32_t) - keywords.insert("uint32_t", DUMMY_ADDR); // foo(... uint32_t) - keywords.insert("const", DUMMY_ADDR); // foo(... const) - keywords.insert("volatile", DUMMY_ADDR); // foo(... volatile) - first=FALSE; - } - return name.length()>0 && keywords.find(name)!=0; -} %} B [ \t] @@ -168,124 +143,124 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <Start>[<(] { BEGIN(ReadFuncArgType); } <ReadFuncArgType>{B}* { - g_curArgTypeName+=" "; + yyextra->curArgTypeName+=" "; } <ReadFuncArgType>"["[^\]]*"]" { - if (g_curArgTypeName.stripWhiteSpace().isEmpty()) + if (yyextra->curArgTypeName.stripWhiteSpace().isEmpty()) { - g_curArgAttrib=yytext; // for M$-IDL + yyextra->curArgAttrib=yytext; // for M$-IDL } else // array type { - g_curArgArray+=yytext; + yyextra->curArgArray+=yytext; } } -<ReadFuncArgDef>"'"\\[0-7]{1,3}"'" { g_curArgDefValue+=yytext; } -<ReadFuncArgDef>"'"\\."'" { g_curArgDefValue+=yytext; } -<ReadFuncArgDef>"'"."'" { g_curArgDefValue+=yytext; } -<ReadFuncArgDef>{RAWBEGIN} { g_curArgDefValue+=yytext; +<ReadFuncArgDef>"'"\\[0-7]{1,3}"'" { yyextra->curArgDefValue+=yytext; } +<ReadFuncArgDef>"'"\\."'" { yyextra->curArgDefValue+=yytext; } +<ReadFuncArgDef>"'"."'" { yyextra->curArgDefValue+=yytext; } +<ReadFuncArgDef>{RAWBEGIN} { yyextra->curArgDefValue+=yytext; QCString text=yytext; int i=text.find('"'); - g_delimiter = yytext+i+1; - g_delimiter=g_delimiter.left(g_delimiter.length()-1); + yyextra->delimiter = yytext+i+1; + yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); BEGIN( CopyRawString ); } <ReadFuncArgDef>\" { - g_curArgDefValue+=*yytext; + yyextra->curArgDefValue+=*yytext; BEGIN( CopyArgString ); } <ReadFuncArgType>"("([^:)]+{B}*"::")*{B}*[&*\^]+{B}*/{ID} { // function pointer as argument - g_curArgTypeName+=yytext; - //g_curArgTypeName=g_curArgTypeName.simplifyWhiteSpace(); + yyextra->curArgTypeName+=yytext; + //yyextra->curArgTypeName=yyextra->curArgTypeName.simplifyWhiteSpace(); BEGIN( ReadFuncArgPtr ); } <ReadFuncArgPtr>{ID} { - g_curArgName=yytext; + yyextra->curArgName=yytext; } <ReadFuncArgPtr>")"{B}*"(" { // function pointer - g_curArgTypeName+=yytext; - //g_curArgTypeName=g_curArgTypeName.simplifyWhiteSpace(); - g_readArgContext = ReadFuncArgType; - g_copyArgValue=&g_curArgTypeName; - g_argRoundCount=0; + yyextra->curArgTypeName+=yytext; + //yyextra->curArgTypeName=yyextra->curArgTypeName.simplifyWhiteSpace(); + yyextra->readArgContext = ReadFuncArgType; + yyextra->copyArgValue=&yyextra->curArgTypeName; + yyextra->argRoundCount=0; BEGIN( CopyArgRound2 ); } <ReadFuncArgPtr>")"/{B}*"[" { // pointer to fixed size array - g_curArgTypeName+=yytext; - g_curArgTypeName+=g_curArgName; - //g_curArgTypeName=g_curArgTypeName.simplifyWhiteSpace(); + yyextra->curArgTypeName+=yytext; + yyextra->curArgTypeName+=yyextra->curArgName; + //yyextra->curArgTypeName=yyextra->curArgTypeName.simplifyWhiteSpace(); BEGIN( ReadFuncArgType ); } <ReadFuncArgPtr>")" { // redundant braces detected / remove them - int i=g_curArgTypeName.findRev('('),l=g_curArgTypeName.length(); + int i=yyextra->curArgTypeName.findRev('('),l=yyextra->curArgTypeName.length(); if (i!=-1) - g_curArgTypeName=g_curArgTypeName.left(i)+ - g_curArgTypeName.right(l-i-1); - g_curArgTypeName+=g_curArgName; + yyextra->curArgTypeName=yyextra->curArgTypeName.left(i)+ + yyextra->curArgTypeName.right(l-i-1); + yyextra->curArgTypeName+=yyextra->curArgName; BEGIN( ReadFuncArgType ); } <ReadFuncArgType>"<="|">="|"->"|">>"|"<<" { // handle operators in defargs - g_curArgTypeName+=yytext; + yyextra->curArgTypeName+=yytext; } <ReadFuncArgType,ReadFuncArgDef>[({<] { if (YY_START==ReadFuncArgType) { - g_curArgTypeName+=*yytext; - g_copyArgValue=&g_curArgTypeName; + yyextra->curArgTypeName+=*yytext; + yyextra->copyArgValue=&yyextra->curArgTypeName; } else // YY_START==ReadFuncArgDef { - g_curArgDefValue+=*yytext; - g_copyArgValue=&g_curArgDefValue; + yyextra->curArgDefValue+=*yytext; + yyextra->copyArgValue=&yyextra->curArgDefValue; } - g_readArgContext = YY_START; + yyextra->readArgContext = YY_START; if (*yytext=='(') { - g_argRoundCount=0; + yyextra->argRoundCount=0; BEGIN( CopyArgRound ); } else if (*yytext=='{') { - g_argCurlyCount=0; + yyextra->argCurlyCount=0; BEGIN( CopyArgCurly ); } else // yytext=='<' { - g_argSharpCount=0; - g_argRoundCount=0; + yyextra->argSharpCount=0; + yyextra->argRoundCount=0; BEGIN( CopyArgSharp ); } } <CopyArgRound,CopyArgRound2>"(" { - g_argRoundCount++; - *g_copyArgValue += *yytext; + yyextra->argRoundCount++; + *yyextra->copyArgValue += *yytext; } <CopyArgRound,CopyArgRound2>")"({B}*{ID})* { - *g_copyArgValue += yytext; - if (g_argRoundCount>0) + *yyextra->copyArgValue += yytext; + if (yyextra->argRoundCount>0) { - g_argRoundCount--; + yyextra->argRoundCount--; } else { if (YY_START==CopyArgRound2) { - *g_copyArgValue+=" "+g_curArgName; + *yyextra->copyArgValue+=" "+yyextra->curArgName; } - BEGIN( g_readArgContext ); + BEGIN( yyextra->readArgContext ); } } <CopyArgRound>")"/{B}* { - *g_copyArgValue += *yytext; - if (g_argRoundCount>0) g_argRoundCount--; - else BEGIN( g_readArgContext ); + *yyextra->copyArgValue += *yytext; + if (yyextra->argRoundCount>0) yyextra->argRoundCount--; + else BEGIN( yyextra->readArgContext ); } <CopyArgSharp>"<<" { - if (g_argRoundCount>0) + if (yyextra->argRoundCount>0) { // for e.g. < typename A = (i<<3) > - *g_copyArgValue += yytext; + *yyextra->copyArgValue += yytext; } else { @@ -293,10 +268,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } } <CopyArgSharp>">>" { - if (g_argRoundCount>0) + if (yyextra->argRoundCount>0) { // for e.g. < typename A = (i>>3) > - *g_copyArgValue += yytext; + *yyextra->copyArgValue += yytext; } else { @@ -305,66 +280,66 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <CopyArgSharp>"<" { // don't count < inside (, e.g. for things like: < typename A=(i<6) > - if (g_argRoundCount==0) g_argSharpCount++; - *g_copyArgValue += *yytext; + if (yyextra->argRoundCount==0) yyextra->argSharpCount++; + *yyextra->copyArgValue += *yytext; } <CopyArgSharp>">" { - *g_copyArgValue += *yytext; - if (g_argRoundCount>0 && g_argSharpCount==0) + *yyextra->copyArgValue += *yytext; + if (yyextra->argRoundCount>0 && yyextra->argSharpCount==0) { // don't count > inside ) } else { - if (g_argSharpCount>0) + if (yyextra->argSharpCount>0) { - g_argSharpCount--; + yyextra->argSharpCount--; } else { - BEGIN( g_readArgContext ); + BEGIN( yyextra->readArgContext ); } } } <CopyArgSharp>"(" { - g_argRoundCount++; - *g_copyArgValue += *yytext; + yyextra->argRoundCount++; + *yyextra->copyArgValue += *yytext; } <CopyArgSharp>")" { - g_argRoundCount--; - *g_copyArgValue += *yytext; + yyextra->argRoundCount--; + *yyextra->copyArgValue += *yytext; } <CopyArgCurly>"{" { - g_argCurlyCount++; - *g_copyArgValue += *yytext; + yyextra->argCurlyCount++; + *yyextra->copyArgValue += *yytext; } <CopyArgCurly>"}" { - *g_copyArgValue += *yytext; - if (g_argCurlyCount>0) g_argCurlyCount--; - else BEGIN( g_readArgContext ); + *yyextra->copyArgValue += *yytext; + if (yyextra->argCurlyCount>0) yyextra->argCurlyCount--; + else BEGIN( yyextra->readArgContext ); } <CopyArgString>\\. { - g_curArgDefValue+=yytext; + yyextra->curArgDefValue+=yytext; } <CopyRawString>{RAWEND} { - g_curArgDefValue+=yytext; + yyextra->curArgDefValue+=yytext; QCString delimiter = yytext+1; delimiter=delimiter.left(delimiter.length()-1); - if (delimiter==g_delimiter) + if (delimiter==yyextra->delimiter) { BEGIN( ReadFuncArgDef ); } } <CopyArgString>\" { - g_curArgDefValue+=*yytext; + yyextra->curArgDefValue+=*yytext; BEGIN( ReadFuncArgDef ); } <ReadFuncArgType>"=" { BEGIN( ReadFuncArgDef ); } <ReadFuncArgType,ReadFuncArgDef>[,)>]{B}*("/*"[*!]|"//"[/!])"<" { - g_lastDocContext=YY_START; - g_lastDocChar=*yytext; + yyextra->lastDocContext=YY_START; + yyextra->lastDocChar=*yytext; QCString text=yytext; if (text.find("//")!=-1) BEGIN( ReadDocLine ); @@ -372,49 +347,49 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" BEGIN( ReadDocBlock ); } <ReadFuncArgType,ReadFuncArgDef>[,)>] { - if (*yytext==')' && g_curArgTypeName.stripWhiteSpace().isEmpty()) + if (*yytext==')' && yyextra->curArgTypeName.stripWhiteSpace().isEmpty()) { - g_curArgTypeName+=*yytext; + yyextra->curArgTypeName+=*yytext; BEGIN(FuncQual); } else { - g_curArgTypeName=removeRedundantWhiteSpace(g_curArgTypeName); - g_curArgDefValue=g_curArgDefValue.stripWhiteSpace(); - //printf("curArgType='%s' curArgDefVal='%s'\n",g_curArgTypeName.data(),g_curArgDefValue.data()); - int l=g_curArgTypeName.length(); + yyextra->curArgTypeName=removeRedundantWhiteSpace(yyextra->curArgTypeName); + yyextra->curArgDefValue=yyextra->curArgDefValue.stripWhiteSpace(); + //printf("curArgType='%s' curArgDefVal='%s'\n",yyextra->curArgTypeName.data(),yyextra->curArgDefValue.data()); + int l=yyextra->curArgTypeName.length(); if (l>0) { int i=l-1; - while (i>=0 && (isspace((uchar)g_curArgTypeName.at(i)) || g_curArgTypeName.at(i)=='.')) i--; - while (i>=0 && (isId(g_curArgTypeName.at(i)) || g_curArgTypeName.at(i)=='$')) i--; + while (i>=0 && (isspace((uchar)yyextra->curArgTypeName.at(i)) || yyextra->curArgTypeName.at(i)=='.')) i--; + while (i>=0 && (isId(yyextra->curArgTypeName.at(i)) || yyextra->curArgTypeName.at(i)=='$')) i--; Argument a; - a.attrib = g_curArgAttrib.copy(); - a.typeConstraint = g_curTypeConstraint.stripWhiteSpace(); + a.attrib = yyextra->curArgAttrib.copy(); + a.typeConstraint = yyextra->curTypeConstraint.stripWhiteSpace(); //printf("a->type=%s a->name=%s i=%d l=%d\n", // a->type.data(),a->name.data(),i,l); a.array.resize(0); - if (i==l-1 && g_curArgTypeName.at(i)==')') // function argument + if (i==l-1 && yyextra->curArgTypeName.at(i)==')') // function argument { - int bi=g_curArgTypeName.find('('); + int bi=yyextra->curArgTypeName.find('('); int fi=bi-1; //printf("func arg fi=%d\n",fi); - while (fi>=0 && (isId(g_curArgTypeName.at(fi)) || g_curArgTypeName.at(fi)==':')) fi--; + while (fi>=0 && (isId(yyextra->curArgTypeName.at(fi)) || yyextra->curArgTypeName.at(fi)==':')) fi--; if (fi>=0) { - a.type = g_curArgTypeName.left(fi+1); - a.name = g_curArgTypeName.mid(fi+1,bi-fi-1).stripWhiteSpace(); - a.array = g_curArgTypeName.right(l-bi); + a.type = yyextra->curArgTypeName.left(fi+1); + a.name = yyextra->curArgTypeName.mid(fi+1,bi-fi-1).stripWhiteSpace(); + a.array = yyextra->curArgTypeName.right(l-bi); } else { - a.type = g_curArgTypeName; + a.type = yyextra->curArgTypeName; } } - else if (i>=0 && g_curArgTypeName.at(i)!=':') + else if (i>=0 && yyextra->curArgTypeName.at(i)!=':') { // type contains a name - a.type = removeRedundantWhiteSpace(g_curArgTypeName.left(i+1)).stripWhiteSpace(); - a.name = g_curArgTypeName.right(l-i-1).stripWhiteSpace(); + a.type = removeRedundantWhiteSpace(yyextra->curArgTypeName.left(i+1)).stripWhiteSpace(); + a.name = yyextra->curArgTypeName.right(l-i-1).stripWhiteSpace(); // if the type becomes a type specifier only then we make a mistake // and need to correct it to avoid seeing a nameless parameter @@ -437,20 +412,20 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } else // assume only the type was specified, try to determine name later { - a.type = removeRedundantWhiteSpace(g_curArgTypeName); + a.type = removeRedundantWhiteSpace(yyextra->curArgTypeName); } if (!a.type.isEmpty() && a.type.at(0)=='$') // typeless PHP name? { a.name = a.type; a.type = ""; } - a.array += removeRedundantWhiteSpace(g_curArgArray); + a.array += removeRedundantWhiteSpace(yyextra->curArgArray); //printf("array=%s\n",a->array.data()); int alen = a.array.length(); if (alen>2 && a.array.at(0)=='(' && a.array.at(alen-1)==')') // fix-up for int *(a[10]) { - int i=a.array.find('[')-1; + i=a.array.find('[')-1; a.array = a.array.mid(1,alen-2); if (i>0 && a.name.isEmpty()) { @@ -458,18 +433,18 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" a.array = a.array.mid(i); } } - a.defval = g_curArgDefValue.copy(); + a.defval = yyextra->curArgDefValue.copy(); //printf("a->type=%s a->name=%s a->defval=\"%s\"\n",a->type.data(),a->name.data(),a->defval.data()); - a.docs = g_curArgDocs.stripWhiteSpace(); + a.docs = yyextra->curArgDocs.stripWhiteSpace(); //printf("Argument '%s' '%s' adding docs='%s'\n",a->type.data(),a->name.data(),a->docs.data()); - g_argList->push_back(a); + yyextra->argList->push_back(a); } - g_curArgAttrib.resize(0); - g_curArgTypeName.resize(0); - g_curArgDefValue.resize(0); - g_curArgArray.resize(0); - g_curArgDocs.resize(0); - g_curTypeConstraint.resize(0); + yyextra->curArgAttrib.resize(0); + yyextra->curArgTypeName.resize(0); + yyextra->curArgDefValue.resize(0); + yyextra->curArgArray.resize(0); + yyextra->curArgDocs.resize(0); + yyextra->curTypeConstraint.resize(0); if (*yytext==')') { BEGIN(FuncQual); @@ -482,72 +457,72 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } } <ReadFuncArgType,ReadFuncArgPtr>"extends" { - if (g_lang!=SrcLangExt_Java) + if (yyextra->lang!=SrcLangExt_Java) { REJECT; } else { - g_curTypeConstraint.resize(0); - g_lastExtendsContext=YY_START; + yyextra->curTypeConstraint.resize(0); + yyextra->lastExtendsContext=YY_START; BEGIN(ReadTypeConstraint); } } <ReadFuncArgType,ReadFuncArgPtr>"$"?{ID} { QCString name=yytext; //resolveDefines(yytext); - if (YY_START==ReadFuncArgType && g_curArgArray=="[]") // Java style array + if (YY_START==ReadFuncArgType && yyextra->curArgArray=="[]") // Java style array { - g_curArgTypeName+=" []"; - g_curArgArray.resize(0); + yyextra->curArgTypeName+=" []"; + yyextra->curArgArray.resize(0); } //printf("resolveName '%s'->'%s'\n",yytext,name.data()); - g_curArgTypeName+=name; + yyextra->curArgTypeName+=name; } <ReadFuncArgType,ReadFuncArgPtr>. { - g_curArgTypeName+=*yytext; + yyextra->curArgTypeName+=*yytext; } <ReadFuncArgDef,CopyArgString>"<="|"->"|">="|">>"|"<<" { - g_curArgDefValue+=yytext; + yyextra->curArgDefValue+=yytext; } <ReadFuncArgDef,CopyArgString,CopyRawString>. { - g_curArgDefValue+=*yytext; + yyextra->curArgDefValue+=*yytext; } <CopyArgRound,CopyArgRound2,CopyArgSharp,CopyArgCurly>{ID} { QCString name=yytext; //resolveDefines(yytext); - *g_copyArgValue+=name; + *yyextra->copyArgValue+=name; } <CopyArgRound,CopyArgRound2,CopyArgSharp,CopyArgCurly>. { - *g_copyArgValue += *yytext; + *yyextra->copyArgValue += *yytext; } <ReadTypeConstraint>[,)>] { unput(*yytext); - BEGIN(g_lastExtendsContext); + BEGIN(yyextra->lastExtendsContext); } <ReadTypeConstraint>. { - g_curTypeConstraint+=yytext; + yyextra->curTypeConstraint+=yytext; } <ReadTypeConstraint>\n { - g_curTypeConstraint+=' '; + yyextra->curTypeConstraint+=' '; } <FuncQual>"const" { - g_argList->constSpecifier=TRUE; + yyextra->argList->setConstSpecifier(TRUE); } <FuncQual>"volatile" { - g_argList->volatileSpecifier=TRUE; + yyextra->argList->setVolatileSpecifier(TRUE); } <FuncQual>"&" { - g_argList->refQualifier=RefQualifierLValue; + yyextra->argList->setRefQualifier(RefQualifierLValue); } <FuncQual>"&&" { - g_argList->refQualifier=RefQualifierRValue; + yyextra->argList->setRefQualifier(RefQualifierRValue); } <FuncQual,TrailingReturn>"="{B}*"0" { - g_argList->pureSpecifier=TRUE; + yyextra->argList->setPureSpecifier(TRUE); BEGIN(FuncQual); } <FuncQual>"->" { // C++11 trailing return type - g_argList->trailingReturnType=" -> "; + yyextra->argList->setTrailingReturnType(" -> "); BEGIN(TrailingReturn); } <TrailingReturn>{B}/("final"|"override"){B}* { @@ -555,40 +530,40 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" BEGIN(FuncQual); } <TrailingReturn>. { - g_argList->trailingReturnType+=yytext; + yyextra->argList->setTrailingReturnType(yyextra->argList->trailingReturnType()+yytext); } <TrailingReturn>\n { - g_argList->trailingReturnType+=yytext; + yyextra->argList->setTrailingReturnType(yyextra->argList->trailingReturnType()+yytext); } <FuncQual>")"{B}*"["[^]]*"]" { // for functions returning a pointer to an array, // i.e. ")[]" in "int (*f(int))[4]" with argsString="(int))[4]" - g_extraTypeChars=yytext; + yyextra->extraTypeChars=yytext; } <ReadDocBlock>[^\*\n]+ { - g_curArgDocs+=yytext; + yyextra->curArgDocs+=yytext; } <ReadDocLine>[^\n]+ { - g_curArgDocs+=yytext; + yyextra->curArgDocs+=yytext; } <ReadDocBlock>"*/" { - if (g_lastDocChar!=0) - unput(g_lastDocChar); - BEGIN(g_lastDocContext); + if (yyextra->lastDocChar!=0) + unput(yyextra->lastDocChar); + BEGIN(yyextra->lastDocContext); } <ReadDocLine>\n { - if (g_lastDocChar!=0) - unput(g_lastDocChar); - BEGIN(g_lastDocContext); + if (yyextra->lastDocChar!=0) + unput(yyextra->lastDocChar); + BEGIN(yyextra->lastDocContext); } <ReadDocBlock>\n { - g_curArgDocs+=*yytext; + yyextra->curArgDocs+=*yytext; } <ReadDocBlock>. { - g_curArgDocs+=*yytext; + yyextra->curArgDocs+=*yytext; } <*>("/*"[*!]|"//"[/!])("<"?) { - g_lastDocContext=YY_START; - g_lastDocChar=0; + yyextra->lastDocContext=YY_START; + yyextra->lastDocChar=0; if (yytext[1]=='/') BEGIN( ReadDocLine ); else @@ -602,6 +577,190 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" /* ---------------------------------------------------------------------------- */ +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t c=0; + while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + { + *buf = yyextra->inputString[yyextra->inputPosition++] ; + c++; buf++; + } + return c; +} + +/* +The following code is generated using 'gperf keywords.txt' +where keywords.txt has the following content + +--------------------------------- +%define class-name KeywordHash +%define lookup-function-name find +%readonly-tables +%language=C++ +%% +unsigned +signed +bool +char +char8_t +char16_t +char32_t +wchar_t +int +short +long +float +double +int8_t +int16_t +int32_t +int64_t +intmax_t +intptr_t +uint8_t +uint16_t +uint32_t +uint64_t +uintmax_t +uintptr_t +const +volatile +void +%% +--------------------------------- +*/ +//--- begin gperf generated code ---------------------------------------------------------- + +#define TOTAL_KEYWORDS 28 +#define MIN_WORD_LENGTH 3 +#define MAX_WORD_LENGTH 9 +#define MIN_HASH_VALUE 3 +#define MAX_HASH_VALUE 48 +/* maximum key range = 46, duplicates = 0 */ + +class KeywordHash +{ + private: + static inline unsigned int hash (const char *str, unsigned int len); + public: + static const char *find (const char *str, unsigned int len); +}; + +inline unsigned int +KeywordHash::hash (const char *str, unsigned int len) +{ + static const unsigned char asso_values[] = + { + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, + 5, 30, 0, 49, 25, 49, 10, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 0, 49, 0, 5, 49, + 15, 0, 49, 10, 49, 30, 49, 49, 0, 20, + 0, 49, 15, 49, 5, 10, 0, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49 + }; + unsigned int hval = len; + + switch (hval) + { + default: + hval += asso_values[static_cast<unsigned char>(str[4])]; + /*FALLTHROUGH*/ + case 4: + hval += asso_values[static_cast<unsigned char>(str[3])]; + /*FALLTHROUGH*/ + case 3: + break; + } + return hval; +} + +const char * +KeywordHash::find (const char *str, unsigned int len) +{ + static const char * const wordlist[] = + { + "", "", "", + "int", + "bool", + "float", + "signed", + "", + "volatile", + "char", + "short", + "double", + "wchar_t", + "uint16_t", + "long", + "const", + "int8_t", + "uint8_t", + "char16_t", + "void", + "", "", + "char8_t", + "intptr_t", + "uintptr_t", + "", "", "", + "intmax_t", + "uintmax_t", + "", "", + "int64_t", + "uint64_t", + "", "", "", + "int16_t", + "uint32_t", + "", "", "", + "int32_t", + "char32_t", + "", "", "", "", + "unsigned" + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + unsigned int key = hash (str, len); + + if (key <= MAX_HASH_VALUE) + { + const char *s = wordlist[key]; + + if (*str == *s && !qstrcmp (str + 1, s + 1)) + return s; + } + } + return 0; +} + +//--- end gperf generated code ---------------------------------------------------------- + +/* bug_520975 */ +static bool nameIsActuallyPartOfType(QCString &name) +{ + return KeywordHash::find(name.data(),name.length())!=0; +} + /*! Converts an argument string into an ArgumentList. * \param[in] argsString the list of Arguments. * \param[out] al a reference to resulting argument list pointer. @@ -609,39 +768,34 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" * for complex types are written to */ -void stringToArgumentList(SrcLangExt lang, const char *argsString,ArgumentList& al,QCString *extraTypeChars) +std::unique_ptr<ArgumentList> stringToArgumentList(SrcLangExt lang, const char *argsString,QCString *extraTypeChars) { - if (argsString==0) return; + std::unique_ptr<ArgumentList> al = std::make_unique<ArgumentList>(); + if (argsString==0) return al; + + yyscan_t yyscanner; + defargsYY_state extra(argsString,al,lang); + defargsYYlex_init_extra(&extra,&yyscanner); +#ifdef FLEX_DEBUG + defargsYYset_debug(1,yyscanner); +#endif + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; printlex(yy_flex_debug, TRUE, __FILE__, NULL); - g_copyArgValue=0; - g_curArgDocs.resize(0); - g_curArgAttrib.resize(0); - g_curArgArray.resize(0); - g_curTypeConstraint.resize(0); - g_extraTypeChars.resize(0); - g_argRoundCount = 0; - g_argSharpCount = 0; - g_argCurlyCount = 0; - g_lastDocChar = 0; - - g_inputString = argsString; - g_inputPosition = 0; - g_curArgTypeName.resize(0); - g_curArgDefValue.resize(0); - g_curArgName.resize(0); - g_argList = &al; - g_lang = lang; - defargsYYrestart( defargsYYin ); + defargsYYrestart( 0, yyscanner ); BEGIN( Start ); - defargsYYlex(); - if (g_argList->empty()) + defargsYYlex(yyscanner); + if (yyextra->argList->empty()) { - g_argList->noParameters = TRUE; + yyextra->argList->setNoParameters(TRUE); } - if (extraTypeChars) *extraTypeChars=g_extraTypeChars; + if (extraTypeChars) *extraTypeChars=yyextra->extraTypeChars; //printf("stringToArgumentList(%s) result=%s\n",argsString,argListToString(al).data()); printlex(yy_flex_debug, FALSE, __FILE__, NULL); + defargsYYlex_destroy(yyscanner); + return al; } +#if USE_STATE2STRING #include "defargs.l.h" +#endif diff --git a/src/defgen.cpp b/src/defgen.cpp index cc3d5af..02f51c5 100644 --- a/src/defgen.cpp +++ b/src/defgen.cpp @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -71,14 +71,14 @@ void generateDEFForMember(MemberDef *md, // + source definition // - source references // - source referenced by - // - include code + // - include code if (md->memberType()==MemberType_EnumValue) return; QCString scopeName; - if (md->getClassDef()) + if (md->getClassDef()) scopeName=md->getClassDef()->name(); - else if (md->getNamespaceDef()) + else if (md->getNamespaceDef()) scopeName=md->getNamespaceDef()->name(); t << " " << Prefix << "-member = {" << endl; @@ -145,8 +145,7 @@ void generateDEFForMember(MemberDef *md, if (isFunc) //function { const ArgumentList &defAl = md->argumentList(); - ArgumentList declAl; - stringToArgumentList(md->getLanguage(),md->argsString(),declAl); + ArgumentList declAl = *stringToArgumentList(md->getLanguage(),md->argsString()); QCString fcnPrefix = " " + memPrefix + "param-"; auto defIt = defAl.begin(); @@ -185,7 +184,7 @@ void generateDEFForMember(MemberDef *md, if (!a.array.isEmpty()) { t << fcnPrefix << "array = "; - writeDEFString(t,a.array); + writeDEFString(t,a.array); t << ';' << endl; } if (!a.defval.isEmpty()) @@ -612,7 +611,7 @@ void generateDEF() FTextStream t(&f); t << "AutoGen Definitions dummy;" << endl; - if (Doxygen::classSDict->count()+Doxygen::inputNameList->count()>0) + if (Doxygen::classSDict->count()+Doxygen::inputNameLinkedMap->size()>0) { ClassSDict::Iterator cli(*Doxygen::classSDict); ClassDef *cd; @@ -620,15 +619,11 @@ void generateDEF() { generateDEFForClass(cd,t); } - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { - generateDEFForFile(fd,t); + generateDEFForFile(fd.get(),t); } } } diff --git a/src/define.cpp b/src/define.cpp deleted file mode 100644 index b5d9170..0000000 --- a/src/define.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#include "define.h" -#include "config.h" - -Define::Define() -{ - fileDef=0; - lineNr=1; - columnNr=1; - nargs=-1; - undef=FALSE; - varArgs=FALSE; - isPredefined=FALSE; - nonRecursive=FALSE; -} - -Define::Define(const Define &d) - : name(d.name),definition(d.definition),fileName(d.fileName) -{ - //name=d.name; definition=d.definition; fileName=d.fileName; - lineNr=d.lineNr; - columnNr=d.columnNr; - nargs=d.nargs; - undef=d.undef; - varArgs=d.varArgs; - isPredefined=d.isPredefined; - nonRecursive=d.nonRecursive; - fileDef=0; -} - -Define::~Define() -{ -} - -bool Define::hasDocumentation() -{ - return definition && (doc || Config_getBool(EXTRACT_ALL)); -} diff --git a/src/define.h b/src/define.h index cc1e390..23da59d 100644 --- a/src/define.h +++ b/src/define.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -18,8 +16,13 @@ #ifndef DEFINE_H #define DEFINE_H -#include <qdict.h> -#include <qlist.h> +#include <vector> +#include <memory> +#include <string> +#include <unordered_map> + +#include <qcstring.h> +#include "containers.h" class FileDef; @@ -27,73 +30,22 @@ class FileDef; class Define { public: - Define(); - Define(const Define &d); - ~Define(); - bool hasDocumentation(); QCString name; QCString definition; QCString fileName; - QCString doc; - QCString brief; QCString args; - QCString anchor; - FileDef *fileDef; - int lineNr; - int columnNr; - int nargs; - bool undef; - bool varArgs; - bool isPredefined; - bool nonRecursive; + FileDef *fileDef = 0; + int lineNr = 1; + int columnNr = 1; + int nargs = -1; + bool undef = FALSE; + bool varArgs = FALSE; + bool isPredefined = FALSE; + bool nonRecursive = FALSE; }; -/** A list of Define objects. */ -class DefineList : public QList<Define> -{ - public: - DefineList() : QList<Define>() {} - ~DefineList() {} - private: - int compareValues(const Define *d1,const Define *d2) const - { - return qstricmp(d1->name,d2->name); - } -}; - -/** A list of Define objects associated with a specific name. */ -class DefineName : public QList<Define> -{ - public: - DefineName(const char *n) : QList<Define>() { name=n; } - ~DefineName() {} - const char *nameString() const { return name; } - - private: - int compareValues(const Define *d1,const Define *d2) const - { - return qstricmp(d1->name,d2->name); - } - QCString name; -}; - -/** A list of DefineName objects. */ -class DefineNameList : public QList<DefineName> -{ - public: - DefineNameList() : QList<DefineName>() {} - ~DefineNameList() {} - private: - int compareValues(const DefineName *n1,const DefineName *n2) const - { - return qstricmp(n1->nameString(),n2->nameString()); - } -}; - -/** An unsorted dictionary of Define objects. */ -typedef QDict<Define> DefineDict; - -/** A sorted dictionary of DefineName object. */ -typedef QDict<DefineName> DefineNameDict; +/** List of all macro definitions */ +using DefineList = std::vector<Define>; +using DefinesPerFileList = std::unordered_map< std::string, DefineList >; #endif diff --git a/src/definition.cpp b/src/definition.cpp index 7540eff..3ed331c 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -44,6 +44,7 @@ #include "dirdef.h" #include "pagedef.h" #include "bufstr.h" +#include "reflist.h" //----------------------------------------------------------------------------------------- @@ -55,11 +56,11 @@ class DefinitionImpl::IMPL void init(const char *df, const char *n); void setDefFileName(const QCString &df); - SectionDict *sectionDict = 0; // dictionary of all sections, not accessible + SectionRefs sectionRefs; MemberSDict *sourceRefByDict = 0; MemberSDict *sourceRefsDict = 0; - std::vector<ListItemInfo> xrefListItems; + RefItemVector xrefListItems; GroupList *partOfGroups = 0; DocInfo *details = 0; // not exported @@ -99,7 +100,6 @@ class DefinitionImpl::IMPL DefinitionImpl::IMPL::~IMPL() { - delete sectionDict; delete sourceRefByDict; delete sourceRefsDict; delete partOfGroups; @@ -122,8 +122,8 @@ void DefinitionImpl::IMPL::setDefFileName(const QCString &df) void DefinitionImpl::IMPL::init(const char *df, const char *n) { setDefFileName(df); - QCString name = n; - if (name!="<globalScope>") + QCString lname = n; + if (lname!="<globalScope>") { //extractNamespaceName(m_name,m_localName,ns); localName=stripScope(n); @@ -140,7 +140,6 @@ void DefinitionImpl::IMPL::init(const char *df, const char *n) inbodyDocs = 0; sourceRefByDict = 0; sourceRefsDict = 0; - sectionDict = 0, outerScope = Doxygen::globalScope; partOfGroups = 0; hidden = FALSE; @@ -160,31 +159,31 @@ void DefinitionImpl::setDefFile(const QCString &df,int defLine,int defCol) static bool matchExcludedSymbols(const char *name) { - static QStrList &exclSyms = Config_getList(EXCLUDE_SYMBOLS); - if (exclSyms.count()==0) return FALSE; // nothing specified - const char *pat = exclSyms.first(); + const StringVector &exclSyms = Config_getList(EXCLUDE_SYMBOLS); + if (exclSyms.empty()) return FALSE; // nothing specified QCString symName = name; - while (pat) + for (const auto &pat : exclSyms) { - QCString pattern = pat; + QCString pattern = pat.c_str(); bool forceStart=FALSE; bool forceEnd=FALSE; - if (pattern.at(0)=='^') + if (pattern.at(0)=='^') pattern=pattern.mid(1),forceStart=TRUE; - if (pattern.at(pattern.length()-1)=='$') + if (pattern.at(pattern.length()-1)=='$') pattern=pattern.left(pattern.length()-1),forceEnd=TRUE; if (pattern.find('*')!=-1) // wildcard mode { QRegExp re(substitute(pattern,"*",".*"),TRUE); - int i,pl; - i = re.match(symName,0,&pl); + int pl; + int i = re.match(symName,0,&pl); //printf(" %d = re.match(%s) pattern=%s\n",i,symName.data(),pattern.data()); if (i!=-1) // wildcard match { - int sl=symName.length(); + uint ui=(uint)i; + uint sl=symName.length(); // check if it is a whole word match - if ((i==0 || pattern.at(0)=='*' || (!isId(symName.at(i-1)) && !forceStart)) && - (i+pl==sl || pattern.at(i+pl)=='*' || (!isId(symName.at(i+pl)) && !forceEnd)) + if ((ui==0 || pattern.at(0)=='*' || (!isId(symName.at(ui-1)) && !forceStart)) && + (ui+pl==sl || pattern.at(ui+pl)=='*' || (!isId(symName.at(ui+pl)) && !forceEnd)) ) { //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); @@ -197,19 +196,19 @@ static bool matchExcludedSymbols(const char *name) int i = symName.find(pattern); if (i!=-1) // we have a match! { - int pl=pattern.length(); - int sl=symName.length(); + uint ui=(uint)i; + uint pl=pattern.length(); + uint sl=symName.length(); // check if it is a whole word match - if ((i==0 || (!isId(symName.at(i-1)) && !forceStart)) && - (i+pl==sl || (!isId(symName.at(i+pl)) && !forceEnd)) + if ((ui==0 || (!isId(symName.at(ui-1)) && !forceStart)) && + (ui+pl==sl || (!isId(symName.at(ui+pl)) && !forceEnd)) ) { //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); - return TRUE; + return TRUE; } } } - pat = exclSyms.next(); } //printf("--> name=%s: no match\n",name); return FALSE; @@ -221,7 +220,7 @@ static void addToMap(const char *name,Definition *d) QCString symbolName = name; int index=computeQualifiedIndex(symbolName); if (!vhdlOpt && index!=-1) symbolName=symbolName.mid(index+2); - if (!symbolName.isEmpty()) + if (!symbolName.isEmpty()) { //printf("******* adding symbol '%s' (%p)\n",symbolName.data(),d); DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); @@ -265,7 +264,7 @@ static void addToMap(const char *name,Definition *d) static void removeFromMap(Definition *d) { QCString symbolName = d->_symbolName(); - if (!symbolName.isEmpty()) + if (!symbolName.isEmpty()) { //printf("******* removing symbol '%s' (%p)\n",symbolName.data(),d); DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); @@ -305,7 +304,7 @@ DefinitionImpl::DefinitionImpl(const char *df,int dl,int dc, if (isSymbol) addToMap(name,this); _setBriefDescription(b,df,dl); _setDocumentation(d,df,dl,TRUE,FALSE); - if (matchExcludedSymbols(name)) + if (matchExcludedSymbols(name)) { m_impl->hidden = TRUE; } @@ -315,7 +314,6 @@ DefinitionImpl::DefinitionImpl(const DefinitionImpl &d) { m_impl = new DefinitionImpl::IMPL; *m_impl = *d.m_impl; - m_impl->sectionDict = 0; m_impl->sourceRefByDict = 0; m_impl->sourceRefsDict = 0; m_impl->partOfGroups = 0; @@ -323,16 +321,6 @@ DefinitionImpl::DefinitionImpl(const DefinitionImpl &d) m_impl->details = 0; m_impl->body = 0; m_impl->inbodyDocs = 0; - if (d.m_impl->sectionDict) - { - m_impl->sectionDict = new SectionDict(17); - SDict<SectionInfo>::Iterator it(*d.m_impl->sectionDict); - SectionInfo *si; - for (it.toFirst();(si=it.current());++it) - { - m_impl->sectionDict->append(si->label,si); - } - } if (d.m_impl->sourceRefByDict) { m_impl->sourceRefByDict = new MemberSDict; @@ -408,7 +396,7 @@ void DefinitionImpl::setId(const char *id) { if (id==0) return; m_impl->id = id; - if (Doxygen::clangUsrMap) + if (Doxygen::clangUsrMap) { //printf("DefinitionImpl::setId '%s'->'%s'\n",id,m_impl->name.data()); Doxygen::clangUsrMap->insert(id,this); @@ -426,22 +414,18 @@ void DefinitionImpl::addSectionsToDefinition(const std::vector<const SectionInfo for (const SectionInfo *si : anchorList) { //printf("Add section '%s' to definition '%s'\n", - // si->label.data(),name().data()); - SectionInfo *gsi=Doxygen::sectionDict->find(si->label); + // si->label().data(),name().data()); + SectionManager &sm = SectionManager::instance(); + SectionInfo *gsi=sm.find(si->label()); //printf("===== label=%s gsi=%p\n",si->label.data(),gsi); if (gsi==0) { - gsi = new SectionInfo(*si); - Doxygen::sectionDict->append(si->label,gsi); - } - if (m_impl->sectionDict==0) - { - m_impl->sectionDict = new SectionDict(17); + gsi = sm.add(*si); } - if (m_impl->sectionDict->find(gsi->label)==0) + if (m_impl->sectionRefs.find(gsi->label())==0) { - m_impl->sectionDict->append(gsi->label,gsi); - gsi->definition = this; + m_impl->sectionRefs.add(gsi); + gsi->setDefinition(this); } } } @@ -449,16 +433,11 @@ void DefinitionImpl::addSectionsToDefinition(const std::vector<const SectionInfo bool DefinitionImpl::hasSections() const { //printf("DefinitionImpl::hasSections(%s) #sections=%d\n",name().data(), - // m_impl->sectionDict ? m_impl->sectionDict->count() : 0); - if (m_impl->sectionDict==0) return FALSE; - SDict<SectionInfo>::Iterator li(*m_impl->sectionDict); - SectionInfo *si; - for (li.toFirst();(si=li.current());++li) - { - if (si->type==SectionInfo::Section || - si->type==SectionInfo::Subsection || - si->type==SectionInfo::Subsubsection || - si->type==SectionInfo::Paragraph) + // m_impl->sectionRefs.size()); + if (m_impl->sectionRefs.empty()) return FALSE; + for (const SectionInfo *si : m_impl->sectionRefs) + { + if (isSection(si->type())) { return TRUE; } @@ -468,20 +447,17 @@ bool DefinitionImpl::hasSections() const void DefinitionImpl::addSectionsToIndex() { - if (m_impl->sectionDict==0) return; + if (m_impl->sectionRefs.empty()) return; //printf("DefinitionImpl::addSectionsToIndex()\n"); - SDict<SectionInfo>::Iterator li(*m_impl->sectionDict); - SectionInfo *si; int level=1; - for (li.toFirst();(si=li.current());++li) + for (auto it = m_impl->sectionRefs.begin(); it!=m_impl->sectionRefs.end(); ++it) { - if (si->type==SectionInfo::Section || - si->type==SectionInfo::Subsection || - si->type==SectionInfo::Subsubsection || - si->type==SectionInfo::Paragraph) + const SectionInfo *si = *it; + SectionType type = si->type(); + if (isSection(type)) { //printf(" level=%d title=%s\n",level,si->title.data()); - int nextLevel = (int)si->type; + int nextLevel = (int)type; int i; if (nextLevel>level) { @@ -497,16 +473,16 @@ void DefinitionImpl::addSectionsToIndex() Doxygen::indexList->decContentsDepth(); } } - QCString title = si->title; - if (title.isEmpty()) title = si->label; + QCString title = si->title(); + if (title.isEmpty()) title = si->label(); // determine if there is a next level inside this item - ++li; - bool isDir = ((li.current()) ? (int)(li.current()->type > nextLevel):FALSE); - --li; + auto it_next = std::next(it); + bool isDir = (it_next!=m_impl->sectionRefs.end()) ? + ((int)((*it_next)->type()) > nextLevel) : FALSE; Doxygen::indexList->addContentsItem(isDir,title, getReference(), getOutputFileBase(), - si->label, + si->label(), FALSE, TRUE); level = nextLevel; @@ -521,23 +497,21 @@ void DefinitionImpl::addSectionsToIndex() void DefinitionImpl::writeDocAnchorsToTagFile(FTextStream &tagFile) const { - if (m_impl->sectionDict) + if (!m_impl->sectionRefs.empty()) { - //printf("%s: writeDocAnchorsToTagFile(%d)\n",name().data(),m_impl->sectionDict->count()); - SDict<SectionInfo>::Iterator sdi(*m_impl->sectionDict); - SectionInfo *si; - for (;(si=sdi.current());++sdi) + //printf("%s: writeDocAnchorsToTagFile(%d)\n",name().data(),m_impl->sectionRef.size()); + for (const SectionInfo *si : m_impl->sectionRefs) { - if (!si->generated && si->ref.isEmpty() && !si->label.startsWith("autotoc_md")) + if (!si->generated() && si->ref().isEmpty() && !si->label().startsWith("autotoc_md")) { //printf("write an entry!\n"); if (definitionType()==TypeMember) tagFile << " "; - tagFile << " <docanchor file=\"" << addHtmlExtensionIfMissing(si->fileName) << "\""; - if (!si->title.isEmpty()) + tagFile << " <docanchor file=\"" << addHtmlExtensionIfMissing(si->fileName()) << "\""; + if (!si->title().isEmpty()) { - tagFile << " title=\"" << convertToXML(si->title) << "\""; + tagFile << " title=\"" << convertToXML(si->title()) << "\""; } - tagFile << ">" << si->label << "</docanchor>" << endl; + tagFile << ">" << si->label() << "</docanchor>" << endl; } } } @@ -619,14 +593,14 @@ void DefinitionImpl::setDocumentation(const char *d,const char *docFile,int docL #define uni_isupper(c) (QChar(c).category()==QChar::Letter_Uppercase) -// do a UTF-8 aware search for the last real character and return TRUE +// do a UTF-8 aware search for the last real character and return TRUE // if that is a multibyte one. static bool lastCharIsMultibyte(const QCString &s) { - int l = s.length(); + uint l = s.length(); int p = 0; int pp = -1; - while ((p=nextUtf8CharPosition(s,l,p))<l) pp=p; + while ((p=nextUtf8CharPosition(s,l,(uint)p))<(int)l) pp=p; if (pp==-1 || ((uchar)s[pp])<0x80) return FALSE; return TRUE; } @@ -634,21 +608,21 @@ static bool lastCharIsMultibyte(const QCString &s) void DefinitionImpl::_setBriefDescription(const char *b,const char *briefFile,int briefLine) { static QCString outputLanguage = Config_getEnum(OUTPUT_LANGUAGE); - static bool needsDot = outputLanguage!="Japanese" && + static bool needsDot = outputLanguage!="Japanese" && outputLanguage!="Chinese" && outputLanguage!="Korean"; QCString brief = b; brief = brief.stripWhiteSpace(); if (brief.isEmpty()) return; - int bl = brief.length(); + uint bl = brief.length(); if (bl>0 && needsDot) // add punctuation if needed { int c = brief.at(bl-1); switch(c) { case '.': case '!': case '?': case '>': case ':': case ')': break; - default: - if (uni_isupper(brief.at(0)) && !lastCharIsMultibyte(brief)) brief+='.'; + default: + if (uni_isupper(brief.at(0)) && !lastCharIsMultibyte(brief)) brief+='.'; break; } } @@ -686,8 +660,8 @@ void DefinitionImpl::_setBriefDescription(const char *b,const char *briefFile,in } } -void DefinitionImpl::setBriefDescription(const char *b,const char *briefFile,int briefLine) -{ +void DefinitionImpl::setBriefDescription(const char *b,const char *briefFile,int briefLine) +{ if (b==0) return; _setBriefDescription(b,briefFile,briefLine); } @@ -721,7 +695,7 @@ void DefinitionImpl::setInbodyDocumentation(const char *d,const char *inbodyFile struct FilterCacheItem { portable_off_t filePos; - uint fileSize; + size_t fileSize; }; /*! Cache for storing the result of filtering a file */ @@ -748,7 +722,7 @@ class FilterCache if (f) { bool success=TRUE; - str.resize(item->fileSize+1); + str.resize(static_cast<uint>(item->fileSize+1)); if (Portable::fseek(f,item->filePos,SEEK_SET)==-1) { err("Failed to seek to position %d in filter database file %s\n",(int)item->filePos,qPrint(Doxygen::filterDBFileName)); @@ -756,11 +730,11 @@ class FilterCache } if (success) { - int numBytes = fread(str.data(),1,item->fileSize,f); + size_t numBytes = fread(str.data(),1,item->fileSize,f); if (numBytes!=item->fileSize) { err("Failed to read %d bytes from position %d in filter database file %s: got %d bytes\n", - (int)item->fileSize,(int)item->filePos,qPrint(Doxygen::filterDBFileName),numBytes); + (int)item->fileSize,(int)item->filePos,qPrint(Doxygen::filterDBFileName),(int)numBytes); success=FALSE; } } @@ -782,7 +756,7 @@ class FilterCache Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd)); f = Portable::popen(cmd,"r"); FILE *bf = Portable::fopen(Doxygen::filterDBFileName,"a+b"); - FilterCacheItem *item = new FilterCacheItem; + item = new FilterCacheItem; item->filePos = m_endPos; if (bf==0) { @@ -794,16 +768,16 @@ class FilterCache return FALSE; } // append the filtered output to the database file - int size=0; + size_t size=0; while (!feof(f)) { - int bytesRead = fread(buf,1,blockSize,f); - int bytesWritten = fwrite(buf,1,bytesRead,bf); + size_t bytesRead = fread(buf,1,blockSize,f); + size_t bytesWritten = fwrite(buf,1,bytesRead,bf); if (bytesRead!=bytesWritten) { // handle error err("Failed to write to filter database %s. Wrote %d out of %d bytes\n", - qPrint(Doxygen::filterDBFileName),bytesWritten,bytesRead); + qPrint(Doxygen::filterDBFileName),(int)bytesWritten,(int)bytesRead); str.addChar('\0'); delete item; Portable::pclose(f); @@ -811,7 +785,7 @@ class FilterCache return FALSE; } size+=bytesWritten; - str.addArray(buf,bytesWritten); + str.addArray(buf,static_cast<uint>(bytesWritten)); } str.addChar('\0'); item->fileSize = size; @@ -831,8 +805,8 @@ class FilterCache f = Portable::fopen(fileName,"r"); while (!feof(f)) { - int bytesRead = fread(buf,1,blockSize,f); - str.addArray(buf,bytesRead); + size_t bytesRead = fread(buf,1,blockSize,f); + str.addArray(buf,static_cast<uint>(bytesRead)); } str.addChar('\0'); fclose(f); @@ -849,7 +823,7 @@ static FilterCache g_filterCache; //----------------------------------------- -/*! Reads a fragment of code from file \a fileName starting at +/*! Reads a fragment of code from file \a fileName starting at * line \a startLine and ending at line \a endLine (inclusive). The fragment is * stored in \a result. If FALSE is returned the code fragment could not be * found. @@ -874,14 +848,13 @@ bool readCodeFragment(const char *fileName, g_filterCache.getFileContents(fileName,str); bool found = lang==SrcLangExt_VHDL || - lang==SrcLangExt_Tcl || lang==SrcLangExt_Python || lang==SrcLangExt_Fortran; - // for VHDL, TCL, Python, and Fortran no bracket search is possible + // for VHDL, Python, and Fortran no bracket search is possible char *p=str.data(); if (p) { - int c=0; + char c=0; int col=0; int lineNr=1; // skip until the startLine has reached @@ -984,7 +957,7 @@ bool readCodeFragment(const char *fileName, int braceIndex = result.findRev('}'); if (braceIndex > newLineIndex) { - result.truncate(braceIndex+1); + result.truncate((uint)braceIndex+1); } endLine=lineNr-1; } @@ -1002,11 +975,11 @@ bool readCodeFragment(const char *fileName, } QCString DefinitionImpl::getSourceFileBase() const -{ +{ ASSERT(definitionType()!=Definition::TypeFile); // file overloads this method QCString fn; static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); - if (sourceBrowser && + if (sourceBrowser && m_impl->body && m_impl->body->startLine!=-1 && m_impl->body->fileDef) { fn = m_impl->body->fileDef->getSourceFileBase(); @@ -1023,11 +996,11 @@ QCString DefinitionImpl::getSourceAnchor() const { if (Htags::useHtags) { - qsnprintf(anchorStr,maxAnchorStrLen,"L%d",m_impl->body->startLine); + qsnprintf(anchorStr,maxAnchorStrLen,"L%d",m_impl->body->defLine); } else { - qsnprintf(anchorStr,maxAnchorStrLen,"l%05d",m_impl->body->startLine); + qsnprintf(anchorStr,maxAnchorStrLen,"l%05d",m_impl->body->defLine); } } return anchorStr; @@ -1050,15 +1023,15 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this. { QCString lineStr; - lineStr.sprintf("%d",m_impl->body->startLine); + lineStr.sprintf("%d",m_impl->body->defLine); QCString anchorStr = getSourceAnchor(); ol.startParagraph("definition"); if (lineMarkerPos<fileMarkerPos) // line marker before file marker { // write text left from linePos marker - ol.parseText(refText.left(lineMarkerPos)); + ol.parseText(refText.left(lineMarkerPos)); ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Man); if (!latexSourceCode) { ol.disable(OutputGenerator::Latex); @@ -1075,7 +1048,7 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const ol.writeObjectLink(0,fn,anchorStr,lineStr); ol.enableAll(); ol.disable(OutputGenerator::Html); - if (latexSourceCode) + if (latexSourceCode) { ol.disable(OutputGenerator::Latex); } @@ -1090,13 +1063,13 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const // write normal text (Man, Latex optionally, RTF optionally) ol.docify(lineStr); ol.popGeneratorState(); - + // write text between markers ol.parseText(refText.mid(lineMarkerPos+2, fileMarkerPos-lineMarkerPos-2)); ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Man); if (!latexSourceCode) { ol.disable(OutputGenerator::Latex); @@ -1113,7 +1086,7 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const ol.writeObjectLink(0,fn,0,m_impl->body->fileDef->name()); ol.enableAll(); ol.disable(OutputGenerator::Html); - if (latexSourceCode) + if (latexSourceCode) { ol.disable(OutputGenerator::Latex); } @@ -1128,17 +1101,16 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const // write normal text (Man, Latex optionally, RTF optionally) ol.docify(m_impl->body->fileDef->name()); ol.popGeneratorState(); - + // write text right from file marker - ol.parseText(refText.right( - refText.length()-fileMarkerPos-2)); + ol.parseText(refText.right(refText.length()-(uint)fileMarkerPos-2)); } else // file marker before line marker { // write text left from file marker - ol.parseText(refText.left(fileMarkerPos)); + ol.parseText(refText.left(fileMarkerPos)); ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Man); if (!latexSourceCode) { ol.disable(OutputGenerator::Latex); @@ -1155,7 +1127,7 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const ol.writeObjectLink(0,fn,0,m_impl->body->fileDef->name()); ol.enableAll(); ol.disable(OutputGenerator::Html); - if (latexSourceCode) + if (latexSourceCode) { ol.disable(OutputGenerator::Latex); } @@ -1170,14 +1142,14 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const // write normal text (RTF/Latex/Man only) ol.docify(m_impl->body->fileDef->name()); ol.popGeneratorState(); - + // write text between markers ol.parseText(refText.mid(fileMarkerPos+2, - lineMarkerPos-fileMarkerPos-2)); + lineMarkerPos-fileMarkerPos-2)); ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - ol.disableAllBut(OutputGenerator::Html); + ol.disable(OutputGenerator::Man); + ol.disableAllBut(OutputGenerator::Html); if (latexSourceCode) { ol.enable(OutputGenerator::Latex); @@ -1194,7 +1166,7 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const ol.writeObjectLink(0,fn,anchorStr,lineStr); ol.enableAll(); ol.disable(OutputGenerator::Html); - if (latexSourceCode) + if (latexSourceCode) { ol.disable(OutputGenerator::Latex); } @@ -1211,8 +1183,7 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const ol.popGeneratorState(); // write text right from linePos marker - ol.parseText(refText.right( - refText.length()-lineMarkerPos-2)); + ol.parseText(refText.right(refText.length()-(uint)lineMarkerPos-2)); } ol.endParagraph(); } @@ -1224,18 +1195,19 @@ void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const ol.popGeneratorState(); } -void DefinitionImpl::setBodySegment(int bls,int ble) +void DefinitionImpl::setBodySegment(int defLine, int bls,int ble) { //printf("setBodySegment(%d,%d) for %s\n",bls,ble,name().data()); if (m_impl->body==0) m_impl->body = new BodyInfo; - m_impl->body->startLine=bls; - m_impl->body->endLine=ble; + m_impl->body->defLine = defLine; + m_impl->body->startLine = bls; + m_impl->body->endLine = ble; } -void DefinitionImpl::setBodyDef(FileDef *fd) +void DefinitionImpl::setBodyDef(FileDef *fd) { if (m_impl->body==0) m_impl->body = new BodyInfo; - m_impl->body->fileDef=fd; + m_impl->body->fileDef=fd; } bool DefinitionImpl::hasSources() const @@ -1288,13 +1260,13 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) const ol.popGeneratorState(); } -/*! Write a reference to the source code fragments in which this +/*! Write a reference to the source code fragments in which this * definition is used. */ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, const QCString &text,MemberSDict *members,bool /*funcOnly*/) const { - static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); + static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); @@ -1308,15 +1280,17 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, ol.parseText(text); ol.docify(" "); - QCString ldefLine=theTranslator->trWriteList(members->count()); + QCString ldefLine=theTranslator->trWriteList((int)members->count()); QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; + uint index=0; + int matchLen; + int newIndex; // now replace all markers in inheritLine with links to the classes while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1) { bool ok; - ol.parseText(ldefLine.mid(index,newIndex-index)); + ol.parseText(ldefLine.mid(index,(uint)newIndex-index)); uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); MemberDef *md=members->at(entryIndex); if (ok && md) @@ -1329,27 +1303,27 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang)); } if (!md->isObjCMethod() && - (md->isFunction() || md->isSlot() || + (md->isFunction() || md->isSlot() || md->isPrototype() || md->isSignal() ) - ) + ) { name+="()"; } //DefinitionImpl *d = md->getOutputFileBase(); //if (d==Doxygen::globalScope) d=md->getBodyDef(); if (sourceBrowser && - !(md->isLinkable() && !refLinkSource) && - md->getStartBodyLine()!=-1 && + !(md->isLinkable() && !refLinkSource) && + md->getStartBodyLine()!=-1 && md->getBodyDef() ) { - //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); + //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); // for HTML write a real link ol.pushGeneratorState(); //ol.disableAllBut(OutputGenerator::Html); - ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Man); if (!latexSourceCode) { ol.disable(OutputGenerator::Latex); @@ -1391,8 +1365,8 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, { // for HTML write a real link ol.pushGeneratorState(); - //ol.disableAllBut(OutputGenerator::Html); - ol.disable(OutputGenerator::Man); + //ol.disableAllBut(OutputGenerator::Html); + ol.disable(OutputGenerator::Man); if (!latexSourceCode) { ol.disable(OutputGenerator::Latex); @@ -1434,8 +1408,8 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, ol.docify(name); } } - index=newIndex+matchLen; - } + index=(uint)newIndex+matchLen; + } ol.parseText(ldefLine.right(ldefLine.length()-index)); ol.writeString("."); ol.endParagraph(); @@ -1454,15 +1428,15 @@ void DefinitionImpl::writeSourceRefs(OutputList &ol,const char *scopeName) const } bool DefinitionImpl::hasDocumentation() const -{ - static bool extractAll = Config_getBool(EXTRACT_ALL); +{ + static bool extractAll = Config_getBool(EXTRACT_ALL); //static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); - bool hasDocs = + bool hasDocs = (m_impl->details && !m_impl->details->doc.isEmpty()) || // has detailed docs (m_impl->brief && !m_impl->brief->doc.isEmpty()) || // has brief description (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty()) || // has inbody docs extractAll //|| // extract everything - // (sourceBrowser && m_impl->body && + // (sourceBrowser && m_impl->body && // m_impl->body->startLine!=-1 && m_impl->body->fileDef) ; // link to definition return hasDocs; @@ -1470,7 +1444,7 @@ bool DefinitionImpl::hasDocumentation() const bool DefinitionImpl::hasUserDocumentation() const { - bool hasDocs = + bool hasDocs = (m_impl->details && !m_impl->details->doc.isEmpty()) || (m_impl->brief && !m_impl->brief->doc.isEmpty()) || (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty()); @@ -1538,24 +1512,24 @@ QCString DefinitionImpl::qualifiedName() const { //static int count=0; //count++; - if (!m_impl->qualifiedName.isEmpty()) + if (!m_impl->qualifiedName.isEmpty()) { //count--; return m_impl->qualifiedName; } - + //printf("start %s::qualifiedName() localName=%s\n",name().data(),m_impl->localName.data()); - if (m_impl->outerScope==0) + if (m_impl->outerScope==0) { - if (m_impl->localName=="<globalScope>") + if (m_impl->localName=="<globalScope>") { //count--; return ""; } - else + else { //count--; - return m_impl->localName; + return m_impl->localName; } } @@ -1604,7 +1578,7 @@ void DefinitionImpl::makePartOfGroup(GroupDef *gd) m_impl->partOfGroups->append(gd); } -void DefinitionImpl::setRefItems(const std::vector<ListItemInfo> &sli) +void DefinitionImpl::setRefItems(const RefItemVector &sli) { m_impl->xrefListItems.insert(m_impl->xrefListItems.end(), sli.cbegin(), sli.cend()); } @@ -1620,31 +1594,34 @@ void DefinitionImpl::mergeRefItems(Definition *d) // sort results on itemId std::sort(m_impl->xrefListItems.begin(),m_impl->xrefListItems.end(), - [](const ListItemInfo &left,const ListItemInfo &right) - { return left.itemId<right.itemId || - (left.itemId==right.itemId && qstrcmp(left.type,right.type)<0); + [](RefItem *left,RefItem *right) + { return left->id() <right->id() || + (left->id()==right->id() && + qstrcmp(left->list()->listName(),right->list()->listName())<0); }); // filter out duplicates auto last = std::unique(m_impl->xrefListItems.begin(),m_impl->xrefListItems.end(), - [](const ListItemInfo &left,const ListItemInfo &right) - { return left.itemId==right.itemId && left.type==right.type; }); + [](const RefItem *left,const RefItem *right) + { return left->id()==right->id() && + left->list()->listName()==right->list()->listName(); + }); m_impl->xrefListItems.erase(last, m_impl->xrefListItems.end()); } int DefinitionImpl::_getXRefListId(const char *listName) const { - for (const ListItemInfo &lii : m_impl->xrefListItems) + for (const RefItem *item : m_impl->xrefListItems) { - if (lii.type==listName) + if (item->list()->listName()==listName) { - return lii.itemId; + return item->id(); } } return -1; } -const std::vector<ListItemInfo> &DefinitionImpl::xrefListItems() const +const RefItemVector &DefinitionImpl::xrefListItems() const { return m_impl->xrefListItems; } @@ -1682,7 +1659,7 @@ QCString DefinitionImpl::pathFragment() const //---------------------------------------------------------------------------------------- // TODO: move to htmlgen -/*! Returns the string used in the footer for $navpath when +/*! Returns the string used in the footer for $navpath when * GENERATE_TREEVIEW is enabled */ QCString DefinitionImpl::navigationPathAsString() const @@ -1756,8 +1733,7 @@ void DefinitionImpl::writeNavigationPath(OutputList &ol) const // TODO: move to htmlgen void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const { - SectionDict *sectionDict = m_impl->sectionDict; - if (sectionDict==0) return; + if (m_impl->sectionRefs.empty()) return; if (localToc.isHtmlEnabled()) { int maxLevel = localToc.htmlLevel(); @@ -1768,21 +1744,17 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const ol.writeString(theTranslator->trRTFTableOfContents()); ol.writeString("</h3>\n"); ol.writeString("<ul>"); - SDict<SectionInfo>::Iterator li(*sectionDict); - SectionInfo *si; int level=1,l; char cs[2]; cs[1]='\0'; - bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; - for (li.toFirst();(si=li.current());++li) + BoolVector inLi(maxLevel+1,false); + for (const SectionInfo *si : m_impl->sectionRefs) { - if (si->type==SectionInfo::Section || - si->type==SectionInfo::Subsection || - si->type==SectionInfo::Subsubsection || - si->type==SectionInfo::Paragraph) + SectionType type = si->type(); + if (isSection(type)) { //printf(" level=%d title=%s\n",level,si->title.data()); - int nextLevel = (int)si->type; + int nextLevel = (int)type; if (nextLevel>level) { for (l=level;l<nextLevel;l++) @@ -1795,28 +1767,39 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const for (l=level;l>nextLevel;l--) { if (l <= maxLevel && inLi[l]) ol.writeString("</li>\n"); - inLi[l]=FALSE; + inLi[l]=false; if (l <= maxLevel) ol.writeString("</ul>\n"); } } - cs[0]='0'+nextLevel; - if (nextLevel <= maxLevel && inLi[nextLevel]) ol.writeString("</li>\n"); - QCString titleDoc = convertToHtml(si->title); - if (nextLevel <= maxLevel) ol.writeString("<li class=\"level"+QCString(cs)+"\"><a href=\"#"+si->label+"\">"+(si->title.isEmpty()?si->label:titleDoc)+"</a>"); - inLi[nextLevel]=TRUE; + cs[0]=(char)('0'+nextLevel); + if (nextLevel <= maxLevel && inLi[nextLevel]) + { + ol.writeString("</li>\n"); + } + QCString titleDoc = convertToHtml(si->title()); + if (nextLevel <= maxLevel) + { + ol.writeString("<li class=\"level"+QCString(cs)+"\">" + "<a href=\"#"+si->label()+"\">"+ + (si->title().isEmpty()?si->label():titleDoc)+"</a>"); + } + inLi[nextLevel]=true; level = nextLevel; } } if (level > maxLevel) level = maxLevel; while (level>1 && level <= maxLevel) { - if (inLi[level]) ol.writeString("</li>\n"); + if (inLi[level]) + { + ol.writeString("</li>\n"); + } inLi[level]=FALSE; ol.writeString("</ul>\n"); level--; } if (level <= maxLevel && inLi[level]) ol.writeString("</li>\n"); - inLi[level]=FALSE; + inLi[level]=false; ol.writeString("</ul>\n"); ol.writeString("</div>\n"); ol.popGeneratorState(); @@ -1828,21 +1811,16 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const ol.disableAllBut(OutputGenerator::Docbook); ol.writeString(" <toc>\n"); ol.writeString(" <title>" + theTranslator->trRTFTableOfContents() + "</title>\n"); - SectionDict *sectionDict = getSectionDict(); - SDict<SectionInfo>::Iterator li(*sectionDict); - SectionInfo *si; int level=1,l; - bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; int maxLevel = localToc.docbookLevel(); - for (li.toFirst();(si=li.current());++li) + BoolVector inLi(maxLevel+1,false); + for (const SectionInfo *si : m_impl->sectionRefs) { - if (si->type==SectionInfo::Section || - si->type==SectionInfo::Subsection || - si->type==SectionInfo::Subsubsection || - si->type==SectionInfo::Paragraph) + SectionType type = si->type(); + if (isSection(type)) { //printf(" level=%d title=%s\n",level,si->title.data()); - int nextLevel = (int)si->type; + int nextLevel = (int)type; if (nextLevel>level) { for (l=level;l<nextLevel;l++) @@ -1860,8 +1838,10 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const } if (nextLevel <= maxLevel) { - QCString titleDoc = convertToDocBook(si->title); - ol.writeString(" <tocentry>" + (si->title.isEmpty()?si->label:titleDoc) + "</tocentry>\n"); + QCString titleDoc = convertToDocBook(si->title()); + ol.writeString(" <tocentry>" + + (si->title().isEmpty()?si->label():titleDoc) + + "</tocentry>\n"); } inLi[nextLevel]=TRUE; level = nextLevel; @@ -1894,31 +1874,31 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const //---------------------------------------------------------------------------------------- -SectionDict * DefinitionImpl::getSectionDict() const +const SectionRefs &DefinitionImpl::getSectionRefs() const { - return m_impl->sectionDict; + return m_impl->sectionRefs; } -QCString DefinitionImpl::symbolName() const -{ - return m_impl->symbolName; +QCString DefinitionImpl::symbolName() const +{ + return m_impl->symbolName; } //---------------------- -QCString DefinitionImpl::documentation() const -{ - return m_impl->details ? m_impl->details->doc : QCString(""); +QCString DefinitionImpl::documentation() const +{ + return m_impl->details ? m_impl->details->doc : QCString(""); } -int DefinitionImpl::docLine() const -{ - return m_impl->details ? m_impl->details->line : 1; +int DefinitionImpl::docLine() const +{ + return m_impl->details ? m_impl->details->line : 1; } -QCString DefinitionImpl::docFile() const -{ - return m_impl->details ? m_impl->details->file : QCString("<"+m_impl->name+">"); +QCString DefinitionImpl::docFile() const +{ + return m_impl->details ? m_impl->details->file : QCString("<"+m_impl->name+">"); } //---------------------------------------------------------------------------- @@ -1926,7 +1906,7 @@ QCString DefinitionImpl::docFile() const static bool stripWord(QCString &s,QCString w) { bool success=FALSE; - if (s.left(w.length())==w) + if (s.left(w.length())==w) { success=TRUE; s=s.right(s.length()-w.length()); @@ -1944,25 +1924,23 @@ QCString abbreviate(const char *s,const char *name) QCString result=s; result=result.stripWhiteSpace(); // strip trailing . - if (!result.isEmpty() && result.at(result.length()-1)=='.') + if (!result.isEmpty() && result.at(result.length()-1)=='.') result=result.left(result.length()-1); // strip any predefined prefix - QStrList &briefDescAbbrev = Config_getList(ABBREVIATE_BRIEF); - const char *p = briefDescAbbrev.first(); - while (p) + const StringVector &briefDescAbbrev = Config_getList(ABBREVIATE_BRIEF); + for (const auto &p : briefDescAbbrev) { - QCString s = p; - s.replace(QRegExp("\\$name"), scopelessName); // replace $name with entity name - s += " "; - stripWord(result,s); - p = briefDescAbbrev.next(); + QCString str = p.c_str(); + str.replace(QRegExp("\\$name"), scopelessName); // replace $name with entity name + str += " "; + stripWord(result,str); } // capitalize first word if (!result.isEmpty()) { - int c=result[0]; + char c=result[0]; if (c>='a' && c<='z') c+='A'-'a'; result[0]=c; } @@ -1972,12 +1950,12 @@ QCString abbreviate(const char *s,const char *name) //---------------------- -QCString DefinitionImpl::briefDescription(bool abbr) const -{ +QCString DefinitionImpl::briefDescription(bool abbr) const +{ //printf("%s::briefDescription(%d)='%s'\n",name().data(),abbr,m_impl->brief?m_impl->brief->doc.data():"<none>"); - return m_impl->brief ? + return m_impl->brief ? (abbr ? abbreviate(m_impl->brief->doc,displayName()) : m_impl->brief->doc) : - QCString(""); + QCString(""); } QCString DefinitionImpl::briefDescriptionAsTooltip() const @@ -1986,7 +1964,7 @@ QCString DefinitionImpl::briefDescriptionAsTooltip() const { if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) { - static bool reentering=FALSE; + static bool reentering=FALSE; if (!reentering) { const MemberDef *md = definitionType()==TypeMember ? dynamic_cast<const MemberDef*>(this) : 0; @@ -2005,44 +1983,44 @@ QCString DefinitionImpl::briefDescriptionAsTooltip() const return QCString(""); } -int DefinitionImpl::briefLine() const -{ - return m_impl->brief ? m_impl->brief->line : 1; +int DefinitionImpl::briefLine() const +{ + return m_impl->brief ? m_impl->brief->line : 1; } -QCString DefinitionImpl::briefFile() const -{ - return m_impl->brief ? m_impl->brief->file : QCString("<"+m_impl->name+">"); +QCString DefinitionImpl::briefFile() const +{ + return m_impl->brief ? m_impl->brief->file : QCString("<"+m_impl->name+">"); } //---------------------- QCString DefinitionImpl::inbodyDocumentation() const { - return m_impl->inbodyDocs ? m_impl->inbodyDocs->doc : QCString(""); + return m_impl->inbodyDocs ? m_impl->inbodyDocs->doc : QCString(""); } -int DefinitionImpl::inbodyLine() const -{ - return m_impl->inbodyDocs ? m_impl->inbodyDocs->line : 1; +int DefinitionImpl::inbodyLine() const +{ + return m_impl->inbodyDocs ? m_impl->inbodyDocs->line : 1; } -QCString DefinitionImpl::inbodyFile() const -{ - return m_impl->inbodyDocs ? m_impl->inbodyDocs->file : QCString("<"+m_impl->name+">"); +QCString DefinitionImpl::inbodyFile() const +{ + return m_impl->inbodyDocs ? m_impl->inbodyDocs->file : QCString("<"+m_impl->name+">"); } //---------------------- -QCString DefinitionImpl::getDefFileName() const -{ - return m_impl->defFileName; +QCString DefinitionImpl::getDefFileName() const +{ + return m_impl->defFileName; } -QCString DefinitionImpl::getDefFileExtension() const -{ - return m_impl->defFileExt; +QCString DefinitionImpl::getDefFileExtension() const +{ + return m_impl->defFileExt; } bool DefinitionImpl::isHidden() const @@ -2050,14 +2028,14 @@ bool DefinitionImpl::isHidden() const return m_impl->hidden; } -bool DefinitionImpl::isVisibleInProject() const -{ - return isLinkableInProject() && !m_impl->hidden; +bool DefinitionImpl::isVisibleInProject() const +{ + return isLinkableInProject() && !m_impl->hidden; } bool DefinitionImpl::isVisible() const -{ - return isLinkable() && !m_impl->hidden; +{ + return isLinkable() && !m_impl->hidden; } bool DefinitionImpl::isArtificial() const @@ -2065,34 +2043,39 @@ bool DefinitionImpl::isArtificial() const return m_impl->isArtificial; } -QCString DefinitionImpl::getReference() const -{ - return m_impl->ref; +QCString DefinitionImpl::getReference() const +{ + return m_impl->ref; } -bool DefinitionImpl::isReference() const -{ - return !m_impl->ref.isEmpty(); +bool DefinitionImpl::isReference() const +{ + return !m_impl->ref.isEmpty(); +} + +int DefinitionImpl::getStartDefLine() const +{ + return m_impl->body ? m_impl->body->defLine : -1; } -int DefinitionImpl::getStartBodyLine() const -{ - return m_impl->body ? m_impl->body->startLine : -1; +int DefinitionImpl::getStartBodyLine() const +{ + return m_impl->body ? m_impl->body->startLine : -1; } -int DefinitionImpl::getEndBodyLine() const -{ - return m_impl->body ? m_impl->body->endLine : -1; +int DefinitionImpl::getEndBodyLine() const +{ + return m_impl->body ? m_impl->body->endLine : -1; } FileDef *DefinitionImpl::getBodyDef() const -{ - return m_impl->body ? m_impl->body->fileDef : 0; +{ + return m_impl->body ? m_impl->body->fileDef : 0; } -GroupList *DefinitionImpl::partOfGroups() const -{ - return m_impl->partOfGroups; +GroupList *DefinitionImpl::partOfGroups() const +{ + return m_impl->partOfGroups; } bool DefinitionImpl::isLinkableViaGroup() const @@ -2110,24 +2093,24 @@ bool DefinitionImpl::isLinkableViaGroup() const return FALSE; } -Definition *DefinitionImpl::getOuterScope() const -{ - return m_impl->outerScope; +Definition *DefinitionImpl::getOuterScope() const +{ + return m_impl->outerScope; } -MemberSDict *DefinitionImpl::getReferencesMembers() const -{ - return m_impl->sourceRefsDict; +MemberSDict *DefinitionImpl::getReferencesMembers() const +{ + return m_impl->sourceRefsDict; } -MemberSDict *DefinitionImpl::getReferencedByMembers() const -{ - return m_impl->sourceRefByDict; +MemberSDict *DefinitionImpl::getReferencedByMembers() const +{ + return m_impl->sourceRefByDict; } -void DefinitionImpl::setReference(const char *r) -{ - m_impl->ref=r; +void DefinitionImpl::setReference(const char *r) +{ + m_impl->ref=r; } SrcLangExt DefinitionImpl::getLanguage() const @@ -2135,9 +2118,9 @@ SrcLangExt DefinitionImpl::getLanguage() const return m_impl->lang; } -void DefinitionImpl::setHidden(bool b) -{ - m_impl->hidden = m_impl->hidden || b; +void DefinitionImpl::setHidden(bool b) +{ + m_impl->hidden = m_impl->hidden || b; } void DefinitionImpl::setArtificial(bool b) @@ -2145,20 +2128,20 @@ void DefinitionImpl::setArtificial(bool b) m_impl->isArtificial = b; } -void DefinitionImpl::setLocalName(const QCString name) -{ - m_impl->localName=name; +void DefinitionImpl::setLocalName(const QCString name) +{ + m_impl->localName=name; } -void DefinitionImpl::setLanguage(SrcLangExt lang) -{ - m_impl->lang=lang; +void DefinitionImpl::setLanguage(SrcLangExt lang) +{ + m_impl->lang=lang; } -void DefinitionImpl::_setSymbolName(const QCString &name) -{ - m_impl->symbolName=name; +void DefinitionImpl::_setSymbolName(const QCString &name) +{ + m_impl->symbolName=name; } QCString DefinitionImpl::_symbolName() const @@ -2181,7 +2164,7 @@ QCString DefinitionImpl::externalReference(const QCString &relPath) const if (dest) { QCString result = *dest; - int l = result.length(); + uint l = result.length(); if (!relPath.isEmpty() && l>0 && result.at(0)=='.') { // relative path -> prepend relPath. result.prepend(relPath); @@ -2194,7 +2177,7 @@ QCString DefinitionImpl::externalReference(const QCString &relPath) const return relPath; } -QCString DefinitionImpl::name() const +const QCString &DefinitionImpl::name() const { return m_impl->name; } @@ -2236,13 +2219,13 @@ void DefinitionImpl::writeSummaryLinks(OutputList &) const //--------------------------------------------------------------------------------- DefinitionAliasImpl::DefinitionAliasImpl(const Definition *scope,const Definition *alias) - : m_scope(scope), m_def(alias), m_cookie(0) + : m_scope(scope), m_def(alias), m_cookie(0) { //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name())); addToMap(alias->name(),this); } -DefinitionAliasImpl::~DefinitionAliasImpl() +DefinitionAliasImpl::~DefinitionAliasImpl() { //printf("~DefinitionAliasImpl()\n"); removeFromMap(this); diff --git a/src/definition.h b/src/definition.h index b3ece2c..8ad15b2 100644 --- a/src/definition.h +++ b/src/definition.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -23,6 +23,7 @@ #include <qdict.h> #include "types.h" +#include "reflist.h" #if defined(_WIN32) && !defined(__CYGWIN__) // To disable 'inherits via dominance' warnings. @@ -32,20 +33,19 @@ class FileDef; class OutputList; -class SectionDict; +class SectionRefs; class MemberSDict; class MemberDef; class GroupDef; class GroupList; -struct ListItemInfo; -struct SectionInfo; +class SectionInfo; class Definition; class FTextStream; - + /** Data associated with a detailed description. */ struct DocInfo { - QCString doc; + QCString doc; int line; QCString file; }; @@ -53,8 +53,8 @@ struct DocInfo /** Data associated with a brief description. */ struct BriefInfo { - QCString doc; - QCString tooltip; + QCString doc; + QCString tooltip; int line; QCString file; }; @@ -62,11 +62,12 @@ struct BriefInfo /** Data associated with description found in the body. */ struct BodyInfo { - int startLine; //!< line number of the start of the definition - int endLine; //!< line number of the end of the definition + int defLine; //!< line number of the start of the definition + int startLine; //!< line number of the start of the definition's body + int endLine; //!< line number of the end of the definition's body FileDef *fileDef; //!< file definition containing the function body }; - + /** Abstract interface for a Definition or DefinitionList */ class DefinitionIntf { @@ -74,23 +75,23 @@ class DefinitionIntf DefinitionIntf() {} virtual ~DefinitionIntf() {} /*! Types of derived classes */ - enum DefType - { - TypeClass = 0, - TypeFile = 1, - TypeNamespace = 2, - TypeMember = 3, - TypeGroup = 4, - TypePackage = 5, - TypePage = 6, - TypeDir = 7, + enum DefType + { + TypeClass = 0, + TypeFile = 1, + TypeNamespace = 2, + TypeMember = 3, + TypeGroup = 4, + TypePackage = 5, + TypePage = 6, + TypeDir = 7, TypeSymbolList = 8 }; /*! Use this for dynamic inspection of the type of the derived class */ virtual DefType definitionType() const = 0; }; -/** The common base class of all entity definitions found in the sources. +/** The common base class of all entity definitions found in the sources. * * This can be a class or a member function, or a file, or a namespace, etc. * Use definitionType() to find which type of definition this is. @@ -110,7 +111,7 @@ class Definition : public DefinitionIntf virtual bool isAlias() const = 0; /*! Returns the name of the definition */ - virtual QCString name() const = 0; + virtual const QCString &name() const = 0; /*! Returns TRUE iff this definition has an artificially generated name * (typically starting with a @) that is used for nameless definitions @@ -160,7 +161,7 @@ class Definition : public DefinitionIntf virtual QCString briefDescription(bool abbreviate=FALSE) const = 0; /*! Returns a plain text version of the brief description suitable for use - * as a tool tip. + * as a tool tip. */ virtual QCString briefDescriptionAsTooltip() const = 0; @@ -173,11 +174,11 @@ class Definition : public DefinitionIntf /*! Returns the file in which the in body documentation was found */ virtual QCString inbodyFile() const = 0; - /*! Returns the line at which the first in body documentation + /*! Returns the line at which the first in body documentation part was found */ virtual int inbodyLine() const = 0; - /*! Returns the file in which the brief description was found. + /*! Returns the file in which the brief description was found. * This can differ from getDefFileName(). */ virtual QCString briefFile() const = 0; @@ -188,14 +189,14 @@ class Definition : public DefinitionIntf /*! returns the extension of the file in which this definition was found */ virtual QCString getDefFileExtension() const = 0; - /*! returns the line number at which the definition was found */ + /*! returns the line number at which the definition was found (can be the declaration) */ virtual int getDefLine() const = 0; /*! returns the column number at which the definition was found */ virtual int getDefColumn() const = 0; - /*! Returns TRUE iff the definition is documented - * (which could be generated documentation) + /*! Returns TRUE iff the definition is documented + * (which could be generated documentation) * @see hasUserDocumentation() */ virtual bool hasDocumentation() const = 0; @@ -204,17 +205,17 @@ class Definition : public DefinitionIntf virtual bool hasUserDocumentation() const = 0; /*! Returns TRUE iff it is possible to link to this item within this - * project. + * project. */ virtual bool isLinkableInProject() const = 0; /*! Returns TRUE iff it is possible to link to this item. This can - * be a link to another project imported via a tag file. + * be a link to another project imported via a tag file. */ virtual bool isLinkable() const = 0; - /*! Returns TRUE iff the name is part of this project and - * may appear in the output + /*! Returns TRUE iff the name is part of this project and + * may appear in the output */ virtual bool isVisibleInProject() const = 0; @@ -224,14 +225,14 @@ class Definition : public DefinitionIntf /*! Returns TRUE iff this item is supposed to be hidden from the output. */ virtual bool isHidden() const = 0; - /*! returns TRUE if this entity was artificially introduced, for - * instance because it is used to show a template instantiation relation. + /*! returns TRUE if this entity was artificially introduced, for + * instance because it is used to show a template instantiation relation. */ virtual bool isArtificial() const = 0; /*! If this definition was imported via a tag file, this function * returns the tagfile for the external project. This can be - * translated into an external link target via + * translated into an external link target via * Doxygen::tagDestinationDict */ virtual QCString getReference() const = 0; @@ -242,12 +243,15 @@ class Definition : public DefinitionIntf /*! Convenience method to return a resolved external link */ virtual QCString externalReference(const QCString &relPath) const = 0; - /*! Returns the first line of the body of this item (applicable to classes and + /*! Returns the first line of the implementation of this item. See also getDefLine() */ + virtual int getStartDefLine() const = 0; + + /*! Returns the first line of the body of this item (applicable to classes and * functions). */ virtual int getStartBodyLine() const = 0; - /*! Returns the last line of the body of this item (applicable to classes and + /*! Returns the last line of the body of this item (applicable to classes and * functions). */ virtual int getEndBodyLine() const = 0; @@ -263,7 +267,7 @@ class Definition : public DefinitionIntf virtual GroupList *partOfGroups() const = 0; virtual bool isLinkableViaGroup() const = 0; - virtual const std::vector<ListItemInfo> &xrefListItems() const = 0; + virtual const RefItemVector &xrefListItems() const = 0; virtual Definition *findInnerCompound(const char *name) const = 0; virtual Definition *getOuterScope() const = 0; @@ -280,7 +284,7 @@ class Definition : public DefinitionIntf virtual QCString id() const = 0; /** returns the section dictionary, only of importance for pagedef */ - virtual SectionDict * getSectionDict() const = 0; + virtual const SectionRefs &getSectionRefs() const = 0; virtual QCString navigationPathAsString() const = 0; virtual QCString pathFragment() const = 0; @@ -316,10 +320,10 @@ class Definition : public DefinitionIntf virtual void setReference(const char *r) = 0; // source references - virtual void setBodySegment(int bls,int ble) = 0; + virtual void setBodySegment(int defLine, int bls,int ble) = 0; virtual void setBodyDef(FileDef *fd) = 0; - virtual void setRefItems(const std::vector<ListItemInfo> &sli) = 0; + virtual void setRefItems(const RefItemVector &sli) = 0; virtual void setOuterScope(Definition *d) = 0; virtual void setHidden(bool b) = 0; @@ -334,7 +338,7 @@ class Definition : public DefinitionIntf virtual void makePartOfGroup(GroupDef *gd) = 0; - /*! Add the list of anchors that mark the sections that are found in the + /*! Add the list of anchors that mark the sections that are found in the * documentation. */ virtual void addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList) = 0; @@ -393,11 +397,11 @@ class DefinitionListIterator : public QListIterator<Definition> }; /** Reads a fragment from file \a fileName starting with line \a startLine - * and ending with line \a endLine. The result is returned as a string - * via \a result. The function returns TRUE if successful and FALSE + * and ending with line \a endLine. The result is returned as a string + * via \a result. The function returns TRUE if successful and FALSE * in case of an error. */ -bool readCodeFragment(const char *fileName, +bool readCodeFragment(const char *fileName, int &startLine,int &endLine, QCString &result); #endif diff --git a/src/definitionimpl.h b/src/definitionimpl.h index 2d8886d..e91d989 100644 --- a/src/definitionimpl.h +++ b/src/definitionimpl.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2019 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -31,7 +31,7 @@ class DefinitionImpl : virtual public Definition virtual ~DefinitionImpl(); virtual bool isAlias() const { return FALSE; } - virtual QCString name() const; + virtual const QCString &name() const; virtual bool isAnonymous() const; virtual QCString localName() const; virtual QCString qualifiedName() const; @@ -61,13 +61,14 @@ class DefinitionImpl : virtual public Definition virtual QCString getReference() const; virtual bool isReference() const; virtual QCString externalReference(const QCString &relPath) const; + virtual int getStartDefLine() const; virtual int getStartBodyLine() const; virtual int getEndBodyLine() const; virtual FileDef *getBodyDef() const; virtual SrcLangExt getLanguage() const; virtual GroupList *partOfGroups() const; virtual bool isLinkableViaGroup() const; - virtual const std::vector<ListItemInfo> &xrefListItems() const; + virtual const RefItemVector &xrefListItems() const; virtual Definition *findInnerCompound(const char *name) const; virtual Definition *getOuterScope() const; virtual MemberSDict *getReferencesMembers() const; @@ -76,7 +77,7 @@ class DefinitionImpl : virtual public Definition virtual bool hasSources() const; virtual bool hasBriefDescription() const; virtual QCString id() const; - virtual SectionDict * getSectionDict() const; + virtual const SectionRefs &getSectionRefs() const; virtual void setName(const char *name); virtual void setId(const char *name); virtual void setDefFile(const QCString& df,int defLine,int defColumn); @@ -85,11 +86,11 @@ class DefinitionImpl : virtual public Definition virtual void setInbodyDocumentation(const char *d,const char *docFile,int docLine); virtual void setReference(const char *r); virtual void addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList); - virtual void setBodySegment(int bls,int ble); + virtual void setBodySegment(int defLine,int bls,int ble); virtual void setBodyDef(FileDef *fd); virtual void addSourceReferencedBy(const MemberDef *d); virtual void addSourceReferences(const MemberDef *d); - virtual void setRefItems(const std::vector<ListItemInfo> &sli); + virtual void setRefItems(const RefItemVector &sli); virtual void mergeRefItems(Definition *d); virtual void addInnerCompound(const Definition *d); virtual void setOuterScope(Definition *d); @@ -117,7 +118,7 @@ class DefinitionImpl : virtual public Definition DefinitionImpl(const DefinitionImpl &d); - private: + private: virtual void _setSymbolName(const QCString &name); virtual QCString _symbolName() const ; @@ -141,7 +142,7 @@ class DefinitionAliasImpl : virtual public Definition virtual ~DefinitionAliasImpl(); virtual bool isAlias() const { return TRUE; } - virtual QCString name() const + virtual const QCString &name() const { return m_def->name(); } virtual bool isAnonymous() const { return m_def->isAnonymous(); } @@ -201,6 +202,8 @@ class DefinitionAliasImpl : virtual public Definition { return m_def->isReference(); } virtual QCString externalReference(const QCString &relPath) const { return m_def->externalReference(relPath); } + virtual int getStartDefLine() const + { return m_def->getStartDefLine(); } virtual int getStartBodyLine() const { return m_def->getStartBodyLine(); } virtual int getEndBodyLine() const @@ -213,7 +216,7 @@ class DefinitionAliasImpl : virtual public Definition { return m_def->partOfGroups(); } virtual bool isLinkableViaGroup() const { return m_def->isLinkableViaGroup(); } - virtual const std::vector<ListItemInfo> &xrefListItems() const + virtual const RefItemVector &xrefListItems() const { return m_def->xrefListItems(); } virtual Definition *findInnerCompound(const char *name) const { return m_def->findInnerCompound(name); } @@ -231,43 +234,43 @@ class DefinitionAliasImpl : virtual public Definition { return m_def->hasBriefDescription(); } virtual QCString id() const { return m_def->id(); } - virtual SectionDict * getSectionDict() const - { return m_def->getSectionDict(); } - virtual QCString navigationPathAsString() const + virtual const SectionRefs &getSectionRefs() const + { return m_def->getSectionRefs(); } + virtual QCString navigationPathAsString() const { return m_def->navigationPathAsString(); } - virtual QCString pathFragment() const + virtual QCString pathFragment() const { return m_def->pathFragment(); } - virtual void setName(const char *name) { } - virtual void setId(const char *name) { } - virtual void setDefFile(const QCString& df,int defLine,int defColumn) {} - virtual void setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace=TRUE) {} - virtual void setBriefDescription(const char *b,const char *briefFile,int briefLine) {} - virtual void setInbodyDocumentation(const char *d,const char *docFile,int docLine) {} - virtual void setReference(const char *r) {} - virtual void addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList) {} - virtual void setBodySegment(int bls,int ble) {} - virtual void setBodyDef(FileDef *fd) {} - virtual void addSourceReferencedBy(const MemberDef *d) {} - virtual void addSourceReferences(const MemberDef *d) {} - virtual void setRefItems(const std::vector<ListItemInfo> &sli) {} - virtual void mergeRefItems(Definition *d) {} - virtual void addInnerCompound(const Definition *d) {} - virtual void setOuterScope(Definition *d) {} - virtual void setHidden(bool b) {} - virtual void setArtificial(bool b) {} - virtual void setLanguage(SrcLangExt lang) {} - virtual void writeSourceDef(OutputList &ol,const char *scopeName) const {} - virtual void writeInlineCode(OutputList &ol,const char *scopeName) const {} - virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const {} - virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const {} - virtual void makePartOfGroup(GroupDef *gd) {} - virtual void writeNavigationPath(OutputList &ol) const {} + virtual void setName(const char *) { } + virtual void setId(const char *) { } + virtual void setDefFile(const QCString&,int,int) {} + virtual void setDocumentation(const char *,const char *,int,bool=TRUE) {} + virtual void setBriefDescription(const char *,const char *,int) {} + virtual void setInbodyDocumentation(const char *,const char *,int) {} + virtual void setReference(const char *) {} + virtual void addSectionsToDefinition(const std::vector<const SectionInfo*> &) {} + virtual void setBodySegment(int,int,int) {} + virtual void setBodyDef(FileDef *) {} + virtual void addSourceReferencedBy(const MemberDef *) {} + virtual void addSourceReferences(const MemberDef *) {} + virtual void setRefItems(const RefItemVector &) {} + virtual void mergeRefItems(Definition *) {} + virtual void addInnerCompound(const Definition *) {} + virtual void setOuterScope(Definition *) {} + virtual void setHidden(bool) {} + virtual void setArtificial(bool) {} + virtual void setLanguage(SrcLangExt) {} + virtual void writeSourceDef(OutputList &,const char *) const {} + virtual void writeInlineCode(OutputList &,const char *) const {} + virtual void writeSourceRefs(OutputList &,const char *) const {} + virtual void writeSourceReffedBy(OutputList &,const char *) const {} + virtual void makePartOfGroup(GroupDef *) {} + virtual void writeNavigationPath(OutputList &) const {} virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const {} virtual void writeSummaryLinks(OutputList &) const {} virtual void writeDocAnchorsToTagFile(FTextStream &) const {} - virtual void setLocalName(const QCString name) {} + virtual void setLocalName(const QCString) {} virtual void addSectionsToIndex() {} - virtual void writeToc(OutputList &ol, const LocalToc <) const {} + virtual void writeToc(OutputList &, const LocalToc &) const {} virtual void setCookie(Cookie *cookie) const { delete m_cookie; m_cookie = cookie; } virtual Cookie *cookie() const { return m_cookie; } protected: diff --git a/src/diagram.cpp b/src/diagram.cpp index 18817e9..d0b7a08 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -42,20 +42,20 @@ class DiagramItemList; class DiagramItem { public: - DiagramItem(DiagramItem *p,int number,const ClassDef *cd, + DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, Protection prot,Specifier virt,const char *ts); ~DiagramItem(); QCString label() const; QCString fileName() const; DiagramItem *parentItem() { return parent; } DiagramItemList *getChildren() { return children; } - void move(int dx,int dy) { x+=dx; y+=dy; } - int xPos() const { return x; } - int yPos() const { return y; } - int avgChildPos() const; - int numChildren() const; + void move(int dx,int dy) { x+=(uint)dx; y+=(uint)dy; } + uint xPos() const { return x; } + uint yPos() const { return y; } + uint avgChildPos() const; + uint numChildren() const; void addChild(DiagramItem *di); - int number() const { return num; } + uint number() const { return num; } Protection protection() const { return prot; } Specifier virtualness() const { return virt; } void putInList() { inList=TRUE; } @@ -64,8 +64,8 @@ class DiagramItem private: DiagramItemList *children; DiagramItem *parent; - int x,y; - int num; + uint x,y; + uint num; Protection prot; Specifier virt; QCString templSpec; @@ -85,8 +85,8 @@ class DiagramItemList : public QList<DiagramItem> class DiagramRow : public QList<DiagramItem> { public: - DiagramRow(TreeDiagram *d,int l) : QList<DiagramItem>() - { + DiagramRow(TreeDiagram *d,uint l) : QList<DiagramItem>() + { diagram=d; level=l; setAutoDelete(TRUE); @@ -129,7 +129,7 @@ class TreeDiagram : public QList<DiagramRow> uint baseRows,uint superRows, uint cellWidth,uint cellheight); private: - bool layoutTree(DiagramItem *root,int row); + bool layoutTree(DiagramItem *root,uint row); TreeDiagram &operator=(const TreeDiagram &); TreeDiagram(const TreeDiagram &); }; @@ -139,8 +139,8 @@ class TreeDiagram : public QList<DiagramRow> //----------------------------------------------------------------------------- const uint maxTreeWidth = 8; -const int gridWidth = 100; -const int gridHeight = 100; +const uint gridWidth = 100; +const uint gridHeight = 100; const uint labelHorSpacing = 10; // horizontal distance between labels const uint labelVertSpacing = 32; // vertical distance between labels @@ -171,7 +171,7 @@ static uint protToMask(Protection p) return 0; } -static uint protToColor(Protection p) +static uchar protToColor(Protection p) { switch(p) { @@ -225,21 +225,23 @@ static Protection getMinProtectionLevel(DiagramItemList *dil) } static void writeBitmapBox(DiagramItem *di,Image *image, - int x,int y,int w,int h,bool firstRow, + uint x,uint y,uint w,uint h,bool firstRow, bool hasDocs,bool children=FALSE) { - int colFill = hasDocs ? (firstRow ? 0 : 2) : 7; - int colBorder = (firstRow || !hasDocs) ? 1 : 3; - int l = Image::stringLength(di->label()); + uchar colFill = hasDocs ? (firstRow ? 0 : 2) : 7; + uchar colBorder = (firstRow || !hasDocs) ? 1 : 3; + uint l = Image::stringLength(di->label()); uint mask=virtToMask(di->virtualness()); image->fillRect(x+1,y+1,w-2,h-2,colFill,mask); image->drawRect(x,y,w,h,colBorder,mask); image->writeString(x+(w-l)/2, y+(h-fontHeight)/2, di->label(),1); if (children) { - int i; + uint i; for (i=0;i<5;i++) + { image->drawHorzLine(y+h+i-6,x+w-2-i,x+w-2,firstRow?1:3,0xffffffff); + } } } @@ -253,7 +255,7 @@ static void writeVectorBox(FTextStream &t,DiagramItem *di, } static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, - int x,int y,int w,int h) + uint x,uint y,uint w,uint h) { if (cd->isLinkable()) { @@ -261,7 +263,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, t << "<area "; if (!ref.isEmpty()) { - t << externalLinkTarget(); + t << externalLinkTarget(true); } t << "href=\""; t << externalRef(relPath,ref,TRUE); @@ -283,12 +285,11 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, } //----------------------------------------------------------------------------- -DiagramItem::DiagramItem(DiagramItem *p,int number,const ClassDef *cd, +DiagramItem::DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, Protection pr,Specifier vi,const char *ts) -{ - parent=p; - x=y=0; - //name=n; +{ + parent=p; + x=y=0; num=number; children = new DiagramItemList; prot=pr; @@ -297,9 +298,9 @@ DiagramItem::DiagramItem(DiagramItem *p,int number,const ClassDef *cd, classDef=cd; templSpec=ts; } - + DiagramItem::~DiagramItem() -{ +{ delete children; } @@ -330,10 +331,10 @@ QCString DiagramItem::fileName() const return classDef->getOutputFileBase(); } -int DiagramItem::avgChildPos() const +uint DiagramItem::avgChildPos() const { DiagramItem *di; - int c=children->count(); + uint c=children->count(); if (c==0) // no children -> don't move return xPos(); if ((di=children->getFirst())->isInList()) // children should be in a list @@ -344,7 +345,7 @@ int DiagramItem::avgChildPos() const return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2; } -int DiagramItem::numChildren() const +uint DiagramItem::numChildren() const { return children->count(); } @@ -363,7 +364,7 @@ void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases cd,prot,virt,ts); //cd->visited=TRUE; if (parent) parent->addChild(di); - di->move(count()*gridWidth,level*gridHeight); + di->move((int)(count()*gridWidth),(int)(level*gridHeight)); append(di); BaseClassList *bcl=doBases ? cd->baseClasses() : cd->subClasses(); int count=0; @@ -431,7 +432,7 @@ void TreeDiagram::moveChildren(DiagramItem *root,int dx) } } -bool TreeDiagram::layoutTree(DiagramItem *root,int r) +bool TreeDiagram::layoutTree(DiagramItem *root,uint r) { bool moved=FALSE; //printf("layoutTree(%s,%d)\n",root->label().data(),r); @@ -440,15 +441,15 @@ bool TreeDiagram::layoutTree(DiagramItem *root,int r) if (dil->count()>0) { uint k; - int pPos=root->xPos(); - int cPos=root->avgChildPos(); + uint pPos=root->xPos(); + uint cPos=root->avgChildPos(); if (pPos>cPos) // move children { DiagramRow *row=at(r+1); //printf("Moving children %d-%d in row %d\n", // dil->getFirst()->number(),row->count()-1,r+1); for (k=dil->getFirst()->number();k<row->count();k++) - row->at(k)->move(pPos-cPos,0); + row->at(k)->move((int)(pPos-cPos),0); moved=TRUE; } else if (pPos<cPos) // move parent @@ -457,7 +458,7 @@ bool TreeDiagram::layoutTree(DiagramItem *root,int r) //printf("Moving parents %d-%d in row %d\n", // root->number(),row->count()-1,r); for (k=root->number();k<row->count();k++) - row->at(k)->move(cPos-pPos,0); + row->at(k)->move((int)(cPos-pPos),0); moved=TRUE; } @@ -525,7 +526,7 @@ void TreeDiagram::computeLayout() uint TreeDiagram::computeRows() { //printf("TreeDiagram::computeRows()=%d\n",count()); - int count=0; + uint count=0; QListIterator<DiagramRow> it(*this); DiagramRow *row; for (;(row=it.current()) && !row->getFirst()->isInList();++it) @@ -535,8 +536,8 @@ uint TreeDiagram::computeRows() //printf("count=%d row=%p\n",count,row); if (row) { - int maxListLen=0; - int curListLen=0; + uint maxListLen=0; + uint curListLen=0; DiagramItem *opi=0; QListIterator<DiagramItem> rit(*row); DiagramItem *di; @@ -587,7 +588,7 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, bool firstRow = doBase; for (;(dr=it.current()) && !done;++it) { - int x=0,y=0; + uint x=0,y=0; float xf=0.0f,yf=0.0f; QListIterator<DiagramItem> rit(*dr); DiagramItem *di = rit.current(); @@ -617,7 +618,7 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth; if (doBase) { - y = image->getHeight()- + y = image->height()- superRows*cellHeight- (superRows-1)*labelVertSpacing- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; @@ -669,7 +670,7 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth; if (doBase) { - y = image->getHeight()- + y = image->height()- superRows*cellHeight- (superRows-1)*labelVertSpacing- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; @@ -717,7 +718,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, DiagramItem *di = rit.current(); if (di->isInList()) // row consists of list connectors { - int x=0,y=0,ys=0; + uint x=0,y=0,ys=0; float xf=0.0f,yf=0.0f,ysf=0.0f; for (;(di=rit.current());++rit) { @@ -731,7 +732,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; if (doBase) // base classes { - y = image->getHeight()- + y = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; image->drawVertArrow(x,y,y+labelVertSpacing/2, @@ -759,7 +760,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, else { t << "0 " << (di->xPos()/(float)gridWidth) << " " - << ((float)superRows-0.25-di->yPos()/(float)gridHeight) + << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } } @@ -772,7 +773,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, (cellWidth+labelHorSpacing)/gridWidth+cellWidth/2; if (doBase) // base classes { - ys = image->getHeight()- + ys = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; y = ys - cellHeight/2; @@ -873,7 +874,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, } else { - t << xf << " " << (ysf + 0.25) << " " << yf << " vedge\n"; + t << xf << " " << (ysf + 0.25f) << " " << yf << " vedge\n"; } } } @@ -884,7 +885,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, { for (;(di=rit.current());++rit) { - int x=0,y=0; + uint x=0,y=0; DiagramItemList *dil = di->getChildren(); DiagramItem *parent = di->parentItem(); if (parent) // item has a parent -> connect to it @@ -894,7 +895,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; if (doBase) // base classes { - y = image->getHeight()- + y = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; /* write input line */ @@ -924,7 +925,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, else { t << "0 " << di->xPos()/(float)gridWidth << " " - << ((float)superRows-0.25-di->yPos()/(float)gridHeight) + << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } } @@ -933,13 +934,13 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, { Protection p=getMinProtectionLevel(dil); uint mask=protToMask(p); - uint col=protToColor(p); + uchar col=protToColor(p); if (bitmap) { x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; if (doBase) // base classes { - y = image->getHeight()- + y = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- cellHeight-labelVertSpacing/2- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; @@ -964,7 +965,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, else { t << "1 " << di->xPos()/(float)gridWidth << " " - << ((float)superRows-1.75-di->yPos()/(float)gridHeight) + << ((float)superRows-1.75f-di->yPos()/(float)gridHeight) << " out\n"; } } @@ -975,9 +976,9 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, { if (bitmap) { - int xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth + uint xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; - int xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth + uint xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; if (doBase) // base classes { @@ -1034,17 +1035,17 @@ ClassDiagram::ClassDiagram(const ClassDef *root) super->computeLayout(); DiagramItem *baseItem = base->getFirst()->getFirst(); DiagramItem *superItem = super->getFirst()->getFirst(); - int xbase = baseItem->xPos(); - int xsuper = superItem->xPos(); + uint xbase = baseItem->xPos(); + uint xsuper = superItem->xPos(); if (xbase>xsuper) { - superItem->move(xbase-xsuper,0); - super->moveChildren(superItem,xbase-xsuper); + superItem->move((int)(xbase-xsuper),0); + super->moveChildren(superItem,(int)(xbase-xsuper)); } else if (xbase<xsuper) { - baseItem->move(xsuper-xbase,0); - base->moveChildren(baseItem,xsuper-xbase); + baseItem->move((int)(xsuper-xbase),0); + base->moveChildren(baseItem,(int)(xsuper-xbase)); } } @@ -1116,7 +1117,7 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, t << "%%For: \n"; t << "%Magnification: 1.00\n"; t << "%%Orientation: Portrait\n"; - t << "%%BoundingBox: 0 0 500 " << estHeight*500.0/(float)estWidth << "\n"; + t << "%%BoundingBox: 0 0 500 " << estHeight*500.0f/(float)estWidth << "\n"; t << "%%Pages: 0\n"; t << "%%BeginSetup\n"; t << "%%EndSetup\n"; diff --git a/src/dirdef.cpp b/src/dirdef.cpp index ba792e1..b058f86 100644 --- a/src/dirdef.cpp +++ b/src/dirdef.cpp @@ -14,6 +14,8 @@ #include "config.h" #include "docparser.h" #include "definitionimpl.h" +#include "filedef.h" +#include <algorithm> //---------------------------------------------------------------------- @@ -34,7 +36,7 @@ class DirDefImpl : public DefinitionImpl, public DirDef virtual FileList * getFiles() const { return m_fileList; } virtual void addFile(FileDef *fd); virtual const DirList &subDirs() const { return m_subdirs; } - virtual bool isCluster() const { return m_subdirs.count()>0; } + virtual bool isCluster() const { return m_subdirs.size()>0; } virtual int level() const { return m_level; } virtual DirDef *parent() const { return m_parent; } virtual int dirCount() const { return m_dirCount; } @@ -67,7 +69,7 @@ class DirDefImpl : public DefinitionImpl, public DirDef void endMemberDeclarations(OutputList &ol); static DirDef *createNewDir(const char *path); - static bool matchPath(const QCString &path,QStrList &l); + static bool matchPath(const QCString &path,const StringVector &l); DirList m_subdirs; QCString m_dispName; @@ -103,7 +105,7 @@ DirDefImpl::DirDefImpl(const char *path) : DefinitionImpl(path,1,1,path) m_shortName = m_shortName.left(m_shortName.length()-1); } int pi=m_shortName.findRev('/'); - if (pi!=-1) + if (pi!=-1) { // remove everything till the last / m_shortName = m_shortName.mid(pi+1); } @@ -113,7 +115,7 @@ DirDefImpl::DirDefImpl(const char *path) : DefinitionImpl(path,1,1,path) { // strip trailing / m_dispName = m_dispName.left(m_dispName.length()-1); } - + m_fileList = new FileList; m_usedDirs = new QDict<UsedDir>(257); m_usedDirs->setAutoDelete(TRUE); @@ -128,19 +130,19 @@ DirDefImpl::~DirDefImpl() delete m_usedDirs; } -bool DirDefImpl::isLinkableInProject() const -{ - return !isReference(); +bool DirDefImpl::isLinkableInProject() const +{ + return !isReference(); } -bool DirDefImpl::isLinkable() const -{ - return isReference() || isLinkableInProject(); +bool DirDefImpl::isLinkable() const +{ + return isReference() || isLinkableInProject(); } void DirDefImpl::addSubDir(DirDef *subdir) { - m_subdirs.append(subdir); + m_subdirs.push_back(subdir); subdir->setOuterScope(this); subdir->setParent(this); } @@ -158,7 +160,7 @@ void DirDefImpl::addFile(FileDef *fd) void DirDefImpl::sort() { - m_subdirs.sort(); + std::sort(m_subdirs.begin(), m_subdirs.end(), compareDirDefs); m_fileList->sort(); } @@ -203,7 +205,7 @@ QCString DirDefImpl::getOutputFileBase() const void DirDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) { - if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) || + if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) || !documentation().isEmpty()) { ol.pushGeneratorState(); @@ -221,10 +223,11 @@ void DirDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) // repeat brief description if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // separator between brief and details - if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && + if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && !documentation().isEmpty()) { ol.pushGeneratorState(); @@ -241,7 +244,8 @@ void DirDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) // write documentation if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } } @@ -251,7 +255,8 @@ void DirDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc( - briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE); + briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startParagraph(); @@ -306,9 +311,7 @@ void DirDefImpl::writeDirectoryGraph(OutputList &ol) void DirDefImpl::writeSubDirList(OutputList &ol) { int numSubdirs = 0; - QListIterator<DirDef> it(m_subdirs); - DirDef *dd; - for (it.toFirst();(dd=it.current());++it) + for(const auto dd : m_subdirs) { if (dd->hasDocumentation() || dd->getFiles()->count()>0) { @@ -323,7 +326,7 @@ void DirDefImpl::writeSubDirList(OutputList &ol) ol.parseText(theTranslator->trDir(TRUE,FALSE)); ol.endMemberHeader(); ol.startMemberList(); - for (it.toFirst();(dd=it.current());++it) + for(const auto dd : m_subdirs) { if (dd->hasDocumentation() || dd->getFiles()->count()==0) { @@ -341,7 +344,8 @@ void DirDefImpl::writeSubDirList(OutputList &ol) FALSE, // isExample 0, // exampleName TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); ol.endMemberDescription(); } @@ -373,9 +377,7 @@ void DirDefImpl::writeFileList(OutputList &ol) ol.parseText(theTranslator->trFile(TRUE,FALSE)); ol.endMemberHeader(); ol.startMemberList(); - QListIterator<FileDef> it(*m_fileList); - FileDef *fd; - for (;(fd=it.current());++it) + for (it.toFirst();(fd=it.current());++it) { if (fd->hasDocumentation()) { @@ -414,7 +416,8 @@ void DirDefImpl::writeFileList(OutputList &ol) FALSE, // isExample 0, // exampleName TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); ol.endMemberDescription(); } @@ -461,11 +464,9 @@ void DirDefImpl::writeTagFile(FTextStream &tagFile) { case LayoutDocEntry::DirSubDirs: { - if (m_subdirs.count()>0) + if (m_subdirs.size()>0) { - DirDef *dd; - QListIterator<DirDef> it(m_subdirs); - for (;(dd=it.current());++it) + for(const auto dd : m_subdirs) { tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl; } @@ -497,7 +498,7 @@ void DirDefImpl::writeDocumentation(OutputList &ol) { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); ol.pushGeneratorState(); - + QCString title=theTranslator->trDirReference(m_dispName); startFile(ol,getOutputFileBase(),name(),title,HLI_Files,!generateTreeView); @@ -529,25 +530,25 @@ void DirDefImpl::writeDocumentation(OutputList &ol) { switch (lde->kind()) { - case LayoutDocEntry::BriefDesc: + case LayoutDocEntry::BriefDesc: writeBriefDescription(ol); - break; - case LayoutDocEntry::DirGraph: + break; + case LayoutDocEntry::DirGraph: writeDirectoryGraph(ol); - break; - case LayoutDocEntry::MemberDeclStart: + break; + case LayoutDocEntry::MemberDeclStart: startMemberDeclarations(ol); - break; - case LayoutDocEntry::DirSubDirs: + break; + case LayoutDocEntry::DirSubDirs: writeSubDirList(ol); - break; - case LayoutDocEntry::DirFiles: + break; + case LayoutDocEntry::DirFiles: writeFileList(ol); - break; - case LayoutDocEntry::MemberDeclEnd: + break; + case LayoutDocEntry::MemberDeclEnd: endMemberDeclarations(ol); break; - case LayoutDocEntry::DetailedDesc: + case LayoutDocEntry::DetailedDesc: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeDetailedDescription(ol,ls->title(lang)); @@ -575,16 +576,16 @@ void DirDefImpl::writeDocumentation(OutputList &ol) case LayoutDocEntry::FileConstantGroups: case LayoutDocEntry::FileIncludes: case LayoutDocEntry::FileIncludeGraph: - case LayoutDocEntry::FileIncludedByGraph: + case LayoutDocEntry::FileIncludedByGraph: case LayoutDocEntry::FileSourceLink: case LayoutDocEntry::FileInlineClasses: - case LayoutDocEntry::GroupClasses: - case LayoutDocEntry::GroupInlineClasses: + case LayoutDocEntry::GroupClasses: + case LayoutDocEntry::GroupInlineClasses: case LayoutDocEntry::GroupNamespaces: - case LayoutDocEntry::GroupDirs: - case LayoutDocEntry::GroupNestedGroups: + case LayoutDocEntry::GroupDirs: + case LayoutDocEntry::GroupNestedGroups: case LayoutDocEntry::GroupFiles: - case LayoutDocEntry::GroupGraph: + case LayoutDocEntry::GroupGraph: case LayoutDocEntry::GroupPageDocs: case LayoutDocEntry::AuthorSection: case LayoutDocEntry::MemberGroups: @@ -626,7 +627,7 @@ void DirDefImpl::setLevel() /** Add as "uses" dependency between \a this dir and \a dir, * that was caused by a dependency on file \a fd. - */ + */ void DirDefImpl::addUsesDependency(DirDef *dir,FileDef *srcFd, FileDef *dstFd,bool inherited) { @@ -648,7 +649,7 @@ void DirDefImpl::addUsesDependency(DirDef *dir,FileDef *srcFd, if (usedPair==0) // new file dependency { //printf(" => new file\n"); - usedDir->addFileDep(srcFd,dstFd); + usedDir->addFileDep(srcFd,dstFd); added=TRUE; } else @@ -660,7 +661,7 @@ void DirDefImpl::addUsesDependency(DirDef *dir,FileDef *srcFd, { //printf(" => new file\n"); usedDir = new UsedDir(dir,inherited); - usedDir->addFileDep(srcFd,dstFd); + usedDir->addFileDep(srcFd,dstFd); m_usedDirs->insert(dir->getOutputFileBase(),usedDir); added=TRUE; } @@ -684,7 +685,7 @@ void DirDefImpl::addUsesDependency(DirDef *dir,FileDef *srcFd, void DirDefImpl::computeDependencies() { FileList *fl = m_fileList; - if (fl) + if (fl) { QListIterator<FileDef> fli(*fl); FileDef *fd; @@ -695,7 +696,7 @@ void DirDefImpl::computeDependencies() QList<IncludeInfo> *ifl = fd->includeFileList(); if (ifl) { - QListIterator<IncludeInfo> ifli(*ifl); + QListIterator<IncludeInfo> ifli(*ifl); IncludeInfo *ii; for (ifli.toFirst();(ii=ifli.current());++ifli) // foreach include file { @@ -729,10 +730,10 @@ void DirDefImpl::computeDependencies() bool DirDefImpl::isParentOf(const DirDef *dir) const { - if (dir->parent()==this) // this is a parent of dir + if (dir->parent()==this) // this is a parent of dir return TRUE; else if (dir->parent()) // repeat for the parent of dir - return isParentOf(dir->parent()); + return isParentOf(dir->parent()); else return FALSE; } @@ -754,7 +755,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); @@ -796,17 +797,15 @@ DirDef *DirDefImpl::createNewDir(const char *path) return dir; } -bool DirDefImpl::matchPath(const QCString &path,QStrList &l) +bool DirDefImpl::matchPath(const QCString &path,const StringVector &l) { - const char *s=l.first(); - while (s) + for (const auto &s : l) { - QCString prefix = s; - if (qstricmp(prefix.left(path.length()),path)==0) // case insensitive compare + std::string prefix = s.substr(0,path.length()); + if (qstricmp(prefix.c_str(),path)==0) // case insensitive compare { return TRUE; } - s = l.next(); } return FALSE; } @@ -824,7 +823,7 @@ DirDef *DirDefImpl::mergeDirectoryInTree(const QCString &path) QCString part=path.left(i+1); if (!matchPath(part,Config_getList(STRIP_FROM_PATH)) && (part!="/" && part!="//")) { - dir=createNewDir(part); + dir=createNewDir(part); } p=i+1; } @@ -835,7 +834,7 @@ DirDef *DirDefImpl::mergeDirectoryInTree(const QCString &path) static void writePartialDirPath(OutputList &ol,const DirDef *root,const DirDef *target) { - if (target->parent()!=root) + if (target->parent()!=root) { writePartialDirPath(ol,root,target->parent()); ol.writeString(" / "); @@ -912,7 +911,7 @@ void DirRelation::writeDocumentation(OutputList &ol) ol.writeString("</table>"); ol.endContents(); - + endFileWithNavPath(m_src,ol); ol.popGeneratorState(); @@ -935,10 +934,10 @@ static void computeCommonDirPrefix() sdi.toFirst(); dir=sdi.current(); path=dir->name(); - int i=path.findRev('/',path.length()-2); + int i=path.findRev('/',(int)path.length()-2); path=path.left(i+1); bool done=FALSE; - if (i==-1) + if (i==-1) { path=""; } @@ -946,8 +945,8 @@ static void computeCommonDirPrefix() { while (!done) { - int l = path.length(); - int count=0; + uint l = path.length(); + uint count=0; for (sdi.toFirst();(dir=sdi.current());++sdi) { QCString dirName = dir->name(); @@ -955,7 +954,7 @@ static void computeCommonDirPrefix() { if (qstrncmp(dirName,path,l)!=0) // dirName does not start with path { - int i=path.findRev('/',l-2); + i=path.findRev('/',(int)l-2); if (i==-1) // no unique prefix -> stop { path=""; @@ -972,7 +971,7 @@ static void computeCommonDirPrefix() { path=dir->name(); l=path.length(); - int i=path.findRev('/',l-2); + i=path.findRev('/',(int)l-2); if (i==-1) // no unique prefix -> stop { path=""; @@ -1005,13 +1004,9 @@ static void computeCommonDirPrefix() void buildDirectories() { // for each input file - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { //printf("buildDirectories %s\n",fd->name().data()); if (fd->getReference().isEmpty()) @@ -1021,7 +1016,7 @@ void buildDirectories() { dir = DirDefImpl::mergeDirectoryInTree(fd->getPath()); } - if (dir && !fd->isDocumentationFile()) dir->addFile(fd); + if (dir && !fd->isDocumentationFile()) dir->addFile(fd.get()); } else { @@ -1037,14 +1032,14 @@ void buildDirectories() for (sdi.toFirst();(dir=sdi.current());++sdi) { QCString name = dir->name(); - int i=name.findRev('/',name.length()-2); + int i=name.findRev('/',(int)name.length()-2); if (i>0) { DirDef *parent = Doxygen::directories->find(name.left(i+1)); //if (parent==0) parent=root; - if (parent) + if (parent) { - parent->addSubDir(dir); + parent->addSubDir(dir); //printf("DirDefImpl::addSubdir(): Adding subdir\n%s to\n%s\n", // dir->displayName().data(), parent->displayName().data()); } @@ -1101,3 +1096,8 @@ void generateDirDocs(OutputList &ol) } } +bool compareDirDefs(const DirDef *item1, const DirDef *item2) +{ + return qstricmp(item1->shortName(),item2->shortName()) < 0; +} + diff --git a/src/dirdef.h b/src/dirdef.h index 2ea54af..468901d 100644 --- a/src/dirdef.h +++ b/src/dirdef.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -21,7 +19,9 @@ #include "sortdict.h" #include "definition.h" -#include <qlist.h> +#include <vector> +#include <qglobal.h> +#include <qcstring.h> class FileList; class ClassSDict; @@ -34,11 +34,9 @@ class FTextStream; class DirDef; /** A list of directories. */ -class DirList : public QList<DirDef> -{ - public: - int compareValues(const DirDef *item1,const DirDef *item2) const; -}; +typedef std::vector<DirDef*> DirList; + +bool compareDirDefs(const DirDef *item1, const DirDef *item2); /** A model of a directory symbol. */ class DirDef : virtual public Definition @@ -82,7 +80,7 @@ class DirDef : virtual public Definition }; /** Class representing a pair of FileDef objects */ -class FilePair +class FilePair { public: FilePair(FileDef *src,FileDef *dst) : m_src(src), m_dst(dst) {} @@ -97,7 +95,7 @@ class FilePair class FilePairDict : public SDict<FilePair> { public: - FilePairDict(int size) : SDict<FilePair>(size) {} + FilePairDict(uint size) : SDict<FilePair>(size) {} private: int compareValues(const FilePair *item1,const FilePair *item2) const; }; @@ -106,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); @@ -116,7 +114,7 @@ class UsedDir void sort(); private: - DirDef *m_dir; + const DirDef *m_dir; FilePairDict m_filePairs; bool m_inherited; }; @@ -125,7 +123,7 @@ class UsedDir class DirRelation { public: - DirRelation(const QCString &name,const DirDef *src,UsedDir *dst) + DirRelation(const QCString &name,const DirDef *src,UsedDir *dst) : m_name(name), m_src(src), m_dst(dst) {} const DirDef *source() const { return m_src; } UsedDir *destination() const { return m_dst; } @@ -138,16 +136,11 @@ class DirRelation UsedDir *m_dst; }; -inline int DirList::compareValues(const DirDef *item1,const DirDef *item2) const -{ - return qstricmp(item1->shortName(),item2->shortName()); -} - /** A sorted dictionary of DirDef objects. */ class DirSDict : public SDict<DirDef> { public: - DirSDict(int size) : SDict<DirDef>(size) {} + DirSDict(uint size) : SDict<DirDef>(size) {} int compareValues(const DirDef *item1,const DirDef *item2) const { return qstricmp(item1->shortName(),item2->shortName()); diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index fff9728..e5c9a6b 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -132,15 +132,13 @@ void writeDocbookLink(FTextStream &t,const char * /*extRef*/,const char *compoun t << "</link>"; } -DocbookCodeGenerator::DocbookCodeGenerator(FTextStream &t) : m_lineNumber(-1), m_col(0), - m_insideCodeLine(FALSE), m_insideSpecialHL(FALSE) +DocbookCodeGenerator::DocbookCodeGenerator(FTextStream &t) { m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING); setTextStream(t); } -DocbookCodeGenerator::DocbookCodeGenerator() : m_lineNumber(-1), m_col(0), - m_insideCodeLine(FALSE), m_insideSpecialHL(FALSE), m_streamSet(FALSE) +DocbookCodeGenerator::DocbookCodeGenerator() { m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING); } @@ -160,9 +158,9 @@ void DocbookCodeGenerator::writeCodeLink(const char *ref,const char *file, writeDocbookLink(m_t,ref,file,anchor,name,tooltip); m_col+=(int)strlen(name); } -void DocbookCodeGenerator::writeCodeLinkLine(const char *ref,const char *file, - const char *anchor,const char *name, - const char *tooltip) +void DocbookCodeGenerator::writeCodeLinkLine(const char *,const char *file, + const char *,const char *name, + const char *) { Docbook_DB(("(writeCodeLinkLine)\n")); m_t << "<anchor xml:id=\"_" << stripExtensionGeneral(stripPath(file),".xml"); @@ -274,8 +272,8 @@ DB_GEN_C m_descTable = FALSE; m_inLevel = -1; m_firstMember = FALSE; - for (int i = 0 ; i < sizeof(m_inListItem) / sizeof(*m_inListItem) ; i++) m_inListItem[i] = FALSE; - for (int i = 0 ; i < sizeof(m_inSimpleSect) / sizeof(*m_inSimpleSect) ; i++) m_inSimpleSect[i] = FALSE; + for (size_t i = 0 ; i < sizeof(m_inListItem) / sizeof(*m_inListItem) ; i++) m_inListItem[i] = FALSE; + for (size_t i = 0 ; i < sizeof(m_inSimpleSect) / sizeof(*m_inSimpleSect) ; i++) m_inSimpleSect[i] = FALSE; } DocbookGenerator::~DocbookGenerator() @@ -322,6 +320,7 @@ DB_GEN_C t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; t << "<" << fileType << " xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""; if (!pageName.isEmpty()) t << " xml:id=\"_" << stripPath(pageName) << "\""; + t << " xml:lang=\"" << theTranslator->trISOLang() << "\""; t << ">" << endl; } @@ -574,13 +573,9 @@ DB_GEN_C2("IndexSections " << is) { t << "</title>" << endl; bool isFirst=TRUE; - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - const FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->isLinkableInProject()) { @@ -655,7 +650,8 @@ DB_GEN_C } } } -void DocbookGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) + +void DocbookGenerator::writeDoc(DocNode *n,const Definition *,const MemberDef *) { DB_GEN_C DocbookDocVisitor *visitor = @@ -680,7 +676,7 @@ void DocbookGenerator::writeString(const char *text) DB_GEN_C t << text; } -void DocbookGenerator::startMemberHeader(const char *name,int) +void DocbookGenerator::startMemberHeader(const char *,int) { DB_GEN_C t << "<simplesect>" << endl; @@ -698,7 +694,7 @@ void DocbookGenerator::docify(const char *str) DB_GEN_C t << convertToDocBook(str); } -void DocbookGenerator::writeObjectLink(const char *ref, const char *f, +void DocbookGenerator::writeObjectLink(const char *, const char *f, const char *anchor, const char *text) { DB_GEN_C @@ -813,7 +809,7 @@ DB_GEN_C t << "<programlisting>"; } } -void DocbookGenerator::endTextBlock(bool dense) +void DocbookGenerator::endTextBlock(bool) { DB_GEN_C if (m_denseText) @@ -822,8 +818,8 @@ DB_GEN_C t << "</programlisting>"; } } -void DocbookGenerator::startMemberDoc(const char *clname, const char *memname, const char *anchor, const char *title, - int memCount, int memTotal, bool showInline) +void DocbookGenerator::startMemberDoc(const char *clname, const char *memname, const char *, const char *title, + int memCount, int memTotal, bool) { DB_GEN_C2("m_inLevel " << m_inLevel) t << " <section>" << endl; @@ -849,15 +845,15 @@ void DocbookGenerator::startTitleHead(const char *) DB_GEN_C t << "<title>"; } -void DocbookGenerator::endTitleHead(const char *fileName,const char *name) +void DocbookGenerator::endTitleHead(const char *,const char *name) { DB_GEN_C t << "</title>" << endl; if (name) addIndexTerm(t, name); } -void DocbookGenerator::startDoxyAnchor(const char *fName,const char *manName, - const char *anchor,const char *name, - const char *args) +void DocbookGenerator::startDoxyAnchor(const char *fName,const char *, + const char *anchor,const char *, + const char *) { DB_GEN_C if (!m_inListItem[m_levelListItem] && !m_descTable) @@ -870,7 +866,7 @@ DB_GEN_C t << "<anchor xml:id=\"_" << stripPath(fName) << "_1" << anchor << "\"/>"; } } -void DocbookGenerator::endDoxyAnchor(const char *fileName,const char *anchor) +void DocbookGenerator::endDoxyAnchor(const char *,const char *) { DB_GEN_C } @@ -883,7 +879,7 @@ void DocbookGenerator::endMemberDocName() { DB_GEN_C } -void DocbookGenerator::startMemberGroupHeader(bool hasHeader) +void DocbookGenerator::startMemberGroupHeader(bool) { DB_GEN_C t << "<simplesect><title>"; @@ -914,7 +910,7 @@ DB_GEN_C t << " <informalfigure>" << endl; t << " <mediaobject>" << endl; t << " <imageobject>" << endl; - t << " <imagedata width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" + t << " <imagedata width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << fileName << ".png\">" << "</imagedata>" << endl; t << " </imageobject>" << endl; d.writeImage(t,m_dir,relPath,fileName,FALSE); @@ -1025,13 +1021,13 @@ DB_GEN_C t << "</para>"; t << "<para>"; } -void DocbookGenerator::startSection(const char *lab,const char *,SectionInfo::SectionType type) +void DocbookGenerator::startSection(const char *lab,const char *,SectionType) { DB_GEN_C t << " <section xml:id=\"_" << stripPath(lab) << "\">"; t << "<title>"; } -void DocbookGenerator::endSection(const char *lab,SectionInfo::SectionType) +void DocbookGenerator::endSection(const char *,SectionType) { DB_GEN_C t << "</title>"; diff --git a/src/docbookgen.h b/src/docbookgen.h index 64e9e67..bed2f5f 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -57,16 +57,16 @@ class DocbookCodeGenerator : public CodeOutputInterface private: FTextStream m_t; - bool m_streamSet; + bool m_streamSet = FALSE; QCString m_refId; QCString m_external; - int m_lineNumber; - int m_col; - bool m_insideCodeLine; - bool m_insideSpecialHL; + int m_lineNumber = -1; + int m_col = 0; + bool m_insideCodeLine = FALSE; + bool m_insideSpecialHL = FALSE; QCString m_relPath; QCString m_sourceFileName; - bool m_prettyCode; + bool m_prettyCode = FALSE; }; @@ -145,14 +145,14 @@ class DocbookGenerator : public OutputGenerator void startFile(const char *name,const char *manName, const char *title); void writeSearchInfo(){DB_GEN_EMPTY}; - void writeFooter(const char *navPath){DB_GEN_NEW}; + void writeFooter(const char *){DB_GEN_NEW}; void endFile(); void startIndexSection(IndexSections); void endIndexSection(IndexSections); void writePageLink(const char *,bool); void startProjectNumber(){DB_GEN_NEW}; void endProjectNumber(){DB_GEN_NEW}; - void writeStyleInfo(int part){DB_GEN_EMPTY}; + void writeStyleInfo(int){DB_GEN_EMPTY}; void startTitleHead(const char *); void endTitleHead(const char *fileName,const char *name); void startIndexListItem(){DB_GEN_NEW}; @@ -166,8 +166,8 @@ class DocbookGenerator : public OutputGenerator void startItemList() {DB_GEN_EMPTY}; void endItemList() {DB_GEN_EMPTY}; - void startIndexItem(const char *ref,const char *file){DB_GEN_NEW}; - void endIndexItem(const char *ref,const char *file){DB_GEN_NEW}; + void startIndexItem(const char *,const char *){DB_GEN_NEW}; + void endIndexItem(const char *,const char *){DB_GEN_NEW}; void startItemListItem() {DB_GEN_EMPTY}; void endItemListItem() {DB_GEN_EMPTY}; void docify(const char *text); @@ -204,8 +204,8 @@ class DocbookGenerator : public OutputGenerator void startTitle(void){DB_GEN_NEW}; void endTitle(void){DB_GEN_NEW}; void writeAnchor(const char *,const char *){DB_GEN_EMPTY}; - void startSection(const char *,const char *,SectionInfo::SectionType); - void endSection(const char *,SectionInfo::SectionType); + void startSection(const char *,const char *,SectionType); + void endSection(const char *,SectionType); void lineBreak(const char *); void addIndexItem(const char *,const char *); void writeNonBreakableSpace(int); @@ -258,23 +258,23 @@ class DocbookGenerator : public OutputGenerator void insertMemberAlign(bool){DB_GEN_EMPTY}; void insertMemberAlignLeft(int,bool){DB_GEN_EMPTY}; void startMemberDoc(const char *,const char *, - const char *,const char *,int,int,bool); + const char *,const char *,int,int,bool); void endMemberDoc(bool); void startDoxyAnchor(const char *fName,const char *manName, - const char *anchor,const char *name, - const char *args); + const char *anchor,const char *name, + const char *args); void endDoxyAnchor(const char *fileName,const char *anchor); void writeLatexSpacing(){DB_GEN_EMPTY} - void writeStartAnnoItem(const char *type,const char *file, - const char *path,const char *name){DB_GEN_NEW}; - void writeEndAnnoItem(const char *name){DB_GEN_NEW}; - void startMemberDescription(const char *anchor,const char *inheritId, bool typ){DB_GEN_EMPTY}; + void writeStartAnnoItem(const char *,const char *, + const char *,const char *){DB_GEN_NEW}; + void writeEndAnnoItem(const char *){DB_GEN_NEW}; + void startMemberDescription(const char *,const char *,bool){DB_GEN_EMPTY}; void endMemberDescription(){DB_GEN_EMPTY}; void startMemberDeclaration(){DB_GEN_EMPTY}; - void endMemberDeclaration(const char *anchor,const char *inheritId){DB_GEN_EMPTY}; - void writeInheritedSectionTitle(const char *id,const char *ref, - const char *file,const char *anchor, - const char *title,const char *name){DB_GEN_NEW}; + void endMemberDeclaration(const char *,const char *){DB_GEN_EMPTY}; + void writeInheritedSectionTitle(const char *,const char *, + const char *,const char *, + const char *,const char *){DB_GEN_NEW}; void startIndent(){DB_GEN_EMPTY}; void endIndent(){DB_GEN_EMPTY}; void writeSynopsis(){DB_GEN_EMPTY}; @@ -290,17 +290,17 @@ class DocbookGenerator : public OutputGenerator void endCallGraph(DotCallGraph &g); void startDirDepGraph(); void endDirDepGraph(DotDirDeps &g); - void writeGraphicalHierarchy(DotGfxHierarchyTable &g){DB_GEN_NEW}; + void writeGraphicalHierarchy(DotGfxHierarchyTable &){DB_GEN_NEW}; void startQuickIndices(){DB_GEN_EMPTY}; void endQuickIndices(){DB_GEN_EMPTY}; void writeSplitBar(const char *){DB_GEN_EMPTY}; void writeNavigationPath(const char *){DB_GEN_NEW}; void writeLogo(){DB_GEN_NEW}; - void writeQuickLinks(bool compact,HighlightedItem hli,const char *file){DB_GEN_EMPTY}; - void writeSummaryLink(const char *file,const char *anchor,const char *title,bool first){DB_GEN_EMPTY}; + void writeQuickLinks(bool,HighlightedItem,const char *){DB_GEN_EMPTY}; + void writeSummaryLink(const char *,const char *,const char *,bool){DB_GEN_EMPTY}; void startContents(){DB_GEN_EMPTY}; void endContents(){DB_GEN_EMPTY}; - void startPageDoc(const char *pageTitle){DB_GEN_EMPTY} + void startPageDoc(const char *){DB_GEN_EMPTY} void endPageDoc() {DB_GEN_EMPTY} void startTextBlock(bool); void endTextBlock(bool); @@ -309,7 +309,7 @@ class DocbookGenerator : public OutputGenerator void endMemberDocPrefixItem(); void startMemberDocName(bool); void endMemberDocName(); - void startParameterType(bool,const char *key){DB_GEN_EMPTY}; + void startParameterType(bool,const char *){DB_GEN_EMPTY}; void endParameterType(){DB_GEN_EMPTY}; void startParameterName(bool); void endParameterName(bool,bool,bool); diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 9de0a16..78af6e0 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -1,9 +1,6 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby @@ -16,6 +13,7 @@ * */ + #include <qfileinfo.h> #include "docbookvisitor.h" @@ -55,7 +53,7 @@ static QCString filterId(const char *s) static GrowBuf growBuf; growBuf.clear(); if (s==0) return ""; - const unsigned char *p=(const unsigned char *)s; + const char *p=s; char c; while ((c=*p++)) { @@ -69,6 +67,23 @@ static QCString filterId(const char *s) return growBuf.get(); } +static bool supportedHtmlAttribute(const QCString &name) +{ + return (name=="align" || + name=="bgcolor" || + name=="border" || + name=="cellpadding" || + name=="cellspacing" || + name=="class" || + name=="frame" || + name=="label" || + name=="style" || + name=="width" || + name=="tabstyle" || + name=="title"); +} + + void DocbookDocVisitor::visitCaption(const QList<DocNode> &children) { QListIterator<DocNode> cli(children); @@ -138,7 +153,7 @@ void DocbookDocVisitor::visitPostEnd(FTextStream &t, bool hasCaption, bool inlin } DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci) - : DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) + : DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci) { DB_VIS_C // m_t << "<section>" << endl; @@ -311,17 +326,17 @@ DB_VIS_C filter(s->text()); m_t << "</computeroutput></literallayout>"; break; - case DocVerbatim::HtmlOnly: + case DocVerbatim::HtmlOnly: break; - case DocVerbatim::RtfOnly: + case DocVerbatim::RtfOnly: break; - case DocVerbatim::ManOnly: + case DocVerbatim::ManOnly: break; - case DocVerbatim::LatexOnly: + case DocVerbatim::LatexOnly: break; - case DocVerbatim::XmlOnly: + case DocVerbatim::XmlOnly: break; - case DocVerbatim::DocbookOnly: + case DocVerbatim::DocbookOnly: m_t << s->text(); break; case DocVerbatim::Dot: @@ -381,7 +396,7 @@ DB_VIS_C int i; if ((i=shortName.findRev('/'))!=-1) { - shortName=shortName.right(shortName.length()-i-1); + shortName=shortName.right((int)shortName.length()-i-1); } m_t << "<para>" << endl; writePlantUMLFile(baseName,s); @@ -434,6 +449,12 @@ DB_VIS_C case DocInclude::DontIncWithLines: case DocInclude::HtmlInclude: case DocInclude::LatexInclude: + case DocInclude::RtfInclude: + case DocInclude::ManInclude: + case DocInclude::XmlInclude: + break; + case DocInclude::DocbookInclude: + m_t << inc->text(); break; case DocInclude::VerbInclude: m_t << "<literallayout>"; @@ -463,7 +484,7 @@ DB_VIS_C extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -475,8 +496,8 @@ DB_VIS_C m_t << "</computeroutput></literallayout>"; } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -657,152 +678,152 @@ DB_VIS_C switch(s->type()) { case DocSimpleSect::See: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << "</title>" << endl; } break; case DocSimpleSect::Return: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trReturns()<< "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << "</title>" << endl; } break; case DocSimpleSect::Author: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << "</title>" << endl; } break; case DocSimpleSect::Authors: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << "</title>" << endl; } break; case DocSimpleSect::Version: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trVersion() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << "</title>" << endl; } break; case DocSimpleSect::Since: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trSince() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << "</title>" << endl; } break; case DocSimpleSect::Date: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trDate() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << "</title>" << endl; } break; case DocSimpleSect::Note: - if (m_insidePre) + if (m_insidePre) { m_t << "<note><title>" << theTranslator->trNote() << "</title>" << endl; - } - else + } + else { m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << "</title>" << endl; } break; case DocSimpleSect::Warning: - if (m_insidePre) + if (m_insidePre) { m_t << "<warning><title>" << theTranslator->trWarning() << "</title>" << endl; - } - else + } + else { m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << "</title>" << endl; } break; case DocSimpleSect::Pre: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trPrecondition() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << "</title>" << endl; } break; case DocSimpleSect::Post: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trPostcondition() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << "</title>" << endl; } break; case DocSimpleSect::Copyright: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trCopyright() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << "</title>" << endl; } break; case DocSimpleSect::Invar: - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trInvariant() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << "</title>" << endl; } break; case DocSimpleSect::Remark: // <remark> is miising the <title> possibility - if (m_insidePre) + if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trRemarks() << "</title>" << endl; - } - else + } + else { m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << "</title>" << endl; } break; case DocSimpleSect::Attention: - if (m_insidePre) + if (m_insidePre) { m_t << "<caution><title>" << theTranslator->trAttention() << "</title>" << endl; - } - else + } + else { m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << "</title>" << endl; } @@ -983,12 +1004,10 @@ DB_VIS_C m_t << "</listitem></varlistentry>\n"; } -static int colCnt = 0; -static bool bodySet = FALSE; // it is possible to have tables without a header void DocbookDocVisitor::visitPre(DocHtmlTable *t) { DB_VIS_C - bodySet = FALSE; + m_bodySet.push(false); if (m_hide) return; m_t << "<informaltable frame=\"all\">" << endl; m_t << " <tgroup cols=\"" << t->numColumns() << "\" align=\"left\" colsep=\"1\" rowsep=\"1\">" << endl; @@ -1003,8 +1022,8 @@ void DocbookDocVisitor::visitPost(DocHtmlTable *) { DB_VIS_C if (m_hide) return; - if (bodySet) m_t << " </tbody>" << endl; - bodySet = FALSE; + if (m_bodySet.top()) m_t << " </tbody>" << endl; + m_bodySet.pop(); m_t << " </tgroup>" << endl; m_t << "</informaltable>" << endl; } @@ -1012,13 +1031,18 @@ DB_VIS_C void DocbookDocVisitor::visitPre(DocHtmlRow *tr) { DB_VIS_C - colCnt = 0; + m_colCnt = 0; if (m_hide) return; - if (tr->isHeading()) m_t << "<thead>\n"; - else if (!bodySet) + if (tr->isHeading()) { - bodySet = TRUE; + if (m_bodySet.top()) m_t << "</tbody>\n"; + m_bodySet.top() = false; + m_t << "<thead>\n"; + } + else if (!m_bodySet.top()) + { + m_bodySet.top() = true; m_t << "<tbody>\n"; } @@ -1028,25 +1052,10 @@ DB_VIS_C HtmlAttrib *opt; for (li.toFirst();(opt=li.current());++li) { - if (opt->name=="class") - { - // just skip it - } - else if (opt->name=="style") - { - // just skip it - } - else if (opt->name=="height") - { - // just skip it - } - else if (opt->name=="filter") + if (supportedHtmlAttribute(opt->name)) { - // just skip it - } - else - { - m_t << " " << opt->name << "='" << opt->value << "'"; + // process supported attributes only + m_t << " " << opt->name << "='" << convertToDocBook(opt->value) << "'"; } } m_t << ">\n"; @@ -1059,15 +1068,15 @@ DB_VIS_C m_t << "</row>\n"; if (tr->isHeading()) { - bodySet = TRUE; m_t << "</thead><tbody>\n"; + m_bodySet.top() = true; } } void DocbookDocVisitor::visitPre(DocHtmlCell *c) { DB_VIS_C - colCnt++; + m_colCnt++; if (m_hide) return; m_t << "<entry"; @@ -1077,10 +1086,10 @@ DB_VIS_C { if (opt->name=="colspan") { - m_t << " namest='c" << colCnt << "'"; + m_t << " namest='c" << m_colCnt << "'"; int cols = opt->value.toInt(); - colCnt += (cols - 1); - m_t << " nameend='c" << colCnt << "'"; + m_colCnt += (cols - 1); + m_t << " nameend='c" << m_colCnt << "'"; } else if (opt->name=="rowspan") { @@ -1089,63 +1098,44 @@ DB_VIS_C } else if (opt->name=="class") { - if (opt->value == "markdownTableBodyRight") + if (opt->value.left(13)=="markdownTable") // handle markdown generated attributes { - m_t << " align='right'"; - } - else if (opt->value == "markdownTableBodyLeftt") - { - m_t << " align='left'"; - } - else if (opt->value == "markdownTableBodyCenter") - { - m_t << " align='center'"; - } - else if (opt->value == "markdownTableHeadRight") - { - m_t << " align='right'"; - } - else if (opt->value == "markdownTableHeadLeftt") - { - m_t << " align='left'"; + if (opt->value.right(5)=="Right") + { + m_t << " align='right'"; + } + else if (opt->value.right(4)=="Left") + { + m_t << " align='left'"; + } + else if (opt->value.right(6)=="Center") + { + m_t << " align='center'"; + } + // skip 'markdownTable*' value ending with "None" } - else if (opt->value == "markdownTableHeadCenter") + else { - m_t << " align='center'"; + m_t << " class='" << convertToDocBook(opt->value) << "'"; } } - else if (opt->name=="style") - { - // just skip it - } - else if (opt->name=="width") - { - // just skip it - } - else if (opt->name=="height") - { - // just skip it - } - else if (opt->name=="nowrap" && opt->value.isEmpty()) + else if (supportedHtmlAttribute(opt->name)) { - m_t << " " << opt->name << "='nowrap'"; - } - else - { - m_t << " " << opt->name << "='" << opt->value << "'"; + // process supported attributes only + m_t << " " << opt->name << "='" << convertToDocBook(opt->value) << "'"; } } m_t << ">"; } -void DocbookDocVisitor::visitPost(DocHtmlCell *c) +void DocbookDocVisitor::visitPost(DocHtmlCell *) { DB_VIS_C if (m_hide) return; m_t << "</entry>"; } -void DocbookDocVisitor::visitPre(DocHtmlCaption *c) +void DocbookDocVisitor::visitPre(DocHtmlCaption *) { DB_VIS_C if (m_hide) return; @@ -1212,7 +1202,7 @@ DB_VIS_C int i; if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1) { - baseName=baseName.right(baseName.length()-i-1); + baseName=baseName.right((int)baseName.length()-i-1); } visitPreStart(m_t, img->children(), img->hasCaption(), img->relPath() + baseName, img->width(), img->height(), img->isInlineImage()); } @@ -1235,12 +1225,12 @@ DB_VIS_C int i; if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1) { - baseName=baseName.right(baseName.length()-i-1); + baseName=baseName.right((int)baseName.length()-i-1); } QCString m_file; bool ambig; - FileDef *fd=findFileDef(Doxygen::imageNameDict, baseName, ambig); - if (fd) + FileDef *fd=findFileDef(Doxygen::imageNameLinkedMap, baseName, ambig); + if (fd) { m_file=fd->absFilePath(); } @@ -1257,8 +1247,8 @@ DB_VIS_C delete[] buffer; } } - } - else + } + else { popEnabled(); } @@ -1342,7 +1332,7 @@ DB_VIS_C if (!ref->file().isEmpty()) endLink(); } -void DocbookDocVisitor::visitPre(DocSecRefItem *ref) +void DocbookDocVisitor::visitPre(DocSecRefItem *) { DB_VIS_C if (m_hide) return; @@ -1425,11 +1415,9 @@ DB_VIS_C if (m_hide) return; m_t << " <row>" << endl; - DocParamSect::Type parentType = DocParamSect::Unknown; DocParamSect *sect = 0; if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect) { - parentType = ((DocParamSect*)pl->parent())->type(); sect=(DocParamSect*)pl->parent(); } @@ -1632,16 +1620,14 @@ DB_VIS_C void DocbookDocVisitor::pushEnabled() { DB_VIS_C - m_enabled.push(new bool(m_hide)); + m_enabled.push(m_hide); } void DocbookDocVisitor::popEnabled() { DB_VIS_C - bool *v=m_enabled.pop(); - ASSERT(v!=0); - m_hide = *v; - delete v; + m_hide=m_enabled.top(); + m_enabled.pop(); } void DocbookDocVisitor::writeMscFile(const QCString &baseName, DocVerbatim *s) @@ -1651,7 +1637,7 @@ DB_VIS_C int i; if ((i=shortName.findRev('/'))!=-1) { - shortName=shortName.right(shortName.length()-i-1); + shortName=shortName.right((int)shortName.length()-i-1); } QCString outDir = Config_getString(DOCBOOK_OUTPUT); writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_BITMAP); @@ -1667,7 +1653,7 @@ DB_VIS_C int i; if ((i=shortName.findRev('/'))!=-1) { - shortName=shortName.right(shortName.length()-i-1); + shortName=shortName.right((int)shortName.length()-i-1); } QCString outDir = Config_getString(DOCBOOK_OUTPUT); PlantumlManager::instance()->generatePlantUMLOutput(baseName,outDir,PlantumlManager::PUML_BITMAP); @@ -1688,7 +1674,7 @@ DB_VIS_C int i; if ((i=baseName.findRev('/'))!=-1) { - baseName=baseName.right(baseName.length()-i-1); + baseName=baseName.right((int)baseName.length()-i-1); } if ((i=baseName.find('.'))!=-1) { @@ -1716,7 +1702,7 @@ DB_VIS_C int i; if ((i=shortName.findRev('/'))!=-1) { - shortName=shortName.right(shortName.length()-i-1); + shortName=shortName.right((int)shortName.length()-i-1); } QCString outDir = Config_getString(DOCBOOK_OUTPUT); writeDiaGraphFromFile(baseName+".dia",outDir,shortName,DIA_BITMAP); @@ -1737,7 +1723,7 @@ DB_VIS_C int i; if ((i=baseName.findRev('/'))!=-1) { - baseName=baseName.right(baseName.length()-i-1); + baseName=baseName.right((int)baseName.length()-i-1); } if ((i=baseName.find('.'))!=-1) { @@ -1765,7 +1751,7 @@ DB_VIS_C int i; if ((i=shortName.findRev('/'))!=-1) { - shortName=shortName.right(shortName.length()-i-1); + shortName=shortName.right((int)shortName.length()-i-1); } QCString outDir = Config_getString(DOCBOOK_OUTPUT); writeDotGraphFromFile(baseName+".dot",outDir,shortName,GOF_BITMAP); @@ -1786,7 +1772,7 @@ DB_VIS_C int i; if ((i=baseName.findRev('/'))!=-1) { - baseName=baseName.right(baseName.length()-i-1); + baseName=baseName.right((int)baseName.length()-i-1); } if ((i=baseName.find('.'))!=-1) { diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h index 47275f7..ee07df5 100644 --- a/src/docbookvisitor.h +++ b/src/docbookvisitor.h @@ -1,8 +1,6 @@ /****************************************************************************** * -* -* -* Copyright (C) 1997-2015 by Dimitri van Heesch. +* Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby @@ -18,6 +16,7 @@ #ifndef _DOCBOOKDOCVISITOR_H #define _DOCBOOKDOCVISITOR_H +#include "containers.h" #include "docvisitor.h" #include <qstack.h> #include <qlist.h> @@ -173,10 +172,12 @@ class DocbookDocVisitor : public DocVisitor //-------------------------------------- FTextStream &m_t; CodeOutputInterface &m_ci; - bool m_insidePre; - bool m_hide; - QStack<bool> m_enabled; + bool m_insidePre = false; + bool m_hide = false; + BoolStack m_enabled; QCString m_langExt; + int m_colCnt = 0; + BoolStack m_bodySet; // it is possible to have tables without a header, needs to be an array as we can have tables in tables }; #endif diff --git a/src/docgroup.cpp b/src/docgroup.cpp index fbdb842..d82d1b3 100644 --- a/src/docgroup.cpp +++ b/src/docgroup.cpp @@ -13,12 +13,14 @@ * */ +#include <atomic> #include "doxygen.h" #include "util.h" #include "entry.h" #include "message.h" #include "docgroup.h" +static std::atomic_int g_groupId; void DocGroup::enterFile(const char *fileName,int) { @@ -84,7 +86,7 @@ void DocGroup::leaveCompound(const char *,int,const char * /*name*/) m_compoundName.resize(0); } -int DocGroup::findExistingGroup(int &groupId,const MemberGroupInfo *info) +int DocGroup::findExistingGroup(const MemberGroupInfo *info) { //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data()); QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict); @@ -100,8 +102,7 @@ int DocGroup::findExistingGroup(int &groupId,const MemberGroupInfo *info) return (int)di.currentKey(); // put the item in this group } } - groupId++; // start new group - return groupId; + return ++g_groupId; // start new group } void DocGroup::open(Entry *e,const char *,int, bool implicit) @@ -118,12 +119,10 @@ void DocGroup::open(Entry *e,const char *,int, bool implicit) //printf(" membergroup id=%d %s\n",m_memberGroupId,m_memberGroupHeader.data()); if (m_memberGroupId==DOX_NOGROUP) // no group started yet { - static int curGroupId=0; - MemberGroupInfo *info = new MemberGroupInfo; info->header = m_memberGroupHeader.stripWhiteSpace(); info->compoundName = m_compoundName; - m_memberGroupId = findExistingGroup(curGroupId,info); + m_memberGroupId = findExistingGroup(info); //printf(" use membergroup %d\n",m_memberGroupId); Doxygen::memGrpInfoDict.insert(m_memberGroupId,info); diff --git a/src/docgroup.h b/src/docgroup.h index 3ccef0d..c724348 100644 --- a/src/docgroup.h +++ b/src/docgroup.h @@ -41,7 +41,7 @@ class DocGroup void addDocs(Entry *e); private: - int findExistingGroup(int &groupId,const MemberGroupInfo *info); + int findExistingGroup(const MemberGroupInfo *info); int m_openCount = 0; QCString m_memberGroupHeader; int m_memberGroupId = 0; diff --git a/src/docparser.cpp b/src/docparser.cpp index 5498adb..73131f6 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -70,11 +70,11 @@ //#define DBG(x) myprintf x #define INTERNAL_ASSERT(x) do {} while(0) -//#define INTERNAL_ASSERT(x) if (!(x)) DBG(("INTERNAL_ASSERT(%s) failed retval=0x%x: file=%s line=%d\n",#x,retval,__FILE__,__LINE__)); +//#define INTERNAL_ASSERT(x) if (!(x)) DBG(("INTERNAL_ASSERT(%s) failed retval=0x%x: file=%s line=%d\n",#x,retval,__FILE__,__LINE__)); //--------------------------------------------------------------------------- -static const char *sectionLevelToName[] = +static const char *sectionLevelToName[] = { "page", "section", @@ -106,18 +106,18 @@ static QDict<void> g_paramsFound; static const MemberDef * g_memberDef; static bool g_isExample; static QCString g_exampleName; -static SectionDict * g_sectionDict; static QCString g_searchUrl; static QCString g_includeFileName; static QCString g_includeFileText; static uint g_includeFileOffset; static uint g_includeFileLength; -static uint g_includeFileLine; +static int g_includeFileLine; static bool g_includeFileShowLineNo; +static bool g_markdownSupport; -/** Parser's context to store all global variables. +/** Parser's context to store all global variables. */ struct DocParserContext { @@ -141,13 +141,12 @@ struct DocParserContext QDict<void> paramsFound; bool isExample; QCString exampleName; - SectionDict *sectionDict; QCString searchUrl; QCString includeFileText; uint includeFileOffset; uint includeFileLength; - uint includeFileLine; + int includeFileLine; bool includeFileLineNo; TokenInfo *token; @@ -191,7 +190,6 @@ static void docParserPushContext(bool saveParamInfo=TRUE) ctx->memberDef = g_memberDef; ctx->isExample = g_isExample; ctx->exampleName = g_exampleName; - ctx->sectionDict = g_sectionDict; ctx->searchUrl = g_searchUrl; ctx->includeFileText = g_includeFileText; @@ -199,7 +197,7 @@ static void docParserPushContext(bool saveParamInfo=TRUE) ctx->includeFileLength = g_includeFileLength; ctx->includeFileLine = g_includeFileLine; ctx->includeFileLineNo = g_includeFileShowLineNo; - + ctx->token = g_token; g_token = new TokenInfo; @@ -232,7 +230,6 @@ static void docParserPopContext(bool keepParamInfo=FALSE) g_memberDef = ctx->memberDef; g_isExample = ctx->isExample; g_exampleName = ctx->exampleName; - g_sectionDict = ctx->sectionDict; g_searchUrl = ctx->searchUrl; g_includeFileText = ctx->includeFileText; @@ -285,7 +282,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool { QCString result; bool ambig; - FileDef *fd = findFileDef(Doxygen::imageNameDict,fileName,ambig); + FileDef *fd = findFileDef(Doxygen::imageNameLinkedMap,fileName,ambig); //printf("Search for %s\n",fileName); if (fd) { @@ -294,8 +291,8 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool QCString text; text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName)); text+="Possible candidates:\n"; - text+=showFileDefMatches(Doxygen::imageNameDict,fileName); - warn_doc_error(g_fileName,doctokenizerYYlineno,text); + text+=showFileDefMatches(Doxygen::imageNameLinkedMap,fileName); + warn_doc_error(g_fileName,doctokenizerYYlineno,"%s", text.data()); } QCString inputFile = fd->absFilePath(); @@ -306,7 +303,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool int i; if ((i=result.findRev('/'))!=-1 || (i=result.findRev('\\'))!=-1) { - result = result.right(result.length()-i-1); + result = result.right((int)result.length()-i-1); } //printf("fileName=%s result=%s\n",fileName,result.data()); QCString outputDir; @@ -368,7 +365,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool "could not open image %s",qPrint(fileName)); } - if (type==DocImage::Latex && Config_getBool(USE_PDFLATEX) && + if (type==DocImage::Latex && Config_getBool(USE_PDFLATEX) && fd->name().right(4)==".eps" ) { // we have an .eps image in pdflatex mode => convert it to a pdf. @@ -393,7 +390,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool if (result.left(5)!="http:" && result.left(6)!="https:" && dowarn) { warn_doc_error(g_fileName,doctokenizerYYlineno, - "image file %s is not found in IMAGE_PATH: " + "image file %s is not found in IMAGE_PATH: " "assuming external image.",qPrint(fileName) ); } @@ -408,7 +405,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool * are disabled altogether). */ static void checkArgumentName(const QCString &name) -{ +{ if (!Config_getBool(WARN_IF_DOC_ERROR)) return; if (g_memberDef==0) return; // not a member const ArgumentList &al=g_memberDef->isDocsForDefinition() ? @@ -478,9 +475,10 @@ static void checkRetvalName(const QCString &name) { warn_doc_error(g_memberDef->getDefFileName(), g_memberDef->getDefLine(), - "return value '" + name + "' of " + + "%s", + ("return value '" + name + "' of " + QCString(g_memberDef->qualifiedName()) + - " has multiple documentation sections"); + " has multiple documentation sections").data()); } g_retvalsFound.insert(name,(void *)(0x8)); } @@ -514,7 +512,7 @@ static void checkUnOrMultipleDocumentedParams() { // allow undocumented self / cls parameter for Python } - else if (!argName.isEmpty() && g_paramsFound.find(argName)==0 && a.docs.isEmpty()) + else if (!argName.isEmpty() && g_paramsFound.find(argName)==0 && a.docs.isEmpty()) { notArgCnt++; } @@ -531,10 +529,11 @@ static void checkUnOrMultipleDocumentedParams() { warn_doc_error(g_memberDef->getDefFileName(), g_memberDef->getDefLine(), - "argument '" + aName + + "%s", + ("argument '" + aName + "' from the argument list of " + QCString(g_memberDef->qualifiedName()) + - " has multiple @param documentation sections"); + " has multiple @param documentation sections").data()); } } if (notArgCnt>0) @@ -544,7 +543,7 @@ static void checkUnOrMultipleDocumentedParams() "The following parameter"; errMsg+= (notArgCnt>1 ? "s" : ""); errMsg+=" of "+ - QCString(g_memberDef->qualifiedName()) + + QCString(g_memberDef->qualifiedName()) + QCString(argListToString(al)) + (notArgCnt>1 ? " are" : " is") + " not documented:\n"; for (const Argument &a : al) @@ -571,7 +570,8 @@ static void checkUnOrMultipleDocumentedParams() } warn_doc_error(g_memberDef->getDefFileName(), g_memberDef->getDefLine(), - substitute(errMsg,"%","%%")); + "%s", + substitute(errMsg,"%","%%").data()); } } } @@ -588,7 +588,7 @@ static QCString stripKnownExtensions(const char *text) result=result.left(result.length()-4); } else if (result.right(Doxygen::htmlFileExtension.length())== - QCString(Doxygen::htmlFileExtension)) + QCString(Doxygen::htmlFileExtension)) { result=result.left(result.length()-Doxygen::htmlFileExtension.length()); } @@ -629,7 +629,7 @@ static bool insideUL(DocNode *n) { while (n) { - if (n->kind()==DocNode::Kind_HtmlList && + if (n->kind()==DocNode::Kind_HtmlList && ((DocHtmlList *)n)->type()==DocHtmlList::Unordered) return TRUE; n=n->parent(); } @@ -643,7 +643,7 @@ static bool insideOL(DocNode *n) { while (n) { - if (n->kind()==DocNode::Kind_HtmlList && + if (n->kind()==DocNode::Kind_HtmlList && ((DocHtmlList *)n)->type()==DocHtmlList::Ordered) return TRUE; n=n->parent(); } @@ -663,7 +663,6 @@ static bool insideTable(DocNode *n) } //--------------------------------------------------------------------------- - /*! Looks for a documentation block with name commandName in the current * context (g_context). The resulting documentation string is * put in pDoc, the definition in which the documentation was found is @@ -680,14 +679,47 @@ static bool findDocsForMemberOrCompound(const char *commandName, *pDoc=""; *pBrief=""; *pDef=0; - QCString cmdArg=substitute(commandName,"#","::"); - cmdArg = replaceScopeSeparator(cmdArg); + QCString cmdArg=commandName; + if (cmdArg.isEmpty()) return FALSE; + + const FileDef *fd=0; + const GroupDef *gd=0; + const PageDef *pd=0; + gd = Doxygen::groupSDict->find(cmdArg); + if (gd) // group + { + *pDoc=gd->documentation(); + *pBrief=gd->briefDescription(); + *pDef=gd; + return TRUE; + } + pd = Doxygen::pageSDict->find(cmdArg); + if (pd) // page + { + *pDoc=pd->documentation(); + *pBrief=pd->briefDescription(); + *pDef=pd; + return TRUE; + } + bool ambig; + fd = findFileDef(Doxygen::inputNameLinkedMap,cmdArg,ambig); + if (fd && !ambig) // file + { + *pDoc=fd->documentation(); + *pBrief=fd->briefDescription(); + *pDef=fd; + return TRUE; + } + + // for symbols we need to normalize the separator, so A#B, or A\B, or A.B becomes A::B + cmdArg = substitute(cmdArg,"#","::"); + cmdArg = substitute(cmdArg,"\\","::"); + cmdArg = substitute(cmdArg,".","::"); - int l=cmdArg.length(); - if (l==0) return FALSE; + int l=(int)cmdArg.length(); int funcStart=cmdArg.find('('); - if (funcStart==-1) + if (funcStart==-1) { funcStart=l; } @@ -697,9 +729,9 @@ static bool findDocsForMemberOrCompound(const char *commandName, // beware of scenarios like operator()((foo)bar) int secondParen = cmdArg.find('(', funcStart+1); int leftParen = cmdArg.find(')', funcStart+1); - if (leftParen!=-1 && secondParen!=-1) + if (leftParen!=-1 && secondParen!=-1) { - if (leftParen<secondParen) + if (leftParen<secondParen) { funcStart=secondParen; } @@ -711,10 +743,7 @@ static bool findDocsForMemberOrCompound(const char *commandName, // try if the link is to a member const MemberDef *md=0; const ClassDef *cd=0; - const FileDef *fd=0; const NamespaceDef *nd=0; - const GroupDef *gd=0; - const PageDef *pd=0; bool found = getDefs( g_context.find('.')==-1?g_context.data():"", // find('.') is a hack to detect files name, @@ -730,7 +759,7 @@ static bool findDocsForMemberOrCompound(const char *commandName, } - int scopeOffset=g_context.length(); + int scopeOffset=(int)g_context.length(); do // for each scope { QCString fullName=cmdArg; @@ -742,7 +771,7 @@ static bool findDocsForMemberOrCompound(const char *commandName, // try class, namespace, group, page, file reference cd = Doxygen::classSDict->find(fullName); - if (cd) // class + if (cd) // class { *pDoc=cd->documentation(); *pBrief=cd->briefDescription(); @@ -757,32 +786,6 @@ static bool findDocsForMemberOrCompound(const char *commandName, *pDef=nd; return TRUE; } - gd = Doxygen::groupSDict->find(cmdArg); - if (gd) // group - { - *pDoc=gd->documentation(); - *pBrief=gd->briefDescription(); - *pDef=gd; - return TRUE; - } - pd = Doxygen::pageSDict->find(cmdArg); - if (pd) // page - { - *pDoc=pd->documentation(); - *pBrief=pd->briefDescription(); - *pDef=pd; - return TRUE; - } - bool ambig; - fd = findFileDef(Doxygen::inputNameDict,cmdArg,ambig); - if (fd && !ambig) // file - { - *pDoc=fd->documentation(); - *pBrief=fd->briefDescription(); - *pDef=fd; - return TRUE; - } - if (scopeOffset==0) { scopeOffset=-1; @@ -794,9 +797,10 @@ static bool findDocsForMemberOrCompound(const char *commandName, } } while (scopeOffset>=0); - + return FALSE; } + //--------------------------------------------------------------------------- inline void errorHandleDefaultToken(DocNode *parent,int tok, QList<DocNode> &children,const char *txt) @@ -825,7 +829,7 @@ inline void errorHandleDefaultToken(DocNode *parent,int tok, //--------------------------------------------------------------------------- // forward declaration -static bool defaultHandleToken(DocNode *parent,int tok, +static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool handleWord=TRUE); @@ -841,15 +845,15 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, qPrint(saveCmdName)); return tok; } - while ((tok=doctokenizerYYlex()) && - tok!=TK_WHITESPACE && + while ((tok=doctokenizerYYlex()) && + tok!=TK_WHITESPACE && tok!=TK_NEWPARA && - tok!=TK_LISTITEM && + tok!=TK_LISTITEM && tok!=TK_ENDLIST ) { static QRegExp specialChar("[.,|()\\[\\]:;\\?]"); - if (tok==TK_WORD && g_token->name.length()==1 && + if (tok==TK_WORD && g_token->name.length()==1 && g_token->name.find(specialChar)!=-1) { // special character that ends the markup command @@ -862,7 +866,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, case TK_HTMLTAG: if (insideLI(parent) && Mappers::htmlTagMapper->map(g_token->name) && g_token->endTag) { // ignore </li> as the end of a style command - continue; + continue; } return tok; break; @@ -875,7 +879,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, } DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(saveCmdName),tok)); return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST - ) ? tok : RetVal_OK; + ) ? tok : RetVal_OK; } /*! Called when a style change starts. For instance a \<b\> command is @@ -942,7 +946,7 @@ static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children) if (!g_styleStack.isEmpty()) { DocStyleChange *sc = g_styleStack.top(); - while (sc && sc->position()>=g_nodeStack.count()) + while (sc && sc->position()>=g_nodeStack.count()) { // there are unclosed style modifiers in the paragraph children.append(new DocStyleChange(parent,g_nodeStack.count(),sc->style(),sc->tagName(),FALSE)); g_initialStyleStack.push(sc); @@ -965,7 +969,7 @@ static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttrib { HtmlAttribListIterator li(tagHtmlAttribs); HtmlAttrib *opt; - int index=0; + uint index=0; int retval = RetVal_OK; for (li.toFirst();(opt=li.current());++li,++index) { @@ -1058,12 +1062,12 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor const Definition *compound=0; const MemberDef *member=0; - int len = g_token->name.length(); + uint len = g_token->name.length(); ClassDef *cd=0; bool ambig; - FileDef *fd = findFileDef(Doxygen::inputNameDict,g_fileName,ambig); + FileDef *fd = findFileDef(Doxygen::inputNameLinkedMap,g_fileName,ambig); //printf("handleLinkedWord(%s) g_context=%s\n",g_token->name.data(),g_context.data()); - if (!g_insideHtmlLink && + if (!g_insideHtmlLink && (resolveRef(g_context,g_token->name,g_inSeeBlock,&compound,&member,TRUE,fd,TRUE) || (!g_context.isEmpty() && // also try with global scope resolveRef("",g_token->name,g_inSeeBlock,&compound,&member,FALSE,0,TRUE)) @@ -1073,12 +1077,12 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor //printf("resolveRef %s = %p (linkable?=%d)\n",qPrint(g_token->name),member,member ? member->isLinkable() : FALSE); if (member && member->isLinkable()) // member link { - if (member->isObjCMethod()) + if (member->isObjCMethod()) { bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE; name = member->objCMethodName(localLink,g_inSeeBlock); } - children.append(new + children.append(new DocLinkedWord(parent,name, member->getReference(), member->getOutputFileBase(), @@ -1098,7 +1102,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor { name=(dynamic_cast<const GroupDef*>(compound))->groupTitle(); } - children.append(new + children.append(new DocLinkedWord(parent,name, compound->getReference(), compound->getOutputFileBase(), @@ -1111,7 +1115,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor (dynamic_cast<const FileDef*>(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { - children.append(new + children.append(new DocLinkedWord(parent,g_token->name, compound->getReference(), compound->getSourceFileBase(), @@ -1127,7 +1131,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor } else if (!g_insideHtmlLink && len>1 && g_token->name.at(len-1)==':') { - // special case, where matching Foo: fails to be an Obj-C reference, + // special case, where matching Foo: fails to be an Obj-C reference, // but Foo itself might be linkable. g_token->name=g_token->name.left(len-1); handleLinkedWord(parent,children,ignoreAutoLinkFlag); @@ -1137,7 +1141,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor { // special case 2, where the token name is not a class, but could // be a Obj-C protocol - children.append(new + children.append(new DocLinkedWord(parent,name, cd->getReference(), cd->getOutputFileBase(), @@ -1149,7 +1153,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor // { // // special case 3, where the token name is not a class, but could // // be a C# generic -// children.append(new +// children.append(new // DocLinkedWord(parent,name, // cd->getReference(), // cd->getOutputFileBase(), @@ -1401,7 +1405,7 @@ reparsetoken: children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,tokenName,FALSE)); if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," ")); if (tok==TK_NEWPARA) goto handlepara; - else if (tok==TK_WORD || tok==TK_HTMLTAG) + else if (tok==TK_WORD || tok==TK_HTMLTAG) { DBG(("CMD_EMPHASIS: reparsing command %s\n",qPrint(g_token->name))); goto reparsetoken; @@ -1415,7 +1419,7 @@ reparsetoken: children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,tokenName,FALSE)); if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," ")); if (tok==TK_NEWPARA) goto handlepara; - else if (tok==TK_WORD || tok==TK_HTMLTAG) + else if (tok==TK_WORD || tok==TK_HTMLTAG) { DBG(("CMD_BOLD: reparsing command %s\n",qPrint(g_token->name))); goto reparsetoken; @@ -1429,7 +1433,7 @@ reparsetoken: children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,tokenName,FALSE)); if (tok!=TK_WORD) children.append(new DocWhiteSpace(parent," ")); if (tok==TK_NEWPARA) goto handlepara; - else if (tok==TK_WORD || tok==TK_HTMLTAG) + else if (tok==TK_WORD || tok==TK_HTMLTAG) { DBG(("CMD_CODE: reparsing command %s\n",qPrint(g_token->name))); goto reparsetoken; @@ -1468,7 +1472,7 @@ reparsetoken: doctokenizerYYsetStateLatexOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker",doctokenizerYYlineno); + if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1477,7 +1481,7 @@ reparsetoken: doctokenizerYYsetStateXmlOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker",doctokenizerYYlineno); + if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1486,7 +1490,7 @@ reparsetoken: doctokenizerYYsetStateDbOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker",doctokenizerYYlineno); + if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1563,6 +1567,7 @@ reparsetoken: { handleStyleLeave(parent,children,DocStyleChange::S,tokenName); } + break; case HTML_STRIKE: if (!g_token->endTag) { @@ -1674,7 +1679,7 @@ reparsetoken: } } break; - case TK_SYMBOL: + case TK_SYMBOL: { DocSymbol::SymType s = DocSymbol::decodeSymbol(tokenName); if (s!=DocSymbol::Sym_Unknown) @@ -1687,15 +1692,15 @@ reparsetoken: } } break; - case TK_WHITESPACE: - case TK_NEWPARA: + case TK_WHITESPACE: + case TK_NEWPARA: handlepara: if (insidePRE(parent) || !children.isEmpty()) { children.append(new DocWhiteSpace(parent,g_token->chars)); } break; - case TK_LNKWORD: + case TK_LNKWORD: if (handleWord) { handleLinkedWord(parent,children); @@ -1703,7 +1708,7 @@ handlepara: else return FALSE; break; - case TK_WORD: + case TK_WORD: if (handleWord) { children.append(new DocWord(parent,g_token->name)); @@ -1734,7 +1739,7 @@ static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribL HtmlAttribListIterator li(tagHtmlAttribs); HtmlAttrib *opt; bool found=FALSE; - int index=0; + uint index=0; for (li.toFirst();(opt=li.current());++li,++index) { //printf("option name=%s value=%s\n",opt->name.data(),opt->value.data()); @@ -1772,7 +1777,7 @@ DocEmoji::DocEmoji(DocNode *parent,const QCString &symName) : { m_parent = parent; QCString locSymName = symName; - int len=locSymName.length(); + uint len=locSymName.length(); if (len>0) { if (locSymName.at(len-1)!=':') locSymName.append(":"); @@ -1795,7 +1800,7 @@ static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children, if (doc.isEmpty()) return retval; - doctokenizerYYinit(doc,g_fileName); + doctokenizerYYinit(doc,g_fileName,g_markdownSupport); // first parse any number of paragraphs bool isFirst=TRUE; @@ -1810,7 +1815,7 @@ static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children, DocPara *par = new DocPara(parent); if (isFirst) { par->markFirst(); isFirst=FALSE; } retval=par->parse(); - if (!par->isEmpty()) + if (!par->isEmpty()) { children.append(par); if (lastPar) lastPar->markLast(FALSE); @@ -1842,23 +1847,21 @@ static void readTextFileByName(const QCString &file,QCString &text) return; } } - QStrList &examplePathList = Config_getList(EXAMPLE_PATH); - char *s=examplePathList.first(); - while (s) + const StringVector &examplePathList = Config_getList(EXAMPLE_PATH); + for (const auto &s : examplePathList) { - QCString absFileName = QCString(s)+Portable::pathSeparator()+file; + QCString absFileName = QCString(s.c_str())+Portable::pathSeparator()+file; QFileInfo fi(absFileName); if (fi.exists()) { text = fileToString(absFileName,Config_getBool(FILTER_SOURCE_FILES)); return; } - s=examplePathList.next(); } // as a fallback we also look in the exampleNameDict bool ambig; - FileDef *fd = findFileDef(Doxygen::exampleNameDict,file,ambig); + FileDef *fd = findFileDef(Doxygen::exampleNameLinkedMap,file,ambig); if (fd) { text = fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)); @@ -1866,7 +1869,7 @@ static void readTextFileByName(const QCString &file,QCString &text) { warn_doc_error(g_fileName,doctokenizerYYlineno,"included file name %s is ambiguous" "Possible candidates:\n%s",qPrint(file), - qPrint(showFileDefMatches(Doxygen::exampleNameDict,file)) + qPrint(showFileDefMatches(Doxygen::exampleNameLinkedMap,file)) ); } } @@ -1879,10 +1882,10 @@ static void readTextFileByName(const QCString &file,QCString &text) //--------------------------------------------------------------------------- -DocWord::DocWord(DocNode *parent,const QCString &word) : - m_word(word) +DocWord::DocWord(DocNode *parent,const QCString &word) : + m_word(word) { - m_parent = parent; + m_parent = parent; //printf("new word %s url=%s\n",word.data(),g_searchUrl.data()); if (Doxygen::searchIndex && !g_searchUrl.isEmpty()) { @@ -1894,12 +1897,12 @@ DocWord::DocWord(DocNode *parent,const QCString &word) : DocLinkedWord::DocLinkedWord(DocNode *parent,const QCString &word, const QCString &ref,const QCString &file, - const QCString &anchor,const QCString &tooltip) : - m_word(word), m_ref(ref), + const QCString &anchor,const QCString &tooltip) : + m_word(word), m_ref(ref), m_file(file), m_relPath(g_relPath), m_anchor(anchor), m_tooltip(tooltip) { - m_parent = parent; + m_parent = parent; //printf("DocLinkedWord: new word %s url=%s tooltip='%s'\n", // word.data(),g_searchUrl.data(),tooltip.data()); if (Doxygen::searchIndex && !g_searchUrl.isEmpty()) @@ -1912,22 +1915,24 @@ DocLinkedWord::DocLinkedWord(DocNode *parent,const QCString &word, DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) { - m_parent = parent; + m_parent = parent; if (id.isEmpty()) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Empty anchor label"); return; } - if (id.left(CiteConsts::anchorPrefix.length()) == CiteConsts::anchorPrefix) + const CitationManager &ct = CitationManager::instance(); + QCString anchorPrefix = ct.anchorPrefix(); + if (id.left(anchorPrefix.length()) == anchorPrefix) { - CiteInfo *cite = Doxygen::citeDict->find(id.mid(CiteConsts::anchorPrefix.length())); - if (cite) + const CiteInfo *cite = ct.find(id.mid(anchorPrefix.length())); + if (cite) { - m_file = convertNameToFile(CiteConsts::fileName,FALSE,TRUE); + m_file = convertNameToFile(ct.fileName(),FALSE,TRUE); m_anchor = id; } - else + else { warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid cite anchor id '%s'",qPrint(id)); m_anchor = "invalid"; @@ -1940,17 +1945,12 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) } else // found \anchor label { - SectionInfo *sec = Doxygen::sectionDict->find(id); + const SectionInfo *sec = SectionManager::instance().find(id); if (sec) { //printf("Found anchor %s\n",id.data()); - m_file = sec->fileName; - m_anchor = sec->label; - if (g_sectionDict && g_sectionDict->find(id)==0) - { - //printf("Inserting in dictionary!\n"); - g_sectionDict->append(id,sec); - } + m_file = sec->fileName(); + m_anchor = sec->label(); } else { @@ -1997,12 +1997,14 @@ void DocInclude::parse() g_includeFileShowLineNo = (m_type == DontIncWithLines || m_type == IncWithLines); //printf("g_includeFile=<<%s>>\n",g_includeFileText.data()); break; - case VerbInclude: + case VerbInclude: // fall through case HtmlInclude: - readTextFileByName(m_file,m_text); - break; case LatexInclude: + case DocInclude::RtfInclude: + case DocInclude::ManInclude: + case DocInclude::XmlInclude: + case DocInclude::DocbookInclude: readTextFileByName(m_file,m_text); break; case Snippet: @@ -2017,8 +2019,8 @@ void DocInclude::parse() m_blockId.data(),m_file.data(),count); } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -2040,7 +2042,7 @@ void DocIncOperator::parse() const char *p = g_includeFileText; uint l = g_includeFileLength; uint o = g_includeFileOffset; - uint il = g_includeFileLine; + int il = g_includeFileLine; DBG(("DocIncOperator::parse() text=%s off=%d len=%d\n",qPrint(p),o,l)); uint so = o,bo; bool nonEmpty = FALSE; @@ -2050,7 +2052,7 @@ void DocIncOperator::parse() while (o<l) { char c = p[o]; - if (c=='\n') + if (c=='\n') { g_includeFileLine++; if (nonEmpty) break; // we have a pattern to match @@ -2167,26 +2169,18 @@ void DocIncOperator::parse() //--------------------------------------------------------------------------- -DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) : +DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) : m_id(id), m_key(key), m_relPath(g_relPath) { - m_parent = parent; + m_parent = parent; } bool DocXRefItem::parse() { - RefList *refList = Doxygen::xrefLists->find(m_key); - if (refList && - ( - // either not a built-in list or the list is enabled - (m_key!="todo" || Config_getBool(GENERATE_TODOLIST)) && - (m_key!="test" || Config_getBool(GENERATE_TESTLIST)) && - (m_key!="bug" || Config_getBool(GENERATE_BUGLIST)) && - (m_key!="deprecated" || Config_getBool(GENERATE_DEPRECATEDLIST)) - ) - ) + RefList *refList = RefListManager::instance().find(m_key); + if (refList && refList->isEnabled()) { - RefItem *item = refList->getRefItem(m_id); + RefItem *item = refList->find(m_id); ASSERT(item!=0); if (item) { @@ -2198,16 +2192,16 @@ bool DocXRefItem::parse() else { m_file = refList->fileName(); - m_anchor = item->listAnchor; + m_anchor = item->anchor(); } m_title = refList->sectionTitle(); //printf("DocXRefItem: file=%s anchor=%s title=%s\n", // m_file.data(),m_anchor.data(),m_title.data()); - if (!item->text.isEmpty()) + if (!item->text().isEmpty()) { docParserPushContext(); - internalValidatingParseDoc(this,m_children,item->text); + internalValidatingParseDoc(this,m_children,item->text()); docParserPopContext(); } } @@ -2221,15 +2215,13 @@ bool DocXRefItem::parse() DocFormula::DocFormula(DocNode *parent,int id) : m_relPath(g_relPath) { - m_parent = parent; - QCString formCmd; - formCmd.sprintf("\\_form#%d",id); - Formula *formula=Doxygen::formulaNameDict->find(formCmd); - if (formula) + m_parent = parent; + QCString text = FormulaManager::instance().findFormula(id); + if (!text.isEmpty()) { - m_id = formula->getId(); + m_id = id; m_name.sprintf("form_%d",m_id); - m_text = formula->getFormulaText(); + m_text = text; } else // wrong \_form#<n> command { @@ -2284,30 +2276,26 @@ void DocSecRefItem::parse() doctokenizerYYsetStatePara(); handlePendingStyleCommands(this,m_children); - SectionInfo *sec=0; + const SectionInfo *sec=0; if (!m_target.isEmpty()) { - sec=Doxygen::sectionDict->find(m_target); + sec = SectionManager::instance().find(m_target); if (sec) { - m_file = sec->fileName; - m_anchor = sec->label; - if (g_sectionDict && g_sectionDict->find(m_target)==0) - { - g_sectionDict->append(m_target,sec); - } + m_file = sec->fileName(); + m_anchor = sec->label(); } else { warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to unknown section %s", qPrint(m_target)); } - } + } else { warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to empty target"); } - + DBG(("DocSecRefItem::parse() end\n")); DocNode *n = g_nodeStack.pop(); ASSERT(n==this); @@ -2333,7 +2321,7 @@ void DocSecRefList::parse() { case CMD_SECREFITEM: { - int tok=doctokenizerYYlex(); + tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\refitem command"); @@ -2381,14 +2369,14 @@ endsecreflist: //--------------------------------------------------------------------------- -DocInternalRef::DocInternalRef(DocNode *parent,const QCString &ref) +DocInternalRef::DocInternalRef(DocNode *parent,const QCString &ref) : m_relPath(g_relPath) { - m_parent = parent; + m_parent = parent; int i=ref.find('#'); if (i!=-1) { - m_anchor = ref.right(ref.length()-i-1); + m_anchor = ref.right((int)ref.length()-i-1); m_file = ref.left(i); } else @@ -2419,38 +2407,38 @@ void DocInternalRef::parse() //--------------------------------------------------------------------------- -DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : +DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : m_refType(Unknown), m_isSubPage(FALSE) { - m_parent = parent; + m_parent = parent; const Definition *compound = 0; QCString anchor; //printf("DocRef::DocRef(target=%s,context=%s)\n",target.data(),context.data()); ASSERT(!target.isEmpty()); SrcLangExt lang = getLanguageFromFileName(target); m_relPath = g_relPath; - SectionInfo *sec = Doxygen::sectionDict->find(target); + const SectionInfo *sec = SectionManager::instance().find(target); if (sec==0 && lang==SrcLangExt_Markdown) // lookup as markdown file { - sec = Doxygen::sectionDict->find(markdownFileNameToId(target)); + sec = SectionManager::instance().find(markdownFileNameToId(target)); } if (sec) // ref to section or anchor { PageDef *pd = 0; - if (sec->type==SectionInfo::Page) + if (sec->type()==SectionType::Page) { pd = Doxygen::pageSDict->find(target); } - m_text = sec->title; - if (m_text.isEmpty()) m_text = sec->label; + m_text = sec->title(); + if (m_text.isEmpty()) m_text = sec->label(); - m_ref = sec->ref; - m_file = stripKnownExtensions(sec->fileName); - if (sec->type==SectionInfo::Anchor) + m_ref = sec->ref(); + m_file = stripKnownExtensions(sec->fileName()); + if (sec->type()==SectionType::Anchor) { m_refType = Anchor; } - else if (sec->type==SectionInfo::Table) + else if (sec->type()==SectionType::Table) { m_refType = Table; } @@ -2459,16 +2447,16 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : m_refType = Section; } m_isSubPage = pd && pd->hasParentPage(); - if (sec->type!=SectionInfo::Page || m_isSubPage) m_anchor = sec->label; + if (sec->type()!=SectionType::Page || m_isSubPage) m_anchor = sec->label(); //printf("m_text=%s,m_ref=%s,m_file=%s,m_refToAnchor=%d type=%d\n", // m_text.data(),m_ref.data(),m_file.data(),m_refToAnchor,sec->type); return; } else if (resolveLink(context,target,TRUE,&compound,anchor)) { - bool isFile = compound ? + bool isFile = compound ? (compound->definitionType()==Definition::TypeFile || - compound->definitionType()==Definition::TypePage ? TRUE : FALSE) : + compound->definitionType()==Definition::TypePage ? TRUE : FALSE) : FALSE; m_text = linkToText(compound?compound->getLanguage():SrcLangExt_Unknown,target,isFile); m_anchor = anchor; @@ -2507,7 +2495,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : } m_text = target; warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to '%s' for \\ref command", - qPrint(target)); + qPrint(target)); } static void flattenParagraphs(DocNode *root,QList<DocNode> &children) @@ -2571,7 +2559,7 @@ void DocRef::parse() } handlePendingStyleCommands(this,m_children); - + DocNode *n=g_nodeStack.pop(); ASSERT(n==this); } @@ -2580,19 +2568,20 @@ void DocRef::parse() DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //context) { - static uint numBibFiles = Config_getList(CITE_BIB_FILES).count(); + size_t numBibFiles = Config_getList(CITE_BIB_FILES).size(); m_parent = parent; //printf("DocCite::DocCite(target=%s)\n",target.data()); ASSERT(!target.isEmpty()); m_relPath = g_relPath; - CiteInfo *cite = Doxygen::citeDict->find(target); + const CitationManager &ct = CitationManager::instance(); + const CiteInfo *cite = ct.find(target); //printf("cite=%p text='%s' numBibFiles=%d\n",cite,cite?cite->text.data():"<null>",numBibFiles); - if (numBibFiles>0 && cite && !cite->text.isEmpty()) // ref to citation + if (numBibFiles>0 && cite && !cite->text().isEmpty()) // ref to citation { - m_text = cite->text; - m_ref = cite->ref; - m_anchor = CiteConsts::anchorPrefix+cite->label; - m_file = convertNameToFile(CiteConsts::fileName,FALSE,TRUE); + m_text = cite->text(); + m_ref = ""; + m_anchor = ct.anchorPrefix()+cite->label(); + m_file = convertNameToFile(ct.fileName(),FALSE,TRUE); //printf("CITE ==> m_text=%s,m_ref=%s,m_file=%s,m_anchor=%s\n", // m_text.data(),m_ref.data(),m_file.data(),m_anchor.data()); return; @@ -2616,7 +2605,7 @@ DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //cont //--------------------------------------------------------------------------- -DocLink::DocLink(DocNode *parent,const QCString &target) +DocLink::DocLink(DocNode *parent,const QCString &target) { m_parent = parent; const Definition *compound = 0; @@ -2648,7 +2637,7 @@ DocLink::DocLink(DocNode *parent,const QCString &target) // bogus link target warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve link to '%s' for \\link command", - qPrint(target)); + qPrint(target)); } @@ -2684,7 +2673,7 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) break; } break; - case TK_SYMBOL: + case TK_SYMBOL: warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found as part of a \\link", qPrint(g_token->name)); break; @@ -2695,8 +2684,8 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) qPrint(g_token->name)); } goto endlink; - case TK_LNKWORD: - case TK_WORD: + case TK_LNKWORD: + case TK_WORD: if (isJavaLink) // special case to detect closing } { QCString w = g_token->name; @@ -2711,7 +2700,7 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) m_children.append(new DocWord(this,w.left(p))); if ((uint)p<l-1) // something left after the } (for instance a .) { - result=w.right(l-p-1); + result=w.right((int)l-p-1); } goto endlink; } @@ -2728,7 +2717,7 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" - " link command\n"); + " link command\n"); } endlink: @@ -2747,10 +2736,10 @@ endlink: //--------------------------------------------------------------------------- -DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &context) : +DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &context) : m_name(name), m_relPath(g_relPath), m_context(context) { - m_parent = parent; + m_parent = parent; } bool DocDotFile::parse() @@ -2759,10 +2748,10 @@ bool DocDotFile::parse() defaultHandleTitleAndSize(CMD_DOTFILE,this,m_children,m_width,m_height); bool ambig; - FileDef *fd = findFileDef(Doxygen::dotFileNameDict,m_name,ambig); + FileDef *fd = findFileDef(Doxygen::dotFileNameLinkedMap,m_name,ambig); if (fd==0 && m_name.right(4)!=".dot") // try with .dot extension as well { - fd = findFileDef(Doxygen::dotFileNameDict,m_name+".dot",ambig); + fd = findFileDef(Doxygen::dotFileNameLinkedMap,m_name+".dot",ambig); } if (fd) { @@ -2772,7 +2761,7 @@ bool DocDotFile::parse() { warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), - qPrint(showFileDefMatches(Doxygen::dotFileNameDict,m_name)) + qPrint(showFileDefMatches(Doxygen::dotFileNameLinkedMap,m_name)) ); } } @@ -2784,10 +2773,10 @@ bool DocDotFile::parse() return ok; } -DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) : +DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) : m_name(name), m_relPath(g_relPath), m_context(context) { - m_parent = parent; + m_parent = parent; } bool DocMscFile::parse() @@ -2796,10 +2785,10 @@ bool DocMscFile::parse() defaultHandleTitleAndSize(CMD_MSCFILE,this,m_children,m_width,m_height); bool ambig; - FileDef *fd = findFileDef(Doxygen::mscFileNameDict,m_name,ambig); + FileDef *fd = findFileDef(Doxygen::mscFileNameLinkedMap,m_name,ambig); if (fd==0 && m_name.right(4)!=".msc") // try with .msc extension as well { - fd = findFileDef(Doxygen::mscFileNameDict,m_name+".msc",ambig); + fd = findFileDef(Doxygen::mscFileNameLinkedMap,m_name+".msc",ambig); } if (fd) { @@ -2809,7 +2798,7 @@ bool DocMscFile::parse() { warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), - qPrint(showFileDefMatches(Doxygen::mscFileNameDict,m_name)) + qPrint(showFileDefMatches(Doxygen::mscFileNameLinkedMap,m_name)) ); } } @@ -2835,10 +2824,10 @@ bool DocDiaFile::parse() defaultHandleTitleAndSize(CMD_DIAFILE,this,m_children,m_width,m_height); bool ambig; - FileDef *fd = findFileDef(Doxygen::diaFileNameDict,m_name,ambig); + FileDef *fd = findFileDef(Doxygen::diaFileNameLinkedMap,m_name,ambig); if (fd==0 && m_name.right(4)!=".dia") // try with .dia extension as well { - fd = findFileDef(Doxygen::diaFileNameDict,m_name+".dia",ambig); + fd = findFileDef(Doxygen::diaFileNameLinkedMap,m_name+".dia",ambig); } if (fd) { @@ -2848,7 +2837,7 @@ bool DocDiaFile::parse() { warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), - qPrint(showFileDefMatches(Doxygen::diaFileNameDict,m_name)) + qPrint(showFileDefMatches(Doxygen::diaFileNameLinkedMap,m_name)) ); } } @@ -2907,7 +2896,7 @@ DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString bool DocImage::isSVG() const { QCString locName = m_url.isEmpty() ? m_name : m_url; - int len = locName.length(); + int len = (int)locName.length(); int fnd = locName.find('?'); // ignore part from ? until end if (fnd==-1) fnd=len; return fnd>=4 && locName.mid(fnd-4,4)==".svg"; @@ -2942,7 +2931,7 @@ int DocHtmlHeader::parse() if (m_level!=1) { warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h1>", - m_level); + m_level); } goto endheader; } @@ -2951,7 +2940,7 @@ int DocHtmlHeader::parse() if (m_level!=2) { warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h2>", - m_level); + m_level); } goto endheader; } @@ -2960,7 +2949,7 @@ int DocHtmlHeader::parse() if (m_level!=3) { warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h3>", - m_level); + m_level); } goto endheader; } @@ -2969,7 +2958,7 @@ int DocHtmlHeader::parse() if (m_level!=4) { warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h4>", - m_level); + m_level); } goto endheader; } @@ -2978,7 +2967,7 @@ int DocHtmlHeader::parse() if (m_level!=5) { warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h5>", - m_level); + m_level); } goto endheader; } @@ -2987,7 +2976,7 @@ int DocHtmlHeader::parse() if (m_level!=6) { warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h6>", - m_level); + m_level); } goto endheader; } @@ -3020,7 +3009,7 @@ int DocHtmlHeader::parse() if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" - " <h%d> tag\n",m_level); + " <h%d> tag\n",m_level); } endheader: handlePendingStyleCommands(this,m_children); @@ -3055,7 +3044,7 @@ int DocHRef::parse() else { warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <a href=...> context", - g_token->endTag?"/":"",qPrint(g_token->name),doctokenizerYYlineno); + g_token->endTag?"/":"",qPrint(g_token->name)); } } break; @@ -3068,7 +3057,7 @@ int DocHRef::parse() if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" - " <a href=...> tag",doctokenizerYYlineno); + " <a href=...> tag"); } endhref: handlePendingStyleCommands(this,m_children); @@ -3094,7 +3083,7 @@ int DocInternal::parse(int level) DocPara *par = new DocPara(this); if (isFirst) { par->markFirst(); isFirst=FALSE; } retval=par->parse(); - if (!par->isEmpty()) + if (!par->isEmpty()) { m_children.append(par); lastPar=par; @@ -3105,9 +3094,9 @@ int DocInternal::parse(int level) } if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found",doctokenizerYYlineno); + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); } - } while (retval!=0 && + } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Subsection && retval!=RetVal_Subsubsection && @@ -3117,7 +3106,7 @@ int DocInternal::parse(int level) if (lastPar) lastPar->markLast(); // then parse any number of level-n sections - while ((level==1 && retval==RetVal_Section) || + while ((level==1 && retval==RetVal_Section) || (level==2 && retval==RetVal_Subsection) || (level==3 && retval==RetVal_Subsubsection) || (level==4 && retval==RetVal_Paragraph) @@ -3162,8 +3151,8 @@ int DocIndexEntry::parse() case TK_WHITESPACE: m_entry+=" "; break; - case TK_WORD: - case TK_LNKWORD: + case TK_WORD: + case TK_LNKWORD: m_entry+=g_token->name; break; case TK_SYMBOL: @@ -3246,18 +3235,13 @@ DocHtmlCaption::DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs) { if (opt->name=="id" && !opt->value.isEmpty()) // interpret id attribute as an anchor { - SectionInfo *sec = Doxygen::sectionDict->find(opt->value); + const SectionInfo *sec = SectionManager::instance().find(opt->value); if (sec) { //printf("Found anchor %s\n",id.data()); - m_file = sec->fileName; - m_anchor = sec->label; + m_file = sec->fileName(); + m_anchor = sec->label(); m_hasCaptionId = TRUE; - if (g_sectionDict && g_sectionDict->find(opt->value)==0) - { - //printf("Inserting in dictionary!\n"); - g_sectionDict->append(opt->value,sec); - } } else { @@ -3308,7 +3292,7 @@ int DocHtmlCaption::parse() if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" - " <caption> tag",doctokenizerYYlineno); + " <caption> tag"); } endcaption: handlePendingStyleCommands(this,m_children); @@ -3394,32 +3378,32 @@ int DocHtmlCell::parseXml() return retval; } -int DocHtmlCell::rowSpan() const +uint DocHtmlCell::rowSpan() const { - int retval = 0; + uint retval = 0; HtmlAttribList attrs = attribs(); uint i; - for (i=0; i<attrs.count(); ++i) + for (i=0; i<attrs.count(); ++i) { if (attrs.at(i)->name.lower()=="rowspan") { - retval = attrs.at(i)->value.toInt(); + retval = attrs.at(i)->value.toUInt(); break; } } return retval; } -int DocHtmlCell::colSpan() const +uint DocHtmlCell::colSpan() const { - int retval = 1; + uint retval = 1; HtmlAttribList attrs = attribs(); uint i; - for (i=0; i<attrs.count(); ++i) + for (i=0; i<attrs.count(); ++i) { if (attrs.at(i)->name.lower()=="colspan") { - retval = QMAX(1,attrs.at(i)->value.toInt()); + retval = QMAX(1,attrs.at(i)->value.toUInt()); break; } } @@ -3602,7 +3586,7 @@ int DocHtmlTable::parse() int retval=RetVal_OK; g_nodeStack.push(this); DBG(("DocHtmlTable::parse() start\n")); - + getrow: // get next token int tok=doctokenizerYYlex(); @@ -3650,14 +3634,14 @@ getrow: warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> tag but found %s token instead!", tokToString(tok)); } - + // parse one or more rows while (retval==RetVal_TableRow) { DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs); m_children.append(tr); retval=tr->parse(); - } + } computeTableGrid(); @@ -3672,7 +3656,7 @@ int DocHtmlTable::parseXml() int retval=RetVal_OK; g_nodeStack.push(this); DBG(("DocHtmlTable::parseXml() start\n")); - + // get next token int tok=doctokenizerYYlex(); // skip whitespace @@ -3701,7 +3685,7 @@ int DocHtmlTable::parseXml() m_children.append(tr); retval=tr->parseXml(isHeader); isHeader=FALSE; - } + } computeTableGrid(); @@ -3715,9 +3699,9 @@ int DocHtmlTable::parseXml() /** Helper class to compute the grid for an HTML style table */ struct ActiveRowSpan { - ActiveRowSpan(int rows,int col) : rowsLeft(rows), column(col) {} - int rowsLeft; - int column; + ActiveRowSpan(uint rows,uint col) : rowsLeft(rows), column(col) {} + uint rowsLeft; + uint column; }; /** List of ActiveRowSpan classes. */ @@ -3732,14 +3716,14 @@ void DocHtmlTable::computeTableGrid() //printf("computeTableGrid()\n"); RowSpanList rowSpans; rowSpans.setAutoDelete(TRUE); - int maxCols=0; - int rowIdx=1; + uint maxCols=0; + uint rowIdx=1; QListIterator<DocNode> li(children()); DocNode *rowNode; for (li.toFirst();(rowNode=li.current());++li) { - int colIdx=1; - int cells=0; + uint colIdx=1; + uint cells=0; if (rowNode->kind()==DocNode::Kind_HtmlRow) { uint i; @@ -3751,13 +3735,13 @@ void DocHtmlTable::computeTableGrid() if (cellNode->kind()==DocNode::Kind_HtmlCell) { DocHtmlCell *cell = (DocHtmlCell*)cellNode; - int rs = cell->rowSpan(); - int cs = cell->colSpan(); + uint rs = cell->rowSpan(); + uint cs = cell->colSpan(); for (i=0;i<rowSpans.count();i++) { - if (rowSpans.at(i)->rowsLeft>0 && - rowSpans.at(i)->column==colIdx) + if (rowSpans.at(i)->rowsLeft>0 && + rowSpans.at(i)->column==colIdx) { colIdx=rowSpans.at(i)->column+1; cells++; @@ -3767,7 +3751,7 @@ void DocHtmlTable::computeTableGrid() //printf("found cell at (%d,%d)\n",rowIdx,colIdx); cell->setRowIndex(rowIdx); cell->setColumnIndex(colIdx); - colIdx+=cs; + colIdx+=cs; cells++; } } @@ -3784,9 +3768,9 @@ void DocHtmlTable::computeTableGrid() m_numCols = maxCols; } -void DocHtmlTable::accept(DocVisitor *v) -{ - v->visitPre(this); +void DocHtmlTable::accept(DocVisitor *v) +{ + v->visitPre(this); // for HTML output we put the caption first //if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v); // doxygen 1.8.11: always put the caption first @@ -3796,7 +3780,7 @@ void DocHtmlTable::accept(DocVisitor *v) for (cli.toFirst();(n=cli.current());++cli) n->accept(v); // for other output formats we put the caption last //if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v); - v->visitPost(this); + v->visitPost(this); } //--------------------------------------------------------------------------- @@ -3826,7 +3810,7 @@ int DocHtmlDescTitle::parse() { case CMD_REF: { - int tok=doctokenizerYYlex(); + tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", @@ -3856,7 +3840,7 @@ int DocHtmlDescTitle::parse() // fall through case CMD_LINK: { - int tok=doctokenizerYYlex(); + tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", @@ -3892,7 +3876,7 @@ int DocHtmlDescTitle::parse() } } break; - case TK_SYMBOL: + case TK_SYMBOL: warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol \\%s found as part of a <dt> tag", qPrint(g_token->name)); break; @@ -3943,7 +3927,7 @@ int DocHtmlDescTitle::parse() if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" - " <dt> tag"); + " <dt> tag"); } endtitle: handlePendingStyleCommands(this,m_children); @@ -3973,7 +3957,7 @@ int DocHtmlDescData::parse() } while (retval==TK_NEWPARA); if (par) par->markLast(); - + DBG(("DocHtmlDescData::parse() end\n")); DocNode *n=g_nodeStack.pop(); ASSERT(n==this); @@ -4178,7 +4162,7 @@ int DocHtmlList::parse() m_children.append(li); retval=li->parse(); } while (retval==RetVal_ListItem); - + if (retval==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <%cl> block", @@ -4241,7 +4225,7 @@ int DocHtmlList::parseXml() if (retval==0) break; //printf("retval=%x g_token->name=%s\n",retval,qPrint(g_token->name)); } while (retval==RetVal_ListItem); - + if (retval==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <list type=\"%s\"> block", @@ -4252,8 +4236,8 @@ endlist: DBG(("DocHtmlList::parseXml() end retval=%x\n",retval)); DocNode *n=g_nodeStack.pop(); ASSERT(n==this); - return retval==RetVal_EndList || - (retval==RetVal_CloseXml || g_token->name=="list") ? + return retval==RetVal_EndList || + (retval==RetVal_CloseXml || g_token->name=="list") ? RetVal_OK : retval; } @@ -4265,7 +4249,7 @@ int DocHtmlBlockQuote::parse() int retval=0; g_nodeStack.push(this); - // parse one or more paragraphs + // parse one or more paragraphs bool isFirst=TRUE; DocPara *par=0; do @@ -4292,7 +4276,7 @@ int DocParBlock::parse() int retval=0; g_nodeStack.push(this); - // parse one or more paragraphs + // parse one or more paragraphs bool isFirst=TRUE; DocPara *par=0; do @@ -4343,17 +4327,17 @@ int DocSimpleList::parse() //-------------------------------------------------------------------------- -DocAutoListItem::DocAutoListItem(DocNode *parent,int indent,int num) +DocAutoListItem::DocAutoListItem(DocNode *parent,int indent,int num) : m_indent(indent), m_itemNum(num) -{ - m_parent = parent; +{ + m_parent = parent; } int DocAutoListItem::parse() { int retval = RetVal_OK; g_nodeStack.push(this); - + // first parse any number of paragraphs bool isFirst=TRUE; DocPara *lastPar=0; @@ -4362,7 +4346,7 @@ int DocAutoListItem::parse() DocPara *par = new DocPara(this); if (isFirst) { par->markFirst(); isFirst=FALSE; } retval=par->parse(); - if (!par->isEmpty()) + if (!par->isEmpty()) { m_children.append(par); if (lastPar) lastPar->markLast(FALSE); @@ -4386,11 +4370,11 @@ int DocAutoListItem::parse() //-------------------------------------------------------------------------- DocAutoList::DocAutoList(DocNode *parent,int indent,bool isEnumList, - int depth) : + int depth) : m_indent(indent), m_isEnumList(isEnumList), m_depth(depth) -{ - m_parent = parent; +{ + m_parent = parent; } int DocAutoList::parse() @@ -4410,11 +4394,11 @@ int DocAutoList::parse() m_children.append(li); retval=li->parse(); //printf("DocAutoList::parse(): retval=0x%x g_token->indent=%d m_indent=%d " - // "m_isEnumList=%d g_token->isEnumList=%d g_token->name=%s\n", + // "m_isEnumList=%d g_token->isEnumList=%d g_token->name=%s\n", // retval,g_token->indent,m_indent,m_isEnumList,g_token->isEnumList, // g_token->name.data()); //printf("num=%d g_token->id=%d\n",num,g_token->id); - } + } while (retval==TK_LISTITEM && // new list item m_indent==g_token->indent && // at same indent level m_isEnumList==g_token->isEnumList && // of the same kind @@ -4456,16 +4440,16 @@ void DocTitle::parseFromString(const QCString &text) //-------------------------------------------------------------------------- -DocSimpleSect::DocSimpleSect(DocNode *parent,Type t) : +DocSimpleSect::DocSimpleSect(DocNode *parent,Type t) : m_type(t) -{ - m_parent = parent; - m_title=0; +{ + m_parent = parent; + m_title=0; } DocSimpleSect::~DocSimpleSect() -{ - delete m_title; +{ + delete m_title; } void DocSimpleSect::accept(DocVisitor *v) @@ -4489,10 +4473,10 @@ int DocSimpleSect::parse(bool userTitle,bool needsSeparator) m_title = new DocTitle(this); m_title->parse(); } - + // add new paragraph as child DocPara *par = new DocPara(this); - if (m_children.isEmpty()) + if (m_children.isEmpty()) { par->markFirst(); } @@ -4504,7 +4488,7 @@ int DocSimpleSect::parse(bool userTitle,bool needsSeparator) par->markLast(); if (needsSeparator) m_children.append(new DocSimpleSectSep(this)); m_children.append(par); - + // parse the contents of the paragraph int retval = par->parse(); @@ -4530,7 +4514,7 @@ int DocSimpleSect::parseRcs() DBG(("DocSimpleSect::parseRcs()\n")); DocNode *n=g_nodeStack.pop(); ASSERT(n==this); - return RetVal_OK; + return RetVal_OK; } int DocSimpleSect::parseXml() @@ -4539,11 +4523,11 @@ int DocSimpleSect::parseXml() g_nodeStack.push(this); int retval = RetVal_OK; - for (;;) + for (;;) { // add new paragraph as child DocPara *par = new DocPara(this); - if (m_children.isEmpty()) + if (m_children.isEmpty()) { par->markFirst(); } @@ -4558,17 +4542,17 @@ int DocSimpleSect::parseXml() // parse the contents of the paragraph retval = par->parse(); if (retval == 0) break; - if (retval == RetVal_CloseXml) + if (retval == RetVal_CloseXml) { retval = RetVal_OK; break; } } - + DBG(("DocSimpleSect::parseXml() end retval=%d\n",retval)); DocNode *n=g_nodeStack.pop(); ASSERT(n==this); - return retval; + return retval; } void DocSimpleSect::appendLinkWord(const QCString &word) @@ -4582,12 +4566,12 @@ void DocSimpleSect::appendLinkWord(const QCString &word) else { p = (DocPara *)m_children.getLast(); - + // Comma-separate <seealso> links. p->injectToken(TK_WORD,","); p->injectToken(TK_WHITESPACE," "); } - + g_inSeeBlock=TRUE; p->injectToken(TK_LNKWORD,word); g_inSeeBlock=FALSE; @@ -4713,7 +4697,7 @@ int DocParamList::parseXml(const QCString ¶mName) g_hasReturnCommand=TRUE; checkRetvalName(g_token->name); } - + handleLinkedWord(this,m_params); do @@ -4742,11 +4726,11 @@ int DocParamList::parseXml(const QCString ¶mName) if (retval == 0) break; - } while (retval==RetVal_CloseXml && + } while (retval==RetVal_CloseXml && Mappers::htmlTagMapper->map(g_token->name)!=XML_PARAM && Mappers::htmlTagMapper->map(g_token->name)!=XML_TYPEPARAM && Mappers::htmlTagMapper->map(g_token->name)!=XML_EXCEPTION); - + if (retval==0) /* premature end of comment block */ { @@ -4802,7 +4786,7 @@ int DocParamSect::parse(const QCString &cmdName,bool xmlContext, Direction d) { retval = RetVal_OK; } - + DBG(("DocParamSect::parse() end retval=%d\n",retval)); DocNode *n=g_nodeStack.pop(); ASSERT(n==this); @@ -4937,7 +4921,7 @@ int DocPara::handleXRefItem() { m_children.append(ref); } - else + else { delete ref; } @@ -5331,7 +5315,7 @@ int DocPara::handleHtmlHeader(const HtmlAttribList &tagHtmlAttribs,int level) // For XML tags whose content is stored in attributes rather than // contained within the element, we need a way to inject the attribute // text into the current paragraph. -bool DocPara::injectToken(int tok,const QCString &tokText) +bool DocPara::injectToken(int tok,const QCString &tokText) { g_token->name = tokText; return defaultHandleToken(this,tok,m_children); @@ -5400,23 +5384,23 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) { case CMD_UNKNOWN: m_children.append(new DocWord(this,TK_COMMAND_CHAR(tok) + cmdName)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unknown command '\\%s'",qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unknown command '%c%s'",TK_COMMAND_CHAR(tok),qPrint(cmdName)); break; case CMD_EMPHASIS: m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,cmdName,TRUE)); - retval=handleStyleArgument(this,m_children,cmdName); + retval=handleStyleArgument(this,m_children,cmdName); m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,cmdName,FALSE)); if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); break; case CMD_BOLD: m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,cmdName,TRUE)); - retval=handleStyleArgument(this,m_children,cmdName); + retval=handleStyleArgument(this,m_children,cmdName); m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,cmdName,FALSE)); if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); break; case CMD_CODE: m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,cmdName,TRUE)); - retval=handleStyleArgument(this,m_children,cmdName); + retval=handleStyleArgument(this,m_children,cmdName); m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,cmdName,FALSE)); if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); break; @@ -5612,7 +5596,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateDbOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker",doctokenizerYYlineno); + if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5702,7 +5686,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) case CMD_ENDMSC: case CMD_ENDUML: warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); - break; + break; case CMD_PARAM: retval = handleParamSection(cmdName,DocParamSect::Param,FALSE,g_token->paramDir); break; @@ -5776,6 +5760,18 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) case CMD_LATEXINCLUDE: handleInclude(cmdName,DocInclude::LatexInclude); break; + case CMD_RTFINCLUDE: + handleInclude(cmdName,DocInclude::RtfInclude); + break; + case CMD_MANINCLUDE: + handleInclude(cmdName,DocInclude::ManInclude); + break; + case CMD_XMLINCLUDE: + handleInclude(cmdName,DocInclude::XmlInclude); + break; + case CMD_DOCBOOKINCLUDE: + handleInclude(cmdName,DocInclude::DocbookInclude); + break; case CMD_VERBINCLUDE: handleInclude(cmdName,DocInclude::VerbInclude); break; @@ -5876,26 +5872,26 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) ASSERT(0); break; } - INTERNAL_ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec || + INTERNAL_ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec || retval==TK_LISTITEM || retval==TK_ENDLIST || retval==TK_NEWPARA || - retval==RetVal_Section || retval==RetVal_EndList || - retval==RetVal_Internal || retval==RetVal_SwitchLang || + retval==RetVal_Section || retval==RetVal_EndList || + retval==RetVal_Internal || retval==RetVal_SwitchLang || retval==RetVal_EndInternal ); DBG(("handleCommand(%s) end retval=%x\n",qPrint(cmdName),retval)); return retval; } -static bool findAttribute(const HtmlAttribList &tagHtmlAttribs, - const char *attrName, - QCString *result) +static bool findAttribute(const HtmlAttribList &tagHtmlAttribs, + const char *attrName, + QCString *result) { HtmlAttribListIterator li(tagHtmlAttribs); HtmlAttrib *opt; for (li.toFirst();(opt=li.current());++li) { - if (opt->name==attrName) + if (opt->name==attrName) { *result = opt->value; return TRUE; @@ -5909,7 +5905,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.count())); int retval=RetVal_OK; int tagId = Mappers::htmlTagMapper->map(tagName); - if (g_token->emptyTag && !(tagId&XML_CmdMask) && + if (g_token->emptyTag && !(tagId&XML_CmdMask) && tagId!=HTML_UNKNOWN && tagId!=HTML_IMG && tagId!=HTML_BR && tagId!=HTML_HR && tagId!=HTML_P) { warn_doc_error(g_fileName,doctokenizerYYlineno,"HTML tag ('<%s/>') may not use the 'empty tag' XHTML syntax.", @@ -5917,7 +5913,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } switch (tagId) { - case HTML_UL: + case HTML_UL: if (!g_token->emptyTag) { DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Unordered); @@ -5925,7 +5921,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta retval=list->parse(); } break; - case HTML_OL: + case HTML_OL: if (!g_token->emptyTag) { DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,DocHtmlList::Ordered); @@ -5964,8 +5960,8 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta break; case HTML_CODE: if (g_token->emptyTag) break; - if (/*getLanguageFromFileName(g_fileName)==SrcLangExt_CSharp ||*/ g_xmlComment) - // for C# source or inside a <summary> or <remark> section we + if (/*getLanguageFromFileName(g_fileName)==SrcLangExt_CSharp ||*/ g_xmlComment) + // for C# source or inside a <summary> or <remark> section we // treat <code> as an XML tag (so similar to @code) { doctokenizerYYsetStateXmlCode(); @@ -6143,7 +6139,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta { //printf("paramName=%s\n",paramName.data()); m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,tagName,TRUE)); - m_children.append(new DocWord(this,paramName)); + m_children.append(new DocWord(this,paramName)); m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,tagName,FALSE)); if (retval!=TK_WORD) m_children.append(new DocWhiteSpace(this," ")); } @@ -6198,7 +6194,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta case XML_SEE: // I'm not sure if <see> is the same as <seealso> or if it // should you link a member without producing a section. The - // C# specification is extremely vague about this (but what else + // C# specification is extremely vague about this (but what else // can we expect from Microsoft...) { QCString cref; @@ -6330,7 +6326,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) int retval=RetVal_OK; switch (tagId) { - case HTML_UL: + case HTML_UL: if (!insideUL(this)) { warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ul> tag without matching <ul>"); @@ -6340,7 +6336,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) retval=RetVal_EndList; } break; - case HTML_OL: + case HTML_OL: if (!insideOL(this)) { warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ol> tag without matching <ol>"); @@ -6558,8 +6554,8 @@ reparsetoken: DocNode::Kind k; if (insidePRE(this) || // all whitespace is relevant ( - // remove leading whitespace - !m_children.isEmpty() && + // remove leading whitespace + !m_children.isEmpty() && // and whitespace after certain constructs (k=m_children.getLast()->kind())!=DocNode::Kind_HtmlDescList && k!=DocNode::Kind_HtmlTable && @@ -6588,7 +6584,7 @@ reparsetoken: { DocAutoList *al = (DocAutoList *)n; DBG(("previous list item at %d\n",al->indent())); - if (al->indent()>=g_token->indent) + if (al->indent()>=g_token->indent) // new item at the same or lower indent level { retval=TK_LISTITEM; @@ -6599,9 +6595,9 @@ reparsetoken: // determine list depth int depth = 0; n=parent(); - while(n) + while(n) { - if (n->kind() == DocNode::Kind_AutoList && + if (n->kind() == DocNode::Kind_AutoList && ((DocAutoList*)n)->isEnumList()) depth++; n=n->parent(); } @@ -6654,7 +6650,7 @@ reparsetoken: } } break; - case TK_ENDLIST: + case TK_ENDLIST: DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno)); if (parent()->kind()==DocNode::Kind_AutoListItem) { @@ -6685,10 +6681,10 @@ reparsetoken: // see if we have to start a simple section int cmd = Mappers::cmdMapper->map(g_token->name); DocNode *n=parent(); - while (n && - n->kind()!=DocNode::Kind_SimpleSect && + while (n && + n->kind()!=DocNode::Kind_SimpleSect && n->kind()!=DocNode::Kind_ParamSect - ) + ) { n=n->parent(); } @@ -6739,25 +6735,25 @@ reparsetoken: DBG(("reparsing command %s\n",qPrint(g_token->name))); goto reparsetoken; } - else if (retval==RetVal_OK) + else if (retval==RetVal_OK) { // the command ended normally, keep scanning for new tokens. retval = 0; } else if (retval>0 && retval<RetVal_OK) - { + { // the command ended with a new command, reparse this token tok = retval; goto reparsetoken; } - else // end of file, end of paragraph, start or end of section + else // end of file, end of paragraph, start or end of section // or some auto list marker { goto endparagraph; } } break; - case TK_HTMLTAG: + case TK_HTMLTAG: { if (!g_token->endTag) // found a start tag { @@ -6767,7 +6763,7 @@ reparsetoken: { retval = handleHtmlEndTag(g_token->name); } - if (retval==RetVal_OK) + if (retval==RetVal_OK) { // the command ended normally, keep scanner for new tokens. retval = 0; @@ -6778,7 +6774,7 @@ reparsetoken: } } break; - case TK_SYMBOL: + case TK_SYMBOL: { DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name); if (s!=DocSymbol::Sym_Unknown) @@ -6792,16 +6788,16 @@ reparsetoken: } break; } - case TK_NEWPARA: + case TK_NEWPARA: retval=TK_NEWPARA; goto endparagraph; case TK_RCSTAG: { DocNode *n=parent(); - while (n && - n->kind()!=DocNode::Kind_SimpleSect && + while (n && + n->kind()!=DocNode::Kind_SimpleSect && n->kind()!=DocNode::Kind_ParamSect - ) + ) { n=n->parent(); } @@ -6838,11 +6834,11 @@ endparagraph: { ((DocPara *)n)->setAttribs(g_token->attribs); } - INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM || - retval==TK_ENDLIST || retval>RetVal_OK + INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM || + retval==TK_ENDLIST || retval>RetVal_OK ); - return retval; + return retval; } //-------------------------------------------------------------------------- @@ -6853,20 +6849,15 @@ int DocSection::parse() int retval=RetVal_OK; g_nodeStack.push(this); - SectionInfo *sec; if (!m_id.isEmpty()) { - sec=Doxygen::sectionDict->find(m_id); + const SectionInfo *sec = SectionManager::instance().find(m_id); if (sec) { - m_file = sec->fileName; - m_anchor = sec->label; - m_title = sec->title; - if (m_title.isEmpty()) m_title = sec->label; - if (g_sectionDict && g_sectionDict->find(m_id)==0) - { - g_sectionDict->append(m_id,sec); - } + m_file = sec->fileName(); + m_anchor = sec->label(); + m_title = sec->title(); + if (m_title.isEmpty()) m_title = sec->label(); } } @@ -6878,7 +6869,7 @@ int DocSection::parse() DocPara *par = new DocPara(this); if (isFirst) { par->markFirst(); isFirst=FALSE; } retval=par->parse(); - if (!par->isEmpty()) + if (!par->isEmpty()) { m_children.append(par); lastPar=par; @@ -6901,7 +6892,7 @@ int DocSection::parse() retval=RetVal_OK; } } - } while (retval!=0 && + } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Subsection && retval!=RetVal_Subsubsection && @@ -6920,7 +6911,6 @@ int DocSection::parse() // then parse any number of nested sections while (retval==RetVal_Subsection) // more sections follow { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; DocSection *s=new DocSection(this, QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); m_children.append(s); @@ -6935,7 +6925,6 @@ int DocSection::parse() // then parse any number of nested sections while (retval==RetVal_Subsubsection) // more sections follow { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; DocSection *s=new DocSection(this, QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); m_children.append(s); @@ -6950,13 +6939,12 @@ int DocSection::parse() // then parse any number of nested sections while (retval==RetVal_Paragraph) // more sections follow { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; DocSection *s=new DocSection(this, QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); m_children.append(s); retval = s->parse(); } - if (!(m_level<Doxygen::subpageNestingLevel+3 && (retval == RetVal_Subsection || retval == RetVal_Subsubsection))) break; + if (!(m_level<Doxygen::subpageNestingLevel+3 && (retval == RetVal_Subsection || retval == RetVal_Subsubsection))) break; } else { @@ -6964,11 +6952,11 @@ int DocSection::parse() } } - INTERNAL_ASSERT(retval==0 || - retval==RetVal_Section || - retval==RetVal_Subsection || - retval==RetVal_Subsubsection || - retval==RetVal_Paragraph || + INTERNAL_ASSERT(retval==0 || + retval==RetVal_Section || + retval==RetVal_Subsection || + retval==RetVal_Subsubsection || + retval==RetVal_Paragraph || retval==RetVal_Internal || retval==RetVal_EndInternal ); @@ -6986,19 +6974,19 @@ void DocText::parse() DBG(("DocText::parse() start\n")); g_nodeStack.push(this); doctokenizerYYsetStateText(); - + int tok; while ((tok=doctokenizerYYlex())) // get the next token { switch(tok) { - case TK_WORD: + case TK_WORD: m_children.append(new DocWord(this,g_token->name)); break; - case TK_WHITESPACE: + case TK_WHITESPACE: m_children.append(new DocWhiteSpace(this,g_token->chars)); break; - case TK_SYMBOL: + case TK_SYMBOL: { DocSymbol::SymType s = DocSymbol::decodeSymbol(g_token->name); if (s!=DocSymbol::Sym_Unknown) @@ -7119,13 +7107,13 @@ void DocRoot::parse() { if (!g_token->sectionId.startsWith("autotoc_md")) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); + warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command (id: '%s') outside of subsubsection context!",qPrint(g_token->sectionId)); } while (retval==RetVal_Paragraph) { if (!g_token->sectionId.isEmpty()) { - SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + const SectionInfo *sec=SectionManager::instance().find(g_token->sectionId); if (sec) { DocSection *s=new DocSection(this, @@ -7149,12 +7137,12 @@ void DocRoot::parse() if (retval==RetVal_Subsubsection) { if (!(g_token->sectionId.startsWith("autotoc_md"))) - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!"); + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command (id: '%s') outside of subsection context!",qPrint(g_token->sectionId)); while (retval==RetVal_Subsubsection) { if (!g_token->sectionId.isEmpty()) { - SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + const SectionInfo *sec=SectionManager::instance().find(g_token->sectionId); if (sec) { DocSection *s=new DocSection(this, @@ -7179,13 +7167,13 @@ void DocRoot::parse() { if (!g_token->sectionId.startsWith("autotoc_md")) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!"); + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command (id: '%s') outside of section context!",qPrint(g_token->sectionId)); } while (retval==RetVal_Subsection) { if (!g_token->sectionId.isEmpty()) { - SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + const SectionInfo *sec=SectionManager::instance().find(g_token->sectionId); if (sec) { DocSection *s=new DocSection(this, @@ -7225,7 +7213,7 @@ void DocRoot::parse() { if (!g_token->sectionId.isEmpty()) { - SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + const SectionInfo *sec=SectionManager::instance().find(g_token->sectionId); if (sec) { DocSection *s=new DocSection(this, @@ -7273,7 +7261,7 @@ static QCString extractCopyDocId(const char *data, uint &j, uint len) case '\'': insideSQuote=TRUE; break; case ' ': // fall through case '\t': // fall through - case '\n': + case '\n': found=(round==0); break; } @@ -7578,7 +7566,8 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef *md, const char *input,bool indexWords, bool isExample, const char *exampleName, - bool singleLine, bool linkFromIndex) + bool singleLine, bool linkFromIndex, + bool markdownSupport) { //printf("validatingParseDoc(%s,%s)=[%s]\n",ctx?ctx->name().data():"<none>", // md?md->name().data():"<none>", @@ -7592,10 +7581,10 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, docParserPushContext(); if (ctx && ctx!=Doxygen::globalScope && - (ctx->definitionType()==Definition::TypeClass || + (ctx->definitionType()==Definition::TypeClass || ctx->definitionType()==Definition::TypeNamespace - ) - ) + ) + ) { g_context = ctx->name(); } @@ -7633,7 +7622,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, { g_searchUrl=md->getOutputFileBase(); Doxygen::searchIndex->setCurrentDoc( - (md->getLanguage()==SrcLangExt_Fortran ? + (md->getLanguage()==SrcLangExt_Fortran ? theTranslator->trSubprogram(TRUE,TRUE): theTranslator->trMember(TRUE,TRUE))+" "+md->qualifiedName(), g_searchUrl, @@ -7713,8 +7702,8 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, } g_fileName = fileName; - g_relPath = (!linkFromIndex && ctx) ? - QCString(relativePathToRoot(ctx->getOutputFileBase())) : + g_relPath = (!linkFromIndex && ctx) ? + QCString(relativePathToRoot(ctx->getOutputFileBase())) : QCString(""); //printf("ctx->name=%s relPath=%s\n",ctx->name().data(),g_relPath.data()); g_memberDef = md; @@ -7735,8 +7724,8 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, g_retvalsFound.clear(); g_paramsFound.setAutoDelete(FALSE); g_paramsFound.clear(); - g_sectionDict = 0; //sections; - + g_markdownSupport = markdownSupport; + //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine); doctokenizerYYlineno=startLine; uint inpLen=qstrlen(input); @@ -7746,7 +7735,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, inpStr+='\n'; } //printf("processCopyDoc(in='%s' out='%s')\n",input,inpStr.data()); - doctokenizerYYinit(inpStr,g_fileName); + doctokenizerYYinit(inpStr,g_fileName,markdownSupport); // build abstract syntax tree DocRoot *root = new DocRoot(md!=0,singleLine); @@ -7774,7 +7763,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, //printf(">>>>>> end validatingParseDoc(%s,%s)\n",ctx?ctx->name().data():"<none>", // md?md->name().data():"<none>"); - + return root; } @@ -7814,7 +7803,7 @@ DocText *validatingParseText(const char *input) if (input) { doctokenizerYYlineno=1; - doctokenizerYYinit(input,g_fileName); + doctokenizerYYinit(input,g_fileName,Config_getBool(MARKDOWN_SUPPORT)); // build abstract syntax tree txt->parse(); @@ -7839,4 +7828,3 @@ void docFindSections(const char *input, { doctokenizerYYFindSections(input,d,fileName); } - diff --git a/src/docparser.h b/src/docparser.h index b7164d7..1dc6b3f 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -32,7 +32,6 @@ class DocNode; class MemberDef; class Definition; class MemberGroup; -class SectionDict; //--------------------------------------------------------------------------- QString::Direction getTextDirByConfig(const QString &text); @@ -53,7 +52,7 @@ QCString getJsDirEmbeddingChar(QString::Direction textDir); * @param md Member definition to which the documentation belongs. * Can be 0. * @param input String representation of the documentation block. - * @param indexWords Indicates whether or not words should be put in the + * @param indexWords Indicates whether or not words should be put in the * search index. * @param isExample TRUE if the documentation belongs to an example. * @param exampleName Base name of the example file (0 if isExample is FALSE). @@ -62,16 +61,19 @@ QCString getJsDirEmbeddingChar(QString::Direction textDir); * @param linkFromIndex TRUE if the documentation is generated from an * index page. In this case context is not used to determine * the relative path when making a link. + * @param markdownSupport TRUE if the input needs to take markdown markup into + * account. * @returns Root node of the abstract syntax tree. Ownership of the * pointer is handed over to the caller. */ DocRoot *validatingParseDoc(const char *fileName,int startLine, const Definition *context, const MemberDef *md, const char *input,bool indexWords, - bool isExample,const char *exampleName=0, - bool singleLine=FALSE,bool linkFromIndex=FALSE); + bool isExample,const char *exampleName, + bool singleLine,bool linkFromIndex, + bool markdownSupport); -/*! Main entry point for parsing simple text fragments. These +/*! Main entry point for parsing simple text fragments. These * fragments are limited to words, whitespace and symbols. */ DocText *validatingParseText(const char *input); @@ -88,11 +90,11 @@ class DocNode { public: /*! Available node types. */ - enum Kind { Kind_Root = 0, - Kind_Word = 1, - Kind_WhiteSpace = 2, - Kind_Para = 3, - Kind_AutoList = 4, + enum Kind { Kind_Root = 0, + Kind_Word = 1, + Kind_WhiteSpace = 2, + Kind_Para = 3, + Kind_AutoList = 4, Kind_AutoListItem = 5, Kind_Symbol = 6, Kind_URL = 7, @@ -159,7 +161,7 @@ class DocNode /*! Sets a new parent for this node. */ void setParent(DocNode *parent) { m_parent = parent; } - /*! Acceptor function for node visitors. Part of the visitor pattern. + /*! Acceptor function for node visitors. Part of the visitor pattern. * @param v Abstract visitor. */ virtual void accept(DocVisitor *v) = 0; @@ -186,31 +188,31 @@ template<class T> class CompAccept : public DocNode { public: CompAccept() { m_children.setAutoDelete(TRUE); } - void accept(DocVisitor *v) + void accept(DocVisitor *v) { T *obj = dynamic_cast<T *>(this); - v->visitPre(obj); + v->visitPre(obj); QListIterator<DocNode> cli(m_children); DocNode *n; for (cli.toFirst();(n=cli.current());++cli) n->accept(v); - v->visitPost(obj); + v->visitPost(obj); } const QList<DocNode> &children() const { return m_children; } QList<DocNode> &children() { return m_children; } - QString::Direction getTextDir(int nodeIndex) const + QString::Direction getTextDir(uint nodeIndex) const { unsigned char resultDir = QString::DirNeutral; for (uint i = nodeIndex; i < m_children.count(); i++) { DocNode* node = m_children.at(i); QString::Direction nodeDir = node->getTextDir(); - resultDir |= nodeDir; + resultDir |= (unsigned char)nodeDir; if (resultDir == QString::DirMixed) return QString::DirMixed; } return static_cast<QString::Direction>(resultDir); } - QString::Direction getTextBasicDir(int nodeIndex) const + QString::Direction getTextBasicDir(uint nodeIndex) const { for (uint i = nodeIndex; i < m_children.count(); i++) { @@ -229,13 +231,13 @@ template<class T> class CompAccept : public DocNode { return getTextBasicDir(0); } - + protected: QList<DocNode> m_children; }; -/** Node representing a word +/** Node representing a word */ class DocWord : public DocNode { @@ -283,7 +285,7 @@ class DocLinkedWord : public DocNode class DocURL : public DocNode { public: - DocURL(DocNode *parent,const QCString &url,bool isEmail) : + DocURL(DocNode *parent,const QCString &url,bool isEmail) : m_url(url), m_isEmail(isEmail) { m_parent=parent; } QCString url() const { return m_url; } Kind kind() const { return Kind_URL; } @@ -483,7 +485,7 @@ class DocSymbol : public DocNode const char *symb; const PerlType type; }PerlSymb; - DocSymbol(DocNode *parent,SymType s) : + DocSymbol(DocNode *parent,SymType s) : m_symbol(s) { m_parent = parent; } SymType symbol() const { return m_symbol; } Kind kind() const { return Kind_Symbol; } @@ -513,7 +515,7 @@ class DocEmoji : public DocNode class DocWhiteSpace : public DocNode { public: - DocWhiteSpace(DocNode *parent,const QCString &chars) : + DocWhiteSpace(DocNode *parent,const QCString &chars) : m_chars(chars) { m_parent = parent; } Kind kind() const { return Kind_WhiteSpace; } QCString chars() const { return m_chars; } @@ -530,7 +532,7 @@ class DocSeparator : public DocNode m_chars(chars) { m_parent = parent; } Kind kind() const { return Kind_Sep; } QCString chars() const { return m_chars; } - void accept(DocVisitor *v) { } + void accept(DocVisitor *) { } private: QCString m_chars; }; @@ -583,21 +585,21 @@ class DocInclude : public DocNode public: enum Type { Include, DontInclude, VerbInclude, HtmlInclude, LatexInclude, IncWithLines, Snippet , IncludeDoc, SnippetDoc, SnipWithLines, - DontIncWithLines}; + DontIncWithLines, RtfInclude, ManInclude, DocbookInclude, XmlInclude}; DocInclude(DocNode *parent,const QCString &file, const QCString context, Type t, bool isExample,const QCString exampleFile, - const QCString blockId, bool isBlock) : + const QCString blockId, bool isBlock) : m_file(file), m_context(context), m_type(t), - m_isExample(isExample), m_exampleFile(exampleFile), - m_blockId(blockId), m_isBlock(isBlock) { m_parent = parent; } + m_isExample(isExample), m_isBlock(isBlock), + m_exampleFile(exampleFile), m_blockId(blockId) { m_parent = parent; } Kind kind() const { return Kind_Include; } QCString file() const { return m_file; } - QCString extension() const { int i=m_file.findRev('.'); - if (i!=-1) - return m_file.right(m_file.length()-i); - else - return ""; + QCString extension() const { int i=m_file.findRev('.'); + if (i!=-1) + return m_file.right(m_file.length()-(uint)i); + else + return ""; } Type type() const { return m_type; } QCString text() const { return m_text; } @@ -613,9 +615,9 @@ class DocInclude : public DocNode QCString m_file; QCString m_context; QCString m_text; - Type m_type = Include; - bool m_isExample = false; - bool m_isBlock = false; + Type m_type; + bool m_isExample; + bool m_isBlock; QCString m_exampleFile; QCString m_blockId; }; @@ -626,7 +628,7 @@ class DocIncOperator : public DocNode public: enum Type { Line, SkipLine, Skip, Until }; DocIncOperator(DocNode *parent,Type t,const QCString &pat, - const QCString &context,bool isExample,const QCString &exampleFile) : + const QCString &context,bool isExample,const QCString &exampleFile) : m_type(t), m_pattern(pat), m_context(context), m_isFirst(FALSE), m_isLast(FALSE), m_isExample(isExample), m_exampleFile(exampleFile) { m_parent = parent; } @@ -696,7 +698,7 @@ class DocFormula : public DocNode class DocIndexEntry : public DocNode { public: - DocIndexEntry(DocNode *parent,const Definition *scope,const MemberDef *md) + DocIndexEntry(DocNode *parent,const Definition *scope,const MemberDef *md) : m_scope(scope), m_member(md){ m_parent = parent; } Kind kind() const { return Kind_IndexEntry; } int parse(); @@ -963,7 +965,7 @@ class DocHRef : public CompAccept<DocHRef> { public: DocHRef(DocNode *parent,const HtmlAttribList &attribs,const QCString &url, - const QCString &relPath) : + const QCString &relPath) : m_attribs(attribs), m_url(url), m_relPath(relPath) { m_parent = parent; } int parse(); QCString url() const { return m_url; } @@ -981,7 +983,7 @@ class DocHRef : public CompAccept<DocHRef> class DocHtmlHeader : public CompAccept<DocHtmlHeader> { public: - DocHtmlHeader(DocNode *parent,const HtmlAttribList &attribs,int level) : + DocHtmlHeader(DocNode *parent,const HtmlAttribList &attribs,int level) : m_level(level), m_attribs(attribs) { m_parent = parent; } int level() const { return m_level; } Kind kind() const { return Kind_HtmlHeader; } @@ -997,7 +999,7 @@ class DocHtmlHeader : public CompAccept<DocHtmlHeader> class DocHtmlDescTitle : public CompAccept<DocHtmlDescTitle> { public: - DocHtmlDescTitle(DocNode *parent,const HtmlAttribList &attribs) : + DocHtmlDescTitle(DocNode *parent,const HtmlAttribList &attribs) : m_attribs(attribs) { m_parent = parent; } Kind kind() const { return Kind_HtmlDescTitle; } const HtmlAttribList &attribs() const { return m_attribs; } @@ -1026,7 +1028,7 @@ class DocSection : public CompAccept<DocSection> { public: DocSection(DocNode *parent,int level,const QCString &id) : - m_level(level), m_id(id) { m_parent = parent; } + m_level(level), m_id(id) { m_parent = parent; } Kind kind() const { return Kind_Section; } int level() const { return m_level; } QCString title() const { return m_title; } @@ -1047,7 +1049,7 @@ class DocSection : public CompAccept<DocSection> class DocSecRefItem : public CompAccept<DocSecRefItem> { public: - DocSecRefItem(DocNode *parent,const QCString &target) : + DocSecRefItem(DocNode *parent,const QCString &target) : m_target(target) { m_parent = parent; } Kind kind() const { return Kind_SecRefItem; } QCString target() const { return m_target; } @@ -1111,7 +1113,7 @@ class DocHtmlList : public CompAccept<DocHtmlList> { public: enum Type { Unordered, Ordered }; - DocHtmlList(DocNode *parent,const HtmlAttribList &attribs,Type t) : + DocHtmlList(DocNode *parent,const HtmlAttribList &attribs,Type t) : m_type(t), m_attribs(attribs) { m_parent = parent; } Kind kind() const { return Kind_HtmlList; } Type type() const { return m_type; } @@ -1128,8 +1130,8 @@ class DocHtmlList : public CompAccept<DocHtmlList> class DocSimpleSect : public CompAccept<DocSimpleSect> { public: - enum Type - { + enum Type + { Unknown, See, Return, Author, Authors, Version, Since, Date, Note, Warning, Copyright, Pre, Post, Invar, Remark, Attention, User, Rcs }; @@ -1151,7 +1153,7 @@ class DocSimpleSect : public CompAccept<DocSimpleSect> }; /** Node representing a separator between two simple sections of the - * same type. + * same type. */ class DocSimpleSectSep : public DocNode { @@ -1168,16 +1170,16 @@ class DocParamSect : public CompAccept<DocParamSect> { friend class DocParamList; public: - enum Type - { + enum Type + { Unknown, Param, RetVal, Exception, TemplateParam }; enum Direction { In=1, Out=2, InOut=3, Unspecified=0 }; - DocParamSect(DocNode *parent,Type t) - : m_type(t), m_hasInOutSpecifier(FALSE), m_hasTypeSpecifier(FALSE) + DocParamSect(DocNode *parent,Type t) + : m_type(t), m_hasInOutSpecifier(FALSE), m_hasTypeSpecifier(FALSE) { m_parent = parent; } int parse(const QCString &cmdName,bool xmlContext,Direction d); Kind kind() const { return Kind_ParamSect; } @@ -1195,7 +1197,7 @@ class DocParamSect : public CompAccept<DocParamSect> class DocPara : public CompAccept<DocPara> { public: - DocPara(DocNode *parent) : + DocPara(DocNode *parent) : m_isFirst(FALSE), m_isLast(FALSE) { m_parent = parent; } int parse(); Kind kind() const { return Kind_Para; } @@ -1242,12 +1244,12 @@ class DocPara : public CompAccept<DocPara> class DocParamList : public DocNode { public: - DocParamList(DocNode *parent,DocParamSect::Type t,DocParamSect::Direction d) + DocParamList(DocNode *parent,DocParamSect::Type t,DocParamSect::Direction d) : m_type(t), m_dir(d), m_isFirst(TRUE), m_isLast(TRUE) - { m_paragraphs.setAutoDelete(TRUE); - m_params.setAutoDelete(TRUE); + { m_paragraphs.setAutoDelete(TRUE); + m_params.setAutoDelete(TRUE); m_paramTypes.setAutoDelete(TRUE); - m_parent = parent; + m_parent = parent; } virtual ~DocParamList() { } Kind kind() const { return Kind_ParamList; } @@ -1260,12 +1262,12 @@ class DocParamList : public DocNode bool isFirst() const { return m_isFirst; } bool isLast() const { return m_isLast; } void accept(DocVisitor *v) - { - v->visitPre(this); + { + v->visitPre(this); QListIterator<DocPara> cli(m_paragraphs); DocNode *n; for (cli.toFirst();(n=cli.current());++cli) n->accept(v); - v->visitPost(this); + v->visitPost(this); } int parse(const QCString &cmdName); int parseXml(const QCString ¶mName); @@ -1291,9 +1293,9 @@ class DocSimpleListItem : public DocNode Kind kind() const { return Kind_SimpleListItem; } void accept(DocVisitor *v) { - v->visitPre(this); + v->visitPre(this); m_paragraph->accept(v); - v->visitPost(this); + v->visitPost(this); } private: @@ -1304,7 +1306,7 @@ class DocSimpleListItem : public DocNode class DocHtmlListItem : public CompAccept<DocHtmlListItem> { public: - DocHtmlListItem(DocNode *parent,const HtmlAttribList &attribs,int num) : + DocHtmlListItem(DocNode *parent,const HtmlAttribList &attribs,int num) : m_attribs(attribs), m_itemNum(num) { m_parent = parent; } Kind kind() const { return Kind_HtmlListItem; } int itemNumber() const { return m_itemNum; } @@ -1336,10 +1338,8 @@ class DocHtmlCell : public CompAccept<DocHtmlCell> friend class DocHtmlTable; public: enum Alignment { Left, Right, Center }; - DocHtmlCell(DocNode *parent,const HtmlAttribList &attribs,bool isHeading) : - m_isHeading(isHeading), - m_isFirst(FALSE), m_isLast(FALSE), m_attribs(attribs), - m_rowIdx(-1), m_colIdx(-1) { m_parent = parent; } + DocHtmlCell(DocNode *parent,const HtmlAttribList &attribs,bool isHeading) : + m_isHeading(isHeading), m_attribs(attribs) { m_parent = parent; } bool isHeading() const { return m_isHeading; } bool isFirst() const { return m_isFirst; } bool isLast() const { return m_isLast; } @@ -1349,21 +1349,21 @@ class DocHtmlCell : public CompAccept<DocHtmlCell> const HtmlAttribList &attribs() const { return m_attribs; } int parse(); int parseXml(); - int rowIndex() const { return m_rowIdx; } - int columnIndex() const { return m_colIdx; } - int rowSpan() const; - int colSpan() const; + uint rowIndex() const { return m_rowIdx; } + uint columnIndex() const { return m_colIdx; } + uint rowSpan() const; + uint colSpan() const; Alignment alignment() const; private: - void setRowIndex(int idx) { m_rowIdx = idx; } - void setColumnIndex(int idx) { m_colIdx = idx; } + void setRowIndex(uint idx) { m_rowIdx = idx; } + void setColumnIndex(uint idx) { m_colIdx = idx; } bool m_isHeading = false; bool m_isFirst = false; bool m_isLast = false; HtmlAttribList m_attribs; - int m_rowIdx = -1; - int m_colIdx = -1; + uint m_rowIdx = (uint)-1; + uint m_colIdx = (uint)-1; }; /** Node representing a HTML table caption */ @@ -1390,8 +1390,8 @@ class DocHtmlRow : public CompAccept<DocHtmlRow> { friend class DocHtmlTable; public: - DocHtmlRow(DocNode *parent,const HtmlAttribList &attribs) : - m_attribs(attribs), m_visibleCells(-1), m_rowIdx(-1) { m_parent = parent; } + DocHtmlRow(DocNode *parent,const HtmlAttribList &attribs) : + m_attribs(attribs) { m_parent = parent; } Kind kind() const { return Kind_HtmlRow; } uint numCells() const { return m_children.count(); } const HtmlAttribList &attribs() const { return m_attribs; } @@ -1410,22 +1410,22 @@ class DocHtmlRow : public CompAccept<DocHtmlRow> } return m_children.count()>0 && heading; } - void setVisibleCells(int n) { m_visibleCells = n; } - int visibleCells() const { return m_visibleCells; } - int rowIndex() const { return m_rowIdx; } + void setVisibleCells(uint n) { m_visibleCells = n; } + uint visibleCells() const { return m_visibleCells; } + uint rowIndex() const { return m_rowIdx; } private: - void setRowIndex(int idx) { m_rowIdx = idx; } + void setRowIndex(uint idx) { m_rowIdx = idx; } HtmlAttribList m_attribs; - int m_visibleCells = -1; - int m_rowIdx = -1; + uint m_visibleCells = 0; + uint m_rowIdx = (uint)-1; }; /** Node representing a HTML table */ class DocHtmlTable : public CompAccept<DocHtmlTable> { public: - DocHtmlTable(DocNode *parent,const HtmlAttribList &attribs) + DocHtmlTable(DocNode *parent,const HtmlAttribList &attribs) : m_attribs(attribs) { m_caption=0; m_numCols=0; m_parent = parent; } ~DocHtmlTable() { delete m_caption; } Kind kind() const { return Kind_HtmlTable; } @@ -1447,7 +1447,7 @@ class DocHtmlTable : public CompAccept<DocHtmlTable> void computeTableGrid(); DocHtmlCaption *m_caption = 0; HtmlAttribList m_attribs; - int m_numCols = 0; + uint m_numCols = 0; }; /** Node representing an HTML blockquote */ diff --git a/src/docsets.cpp b/src/docsets.cpp index a838923..d92e4f3 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -328,7 +328,6 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, case SrcLangExt_VHDL: lang="vhdl"; break; // VHDL case SrcLangExt_XML: lang="xml"; break; // DBUS XML case SrcLangExt_SQL: lang="sql"; break; // Sql - case SrcLangExt_Tcl: lang="tcl"; break; // Tcl case SrcLangExt_Markdown:lang="markdown"; break; // Markdown case SrcLangExt_Slice: lang="slice"; break; // Slice case SrcLangExt_Unknown: lang="unknown"; break; // should not happen! diff --git a/src/doctokenizer.h b/src/doctokenizer.h index e01f045..f43cd07 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -6,8 +6,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -78,7 +78,7 @@ struct TokenInfo QCString text; // comment blocks - + // list token info bool isEnumList = false; int indent = 0; @@ -124,7 +124,7 @@ const char *tokToString(int token); // operations on the scanner void doctokenizerYYFindSections(const char *input,const Definition *d, const char *fileName); -void doctokenizerYYinit(const char *input,const char *fileName); +void doctokenizerYYinit(const char *input,const char *fileName,bool markdownSupport); void doctokenizerYYcleanup(); void doctokenizerYYpushContext(); bool doctokenizerYYpopContext(); diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 4882570..ac5b6d2 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -18,6 +18,9 @@ %option never-interactive %option prefix="doctokenizerYY" +%top{ +#include <stdint.h> +} %{ @@ -43,6 +46,8 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + #define TK_COMMAND_SEL() (yytext[0] == '@' ? TK_COMMAND_AT : TK_COMMAND_BS) //-------------------------------------------------------------------------- @@ -50,17 +55,18 @@ // context for tokenizer phase static int g_commentState; TokenInfo *g_token = 0; -static int g_inputPos = 0; +static yy_size_t g_inputPos = 0; static const char *g_inputString; static QCString g_fileName; static bool g_insidePre; static int g_sharpCount=0; +static bool g_markdownSupport=TRUE; // context for section finding phase static const Definition *g_definition; static QCString g_secLabel; static QCString g_secTitle; -static SectionInfo::SectionType g_secType; +static SectionType g_secType; static QCString g_endMarker; static int g_autoListLevel; @@ -76,7 +82,9 @@ struct DocLexerContext static QStack<DocLexerContext> g_lexerStack; +#if USE_STATE2STRING static const char *stateToString(int state); +#endif //-------------------------------------------------------------------------- void doctokenizerYYpushContext() @@ -106,6 +114,20 @@ bool doctokenizerYYpopContext() return TRUE; } +QCString extractPartAfterNewLine(const QCString &text) +{ + int nl1 = text.findRev('\n'); + if (nl1!=-1) + { + return text.mid(nl1+1); + } + int nl2 = text.findRev("\\ilinebr"); + if (nl2!=-1) + { + return text.mid(nl2+8); + } + return text; +} //-------------------------------------------------------------------------- @@ -167,11 +189,11 @@ static void processSection() { warn(g_fileName,yylineno,"Found section/anchor %s without context\n",g_secLabel.data()); } - SectionInfo *si=0; - if ((si=Doxygen::sectionDict->find(g_secLabel))) + SectionInfo *si = SectionManager::instance().find(g_secLabel); + if (si) { - si->fileName = file; - si->type = g_secType; + si->setFileName(file); + si->setType(g_secType); } } @@ -320,9 +342,9 @@ static QCString stripEmptyLines(const QCString &s) #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -static int yyread(char *buf,int max_size) +static yy_size_t yyread(char *buf,yy_size_t max_size) { - int c=0; + yy_size_t c=0; const char *src=g_inputString+g_inputPos; while ( c < max_size && *src ) *buf++ = *src++, c++; g_inputPos+=c; @@ -370,7 +392,7 @@ SPCMD2 {CMD}[\\@<>&$#%~".+=|-] SPCMD3 {CMD}_form#[0-9]+ SPCMD4 {CMD}"::" SPCMD5 {CMD}":" -INOUT "inout"|"in"|"out"|("in"{BLANK}*","{BLANK}*"out")|("out"{BLANK}*","{BLANK}*"in") +INOUT "in"|"out"|("in"{BLANK}*","?{BLANK}*"out")|("out"{BLANK}*","?{BLANK}*"in") PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]" VARARGS "..." TEMPCHAR [a-z_A-Z0-9.,: \t\*\&\(\)\[\]] @@ -388,7 +410,7 @@ FUNCARG "("{FUNCPART}")"({BLANK}*("volatile"|"const"){BLANK})? FUNCARG2 "("{FUNCPART}")"({BLANK}*("volatile"|"const"))? OPNEW {BLANK}+"new"({BLANK}*"[]")? OPDEL {BLANK}+"delete"({BLANK}*"[]")? -OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()" +OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()"|"<=>" OPCAST {BLANK}+[^<(\r\n.,][^(\r\n.,]* OPMASK ({BLANK}*{OPNORM}{FUNCARG}) OPMASKOPT ({BLANK}*{OPNORM}{FUNCARG}?)|({OPCAST}{FUNCARG}) @@ -480,7 +502,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } <St_Para>^{MLISTITEM} { /* list item */ - if (!Doxygen::markdownSupport || g_insidePre) + if (!g_markdownSupport || g_insidePre) { REJECT; } @@ -496,7 +518,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } <St_Para>^{OLISTITEM} { /* numbered list item */ - if (!Doxygen::markdownSupport || g_insidePre) + if (!g_markdownSupport || g_insidePre) { REJECT; } @@ -512,25 +534,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>{BLANK}*\n{LISTITEM} { /* list item on next line */ - QCString text=yytext; - text=text.right(text.length()-text.find('\n')-1); +<St_Para>{BLANK}*(\n|"\\ilinebr"){LISTITEM} { /* list item on next line */ + QCString text=extractPartAfterNewLine(yytext); int dashPos = text.findRev('-'); g_token->isEnumList = text.at(dashPos+1)=='#'; g_token->id = -1; g_token->indent = computeIndent(text,dashPos); return TK_LISTITEM; } -<St_Para>{BLANK}*\n{MLISTITEM} { /* list item on next line */ - if (!Doxygen::markdownSupport || g_insidePre) +<St_Para>{BLANK}*(\n|"\\ilinebr"){MLISTITEM} { /* list item on next line */ + if (!g_markdownSupport || g_insidePre) { REJECT; } else { - QCString text=yytext; + QCString text=extractPartAfterNewLine(yytext); static QRegExp re("[*+]"); - text=text.right(text.length()-text.find('\n')-1); int markPos = text.findRev(re); g_token->isEnumList = FALSE; g_token->id = -1; @@ -538,17 +558,14 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>{BLANK}*\n{OLISTITEM} { /* list item on next line */ - if (!Doxygen::markdownSupport || g_insidePre) +<St_Para>{BLANK}*(\n|"\\ilinebr"){OLISTITEM} { /* list item on next line */ + if (!g_markdownSupport || g_insidePre) { REJECT; } else { - QCString text=yytext; - int nl=text.findRev('\n'); - int len=text.length(); - text=text.right(len-nl-1); + QCString text=extractPartAfterNewLine(yytext); static QRegExp re("[1-9]"); int digitPos = text.find(re); int dotPos = text.find('.',digitPos); @@ -563,11 +580,10 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->indent = computeIndent(yytext,dotPos); return TK_ENDLIST; } -<St_Para>{BLANK}*\n{ENDLIST} { /* end list on next line */ - QCString text=yytext; - text=text.right(text.length()-text.find('\n')-1); +<St_Para>{BLANK}*(\n|"\\ilinebr"){ENDLIST} { /* end list on next line */ + QCString text=extractPartAfterNewLine(yytext); int dotPos = text.findRev('.'); - g_token->indent = computeIndent(text,dotPos); + g_token->indent = computeIndent(text,dotPos); return TK_ENDLIST; } <St_Para>"{"{BLANK}*"@link"/{BLANK}+ { @@ -578,9 +594,9 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->name = "inheritdoc"; return TK_COMMAND_AT; } -<St_Para>"@_fakenl" { // artificial new line - yylineno++; - } +<St_Para>"@_fakenl" { // artificial new line + yylineno++; + } <St_Para>{SPCMD3} { g_token->name = "_form"; bool ok; @@ -595,6 +611,8 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); } +<St_Para>"\\ilinebr" { + } <St_Para>{SPCMD1} | <St_Para>{SPCMD2} | <St_Para>{SPCMD5} | @@ -630,7 +648,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } return TK_COMMAND_SEL(); } -<St_Para>{URLPROTOCOL}{URLMASK}/\. { // URL. +<St_Para>{URLPROTOCOL}{URLMASK}/[,\.] { // URL, or URL. g_token->name=yytext; g_token->isEMailAddr=FALSE; return TK_URL; @@ -761,13 +779,13 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } <St_Para>({BLANK}*\n)+{BLANK}*\n/{MLISTITEM} { /* skip trailing paragraph followed by new list item */ - if (!Doxygen::markdownSupport || g_insidePre || g_autoListLevel==0) + if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } } <St_Para>({BLANK}*\n)+{BLANK}*\n/{OLISTITEM} { /* skip trailing paragraph followed by new list item */ - if (!Doxygen::markdownSupport || g_insidePre || g_autoListLevel==0) + if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } @@ -792,9 +810,10 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->name = g_token->name.mid(i+1,g_token->name.length()-i-2); BEGIN(St_Code); } +<St_CodeOpt>"\\ilinebr" | <St_CodeOpt>\n | <St_CodeOpt>. { - unput(*yytext); + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); BEGIN(St_Code); } <St_Code>{WS}*{CMD}"endcode" { @@ -816,6 +835,10 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} unput(*yytext); BEGIN(St_HtmlOnly); } +<St_HtmlOnlyOption>"\\ilinebr" { + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + BEGIN(St_HtmlOnly); + } <St_HtmlOnly>{CMD}"endhtmlonly" { return RetVal_OK; } @@ -907,10 +930,15 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->sectionId = QCString(yytext).stripWhiteSpace(); return RetVal_OK; } +<St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}*/"\\ilinebr" { // case 5: plain file name specified without title or attributes + g_token->sectionId = QCString(yytext).stripWhiteSpace(); + return RetVal_OK; + } +<St_PlantUMLOpt>"\\ilinebr" | <St_PlantUMLOpt>"\n" | <St_PlantUMLOpt>. { g_token->sectionId = ""; - unput(*yytext); + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); return RetVal_OK; } <St_PlantUML>{CMD}"enduml" { @@ -936,12 +964,20 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} unput(*yytext); return 0; } +<St_Title>"\\ilinebr" { + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + return 0; + } <St_TitleN>"&"{ID}";" { /* symbol */ g_token->name = yytext; return TK_SYMBOL; } <St_TitleN>{HTMLTAG} { } +<St_TitleN>(\n|"\\ilinebr") { /* new line => end of title */ + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + return 0; + } <St_TitleN>{SPCMD1} | <St_TitleN>{SPCMD2} { /* special command */ g_token->name = yytext+1; @@ -968,14 +1004,14 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->chars=yytext; return TK_WHITESPACE; } -<St_TitleN>\n { /* new line => end of title */ - unput(*yytext); - return 0; - } <St_TitleQ>"&"{ID}";" { /* symbol */ g_token->name = yytext; return TK_SYMBOL; } +<St_TitleQ>(\n|"\\ilinebr") { /* new line => end of title */ + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + return 0; + } <St_TitleQ>{SPCMD1} | <St_TitleQ>{SPCMD2} { /* special command */ g_token->name = yytext+1; @@ -995,10 +1031,6 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} BEGIN(St_TitleA); return 0; } -<St_TitleQ>\n { /* new line => end of title */ - unput(*yytext); - return 0; - } <St_TitleA>{BLANK}*{ID}{BLANK}*"="{BLANK}* { // title attribute g_token->name = yytext; g_token->name = g_token->name.left(g_token->name.find('=')).stripWhiteSpace(); @@ -1013,8 +1045,8 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} unput(*yytext); return 0; } -<St_TitleV,St_TitleA>\n { - unput(*yytext); +<St_TitleV,St_TitleA>(\n|"\\ilinebr") { + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); return 0; } @@ -1030,7 +1062,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} if (yytext[0] =='"') { g_token->name=yytext+1; - g_token->name=g_token->name.left(yyleng-2); + g_token->name=g_token->name.left(static_cast<uint>(yyleng)-2); } else { @@ -1042,8 +1074,8 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} unput(' '); return 0; } -<St_Cite>\n { // new line - unput(*yytext); +<St_Cite>(\n|"\\ilinebr") { // new line + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); return 0; } <St_Cite>. { // any other character @@ -1069,8 +1101,8 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_Ref>{WS}+"\""{WS}* { // white space following by quoted string BEGIN(St_Ref2); } -<St_Ref>\n { // new line - unput(*yytext); +<St_Ref>(\n|"\\ilinebr") { // new line + for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); return 0; } <St_Ref>. { // any other character @@ -1116,6 +1148,9 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->name = yytext; return TK_SYMBOL; } +<St_Ref2>"\""|\n|"\\ilinebr" { /* " or \n => end of title */ + return 0; + } <St_Ref2>{SPCMD1} | <St_Ref2>{SPCMD2} { /* special command */ g_token->name = yytext+1; @@ -1132,9 +1167,6 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->chars=yytext; return TK_WHITESPACE; } -<St_Ref2>"\""|\n { /* " or \n => end of title */ - return 0; - } <St_XRefItem>{LABELID} { g_token->name=yytext; } @@ -1167,9 +1199,9 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } <St_Param>[^ \t\n,@\\]+ { g_token->name = yytext; - if (g_token->name.at(yyleng-1)==':') + if (g_token->name.at(static_cast<uint>(yyleng)-1)==':') { - g_token->name=g_token->name.left(yyleng-1); + g_token->name=g_token->name.left(static_cast<uint>(yyleng)-1); } return TK_WORD; } @@ -1228,7 +1260,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} /* State for skipping title (all chars until the end of the line) */ <St_SkipTitle>. -<St_SkipTitle>\n { return 0; } +<St_SkipTitle>(\n|"\\ilinebr") { return 0; } /* State for the pass used to find the anchors and sections */ @@ -1245,7 +1277,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} int e=tag.find(c,s+4); if (e!=-1) // found matching end { - g_secType = SectionInfo::Table; + g_secType = SectionType::Table; g_secLabel=tag.mid(s+4,e-s-4); // extract id processSection(); } @@ -1253,23 +1285,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } <St_Sections>{CMD}"anchor"{BLANK}+ { - g_secType = SectionInfo::Anchor; + g_secType = SectionType::Anchor; BEGIN(St_SecLabel1); } <St_Sections>{CMD}"section"{BLANK}+ { - g_secType = SectionInfo::Section; + g_secType = SectionType::Section; BEGIN(St_SecLabel2); } <St_Sections>{CMD}"subsection"{BLANK}+ { - g_secType = SectionInfo::Subsection; + g_secType = SectionType::Subsection; BEGIN(St_SecLabel2); } <St_Sections>{CMD}"subsubsection"{BLANK}+ { - g_secType = SectionInfo::Subsubsection; + g_secType = SectionType::Subsubsection; BEGIN(St_SecLabel2); } <St_Sections>{CMD}"paragraph"{BLANK}+ { - g_secType = SectionInfo::Paragraph; + g_secType = SectionType::Paragraph; BEGIN(St_SecLabel2); } <St_Sections>{CMD}"verbatim"/[^a-z_A-Z0-9] { @@ -1296,6 +1328,14 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_endMarker="endlatexonly"; BEGIN(St_SecSkip); } +<St_Sections>{CMD}"manonly"/[^a-z_A-Z0-9] { + g_endMarker="endmanonly"; + BEGIN(St_SecSkip); + } +<St_Sections>{CMD}"rtfonly"/[^a-z_A-Z0-9] { + g_endMarker="endrtfonly"; + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"xmlonly"/[^a-z_A-Z0-9] { g_endMarker="endxmlonly"; BEGIN(St_SecSkip); @@ -1326,9 +1366,9 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } <St_SecSkip>[^a-z_A-Z0-9\-\\\@]+ <St_SecSkip>. -<St_SecSkip>\n +<St_SecSkip>(\n|"\\ilinebr") <St_Sections>. -<St_Sections>\n +<St_Sections>(\n|"\\ilinebr") <St_SecLabel1>{LABELID} { g_secLabel = yytext; processSection(); @@ -1344,6 +1384,10 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_SecTitle>[^\n]*\n { g_secTitle = yytext; g_secTitle = g_secTitle.stripWhiteSpace(); + if (g_secTitle.right(8)=="\\ilinebr") + { + g_secTitle.left(g_secTitle.length()-8); + } processSection(); BEGIN(St_Sections); } @@ -1351,17 +1395,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} warn(g_fileName,yylineno,"Unexpected character '%s' while looking for section label or title",yytext); } -<St_Snippet>[^\n]+ | -<St_Snippet>[^\n]*\n { - g_token->name = yytext; +<St_Snippet>[^\\\n]+ { + g_token->name += yytext; + } +<St_Snippet>"\\" { + g_token->name += yytext; + } +<St_Snippet>(\n|"\\ilinebr") { g_token->name = g_token->name.stripWhiteSpace(); - return TK_WORD; + return TK_WORD; } /* Generic rules that work for all states */ <*>\n { warn(g_fileName,yylineno,"Unexpected new line character"); } +<*>"\\ilinebr" { + } <*>[\\@<>&$#%~"=] { /* unescaped special character */ //warn(g_fileName,yylineno,"Unexpected character '%s', assuming command \\%s was meant.",yytext,yytext); g_token->name = yytext; @@ -1390,13 +1440,14 @@ void doctokenizerYYFindSections(const char *input,const Definition *d, printlex(yy_flex_debug, FALSE, __FILE__, fileName); } -void doctokenizerYYinit(const char *input,const char *fileName) +void doctokenizerYYinit(const char *input,const char *fileName,bool markdownSupport) { g_autoListLevel = 0; g_inputString = input; g_inputPos = 0; g_fileName = fileName; g_insidePre = FALSE; + g_markdownSupport = markdownSupport; BEGIN(St_Para); } @@ -1554,6 +1605,7 @@ void doctokenizerYYsetStateAnchor() void doctokenizerYYsetStateSnippet() { + g_token->name=""; BEGIN(St_Snippet); } @@ -1620,4 +1672,6 @@ void doctokenizerYYendAutoList() // return retval; //} +#if USE_STATE2STRING #include "doctokenizer.l.h" +#endif diff --git a/src/dot.cpp b/src/dot.cpp index f26bee4..ddabbc7 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -13,7 +13,8 @@ * */ -#include <stdlib.h> +#include <cstdlib> +#include <cassert> #include <qdir.h> @@ -83,10 +84,14 @@ DotManager *DotManager::instance() return m_theInstance; } -DotManager::DotManager() : m_runners(1009), m_filePatchers(1009) +void DotManager::deleteInstance() +{ + delete m_theInstance; + m_theInstance=0; +} + +DotManager::DotManager() : m_runners(), m_filePatchers() { - m_runners.setAutoDelete(TRUE); - m_filePatchers.setAutoDelete(TRUE); m_queue = new DotRunnerQueue; int i; int dotNumThreads = Config_getInt(DOT_NUM_THREADS); @@ -94,18 +99,17 @@ DotManager::DotManager() : m_runners(1009), m_filePatchers(1009) { for (i=0;i<dotNumThreads;i++) { - DotWorkerThread *thread = new DotWorkerThread(m_queue); + std::unique_ptr<DotWorkerThread> thread = std::make_unique<DotWorkerThread>(m_queue); thread->start(); if (thread->isRunning()) { - m_workers.append(thread); + m_workers.push_back(std::move(thread)); } else // no more threads available! { - delete thread; } } - ASSERT(m_workers.count()>0); + ASSERT(m_workers.size()>0); } } @@ -114,53 +118,56 @@ DotManager::~DotManager() delete m_queue; } -DotRunner* DotManager::createRunner(const QCString& absDotName, const QCString& md5Hash) +DotRunner* DotManager::createRunner(const std::string &absDotName, const std::string& md5Hash) { - DotRunner * run = m_runners.find(absDotName); - if (run == 0) + DotRunner* rv = nullptr; + auto const runit = m_runners.find(absDotName); + if (runit == m_runners.end()) { - run = new DotRunner(absDotName, md5Hash); - m_runners.insert(absDotName, run); + auto insobj = std::make_unique<DotRunner>(absDotName, md5Hash); + rv = insobj.get(); + m_runners.emplace(absDotName, std::move(insobj)); } else { // we have a match - if (md5Hash != QCString(run->getMd5Hash().data())) + if (md5Hash != runit->second->getMd5Hash()) { err("md5 hash does not match for two different runs of %s !\n", absDotName.data()); } + rv = runit->second.get(); } - return run; + assert(rv); + return rv; } -DotFilePatcher *DotManager::createFilePatcher(const QCString &fileName) +DotFilePatcher *DotManager::createFilePatcher(const std::string &fileName) { - DotFilePatcher *patcher = m_filePatchers.find(fileName); - if (patcher==0) - { - patcher = new DotFilePatcher(fileName); - m_filePatchers.append(fileName,patcher); - } - return patcher; + auto patcher = m_filePatchers.find(fileName); + + if (patcher != m_filePatchers.end()) return &(patcher->second); + + auto rv = m_filePatchers.emplace(fileName, fileName.c_str()); + assert(rv.second); + return &(rv.first->second); } bool DotManager::run() const { - uint numDotRuns = m_runners.count(); - uint numFilePatchers = m_filePatchers.count(); + size_t numDotRuns = m_runners.size(); + size_t numFilePatchers = m_filePatchers.size(); if (numDotRuns+numFilePatchers>1) { - if (m_workers.count()==0) + if (m_workers.size()==0) { msg("Generating dot graphs in single threaded mode...\n"); } else { - msg("Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numFilePatchers,m_workers.count())); + msg("Generating dot graphs using %zu parallel threads...\n",QMIN(numDotRuns+numFilePatchers,m_workers.size())); } } - int i=1; - QDictIterator<DotRunner> li(m_runners); + size_t i=1; bool setPath=FALSE; if (Config_getBool(GENERATE_HTML)) @@ -185,46 +192,45 @@ bool DotManager::run() const } Portable::sysTimerStart(); // fill work queue with dot operations - DotRunner *dr; - int prev=1; - if (m_workers.count()==0) // no threads to work with + size_t prev=1; + if (m_workers.size()==0) // no threads to work with { - for (li.toFirst();(dr=li.current());++li) + for (auto & dr : m_runners) { - msg("Running dot for graph %d/%d\n",prev,numDotRuns); - dr->run(); + msg("Running dot for graph %zu/%zu\n",prev,numDotRuns); + dr.second->run(); prev++; } } else // use multiple threads to run instances of dot in parallel { - for (li.toFirst();(dr=li.current());++li) + for (auto & dr: m_runners) { - m_queue->enqueue(dr); + m_queue->enqueue(dr.second.get()); } // wait for the queue to become empty - while ((i=m_queue->count())>0) + while ((i=m_queue->size())>0) { i = numDotRuns - i; while (i>=prev) { - msg("Running dot for graph %d/%d\n",prev,numDotRuns); + msg("Running dot for graph %zu/%zu\n",prev,numDotRuns); prev++; } Portable::sleep(100); } - while ((int)numDotRuns>=prev) + while (numDotRuns>=prev) { - msg("Running dot for graph %d/%d\n",prev,numDotRuns); + msg("Running dot for graph %zu/%zu\n",prev,numDotRuns); prev++; } // signal the workers we are done - for (i=0;i<(int)m_workers.count();i++) + for (i=0;i<m_workers.size();i++) { m_queue->enqueue(0); // add terminator for each worker } // wait for the workers to finish - for (i=0;i<(int)m_workers.count();i++) + for (i=0;i<m_workers.size();i++) { m_workers.at(i)->wait(); } @@ -237,27 +243,25 @@ bool DotManager::run() const // patch the output file and insert the maps and figures i=1; - SDict<DotFilePatcher>::Iterator di(m_filePatchers); - const DotFilePatcher *fp; // since patching the svg files may involve patching the header of the SVG // (for zoomable SVGs), and patching the .html files requires reading that - // header after the SVG is patched, we first process the .svg files and - // then the other files. - for (di.toFirst();(fp=di.current());++di) + // header after the SVG is patched, we first process the .svg files and + // then the other files. + for (auto & fp : m_filePatchers) { - if (fp->isSVGFile()) + if (fp.second.isSVGFile()) { - msg("Patching output file %d/%d\n",i,numFilePatchers); - if (!fp->run()) return FALSE; + msg("Patching output file %zu/%zu\n",i,numFilePatchers); + if (!fp.second.run()) return FALSE; i++; } } - for (di.toFirst();(fp=di.current());++di) + for (auto& fp : m_filePatchers) { - if (!fp->isSVGFile()) + if (!fp.second.isSVGFile()) { - msg("Patching output file %d/%d\n",i,numFilePatchers); - if (!fp->run()) return FALSE; + msg("Patching output file %zu/%zu\n",i,numFilePatchers); + if (!fp.second.run()) return FALSE; i++; } } @@ -280,7 +284,7 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir, QCString absImgName = d.absPath().utf8()+"/"+imgName; QCString absOutFile = d.absPath().utf8()+"/"+outFile; - DotRunner dotRun(inFile, QCString()); + DotRunner dotRun(inFile); if (format==GOF_BITMAP) { dotRun.addJob(Config_getEnum(DOT_IMAGE_FORMAT),absImgName); @@ -333,7 +337,7 @@ void writeDotImageMapFromFile(FTextStream &t, QCString imgName = baseName+"."+imgExt; QCString absOutFile = d.absPath().utf8()+"/"+mapName; - DotRunner dotRun(inFile, QCString()); + DotRunner dotRun(inFile.data()); dotRun.addJob(MAP_CMD,absOutFile); dotRun.preventCleanUp(); if (!dotRun.run()) @@ -16,9 +16,8 @@ #ifndef DOT_H #define DOT_H -#include <qlist.h> -#include <qdict.h> #include <qcstring.h> +#include <map> #include "sortdict.h" @@ -35,19 +34,20 @@ class DotManager { public: static DotManager *instance(); - DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); - DotFilePatcher *createFilePatcher(const QCString &fileName); + static void deleteInstance(); + DotRunner* createRunner(const std::string& absDotName, const std::string& md5Hash); + DotFilePatcher *createFilePatcher(const std::string &fileName); bool run() const; private: DotManager(); virtual ~DotManager(); - QDict<DotRunner> m_runners; - SDict<DotFilePatcher> m_filePatchers; + std::map<std::string, std::unique_ptr<DotRunner>> m_runners; + std::map<std::string, DotFilePatcher> m_filePatchers; static DotManager *m_theInstance; DotRunnerQueue *m_queue; - QList<DotWorkerThread> m_workers; + std::vector< std::unique_ptr<DotWorkerThread> > m_workers; }; void writeDotGraphFromFile(const char *inFile,const char *outDir, diff --git a/src/dotclassgraph.cpp b/src/dotclassgraph.cpp index da272b4..84b7962 100644 --- a/src/dotclassgraph.cpp +++ b/src/dotclassgraph.cpp @@ -13,6 +13,7 @@ * */ +#include "containers.h" #include "dotclassgraph.h" #include "dotnode.h" @@ -72,7 +73,7 @@ void DotClassGraph::addClass(const ClassDef *cd,DotNode *n,int prot, QCString displayName=className; if (HIDE_SCOPE_NAMES) displayName=stripScope(displayName); QCString tmp_url; - if (cd->isLinkable() && !cd->isHidden()) + if (cd->isLinkable() && !cd->isHidden()) { tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); if (!cd->anchor().isEmpty()) @@ -121,9 +122,9 @@ void DotClassGraph::determineTruncatedNodes(QList<DotNode> &queue,bool includePa const DotNode *dn; for (li.toFirst();(dn=li.current());++li) { - if (!dn->isVisible()) + if (!dn->isVisible()) truncated = TRUE; - else + else queue.append(dn); } } @@ -133,9 +134,9 @@ void DotClassGraph::determineTruncatedNodes(QList<DotNode> &queue,bool includePa const DotNode *dn; for (li.toFirst();(dn=li.current());++li) { - if (!dn->isVisible()) + if (!dn->isVisible()) truncated = TRUE; - else + else queue.append(dn); } } @@ -149,11 +150,11 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, { QList<DotNode> childQueue; QList<DotNode> parentQueue; - QArray<int> childTreeWidth; - QArray<int> parentTreeWidth; + IntVector childTreeWidth; + IntVector parentTreeWidth; childQueue.append(rootNode); if (includeParents) parentQueue.append(rootNode); - bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop + bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop // despite being marked visible in the child loop while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0) { @@ -238,6 +239,25 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, // left to right order. } +static QCString joinLabels(const StringSet &ss) +{ + QCString label; + int count=1; + int maxLabels=10; + auto it = std::begin(ss), e = std::end(ss); + if (it!=e) // set not empty + { + label += (*it++).c_str(); + for (; it!=e && count < maxLabels ; ++it,++count) + { + label += '\n'; + label += (*it).c_str(); + } + if (count==maxLabels) label+="\n..."; + } + return label; +} + void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int distance) { //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n", @@ -256,7 +276,7 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista //printf("-------- inheritance relation %s->%s templ='%s'\n", // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName, - bcd->templSpecifiers,base,distance); + bcd->templSpecifiers,base,distance); } } } @@ -274,27 +294,8 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista UsesClassDef *ucd; for (;(ucd=ucdi.current());++ucdi) { - QCString label; - QDictIterator<void> dvi(*ucd->accessors); - const char *s; - bool first=TRUE; - int count=0; - int maxLabels=10; - for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count) - { - if (first) - { - label=s; - first=FALSE; - } - else - { - label+=QCString("\n")+s; - } - } - if (count==maxLabels) label+="\n..."; //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data()); - addClass(ucd->classDef,n,EdgeInfo::Purple,label,0, + addClass(ucd->classDef,n,EdgeInfo::Purple,joinLabels(ucd->accessors),0, ucd->templSpecifiers,base,distance); } } @@ -308,27 +309,8 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista ConstraintClassDef *ccd; for (;(ccd=ccdi.current());++ccdi) { - QCString label; - QDictIterator<void> dvi(*ccd->accessors); - const char *s; - bool first=TRUE; - int count=0; - int maxLabels=10; - for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count) - { - if (first) - { - label=s; - first=FALSE; - } - else - { - label+=QCString("\n")+s; - } - } - if (count==maxLabels) label+="\n..."; //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data()); - addClass(ccd->classDef,n,EdgeInfo::Orange2,label,0, + addClass(ccd->classDef,n,EdgeInfo::Orange2,joinLabels(ccd->accessors),0, 0,TRUE,distance); } } @@ -377,7 +359,7 @@ DotClassGraph::DotClassGraph(const ClassDef *cd,GraphType t) //printf("--------------- DotClassGraph::DotClassGraph '%s'\n",cd->displayName().data()); m_graphType = t; QCString tmp_url=""; - if (cd->isLinkable() && !cd->isHidden()) + if (cd->isLinkable() && !cd->isHidden()) { tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); if (!cd->anchor().isEmpty()) @@ -490,7 +472,7 @@ QCString DotClassGraph::getMapLabel() const return escapeCharsInString(m_startNode->label(),FALSE)+"_"+escapeCharsInString(mapName,FALSE); } -QCString DotClassGraph::getImgAltText() const +QCString DotClassGraph::getImgAltText() const { switch (m_graphType) { @@ -504,7 +486,7 @@ QCString DotClassGraph::getImgAltText() const ASSERT(0); break; } - return ""; + return ""; } QCString DotClassGraph::writeGraph(FTextStream &out, diff --git a/src/dotdirdeps.cpp b/src/dotdirdeps.cpp index c70128c..c0e4712 100644 --- a/src/dotdirdeps.cpp +++ b/src/dotdirdeps.cpp @@ -55,11 +55,9 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) << dd->shortName() << "\"];\n"; // add nodes for sub directories - QListIterator<DirDef> sdi(dd->subDirs()); - const DirDef *sdir; - for (sdi.toFirst();(sdir=sdi.current());++sdi) + for(const auto sdir : dd->subDirs()) { - t << " " << sdir->getOutputFileBase() << " [shape=box label=\"" + t << " " << sdir->getOutputFileBase() << " [shape=box label=\"" << sdir->shortName() << "\""; if (sdir->isCluster()) { @@ -70,7 +68,7 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) t << " color=\"black\""; } t << " fillcolor=\"white\" style=\"filled\""; - t << " URL=\"" << sdir->getOutputFileBase() + t << " URL=\"" << sdir->getOutputFileBase() << Doxygen::htmlFileExtension << "\""; t << "];\n"; dirsInGraph.insert(sdir->getOutputFileBase(),sdir); @@ -90,50 +88,52 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) } // add nodes for other used directories - QDictIterator<UsedDir> udi(*dd->usedDirs()); - UsedDir *udir; - //printf("*** For dir %s\n",shortName().data()); - for (udi.toFirst();(udir=udi.current());++udi) - // for each used dir (=directly used or a parent of a directly used dir) { - const DirDef *usedDir=udir->dir(); - const DirDef *dir=dd; - while (dir) + QDictIterator<UsedDir> udi(*dd->usedDirs()); + UsedDir *udir; + //printf("*** For dir %s\n",shortName().data()); + for (udi.toFirst();(udir=udi.current());++udi) + // for each used dir (=directly used or a parent of a directly used dir) { - //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n", - // dir->shortName().data(),usedDir->shortName().data(), - // dir->parent()==usedDir->parent(), - // usedDir->shortName().data(), - // shortName().data(), - // !usedDir->isParentOf(this) - // ); - if (dir!=usedDir && dir->parent()==usedDir->parent() && - !usedDir->isParentOf(dd)) - // include if both have the same parent (or no parent) + const DirDef *usedDir=udir->dir(); + const DirDef *dir=dd; + while (dir) { - t << " " << usedDir->getOutputFileBase() << " [shape=box label=\"" - << usedDir->shortName() << "\""; - if (usedDir->isCluster()) + //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n", + // dir->shortName().data(),usedDir->shortName().data(), + // dir->parent()==usedDir->parent(), + // usedDir->shortName().data(), + // shortName().data(), + // !usedDir->isParentOf(this) + // ); + if (dir!=usedDir && dir->parent()==usedDir->parent() && + !usedDir->isParentOf(dd)) + // include if both have the same parent (or no parent) { - if (!Config_getBool(DOT_TRANSPARENT)) + t << " " << usedDir->getOutputFileBase() << " [shape=box label=\"" + << usedDir->shortName() << "\""; + if (usedDir->isCluster()) { - t << " fillcolor=\"white\" style=\"filled\""; + if (!Config_getBool(DOT_TRANSPARENT)) + { + t << " fillcolor=\"white\" style=\"filled\""; + } + t << " color=\"red\""; } - t << " color=\"red\""; + t << " URL=\"" << usedDir->getOutputFileBase() + << Doxygen::htmlFileExtension << "\"];\n"; + dirsInGraph.insert(usedDir->getOutputFileBase(),usedDir); + break; } - t << " URL=\"" << usedDir->getOutputFileBase() - << Doxygen::htmlFileExtension << "\"];\n"; - dirsInGraph.insert(usedDir->getOutputFileBase(),usedDir); - break; + dir=dir->parent(); } - dir=dir->parent(); } } // add relations between all selected directories const DirDef *dir; QDictIterator<DirDef> di(dirsInGraph); - for (di.toFirst();(dir=di.current());++di) // foreach dir in the graph + for (;(dir=di.current());++di) // foreach dir in the graph { QDictIterator<UsedDir> udi(*dir->usedDirs()); UsedDir *udir; diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index efc6341..17f8cb7 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -132,7 +132,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, //bool isXLink=FALSE; int len = 6; int indexS = buf.find("href=\""), indexE; - bool setTarget = FALSE; + bool targetAlreadySet = buf.find("target=")!=-1; if (indexS>5 && buf.find("xlink:href=\"")!=-1) // XLink href (for SVG) { indexS-=6; @@ -152,9 +152,9 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, // fake ref node to resolve the url DocRef *df = new DocRef( (DocNode*) 0, link.mid(5), context ); result+=externalRef(relPath,df->ref(),TRUE); - if (!df->file().isEmpty()) + if (!df->file().isEmpty()) result += df->file().data() + Doxygen::htmlFileExtension; - if (!df->anchor().isEmpty()) + if (!df->anchor().isEmpty()) result += "#" + df->anchor(); delete df; result += "\""; @@ -173,8 +173,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, QCString url = link.mid(marker+1); if (!ref.isEmpty()) { - result = externalLinkTarget(); - if (result != "") setTarget = TRUE; + result = externalLinkTarget(true); } result+= href+"=\""; result+=externalRef(relPath,ref,TRUE); @@ -185,12 +184,14 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, result = href+"=\"" + link + "\""; } } - if (!target.isEmpty() && !setTarget) + if (!target.isEmpty() && !targetAlreadySet) { result+=" target=\""+target+"\""; } QCString leftPart = buf.left(indexS); QCString rightPart = buf.mid(indexE+1); + //printf("replaceRef(\n'%s'\n)->\n'%s+%s+%s'\n", + // buf.data(),leftPart.data(),result.data(),rightPart.data()); return leftPart + result + rightPart; } else @@ -215,7 +216,7 @@ bool DotFilePatcher::convertMapFile(FTextStream &t,const char *mapName, const QCString &context) { QFile f(mapName); - if (!f.open(IO_ReadOnly)) + if (!f.open(IO_ReadOnly)) { err("problems opening map file %s for inclusion in the docs!\n" "If you installed Graphviz/dot after a previous failing run, \n" @@ -250,7 +251,7 @@ bool DotFilePatcher::convertMapFile(FTextStream &t,const char *mapName, return TRUE; } -DotFilePatcher::DotFilePatcher(const char *patchFile) +DotFilePatcher::DotFilePatcher(const char *patchFile) : m_patchFile(patchFile) { m_maps.setAutoDelete(TRUE); @@ -346,7 +347,7 @@ bool DotFilePatcher::run() const } QFile fi(tmpName); QFile fo(patchFile); - if (!fi.open(IO_ReadOnly)) + if (!fi.open(IO_ReadOnly)) { err("problem opening file %s for patching!\n",tmpName.data()); QDir::current().rename(tmpName,patchFile); @@ -380,7 +381,7 @@ bool DotFilePatcher::run() const ASSERT(numBytes<maxLineLen); if (isSVGFile) { - if (interactiveSVG_local) + if (interactiveSVG_local) { if (line.find("<svg")!=-1 && !replacedHeader) { @@ -412,7 +413,7 @@ bool DotFilePatcher::run() const replacedHeader=TRUE; } } - if (!insideHeader || !foundSize) // copy SVG and replace refs, + if (!insideHeader || !foundSize) // copy SVG and replace refs, // unless we are inside the header of the SVG. // Then we replace it with another header. { @@ -459,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; } @@ -506,9 +507,9 @@ bool DotFilePatcher::run() const fo.close(); // keep original SVG file so we can refer to it, we do need to replace // dummy link by real ones - QFile fi(tmpName); - QFile fo(orgName); - if (!fi.open(IO_ReadOnly)) + fi.setName(tmpName); + fo.setName(orgName); + if (!fi.open(IO_ReadOnly)) { err("problem opening file %s for reading!\n",tmpName.data()); return FALSE; @@ -518,7 +519,7 @@ bool DotFilePatcher::run() const err("problem opening file %s for writing!\n",orgName.data()); return FALSE; } - FTextStream t(&fo); + FTextStream to(&fo); while (!fi.atEnd()) // foreach line { QCString line(maxLineLen); @@ -529,7 +530,7 @@ bool DotFilePatcher::run() const } line.resize(numBytes+1); Map *map = m_maps.at(0); // there is only one 'map' for a SVG file - t << replaceRef(line,map->relPath,map->urlOnly,map->context,"_top"); + to << replaceRef(line,map->relPath,map->urlOnly,map->context,"_top"); } fi.close(); fo.close(); @@ -602,18 +603,18 @@ bool DotFilePatcher::writeSVGFigureLink(FTextStream &out,const QCString &relPath if (height<=60) height=300; else height+=300; // add some extra space for zooming if (height>600) height=600; // clip to maximum height of 600 pixels out << "<div class=\"zoom\">"; - //out << "<object type=\"image/svg+xml\" data=\"" - //out << "<embed type=\"image/svg+xml\" src=\"" - out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" + //out << "<object type=\"image/svg+xml\" data=\"" + //out << "<embed type=\"image/svg+xml\" src=\"" + out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg\" width=\"100%\" height=\"" << height << "\">"; } else { - //out << "<object type=\"image/svg+xml\" data=\"" - //out << "<embed type=\"image/svg+xml\" src=\"" - out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" - << relPath << baseName << ".svg\" width=\"" - << ((width*96+48)/72) << "\" height=\"" + //out << "<object type=\"image/svg+xml\" data=\"" + //out << "<embed type=\"image/svg+xml\" src=\"" + out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" + << relPath << baseName << ".svg\" width=\"" + << ((width*96+48)/72) << "\" height=\"" << ((height*96+48)/72) << "\">"; } writeSVGNotSupported(out); @@ -650,7 +651,7 @@ bool DotFilePatcher::writeVecGfxFigure(FTextStream &out,const QCString &baseName } //printf("Got PDF/EPS size %d,%d\n",width,height); int maxWidth = 350; /* approx. page width in points, excl. margins */ - int maxHeight = 550; /* approx. page height in points, excl. margins */ + int maxHeight = 550; /* approx. page height in points, excl. margins */ out << "\\nopagebreak\n" "\\begin{figure}[H]\n" "\\begin{center}\n" diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index 0bfa712..1ad85e1 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -74,15 +74,6 @@ static bool checkDeliverables(const QCString &file1, return file1Ok && file2Ok; } -static void removeDotGraph(const QCString &dotName) -{ - if (Config_getBool(DOT_CLEANUP)) - { - QDir d; - d.remove(dotName); - } -} - static bool insertMapFile(FTextStream &out,const QCString &mapFile, const QCString &relPath,const QCString &mapLabel) { @@ -108,7 +99,7 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile, QCString DotGraph::imgName() const { return m_baseName + ((m_graphFormat == GOF_BITMAP) ? - ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); + ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); } QCString DotGraph::writeGraph( @@ -166,7 +157,6 @@ bool DotGraph::prepareDotFile() ) { // all needed files are there - removeDotGraph(absDotName()); return FALSE; } @@ -186,14 +176,14 @@ bool DotGraph::prepareDotFile() if (m_graphFormat == GOF_BITMAP) { // run dot to create a bitmap image - DotRunner * dotRun = DotManager::instance()->createRunner(absDotName(), sigStr); + DotRunner * dotRun = DotManager::instance()->createRunner(absDotName().data(), sigStr.data()); dotRun->addJob(Config_getEnum(DOT_IMAGE_FORMAT), absImgName()); if (m_generateImageMap) dotRun->addJob(MAP_CMD, absMapName()); } else if (m_graphFormat == GOF_EPS) { // run dot to create a .eps image - DotRunner *dotRun = DotManager::instance()->createRunner(absDotName(), sigStr); + DotRunner *dotRun = DotManager::instance()->createRunner(absDotName().data(), sigStr.data()); if (Config_getBool(USE_PDFLATEX)) { dotRun->addJob("pdf",absImgName()); @@ -233,11 +223,11 @@ void DotGraph::generateCode(FTextStream &t) if (m_regenerate) { DotManager::instance()-> - createFilePatcher(absImgName())-> + createFilePatcher(absImgName().data())-> addSVGConversion(m_relPath,FALSE,QCString(),m_zoomable,m_graphId); } int mapId = DotManager::instance()-> - createFilePatcher(m_fileName)-> + createFilePatcher(m_fileName.data())-> addSVGObject(m_baseName,absImgName(),m_relPath); t << "<!-- SVG " << mapId << " -->" << endl; } @@ -246,13 +236,13 @@ 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())) { int mapId = DotManager::instance()-> - createFilePatcher(m_fileName)-> + createFilePatcher(m_fileName.data())-> addMap(absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); t << "<!-- MAP " << mapId << " -->" << endl; } @@ -263,7 +253,7 @@ void DotGraph::generateCode(FTextStream &t) if (m_regenerate || !DotFilePatcher::writeVecGfxFigure(t,m_baseName,absBaseName())) { int figId = DotManager::instance()-> - createFilePatcher(m_fileName)-> + createFilePatcher(m_fileName.data())-> addFigure(m_baseName,absBaseName(),FALSE /*TRUE*/); t << endl << "% FIG " << figId << endl; } diff --git a/src/dotgraph.h b/src/dotgraph.h index edba009..b90d980 100644 --- a/src/dotgraph.h +++ b/src/dotgraph.h @@ -31,7 +31,8 @@ enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, C class DotGraph { public: - DotGraph() : m_curNodeNumber(0), m_doNotAddImageToIndex(FALSE), m_noDivTag(FALSE), m_zoomable(TRUE), m_urlOnly(FALSE) {} + DotGraph() : m_doNotAddImageToIndex(FALSE), m_noDivTag(FALSE), + m_zoomable(TRUE), m_urlOnly(FALSE) {} virtual ~DotGraph() {} protected: @@ -98,7 +99,7 @@ class DotGraph bool prepareDotFile(); void generateCode(FTextStream &t); - int m_curNodeNumber; + int m_curNodeNumber = 0; }; #endif diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp index 0a56460..8121657 100644 --- a/src/dotgroupcollaboration.cpp +++ b/src/dotgroupcollaboration.cpp @@ -122,7 +122,7 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) { tmp_url+="#"+def->anchor(); } - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass ); + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass ); } } @@ -134,7 +134,7 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) for (;(def=defli.current());++defli) { tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace ); + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace ); } } @@ -146,7 +146,7 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) for (;(def=defli.current());++defli) { tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile ); + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile ); } } @@ -158,19 +158,17 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) for (;(def=defli.current());++defli) { tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages ); + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages ); } } // Add directories - if ( gd->getDirs() && gd->getDirs()->count() ) + if ( !gd->getDirs().empty() ) { - QListIterator<DirDef> defli(*gd->getDirs()); - const DirDef *def; - for (;(def=defli.current());++defli) + for(const auto def : gd->getDirs()) { tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir ); + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir ); } } } @@ -188,7 +186,7 @@ void DotGroupCollaboration::addMemberList( MemberList* ml ) } } -DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge( +DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType, const QCString& _label, const QCString& _url ) { @@ -197,9 +195,9 @@ DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge( Edge* newEdge = 0; for ( lli.toFirst(); (newEdge=lli.current()); ++lli) { - if ( newEdge->pNStart==_pNStart && + if ( newEdge->pNStart==_pNStart && newEdge->pNEnd==_pNEnd && - newEdge->eType==_eType + newEdge->eType==_eType ) { // edge already found break; @@ -209,7 +207,7 @@ DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge( { newEdge = new Edge(_pNStart,_pNEnd,_eType); m_edges.append( newEdge ); - } + } if (!_label.isEmpty()) { @@ -219,7 +217,7 @@ DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge( return newEdge; } -void DotGroupCollaboration::addCollaborationMember( +void DotGroupCollaboration::addCollaborationMember( const Definition* def, QCString& url, EdgeType eType ) { // Create group nodes @@ -304,8 +302,8 @@ void DotGroupCollaboration::Edge::write( FTextStream &t ) const "darkorchid3" ,"orange" ,"blueviolet" - ,"darkgreen" - ,"firebrick4" + ,"darkgreen" + ,"firebrick4" ,"grey75" ,"midnightblue" }; @@ -341,7 +339,7 @@ void DotGroupCollaboration::Edge::write( FTextStream &t ) const const int maxLabels = 10; for( lli.toFirst(); (link=lli.current()) && count<maxLabels; ++lli,++count) { - if (first) first=FALSE; else t << "\\n"; + if (first) first=FALSE; else t << "\\n"; t << DotNode::convertLabel(link->label); } if (count==maxLabels) t << "\\n..."; diff --git a/src/dotlegendgraph.cpp b/src/dotlegendgraph.cpp index 98e1f88..b17a293 100644 --- a/src/dotlegendgraph.cpp +++ b/src/dotlegendgraph.cpp @@ -29,7 +29,7 @@ void DotLegendGraph::writeGraph(const char *path) if (getDotImageExtension()=="svg") { DotManager::instance()-> - createFilePatcher(absBaseName()+Config_getString(HTML_FILE_EXTENSION))-> + createFilePatcher((absBaseName()+Config_getString(HTML_FILE_EXTENSION)).data())-> addSVGObject("graph_legend", absImgName(),QCString()); } } diff --git a/src/dotnode.cpp b/src/dotnode.cpp index 9eccdde..c02827f 100644 --- a/src/dotnode.cpp +++ b/src/dotnode.cpp @@ -87,7 +87,7 @@ static const char *umlEdgeStyleMap[] = "solid" // usage }; -static EdgeProperties normalEdgeProps = +static EdgeProperties normalEdgeProps = { normalEdgeColorMap, normalArrowStyleMap, normalEdgeStyleMap }; @@ -117,9 +117,8 @@ static QCString escapeTooltip(const QCString &tooltip) static void writeBoxMemberList(FTextStream &t, char prot,MemberList *ml,const ClassDef *scope, - bool isStatic=FALSE,const QDict<void> *skipNames=0) + bool isStatic=FALSE,const StringUnorderedSet *skipNames=nullptr) { - (void)isStatic; if (ml) { MemberListIterator mlia(*ml); @@ -127,8 +126,8 @@ static void writeBoxMemberList(FTextStream &t, int totalCount=0; for (mlia.toFirst();(mma = mlia.current());++mlia) { - if (mma->getClassDef()==scope && - (skipNames==0 || skipNames->find(mma->name())==0)) + if (mma->getClassDef()==scope && + (skipNames==nullptr || skipNames->find(mma->name().str())==std::end(*skipNames))) { totalCount++; } @@ -138,7 +137,7 @@ static void writeBoxMemberList(FTextStream &t, for (mlia.toFirst();(mma = mlia.current());++mlia) { if (mma->getClassDef() == scope && - (skipNames==0 || skipNames->find(mma->name())==0)) + (skipNames==nullptr || skipNames->find(mma->name().str())==std::end(*skipNames))) { int numFields = Config_getInt(UML_LIMIT_NUM_FIELDS); if (numFields>0 && (totalCount>numFields*3/2 && count>=numFields)) @@ -150,7 +149,7 @@ static void writeBoxMemberList(FTextStream &t, { t << prot << " "; t << DotNode::convertLabel(mma->name()); - if (!mma->isObjCMethod() && + if (!mma->isObjCMethod() && (mma->isFunction() || mma->isSlot() || mma->isSignal())) t << "()"; t << "\\l"; count++; @@ -218,7 +217,7 @@ QCString DotNode::convertLabel(const QCString &l) foldLen = (foldLen+sinceLast+1)/2; sinceLast=1; } - else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 && + else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 && !isupper(c) && isupper(p[idx])) { result+=replacement; @@ -258,23 +257,12 @@ static QCString stripProtectionPrefix(const QCString &s) DotNode::DotNode(int n,const char *lab,const char *tip, const char *url, bool isRoot,const ClassDef *cd) - : m_subgraphId(-1) - , m_number(n) + : m_number(n) , m_label(lab) , m_tooltip(tip) , m_url(url) - , m_parents(0) - , m_children(0) - , m_edgeInfo(0) - , m_deleted(FALSE) - , m_written(FALSE) - , m_hasDoc(FALSE) , m_isRoot(isRoot) , m_classDef(cd) - , m_visible(FALSE) - , m_truncated(Unknown) - , m_distance(1000) - , m_renumbered(false) { } @@ -396,9 +384,9 @@ void DotNode::writeBox(FTextStream &t, if (m_classDef && Config_getBool(UML_LOOK) && (gt==Inheritance || gt==Collaboration)) { - // add names shown as relations to a dictionary, so we don't show + // add names shown as relations to a set, so we don't show // them as attributes as well - QDict<void> arrowNames(17); + StringUnorderedSet arrowNames; if (m_edgeInfo) { // for each edge @@ -408,17 +396,17 @@ void DotNode::writeBox(FTextStream &t, { if (!ei->label().isEmpty()) // labels joined by \n { - int li=ei->label().find('\n'); + int i=ei->label().find('\n'); int p=0; QCString lab; - while ((li=ei->label().find('\n',p))!=-1) + while ((i=ei->label().find('\n',p))!=-1) { - lab = stripProtectionPrefix(ei->label().mid(p,li-p)); - arrowNames.insert(lab,(void*)0x8); - p=li+1; + lab = stripProtectionPrefix(ei->label().mid(p,i-p)); + arrowNames.insert(lab.str()); + p=i+1; } lab = stripProtectionPrefix(ei->label().right(ei->label().length()-p)); - arrowNames.insert(lab,(void*)0x8); + arrowNames.insert(lab.str()); } } } @@ -511,7 +499,7 @@ void DotNode::writeBox(FTextStream &t, { t << ",tooltip=\" \""; // space in tooltip is required otherwise still something like 'Node0' is used } - t << "];" << endl; + t << "];" << endl; } void DotNode::writeArrow(FTextStream &t, @@ -547,20 +535,20 @@ void DotNode::writeArrow(FTextStream &t, t << ",label=\" " << convertLabel(ei->label()) << "\" "; } if (Config_getBool(UML_LOOK) && - eProps->arrowStyleMap[ei->color()] && + eProps->arrowStyleMap[ei->color()] && (gt==Inheritance || gt==Collaboration) ) { bool rev = pointBack; if (umlUseArrow) rev=!rev; // UML use relates has arrow on the start side - if (rev) - t << ",arrowtail=\"" << eProps->arrowStyleMap[ei->color()] << "\""; - else + if (rev) + t << ",arrowtail=\"" << eProps->arrowStyleMap[ei->color()] << "\""; + else t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->color()] << "\""; } if (format==GOF_BITMAP) t << ",fontname=\"" << Config_getString(DOT_FONTNAME) << "\""; - t << "];" << endl; + t << "];" << endl; } void DotNode::write(FTextStream &t, @@ -575,7 +563,7 @@ void DotNode::write(FTextStream &t, if (!m_visible) return; // node is not visible writeBox(t,gt,format,m_truncated==Truncated); m_written=TRUE; - QList<DotNode> *nl = toChildren ? m_children : m_parents; + QList<DotNode> *nl = toChildren ? m_children : m_parents; if (nl) { if (toChildren) @@ -682,7 +670,7 @@ void DotNode::writeXML(FTextStream &t,bool isClassGraph) const << "</edgelabel>" << endl; } t << " </childnode>" << endl; - } + } } t << " </node>" << endl; } @@ -852,7 +840,7 @@ void DotNode::clearWriteFlag() } void DotNode::colorConnectedNodes(int curColor) -{ +{ if (m_children) { QListIterator<DotNode> dnlic(*m_children); diff --git a/src/dotnode.h b/src/dotnode.h index 334fdef..92f268e 100644 --- a/src/dotnode.h +++ b/src/dotnode.h @@ -107,22 +107,22 @@ class DotNode private: int m_number; - QCString m_label; //!< label text - QCString m_tooltip; //!< node's tooltip - QCString m_url; //!< url of the node (format: remote$local) - QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows) - QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows) - QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child - bool m_deleted; //!< used to mark a node as deleted - mutable bool m_written; //!< used to mark a node as written - bool m_hasDoc; //!< used to mark a node as documented - bool m_isRoot; //!< indicates if this is a root node - const ClassDef * m_classDef; //!< class representing this node (can be 0) - bool m_visible; //!< is the node visible in the output - TruncState m_truncated; //!< does the node have non-visible children/parents - int m_distance; //!< shortest path to the root node - bool m_renumbered;//!< indicates if the node has been renumbered (to prevent endless loops) - int m_subgraphId; + QCString m_label; //!< label text + QCString m_tooltip; //!< node's tooltip + QCString m_url; //!< url of the node (format: remote$local) + QList<DotNode> *m_parents = 0; //!< list of parent nodes (incoming arrows) + QList<DotNode> *m_children = 0; //!< list of child nodes (outgoing arrows) + QList<EdgeInfo> *m_edgeInfo = 0; //!< edge info for each child + bool m_deleted = false; //!< used to mark a node as deleted + mutable bool m_written = false; //!< used to mark a node as written + bool m_hasDoc = false; //!< used to mark a node as documented + bool m_isRoot; //!< indicates if this is a root node + const ClassDef * m_classDef; //!< class representing this node (can be 0) + bool m_visible = false; //!< is the node visible in the output + TruncState m_truncated = Unknown; //!< does the node have non-visible children/parents + int m_distance = 1000; //!< shortest path to the root node + bool m_renumbered = false; //!< indicates if the node has been renumbered (to prevent endless loops) + int m_subgraphId = -1; }; /** Class representing a list of DotNode objects. */ diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp index fbfeaca..a1bbc52 100644 --- a/src/dotrunner.cpp +++ b/src/dotrunner.cpp @@ -13,8 +13,11 @@ * */ +#include <cassert> + #include "dotrunner.h" +#include "qstring.h" #include "util.h" #include "portable.h" #include "dot.h" @@ -72,7 +75,7 @@ static bool resetPDFSize(const int width,const int height, const char *base) } QFile fi(tmpName); QFile fo(patchFile); - if (!fi.open(IO_ReadOnly)) + if (!fi.open(IO_ReadOnly)) { err("problem opening file %s for patching!\n",tmpName.data()); QDir::current().rename(tmpName,patchFile); @@ -114,9 +117,9 @@ static bool resetPDFSize(const int width,const int height, const char *base) bool DotRunner::readBoundingBox(const char *fileName,int *width,int *height,bool isEps) { const char *bb = isEps ? "%%PageBoundingBox:" : "/MediaBox ["; - int bblen = strlen(bb); + int bblen = (int)strlen(bb); FILE *f = Portable::fopen(fileName,"rb"); - if (!f) + if (!f) { //printf("readBoundingBox: could not open %s\n",fileName); return FALSE; @@ -145,29 +148,30 @@ bool DotRunner::readBoundingBox(const char *fileName,int *width,int *height,bool //--------------------------------------------------------------------------------- -DotRunner::DotRunner(const QCString& absDotName, const QCString& md5Hash) - : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(Config_getBool(DOT_CLEANUP)), - m_dotExe(Config_getString(DOT_PATH)+"dot") +DotRunner::DotRunner(const std::string& absDotName, const std::string& md5Hash) + : m_file(absDotName.data()) + , m_md5Hash(md5Hash.data()) + , m_dotExe(Config_getString(DOT_PATH)+"dot") + , m_cleanUp(Config_getBool(DOT_CLEANUP)) { - m_jobs.setAutoDelete(TRUE); } -void DotRunner::addJob(const char *format,const char *output) + +void DotRunner::addJob(const char *format, const char *output) { - QListIterator<DotJob> li(m_jobs); - DotJob *s; - for (li.toFirst(); (s = li.current()); ++li) + + for (auto& s: m_jobs) { - if (qstrcmp(s->format.data(), format) != 0) continue; - if (qstrcmp(s->output.data(), output) != 0) continue; + if (s.format != format) continue; + if (s.output != output) continue; // we have this job already return; } - QCString args = QCString("-T")+format+" -o \""+output+"\""; - m_jobs.append(new DotJob(format, output, args)); + auto args = std::string ("-T") + format + " -o \"" + output + "\""; + m_jobs.emplace_back(format, output, args); } -QCString getBaseNameOfOutput(QCString const& output) +QCString getBaseNameOfOutput(const QCString &output) { int index = output.findRev('.'); if (index < 0) return output; @@ -179,66 +183,64 @@ bool DotRunner::run() int exitCode=0; QCString dotArgs; - QListIterator<DotJob> li(m_jobs); - DotJob *s; // create output if (Config_getBool(DOT_MULTI_TARGETS)) { dotArgs=QCString("\"")+m_file.data()+"\""; - for (li.toFirst();(s=li.current());++li) + for (auto& s: m_jobs) { dotArgs+=' '; - dotArgs+=s->args.data(); + dotArgs+=s.args.data(); } if ((exitCode=Portable::system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } else { - for (li.toFirst();(s=li.current());++li) + for (auto& s : m_jobs) { - dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); + dotArgs=QCString("\"")+m_file.data()+"\" "+s.args.data(); if ((exitCode=Portable::system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } // check output // As there should be only one pdf file be generated, we don't need code for regenerating multiple pdf files in one call - for (li.toFirst();(s=li.current());++li) + for (auto& s : m_jobs) { - if (qstrncmp(s->format.data(), "pdf", 3) == 0) + if (s.format.compare(0, 3, "pdf") == 0) { int width=0,height=0; - if (!readBoundingBox(s->output.data(),&width,&height,FALSE)) goto error; + if (!readBoundingBox(s.output.data(),&width,&height,FALSE)) goto error; if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE)) { - if (!resetPDFSize(width,height,getBaseNameOfOutput(s->output.data()))) goto error; - dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); + if (!resetPDFSize(width,height,getBaseNameOfOutput(s.output.data()))) goto error; + dotArgs=QCString("\"")+m_file.data()+"\" "+s.args.data(); if ((exitCode=Portable::system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } - if (qstrncmp(s->format.data(), "png", 3) == 0) + if (s.format.compare(0, 3, "png") == 0) { - checkPngResult(s->output.data()); + checkPngResult(s.output.data()); } } // remove .dot files - if (m_cleanUp) + if (m_cleanUp) { //printf("removing dot file %s\n",m_file.data()); Portable::unlink(m_file.data()); } // create checksum file - if (!m_md5Hash.isEmpty()) + if (!m_md5Hash.empty()) { QCString md5Name = getBaseNameOfOutput(m_file.data()) + ".md5"; FILE *f = Portable::fopen(md5Name,"w"); if (f) { - fwrite(m_md5Hash.data(),1,32,f); + fwrite(m_md5Hash.data(),1,32,f); fclose(f); } } @@ -254,27 +256,27 @@ error: void DotRunnerQueue::enqueue(DotRunner *runner) { - QMutexLocker locker(&m_mutex); - m_queue.enqueue(runner); - m_bufferNotEmpty.wakeAll(); + std::lock_guard<std::mutex> locker(m_mutex); + m_queue.push(runner); + m_bufferNotEmpty.notify_all(); } DotRunner *DotRunnerQueue::dequeue() { - QMutexLocker locker(&m_mutex); - while (m_queue.isEmpty()) - { - // wait until something is added to the queue - m_bufferNotEmpty.wait(&m_mutex); - } - DotRunner *result = m_queue.dequeue(); + std::unique_lock<std::mutex> locker(m_mutex); + + // wait until something is added to the queue + m_bufferNotEmpty.wait(locker, [this]() { return !m_queue.empty(); }); + + DotRunner *result = m_queue.front(); + m_queue.pop(); return result; } -uint DotRunnerQueue::count() const +size_t DotRunnerQueue::size() const { - QMutexLocker locker(&m_mutex); - return m_queue.count(); + std::lock_guard<std::mutex> locker(m_mutex); + return m_queue.size(); } //-------------------------------------------------------------------- @@ -284,6 +286,14 @@ DotWorkerThread::DotWorkerThread(DotRunnerQueue *queue) { } +DotWorkerThread::~DotWorkerThread() +{ + if (isRunning()) + { + wait(); + } +} + void DotWorkerThread::run() { DotRunner *runner; @@ -292,3 +302,9 @@ void DotWorkerThread::run() runner->run(); } } + +void DotWorkerThread::start() +{ + assert(!m_thread); + m_thread = std::make_unique<std::thread>(&DotWorkerThread::run, this); +} diff --git a/src/dotrunner.h b/src/dotrunner.h index 1b68c18..1b54617 100644 --- a/src/dotrunner.h +++ b/src/dotrunner.h @@ -16,70 +16,29 @@ #ifndef DOTRUNNER_H #define DOTRUNNER_H -#include "qcstring.h" -#include "qlist.h" -#include "qwaitcondition.h" -#include "qthread.h" -#include "qqueue.h" -#include "qmutex.h" - -/** Minimal constant string class that is thread safe, once initialized. */ -class DotConstString -{ - public: - DotConstString() { m_str=0;} - ~DotConstString() { delete[] m_str;} - DotConstString(char const* s) : m_str(0) { set(s); } - DotConstString(const QCString &s) : m_str(0) { set(s); } - DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); } - const char *data() const { return m_str; } - bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; } - - private: - void set(char const* s) - { - delete[] m_str; - m_str=0; - if (s) - { - m_str=new char[strlen(s) + 1]; - qstrcpy(m_str,s); - } - } - - void set(const QCString &s) - { - delete[] m_str; - m_str=0; - if (!s.isEmpty()) - { - m_str=new char[s.length()+1]; - qstrcpy(m_str,s.data()); - } - } - - DotConstString &operator=(const DotConstString &); - - char *m_str; -}; +#include <string> +#include <thread> +#include <list> +#include <queue> +#include <mutex> +#include <condition_variable> +#include <memory> /** Helper class to run dot from doxygen from multiple threads. */ class DotRunner { - public: struct DotJob { - DotJob(const DotConstString & format, - const DotConstString & output, - const DotConstString & args) - : format(format), output(output), args(args) {} - DotConstString format; - DotConstString output; - DotConstString args; + DotJob(std::string f, std::string o, std::string a) + : format(f), output(o), args(a) {} + std::string format; + std::string output; + std::string args; }; + public: /** Creates a runner for a dot \a file. */ - DotRunner(const QCString& absDotName, const QCString& md5Hash); + DotRunner(const std::string& absDotName, const std::string& md5Hash = std::string()); /** Adds an additional job to the run. * Performing multiple jobs one file can be faster. @@ -87,22 +46,22 @@ class DotRunner void addJob(const char *format,const char *output); /** Prevent cleanup of the dot file (for user provided dot files) */ - void preventCleanUp() { m_cleanUp = FALSE; } + void preventCleanUp() { m_cleanUp = false; } /** Runs dot for all jobs added. */ bool run(); // DotConstString const& getFileName() { return m_file; } - DotConstString const& getMd5Hash() { return m_md5Hash; } + std::string const & getMd5Hash() { return m_md5Hash; } static bool readBoundingBox(const char* fileName, int* width, int* height, bool isEps); private: - DotConstString m_file; - DotConstString m_md5Hash; - DotConstString m_dotExe; - bool m_cleanUp; - QList<DotJob> m_jobs; + std::string m_file; + std::string m_md5Hash; + std::string m_dotExe; + bool m_cleanUp; + std::vector<DotJob> m_jobs; }; /** Queue of dot jobs to run. */ @@ -112,20 +71,25 @@ class DotRunnerQueue public: void enqueue(DotRunner *runner); DotRunner *dequeue(); - uint count() const; + size_t size() const; private: - QWaitCondition m_bufferNotEmpty; - QQueue<DotRunner> m_queue; - mutable QMutex m_mutex; + std::condition_variable m_bufferNotEmpty; + std::queue<DotRunner *> m_queue; + mutable std::mutex m_mutex; }; /** Worker thread to execute a dot run */ -class DotWorkerThread : public QThread +class DotWorkerThread { public: DotWorkerThread(DotRunnerQueue *queue); + ~DotWorkerThread(); void run(); + void start(); + bool isRunning() { return m_thread && m_thread->joinable(); } + void wait() { m_thread->join(); } private: + std::unique_ptr<std::thread> m_thread; DotRunnerQueue *m_queue; }; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 957c3ae..8d3b157 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -13,10 +13,6 @@ * */ -#if !defined(_WIN32) || defined(__CYGWIN__) -#define _DEFAULT_SOURCE 1 -#endif - #include <locale.h> #include <qfileinfo.h> @@ -33,6 +29,7 @@ #include <qptrdict.h> #include <qtextstream.h> +#include <algorithm> #include <unordered_map> #include <memory> @@ -81,12 +78,11 @@ #include "fortranscanner.h" #include "xmlcode.h" #include "sqlcode.h" -#include "tclscanner.h" #include "code.h" -#include "objcache.h" #include "portable.h" #include "vhdljjparser.h" #include "vhdldocgen.h" +#include "vhdlcode.h" #include "eclipsehelp.h" #include "cite.h" #include "markdown.h" @@ -107,6 +103,8 @@ #include "emoji.h" #include "plantuml.h" #include "stlsupport.h" +#include "threadpool.h" +#include "clangparser.h" // provided by the generated file resources.cpp extern void initResources(); @@ -120,36 +118,28 @@ extern void initResources(); ClassSDict *Doxygen::classSDict = 0; ClassSDict *Doxygen::hiddenClasses = 0; NamespaceSDict *Doxygen::namespaceSDict = 0; -MemberNameSDict *Doxygen::memberNameSDict = 0; -MemberNameSDict *Doxygen::functionNameSDict = 0; -FileNameList *Doxygen::inputNameList = 0; // all input files -FileNameDict *Doxygen::inputNameDict = 0; +MemberNameLinkedMap *Doxygen::memberNameLinkedMap = 0; +MemberNameLinkedMap *Doxygen::functionNameLinkedMap = 0; +FileNameLinkedMap *Doxygen::inputNameLinkedMap = 0; GroupSDict *Doxygen::groupSDict = 0; -FormulaList *Doxygen::formulaList = 0; // all formulas -FormulaDict *Doxygen::formulaDict = 0; // all formulas -FormulaDict *Doxygen::formulaNameDict = 0; // the label name of all formulas PageSDict *Doxygen::pageSDict = 0; PageSDict *Doxygen::exampleSDict = 0; -SectionDict *Doxygen::sectionDict = 0; // all page sections -CiteDict *Doxygen::citeDict=0; // database of bibliographic references StringDict Doxygen::aliasDict(257); // aliases -QDict<void> Doxygen::inputPaths(1009); -FileNameDict *Doxygen::includeNameDict = 0; // include names -FileNameDict *Doxygen::exampleNameDict = 0; // examples -FileNameDict *Doxygen::imageNameDict = 0; // images -FileNameDict *Doxygen::dotFileNameDict = 0; // dot files -FileNameDict *Doxygen::mscFileNameDict = 0; // msc files -FileNameDict *Doxygen::diaFileNameDict = 0; // dia files -StringDict Doxygen::namespaceAliasDict(257); // all namespace aliases +StringSet Doxygen::inputPaths; +FileNameLinkedMap *Doxygen::includeNameLinkedMap = 0; // include names +FileNameLinkedMap *Doxygen::exampleNameLinkedMap = 0; // examples +FileNameLinkedMap *Doxygen::imageNameLinkedMap = 0; // images +FileNameLinkedMap *Doxygen::dotFileNameLinkedMap = 0; // dot files +FileNameLinkedMap *Doxygen::mscFileNameLinkedMap = 0; // msc files +FileNameLinkedMap *Doxygen::diaFileNameLinkedMap = 0; // dia files +StringUnorderedMap Doxygen::namespaceAliasMap; // all namespace aliases StringDict Doxygen::tagDestinationDict(257); // all tag locations -QDict<void> Doxygen::expandAsDefinedDict(257); // all macros that should be expanded +StringUnorderedSet Doxygen::expandAsDefinedSet; // all macros that should be expanded QIntDict<MemberGroupInfo> Doxygen::memGrpInfoDict(1009); // dictionary of the member groups heading PageDef *Doxygen::mainPage = 0; bool Doxygen::insideMainPage = FALSE; // are we generating docs for the main page? NamespaceDef *Doxygen::globalScope = 0; -QDict<RefList> *Doxygen::xrefLists = new QDict<RefList>; // dictionary of cross-referenced item lists bool Doxygen::parseSourcesNeeded = FALSE; -QTime Doxygen::runningTime; SearchIndexIntf *Doxygen::searchIndex=0; QDict<DefinitionIntf> *Doxygen::symbolMap = 0; QDict<Definition> *Doxygen::clangUsrMap = 0; @@ -161,24 +151,21 @@ SDict<DirRelation> Doxygen::dirRelations(257); ParserManager *Doxygen::parserManager = 0; QCString Doxygen::htmlFileExtension; bool Doxygen::suppressDocWarnings = FALSE; -//Store *Doxygen::symbolStorage; QCString Doxygen::objDBFileName; QCString Doxygen::entryDBFileName; QCString Doxygen::filterDBFileName; -bool Doxygen::gatherDefines = TRUE; IndexList *Doxygen::indexList; int Doxygen::subpageNestingLevel = 0; bool Doxygen::userComments = FALSE; QCString Doxygen::spaces; bool Doxygen::generatingXmlOutput = FALSE; -bool Doxygen::markdownSupport = TRUE; GenericsSDict *Doxygen::genericsDict; -DocGroup Doxygen::docGroup; -Preprocessor *Doxygen::preprocessor = 0; +DefinesPerFileList Doxygen::macroDefinitions; +bool Doxygen::clangAssistedParsing = FALSE; // locally accessible globals static std::unordered_map< std::string, const Entry* > g_classEntries; -static StringList g_inputFiles; +static StringVector g_inputFiles; static QDict<void> g_compoundKeywordDict(7); // keywords recognised as compounds static OutputList *g_outputList = 0; // list of output generating objects static QDict<FileDef> g_usingDeclarations(1009); // used classes @@ -196,21 +183,18 @@ void clearAll() Doxygen::namespaceSDict->clear(); Doxygen::pageSDict->clear(); Doxygen::exampleSDict->clear(); - Doxygen::inputNameList->clear(); - Doxygen::formulaList->clear(); - Doxygen::sectionDict->clear(); - Doxygen::inputNameDict->clear(); - Doxygen::includeNameDict->clear(); - Doxygen::exampleNameDict->clear(); - Doxygen::imageNameDict->clear(); - Doxygen::dotFileNameDict->clear(); - Doxygen::mscFileNameDict->clear(); - Doxygen::diaFileNameDict->clear(); - Doxygen::formulaDict->clear(); - Doxygen::formulaNameDict->clear(); + Doxygen::inputNameLinkedMap->clear(); + Doxygen::includeNameLinkedMap->clear(); + Doxygen::exampleNameLinkedMap->clear(); + Doxygen::imageNameLinkedMap->clear(); + Doxygen::dotFileNameLinkedMap->clear(); + Doxygen::mscFileNameLinkedMap->clear(); + Doxygen::diaFileNameLinkedMap->clear(); Doxygen::tagDestinationDict.clear(); - delete Doxygen::citeDict; + SectionManager::instance().clear(); + CitationManager::instance().clear(); delete Doxygen::mainPage; Doxygen::mainPage=0; + FormulaManager::instance().clear(); } class Statistics @@ -219,7 +203,7 @@ class Statistics Statistics() { stats.setAutoDelete(TRUE); } void begin(const char *name) { - msg(name); + msg("%s", name); stat *entry= new stat(name,0); stats.append(entry); time.restart(); @@ -260,8 +244,9 @@ class Statistics void statistics() { - fprintf(stderr,"--- inputNameDict stats ----\n"); - Doxygen::inputNameDict->statistics(); +#if 0 + fprintf(stderr,"--- inputNameLinkedMap stats ----\n"); + Doxygen::inputNameLinkedMap->statistics(); fprintf(stderr,"--- includeNameDict stats ----\n"); Doxygen::includeNameDict->statistics(); fprintf(stderr,"--- exampleNameDict stats ----\n"); @@ -274,23 +259,15 @@ void statistics() Doxygen::mscFileNameDict->statistics(); fprintf(stderr,"--- diaFileNameDict stats ----\n"); Doxygen::diaFileNameDict->statistics(); +#endif //fprintf(stderr,"--- g_excludeNameDict stats ----\n"); //g_excludeNameDict.statistics(); fprintf(stderr,"--- aliasDict stats ----\n"); Doxygen::aliasDict.statistics(); - fprintf(stderr,"--- typedefDict stats ----\n"); - fprintf(stderr,"--- namespaceAliasDict stats ----\n"); - Doxygen::namespaceAliasDict.statistics(); - fprintf(stderr,"--- formulaDict stats ----\n"); - Doxygen::formulaDict->statistics(); - fprintf(stderr,"--- formulaNameDict stats ----\n"); - Doxygen::formulaNameDict->statistics(); fprintf(stderr,"--- tagDestinationDict stats ----\n"); Doxygen::tagDestinationDict.statistics(); fprintf(stderr,"--- g_compoundKeywordDict stats ----\n"); g_compoundKeywordDict.statistics(); - fprintf(stderr,"--- expandAsDefinedDict stats ----\n"); - Doxygen::expandAsDefinedDict.statistics(); fprintf(stderr,"--- memGrpInfoDict stats ----\n"); Doxygen::memGrpInfoDict.statistics(); } @@ -520,7 +497,7 @@ static void buildFileList(const Entry *root) ) { bool ambig; - FileDef *fd=findFileDef(Doxygen::inputNameDict,root->name,ambig); + FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,root->name,ambig); if (!fd || ambig) { int save_ambig = ambig; @@ -528,7 +505,7 @@ static void buildFileList(const Entry *root) // directory as the describing file. QCString fn = root->fileName; int newIndex=fn.findRev('/'); - fd=findFileDef(Doxygen::inputNameDict,fn.left(newIndex) + "/" + root->name,ambig); + fd=findFileDef(Doxygen::inputNameLinkedMap,fn.left(newIndex) + "/" + root->name,ambig); if (!fd) ambig = save_ambig; } //printf("**************** root->name=%s fd=%p\n",root->name.data(),fd); @@ -563,7 +540,7 @@ static void buildFileList(const Entry *root) if (ambig) // name is ambiguous { text+="matches the following input files:\n"; - text+=showFileDefMatches(Doxygen::inputNameDict,root->name); + text+=showFileDefMatches(Doxygen::inputNameLinkedMap,root->name); text+="Please use a more specific name by " "including a (larger) part of the path!"; } @@ -571,7 +548,7 @@ static void buildFileList(const Entry *root) { text+="is not an input file"; } - warn(fn,root->startLine,text); + warn(fn,root->startLine,"%s", text.data()); } } for (const auto &e : root->children()) buildFileList(e.get()); @@ -606,7 +583,7 @@ static void addIncludeFile(ClassDef *cd,FileDef *ifd,const Entry *root) // see if we need to include a verbatim copy of the header file //printf("root->includeFile=%s\n",root->includeFile.data()); if (!includeFile.isEmpty() && - (fd=findFileDef(Doxygen::inputNameDict,includeFile,ambig))==0 + (fd=findFileDef(Doxygen::inputNameLinkedMap,includeFile,ambig))==0 ) { // explicit request QCString text; @@ -617,7 +594,7 @@ static void addIncludeFile(ClassDef *cd,FileDef *ifd,const Entry *root) if (ambig) // name is ambiguous { text+="matches the following input files:\n"; - text+=showFileDefMatches(Doxygen::inputNameDict,root->includeFile); + text+=showFileDefMatches(Doxygen::inputNameLinkedMap,root->includeFile); text+="Please use a more specific name by " "including a (larger) part of the path!"; } @@ -625,7 +602,7 @@ static void addIncludeFile(ClassDef *cd,FileDef *ifd,const Entry *root) { text+="is not an input file"; } - warn(root->fileName,root->startLine,text); + warn(root->fileName,root->startLine, "%s", text.data()); } else if (includeFile.isEmpty() && ifd && // see if the file extension makes sense @@ -652,7 +629,7 @@ static void addIncludeFile(ClassDef *cd,FileDef *ifd,const Entry *root) iName=fd->name(); } } - else if (!Config_getList(STRIP_FROM_INC_PATH).isEmpty()) + else if (!Config_getList(STRIP_FROM_INC_PATH).empty()) { iName=stripFromIncludePath(fd->absFilePath()); } @@ -883,9 +860,9 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr return resultScope; } -ArgumentList getTemplateArgumentsFromName( +std::unique_ptr<ArgumentList> getTemplateArgumentsFromName( const QCString &name, - const std::vector<ArgumentList> &tArgLists) + const ArgumentLists &tArgLists) { // for each scope fragment, check if it is a template and advance through // the list if so. @@ -907,7 +884,9 @@ ArgumentList getTemplateArgumentsFromName( } p=i+2; } - return alIt!=tArgLists.end() ? *alIt : ArgumentList(); + return alIt!=tArgLists.end() ? + std::make_unique<ArgumentList>(*alIt) : + std::unique_ptr<ArgumentList>(); } static @@ -1009,20 +988,26 @@ static void addClassToContext(const Entry *root) cd->setDocumentation(root->doc,root->docFile,root->docLine); cd->setBriefDescription(root->brief,root->briefFile,root->briefLine); - if (root->bodyLine!=-1 && cd->getStartBodyLine()==-1) + if ((root->spec&Entry::ForwardDecl)==0 && cd->isForwardDeclared()) { - cd->setBodySegment(root->bodyLine,root->endBodyLine); - cd->setBodyDef(fd); + cd->setDefFile(root->fileName,root->startLine,root->startColumn); + if (root->bodyLine!=-1) + { + cd->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); + cd->setBodyDef(fd); + } } - //cd->setName(fullName); // change name to match docs if (cd->templateArguments().empty() || (cd->isForwardDeclared() && (root->spec&Entry::ForwardDecl)==0)) { // this happens if a template class declared with @class is found // before the actual definition or if a forward declaration has different template // parameter names. - ArgumentList tArgList = getTemplateArgumentsFromName(cd->name(),root->tArgLists); - cd->setTemplateArguments(tArgList); + std::unique_ptr<ArgumentList> tArgList = getTemplateArgumentsFromName(cd->name(),root->tArgLists); + if (tArgList) + { + cd->setTemplateArguments(*tArgList); + } } cd->setCompoundType(convertToCompoundType(root->section,root->spec)); @@ -1055,12 +1040,12 @@ static void addClassToContext(const Entry *root) buildScopeFromQualifiedName(fullName,fullName.contains("::"),root->lang,tagInfo); } } - ArgumentList tArgList; + std::unique_ptr<ArgumentList> tArgList; if ((root->lang==SrcLangExt_CSharp || root->lang==SrcLangExt_Java) && (i=fullName.find('<'))!=-1) { // a Java/C# generic class looks like a C++ specialization, so we need to split the // name and template arguments here - stringToArgumentList(root->lang,fullName.mid(i),tArgList); + tArgList = stringToArgumentList(root->lang,fullName.mid(i)); fullName=fullName.left(i); } else @@ -1083,12 +1068,15 @@ static void addClassToContext(const Entry *root) //printf("class %s template args=%s\n",fullName.data(), // tArgList ? tempArgListToString(tArgList,root->lang).data() : "<none>"); - cd->setTemplateArguments(tArgList); + if (tArgList) + { + cd->setTemplateArguments(*tArgList); + } cd->setProtection(root->protection); cd->setIsStatic(root->stat); // file definition containing the class cd - cd->setBodySegment(root->bodyLine,root->endBodyLine); + cd->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); cd->setBodyDef(fd); cd->setMetaData(root->metaData); @@ -1111,19 +1099,22 @@ static void addClassToContext(const Entry *root) cd->addSectionsToDefinition(root->anchors); if (!root->subGrouping) cd->setSubGrouping(FALSE); - if (cd->hasDocumentation()) + if ((root->spec&Entry::ForwardDecl)==0) { - addIncludeFile(cd,fd,root); - } - if (fd && (root->section & Entry::COMPOUND_MASK)) - { - //printf(">> Inserting class '%s' in file '%s' (root->fileName='%s')\n", - // cd->name().data(), - // fd->name().data(), - // root->fileName.data() - // ); - cd->setFileDef(fd); - fd->insertClass(cd); + if (cd->hasDocumentation()) + { + addIncludeFile(cd,fd,root); + } + if (fd && (root->section & Entry::COMPOUND_MASK)) + { + //printf(">> Inserting class '%s' in file '%s' (root->fileName='%s')\n", + // cd->name().data(), + // fd->name().data(), + // root->fileName.data() + // ); + cd->setFileDef(fd); + fd->insertClass(cd); + } } addClassToGroups(root,cd); cd->setRefItems(root->sli); @@ -1294,7 +1285,7 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC cd->setDocumentation(templ->documentation(),templ->docFile(),templ->docLine()); // copy docs to definition cd->setBriefDescription(templ->briefDescription(),templ->briefFile(),templ->briefLine()); cd->setLanguage(templ->getLanguage()); - cd->setBodySegment(templ->getStartBodyLine(),templ->getEndBodyLine()); + cd->setBodySegment(templ->getDefLine(),templ->getStartBodyLine(),templ->getEndBodyLine()); cd->setBodyDef(templ->getBodyDef()); cd->setOuterScope(rootCd->getOuterScope()); @@ -1525,7 +1516,7 @@ static void buildNamespaceList(const Entry *root) tagFileName = tagInfo->fileName; } //printf("++ new namespace %s lang=%s tagName=%s\n",fullName.data(),langToString(root->lang).data(),tagName.data()); - NamespaceDef *nd=createNamespaceDef(tagInfo?tagName:root->fileName,root->startLine, + nd=createNamespaceDef(tagInfo?tagName:root->fileName,root->startLine, root->startColumn,fullName,tagName,tagFileName, root->type,root->spec&Entry::Published); nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition @@ -1550,7 +1541,7 @@ static void buildNamespaceList(const Entry *root) // the empty string test is needed for extract all case nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); nd->insertUsedFile(fd); - nd->setBodySegment(root->bodyLine,root->endBodyLine); + nd->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); nd->setBodyDef(fd); // add class to the list Doxygen::namespaceSDict->inSort(fullName,nd); @@ -1561,7 +1552,7 @@ static void buildNamespaceList(const Entry *root) if (d==0) // we didn't find anything, create the scope artificially // anyway, so we can at least relate scopes properly. { - Definition *d = buildScopeFromQualifiedName(fullName,fullName.contains("::"),nd->getLanguage(),tagInfo); + d = buildScopeFromQualifiedName(fullName,fullName.contains("::"),nd->getLanguage(),tagInfo); d->addInnerCompound(nd); nd->setOuterScope(d); // TODO: Due to the order in which the tag file is written @@ -1717,7 +1708,7 @@ static void findUsingDirectives(const Entry *root) else // unknown namespace, but add it anyway. { //printf("++ new unknown namespace %s lang=%s\n",name.data(),langToString(root->lang).data()); - NamespaceDef *nd=createNamespaceDef(root->fileName,root->startLine,root->startColumn,name); + nd=createNamespaceDef(root->fileName,root->startLine,root->startColumn,name); nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); nd->addSectionsToDefinition(root->anchors); @@ -1890,67 +1881,61 @@ static void findUsingDeclImports(const Entry *root) if (bcd && bcd!=cd) { //printf("found class %s memName=%s\n",bcd->name().data(),memName.data()); - MemberNameInfoSDict *mndict=bcd->memberNameInfoSDict(); - if (mndict) + const MemberNameInfoLinkedMap &mnlm=bcd->memberNameInfoLinkedMap(); + const MemberNameInfo *mni = mnlm.find(memName); + if (mni) { - MemberNameInfo *mni = mndict->find(memName); - if (mni) + for (auto &mi : *mni) { - MemberNameInfoIterator mnii(*mni); - MemberInfo *mi; - for ( ; (mi=mnii.current()) ; ++mnii ) + MemberDef *md = mi->memberDef(); + if (md && md->protection()!=Private) { - MemberDef *md = mi->memberDef; - if (md && md->protection()!=Private) + //printf("found member %s\n",mni->memberName()); + QCString fileName = root->fileName; + if (fileName.isEmpty() && root->tagInfo()) { - //printf("found member %s\n",mni->memberName()); - MemberDef *newMd = 0; - { - QCString fileName = root->fileName; - if (fileName.isEmpty() && root->tagInfo()) - { - fileName = root->tagInfo()->tagName; - } - const ArgumentList &templAl = md->templateArguments(); - const ArgumentList &al = md->templateArguments(); - newMd = createMemberDef( - fileName,root->startLine,root->startColumn, - md->typeString(),memName,md->argsString(), - md->excpString(),root->protection,root->virt, - md->isStatic(),Member,md->memberType(), - templAl,al,root->metaData - ); - } - newMd->setMemberClass(cd); - cd->insertMember(newMd); - if (!root->doc.isEmpty() || !root->brief.isEmpty()) - { - newMd->setDocumentation(root->doc,root->docFile,root->docLine); - newMd->setBriefDescription(root->brief,root->briefFile,root->briefLine); - newMd->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - } - else - { - newMd->setDocumentation(md->documentation(),md->docFile(),md->docLine()); - newMd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine()); - newMd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); - } - newMd->setDefinition(md->definition()); - newMd->enableCallGraph(root->callGraph); - newMd->enableCallerGraph(root->callerGraph); - newMd->enableReferencedByRelation(root->referencedByRelation); - newMd->enableReferencesRelation(root->referencesRelation); - newMd->setBitfields(md->bitfieldString()); - newMd->addSectionsToDefinition(root->anchors); - newMd->setBodySegment(md->getStartBodyLine(),md->getEndBodyLine()); - newMd->setBodyDef(md->getBodyDef()); - newMd->setInitializer(md->initializer()); - newMd->setMaxInitLines(md->initializerLines()); - newMd->setMemberGroupId(root->mGrpId); - newMd->setMemberSpecifiers(md->getMemberSpecifiers()); - newMd->setLanguage(root->lang); - newMd->setId(root->id); + fileName = root->tagInfo()->tagName; + } + const ArgumentList &templAl = md->templateArguments(); + const ArgumentList &al = md->templateArguments(); + std::unique_ptr<MemberDef> newMd { createMemberDef( + fileName,root->startLine,root->startColumn, + md->typeString(),memName,md->argsString(), + md->excpString(),root->protection,root->virt, + md->isStatic(),Member,md->memberType(), + templAl,al,root->metaData + ) }; + newMd->setMemberClass(cd); + cd->insertMember(newMd.get()); + if (!root->doc.isEmpty() || !root->brief.isEmpty()) + { + newMd->setDocumentation(root->doc,root->docFile,root->docLine); + newMd->setBriefDescription(root->brief,root->briefFile,root->briefLine); + newMd->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); } + else + { + newMd->setDocumentation(md->documentation(),md->docFile(),md->docLine()); + newMd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine()); + newMd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); + } + newMd->setDefinition(md->definition()); + newMd->enableCallGraph(root->callGraph); + newMd->enableCallerGraph(root->callerGraph); + newMd->enableReferencedByRelation(root->referencedByRelation); + newMd->enableReferencesRelation(root->referencesRelation); + newMd->setBitfields(md->bitfieldString()); + newMd->addSectionsToDefinition(root->anchors); + newMd->setBodySegment(md->getDefLine(),md->getStartBodyLine(),md->getEndBodyLine()); + newMd->setBodyDef(md->getBodyDef()); + newMd->setInitializer(md->initializer()); + newMd->setMaxInitLines(md->initializerLines()); + newMd->setMemberGroupId(root->mGrpId); + newMd->setMemberSpecifiers(md->getMemberSpecifiers()); + newMd->setLanguage(root->lang); + newMd->setId(root->id); + MemberName *mn = Doxygen::memberNameLinkedMap->add(memName); + mn->push_back(std::move(newMd)); } } } @@ -1967,24 +1952,18 @@ static void findUsingDeclImports(const Entry *root) static void findIncludedUsingDirectives() { // first mark all files as not visited - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->setVisited(FALSE); } } // then recursively add using directives found in #include files // to files that have not been visited. - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (!fd->isVisited()) { @@ -2040,7 +2019,7 @@ static MemberDef *addVariableToClass( } else { - def=type+" "+name+root->args; + def=type+" "+name+args; } } else @@ -2071,12 +2050,10 @@ static MemberDef *addVariableToClass( // see if the member is already found in the same scope // (this may be the case for a static member that is initialized // outside the class) - MemberName *mn=Doxygen::memberNameSDict->find(name); + MemberName *mn=Doxygen::memberNameLinkedMap->find(name); if (mn) { - MemberNameIterator mni(*mn); - MemberDef *md; - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n", // md->getClassDef(),cd,type.data(),md->typeString()); @@ -2092,11 +2069,11 @@ static MemberDef *addVariableToClass( { // Objective-C 2.0 property // turn variable into a property md->setProtection(root->protection); - cd->reclassifyMember(md,MemberType_Property); + cd->reclassifyMember(md.get(),MemberType_Property); } - addMemberDocs(root,md,def,0,FALSE,root->spec); + addMemberDocs(root,md.get(),def,0,FALSE,root->spec); //printf(" Member already found!\n"); - return md; + return md.get(); } } } @@ -2108,16 +2085,14 @@ static MemberDef *addVariableToClass( } // new member variable, typedef or enum value - MemberDef *md=createMemberDef( + std::unique_ptr<MemberDef> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,root->exception, prot,Normal,root->stat,related, mtype,!root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList(), - ArgumentList(), root->metaData); + ArgumentList(), root->metaData) }; md->setTagInfo(root->tagInfo()); md->setMemberClass(cd); // also sets outer scope (i.e. getOuterScope()) - //md->setDefFile(root->fileName); - //md->setDefLine(root->startLine); md->setDocumentation(root->doc,root->docFile,root->docLine); md->setBriefDescription(root->brief,root->briefFile,root->briefLine); md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); @@ -2127,7 +2102,7 @@ static MemberDef *addVariableToClass( md->setFromAnonymousScope(fromAnnScope); md->setFromAnonymousMember(fromAnnMemb); //md->setIndentDepth(indentDepth); - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setInitializer(root->initializer); md->setMaxInitLines(root->initLines); md->setMemberGroupId(root->mGrpId); @@ -2142,38 +2117,24 @@ static MemberDef *addVariableToClass( md->setArtificial(root->artificial); md->setLanguage(root->lang); md->setId(root->id); - addMemberToGroups(root,md); - //if (root->mGrpId!=-1) - //{ - // printf("memberdef %s in memberGroup %d\n",name.data(),root->mGrpId); - // md->setMemberGroup(memberGroupDict[root->mGrpId]); - // + addMemberToGroups(root,md.get()); md->setBodyDef(root->fileDef()); - //printf(" Adding member=%s\n",md->name().data()); - // add the member to the global list - if (mn) - { - mn->append(md); - } - else // new variable name - { - mn = new MemberName(name); - mn->append(md); - //printf("Adding memberName=%s\n",mn->memberName()); - //Doxygen::memberNameDict.insert(name,mn); - //Doxygen::memberNameList.append(mn); - Doxygen::memberNameSDict->append(name,mn); - // add the member to the class - } //printf(" New member adding to %s (%p)!\n",cd->name().data(),cd); - cd->insertMember(md); + cd->insertMember(md.get()); md->setRefItems(root->sli); //TODO: insert FileDef instead of filename strings. cd->insertUsedFile(root->fileDef()); root->markAsProcessed(); - return md; + + //printf(" Adding member=%s\n",md->name().data()); + // add the member to the global list + MemberDef *result = md.get(); + mn = Doxygen::memberNameLinkedMap->add(name); + mn->push_back(std::move(md)); + + return result; } //---------------------------------------------------------------------- @@ -2298,7 +2259,7 @@ static MemberDef *addVariableToFile( } def.stripPrefix("static "); - MemberName *mn=Doxygen::functionNameSDict->find(name); + MemberName *mn=Doxygen::functionNameLinkedMap->find(name); if (mn) { //QCString nscope=removeAnonymousScopes(scope); @@ -2308,9 +2269,7 @@ static MemberDef *addVariableToFile( { nd = getResolvedNamespace(scope); } - MemberNameIterator mni(*mn); - MemberDef *md; - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { if (!md->isAlias() && ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() && @@ -2338,7 +2297,7 @@ static MemberDef *addVariableToFile( { Debug::print(Debug::Variables,0, " variable already found: scope=%s\n",qPrint(md->getOuterScope()->name())); - addMemberDocs(root,md,def,0,FALSE,root->spec); + addMemberDocs(root,md.get(),def,0,FALSE,root->spec); md->setRefItems(root->sli); // if md is a variable forward declaration and root is the definition that // turn md into the definition @@ -2353,7 +2312,7 @@ static MemberDef *addVariableToFile( { md->setDeclFile(root->fileName,root->startLine,root->startColumn); } - return md; + return md.get(); } } } @@ -2368,12 +2327,12 @@ static MemberDef *addVariableToFile( Debug::print(Debug::Variables,0, " new variable, nd=%s tagInfo=%p!\n",nd?qPrint(nd->name()):"<global>",root->tagInfo()); // new global variable, enum value or typedef - MemberDef *md=createMemberDef( + std::unique_ptr<MemberDef> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,0, root->protection, Normal,root->stat,Member, mtype,!root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList(), - ArgumentList(), root->metaData); + ArgumentList(), root->metaData) }; md->setTagInfo(root->tagInfo()); md->setMemberSpecifiers(root->spec); md->setDocumentation(root->doc,root->docFile,root->docLine); @@ -2396,16 +2355,16 @@ static MemberDef *addVariableToFile( //md->setOuterScope(fd); if (!root->explicitExternal) { - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setBodyDef(fd); } - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); md->setRefItems(root->sli); if (nd && !nd->isAnonymous()) { md->setNamespace(nd); - nd->insertMember(md); + nd->insertMember(md.get()); } // add member to the file (we do this even if we have already inserted @@ -2413,22 +2372,17 @@ static MemberDef *addVariableToFile( if (fd) { md->setFileDef(fd); - fd->insertMember(md); + fd->insertMember(md.get()); } - // add member definition to the list of globals - if (mn) - { - mn->append(md); - } - else - { - mn = new MemberName(name); - mn->append(md); - Doxygen::functionNameSDict->append(name,mn); - } root->markAsProcessed(); - return md; + + // add member definition to the list of globals + MemberDef *result = md.get(); + mn = Doxygen::functionNameLinkedMap->add(name); + mn->push_back(std::move(md)); + + return result; } /*! See if the return type string \a type is that of a function pointer @@ -2613,11 +2567,13 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) type=name; static const QRegExp reName("[a-z_A-Z][a-z_A-Z0-9]*"); int l=0; + int j=0; int i=args.isEmpty() ? -1 : reName.match(args,0,&l); if (i!=-1) { name=args.mid(i,l); - args=args.mid(i+l,args.find(')',i+l)-i-l); + j=args.find(')',i+l)-i-l; + if (j >= 0) args=args.mid(i+l,j); } //printf("new: type='%s' name='%s' args='%s'\n", // type.data(),name.data(),args.data()); @@ -2901,17 +2857,17 @@ static void addInterfaceOrServiceToServiceOrSingleton( { fileName = root->tagInfo()->tagName; } - MemberDef *const md = createMemberDef( + std::unique_ptr<MemberDef> md { createMemberDef( fileName, root->startLine, root->startColumn, root->type, rname, "", "", root->protection, root->virt, root->stat, Member, - type, ArgumentList(), root->argList, root->metaData); + type, ArgumentList(), root->argList, root->metaData) }; md->setTagInfo(root->tagInfo()); md->setMemberClass(cd); md->setDocumentation(root->doc,root->docFile,root->docLine); md->setDocsForDefinition(false); md->setBriefDescription(root->brief,root->briefFile,root->briefLine); md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setMemberSpecifiers(root->spec); md->setMemberGroupId(root->mGrpId); md->setTypeConstraints(root->typeConstr); @@ -2936,21 +2892,9 @@ static void addInterfaceOrServiceToServiceOrSingleton( qPrint(def) ); - // add member to the global list of all members - MemberName *mn; - if ((mn=Doxygen::memberNameSDict->find(rname))) - { - mn->append(md); - } - else - { - mn = new MemberName(rname); - mn->append(md); - Doxygen::memberNameSDict->append(rname,mn); - } // add member to the class cd - cd->insertMember(md); + cd->insertMember(md.get()); // also add the member as a "base" (to get nicer diagrams) // "optional" interface/service get Protected which turns into dashed line BaseInfo base(rname, @@ -2959,9 +2903,13 @@ static void addInterfaceOrServiceToServiceOrSingleton( // add file to list of used files cd->insertUsedFile(fd); - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); root->markAsProcessed(); md->setRefItems(root->sli); + + // add member to the global list of all members + MemberName *mn = Doxygen::memberNameLinkedMap->add(rname); + mn->push_back(std::move(md)); } static void buildInterfaceAndServiceList(const Entry *root) @@ -3068,8 +3016,13 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, else mtype=MemberType_Function; // strip redundant template specifier for constructors + int j = -1; if ((fd==0 || fd->getLanguage()==SrcLangExt_Cpp) && - name.left(9)!="operator " && (i=name.find('<'))!=-1 && name.find('>')!=-1) + name.left(9)!="operator " && // not operator + (i=name.find('<'))!=-1 && // containing < + (j=name.find('>'))!=-1 && // or > + (j!=i+2 || name.at(i+1)!='=') // but not the C++20 spaceship operator <=> + ) { name=name.left(i); } @@ -3085,7 +3038,7 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, // ); // adding class member - MemberDef *md=createMemberDef( + std::unique_ptr<MemberDef> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,root->exception, protection,virt, @@ -3093,14 +3046,14 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, relates.isEmpty() ? Member : root->relatesType == MemberOf ? Foreign : Related, mtype,!root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList(), - root->argList, root->metaData); + root->argList, root->metaData) }; md->setTagInfo(root->tagInfo()); md->setMemberClass(cd); md->setDocumentation(root->doc,root->docFile,root->docLine); md->setDocsForDefinition(!root->proto); md->setBriefDescription(root->brief,root->briefFile,root->briefLine); md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setMemberSpecifiers(spec); md->setMemberGroupId(root->mGrpId); md->setTypeConstraints(root->typeConstr); @@ -3108,7 +3061,6 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, md->setId(root->id); md->setBodyDef(fd); md->setFileDef(fd); - //md->setScopeTemplateArguments(root->tArgList); md->addSectionsToDefinition(root->anchors); QCString def; QCString qualScope = cd->qualifiedNameWithTemplateParameters(); @@ -3165,30 +3117,140 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, qPrint(def) ); + // add member to the class cd + cd->insertMember(md.get()); + // add file to list of used files + cd->insertUsedFile(fd); + + addMemberToGroups(root,md.get()); + root->markAsProcessed(); + md->setRefItems(root->sli); + // add member to the global list of all members //printf("Adding member=%s class=%s\n",md->name().data(),cd->name().data()); - MemberName *mn; - if ((mn=Doxygen::memberNameSDict->find(name))) + MemberName *mn = Doxygen::memberNameLinkedMap->add(name); + mn->push_back(std::move(md)); +} + +//------------------------------------------------------------------------------------------ + +void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &sc, + NamespaceDef *nd) +{ + QCString scope = sc; + Debug::print(Debug::Functions,0," --> new function %s found!\n",qPrint(rname)); + //printf("New function type='%s' name='%s' args='%s' bodyLine=%d\n", + // root->type.data(),rname.data(),root->args.data(),root->bodyLine); + + // new global function + QCString name=removeRedundantWhiteSpace(rname); + std::unique_ptr<MemberDef> md { createMemberDef( + root->fileName,root->startLine,root->startColumn, + root->type,name,root->args,root->exception, + root->protection,root->virt,root->stat,Member, + MemberType_Function, + !root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList(), + root->argList,root->metaData) }; + + md->setTagInfo(root->tagInfo()); + md->setLanguage(root->lang); + md->setId(root->id); + md->setDocumentation(root->doc,root->docFile,root->docLine); + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); + md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); + md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); + md->setDocsForDefinition(!root->proto); + md->setTypeConstraints(root->typeConstr); + //md->setBody(root->body); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); + FileDef *fd=root->fileDef(); + md->setBodyDef(fd); + md->addSectionsToDefinition(root->anchors); + md->setMemberSpecifiers(root->spec); + md->setMemberGroupId(root->mGrpId); + + // see if the function is inside a namespace that was not part of + // the name already (in that case nd should be non-zero already) + if (nd==0 && root->parent()->section == Entry::NAMESPACE_SEC ) { - mn->append(md); + //QCString nscope=removeAnonymousScopes(root->parent()->name); + QCString nscope=root->parent()->name; + if (!nscope.isEmpty()) + { + nd = getResolvedNamespace(nscope); + } } - else + + if (!scope.isEmpty()) { - mn = new MemberName(name); - mn->append(md); - Doxygen::memberNameSDict->append(name,mn); + QCString sep = getLanguageSpecificSeparator(root->lang); + if (sep!="::") + { + scope = substitute(scope,"::",sep); + } + scope+=sep; } - // add member to the class cd - cd->insertMember(md); - // add file to list of used files - cd->insertUsedFile(fd); + QCString def; + //QCString optArgs = root->argList.empty() ? QCString() : root->args; + if (!root->type.isEmpty()) + { + def=root->type+" "+scope+name; //+optArgs; + } + else + { + def=scope+name; //+optArgs; + } + Debug::print(Debug::Functions,0, + " Global Function:\n" + " '%s' '%s'::'%s' '%s' proto=%d\n" + " def='%s'\n", + qPrint(root->type), + qPrint(root->parent()->name), + qPrint(rname), + qPrint(root->args), + root->proto, + qPrint(def) + ); + md->setDefinition(def); + md->enableCallGraph(root->callGraph); + md->enableCallerGraph(root->callerGraph); + md->enableReferencedByRelation(root->referencedByRelation); + md->enableReferencesRelation(root->referencesRelation); + //if (root->mGrpId!=-1) + //{ + // md->setMemberGroup(memberGroupDict[root->mGrpId]); + //} - addMemberToGroups(root,md); - root->markAsProcessed(); md->setRefItems(root->sli); + if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') + { + // add member to namespace + md->setNamespace(nd); + nd->insertMember(md.get()); + } + if (fd) + { + // add member to the file (we do this even if we have already + // inserted it into the namespace) + md->setFileDef(fd); + fd->insertMember(md.get()); + } + + addMemberToGroups(root,md.get()); + if (root->relatesType == Simple) // if this is a relatesalso command, + // allow find Member to pick it up + { + root->markAsProcessed(); // Otherwise we have finished with this entry. + } + + // add member to the list of file members + //printf("Adding member=%s\n",md->name().data()); + MemberName *mn = Doxygen::functionNameLinkedMap->add(name); + mn->push_back(std::move(md)); } +//------------------------------------------------------------------------------------------ static void buildFunctionList(const Entry *root) { @@ -3299,12 +3361,11 @@ static void buildFunctionList(const Entry *root) */ bool found=FALSE; MemberName *mn; - MemberDef *md=0; - if ((mn=Doxygen::functionNameSDict->find(rname))) + MemberDef *md_found=0; + if ((mn=Doxygen::functionNameLinkedMap->find(rname))) { Debug::print(Debug::Functions,0," --> function %s already found!\n",qPrint(rname)); - MemberNameIterator mni(*mn); - for (mni.toFirst();(!found && (md=mni.current()));++mni) + for (const auto &md : *mn) { if (!md->isAlias()) { @@ -3349,8 +3410,8 @@ static void buildFunctionList(const Entry *root) root->stat && md->isStatic() && root->fileName!=md->getDefFileName(); if ( - matchArguments2(md->getOuterScope(),mfd,mdAl, - rnd ? rnd : Doxygen::globalScope,rfd,root->argList, + matchArguments2(md->getOuterScope(),mfd,&mdAl, + rnd ? rnd : Doxygen::globalScope,rfd,&root->argList, FALSE) && sameNumTemplateArgs && matchingReturnTypes && @@ -3388,16 +3449,14 @@ static void buildFunctionList(const Entry *root) // merge documentation if (md->documentation().isEmpty() && !root->doc.isEmpty()) { - ArgumentList argList; - stringToArgumentList(root->lang,root->args,argList); if (root->proto) { //printf("setDeclArgumentList to %p\n",argList); - md->setDeclArgumentList(argList); + md->moveDeclArgumentList(stringToArgumentList(root->lang,root->args)); } else { - md->setArgumentList(argList); + md->moveArgumentList(stringToArgumentList(root->lang,root->args)); } } @@ -3406,7 +3465,7 @@ static void buildFunctionList(const Entry *root) md->setDocsForDefinition(!root->proto); if (md->getStartBodyLine()==-1 && root->bodyLine!=-1) { - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setBodyDef(rfd); } @@ -3426,7 +3485,7 @@ static void buildFunctionList(const Entry *root) // merge ingroup specifiers if (md->getGroupDef()==0 && !root->groups.empty()) { - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); } else if (md->getGroupDef()!=0 && root->groups.empty()) { @@ -3452,130 +3511,16 @@ static void buildFunctionList(const Entry *root) } } } + if (found) + { + md_found = md.get(); + break; + } } } if (!found) /* global function is unique with respect to the file */ { - Debug::print(Debug::Functions,0," --> new function %s found!\n",qPrint(rname)); - //printf("New function type='%s' name='%s' args='%s' bodyLine=%d\n", - // root->type.data(),rname.data(),root->args.data(),root->bodyLine); - - // new global function - QCString name=removeRedundantWhiteSpace(rname); - md=createMemberDef( - root->fileName,root->startLine,root->startColumn, - root->type,name,root->args,root->exception, - root->protection,root->virt,root->stat,Member, - MemberType_Function, - !root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList(), - root->argList,root->metaData); - - md->setTagInfo(root->tagInfo()); - md->setLanguage(root->lang); - md->setId(root->id); - //md->setDefFile(root->fileName); - //md->setDefLine(root->startLine); - md->setDocumentation(root->doc,root->docFile,root->docLine); - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); - md->setDocsForDefinition(!root->proto); - md->setTypeConstraints(root->typeConstr); - //md->setBody(root->body); - md->setBodySegment(root->bodyLine,root->endBodyLine); - FileDef *fd=root->fileDef(); - md->setBodyDef(fd); - md->addSectionsToDefinition(root->anchors); - md->setMemberSpecifiers(root->spec); - md->setMemberGroupId(root->mGrpId); - - // see if the function is inside a namespace that was not part of - // the name already (in that case nd should be non-zero already) - if (nd==0 && root->parent()->section == Entry::NAMESPACE_SEC ) - { - //QCString nscope=removeAnonymousScopes(root->parent()->name); - QCString nscope=root->parent()->name; - if (!nscope.isEmpty()) - { - nd = getResolvedNamespace(nscope); - } - } - - if (!scope.isEmpty()) - { - QCString sep = getLanguageSpecificSeparator(root->lang); - if (sep!="::") - { - scope = substitute(scope,"::",sep); - } - scope+=sep; - } - - QCString def; - //QCString optArgs = root->argList.empty() ? QCString() : root->args; - if (!root->type.isEmpty()) - { - def=root->type+" "+scope+name; //+optArgs; - } - else - { - def=scope+name; //+optArgs; - } - Debug::print(Debug::Functions,0, - " Global Function:\n" - " '%s' '%s'::'%s' '%s' proto=%d\n" - " def='%s'\n", - qPrint(root->type), - qPrint(root->parent()->name), - qPrint(rname), - qPrint(root->args), - root->proto, - qPrint(def) - ); - md->setDefinition(def); - md->enableCallGraph(root->callGraph); - md->enableCallerGraph(root->callerGraph); - md->enableReferencedByRelation(root->referencedByRelation); - md->enableReferencesRelation(root->referencesRelation); - //if (root->mGrpId!=-1) - //{ - // md->setMemberGroup(memberGroupDict[root->mGrpId]); - //} - - md->setRefItems(root->sli); - if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') - { - // add member to namespace - md->setNamespace(nd); - nd->insertMember(md); - } - if (fd) - { - // add member to the file (we do this even if we have already - // inserted it into the namespace) - md->setFileDef(fd); - fd->insertMember(md); - } - - // add member to the list of file members - //printf("Adding member=%s\n",md->name().data()); - MemberName *mn; - if ((mn=Doxygen::functionNameSDict->find(name))) - { - mn->append(md); - } - else - { - mn = new MemberName(name); - mn->append(md); - Doxygen::functionNameSDict->append(name,mn); - } - addMemberToGroups(root,md); - if (root->relatesType == Simple) // if this is a relatesalso command, - // allow find Member to pick it up - { - root->markAsProcessed(); // Otherwise we have finished with this entry. - } + addGlobalFunction(root,rname,scope,nd); } else { @@ -3584,7 +3529,7 @@ static void buildFunctionList(const Entry *root) { // add member to the file (we do this even if we have already // inserted it into the namespace) - fd->insertMember(md); + fd->insertMember(md_found); } } @@ -3611,32 +3556,28 @@ static void buildFunctionList(const Entry *root) static void findFriends() { //printf("findFriends()\n"); - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); - MemberName *fn; - for (;(fn=fnli.current());++fnli) // for each global function name + for (const auto &fn : *Doxygen::functionNameLinkedMap) // for each global function name { //printf("Function name='%s'\n",fn->memberName()); MemberName *mn; - if ((mn=Doxygen::memberNameSDict->find(fn->memberName()))) + if ((mn=Doxygen::memberNameLinkedMap->find(fn->memberName()))) { // there are members with the same name //printf("Function name is also a member name\n"); - MemberNameIterator fni(*fn); - MemberDef *fmd; - for (;(fmd=fni.current());++fni) // for each function with that name + // for each function with that name + for (const auto &fmd : *fn) { - const MemberDef *cfmd = const_cast<const MemberDef*>(fmd); - MemberNameIterator mni(*mn); - MemberDef *mmd; - for (;(mmd=mni.current());++mni) // for each member with that name + const MemberDef *cfmd = fmd.get(); + // for each member with that name + for (const auto &mmd : *mn) { - const MemberDef *cmmd = const_cast<const MemberDef*>(mmd); + const MemberDef *cmmd = mmd.get(); //printf("Checking for matching arguments // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n", // mmd->isRelated(),mmd->isFriend(),mmd->isFunction()); if ((cmmd->isFriend() || (cmmd->isRelated() && cmmd->isFunction())) && !fmd->isAlias() && !mmd->isAlias() && - matchArguments2(cmmd->getOuterScope(), cmmd->getFileDef(), cmmd->argumentList(), - cfmd->getOuterScope(), cfmd->getFileDef(), cfmd->argumentList(), + matchArguments2(cmmd->getOuterScope(), cmmd->getFileDef(), &cmmd->argumentList(), + cfmd->getOuterScope(), cfmd->getFileDef(), &cfmd->argumentList(), TRUE ) @@ -3673,13 +3614,13 @@ static void findFriends() //printf("body mmd %d fmd %d\n",mmd->getStartBodyLine(),fmd->getStartBodyLine()); if (mmd->getStartBodyLine()==-1 && fmd->getStartBodyLine()!=-1) { - mmd->setBodySegment(fmd->getStartBodyLine(),fmd->getEndBodyLine()); + mmd->setBodySegment(fmd->getDefLine(),fmd->getStartBodyLine(),fmd->getEndBodyLine()); mmd->setBodyDef(fmd->getBodyDef()); //mmd->setBodyMember(fmd); } else if (mmd->getStartBodyLine()!=-1 && fmd->getStartBodyLine()==-1) { - fmd->setBodySegment(mmd->getStartBodyLine(),mmd->getEndBodyLine()); + fmd->setBodySegment(mmd->getDefLine(),mmd->getStartBodyLine(),mmd->getEndBodyLine()); fmd->setBodyDef(mmd->getBodyDef()); //fmd->setBodyMember(mmd); } @@ -3708,26 +3649,23 @@ static void transferFunctionDocumentation() //printf("---- transferFunctionDocumentation()\n"); // find matching function declaration and definitions. - MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict); - MemberName *mn; - for (;(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { //printf("memberName=%s count=%d\n",mn->memberName(),mn->count()); - MemberDef *mdef=0,*mdec=0; - MemberNameIterator mni1(*mn); /* find a matching function declaration and definition for this function */ - for (;(mdec=mni1.current());++mni1) + for (const auto &mdec : *mn) { if (mdec->isPrototype() || (mdec->isVariable() && mdec->isExternal()) ) { - MemberNameIterator mni2(*mn); - for (;(mdef=mni2.current());++mni2) + for (const auto &mdef : *mn) { - if (mdec!=mdef && !mdec->isAlias() && !mdef->isAlias()) + if (mdec!=mdef && + !mdec->isAlias() && !mdef->isAlias() && + mdec->getNamespaceDef()==mdef->getNamespaceDef()) { - combineDeclarationAndDefinition(mdec,mdef); + combineDeclarationAndDefinition(mdec.get(),mdef.get()); } } } @@ -3739,15 +3677,13 @@ static void transferFunctionDocumentation() static void transferFunctionReferences() { - MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict); - MemberName *mn; - for (;(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *md,*mdef=0,*mdec=0; - MemberNameIterator mni(*mn); + MemberDef *mdef=0,*mdec=0; /* find a matching function declaration and definition for this function */ - for (;(md=mni.current());++mni) + for (const auto &md_p : *mn) { + MemberDef *md = md_p.get(); if (md->isPrototype()) mdec=md; else if (md->isVariable() && md->isExternal()) @@ -3757,14 +3693,16 @@ static void transferFunctionReferences() mdef=md; else if (md->isVariable() && !md->isExternal() && !md->isStatic()) mdef=md; + + if (mdef && mdec) break; } if (mdef && mdec) { ArgumentList &mdefAl = mdef->argumentList(); ArgumentList &mdecAl = mdec->argumentList(); if ( - matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl, - mdec->getOuterScope(),mdec->getFileDef(),mdecAl, + matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl, + mdec->getOuterScope(),mdec->getFileDef(),&mdecAl, TRUE ) ) /* match found */ @@ -3833,29 +3771,25 @@ static void transferRelatedFunctionDocumentation() { // find match between function declaration and definition for // related functions - MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict); - MemberName *mn; - for (mnli.toFirst();(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); /* find a matching function declaration and definition for this function */ - for (mni.toFirst();(md=mni.current());++mni) // for each global function + // for each global function + for (const auto &md : *mn) { //printf(" Function '%s'\n",md->name().data()); MemberName *rmn; - if ((rmn=Doxygen::memberNameSDict->find(md->name()))) // check if there is a member with the same name + if ((rmn=Doxygen::memberNameLinkedMap->find(md->name()))) // check if there is a member with the same name { //printf(" Member name found\n"); - MemberDef *rmd; - MemberNameIterator rmni(*rmn); - for (rmni.toFirst();(rmd=rmni.current());++rmni) // for each member with the same name + // for each member with the same name + for (const auto &rmd : *rmn) { //printf(" Member found: related='%d'\n",rmd->isRelated()); if ((rmd->isRelated() || rmd->isForeign()) && // related function !md->isAlias() && !rmd->isAlias() && - matchArguments2( md->getOuterScope(), md->getFileDef(), md->argumentList(), - rmd->getOuterScope(),rmd->getFileDef(),rmd->argumentList(), + matchArguments2( md->getOuterScope(), md->getFileDef(), &md->argumentList(), + rmd->getOuterScope(),rmd->getFileDef(),&rmd->argumentList(), TRUE ) ) @@ -3951,160 +3885,148 @@ static void findUsedClassesForClass(const Entry *root, ClassDef *masterCd, ClassDef *instanceCd, bool isArtificial, - const ArgumentList &actualArgs=ArgumentList(), + const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(), QDict<int> *templateNames=0 ) { masterCd->setVisited(TRUE); const ArgumentList &formalArgs = masterCd->templateArguments(); - if (masterCd->memberNameInfoSDict()) + for (auto &mni : masterCd->memberNameInfoLinkedMap()) { - MemberNameInfoSDict::Iterator mnili(*masterCd->memberNameInfoSDict()); - MemberNameInfo *mni; - for (;(mni=mnili.current());++mnili) + for (auto &mi : *mni) { - MemberNameInfoIterator mnii(*mni); - MemberInfo *mi; - for (mnii.toFirst();(mi=mnii.current());++mnii) + MemberDef *md=mi->memberDef(); + if (md->isVariable() || md->isObjCProperty()) // for each member variable in this class { - MemberDef *md=mi->memberDef; - if (md->isVariable() || md->isObjCProperty()) // for each member variable in this class + //printf(" Found variable %s in class %s\n",md->name().data(),masterCd->name().data()); + QCString type = normalizeNonTemplateArgumentsInString(md->typeString(),masterCd,formalArgs); + QCString typedefValue = resolveTypeDef(masterCd,type); + if (!typedefValue.isEmpty()) { - //printf(" Found variable %s in class %s\n",md->name().data(),masterCd->name().data()); - QCString type = normalizeNonTemplateArgumentsInString(md->typeString(),masterCd,formalArgs); - QCString typedefValue = resolveTypeDef(masterCd,type); - if (!typedefValue.isEmpty()) + type = typedefValue; + } + int pos=0; + QCString usedClassName; + QCString templSpec; + bool found=FALSE; + // the type can contain template variables, replace them if present + type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs); + + //printf(" template substitution gives=%s\n",type.data()); + while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,root->lang)!=-1) + { + // find the type (if any) that matches usedClassName + const ClassDef *typeCd = getResolvedClass(masterCd, + masterCd->getFileDef(), + usedClassName, + 0,0, + FALSE,TRUE + ); + //printf("====> usedClassName=%s -> typeCd=%s\n", + // usedClassName.data(),typeCd?typeCd->name().data():"<none>"); + if (typeCd) { - type = typedefValue; + usedClassName = typeCd->name(); } - int pos=0; - QCString usedClassName; - QCString templSpec; - bool found=FALSE; - // the type can contain template variables, replace them if present - type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs); - //printf(" template substitution gives=%s\n",type.data()); - while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,root->lang)!=-1) + int sp=usedClassName.find('<'); + if (sp==-1) sp=0; + int si=usedClassName.findRev("::",sp); + if (si!=-1) { - // find the type (if any) that matches usedClassName - const ClassDef *typeCd = getResolvedClass(masterCd, - masterCd->getFileDef(), - usedClassName, - 0,0, - FALSE,TRUE - ); - //printf("====> usedClassName=%s -> typeCd=%s\n", - // usedClassName.data(),typeCd?typeCd->name().data():"<none>"); - if (typeCd) - { - usedClassName = typeCd->name(); - } + // replace any namespace aliases + replaceNamespaceAliases(usedClassName,si); + } + // add any template arguments to the class + QCString usedName = removeRedundantWhiteSpace(usedClassName+templSpec); + //printf(" usedName=%s\n",usedName.data()); - int sp=usedClassName.find('<'); - if (sp==-1) sp=0; - int si=usedClassName.findRev("::",sp); - if (si!=-1) - { - // replace any namespace aliases - replaceNamespaceAliases(usedClassName,si); - } - // add any template arguments to the class - QCString usedName = removeRedundantWhiteSpace(usedClassName+templSpec); - //printf(" usedName=%s\n",usedName.data()); + bool delTempNames=FALSE; + if (templateNames==0) + { + templateNames = getTemplateArgumentsInName(formalArgs,usedName); + delTempNames=TRUE; + } + BaseInfo bi(usedName,Public,Normal); + findClassRelation(root,context,instanceCd,&bi,templateNames,TemplateInstances,isArtificial); - bool delTempNames=FALSE; - if (templateNames==0) + for (const Argument &arg : masterCd->templateArguments()) + { + if (arg.name==usedName) // type is a template argument { - templateNames = getTemplateArgumentsInName(formalArgs,usedName); - delTempNames=TRUE; - } - BaseInfo bi(usedName,Public,Normal); - findClassRelation(root,context,instanceCd,&bi,templateNames,TemplateInstances,isArtificial); + found=TRUE; + Debug::print(Debug::Classes,0," New used class '%s'\n", qPrint(usedName)); - int count=0; - for (const Argument &arg : masterCd->templateArguments()) - { - if (arg.name==usedName) // type is a template argument + ClassDef *usedCd = Doxygen::hiddenClasses->find(usedName); + if (usedCd==0) { - found=TRUE; - Debug::print(Debug::Classes,0," New used class '%s'\n", qPrint(usedName)); - - ClassDef *usedCd = Doxygen::hiddenClasses->find(usedName); - if (usedCd==0) - { - usedCd = createClassDef( - masterCd->getDefFileName(),masterCd->getDefLine(), - masterCd->getDefColumn(), - usedName, - ClassDef::Class); - //printf("making %s a template argument!!!\n",usedCd->name().data()); - usedCd->makeTemplateArgument(); - usedCd->setUsedOnly(TRUE); - usedCd->setLanguage(masterCd->getLanguage()); - Doxygen::hiddenClasses->append(usedName,usedCd); - } - if (isArtificial) usedCd->setArtificial(TRUE); - Debug::print(Debug::Classes,0," Adding used class '%s' (1)\n", qPrint(usedCd->name())); - instanceCd->addUsedClass(usedCd,md->name(),md->protection()); - usedCd->addUsedByClass(instanceCd,md->name(),md->protection()); + usedCd = createClassDef( + masterCd->getDefFileName(),masterCd->getDefLine(), + masterCd->getDefColumn(), + usedName, + ClassDef::Class); + //printf("making %s a template argument!!!\n",usedCd->name().data()); + usedCd->makeTemplateArgument(); + usedCd->setUsedOnly(TRUE); + usedCd->setLanguage(masterCd->getLanguage()); + Doxygen::hiddenClasses->append(usedName,usedCd); } + if (isArtificial) usedCd->setArtificial(TRUE); + Debug::print(Debug::Classes,0," Adding used class '%s' (1)\n", qPrint(usedCd->name())); + instanceCd->addUsedClass(usedCd,md->name(),md->protection()); + usedCd->addUsedByClass(instanceCd,md->name(),md->protection()); } + } - if (!found) - { - ClassDef *usedCd=findClassWithinClassContext(context,masterCd,usedName); - //printf("Looking for used class %s: result=%s master=%s\n", - // usedName.data(),usedCd?usedCd->name().data():"<none>",masterCd?masterCd->name().data():"<none>"); + if (!found) + { + ClassDef *usedCd=findClassWithinClassContext(context,masterCd,usedName); + //printf("Looking for used class %s: result=%s master=%s\n", + // usedName.data(),usedCd?usedCd->name().data():"<none>",masterCd?masterCd->name().data():"<none>"); - if (usedCd) - { - found=TRUE; - Debug::print(Debug::Classes,0," Adding used class '%s' (2)\n", qPrint(usedCd->name())); - instanceCd->addUsedClass(usedCd,md->name(),md->protection()); // class exists - usedCd->addUsedByClass(instanceCd,md->name(),md->protection()); - } - } - if (delTempNames) + if (usedCd) { - delete templateNames; - templateNames=0; + found=TRUE; + Debug::print(Debug::Classes,0," Adding used class '%s' (2)\n", qPrint(usedCd->name())); + instanceCd->addUsedClass(usedCd,md->name(),md->protection()); // class exists + usedCd->addUsedByClass(instanceCd,md->name(),md->protection()); } } - if (!found && !type.isEmpty()) // used class is not documented in any scope + if (delTempNames) { - ClassDef *usedCd = Doxygen::hiddenClasses->find(type); - if (usedCd==0 && !Config_getBool(HIDE_UNDOC_RELATIONS)) - { - if (type.right(2)=="(*" || type.right(2)=="(^") // type is a function pointer - { - type+=md->argsString(); - } - Debug::print(Debug::Classes,0," New undocumented used class '%s'\n", qPrint(type)); - usedCd = createClassDef( - masterCd->getDefFileName(),masterCd->getDefLine(), - masterCd->getDefColumn(), - type,ClassDef::Class); - usedCd->setUsedOnly(TRUE); - usedCd->setLanguage(masterCd->getLanguage()); - Doxygen::hiddenClasses->append(type,usedCd); - } - if (usedCd) + delete templateNames; + templateNames=0; + } + } + if (!found && !type.isEmpty()) // used class is not documented in any scope + { + ClassDef *usedCd = Doxygen::hiddenClasses->find(type); + if (usedCd==0 && !Config_getBool(HIDE_UNDOC_RELATIONS)) + { + if (type.right(2)=="(*" || type.right(2)=="(^") // type is a function pointer { - if (isArtificial) usedCd->setArtificial(TRUE); - Debug::print(Debug::Classes,0," Adding used class '%s' (3)\n", qPrint(usedCd->name())); - instanceCd->addUsedClass(usedCd,md->name(),md->protection()); - usedCd->addUsedByClass(instanceCd,md->name(),md->protection()); + type+=md->argsString(); } + Debug::print(Debug::Classes,0," New undocumented used class '%s'\n", qPrint(type)); + usedCd = createClassDef( + masterCd->getDefFileName(),masterCd->getDefLine(), + masterCd->getDefColumn(), + type,ClassDef::Class); + usedCd->setUsedOnly(TRUE); + usedCd->setLanguage(masterCd->getLanguage()); + Doxygen::hiddenClasses->append(type,usedCd); + } + if (usedCd) + { + if (isArtificial) usedCd->setArtificial(TRUE); + Debug::print(Debug::Classes,0," Adding used class '%s' (3)\n", qPrint(usedCd->name())); + instanceCd->addUsedClass(usedCd,md->name(),md->protection()); + usedCd->addUsedByClass(instanceCd,md->name(),md->protection()); } } } } } - else - { - //printf("no members for class %s (%p)\n",masterCd->name().data(),masterCd); - } } static void findBaseClassesForClass( @@ -4114,7 +4036,7 @@ static void findBaseClassesForClass( ClassDef *instanceCd, FindBaseClassRelation_Mode mode, bool isArtificial, - const ArgumentList &actualArgs=ArgumentList(), + const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(), QDict<int> *templateNames=0 ) { @@ -4211,8 +4133,7 @@ static bool findTemplateInstanceRelation(const Entry *root, const Entry *templateRoot = it->second; Debug::print(Debug::Classes,0," template root found %s templSpec=%s!\n", qPrint(templateRoot->name),qPrint(templSpec)); - ArgumentList templArgs; - stringToArgumentList(root->lang,templSpec,templArgs); + std::unique_ptr<ArgumentList> templArgs = stringToArgumentList(root->lang,templSpec); findBaseClassesForClass(templateRoot,context,templateClass,instanceClass, TemplateInstances,isArtificial,templArgs,templateNames); @@ -4510,10 +4431,10 @@ static bool findClassRelation( { // for PHP the "use A\B as C" construct map class C to A::B, so we lookup // the class name also in the alias mapping. - QCString *aliasName = Doxygen::namespaceAliasDict[baseClassName]; - if (aliasName) // see if it is indeed a class. + auto it = Doxygen::namespaceAliasMap.find(baseClassName.data()); + if (it!=Doxygen::namespaceAliasMap.end()) // see if it is indeed a class. { - baseClass=getClass(*aliasName); + baseClass=getClass(it->second.c_str()); found = baseClass!=0 && baseClass!=cd; } } @@ -4610,7 +4531,7 @@ static bool findClassRelation( Doxygen::classSDict->append(baseClassName,baseClass); if (isArtificial) baseClass->setArtificial(TRUE); baseClass->setLanguage(root->lang); - int si = baseClassName.findRev("::"); + si = baseClassName.findRev("::"); if (si!=-1) // class is nested { Definition *sd = findScopeFromQualifiedName(Doxygen::globalScope,baseClassName.left(si),0,root->tagInfo()); @@ -4787,7 +4708,7 @@ static void computeClassRelations() { findBaseClassesForClass(root,cd,cd,cd,DocumentedOnly,FALSE); } - int numMembers = cd && cd->memberNameInfoSDict() ? cd->memberNameInfoSDict()->count() : 0; + size_t numMembers = cd ? cd->memberNameInfoLinkedMap().size() : 0; if ((cd==0 || (!cd->hasDocumentation() && !cd->isReference())) && numMembers>0 && bName.right(2)!="::") { @@ -4825,8 +4746,7 @@ static void computeTemplateClassRelations() { Debug::print(Debug::Classes,0," Template instance %s : \n",qPrint(tcd->name())); QCString templSpec = tdi.currentKey(); - ArgumentList templArgs; - stringToArgumentList(tcd->getLanguage(),templSpec,templArgs); + std::unique_ptr<ArgumentList> templArgs = stringToArgumentList(tcd->getLanguage(),templSpec); for (const BaseInfo &bi : root->extends) { // check if the base class is a template argument @@ -4846,9 +4766,9 @@ static void computeTemplateClassRelations() int templIndex = *qdi.current(); Argument actArg; bool hasActArg=FALSE; - if (templIndex<(int)templArgs.size()) + if (templIndex<(int)templArgs->size()) { - actArg=templArgs.at(templIndex); + actArg=templArgs->at(templIndex); hasActArg=TRUE; } if (hasActArg && @@ -4888,13 +4808,9 @@ static void computeMemberReferences() { cd->computeAnchors(); } - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->computeAnchors(); } @@ -4927,13 +4843,9 @@ static void addListReferences() } } - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->addListReferences(); } @@ -4966,7 +4878,7 @@ static void addListReferences() name = pd->getGroupDef()->getOutputFileBase(); } { - const std::vector<ListItemInfo> &xrefItems = pd->xrefListItems(); + const RefItemVector &xrefItems = pd->xrefListItems(); addRefItem(xrefItems, name, theTranslator->trPage(TRUE,TRUE), @@ -4983,7 +4895,7 @@ static void addListReferences() //{ // name = dd->getGroupDef()->getOutputFileBase(); //} - const std::vector<ListItemInfo> &xrefItems = dd->xrefListItems(); + const RefItemVector &xrefItems = dd->xrefListItems(); addRefItem(xrefItems, name, theTranslator->trDir(TRUE,TRUE), @@ -4995,9 +4907,7 @@ static void addListReferences() static void generateXRefPages() { - QDictIterator<RefList> di(*Doxygen::xrefLists); - RefList *rl; - for (di.toFirst();(rl=di.current());++di) + for (RefListManager::Ptr &rl : RefListManager::instance()) { rl->generatePage(); } @@ -5050,8 +4960,8 @@ static void addMemberDocs(const Entry *root, else { if ( - matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl, - rscope,rfd,root->argList, + matchArguments2( md->getOuterScope(), md->getFileDef(), &mdAl, + rscope,rfd,&root->argList, TRUE ) ) @@ -5110,7 +5020,7 @@ static void addMemberDocs(const Entry *root, ) { //printf("Setting new body segment [%d,%d]\n",root->bodyLine,root->endBodyLine); - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setBodyDef(rfd); } @@ -5181,19 +5091,17 @@ static bool findGlobalMember(const Entry *root, QCString n=name; if (n.isEmpty()) return FALSE; if (n.find("::")!=-1) return FALSE; // skip undefined class members - MemberName *mn=Doxygen::functionNameSDict->find(n+tempArg); // look in function dictionary + MemberName *mn=Doxygen::functionNameLinkedMap->find(n+tempArg); // look in function dictionary if (mn==0) { - mn=Doxygen::functionNameSDict->find(n); // try without template arguments + mn=Doxygen::functionNameLinkedMap->find(n); // try without template arguments } if (mn) // function name defined { Debug::print(Debug::FindMembers,0,"3. Found symbol scope\n"); //int count=0; - MemberNameIterator mni(*mn); - MemberDef *md; bool found=FALSE; - for (mni.toFirst();(md=mni.current()) && !found;++mni) + for (const auto &md : *mn) { const NamespaceDef *nd=0; if (md->isAlias() && md->getOuterScope() && @@ -5229,12 +5137,12 @@ static bool findGlobalMember(const Entry *root, NamespaceDef *rnd = 0; if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceSDict->find(namespaceName); - const ArgumentList &mdAl = const_cast<const MemberDef *>(md)->argumentList(); + const ArgumentList &mdAl = const_cast<const MemberDef *>(md.get())->argumentList(); bool matching= (mdAl.empty() && root->argList.empty()) || md->isVariable() || md->isTypedef() || /* in case of function pointers */ - matchArguments2(md->getOuterScope(),const_cast<const MemberDef *>(md)->getFileDef(),mdAl, - rnd ? rnd : Doxygen::globalScope,fd,root->argList, + matchArguments2(md->getOuterScope(),const_cast<const MemberDef *>(md.get())->getFileDef(),&mdAl, + rnd ? rnd : Doxygen::globalScope,fd,&root->argList, FALSE); // for template members we need to check if the number of @@ -5259,7 +5167,7 @@ static bool findGlobalMember(const Entry *root, // put the comment block at the first syntactically matching member. if (matching && md->isStatic() && md->getDefFileName()!=root->fileName && - mn->count()>1) + mn->size()>1) { matching = FALSE; } @@ -5282,6 +5190,7 @@ static bool findGlobalMember(const Entry *root, Debug::print(Debug::FindMembers,0,"5. Match found\n"); addMemberDocs(root,md->resolveAlias(),decl,&root->argList,FALSE,root->spec); found=TRUE; + break; } } } @@ -5291,10 +5200,10 @@ static bool findGlobalMember(const Entry *root, if (!root->argList.empty()) fullFuncDecl+=argListToString(root->argList,TRUE); QCString warnMsg = QCString("no matching file member found for \n")+substitute(fullFuncDecl,"%","%%"); - if (mn->count()>0) + if (mn->size()>0) { warnMsg+="\nPossible candidates:\n"; - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { warnMsg+=" '"; warnMsg+=substitute(md->declaration(),"%","%%"); @@ -5302,7 +5211,7 @@ static bool findGlobalMember(const Entry *root, " of file "+md->getDefFileName()+"\n"; } } - warn(root->fileName,root->startLine,warnMsg); + warn(root->fileName,root->startLine, "%s", warnMsg.data()); } } else // got docs for an undefined member! @@ -5324,8 +5233,8 @@ static bool findGlobalMember(const Entry *root, } static bool isSpecialization( - const std::vector<ArgumentList> &srcTempArgLists, - const std::vector<ArgumentList> &dstTempArgLists + const ArgumentLists &srcTempArgLists, + const ArgumentLists &dstTempArgLists ) { auto srcIt = srcTempArgLists.begin(); @@ -5351,8 +5260,8 @@ static bool scopeIsTemplate(const Definition *d) } static QCString substituteTemplatesInString( - const std::vector<ArgumentList> &srcTempArgLists, - const std::vector<ArgumentList> &dstTempArgLists, + const ArgumentLists &srcTempArgLists, + const ArgumentLists &dstTempArgLists, const QCString &src ) { @@ -5430,8 +5339,8 @@ static QCString substituteTemplatesInString( } static void substituteTemplatesInArgList( - const std::vector<ArgumentList> &srcTempArgLists, - const std::vector<ArgumentList> &dstTempArgLists, + const ArgumentLists &srcTempArgLists, + const ArgumentLists &dstTempArgLists, const ArgumentList &src, ArgumentList &dst ) @@ -5457,18 +5366,517 @@ static void substituteTemplatesInArgList( ++dstIt; } } - dst.constSpecifier = src.constSpecifier; - dst.volatileSpecifier = src.volatileSpecifier; - dst.pureSpecifier = src.pureSpecifier; - dst.trailingReturnType = substituteTemplatesInString( + dst.setConstSpecifier(src.constSpecifier()); + dst.setVolatileSpecifier(src.volatileSpecifier()); + dst.setPureSpecifier(src.pureSpecifier()); + dst.setTrailingReturnType(substituteTemplatesInString( srcTempArgLists,dstTempArgLists, - src.trailingReturnType); + src.trailingReturnType())); //printf("substituteTemplatesInArgList: replacing %s with %s\n", // argListToString(src).data(),argListToString(dst).data() // ); } +//------------------------------------------------------------------------------------------- + +static void addLocalObjCMethod(const Entry *root, + const QCString &scopeName, + const QCString &funcType,const QCString &funcName,const QCString &funcArgs, + const QCString &exceptions,const QCString &funcDecl, + uint64 spec) +{ + //printf("scopeName='%s' className='%s'\n",scopeName.data(),className.data()); + ClassDef *cd=0; + if (Config_getBool(EXTRACT_LOCAL_METHODS) && (cd=getClass(scopeName))) + { + Debug::print(Debug::FindMembers,0,"4. Local objective C method %s\n" + " scopeName=%s\n",qPrint(root->name),qPrint(scopeName)); + //printf("Local objective C method '%s' of class '%s' found\n",root->name.data(),cd->name().data()); + std::unique_ptr<MemberDef> md { createMemberDef( + root->fileName,root->startLine,root->startColumn, + funcType,funcName,funcArgs,exceptions, + root->protection,root->virt,root->stat,Member, + MemberType_Function,ArgumentList(),root->argList,root->metaData) }; + md->setTagInfo(root->tagInfo()); + md->setLanguage(root->lang); + md->setId(root->id); + md->makeImplementationDetail(); + md->setMemberClass(cd); + md->setDefinition(funcDecl); + md->enableCallGraph(root->callGraph); + md->enableCallerGraph(root->callerGraph); + md->enableReferencedByRelation(root->referencedByRelation); + md->enableReferencesRelation(root->referencesRelation); + md->setDocumentation(root->doc,root->docFile,root->docLine); + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); + md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); + md->setDocsForDefinition(!root->proto); + md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); + md->addSectionsToDefinition(root->anchors); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); + FileDef *fd=root->fileDef(); + md->setBodyDef(fd); + md->setMemberSpecifiers(spec); + md->setMemberGroupId(root->mGrpId); + cd->insertMember(md.get()); + cd->insertUsedFile(fd); + md->setRefItems(root->sli); + + MemberName *mn = Doxygen::memberNameLinkedMap->add(root->name); + mn->push_back(std::move(md)); + } + else + { + // local objective C method found for class without interface + } +} + +//------------------------------------------------------------------------------------------- + +static void addMemberFunction(const Entry *root, + MemberName *mn, + const QCString &scopeName, + const QCString &namespaceName, + const QCString &className, + const QCString &funcTyp, + const QCString &funcName, + const QCString &funcArgs, + const QCString &funcTempList, + const QCString &exceptions, + const QCString &type, + const QCString &args, + bool isFriend, + uint64 spec, + const QCString &relates, + const QCString &funcDecl, + bool overloaded, + bool isFunc) +{ + QCString funcType = funcTyp; + int count=0; + int noMatchCount=0; + bool memFound=FALSE; + for (const auto &md : *mn) + { + ClassDef *cd=md->getClassDef(); + Debug::print(Debug::FindMembers,0, + "3. member definition found, " + "scope needed='%s' scope='%s' args='%s' fileName=%s\n", + qPrint(scopeName),cd ? qPrint(cd->name()) : "<none>", + qPrint(md->argsString()), + qPrint(root->fileName)); + //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data()); + FileDef *fd=root->fileDef(); + NamespaceDef *nd=0; + if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName); + + //printf("scopeName %s->%s\n",scopeName.data(), + // stripTemplateSpecifiersFromScope(scopeName,FALSE).data()); + + const ClassDef *tcd=findClassDefinition(fd,nd,scopeName); + if (tcd==0 && cd && stripAnonymousNamespaceScope(cd->name())==scopeName) + { + // don't be fooled by anonymous scopes + tcd=cd; + } + //printf("Looking for %s inside nd=%s result=%p (%s) cd=%p\n", + // scopeName.data(),nd?nd->name().data():"<none>",tcd,tcd?tcd->name().data():"",cd); + + if (cd && tcd==cd) // member's classes match + { + Debug::print(Debug::FindMembers,0, + "4. class definition %s found\n",cd->name().data()); + + // get the template parameter lists found at the member declaration + ArgumentLists declTemplArgs = cd->getTemplateParameterLists(); + const ArgumentList &templAl = md->templateArguments(); + if (!templAl.empty()) + { + declTemplArgs.push_back(templAl); + } + + // get the template parameter lists found at the member definition + const ArgumentLists &defTemplArgs = root->tArgLists; + //printf("defTemplArgs=%p\n",defTemplArgs); + + // do we replace the decl argument lists with the def argument lists? + bool substDone=FALSE; + ArgumentList argList; + + /* substitute the occurrences of class template names in the + * argument list before matching + */ + const ArgumentList &mdAl = md->argumentList(); + if (declTemplArgs.size()>0 && declTemplArgs.size()==defTemplArgs.size()) + { + /* the function definition has template arguments + * and the class definition also has template arguments, so + * we must substitute the template names of the class by that + * of the function definition before matching. + */ + substituteTemplatesInArgList(declTemplArgs,defTemplArgs,mdAl,argList); + + substDone=TRUE; + } + else /* no template arguments, compare argument lists directly */ + { + argList = mdAl; + } + + Debug::print(Debug::FindMembers,0, + "5. matching '%s'<=>'%s' className=%s namespaceName=%s\n", + qPrint(argListToString(argList,TRUE)),qPrint(argListToString(root->argList,TRUE)), + qPrint(className),qPrint(namespaceName) + ); + + bool matching= + md->isVariable() || md->isTypedef() || // needed for function pointers + matchArguments2( + md->getClassDef(),md->getFileDef(),&argList, + cd,fd,&root->argList, + TRUE); + + if (md->getLanguage()==SrcLangExt_ObjC && md->isVariable() && (root->section&Entry::FUNCTION_SEC)) + { + matching = FALSE; // don't match methods and attributes with the same name + } + + // for template member we also need to check the return type + if (!md->templateArguments().empty() && !root->tArgLists.empty()) + { + QCString memType = md->typeString(); + memType.stripPrefix("static "); // see bug700696 + funcType=substitute(stripTemplateSpecifiersFromScope(funcType,TRUE), + className+"::",""); // see bug700693 & bug732594 + memType=substitute(stripTemplateSpecifiersFromScope(memType,TRUE), + className+"::",""); // see bug758900 + Debug::print(Debug::FindMembers,0, + "5b. Comparing return types '%s'<->'%s' #args %d<->%d\n", + qPrint(md->typeString()),qPrint(funcType), + md->templateArguments().size(),root->tArgLists.back().size()); + if (md->templateArguments().size()!=root->tArgLists.back().size() || + qstrcmp(memType,funcType)) + { + //printf(" ---> no matching\n"); + matching = FALSE; + } + } + bool rootIsUserDoc = (root->section&Entry::MEMBERDOC_SEC)!=0; + bool classIsTemplate = scopeIsTemplate(md->getClassDef()); + bool mdIsTemplate = md->templateArguments().hasParameters(); + bool classOrMdIsTemplate = mdIsTemplate || classIsTemplate; + bool rootIsTemplate = !root->tArgLists.empty(); + //printf("classIsTemplate=%d mdIsTemplate=%d rootIsTemplate=%d\n",classIsTemplate,mdIsTemplate,rootIsTemplate); + if (!rootIsUserDoc && // don't check out-of-line @fn references, see bug722457 + (mdIsTemplate || rootIsTemplate) && // either md or root is a template + ((classOrMdIsTemplate && !rootIsTemplate) || (!classOrMdIsTemplate && rootIsTemplate)) + ) + { + // Method with template return type does not match method without return type + // even if the parameters are the same. See also bug709052 + Debug::print(Debug::FindMembers,0, + "5b. Comparing return types: template v.s. non-template\n"); + matching = FALSE; + } + + + Debug::print(Debug::FindMembers,0, + "6. match results of matchArguments2 = %d substDone=%d\n",matching,substDone); + + if (substDone) // found a new argument list + { + if (matching) // replace member's argument list + { + md->setDefinitionTemplateParameterLists(root->tArgLists); + md->moveArgumentList(std::make_unique<ArgumentList>(argList)); + } + else // no match + { + if (!funcTempList.isEmpty() && + isSpecialization(declTemplArgs,defTemplArgs)) + { + // check if we are dealing with a partial template + // specialization. In this case we add it to the class + // even though the member arguments do not match. + + addMethodToClass(root,cd,type,md->name(),args,isFriend, + md->protection(),md->isStatic(),md->virtualness(),spec,relates); + return; + } + } + } + if (matching) + { + addMemberDocs(root,md.get(),funcDecl,0,overloaded,spec); + count++; + memFound=TRUE; + } + } + else if (cd && cd!=tcd) // we did find a class with the same name as cd + // but in a different namespace + { + noMatchCount++; + } + + if (memFound) break; + } + if (count==0 && root->parent() && + root->parent()->section==Entry::OBJCIMPL_SEC) + { + addLocalObjCMethod(root,scopeName,funcType,funcName,funcArgs,exceptions,funcDecl,spec); + return; + } + if (count==0 && !(isFriend && funcType=="class")) + { + int candidates=0; + const ClassDef *ecd = 0, *ucd = 0; + MemberDef *emd = 0, *umd = 0; + //printf("Assume template class\n"); + for (const auto &md : *mn) + { + ClassDef *ccd=md->getClassDef(); + MemberDef *cmd=md.get(); + //printf("ccd->name()==%s className=%s\n",ccd->name().data(),className.data()); + if (ccd!=0 && rightScopeMatch(ccd->name(),className)) + { + const ArgumentList &templAl = md->templateArguments(); + if (!root->tArgLists.empty() && !templAl.empty() && + root->tArgLists.back().size()<=templAl.size()) + { + Debug::print(Debug::FindMembers,0,"7. add template specialization\n"); + addMethodToClass(root,ccd,type,md->name(),args,isFriend, + root->protection,root->stat,root->virt,spec,relates); + return; + } + if (md->argsString()==argListToString(root->argList,FALSE,FALSE)) + { // exact argument list match -> remember + ucd = ecd = ccd; + umd = emd = cmd; + Debug::print(Debug::FindMembers,0, + "7. new candidate className=%s scope=%s args=%s exact match\n", + qPrint(className),qPrint(ccd->name()),qPrint(md->argsString())); + } + else // arguments do not match, but member name and scope do -> remember + { + ucd = ccd; + umd = cmd; + Debug::print(Debug::FindMembers,0, + "7. new candidate className=%s scope=%s args=%s no match\n", + qPrint(className),qPrint(ccd->name()),qPrint(md->argsString())); + } + candidates++; + } + } + static bool strictProtoMatching = Config_getBool(STRICT_PROTO_MATCHING); + if (!strictProtoMatching) + { + if (candidates==1 && ucd && umd) + { + // we didn't find an actual match on argument lists, but there is only 1 member with this + // name in the same scope, so that has to be the one. + addMemberDocs(root,umd,funcDecl,0,overloaded,spec); + return; + } + else if (candidates>1 && ecd && emd) + { + // we didn't find a unique match using type resolution, + // but one of the matches has the exact same signature so + // we take that one. + addMemberDocs(root,emd,funcDecl,0,overloaded,spec); + return; + } + } + + QCString warnMsg = "no "; + if (noMatchCount>1) warnMsg+="uniquely "; + warnMsg+="matching class member found for \n"; + + for (const ArgumentList &al : root->tArgLists) + { + warnMsg+=" template "; + warnMsg+=tempArgListToString(al,root->lang); + warnMsg+='\n'; + } + + QCString fullFuncDecl=funcDecl.copy(); + if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE); + + warnMsg+=" "; + warnMsg+=fullFuncDecl; + warnMsg+='\n'; + + if (candidates>0) + { + warnMsg+="Possible candidates:\n"; + for (const auto &md : *mn) + { + ClassDef *cd=md->getClassDef(); + if (cd!=0 && rightScopeMatch(cd->name(),className)) + { + const ArgumentList &templAl = md->templateArguments(); + warnMsg+=" '"; + if (templAl.hasParameters()) + { + warnMsg+="template "; + warnMsg+=tempArgListToString(templAl,root->lang); + warnMsg+='\n'; + warnMsg+=" "; + } + if (md->typeString()) + { + warnMsg+=md->typeString(); + warnMsg+=' '; + } + QCString qScope = cd->qualifiedNameWithTemplateParameters(); + if (!qScope.isEmpty()) + warnMsg+=qScope+"::"+md->name(); + if (md->argsString()) + warnMsg+=md->argsString(); + if (noMatchCount>1) + { + warnMsg+="' at line "+QCString().setNum(md->getDefLine()) + + " of file "+md->getDefFileName(); + } + else + warnMsg += "'"; + + warnMsg+='\n'; + } + } + } + warn_simple(root->fileName,root->startLine,warnMsg); + } +} + +//------------------------------------------------------------------------------------------- + +static void addMemberSpecialization(const Entry *root, + MemberName *mn, + ClassDef *cd, + const QCString &funcType, + const QCString &funcName, + const QCString &funcArgs, + const QCString &funcDecl, + const QCString &exceptions, + uint64 spec + ) +{ + MemberDef *declMd=0; + for (const auto &md : *mn) + { + if (md->getClassDef()==cd) + { + // TODO: we should probably also check for matching arguments + declMd = md.get(); + break; + } + } + MemberType mtype=MemberType_Function; + ArgumentList tArgList; + // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists); + std::unique_ptr<MemberDef> md { createMemberDef( + root->fileName,root->startLine,root->startColumn, + funcType,funcName,funcArgs,exceptions, + declMd ? declMd->protection() : root->protection, + root->virt,root->stat,Member, + mtype,tArgList,root->argList,root->metaData) }; + //printf("new specialized member %s args='%s'\n",md->name().data(),funcArgs.data()); + md->setTagInfo(root->tagInfo()); + md->setLanguage(root->lang); + md->setId(root->id); + md->setMemberClass(cd); + md->setTemplateSpecialization(TRUE); + md->setTypeConstraints(root->typeConstr); + md->setDefinition(funcDecl); + md->enableCallGraph(root->callGraph); + md->enableCallerGraph(root->callerGraph); + md->enableReferencedByRelation(root->referencedByRelation); + md->enableReferencesRelation(root->referencesRelation); + md->setDocumentation(root->doc,root->docFile,root->docLine); + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); + md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); + md->setDocsForDefinition(!root->proto); + md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); + md->addSectionsToDefinition(root->anchors); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); + FileDef *fd=root->fileDef(); + md->setBodyDef(fd); + md->setMemberSpecifiers(spec); + md->setMemberGroupId(root->mGrpId); + cd->insertMember(md.get()); + md->setRefItems(root->sli); + + mn->push_back(std::move(md)); +} + +//------------------------------------------------------------------------------------------- +static void addOverloaded(const Entry *root,MemberName *mn, + const QCString &funcType,const QCString &funcName,const QCString &funcArgs, + const QCString &funcDecl,const QCString &exceptions,uint64 spec) +{ + // for unique overloaded member we allow the class to be + // omitted, this is to be Qt compatible. Using this should + // however be avoided, because it is error prone + bool sameClass=false; + if (mn->size()>0) + { + // check if all members with the same name are also in the same class + sameClass = std::equal(mn->begin()+1,mn->end(),mn->begin(), + [](const auto &md1,const auto &md2) + { return md1->getClassDef()->name()==md2->getClassDef()->name(); }); + } + if (sameClass) + { + ClassDef *cd = mn->front()->getClassDef(); + MemberType mtype; + if (root->mtype==Signal) mtype=MemberType_Signal; + else if (root->mtype==Slot) mtype=MemberType_Slot; + else if (root->mtype==DCOP) mtype=MemberType_DCOP; + else mtype=MemberType_Function; + + // new overloaded member function + std::unique_ptr<ArgumentList> tArgList = + getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists); + //printf("new related member %s args='%s'\n",md->name().data(),funcArgs.data()); + std::unique_ptr<MemberDef> md { createMemberDef( + root->fileName,root->startLine,root->startColumn, + funcType,funcName,funcArgs,exceptions, + root->protection,root->virt,root->stat,Related, + mtype,tArgList ? *tArgList : ArgumentList(),root->argList,root->metaData) }; + md->setTagInfo(root->tagInfo()); + md->setLanguage(root->lang); + md->setId(root->id); + md->setTypeConstraints(root->typeConstr); + md->setMemberClass(cd); + md->setDefinition(funcDecl); + md->enableCallGraph(root->callGraph); + md->enableCallerGraph(root->callerGraph); + md->enableReferencedByRelation(root->referencedByRelation); + md->enableReferencesRelation(root->referencesRelation); + QCString doc=getOverloadDocs(); + doc+="<p>"; + doc+=root->doc; + md->setDocumentation(doc,root->docFile,root->docLine); + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); + md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); + md->setDocsForDefinition(!root->proto); + md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); + md->addSectionsToDefinition(root->anchors); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); + FileDef *fd=root->fileDef(); + md->setBodyDef(fd); + md->setMemberSpecifiers(spec); + md->setMemberGroupId(root->mGrpId); + cd->insertMember(md.get()); + cd->insertUsedFile(fd); + md->setRefItems(root->sli); + + mn->push_back(std::move(md)); + } +} + +//------------------------------------------------------------------------------------------- /*! This function tries to find a member (in a documented class/file/namespace) * that corresponds to the function/variable declaration given in \a funcDecl. @@ -5697,7 +6105,7 @@ static void findMember(const Entry *root, { if (funcSpec.isEmpty()) { - int argListIndex=0; + uint argListIndex=0; tempScopeName=cd->qualifiedNameWithTemplateParameters(&root->tArgLists,&argListIndex); } else @@ -5797,366 +6205,27 @@ static void findMember(const Entry *root, } if (!funcTempList.isEmpty()) // try with member specialization { - mn=Doxygen::memberNameSDict->find(funcName+funcTempList); + mn=Doxygen::memberNameLinkedMap->find(funcName+funcTempList); } if (mn==0) // try without specialization { - mn=Doxygen::memberNameSDict->find(funcName); + mn=Doxygen::memberNameLinkedMap->find(funcName); } if (!isRelated && mn) // function name already found { Debug::print(Debug::FindMembers,0, - "2. member name exists (%d members with this name)\n",mn->count()); + "2. member name exists (%d members with this name)\n",mn->size()); if (!className.isEmpty()) // class name is valid { if (funcSpec.isEmpty()) // not a member specialization { - int count=0; - int noMatchCount=0; - MemberNameIterator mni(*mn); - MemberDef *md; - bool memFound=FALSE; - for (mni.toFirst();!memFound && (md=mni.current());++mni) - { - ClassDef *cd=md->getClassDef(); - Debug::print(Debug::FindMembers,0, - "3. member definition found, " - "scope needed='%s' scope='%s' args='%s' fileName=%s\n", - qPrint(scopeName),cd ? qPrint(cd->name()) : "<none>", - qPrint(md->argsString()), - qPrint(root->fileName)); - //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data()); - FileDef *fd=root->fileDef(); - NamespaceDef *nd=0; - if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName); - - //printf("scopeName %s->%s\n",scopeName.data(), - // stripTemplateSpecifiersFromScope(scopeName,FALSE).data()); - - const ClassDef *tcd=findClassDefinition(fd,nd,scopeName); - if (tcd==0 && cd && stripAnonymousNamespaceScope(cd->name())==scopeName) - { - // don't be fooled by anonymous scopes - tcd=cd; - } - //printf("Looking for %s inside nd=%s result=%p (%s) cd=%p\n", - // scopeName.data(),nd?nd->name().data():"<none>",tcd,tcd?tcd->name().data():"",cd); - - if (cd && tcd==cd) // member's classes match - { - Debug::print(Debug::FindMembers,0, - "4. class definition %s found\n",cd->name().data()); - - // get the template parameter lists found at the member declaration - std::vector<ArgumentList> declTemplArgs = cd->getTemplateParameterLists(); - const ArgumentList &templAl = md->templateArguments(); - if (!templAl.empty()) - { - declTemplArgs.push_back(templAl); - } - - // get the template parameter lists found at the member definition - const std::vector<ArgumentList> &defTemplArgs = root->tArgLists; - //printf("defTemplArgs=%p\n",defTemplArgs); - - // do we replace the decl argument lists with the def argument lists? - bool substDone=FALSE; - ArgumentList argList; - - /* substitute the occurrences of class template names in the - * argument list before matching - */ - const ArgumentList &mdAl = md->argumentList(); - if (declTemplArgs.size()>0 && declTemplArgs.size()==defTemplArgs.size()) - { - /* the function definition has template arguments - * and the class definition also has template arguments, so - * we must substitute the template names of the class by that - * of the function definition before matching. - */ - substituteTemplatesInArgList(declTemplArgs,defTemplArgs,mdAl,argList); - - substDone=TRUE; - } - else /* no template arguments, compare argument lists directly */ - { - argList = mdAl; - } - - Debug::print(Debug::FindMembers,0, - "5. matching '%s'<=>'%s' className=%s namespaceName=%s\n", - qPrint(argListToString(argList,TRUE)),qPrint(argListToString(root->argList,TRUE)), - qPrint(className),qPrint(namespaceName) - ); - - bool matching= - md->isVariable() || md->isTypedef() || // needed for function pointers - (mdAl.empty() && root->argList.empty()) || - matchArguments2( - md->getClassDef(),md->getFileDef(),argList, - cd,fd,root->argList, - TRUE); - - if (md->getLanguage()==SrcLangExt_ObjC && md->isVariable() && (root->section&Entry::FUNCTION_SEC)) - { - matching = FALSE; // don't match methods and attributes with the same name - } - - // for template member we also need to check the return type - if (!md->templateArguments().empty() && !root->tArgLists.empty()) - { - QCString memType = md->typeString(); - memType.stripPrefix("static "); // see bug700696 - funcType=substitute(stripTemplateSpecifiersFromScope(funcType,TRUE), - className+"::",""); // see bug700693 & bug732594 - memType=substitute(stripTemplateSpecifiersFromScope(memType,TRUE), - className+"::",""); // see bug758900 - Debug::print(Debug::FindMembers,0, - "5b. Comparing return types '%s'<->'%s' #args %d<->%d\n", - qPrint(md->typeString()),qPrint(funcType), - md->templateArguments().size(),root->tArgLists.back().size()); - if (md->templateArguments().size()!=root->tArgLists.back().size() || - qstrcmp(memType,funcType)) - { - //printf(" ---> no matching\n"); - matching = FALSE; - } - } - bool rootIsUserDoc = (root->section&Entry::MEMBERDOC_SEC)!=0; - bool classIsTemplate = scopeIsTemplate(md->getClassDef()); - bool mdIsTemplate = md->templateArguments().hasParameters(); - bool classOrMdIsTemplate = mdIsTemplate || classIsTemplate; - bool rootIsTemplate = !root->tArgLists.empty(); - //printf("classIsTemplate=%d mdIsTemplate=%d rootIsTemplate=%d\n",classIsTemplate,mdIsTemplate,rootIsTemplate); - if (!rootIsUserDoc && // don't check out-of-line @fn references, see bug722457 - (mdIsTemplate || rootIsTemplate) && // either md or root is a template - ((classOrMdIsTemplate && !rootIsTemplate) || (!classOrMdIsTemplate && rootIsTemplate)) - ) - { - // Method with template return type does not match method without return type - // even if the parameters are the same. See also bug709052 - Debug::print(Debug::FindMembers,0, - "5b. Comparing return types: template v.s. non-template\n"); - matching = FALSE; - } - - - Debug::print(Debug::FindMembers,0, - "6. match results of matchArguments2 = %d substDone=%d\n",matching,substDone); - - if (substDone) // found a new argument list - { - if (matching) // replace member's argument list - { - md->setDefinitionTemplateParameterLists(root->tArgLists); - md->setArgumentList(argList); - } - else // no match - { - if (!funcTempList.isEmpty() && - isSpecialization(declTemplArgs,defTemplArgs)) - { - // check if we are dealing with a partial template - // specialization. In this case we add it to the class - // even though the member arguments do not match. - - addMethodToClass(root,cd,type,md->name(),args,isFriend, - md->protection(),md->isStatic(),md->virtualness(),spec,relates); - return; - } - } - } - if (matching) - { - addMemberDocs(root,md,funcDecl,0,overloaded,spec); - count++; - memFound=TRUE; - } - } - else if (cd && cd!=tcd) // we did find a class with the same name as cd - // but in a different namespace - { - noMatchCount++; - } - } - if (count==0 && root->parent() && - root->parent()->section==Entry::OBJCIMPL_SEC) - { - goto localObjCMethod; - } - if (count==0 && !(isFriend && funcType=="class")) - { - int candidates=0; - const ClassDef *ecd = 0, *ucd = 0; - MemberDef *emd = 0, *umd = 0; - if (mn->count()>0) - { - //printf("Assume template class\n"); - for (mni.toFirst();(md=mni.current());++mni) - { - ClassDef *ccd=md->getClassDef(); - MemberDef *cmd=md; - //printf("ccd->name()==%s className=%s\n",ccd->name().data(),className.data()); - if (ccd!=0 && rightScopeMatch(ccd->name(),className)) - { - const ArgumentList &templAl = md->templateArguments(); - if (!root->tArgLists.empty() && !templAl.empty() && - root->tArgLists.back().size()<=templAl.size()) - { - Debug::print(Debug::FindMembers,0,"7. add template specialization\n"); - addMethodToClass(root,ccd,type,md->name(),args,isFriend, - root->protection,root->stat,root->virt,spec,relates); - return; - } - if (md->argsString()==argListToString(root->argList,TRUE,FALSE)) - { // exact argument list match -> remember - ucd = ecd = ccd; - umd = emd = cmd; - Debug::print(Debug::FindMembers,0, - "7. new candidate className=%s scope=%s args=%s exact match\n", - qPrint(className),qPrint(ccd->name()),qPrint(md->argsString())); - } - else // arguments do not match, but member name and scope do -> remember - { - ucd = ccd; - umd = cmd; - Debug::print(Debug::FindMembers,0, - "7. new candidate className=%s scope=%s args=%s no match\n", - qPrint(className),qPrint(ccd->name()),qPrint(md->argsString())); - } - candidates++; - } - } - } - static bool strictProtoMatching = Config_getBool(STRICT_PROTO_MATCHING); - if (!strictProtoMatching) - { - if (candidates==1 && ucd && umd) - { - // we didn't find an actual match on argument lists, but there is only 1 member with this - // name in the same scope, so that has to be the one. - addMemberDocs(root,umd,funcDecl,0,overloaded,spec); - return; - } - else if (candidates>1 && ecd && emd) - { - // we didn't find a unique match using type resolution, - // but one of the matches has the exact same signature so - // we take that one. - addMemberDocs(root,emd,funcDecl,0,overloaded,spec); - return; - } - } - - QCString warnMsg = "no "; - if (noMatchCount>1) warnMsg+="uniquely "; - warnMsg+="matching class member found for \n"; - - for (const ArgumentList &al : root->tArgLists) - { - warnMsg+=" template "; - warnMsg+=tempArgListToString(al,root->lang); - warnMsg+='\n'; - } - - QCString fullFuncDecl=funcDecl.copy(); - if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE); - - warnMsg+=" "; - warnMsg+=fullFuncDecl; - warnMsg+='\n'; - - if (candidates>0) - { - warnMsg+="Possible candidates:\n"; - for (mni.toFirst();(md=mni.current());++mni) - { - const ClassDef *cd=md->getClassDef(); - if (cd!=0 && rightScopeMatch(cd->name(),className)) - { - const ArgumentList &templAl = md->templateArguments(); - warnMsg+=" '"; - if (templAl.hasParameters()) - { - warnMsg+="template "; - warnMsg+=tempArgListToString(templAl,root->lang); - warnMsg+='\n'; - warnMsg+=" "; - } - if (md->typeString()) - { - warnMsg+=md->typeString(); - warnMsg+=' '; - } - QCString qScope = cd->qualifiedNameWithTemplateParameters(); - if (!qScope.isEmpty()) - warnMsg+=qScope+"::"+md->name(); - if (md->argsString()) - warnMsg+=md->argsString(); - if (noMatchCount>1) - { - warnMsg+="' at line "+QCString().setNum(md->getDefLine()) + - " of file "+md->getDefFileName(); - } - else - warnMsg += "'"; - - warnMsg+='\n'; - } - } - } - warn_simple(root->fileName,root->startLine,warnMsg); - } + addMemberFunction(root,mn,scopeName,namespaceName,className,funcType,funcName, + funcArgs,funcTempList,exceptions, + type,args,isFriend,spec,relates,funcDecl,overloaded,isFunc); } else if (cd) // member specialization { - MemberNameIterator mni(*mn); - MemberDef *declMd=0; - MemberDef *md=0; - for (mni.toFirst();(md=mni.current());++mni) - { - if (md->getClassDef()==cd) - { - // TODO: we should probably also check for matching arguments - declMd = md; - break; - } - } - MemberType mtype=MemberType_Function; - ArgumentList tArgList; - // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists); - md=createMemberDef( - root->fileName,root->startLine,root->startColumn, - funcType,funcName,funcArgs,exceptions, - declMd ? declMd->protection() : root->protection, - root->virt,root->stat,Member, - mtype,tArgList,root->argList,root->metaData); - //printf("new specialized member %s args='%s'\n",md->name().data(),funcArgs.data()); - md->setTagInfo(root->tagInfo()); - md->setLanguage(root->lang); - md->setId(root->id); - md->setMemberClass(cd); - md->setTemplateSpecialization(TRUE); - md->setTypeConstraints(root->typeConstr); - md->setDefinition(funcDecl); - md->enableCallGraph(root->callGraph); - md->enableCallerGraph(root->callerGraph); - md->enableReferencedByRelation(root->referencedByRelation); - md->enableReferencesRelation(root->referencesRelation); - md->setDocumentation(root->doc,root->docFile,root->docLine); - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - md->setDocsForDefinition(!root->proto); - md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); - md->addSectionsToDefinition(root->anchors); - md->setBodySegment(root->bodyLine,root->endBodyLine); - FileDef *fd=root->fileDef(); - md->setBodyDef(fd); - md->setMemberSpecifiers(spec); - md->setMemberGroupId(root->mGrpId); - mn->append(md); - cd->insertMember(md); - md->setRefItems(root->sli); + addMemberSpecialization(root,mn,cd,funcType,funcName,funcArgs,funcDecl,exceptions,spec); } else { @@ -6166,68 +6235,7 @@ static void findMember(const Entry *root, } else if (overloaded) // check if the function belongs to only one class { - // for unique overloaded member we allow the class to be - // omitted, this is to be Qt compatible. Using this should - // however be avoided, because it is error prone - MemberNameIterator mni(*mn); - MemberDef *md=mni.toFirst(); - ASSERT(md); - ClassDef *cd=md->getClassDef(); - ASSERT(cd); - QCString className=cd->name().copy(); - ++mni; - bool unique=TRUE; - for (;(md=mni.current());++mni) - { - const ClassDef *cd=md->getClassDef(); - if (className!=cd->name()) unique=FALSE; - } - if (unique) - { - MemberType mtype; - if (root->mtype==Signal) mtype=MemberType_Signal; - else if (root->mtype==Slot) mtype=MemberType_Slot; - else if (root->mtype==DCOP) mtype=MemberType_DCOP; - else mtype=MemberType_Function; - - // new overloaded member function - ArgumentList tArgList = - getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists); - //printf("new related member %s args='%s'\n",md->name().data(),funcArgs.data()); - MemberDef *md=createMemberDef( - root->fileName,root->startLine,root->startColumn, - funcType,funcName,funcArgs,exceptions, - root->protection,root->virt,root->stat,Related, - mtype,tArgList,root->argList,root->metaData); - md->setTagInfo(root->tagInfo()); - md->setLanguage(root->lang); - md->setId(root->id); - md->setTypeConstraints(root->typeConstr); - md->setMemberClass(cd); - md->setDefinition(funcDecl); - md->enableCallGraph(root->callGraph); - md->enableCallerGraph(root->callerGraph); - md->enableReferencedByRelation(root->referencedByRelation); - md->enableReferencesRelation(root->referencesRelation); - QCString doc=getOverloadDocs(); - doc+="<p>"; - doc+=root->doc; - md->setDocumentation(doc,root->docFile,root->docLine); - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - md->setDocsForDefinition(!root->proto); - md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); - md->addSectionsToDefinition(root->anchors); - md->setBodySegment(root->bodyLine,root->endBodyLine); - FileDef *fd=root->fileDef(); - md->setBodyDef(fd); - md->setMemberSpecifiers(spec); - md->setMemberGroupId(root->mGrpId); - mn->append(md); - cd->insertMember(md); - cd->insertUsedFile(fd); - md->setRefItems(root->sli); - } + addOverloaded(root,mn,funcType,funcName,funcArgs,funcDecl,exceptions,spec); } else // unrelated function with the same name as a member { @@ -6247,62 +6255,62 @@ static void findMember(const Entry *root, Debug::print(Debug::FindMembers,0,"2. related function\n" " scopeName=%s className=%s\n",qPrint(scopeName),qPrint(className)); if (className.isEmpty()) className=relates; - ClassDef *cd; //printf("scopeName='%s' className='%s'\n",scopeName.data(),className.data()); if ((cd=getClass(scopeName))) { bool newMember=TRUE; // assume we have a new member - bool newMemberName=FALSE; MemberDef *mdDefine=0; - bool isDefine=FALSE; { - MemberName *mn = Doxygen::functionNameSDict->find(funcName); + mn = Doxygen::functionNameLinkedMap->find(funcName); if (mn) { - MemberNameIterator mni(*mn); - mdDefine = mni.current(); - while (mdDefine && !isDefine) + for (const auto &md : *mn) { - isDefine = isDefine || mdDefine->isDefine(); - if (!isDefine) { ++mni; mdDefine=mni.current(); } + if (md->isDefine()) + { + mdDefine = md.get(); + break; + } } } } FileDef *fd=root->fileDef(); - if ((mn=Doxygen::memberNameSDict->find(funcName))==0) + if ((mn=Doxygen::memberNameLinkedMap->find(funcName))==0) { - mn=new MemberName(funcName); - newMemberName=TRUE; // we create a new member name + mn=Doxygen::memberNameLinkedMap->add(funcName); } else { - MemberNameIterator mni(*mn); - MemberDef *rmd; - while ((rmd=mni.current()) && newMember) // see if we got another member with matching arguments + // see if we got another member with matching arguments + MemberDef *rmd_found = 0; + for (const auto &rmd : *mn) { const ArgumentList &rmdAl = rmd->argumentList(); newMember= className!=rmd->getOuterScope()->name() || - !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl, - cd,fd,root->argList, + !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, + cd,fd,&root->argList, TRUE); - if (newMember) ++mni; + if (!newMember) + { + rmd_found = rmd.get(); + } } - if (!newMember && rmd) // member already exists as rmd -> add docs + if (rmd_found) // member already exists as rmd -> add docs { //printf("addMemberDocs for related member %s\n",root->name.data()); //rmd->setMemberDefTemplateArguments(root->mtArgList); - addMemberDocs(root,rmd,funcDecl,0,overloaded,spec); + addMemberDocs(root,rmd_found,funcDecl,0,overloaded,spec); } } if (newMember) // need to create a new member { MemberType mtype; - if (isDefine) + if (mdDefine) mtype=MemberType_Define; else if (root->mtype==Signal) mtype=MemberType_Signal; @@ -6313,7 +6321,7 @@ static void findMember(const Entry *root, else mtype=MemberType_Function; - if (isDefine && mdDefine) + if (mdDefine) { mdDefine->setHidden(TRUE); funcType="#define"; @@ -6330,7 +6338,7 @@ static void findMember(const Entry *root, // this accurately reflects the template arguments of // the related function, which don't have to do with // those of the related class. - MemberDef *md=createMemberDef( + std::unique_ptr<MemberDef> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt, @@ -6339,9 +6347,9 @@ static void findMember(const Entry *root, mtype, (!root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList()), funcArgs.isEmpty() ? ArgumentList() : root->argList, - root->metaData); + root->metaData) }; - if (isDefine && mdDefine) + if (mdDefine) { md->setInitializer(mdDefine->initializer()); } @@ -6361,8 +6369,6 @@ static void findMember(const Entry *root, md->setTagInfo(root->tagInfo()); - - //printf("Related member name='%s' decl='%s' bodyLine='%d'\n", // funcName.data(),funcDecl.data(),root->bodyLine); @@ -6371,29 +6377,29 @@ static void findMember(const Entry *root, bool found=FALSE; if (root->bodyLine==-1) { - MemberName *rmn=Doxygen::functionNameSDict->find(funcName); + MemberName *rmn=Doxygen::functionNameLinkedMap->find(funcName); if (rmn) { - MemberNameIterator rmni(*rmn); - const MemberDef *rmd; - while ((rmd=rmni.current()) && !found) // see if we got another member with matching arguments + const MemberDef *rmd_found=0; + for (const auto &rmd : *rmn) { const ArgumentList &rmdAl = rmd->argumentList(); // check for matching argument lists if ( - matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl, - cd,fd,root->argList, + matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, + cd,fd,&root->argList, TRUE) ) { found=TRUE; + rmd_found = rmd.get(); + break; } - if (!found) ++rmni; } - if (rmd) // member found -> copy line number info + if (rmd_found) // member found -> copy line number info { - md->setBodySegment(rmd->getStartBodyLine(),rmd->getEndBodyLine()); - md->setBodyDef(rmd->getBodyDef()); + md->setBodySegment(rmd_found->getDefLine(),rmd_found->getStartBodyLine(),rmd_found->getEndBodyLine()); + md->setBodyDef(rmd_found->getBodyDef()); //md->setBodyMember(rmd); } } @@ -6401,7 +6407,7 @@ static void findMember(const Entry *root, if (!found) // line number could not be found or is available in this // entry { - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setBodyDef(fd); } @@ -6426,22 +6432,16 @@ static void findMember(const Entry *root, md->setLanguage(root->lang); md->setId(root->id); //md->setMemberDefTemplateArguments(root->mtArgList); - mn->append(md); - cd->insertMember(md); + cd->insertMember(md.get()); cd->insertUsedFile(fd); md->setRefItems(root->sli); if (root->relatesType == Duplicate) md->setRelatedAlso(cd); - if (!isDefine) + if (!mdDefine) { - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); } //printf("Adding member=%s\n",md->name().data()); - if (newMemberName) - { - //Doxygen::memberNameList.append(mn); - //Doxygen::memberNameDict.insert(funcName,mn); - Doxygen::memberNameSDict->append(funcName,mn); - } + mn->push_back(std::move(md)); } if (root->relatesType == Duplicate) { @@ -6467,58 +6467,7 @@ static void findMember(const Entry *root, } else if (root->parent() && root->parent()->section==Entry::OBJCIMPL_SEC) { -localObjCMethod: - ClassDef *cd; - //printf("scopeName='%s' className='%s'\n",scopeName.data(),className.data()); - if (Config_getBool(EXTRACT_LOCAL_METHODS) && (cd=getClass(scopeName))) - { - Debug::print(Debug::FindMembers,0,"4. Local objective C method %s\n" - " scopeName=%s className=%s\n",qPrint(root->name),qPrint(scopeName),qPrint(className)); - //printf("Local objective C method '%s' of class '%s' found\n",root->name.data(),cd->name().data()); - MemberDef *md=createMemberDef( - root->fileName,root->startLine,root->startColumn, - funcType,funcName,funcArgs,exceptions, - root->protection,root->virt,root->stat,Member, - MemberType_Function,ArgumentList(),root->argList,root->metaData); - md->setTagInfo(root->tagInfo()); - md->setLanguage(root->lang); - md->setId(root->id); - md->makeImplementationDetail(); - md->setMemberClass(cd); - md->setDefinition(funcDecl); - md->enableCallGraph(root->callGraph); - md->enableCallerGraph(root->callerGraph); - md->enableReferencedByRelation(root->referencedByRelation); - md->enableReferencesRelation(root->referencesRelation); - md->setDocumentation(root->doc,root->docFile,root->docLine); - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - md->setDocsForDefinition(!root->proto); - md->setPrototype(root->proto,root->fileName,root->startLine,root->startColumn); - md->addSectionsToDefinition(root->anchors); - md->setBodySegment(root->bodyLine,root->endBodyLine); - FileDef *fd=root->fileDef(); - md->setBodyDef(fd); - md->setMemberSpecifiers(spec); - md->setMemberGroupId(root->mGrpId); - cd->insertMember(md); - cd->insertUsedFile(fd); - md->setRefItems(root->sli); - if ((mn=Doxygen::memberNameSDict->find(root->name))) - { - mn->append(md); - } - else - { - mn = new MemberName(root->name); - mn->append(md); - Doxygen::memberNameSDict->append(root->name,mn); - } - } - else - { - // local objective C method found for class without interface - } + addLocalObjCMethod(root,scopeName,funcType,funcName,funcArgs,exceptions,funcDecl,spec); } else // unrelated not overloaded member found { @@ -6763,11 +6712,10 @@ static void findEnums(const Entry *root) { if (root->section==Entry::ENUM_SEC) { - MemberDef *md=0; ClassDef *cd=0; FileDef *fd=0; NamespaceDef *nd=0; - MemberNameSDict *mnsd=0; + MemberNameLinkedMap *mnsd=0; bool isGlobal; bool isRelated=FALSE; bool isMemberOf=FALSE; @@ -6810,36 +6758,36 @@ static void findEnums(const Entry *root) { //printf("Enum '%s'::'%s'\n",cd->name().data(),name.data()); fd=0; - mnsd=Doxygen::memberNameSDict; + mnsd=Doxygen::memberNameLinkedMap; isGlobal=FALSE; } else if (nd) // found enum inside namespace { - mnsd=Doxygen::functionNameSDict; + mnsd=Doxygen::functionNameLinkedMap; isGlobal=TRUE; } else // found a global enum { fd=root->fileDef(); - mnsd=Doxygen::functionNameSDict; + mnsd=Doxygen::functionNameLinkedMap; isGlobal=TRUE; } if (!name.isEmpty()) { // new enum type - md = createMemberDef( + std::unique_ptr<MemberDef> md { createMemberDef( root->fileName,root->startLine,root->startColumn, 0,name,0,0, root->protection,Normal,FALSE, isMemberOf ? Foreign : isRelated ? Related : Member, MemberType_Enumeration, - ArgumentList(),ArgumentList(),root->metaData); + ArgumentList(),ArgumentList(),root->metaData) }; md->setTagInfo(root->tagInfo()); md->setLanguage(root->lang); md->setId(root->id); if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd); - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setBodyDef(root->fileDef()); md->setMemberSpecifiers(root->spec); md->setEnumBaseType(root->args); @@ -6875,7 +6823,7 @@ static void findEnums(const Entry *root) //printf("definition=%s\n",md->definition()); defSet=TRUE; md->setNamespace(nd); - nd->insertMember(md); + nd->insertMember(md.get()); } // even if we have already added the enum to a namespace, we still @@ -6891,7 +6839,7 @@ static void findEnums(const Entry *root) if (fd) { md->setFileDef(fd); - fd->insertMember(md); + fd->insertMember(md.get()); } } else if (cd) @@ -6904,7 +6852,7 @@ static void findEnums(const Entry *root) { md->setDefinition(cd->name()+"::"+name+baseType); } - cd->insertMember(md); + cd->insertMember(md.get()); cd->insertUsedFile(fd); } md->setDocumentation(root->doc,root->docFile,root->docLine); @@ -6913,21 +6861,10 @@ static void findEnums(const Entry *root) md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); //printf("Adding member=%s\n",md->name().data()); - MemberName *mn; - if ((mn=(*mnsd)[name])) - { - // this is used if the same enum is in multiple namespaces/classes - mn->append(md); - } - else // new enum name - { - mn = new MemberName(name); - mn->append(md); - mnsd->append(name,mn); - //printf("add %s to new memberName. Now %d members\n", - // name.data(),mn->count()); - } - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); + + MemberName *mn = mnsd->add(name); + mn->push_back(std::move(md)); } } else @@ -6946,7 +6883,7 @@ static void addEnumValuesToEnums(const Entry *root) ClassDef *cd=0; FileDef *fd=0; NamespaceDef *nd=0; - MemberNameSDict *mnsd=0; + MemberNameLinkedMap *mnsd=0; bool isGlobal; bool isRelated=FALSE; //printf("Found enum with name '%s' relates=%s\n",root->name.data(),root->relates.data()); @@ -6987,20 +6924,20 @@ static void addEnumValuesToEnums(const Entry *root) { //printf("Enum in class '%s'::'%s'\n",cd->name().data(),name.data()); fd=0; - mnsd=Doxygen::memberNameSDict; + mnsd=Doxygen::memberNameLinkedMap; isGlobal=FALSE; } else if (nd && !nd->isAnonymous()) // found enum inside namespace { //printf("Enum in namespace '%s'::'%s'\n",nd->name().data(),name.data()); - mnsd=Doxygen::functionNameSDict; + mnsd=Doxygen::functionNameLinkedMap; isGlobal=TRUE; } else // found a global enum { fd=root->fileDef(); //printf("Enum in file '%s': '%s'\n",fd->name().data(),name.data()); - mnsd=Doxygen::functionNameSDict; + mnsd=Doxygen::functionNameLinkedMap; isGlobal=TRUE; } @@ -7010,10 +6947,11 @@ static void addEnumValuesToEnums(const Entry *root) MemberName *mn = mnsd->find(name); // for all members with this name if (mn) { - MemberNameIterator mni(*mn); - MemberDef *md; - for (mni.toFirst(); (md=mni.current()) ; ++mni) // for each enum in this list + std::vector< std::unique_ptr<MemberDef> > extraMembers; + // for each enum in this list + for (const auto &md : *mn) { + // use raw pointer in this loop, since we modify mn and can then invalidate mdp. if (!md->isAlias() && md->isEnumerate() && !root->children().empty()) { //printf(" enum with %d children\n",root->children()->count()); @@ -7046,11 +6984,11 @@ static void addEnumValuesToEnums(const Entry *root) { fileName = e->tagInfo()->tagName; } - MemberDef *fmd=createMemberDef( + std::unique_ptr<MemberDef> fmd { createMemberDef( fileName,e->startLine,e->startColumn, e->type,e->name,e->args,0, e->protection, Normal,e->stat,Member, - MemberType_EnumValue,ArgumentList(),ArgumentList(),e->metaData); + MemberType_EnumValue,ArgumentList(),ArgumentList(),e->metaData) }; if (md->getClassDef()) fmd->setMemberClass(md->getClassDef()); else if (md->getNamespaceDef()) fmd->setNamespace(md->getNamespaceDef()); else if (md->getFileDef()) fmd->setFileDef(md->getFileDef()); @@ -7067,32 +7005,21 @@ static void addEnumValuesToEnums(const Entry *root) fmd->setExplicitExternal(e->explicitExternal,fileName,e->startLine,e->startColumn); fmd->setRefItems(e->sli); fmd->setAnchor(); - md->insertEnumField(fmd); - fmd->setEnumScope(md,TRUE); - MemberName *mn=mnsd->find(e->name); - if (mn) - { - mn->append(fmd); - } - else - { - mn = new MemberName(e->name); - mn->append(fmd); - mnsd->append(e->name,mn); - } + md->insertEnumField(fmd.get()); + fmd->setEnumScope(md.get(),TRUE); + mn=mnsd->add(e->name); + extraMembers.push_back(std::move(fmd)); } } else { - //printf("e->name=%s isRelated=%d\n",e->name().data(),isRelated); + //printf("e->name=%s isRelated=%d\n",e->name.data(),isRelated); MemberName *fmn=0; - MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd; - if (!e->name.isEmpty() && (fmn=(*emnsd)[e->name])) + MemberNameLinkedMap *emnsd = isRelated ? Doxygen::functionNameLinkedMap : mnsd; + if (!e->name.isEmpty() && (fmn=emnsd->find(e->name))) // get list of members with the same name as the field { - MemberNameIterator fmni(*fmn); - MemberDef *fmd; - for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni) + for (const auto &fmd : *fmn) { if (fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope { @@ -7103,8 +7030,8 @@ static void addEnumValuesToEnums(const Entry *root) const NamespaceDef *fnd=fmd->getNamespaceDef(); if (fnd==nd) // enum value is inside a namespace { - md->insertEnumField(fmd); - fmd->setEnumScope(md); + md->insertEnumField(fmd.get()); + fmd->setEnumScope(md.get()); } } else if (isGlobal) @@ -7112,19 +7039,19 @@ static void addEnumValuesToEnums(const Entry *root) const FileDef *ffd=fmd->getFileDef(); if (ffd==fd) // enum value has file scope { - md->insertEnumField(fmd); - fmd->setEnumScope(md); + md->insertEnumField(fmd.get()); + fmd->setEnumScope(md.get()); } } else if (isRelated && cd) // reparent enum value to // match the enum's scope { - md->insertEnumField(fmd); // add field def to list - fmd->setEnumScope(md); // cross ref with enum name + md->insertEnumField(fmd.get()); // add field def to list + fmd->setEnumScope(md.get()); // cross ref with enum name fmd->setEnumClassScope(cd); // cross ref with enum name fmd->setOuterScope(cd); fmd->makeRelated(); - cd->insertMember(fmd); + cd->insertMember(fmd.get()); } else { @@ -7133,8 +7060,8 @@ static void addEnumValuesToEnums(const Entry *root) { //printf("Inserting enum field %s in enum scope %s\n", // fmd->name().data(),md->name().data()); - md->insertEnumField(fmd); // add field def to list - fmd->setEnumScope(md); // cross ref with enum name + md->insertEnumField(fmd.get()); // add field def to list + fmd->setEnumScope(md.get()); // cross ref with enum name } } } @@ -7144,6 +7071,11 @@ static void addEnumValuesToEnums(const Entry *root) } } } + // move the newly added members into mn + for (auto &md : extraMembers) + { + mn->push_back(std::move(md)); + } } } } @@ -7195,14 +7127,12 @@ static void findEnumDocumentation(const Entry *root) { //printf("Enum: scope='%s' name='%s'\n",cd->name(),name.data()); QCString className=cd->name().copy(); - MemberName *mn=Doxygen::memberNameSDict->find(name); + MemberName *mn=Doxygen::memberNameLinkedMap->find(name); if (mn) { - MemberNameIterator mni(*mn); - MemberDef *md; - for (mni.toFirst();(md=mni.current()) && !found;++mni) + for (const auto &md : *mn) { - const ClassDef *cd=md->getClassDef(); + cd=md->getClassDef(); if (cd && cd->name()==className && md->isEnumerate()) { // documentation outside a compound overrides the documentation inside it @@ -7239,10 +7169,11 @@ static void findEnumDocumentation(const Entry *root) const GroupDef *gd=md->getGroupDef(); if (gd==0 && !root->groups.empty()) // member not grouped but out-of-line documentation is { - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); } found=TRUE; + break; } } } @@ -7254,12 +7185,10 @@ static void findEnumDocumentation(const Entry *root) else // enum outside class { //printf("Enum outside class: %s grpId=%d\n",name.data(),root->mGrpId); - MemberName *mn=Doxygen::functionNameSDict->find(name); + MemberName *mn=Doxygen::functionNameLinkedMap->find(name); if (mn) { - MemberNameIterator mni(*mn); - MemberDef *md; - for (mni.toFirst();(md=mni.current()) && !found;++mni) + for (const auto &md : *mn) { if (md->isEnumerate()) { @@ -7273,10 +7202,11 @@ static void findEnumDocumentation(const Entry *root) const GroupDef *gd=md->getGroupDef(); if (gd==0 && !root->groups.empty()) // member not grouped but out-of-line documentation is { - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); } found=TRUE; + break; } } } @@ -7295,17 +7225,13 @@ static void findEnumDocumentation(const Entry *root) // search for each enum (member or function) in mnl if it has documented // enum values. -static void findDEV(const MemberNameSDict &mnsd) +static void findDEV(const MemberNameLinkedMap &mnsd) { - MemberName *mn; - MemberNameSDict::Iterator mnli(mnsd); // for each member name - for (mnli.toFirst();(mn=mnli.current());++mnli) + for (const auto &mn : mnsd) { - MemberDef *md; - MemberNameIterator mni(*mn); // for each member definition - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { if (md->isEnumerate()) // member is an enum { @@ -7332,45 +7258,38 @@ static void findDEV(const MemberNameSDict &mnsd) // values. static void findDocumentedEnumValues() { - findDEV(*Doxygen::memberNameSDict); - findDEV(*Doxygen::functionNameSDict); + findDEV(*Doxygen::memberNameLinkedMap); + findDEV(*Doxygen::functionNameLinkedMap); } //---------------------------------------------------------------------- static void addMembersToIndex() { - MemberName *mn; - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); // for each member name - for (mnli.toFirst();(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); // for each member definition - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { - addClassMemberNameToIndex(md); + addClassMemberNameToIndex(md.get()); } } - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); // for each member name - for (fnli.toFirst();(mn=fnli.current());++fnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); // for each member definition - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { if (!md->isAlias()) { if (md->getNamespaceDef()) { - addNamespaceMemberNameToIndex(md); + addNamespaceMemberNameToIndex(md.get()); } else { - addFileMemberNameToIndex(md); + addFileMemberNameToIndex(md.get()); } } } @@ -7381,29 +7300,22 @@ static void addMembersToIndex() static void vhdlCorrectMemberProperties() { - MemberName *mn; - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); // for each member name - for (mnli.toFirst();(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); // for each member definition - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { - VhdlDocGen::correctMemberProperties(md); + VhdlDocGen::correctMemberProperties(md.get()); } } - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); // for each member name - for (fnli.toFirst();(mn=fnli.current());++fnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); // for each member definition - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { - VhdlDocGen::correctMemberProperties(md); + VhdlDocGen::correctMemberProperties(md.get()); } } } @@ -7416,61 +7328,60 @@ static void vhdlCorrectMemberProperties() static void computeMemberRelations() { - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); - MemberName *mn; - for ( ; (mn=mnli.current()) ; ++mnli ) // for each member name + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - MemberNameIterator mdi(*mn); - MemberNameIterator bmdi(*mn); - MemberDef *md; - MemberDef *bmd; - for ( ; (md=mdi.current()) ; ++mdi ) // for each member with a specific name - { - for ( bmdi.toFirst() ; (bmd=bmdi.current()); ++bmdi ) // for each other member with the same name - { - const ClassDef *mcd = md->getClassDef(); - if (mcd && mcd->baseClasses()) - { - const ClassDef *bmcd = bmd->getClassDef(); - //printf("Check relation between '%s'::'%s' (%p) and '%s'::'%s' (%p)\n", - // mcd->name().data(),md->name().data(),md, - // bmcd->name().data(),bmd->name().data(),bmd - // ); - if (md!=bmd && bmcd && mcd && bmcd!=mcd && - (bmd->virtualness()!=Normal || bmd->getLanguage()==SrcLangExt_Python || - bmd->getLanguage()==SrcLangExt_Java || bmd->getLanguage()==SrcLangExt_PHP || - bmcd->compoundType()==ClassDef::Interface || - bmcd->compoundType()==ClassDef::Protocol - ) && - md->isFunction() && - mcd->isLinkable() && - bmcd->isLinkable() && - mcd->isBaseClass(bmcd,TRUE)) + // for each member with a specific name + for (const auto &md : *mn) + { + // for each other member with the same name + for ( const auto &bmd : *mn) + { + if (md!=bmd) + { + const ClassDef *mcd = md->getClassDef(); + if (mcd && mcd->baseClasses()) { - //printf(" derived scope\n"); - const ArgumentList &bmdAl = bmd->argumentList(); - const ArgumentList &mdAl = md->argumentList(); - //printf(" Base argList='%s'\n Super argList='%s'\n", - // argListToString(bmdAl.pointer()).data(), - // argListToString(mdAl.pointer()).data() + const ClassDef *bmcd = bmd->getClassDef(); + //printf("Check relation between '%s'::'%s' (%p) and '%s'::'%s' (%p)\n", + // mcd->name().data(),md->name().data(),md, + // bmcd->name().data(),bmd->name().data(),bmd // ); - if ( - matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),bmdAl, - md->getOuterScope(), md->getFileDef(), mdAl, - TRUE - ) - ) + if (bmcd && mcd && bmcd!=mcd && + (bmd->virtualness()!=Normal || bmd->getLanguage()==SrcLangExt_Python || + bmd->getLanguage()==SrcLangExt_Java || bmd->getLanguage()==SrcLangExt_PHP || + bmcd->compoundType()==ClassDef::Interface || + bmcd->compoundType()==ClassDef::Protocol + ) && + md->isFunction() && + mcd->isLinkable() && + bmcd->isLinkable() && + mcd->isBaseClass(bmcd,TRUE)) { - MemberDef *rmd; - if ((rmd=md->reimplements())==0 || - minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef()) + //printf(" derived scope\n"); + const ArgumentList &bmdAl = bmd->argumentList(); + const ArgumentList &mdAl = md->argumentList(); + //printf(" Base argList='%s'\n Super argList='%s'\n", + // argListToString(bmdAl.pointer()).data(), + // argListToString(mdAl.pointer()).data() + // ); + if ( + matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),&bmdAl, + md->getOuterScope(), md->getFileDef(), &mdAl, + TRUE + ) ) { - //printf("setting (new) reimplements member\n"); - md->setReimplements(bmd); + MemberDef *rmd; + if ((rmd=md->reimplements())==0 || + minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef()) + ) + { + //printf("setting (new) reimplements member\n"); + md->setReimplements(bmd.get()); + } + //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data()); + bmd->insertReimplementedBy(md.get()); } - //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data()); - bmd->insertReimplementedBy(md); } } } @@ -7556,10 +7467,10 @@ static void buildCompleteMemberLists() cd->mergeMembers(); } } - // now sort the member list of all classes. + // now sort the member list of all members for all classes. for (cli.toFirst();(cd=cli.current());++cli) { - if (cd->memberNameInfoSDict()) cd->memberNameInfoSDict()->sort(); + cd->sortAllMembersList(); } } @@ -7567,108 +7478,98 @@ static void buildCompleteMemberLists() static void generateFileSources() { - if (Doxygen::inputNameList->count()>0) + if (!Doxygen::inputNameLinkedMap->empty()) { #if USE_LIBCLANG - static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); - if (clangAssistedParsing) + if (Doxygen::clangAssistedParsing) { - QDict<void> g_processedFiles(10007); + StringUnorderedSet processedFiles; // create a dictionary with files to process - QDict<void> g_filesToProcess(10007); - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + StringUnorderedSet filesToProcess; + + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { - g_filesToProcess.insert(fd->absFilePath(),(void*)0x8); + filesToProcess.insert(fd->absFilePath().str()); } } // process source files (and their include dependencies) - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->isSource() && !fd->isReference()) { - QStrList filesInSameTu; - fd->getAllIncludeFilesRecursively(filesInSameTu); - fd->startParsing(); + auto clangParser = ClangParser::instance()->createTUParser(fd.get()); if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output { msg("Generating code for file %s...\n",fd->docName().data()); - fd->writeSource(*g_outputList,FALSE,filesInSameTu); + clangParser->parse(); + fd->writeSource(*g_outputList,clangParser.get()); } 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()); - fd->parseSource(FALSE,filesInSameTu); + clangParser->parse(); + fd->parseSource(clangParser.get()); } - char *incFile = filesInSameTu.first(); - while (incFile && g_filesToProcess.find(incFile)) + for (auto incFile : clangParser->filesInSameTU()) { - if (fd->absFilePath()!=incFile && !g_processedFiles.find(incFile)) + if (filesToProcess.find(incFile)!=filesToProcess.end() && // part of input + fd->absFilePath()!=incFile && // not same file + processedFiles.find(incFile)==processedFiles.end()) // not yet marked as processed { - QStrList moreFiles; + StringVector moreFiles; bool ambig; - FileDef *ifd=findFileDef(Doxygen::inputNameDict,incFile,ambig); + FileDef *ifd=findFileDef(Doxygen::inputNameLinkedMap,incFile.c_str(),ambig); if (ifd && !ifd->isReference()) { 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,TRUE,moreFiles); - + ifd->writeSource(*g_outputList,clangParser.get()); } else if (!ifd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them { msg(" Parsing code for file %s...\n",ifd->docName().data()); - ifd->parseSource(TRUE,moreFiles); + ifd->parseSource(clangParser.get()); } - g_processedFiles.insert(incFile,(void*)0x8); + processedFiles.insert(incFile); } } - incFile = filesInSameTu.next(); } - fd->finishParsing(); - g_processedFiles.insert(fd->absFilePath(),(void*)0x8); + processedFiles.insert(fd->absFilePath().str()); } } } // process remaining files - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { - if (!g_processedFiles.find(fd->absFilePath())) // not yet processed + if (processedFiles.find(fd->absFilePath().str())==processedFiles.end()) // not yet processed { - QStrList filesInSameTu; - fd->startParsing(); + auto clangParser = ClangParser::instance()->createTUParser(fd.get()); 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,FALSE,filesInSameTu); + clangParser->parse(); + fd->writeSource(*g_outputList,clangParser.get()); } 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()); - fd->parseSource(FALSE,filesInSameTu); + clangParser->parse(); + fd->parseSource(clangParser.get()); } - fd->finishParsing(); } } } @@ -7676,29 +7577,24 @@ static void generateFileSources() else #endif { - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { - QStrList filesInSameTu; - fd->startParsing(); + StringVector filesInSameTu; + fd->getAllIncludeFilesRecursively(filesInSameTu); 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,FALSE,filesInSameTu); + fd->writeSource(*g_outputList,nullptr); } 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()); - fd->parseSource(FALSE,filesInSameTu); + fd->parseSource(nullptr); } - fd->finishParsing(); } } } @@ -7711,15 +7607,11 @@ static void generateFileDocs() { if (documentedHtmlFiles==0) return; - if (Doxygen::inputNameList->count()>0) + if (!Doxygen::inputNameLinkedMap->empty()) { - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { bool doc = fd->isLinkableInProject(); if (doc) @@ -7742,9 +7634,9 @@ static void addSourceReferences() for (cli.toFirst();(cd=cli.current());++cli) { FileDef *fd=cd->getBodyDef(); - if (fd && cd->isLinkableInProject() && cd->getStartBodyLine()!=-1) + if (fd && cd->isLinkableInProject() && cd->getStartDefLine()!=-1) { - fd->addSourceRef(cd->getStartBodyLine(),cd,0); + fd->addSourceRef(cd->getStartDefLine(),cd,0); } } // add source references for namespace definitions @@ -7753,20 +7645,16 @@ static void addSourceReferences() for (nli.toFirst();(nd=nli.current());++nli) { FileDef *fd=nd->getBodyDef(); - if (fd && nd->isLinkableInProject() && nd->getStartBodyLine()!=-1) + if (fd && nd->isLinkableInProject() && nd->getStartDefLine()!=-1) { - fd->addSourceRef(nd->getStartBodyLine(),nd,0); + fd->addSourceRef(nd->getStartDefLine(),nd,0); } } // add source references for member names - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); - MemberName *mn=0; - for (mnli.toFirst();(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - MemberNameIterator mni(*mn); - MemberDef *md=0; - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { //printf("class member %s: def=%s body=%d link?=%d\n", // md->name().data(), @@ -7774,23 +7662,20 @@ static void addSourceReferences() // md->getStartBodyLine(),md->isLinkableInProject()); FileDef *fd=md->getBodyDef(); if (fd && - md->getStartBodyLine()!=-1 && + md->getStartDefLine()!=-1 && md->isLinkableInProject() && (fd->generateSourceFile() || Doxygen::parseSourcesNeeded) ) { //printf("Found member '%s' in file '%s' at line '%d' def=%s\n", // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data()); - fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md); + fd->addSourceRef(md->getStartDefLine(),md->getOuterScope(),md.get()); } } } - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); - for (fnli.toFirst();(mn=fnli.current());++fnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberNameIterator mni(*mn); - MemberDef *md=0; - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { FileDef *fd=md->getBodyDef(); //printf("member %s body=[%d,%d] fd=%p link=%d parseSources=%d\n", @@ -7799,14 +7684,51 @@ static void addSourceReferences() // md->isLinkableInProject(), // Doxygen::parseSourcesNeeded); if (fd && - md->getStartBodyLine()!=-1 && + md->getStartDefLine()!=-1 && md->isLinkableInProject() && (fd->generateSourceFile() || Doxygen::parseSourcesNeeded) ) { //printf("Found member '%s' in file '%s' at line '%d' def=%s\n", // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data()); - fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md); + fd->addSourceRef(md->getStartDefLine(),md->getOuterScope(),md.get()); + } + } + } +} + +//---------------------------------------------------------------------------- + +// add the macro definitions found during preprocessing as file members +static void buildDefineList() +{ + for (const auto &s : g_inputFiles) + { + auto it = Doxygen::macroDefinitions.find(s); + if (it!=Doxygen::macroDefinitions.end()) + { + for (const auto &def : it->second) + { + std::unique_ptr<MemberDef> md { createMemberDef( + def.fileName,def.lineNr,def.columnNr, + "#define",def.name,def.args,0, + Public,Normal,FALSE,Member,MemberType_Define, + ArgumentList(),ArgumentList(),"") }; + + if (!def.args.isEmpty()) + { + md->moveArgumentList(stringToArgumentList(SrcLangExt_Cpp, def.args)); + } + md->setInitializer(def.definition); + md->setFileDef(def.fileDef); + md->setDefinition("#define "+def.name); + + MemberName *mn=Doxygen::functionNameLinkedMap->add(def.name); + if (def.fileDef) + { + def.fileDef->insertMember(md.get()); + } + mn->push_back(std::move(md)); } } } @@ -7833,13 +7755,9 @@ static void sortMemberLists() } // sort file member lists - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->sortMemberLists(); } @@ -7864,34 +7782,6 @@ static void setAnonymousEnumType() { cd->setAnonymousEnumType(); } - -#if 0 - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd=0; - for (nli.toFirst();(nd=nli.current());++nli) - { - nd->setAnonymousEnumType(); - } - - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) - { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) - { - fd->setAnonymousEnumType(); - } - } - - GroupSDict::Iterator gli(*Doxygen::groupSDict); - GroupDef *gd; - for (gli.toFirst();(gd=gli.current());++gli) - { - gd->setAnonymousEnumType(); - } -#endif } //---------------------------------------------------------------------------- @@ -7912,13 +7802,9 @@ static void countMembers() nd->countMembers(); } - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->countMembers(); } @@ -7975,14 +7861,9 @@ static void generateClassDocs() static void inheritDocumentation() { - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); - MemberName *mn; - //int count=0; - for (;(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - MemberNameIterator mni(*mn); - MemberDef *md; - for (;(md=mni.current());++mni) + for (const auto &md : *mn) { //printf("%04d Member '%s'\n",count++,md->name().data()); if (md->documentation().isEmpty() && md->briefDescription().isEmpty()) @@ -8014,22 +7895,16 @@ static void inheritDocumentation() static void combineUsingRelations() { // for each file - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->setVisited(FALSE); } } - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->combineUsingRelations(); } @@ -8060,13 +7935,9 @@ static void addMembersToMemberGroup() cd->addMembersToMemberGroup(); } // for each file - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->addMembersToMemberGroup(); } @@ -8099,13 +7970,9 @@ static void distributeMemberGroupDocumentation() cd->distributeMemberGroupDocumentation(); } // for each file - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->distributeMemberGroupDocumentation(); } @@ -8138,13 +8005,9 @@ static void findSectionsInDocumentation() cd->findSectionsInDocumentation(); } // for each file - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { fd->findSectionsInDocumentation(); } @@ -8190,13 +8053,11 @@ static void flushCachedTemplateRelations() } // remove all cached typedef resolutions whose target is a // template class as this may now be a template instance - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); - MemberName *fn; - for (;(fn=fnli.current());++fnli) // for each global function name + // for each global function name + for (const auto &fn : *Doxygen::functionNameLinkedMap) { - MemberNameIterator fni(*fn); - MemberDef *fmd; - for (;(fmd=fni.current());++fni) // for each function with that name + // for each function with that name + for (const auto &fmd : *fn) { if (fmd->isTypedefValCached()) { @@ -8205,17 +8066,16 @@ static void flushCachedTemplateRelations() } } } - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); - for (;(fn=mnli.current());++mnli) // for each class method name + // for each class method name + for (const auto &nm : *Doxygen::memberNameLinkedMap) { - MemberNameIterator mni(*fn); - MemberDef *fmd; - for (;(fmd=mni.current());++mni) // for each function with that name + // for each function with that name + for (const auto &md : *nm) { - if (fmd->isTypedefValCached()) + if (md->isTypedefValCached()) { - const ClassDef *cd = fmd->getCachedTypedefVal(); - if (cd->isTemplate()) fmd->invalidateTypedefValCache(); + const ClassDef *cd = md->getCachedTypedefVal(); + if (cd->isTemplate()) md->invalidateTypedefValCache(); } } } @@ -8245,25 +8105,22 @@ static void flushUnresolvedRelations() } } - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); - MemberName *fn; - for (;(fn=fnli.current());++fnli) // for each global function name + // for each global function name + for (const auto &fn : *Doxygen::functionNameLinkedMap) { - MemberNameIterator fni(*fn); - MemberDef *fmd; - for (;(fmd=fni.current());++fni) // for each function with that name + // for each function with that name + for (const auto &fmd : *fn) { fmd->invalidateCachedArgumentTypes(); } } - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); - for (;(fn=mnli.current());++mnli) // for each class method name + // for each class method name + for (const auto &nm : *Doxygen::memberNameLinkedMap) { - MemberNameIterator mni(*fn); - MemberDef *fmd; - for (;(fmd=mni.current());++mni) // for each function with that name + // for each function with that name + for (const auto &md : *nm) { - fmd->invalidateCachedArgumentTypes(); + md->invalidateCachedArgumentTypes(); } } @@ -8282,40 +8139,29 @@ static void findDefineDocumentation(Entry *root) if (root->tagInfo() && !root->name.isEmpty()) // define read from a tag file { - MemberDef *md=createMemberDef(root->tagInfo()->tagName,1,1, + std::unique_ptr<MemberDef> md { createMemberDef(root->tagInfo()->tagName,1,1, "#define",root->name,root->args,0, Public,Normal,FALSE,Member,MemberType_Define, - ArgumentList(),ArgumentList(),""); + ArgumentList(),ArgumentList(),"") }; md->setTagInfo(root->tagInfo()); md->setLanguage(root->lang); //printf("Searching for '%s' fd=%p\n",filePathName.data(),fd); md->setFileDef(root->parent()->fileDef()); //printf("Adding member=%s\n",md->name().data()); - MemberName *mn; - if ((mn=Doxygen::functionNameSDict->find(root->name))) - { - mn->append(md); - } - else - { - mn = new MemberName(root->name); - mn->append(md); - Doxygen::functionNameSDict->append(root->name,mn); - } + MemberName *mn = Doxygen::functionNameLinkedMap->add(root->name); + mn->push_back(std::move(md)); } - MemberName *mn=Doxygen::functionNameSDict->find(root->name); + MemberName *mn=Doxygen::functionNameLinkedMap->find(root->name); if (mn) { - MemberNameIterator mni(*mn); - MemberDef *md; int count=0; - for (;(md=mni.current());++mni) + for (const auto &md : *mn) { if (md->memberType()==MemberType_Define) count++; } if (count==1) { - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { if (md->memberType()==MemberType_Define) { @@ -8326,13 +8172,13 @@ static void findDefineDocumentation(Entry *root) { md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); } - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setBodyDef(root->fileDef()); md->addSectionsToDefinition(root->anchors); md->setMaxInitLines(root->initLines); md->setRefItems(root->sli); if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId); - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); } } } @@ -8345,7 +8191,7 @@ static void findDefineDocumentation(Entry *root) // multiple defines don't know where to add docs // but maybe they are in different files together with their documentation { - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { if (md->memberType()==MemberType_Define) { @@ -8370,13 +8216,13 @@ static void findDefineDocumentation(Entry *root) { md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); } - md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); md->setBodyDef(root->fileDef()); md->addSectionsToDefinition(root->anchors); md->setRefItems(root->sli); md->setLanguage(root->lang); if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId); - addMemberToGroups(root,md); + addMemberToGroups(root,md.get()); } } } @@ -8399,7 +8245,7 @@ static void findDefineDocumentation(Entry *root) else { warn(root->fileName,root->startLine, - "found documented #define but ignoring it because " + "found documented #define %s but ignoring it because " "ENABLE_PREPROCESSING is NO.\n", root->name.data() ); @@ -8519,30 +8365,32 @@ static void findMainPage(Entry *root) Doxygen::mainPage->setLocalToc(root->localToc); addPageToContext(Doxygen::mainPage,root); - SectionInfo *si = Doxygen::sectionDict->find(Doxygen::mainPage->name()); + const SectionInfo *si = SectionManager::instance().find(Doxygen::mainPage->name()); if (si) { - if (si->lineNr != -1) + if (si->lineNr() != -1) { - warn(root->fileName,root->startLine,"multiple use of section label '%s' for main page, (first occurrence: %s, line %d)",Doxygen::mainPage->name().data(),si->fileName.data(),si->lineNr); + warn(root->fileName,root->startLine,"multiple use of section label '%s' for main page, (first occurrence: %s, line %d)", + Doxygen::mainPage->name().data(),si->fileName().data(),si->lineNr()); } else { - warn(root->fileName,root->startLine,"multiple use of section label '%s' for main page, (first occurrence: %s)",Doxygen::mainPage->name().data(),si->fileName.data()); + warn(root->fileName,root->startLine,"multiple use of section label '%s' for main page, (first occurrence: %s)", + Doxygen::mainPage->name().data(),si->fileName().data()); } } else { // a page name is a label as well! but should no be double either - si=new SectionInfo( - indexName, root->startLine, + SectionManager::instance().add( Doxygen::mainPage->name(), + indexName, + root->startLine, Doxygen::mainPage->title(), - SectionInfo::Page, + SectionType::Page, 0); // level 0 - Doxygen::sectionDict->append(indexName,si); - Doxygen::mainPage->addSectionsToDefinition(root->anchors); } + Doxygen::mainPage->addSectionsToDefinition(root->anchors); } else if (root->tagInfo()==0) { @@ -8625,9 +8473,7 @@ static void checkPageRelations() static void resolveUserReferences() { - SDict<SectionInfo>::Iterator sdi(*Doxygen::sectionDict); - SectionInfo *si; - for (;(si=sdi.current());++sdi) + for (const auto &si : SectionManager::instance()) { //printf("si->label='%s' si->definition=%s si->fileName='%s'\n", // si->label.data(),si->definition?si->definition->name().data():"<none>", @@ -8639,44 +8485,42 @@ static void resolveUserReferences() // name (not from the todo/test/bug/deprecated list, but from the file in // which they are defined). We correct this here by looking at the // generated section labels! - QDictIterator<RefList> rli(*Doxygen::xrefLists); - RefList *rl; - for (rli.toFirst();(rl=rli.current());++rli) + for (const RefListManager::Ptr &rl : RefListManager::instance()) { QCString label="_"+rl->listName(); // "_todo", "_test", ... - if (si->label.left(label.length())==label) + if (si->label().left(label.length())==label) { - si->fileName=rl->listName(); - si->generated=TRUE; + si->setFileName(rl->listName()); + si->setGenerated(TRUE); break; } } //printf("start: si->label=%s si->fileName=%s\n",si->label.data(),si->fileName.data()); - if (!si->generated) + if (!si->generated()) { // if this section is in a page and the page is in a group, then we // have to adjust the link file name to point to the group. - if (!si->fileName.isEmpty() && - (pd=Doxygen::pageSDict->find(si->fileName)) && + if (!si->fileName().isEmpty() && + (pd=Doxygen::pageSDict->find(si->fileName())) && pd->getGroupDef()) { - si->fileName=pd->getGroupDef()->getOutputFileBase().copy(); + si->setFileName(pd->getGroupDef()->getOutputFileBase()); } - if (si->definition) + if (si->definition()) { // TODO: there should be one function in Definition that returns // the file to link to, so we can avoid the following tests. const GroupDef *gd=0; - if (si->definition->definitionType()==Definition::TypeMember) + if (si->definition()->definitionType()==Definition::TypeMember) { - gd = (dynamic_cast<MemberDef *>(si->definition))->getGroupDef(); + gd = (dynamic_cast<MemberDef *>(si->definition()))->getGroupDef(); } if (gd) { - si->fileName=gd->getOutputFileBase().copy(); + si->setFileName(gd->getOutputFileBase()); } else { @@ -8795,7 +8639,10 @@ static void generateExampleDocs() pd->documentation()+"\n\n\\include"+lineNoOptStr+" "+pd->name(), // docs TRUE, // index words TRUE, // is example - pd->name() + pd->name(), + FALSE, + FALSE, + Config_getBool(MARKDOWN_SUPPORT) ); endFile(*g_outputList); // contains g_outputList->endContents() } @@ -9019,10 +8866,10 @@ static void readTagFile(const std::shared_ptr<Entry> &root,const char *tl) //---------------------------------------------------------------------------- static void copyLatexStyleSheet() { - QStrList latexExtraStyleSheet = Config_getList(LATEX_EXTRA_STYLESHEET); - for (uint i=0; i<latexExtraStyleSheet.count(); ++i) + const StringVector &latexExtraStyleSheet = Config_getList(LATEX_EXTRA_STYLESHEET); + for (const auto &sheet : latexExtraStyleSheet) { - QCString fileName(latexExtraStyleSheet.at(i)); + QCString fileName = sheet.c_str(); if (!fileName.isEmpty()) { QFileInfo fi(fileName); @@ -9033,9 +8880,9 @@ static void copyLatexStyleSheet() else { QCString destFileName = Config_getString(LATEX_OUTPUT)+"/"+fi.fileName().data(); - if (!checkExtension(fi.fileName().data(), latexStyleExtension)) + if (!checkExtension(fi.fileName().data(), LATEX_STYLE_EXTENSION)) { - destFileName += latexStyleExtension; + destFileName += LATEX_STYLE_EXTENSION; } copyFile(fileName, destFileName); } @@ -9046,14 +8893,14 @@ static void copyLatexStyleSheet() //---------------------------------------------------------------------------- static void copyStyleSheet() { - QCString &htmlStyleSheet = Config_getString(HTML_STYLESHEET); + QCString htmlStyleSheet = Config_getString(HTML_STYLESHEET); if (!htmlStyleSheet.isEmpty()) { QFileInfo fi(htmlStyleSheet); if (!fi.exists()) { err("Style sheet '%s' specified by HTML_STYLESHEET does not exist!\n",htmlStyleSheet.data()); - htmlStyleSheet.resize(0); // revert to the default + htmlStyleSheet = Config_updateString(HTML_STYLESHEET,""); // revert to the default } else { @@ -9061,10 +8908,10 @@ static void copyStyleSheet() copyFile(htmlStyleSheet,destFileName); } } - QStrList htmlExtraStyleSheet = Config_getList(HTML_EXTRA_STYLESHEET); - for (uint i=0; i<htmlExtraStyleSheet.count(); ++i) + const StringVector &htmlExtraStyleSheet = Config_getList(HTML_EXTRA_STYLESHEET); + for (const auto &sheet : htmlExtraStyleSheet) { - QCString fileName(htmlExtraStyleSheet.at(i)); + QCString fileName = sheet.c_str(); if (!fileName.isEmpty()) { QFileInfo fi(fileName); @@ -9087,14 +8934,14 @@ static void copyStyleSheet() static void copyLogo(const QCString &outputOption) { - QCString &projectLogo = Config_getString(PROJECT_LOGO); + QCString projectLogo = Config_getString(PROJECT_LOGO); if (!projectLogo.isEmpty()) { QFileInfo fi(projectLogo); if (!fi.exists()) { err("Project logo '%s' specified by PROJECT_LOGO does not exist!\n",projectLogo.data()); - projectLogo.resize(0); // revert to the default + projectLogo = Config_updateString(PROJECT_LOGO,""); // revert to the default } else { @@ -9105,13 +8952,11 @@ static void copyLogo(const QCString &outputOption) } } -static void copyExtraFiles(QStrList files,const QCString &filesOption,const QCString &outputOption) +static void copyExtraFiles(const StringVector &files,const QCString &filesOption,const QCString &outputOption) { - uint i; - for (i=0; i<files.count(); ++i) + for (const auto &file : files) { - QCString fileName(files.at(i)); - + QCString fileName = file.c_str(); if (!fileName.isEmpty()) { QFileInfo fi(fileName); @@ -9131,7 +8976,73 @@ static void copyExtraFiles(QStrList files,const QCString &filesOption,const QCSt //---------------------------------------------------------------------------- -static OutlineParserInterface &getParserForFile(const char *fn) +static void generateDiskNames() +{ + for (const auto &fn : *Doxygen::inputNameLinkedMap) + { + struct FileEntry + { + FileEntry(const QCString &p,FileDef *fd) : path(p), fileDef(fd) {} + QCString path; + FileDef *fileDef; + }; + + // collect the entry for which to compute the longest common prefix (LCP) of the path + std::vector<FileEntry> fileEntries; + for (const auto &fd : *fn) + { + if (!fd->isReference()) // skip external references + { + fileEntries.emplace_back(fd->getPath(),fd.get()); + } + } + + size_t size = fileEntries.size(); + + if (size==1) // name if unique, so diskname is simply the name + { + FileDef *fd = fileEntries[0].fileDef; + fd->setDiskName(fn->fileName()); + } + else if (size>1) // multiple occurrences of the same file name + { + // sort the array + std::sort(fileEntries.begin(), + fileEntries.end(), + [](const FileEntry &fe1,const FileEntry &fe2) + { return qstrcmp(fe1.path.data(),fe2.path.data())<0; } + ); + + // since the entries are sorted, the common prefix of the whole array is same + // as the common prefix between the first and last entry + const FileEntry &first = fileEntries[0]; + const FileEntry &last = fileEntries[size-1]; + int first_path_size = static_cast<int>(first.path.size()); + int last_path_size = static_cast<int>(last.path.size()); + int j=0; + for (int i=0;i<first_path_size && i<last_path_size;i++) + { + if (first.path[i]=='/') j=i; + if (first.path[i]!=last.path[i]) break; + } + + // add non-common part of the path to the name + for (auto &fileEntry : fileEntries) + { + QCString prefix = fileEntry.path.right(fileEntry.path.length()-j-1); + fileEntry.fileDef->setName(prefix+fn->fileName()); + //printf("!!!!!!!! non unique disk name=%s:%s\n",prefix.data(),fn->fileName()); + fileEntry.fileDef->setDiskName(prefix+fn->fileName()); + } + } + } +} + + + +//---------------------------------------------------------------------------- + +static std::unique_ptr<OutlineParserInterface> getParserForFile(const char *fn) { QCString fileName=fn; QCString extension; @@ -9149,15 +9060,10 @@ static OutlineParserInterface &getParserForFile(const char *fn) return Doxygen::parserManager->getOutlineParser(extension); } -static void parseFile(OutlineParserInterface &parser, - const std::shared_ptr<Entry> &root,FileDef *fd,const char *fn, - bool sameTu,QStrList &filesInSameTu) +static std::shared_ptr<Entry> parseFile(OutlineParserInterface &parser, + FileDef *fd,const char *fn, + ClangTUParser *clangParser,bool newTU) { -#if USE_LIBCLANG - static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); -#else - static bool clangAssistedParsing = FALSE; -#endif QCString fileName=fn; QCString extension; int ei = fileName.findRev('.'); @@ -9176,10 +9082,16 @@ static void parseFile(OutlineParserInterface &parser, if (Config_getBool(ENABLE_PREPROCESSING) && parser.needsPreprocessing(extension)) { + Preprocessor preprocessor; + const StringVector &includePath = Config_getList(INCLUDE_PATH); + for (const auto &s : includePath) + { + preprocessor.addSearchDir(QFileInfo(s.c_str()).absFilePath().utf8()); + } BufStr inBuf(fi.size()+4096); msg("Preprocessing %s...\n",fn); readInputFile(fileName,inBuf); - Doxygen::preprocessor->processFile(fileName,inBuf,preBuf); + preprocessor.processFile(fileName,inBuf,preBuf); } else // no preprocessing { @@ -9198,103 +9110,235 @@ static void parseFile(OutlineParserInterface &parser, convBuf.addChar('\0'); - if (clangAssistedParsing && !sameTu) - { - fd->getAllIncludeFilesRecursively(filesInSameTu); - } - std::shared_ptr<Entry> fileRoot = std::make_shared<Entry>(); // use language parse to parse the file - parser.parseInput(fileName,convBuf.data(),fileRoot,sameTu,filesInSameTu); + if (clangParser) + { + if (newTU) clangParser->parse(); + clangParser->switchToFile(fd); + } + parser.parseInput(fileName,convBuf.data(),fileRoot,clangParser); fileRoot->setFileDef(fd); - root->moveToSubEntryAndKeep(fileRoot); + return fileRoot; +} + +//! parse the list of input files +static void parseFilesMultiThreading(const std::shared_ptr<Entry> &root) +{ +#if USE_LIBCLANG + if (Doxygen::clangAssistedParsing) + { + StringUnorderedSet processedFiles; + + // create a dictionary with files to process + StringUnorderedSet filesToProcess; + for (const auto &s : g_inputFiles) + { + filesToProcess.insert(s); + } + + std::mutex processedFilesLock; + // process source files (and their include dependencies) + std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS)); + if (numThreads==0) + { + numThreads = std::thread::hardware_concurrency(); + } + msg("Processing input using %zu threads.\n",numThreads); + ThreadPool threadPool(numThreads); + using FutureType = std::vector< std::shared_ptr<Entry> >; + std::vector< std::future< FutureType > > results; + for (const auto &s : g_inputFiles) + { + bool ambig; + FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,s.c_str(),ambig); + ASSERT(fd!=0); + if (fd->isSource() && !fd->isReference()) // this is a source file + { + // lambda representing the work to executed by a thread + auto processFile = [s,&filesToProcess,&processedFilesLock,&processedFiles]() { + bool ambig_l; + std::vector< std::shared_ptr<Entry> > roots; + FileDef *fd_l = findFileDef(Doxygen::inputNameLinkedMap,s.c_str(),ambig_l); + auto clangParser = ClangParser::instance()->createTUParser(fd_l); + auto parser = getParserForFile(s.c_str()); + auto fileRoot { parseFile(*parser.get(),fd_l,s.c_str(),clangParser.get(),true) }; + roots.push_back(fileRoot); + + // Now process any include files in the same translation unit + // first. When libclang is used this is much more efficient. + for (auto incFile : clangParser->filesInSameTU()) + { + if (filesToProcess.find(incFile)!=filesToProcess.end()) + { + bool needsToBeProcessed; + { + std::lock_guard<std::mutex> lock(processedFilesLock); + needsToBeProcessed = processedFiles.find(incFile)==processedFiles.end(); + if (needsToBeProcessed) processedFiles.insert(incFile); + } + if (incFile!=s && needsToBeProcessed) + { + FileDef *ifd=findFileDef(Doxygen::inputNameLinkedMap,incFile.c_str(),ambig_l); + if (ifd && !ifd->isReference()) + { + //printf(" Processing %s in same translation unit as %s\n",incFile,s->c_str()); + fileRoot = parseFile(*parser.get(),ifd,incFile.c_str(),clangParser.get(),false); + roots.push_back(fileRoot); + } + } + } + } + return roots; + }; + // dispatch the work and collect the future results + results.emplace_back(threadPool.queue(processFile)); + } + } + // synchronise with the Entry result lists produced and add them to the root + for (auto &f : results) + { + auto l = f.get(); + for (auto &e : l) + { + root->moveToSubEntryAndKeep(e); + } + } + // process remaining files + results.clear(); + for (const auto &s : g_inputFiles) + { + if (processedFiles.find(s)==processedFiles.end()) // not yet processed + { + // lambda representing the work to executed by a thread + auto processFile = [s]() { + bool ambig; + std::vector< std::shared_ptr<Entry> > roots; + FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,s.c_str(),ambig); + auto clangParser = ClangParser::instance()->createTUParser(fd); + auto parser { getParserForFile(s.c_str()) }; + auto fileRoot = parseFile(*parser.get(),fd,s.c_str(),clangParser.get(),true); + roots.push_back(fileRoot); + return roots; + }; + // dispatch the work and collect the future results + results.emplace_back(threadPool.queue(processFile)); + } + } + // synchronise with the Entry result lists produced and add them to the root + for (auto &f : results) + { + auto l = f.get(); + for (auto &e : l) + { + root->moveToSubEntryAndKeep(e); + } + } + } + else // normal processing +#endif + { + std::size_t numThreads = std::thread::hardware_concurrency(); + msg("Processing input using %zu threads.\n",numThreads); + ThreadPool threadPool(numThreads); + using FutureType = std::shared_ptr<Entry>; + std::vector< std::future< FutureType > > results; + for (const auto &s : g_inputFiles) + { + // lambda representing the work to executed by a thread + auto processFile = [s]() { + bool ambig; + FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,s.c_str(),ambig); + auto parser = getParserForFile(s.c_str()); + auto fileRoot = parseFile(*parser.get(),fd,s.c_str(),nullptr,true); + return fileRoot; + }; + // dispatch the work and collect the future results + results.emplace_back(threadPool.queue(processFile)); + } + // synchronise with the Entry results produced and add them to the root + for (auto &f : results) + { + root->moveToSubEntryAndKeep(f.get()); + } + } } //! parse the list of input files -static void parseFiles(const std::shared_ptr<Entry> &root) +static void parseFilesSingleThreading(const std::shared_ptr<Entry> &root) { #if USE_LIBCLANG - static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); - if (clangAssistedParsing) + if (Doxygen::clangAssistedParsing) { - QDict<void> g_processedFiles(10007); + StringUnorderedSet processedFiles; // create a dictionary with files to process - QDict<void> g_filesToProcess(10007); - StringListIterator it(g_inputFiles); - QCString *s; - for (;(s=it.current());++it) + StringUnorderedSet filesToProcess; + for (const auto &s : g_inputFiles) { - g_filesToProcess.insert(*s,(void*)0x8); + filesToProcess.insert(s); } // process source files (and their include dependencies) - for (it.toFirst();(s=it.current());++it) + for (const auto &s : g_inputFiles) { bool ambig; - FileDef *fd=findFileDef(Doxygen::inputNameDict,s->data(),ambig); + FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,s.c_str(),ambig); ASSERT(fd!=0); if (fd->isSource() && !fd->isReference()) // this is a source file { - QStrList filesInSameTu; - OutlineParserInterface &parser = getParserForFile(s->data()); - parser.startTranslationUnit(s->data()); - parseFile(parser,root,fd,s->data(),FALSE,filesInSameTu); - //printf(" got %d extra files in tu\n",filesInSameTu.count()); + auto clangParser = ClangParser::instance()->createTUParser(fd); + auto parser { getParserForFile(s.c_str()) }; + auto fileRoot = parseFile(*parser.get(),fd,s.c_str(),clangParser.get(),true); + root->moveToSubEntryAndKeep(fileRoot); + processedFiles.insert(s); // Now process any include files in the same translation unit // first. When libclang is used this is much more efficient. - char *incFile = filesInSameTu.first(); - while (incFile && g_filesToProcess.find(incFile)) + for (auto incFile : clangParser->filesInSameTU()) { - if (qstrcmp(incFile,s->data()) && !g_processedFiles.find(incFile)) + //printf(" file %s\n",incFile.c_str()); + if (filesToProcess.find(incFile)!=filesToProcess.end() && // file need to be processed + processedFiles.find(incFile)==processedFiles.end()) // and is not processed already { - FileDef *ifd=findFileDef(Doxygen::inputNameDict,incFile,ambig); + FileDef *ifd=findFileDef(Doxygen::inputNameLinkedMap,incFile.c_str(),ambig); if (ifd && !ifd->isReference()) { - QStrList moreFiles; - //printf(" Processing %s in same translation unit as %s\n",incFile,s->data()); - parseFile(parser,root,ifd,incFile,TRUE,moreFiles); - g_processedFiles.insert(incFile,(void*)0x8); + //printf(" Processing %s in same translation unit as %s\n",incFile.c_str(),s.c_str()); + fileRoot = parseFile(*parser.get(),ifd,incFile.c_str(),clangParser.get(),false); + root->moveToSubEntryAndKeep(fileRoot); + processedFiles.insert(incFile); } } - incFile = filesInSameTu.next(); } - parser.finishTranslationUnit(); - g_processedFiles.insert(*s,(void*)0x8); } } // process remaining files - for (it.toFirst();(s=it.current());++it) + for (const auto &s : g_inputFiles) { - if (!g_processedFiles.find(*s)) // not yet processed + if (processedFiles.find(s)==processedFiles.end()) // not yet processed { bool ambig; - QStrList filesInSameTu; - FileDef *fd=findFileDef(Doxygen::inputNameDict,s->data(),ambig); - ASSERT(fd!=0); - OutlineParserInterface &parser = getParserForFile(s->data()); - parser.startTranslationUnit(s->data()); - parseFile(parser,root,fd,s->data(),FALSE,filesInSameTu); - parser.finishTranslationUnit(); - g_processedFiles.insert(*s,(void*)0x8); + FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,s.c_str(),ambig); + auto clangParser = ClangParser::instance()->createTUParser(fd); + auto parser { getParserForFile(s.c_str()) }; + auto fileRoot = parseFile(*parser.get(),fd,s.c_str(),clangParser.get(),true); + root->moveToSubEntryAndKeep(fileRoot); + processedFiles.insert(s); } } } else // normal processing #endif { - StringListIterator it(g_inputFiles); - QCString *s; - for (;(s=it.current());++it) + for (const auto &s : g_inputFiles) { bool ambig; - QStrList filesInSameTu; - FileDef *fd=findFileDef(Doxygen::inputNameDict,s->data(),ambig); + FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,s.c_str(),ambig); ASSERT(fd!=0); - OutlineParserInterface &parser = getParserForFile(s->data()); - parser.startTranslationUnit(s->data()); - parseFile(parser,root,fd,s->data(),FALSE,filesInSameTu); + std::unique_ptr<OutlineParserInterface> parser { getParserForFile(s.c_str()) }; + std::shared_ptr<Entry> fileRoot = parseFile(*parser.get(),fd,s.c_str(),nullptr,true); + root->moveToSubEntryAndKeep(fileRoot); } } } @@ -9367,7 +9411,8 @@ static QCString resolveSymlink(QCString path) return QDir::cleanDirPath(result).data(); } -static QDict<void> g_pathsVisited(1009); +static std::mutex g_pathsVisitedMutex; +static StringUnorderedSet g_pathsVisited(1009); //---------------------------------------------------------------------------- // Read all files matching at least one pattern in 'patList' in the @@ -9375,37 +9420,38 @@ static QDict<void> g_pathsVisited(1009); // The directory is read iff the recursiveFlag is set. // The contents of all files is append to the input string -int readDir(QFileInfo *fi, - FileNameList *fnList, - FileNameDict *fnDict, - StringDict *exclDict, - QStrList *patList, - QStrList *exclPatList, - StringList *resultList, - StringDict *resultDict, +static int readDir(QFileInfo *fi, + FileNameLinkedMap *fnMap, + StringUnorderedSet *exclSet, + const StringVector *patList, + const StringVector *exclPatList, + StringVector *resultList, + StringUnorderedSet *resultSet, bool errorIfNotExist, bool recursive, - QDict<void> *killDict, - QDict<void> *paths + StringUnorderedSet *killSet, + StringSet *paths ) { QCString dirName = fi->absFilePath().utf8(); - if (paths && paths->find(dirName)==0) + if (paths && !dirName.isEmpty()) { - paths->insert(dirName,(void*)0x8); + paths->insert(dirName.data()); } if (fi->isSymLink()) { dirName = resolveSymlink(dirName.data()); if (dirName.isEmpty()) return 0; // recursive symlink - if (g_pathsVisited.find(dirName)) return 0; // already visited path - g_pathsVisited.insert(dirName,(void*)0x8); + + std::lock_guard<std::mutex> lock(g_pathsVisitedMutex); + if (g_pathsVisited.find(dirName.str())!=g_pathsVisited.end()) return 0; // already visited path + g_pathsVisited.insert(dirName.str()); } QDir dir(dirName); dir.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden ); int totalSize=0; msg("Searching for files in directory %s\n", fi->absFilePath().data()); - //printf("killDict=%p count=%d\n",killDict,killDict->count()); + //printf("killSet=%p count=%d\n",killSet,killSet ? (int)killSet->count() : -1); const QFileInfoList *list = dir.entryInfoList(); if (list) @@ -9415,9 +9461,9 @@ int readDir(QFileInfo *fi, while ((cfi=it.current())) { - if (exclDict==0 || exclDict->find(cfi->absFilePath().utf8())==0) + if (exclSet==0 || exclSet->find(cfi->absFilePath().utf8().data())==exclSet->end()) { // file should not be excluded - //printf("killDict->find(%s)\n",cfi->absFilePath().data()); + //printf("killSet->find(%s)\n",cfi->absFilePath().data()); if (!cfi->exists() || !cfi->isReadable()) { if (errorIfNotExist) @@ -9427,49 +9473,38 @@ int readDir(QFileInfo *fi, } else if (cfi->isFile() && (!Config_getBool(EXCLUDE_SYMLINKS) || !cfi->isSymLink()) && - (patList==0 || patternMatch(*cfi,patList)) && - !patternMatch(*cfi,exclPatList) && - (killDict==0 || killDict->find(cfi->absFilePath().utf8())==0) + (patList==0 || patternMatch(*cfi,*patList)) && + (exclPatList==0 || !patternMatch(*cfi,*exclPatList)) && + (killSet==0 || killSet->find(cfi->absFilePath().utf8().data())==killSet->end()) ) { totalSize+=cfi->size()+cfi->absFilePath().length()+4; QCString name=cfi->fileName().utf8(); //printf("New file %s\n",name.data()); - if (fnDict) + if (fnMap) { - FileDef *fd=createFileDef(cfi->dirPath().utf8()+"/",name); + std::unique_ptr<FileDef> fd { createFileDef(cfi->dirPath().utf8()+"/",name) }; FileName *fn=0; - if (!name.isEmpty() && (fn=(*fnDict)[name])) + if (!name.isEmpty()) { - fn->append(fd); + fn = fnMap->add(name,cfi->absFilePath().utf8()); + fn->push_back(std::move(fd)); } - else - { - fn = new FileName(cfi->absFilePath().utf8(),name); - fn->append(fd); - if (fnList) fnList->append(fn); - fnDict->insert(name,fn); - } - } - QCString *rs=0; - if (resultList || resultDict) - { - rs=new QCString(cfi->absFilePath().utf8()); } - if (resultList) resultList->append(rs); - if (resultDict) resultDict->insert(cfi->absFilePath().utf8(),rs); - if (killDict) killDict->insert(cfi->absFilePath().utf8(),(void *)0x8); + if (resultList) resultList->push_back(cfi->absFilePath().utf8().data()); + if (resultSet) resultSet->insert(cfi->absFilePath().utf8().data()); + if (killSet) killSet->insert(cfi->absFilePath().utf8().data()); } else if (recursive && (!Config_getBool(EXCLUDE_SYMLINKS) || !cfi->isSymLink()) && cfi->isDir() && - !patternMatch(*cfi,exclPatList) && + (exclPatList==0 || !patternMatch(*cfi,*exclPatList)) && cfi->fileName().at(0)!='.') // skip "." ".." and ".dir" { cfi->setFile(cfi->absFilePath()); - totalSize+=readDir(cfi,fnList,fnDict,exclDict, - patList,exclPatList,resultList,resultDict,errorIfNotExist, - recursive,killDict,paths); + totalSize+=readDir(cfi,fnMap,exclSet, + patList,exclPatList,resultList,resultSet,errorIfNotExist, + recursive,killSet,paths); } } ++it; @@ -9484,20 +9519,19 @@ int readDir(QFileInfo *fi, // input string. The names of the files are appended to the 'fiList' list. int readFileOrDirectory(const char *s, - FileNameList *fnList, - FileNameDict *fnDict, - StringDict *exclDict, - QStrList *patList, - QStrList *exclPatList, - StringList *resultList, - StringDict *resultDict, + FileNameLinkedMap *fnMap, + StringUnorderedSet *exclSet, + const StringVector *patList, + const StringVector *exclPatList, + StringVector *resultList, + StringUnorderedSet *resultSet, bool recursive, bool errorIfNotExist, - QDict<void> *killDict, - QDict<void> *paths + StringUnorderedSet *killSet, + StringSet *paths ) { - //printf("killDict=%p count=%d\n",killDict,killDict->count()); + //printf("killSet count=%d\n",killSet ? (int)killSet->size() : -1); // strip trailing slashes if (s==0) return 0; QCString fs = s; @@ -9508,7 +9542,7 @@ int readFileOrDirectory(const char *s, //printf("readFileOrDirectory(%s)\n",s); int totalSize=0; { - if (exclDict==0 || exclDict->find(fi.absFilePath().utf8())==0) + if (exclSet==0 || exclSet->find(fi.absFilePath().utf8().data())==exclSet->end()) { if (!fi.exists() || !fi.isReadable()) { @@ -9523,49 +9557,40 @@ int readFileOrDirectory(const char *s, { QCString dirPath = fi.dirPath(TRUE).utf8(); QCString filePath = fi.absFilePath().utf8(); - if (paths && paths->find(dirPath)) + if (paths && !dirPath.isEmpty()) { - paths->insert(dirPath,(void*)0x8); + paths->insert(dirPath.data()); } - //printf("killDict->find(%s)\n",fi.absFilePath().data()); - if (killDict==0 || killDict->find(filePath)==0) + //printf("killSet.find(%s)=%d\n",fi.absFilePath().data(),killSet.find(fi.absFilePath())!=killSet.end()); + if (killSet==0 || killSet->find(filePath.data())==killSet->end()) { totalSize+=fi.size()+fi.absFilePath().length()+4; //readFile(&fi,fiList,input); //fiList->inSort(new FileInfo(fi)); QCString name=fi.fileName().utf8(); //printf("New file %s\n",name.data()); - if (fnDict) + if (fnMap) { - FileDef *fd=createFileDef(dirPath+"/",name); - FileName *fn=0; - if (!name.isEmpty() && (fn=(*fnDict)[name])) + std::unique_ptr<FileDef> fd { createFileDef(dirPath+"/",name) }; + if (!name.isEmpty()) { - fn->append(fd); - } - else - { - fn = new FileName(filePath,name); - fn->append(fd); - if (fnList) fnList->append(fn); - fnDict->insert(name,fn); + FileName *fn = fnMap->add(name,filePath); + fn->push_back(std::move(fd)); } } - QCString *rs=0; - if (resultList || resultDict) + if (resultList || resultSet) { - rs=new QCString(filePath); - if (resultList) resultList->append(rs); - if (resultDict) resultDict->insert(filePath,rs); + if (resultList) resultList->push_back(filePath.data()); + if (resultSet) resultSet->insert(filePath.data()); } - if (killDict) killDict->insert(fi.absFilePath().utf8(),(void *)0x8); + if (killSet) killSet->insert(fi.absFilePath().utf8().data()); } } else if (fi.isDir()) // readable dir { - totalSize+=readDir(&fi,fnList,fnDict,exclDict,patList, - exclPatList,resultList,resultDict,errorIfNotExist, - recursive,killDict,paths); + totalSize+=readDir(&fi,fnMap,exclSet,patList, + exclPatList,resultList,resultSet,errorIfNotExist, + recursive,killSet,paths); } } } @@ -9575,66 +9600,6 @@ int readFileOrDirectory(const char *s, //---------------------------------------------------------------------------- -void readFormulaRepository(QCString dir, bool cmp) -{ - static int current_repository = 0; - int new_repository = 0; - QFile f(dir+"/formula.repository"); - if (f.open(IO_ReadOnly)) // open repository - { - msg("Reading formula repository...\n"); - QTextStream t(&f); - QCString line; - Formula *f; - while (!t.eof()) - { - line=t.readLine().utf8(); - int se=line.find(':'); // find name and text separator. - if (se==-1) - { - warn_uncond("formula.repository is corrupted!\n"); - break; - } - else - { - QCString formName = line.left(se); - QCString formText = line.right(line.length()-se-1); - if (cmp) - { - if ((f=Doxygen::formulaDict->find(formText))==0) - { - term("discrepancy between formula repositories! Remove " - "formula.repository and from_* files from output directories."); - } - QCString formLabel; - formLabel.sprintf("\\_form#%d",f->getId()); - if (formLabel != formName) - { - term("discrepancy between formula repositories! Remove " - "formula.repository and from_* files from output directories."); - } - new_repository++; - } - else - { - f=new Formula(formText); - Doxygen::formulaList->append(f); - Doxygen::formulaDict->insert(formText,f); - Doxygen::formulaNameDict->insert(formName,f); - current_repository++; - } - } - } - } - if (cmp && (current_repository != new_repository)) - { - term("size discrepancy between formula repositories! Remove " - "formula.repository and from_* files from output directories."); - } -} - -//---------------------------------------------------------------------------- - static void expandAliases() { QDictIterator<QCString> adi(Doxygen::aliasDict); @@ -9666,7 +9631,7 @@ static void escapeAliases() value.mid(in,14)!="\\nosubgrouping" ) { - newValue+="\\_linebr "; + newValue+="\\ilinebr "; } else { @@ -9681,7 +9646,7 @@ static void escapeAliases() while ((in=value.find("^^",p))!=-1) { newValue+=value.mid(p,in-p); - newValue+="\\\\_linebr "; + newValue+="\\ilinebr "; p=in+2; } newValue+=value.mid(p,value.length()-p); @@ -9696,13 +9661,12 @@ void readAliases() { // add aliases to a dictionary Doxygen::aliasDict.setAutoDelete(TRUE); - QStrList &aliasList = Config_getList(ALIASES); - const char *s=aliasList.first(); - while (s) + const StringVector &aliasList = Config_getList(ALIASES); + for (const auto &s : aliasList) { - if (Doxygen::aliasDict[s]==0) + QCString alias=s.c_str(); + if (Doxygen::aliasDict[alias]==0) { - QCString alias=s; int i=alias.find('='); if (i>0) { @@ -9723,7 +9687,6 @@ void readAliases() } } } - s=aliasList.next(); } expandAliases(); escapeAliases(); @@ -9851,14 +9814,16 @@ static const char *getArg(int argc,char **argv,int &optind) class NullOutlineParser : public OutlineParserInterface { public: - void startTranslationUnit(const char *) {} - void finishTranslationUnit() {} - void parseInput(const char *, const char *,const std::shared_ptr<Entry> &, bool, QStrList &) {} + void parseInput(const char *, const char *,const std::shared_ptr<Entry> &, ClangTUParser*) {} bool needsPreprocessing(const QCString &) const { return FALSE; } void parsePrototype(const char *) {} }; +template<class T> std::function< std::unique_ptr<T>() > make_output_parser_factory() +{ + return []() { return std::make_unique<T>(); }; +} void initDoxygen() { @@ -9871,30 +9836,26 @@ void initDoxygen() Portable::correct_path(); - Doxygen::runningTime.start(); - Doxygen::preprocessor = new Preprocessor(); - - Doxygen::parserManager = new ParserManager( std::make_unique<NullOutlineParser>(), + Debug::startTimer(); + Doxygen::parserManager = new ParserManager( make_output_parser_factory<NullOutlineParser>(), std::make_unique<FileCodeParser>()); - Doxygen::parserManager->registerParser("c", std::make_unique<COutlineParser>(), + Doxygen::parserManager->registerParser("c", make_output_parser_factory<COutlineParser>(), std::make_unique<CCodeParser>()); - Doxygen::parserManager->registerParser("python", std::make_unique<PythonOutlineParser>(), + Doxygen::parserManager->registerParser("python", make_output_parser_factory<PythonOutlineParser>(), std::make_unique<PythonCodeParser>()); - Doxygen::parserManager->registerParser("fortran", std::make_unique<FortranOutlineParser>(), + Doxygen::parserManager->registerParser("fortran", make_output_parser_factory<FortranOutlineParser>(), std::make_unique<FortranCodeParser>()); - Doxygen::parserManager->registerParser("fortranfree", std::make_unique<FortranOutlineParserFree>(), + Doxygen::parserManager->registerParser("fortranfree", make_output_parser_factory<FortranOutlineParserFree>(), std::make_unique<FortranCodeParserFree>()); - Doxygen::parserManager->registerParser("fortranfixed", std::make_unique<FortranOutlineParserFixed>(), + Doxygen::parserManager->registerParser("fortranfixed", make_output_parser_factory<FortranOutlineParserFixed>(), std::make_unique<FortranCodeParserFixed>()); - Doxygen::parserManager->registerParser("vhdl", std::make_unique<VHDLOutlineParser>(), + Doxygen::parserManager->registerParser("vhdl", make_output_parser_factory<VHDLOutlineParser>(), std::make_unique<VHDLCodeParser>()); - Doxygen::parserManager->registerParser("xml", std::make_unique<NullOutlineParser>(), + Doxygen::parserManager->registerParser("xml", make_output_parser_factory<NullOutlineParser>(), std::make_unique<XMLCodeParser>()); - Doxygen::parserManager->registerParser("sql", std::make_unique<NullOutlineParser>(), + Doxygen::parserManager->registerParser("sql", make_output_parser_factory<NullOutlineParser>(), std::make_unique<SQLCodeParser>()); - Doxygen::parserManager->registerParser("tcl", std::make_unique<TclOutlineParser>(), - std::make_unique<TclCodeParser>()); - Doxygen::parserManager->registerParser("md", std::make_unique<MarkdownOutlineParser>(), + Doxygen::parserManager->registerParser("md", make_output_parser_factory<MarkdownOutlineParser>(), std::make_unique<FileCodeParser>()); // register any additional parsers here... @@ -9908,12 +9869,8 @@ void initDoxygen() #ifdef USE_LIBCLANG Doxygen::clangUsrMap = new QDict<Definition>(50177); #endif - Doxygen::inputNameList = new FileNameList; - Doxygen::inputNameList->setAutoDelete(TRUE); - Doxygen::memberNameSDict = new MemberNameSDict(10000); - Doxygen::memberNameSDict->setAutoDelete(TRUE); - Doxygen::functionNameSDict = new MemberNameSDict(10000); - Doxygen::functionNameSDict->setAutoDelete(TRUE); + Doxygen::memberNameLinkedMap = new MemberNameLinkedMap; + Doxygen::functionNameLinkedMap = new MemberNameLinkedMap; Doxygen::groupSDict = new GroupSDict(17); Doxygen::groupSDict->setAutoDelete(TRUE); Doxygen::namespaceSDict = new NamespaceSDict(20); @@ -9931,26 +9888,19 @@ void initDoxygen() Doxygen::memGrpInfoDict.setAutoDelete(TRUE); Doxygen::tagDestinationDict.setAutoDelete(TRUE); Doxygen::dirRelations.setAutoDelete(TRUE); - Doxygen::citeDict = new CiteDict(257); Doxygen::genericsDict = new GenericsSDict; Doxygen::indexList = new IndexList; - Doxygen::formulaList = new FormulaList; - Doxygen::formulaList->setAutoDelete(TRUE); - Doxygen::formulaDict = new FormulaDict(1009); - Doxygen::formulaNameDict = new FormulaDict(1009); - Doxygen::sectionDict = new SectionDict(257); - Doxygen::sectionDict->setAutoDelete(TRUE); // initialisation of these globals depends on // configuration switches so we need to postpone these Doxygen::globalScope = 0; - Doxygen::inputNameDict = 0; - Doxygen::includeNameDict = 0; - Doxygen::exampleNameDict = 0; - Doxygen::imageNameDict = 0; - Doxygen::dotFileNameDict = 0; - Doxygen::mscFileNameDict = 0; - Doxygen::diaFileNameDict = 0; + Doxygen::inputNameLinkedMap = 0; + Doxygen::includeNameLinkedMap = 0; + Doxygen::exampleNameLinkedMap = 0; + Doxygen::imageNameLinkedMap = 0; + Doxygen::dotFileNameLinkedMap = 0; + Doxygen::mscFileNameLinkedMap = 0; + Doxygen::diaFileNameLinkedMap = 0; /************************************************************************** * Initialize some global constants @@ -9967,26 +9917,23 @@ void initDoxygen() void cleanUpDoxygen() { - delete Doxygen::sectionDict; - delete Doxygen::formulaNameDict; - delete Doxygen::formulaDict; - delete Doxygen::formulaList; + FormulaManager::instance().clear(); + SectionManager::instance().clear(); + delete Doxygen::indexList; delete Doxygen::genericsDict; - delete Doxygen::inputNameDict; - delete Doxygen::includeNameDict; - delete Doxygen::exampleNameDict; - delete Doxygen::imageNameDict; - delete Doxygen::dotFileNameDict; - delete Doxygen::mscFileNameDict; - delete Doxygen::diaFileNameDict; + delete Doxygen::inputNameLinkedMap; + delete Doxygen::includeNameLinkedMap; + delete Doxygen::exampleNameLinkedMap; + delete Doxygen::imageNameLinkedMap; + delete Doxygen::dotFileNameLinkedMap; + delete Doxygen::mscFileNameLinkedMap; + delete Doxygen::diaFileNameLinkedMap; delete Doxygen::mainPage; delete Doxygen::pageSDict; delete Doxygen::exampleSDict; delete Doxygen::globalScope; - delete Doxygen::xrefLists; delete Doxygen::parserManager; - delete Doxygen::preprocessor; delete theTranslator; delete g_outputList; Mappers::freeMappers(); @@ -10011,15 +9958,16 @@ void cleanUpDoxygen() } } - delete Doxygen::inputNameList; - delete Doxygen::memberNameSDict; - delete Doxygen::functionNameSDict; + delete Doxygen::memberNameLinkedMap; + delete Doxygen::functionNameLinkedMap; delete Doxygen::groupSDict; delete Doxygen::classSDict; delete Doxygen::hiddenClasses; delete Doxygen::namespaceSDict; delete Doxygen::directories; + DotManager::deleteInstance(); + //delete Doxygen::symbolMap; <- we cannot do this unless all static lists // (such as Doxygen::namespaceSDict) // with objects based on Definition are made @@ -10040,15 +9988,7 @@ static int computeIdealCacheParam(uint v) void readConfiguration(int argc, char **argv) { - QCString versionString; - if (strlen(getGitVersion())>0) - { - versionString = QCString(getVersion())+" ("+getGitVersion()+")"; - } - else - { - versionString = getVersion(); - } + QCString versionString = getFullVersion(); /************************************************************************** * Handle arguments * @@ -10441,18 +10381,13 @@ void checkConfiguration() void adjustConfiguration() { Doxygen::globalScope = createNamespaceDef("<globalScope>",1,1,"<globalScope>"); - Doxygen::inputNameDict = new FileNameDict(10007); - Doxygen::includeNameDict = new FileNameDict(10007); - Doxygen::exampleNameDict = new FileNameDict(1009); - Doxygen::exampleNameDict->setAutoDelete(TRUE); - Doxygen::imageNameDict = new FileNameDict(257); - Doxygen::imageNameDict->setAutoDelete(TRUE); - Doxygen::dotFileNameDict = new FileNameDict(257); - Doxygen::dotFileNameDict->setAutoDelete(TRUE); - Doxygen::mscFileNameDict = new FileNameDict(257); - Doxygen::mscFileNameDict->setAutoDelete(TRUE); - Doxygen::diaFileNameDict = new FileNameDict(257); - Doxygen::diaFileNameDict->setAutoDelete(TRUE); + Doxygen::inputNameLinkedMap = new FileNameLinkedMap; + Doxygen::includeNameLinkedMap = new FileNameLinkedMap; + Doxygen::exampleNameLinkedMap = new FileNameLinkedMap; + Doxygen::imageNameLinkedMap = new FileNameLinkedMap; + Doxygen::dotFileNameLinkedMap = new FileNameLinkedMap; + Doxygen::mscFileNameLinkedMap = new FileNameLinkedMap; + Doxygen::diaFileNameLinkedMap = new FileNameLinkedMap; QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE); if (!setTranslator(outputLanguage)) @@ -10460,41 +10395,27 @@ void adjustConfiguration() warn_uncond("Output language %s not supported! Using English instead.\n", outputLanguage.data()); } - QStrList &includePath = Config_getList(INCLUDE_PATH); - char *s=includePath.first(); - while (s) - { - QFileInfo fi(s); - Doxygen::preprocessor->addSearchDir(fi.absFilePath().utf8()); - s=includePath.next(); - } /* Set the global html file extension. */ Doxygen::htmlFileExtension = Config_getString(HTML_FILE_EXTENSION); - Doxygen::xrefLists->setAutoDelete(TRUE); - Doxygen::parseSourcesNeeded = Config_getBool(CALL_GRAPH) || Config_getBool(CALLER_GRAPH) || Config_getBool(REFERENCES_RELATION) || Config_getBool(REFERENCED_BY_RELATION); - Doxygen::markdownSupport = Config_getBool(MARKDOWN_SUPPORT); - /************************************************************************** * Add custom extension mappings **************************************************************************/ - QStrList &extMaps = Config_getList(EXTENSION_MAPPING); - char *mapping = extMaps.first(); - while (mapping) + const StringVector &extMaps = Config_getList(EXTENSION_MAPPING); + for (const auto &mapping : extMaps) { - QCString mapStr = mapping; + QCString mapStr = mapping.c_str(); int i=mapStr.find('='); if (i==-1) { - mapping = extMaps.next(); continue; } else @@ -10503,7 +10424,6 @@ void adjustConfiguration() QCString language = mapStr.mid(i+1).stripWhiteSpace().lower(); if (ext.isEmpty() || language.isEmpty()) { - mapping = extMaps.next(); continue; } @@ -10519,26 +10439,20 @@ void adjustConfiguration() ext.data(),language.data()); } } - mapping = extMaps.next(); } // add predefined macro name to a dictionary - QStrList &expandAsDefinedList =Config_getList(EXPAND_AS_DEFINED); - s=expandAsDefinedList.first(); - while (s) + const StringVector &expandAsDefinedList =Config_getList(EXPAND_AS_DEFINED); + for (const auto &s : expandAsDefinedList) { - if (Doxygen::expandAsDefinedDict[s]==0) - { - Doxygen::expandAsDefinedDict.insert(s,(void *)666); - } - s=expandAsDefinedList.next(); + Doxygen::expandAsDefinedSet.insert(s.c_str()); } // read aliases and store them in a dictionary readAliases(); // store number of spaces in a tab into Doxygen::spaces - int &tabSize = Config_getInt(TAB_SIZE); + int tabSize = Config_getInt(TAB_SIZE); Doxygen::spaces.resize(tabSize+1); int sp;for (sp=0;sp<tabSize;sp++) Doxygen::spaces.at(sp)=' '; Doxygen::spaces.at(tabSize)='\0'; @@ -10568,7 +10482,7 @@ static void stopDoxygen(int) static void writeTagFile() { - QCString &generateTagFile = Config_getString(GENERATE_TAGFILE); + QCString generateTagFile = Config_getString(GENERATE_TAGFILE); if (generateTagFile.isEmpty()) return; QFile tag(generateTagFile); @@ -10581,16 +10495,17 @@ static void writeTagFile() } FTextStream tagFile(&tag); tagFile << "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>" << endl; - tagFile << "<tagfile>" << endl; + tagFile << "<tagfile doxygen_version=\"" << getDoxygenVersion() << "\""; + if (strlen(getGitVersion())>0) + { + tagFile << " doxygen_gitid=\"" << getGitVersion() << "\""; + } + tagFile << ">" << endl; // for each file - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->isLinkableInProject()) fd->writeTagFile(tagFile); } @@ -10637,6 +10552,7 @@ static void writeTagFile() << "</title>" << endl << " <filename>" << convertToXML(Doxygen::mainPage->getOutputFileBase()) + << Doxygen::htmlFileExtension << "</filename>" << endl; mainPage->writeDocAnchorsToTagFile(); @@ -10669,26 +10585,26 @@ static void exitDoxygen() } static QCString createOutputDirectory(const QCString &baseDirName, - QCString &formatDirName, + const QCString &formatDirName, const char *defaultDirName) { - // Note the & on the next line, we modify the formatDirOption! - if (formatDirName.isEmpty()) + QCString result = formatDirName; + if (result.isEmpty()) { - formatDirName = baseDirName + defaultDirName; + result = baseDirName + defaultDirName; } else if (formatDirName[0]!='/' && (formatDirName.length()==1 || formatDirName[1]!=':')) { - formatDirName.prepend(baseDirName+'/'); + result.prepend(baseDirName+'/'); } - QDir formatDir(formatDirName); - if (!formatDir.exists() && !formatDir.mkdir(formatDirName)) + QDir formatDir(result); + if (!formatDir.exists() && !formatDir.mkdir(result)) { - err("Could not create output directory %s\n", formatDirName.data()); + err("Could not create output directory %s\n", result.data()); cleanUpDoxygen(); exit(1); } - return formatDirName; + return result; } static QCString getQchFileName() @@ -10710,114 +10626,137 @@ static QCString getQchFileName() void searchInputFiles() { - QDict<void> *killDict = new QDict<void>(10007); + StringUnorderedSet killSet; - QStrList &exclPatterns = Config_getList(EXCLUDE_PATTERNS); + const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS); bool alwaysRecursive = Config_getBool(RECURSIVE); - StringDict excludeNameDict(1009); - excludeNameDict.setAutoDelete(TRUE); + StringUnorderedSet excludeNameSet; // gather names of all files in the include path g_s.begin("Searching for include files...\n"); - killDict->clear(); - QStrList &includePathList = Config_getList(INCLUDE_PATH); - char *s=includePathList.first(); - while (s) - { - QStrList &pl = Config_getList(INCLUDE_FILE_PATTERNS); - if (pl.count()==0) - { - pl = Config_getList(FILE_PATTERNS); - } - readFileOrDirectory(s,0,Doxygen::includeNameDict,0,&pl, - &exclPatterns,0,0, - alwaysRecursive, - TRUE,killDict); - s=includePathList.next(); + killSet.clear(); + const StringVector &includePathList = Config_getList(INCLUDE_PATH); + for (const auto &s : includePathList) + { + size_t plSize = Config_getList(INCLUDE_FILE_PATTERNS).size(); + const StringVector &pl = plSize==0 ? Config_getList(FILE_PATTERNS) : + Config_getList(INCLUDE_FILE_PATTERNS); + readFileOrDirectory(s.c_str(), // s + Doxygen::includeNameLinkedMap, // fnDict + 0, // exclSet + &pl, // patList + &exclPatterns, // exclPatList + 0, // resultList + 0, // resultSet + alwaysRecursive, // recursive + TRUE, // errorIfNotExist + &killSet); // killSet } g_s.end(); g_s.begin("Searching for example files...\n"); - killDict->clear(); - QStrList &examplePathList = Config_getList(EXAMPLE_PATH); - s=examplePathList.first(); - while (s) - { - readFileOrDirectory(s,0,Doxygen::exampleNameDict,0, - &Config_getList(EXAMPLE_PATTERNS), - 0,0,0, - (alwaysRecursive || Config_getBool(EXAMPLE_RECURSIVE)), - TRUE,killDict); - s=examplePathList.next(); + killSet.clear(); + const StringVector &examplePathList = Config_getList(EXAMPLE_PATH); + for (const auto &s : examplePathList) + { + readFileOrDirectory(s.c_str(), // s + Doxygen::exampleNameLinkedMap, // fnDict + 0, // exclSet + &Config_getList(EXAMPLE_PATTERNS), // patList + 0, // exclPatList + 0, // resultList + 0, // resultSet + (alwaysRecursive || Config_getBool(EXAMPLE_RECURSIVE)), // recursive + TRUE, // errorIfNotExist + &killSet); // killSet } g_s.end(); g_s.begin("Searching for images...\n"); - killDict->clear(); - QStrList &imagePathList=Config_getList(IMAGE_PATH); - s=imagePathList.first(); - while (s) - { - readFileOrDirectory(s,0,Doxygen::imageNameDict,0,0, - 0,0,0, - alwaysRecursive, - TRUE,killDict); - s=imagePathList.next(); + killSet.clear(); + const StringVector &imagePathList=Config_getList(IMAGE_PATH); + for (const auto &s : imagePathList) + { + readFileOrDirectory(s.c_str(), // s + Doxygen::imageNameLinkedMap, // fnDict + 0, // exclSet + 0, // patList + 0, // exclPatList + 0, // resultList + 0, // resultSet + alwaysRecursive, // recursive + TRUE, // errorIfNotExist + &killSet); // killSet } g_s.end(); g_s.begin("Searching for dot files...\n"); - killDict->clear(); - QStrList &dotFileList=Config_getList(DOTFILE_DIRS); - s=dotFileList.first(); - while (s) - { - readFileOrDirectory(s,0,Doxygen::dotFileNameDict,0,0, - 0,0,0, - alwaysRecursive, - TRUE,killDict); - s=dotFileList.next(); + killSet.clear(); + const StringVector &dotFileList=Config_getList(DOTFILE_DIRS); + for (const auto &s : dotFileList) + { + readFileOrDirectory(s.c_str(), // s + Doxygen::dotFileNameLinkedMap, // fnDict + 0, // exclSet + 0, // patList + 0, // exclPatList + 0, // resultList + 0, // resultSet + alwaysRecursive, // recursive + TRUE, // errorIfNotExist + &killSet); // killSet } g_s.end(); g_s.begin("Searching for msc files...\n"); - killDict->clear(); - QStrList &mscFileList=Config_getList(MSCFILE_DIRS); - s=mscFileList.first(); - while (s) - { - readFileOrDirectory(s,0,Doxygen::mscFileNameDict,0,0, - 0,0,0, - alwaysRecursive, - TRUE,killDict); - s=mscFileList.next(); + killSet.clear(); + const StringVector &mscFileList=Config_getList(MSCFILE_DIRS); + for (const auto &s : mscFileList) + { + readFileOrDirectory(s.c_str(), // s + Doxygen::mscFileNameLinkedMap, // fnDict + 0, // exclSet + 0, // patList + 0, // exclPatList + 0, // resultList + 0, // resultSet + alwaysRecursive, // recursive + TRUE, // errorIfNotExist + &killSet); // killSet } g_s.end(); g_s.begin("Searching for dia files...\n"); - killDict->clear(); - QStrList &diaFileList=Config_getList(DIAFILE_DIRS); - s=diaFileList.first(); - while (s) - { - readFileOrDirectory(s,0,Doxygen::diaFileNameDict,0,0, - 0,0,0, - alwaysRecursive, - TRUE,killDict); - s=diaFileList.next(); + killSet.clear(); + const StringVector &diaFileList=Config_getList(DIAFILE_DIRS); + for (const auto &s : diaFileList) + { + readFileOrDirectory(s.c_str(), // s + Doxygen::diaFileNameLinkedMap, // fnDict + 0, // exclSet + 0, // patList + 0, // exclPatList + 0, // resultList + 0, // resultSet + alwaysRecursive, // recursive + TRUE, // errorIfNotExist + &killSet); // killSet } g_s.end(); g_s.begin("Searching for files to exclude\n"); - QStrList &excludeList = Config_getList(EXCLUDE); - s=excludeList.first(); - while (s) - { - readFileOrDirectory(s,0,0,0,&Config_getList(FILE_PATTERNS), - 0,0,&excludeNameDict, - alwaysRecursive, - FALSE); - s=excludeList.next(); + const StringVector &excludeList = Config_getList(EXCLUDE); + for (const auto &s : excludeList) + { + readFileOrDirectory(s.c_str(), // s + 0, // fnDict + 0, // exclSet + &Config_getList(FILE_PATTERNS), // patList + 0, // exclPatList + 0, // resultList + &excludeNameSet, // resultSet + alwaysRecursive, // recursive + FALSE); // errorIfNotExist } g_s.end(); @@ -10826,13 +10765,12 @@ void searchInputFiles() **************************************************************************/ g_s.begin("Searching INPUT for files to process...\n"); - killDict->clear(); - QStrList &inputList=Config_getList(INPUT); - g_inputFiles.setAutoDelete(TRUE); - s=inputList.first(); - while (s) + killSet.clear(); + Doxygen::inputPaths.clear(); + const StringVector &inputList=Config_getList(INPUT); + for (const auto &s : inputList) { - QCString path=s; + QCString path=s.c_str(); uint l = path.length(); if (l>0) { @@ -10840,24 +10778,28 @@ void searchInputFiles() if (path.at(l-1)=='\\' || path.at(l-1)=='/') path=path.left(l-1); readFileOrDirectory( - path, - Doxygen::inputNameList, - Doxygen::inputNameDict, - &excludeNameDict, - &Config_getList(FILE_PATTERNS), - &exclPatterns, - &g_inputFiles,0, - alwaysRecursive, - TRUE, - killDict, - &Doxygen::inputPaths); - } - s=inputList.next(); - } - Doxygen::inputNameList->sort(); + path, // s + Doxygen::inputNameLinkedMap, // fnDict + &excludeNameSet, // exclSet + &Config_getList(FILE_PATTERNS), // patList + &exclPatterns, // exclPatList + &g_inputFiles, // resultList + 0, // resultSet + alwaysRecursive, // recursive + TRUE, // errorIfNotExist + &killSet, // killSet + &Doxygen::inputPaths); // paths + } + } + std::sort(Doxygen::inputNameLinkedMap->begin(), + Doxygen::inputNameLinkedMap->end(), + [](const auto &f1,const auto &f2) + { + return Config_getBool(FULL_PATH_NAMES) ? + qstricmp(f1->fullName(),f2->fullName())<0 : + qstricmp(f1->fileName(),f2->fileName())<0; + }); g_s.end(); - - delete killDict; } @@ -10865,14 +10807,22 @@ void parseInput() { atexit(exitDoxygen); +#if USE_LIBCLANG + Doxygen::clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); +#endif + + // we would like to show the versionString earlier, but we first have to handle the configuration file + // to know the value of the QUIET setting. + QCString versionString = getFullVersion(); + msg("Doxygen version used: %s\n",versionString.data()); /************************************************************************** * Make sure the output directory exists **************************************************************************/ - QCString &outputDirectory = Config_getString(OUTPUT_DIRECTORY); + QCString outputDirectory = Config_getString(OUTPUT_DIRECTORY); if (outputDirectory.isEmpty()) { - outputDirectory=QDir::currentDirPath().utf8(); + outputDirectory = Config_updateString(OUTPUT_DIRECTORY,QDir::currentDirPath().utf8()); } else { @@ -10894,15 +10844,13 @@ void parseInput() } dir.cd(outputDirectory); } - outputDirectory=dir.absPath().utf8(); + outputDirectory = Config_updateString(OUTPUT_DIRECTORY,dir.absPath().utf8()); } /************************************************************************** * Initialize global lists and dictionaries **************************************************************************/ - //Doxygen::symbolStorage = new Store; - // also scale lookup cache with SYMBOL_CACHE_SIZE int cacheSize = Config_getInt(LOOKUP_CACHE_SIZE); if (cacheSize<0) cacheSize=0; @@ -10923,52 +10871,67 @@ void parseInput() Doxygen::filterDBFileName.sprintf("doxygen_filterdb_%d.tmp",pid); Doxygen::filterDBFileName.prepend(outputDirectory+"/"); -// if (Doxygen::symbolStorage->open(Doxygen::objDBFileName)==-1) -// { -// err("Failed to open temporary file %s\n",Doxygen::objDBFileName.data()); -// exit(1); -// } - - - /************************************************************************** * Check/create output directories * **************************************************************************/ QCString htmlOutput; - bool &generateHtml = Config_getBool(GENERATE_HTML); + bool generateHtml = Config_getBool(GENERATE_HTML); if (generateHtml || g_useOutputTemplate /* TODO: temp hack */) + { htmlOutput = createOutputDirectory(outputDirectory,Config_getString(HTML_OUTPUT),"/html"); + Config_updateString(HTML_OUTPUT,htmlOutput); + } QCString docbookOutput; - bool &generateDocbook = Config_getBool(GENERATE_DOCBOOK); + bool generateDocbook = Config_getBool(GENERATE_DOCBOOK); if (generateDocbook) + { docbookOutput = createOutputDirectory(outputDirectory,Config_getString(DOCBOOK_OUTPUT),"/docbook"); + Config_updateString(DOCBOOK_OUTPUT,docbookOutput); + } QCString xmlOutput; - bool &generateXml = Config_getBool(GENERATE_XML); + bool generateXml = Config_getBool(GENERATE_XML); if (generateXml) + { xmlOutput = createOutputDirectory(outputDirectory,Config_getString(XML_OUTPUT),"/xml"); + Config_updateString(XML_OUTPUT,xmlOutput); + } QCString latexOutput; - bool &generateLatex = Config_getBool(GENERATE_LATEX); + bool generateLatex = Config_getBool(GENERATE_LATEX); if (generateLatex) - latexOutput = createOutputDirectory(outputDirectory,Config_getString(LATEX_OUTPUT),"/latex"); + { + latexOutput = createOutputDirectory(outputDirectory,Config_getString(LATEX_OUTPUT), "/latex"); + Config_updateString(LATEX_OUTPUT,latexOutput); + } QCString rtfOutput; - bool &generateRtf = Config_getBool(GENERATE_RTF); + bool generateRtf = Config_getBool(GENERATE_RTF); if (generateRtf) + { rtfOutput = createOutputDirectory(outputDirectory,Config_getString(RTF_OUTPUT),"/rtf"); + Config_updateString(RTF_OUTPUT,rtfOutput); + } QCString manOutput; - bool &generateMan = Config_getBool(GENERATE_MAN); + bool generateMan = Config_getBool(GENERATE_MAN); if (generateMan) + { manOutput = createOutputDirectory(outputDirectory,Config_getString(MAN_OUTPUT),"/man"); + Config_updateString(MAN_OUTPUT,manOutput); + } - //QCString sqlOutput; - //bool &generateSql = Config_getBool(GENERATE_SQLITE3); - //if (generateSql) - // sqlOutput = createOutputDirectory(outputDirectory,"SQLITE3_OUTPUT","/sqlite3"); +#if USE_SQLITE3 + QCString sqlOutput; + bool generateSql = Config_getBool(GENERATE_SQLITE3); + if (generateSql) + { + sqlOutput = createOutputDirectory(outputDirectory,Config_getString(SQLITE3_OUTPUT),"/sqlite3"); + Config_updateString(SQLITE3_OUTPUT,sqlOutput); + } +#endif if (Config_getBool(HAVE_DOT)) { @@ -10997,11 +10960,11 @@ void parseInput() **************************************************************************/ LayoutDocManager::instance().init(); - QCString &layoutFileName = Config_getString(LAYOUT_FILE); + QCString layoutFileName = Config_getString(LAYOUT_FILE); bool defaultLayoutUsed = FALSE; if (layoutFileName.isEmpty()) { - layoutFileName = "DoxygenLayout.xml"; + layoutFileName = Config_updateString(LAYOUT_FILE,"DoxygenLayout.xml"); defaultLayoutUsed = TRUE; } @@ -11021,13 +10984,14 @@ void parseInput() **************************************************************************/ // prevent search in the output directories - QStrList &exclPatterns = Config_getList(EXCLUDE_PATTERNS); - if (generateHtml) exclPatterns.append(htmlOutput); - if (generateDocbook) exclPatterns.append(docbookOutput); - if (generateXml) exclPatterns.append(xmlOutput); - if (generateLatex) exclPatterns.append(latexOutput); - if (generateRtf) exclPatterns.append(rtfOutput); - if (generateMan) exclPatterns.append(manOutput); + StringVector exclPatterns = Config_getList(EXCLUDE_PATTERNS); + if (generateHtml) exclPatterns.push_back(htmlOutput.data()); + if (generateDocbook) exclPatterns.push_back(docbookOutput.data()); + if (generateXml) exclPatterns.push_back(xmlOutput.data()); + if (generateLatex) exclPatterns.push_back(latexOutput.data()); + if (generateRtf) exclPatterns.push_back(rtfOutput.data()); + if (generateMan) exclPatterns.push_back(manOutput.data()); + Config_updateList(EXCLUDE_PATTERNS,exclPatterns); searchInputFiles(); @@ -11035,18 +10999,22 @@ void parseInput() if (Config_getBool(GENERATE_HTML) && !Config_getBool(USE_MATHJAX)) { - readFormulaRepository(Config_getString(HTML_OUTPUT)); + FormulaManager::instance().readFormulas(Config_getString(HTML_OUTPUT)); } if (Config_getBool(GENERATE_RTF)) { // in case GENERRATE_HTML is set we just have to compare, both repositories should be identical - readFormulaRepository(Config_getString(RTF_OUTPUT),Config_getBool(GENERATE_HTML) && !Config_getBool(USE_MATHJAX)); + FormulaManager::instance().readFormulas(Config_getString(RTF_OUTPUT), + Config_getBool(GENERATE_HTML) && + !Config_getBool(USE_MATHJAX)); } if (Config_getBool(GENERATE_DOCBOOK)) { // in case GENERRATE_HTML is set we just have to compare, both repositories should be identical - readFormulaRepository(Config_getString(DOCBOOK_OUTPUT), - (Config_getBool(GENERATE_HTML) && !Config_getBool(USE_MATHJAX)) || Config_getBool(GENERATE_RTF)); + FormulaManager::instance().readFormulas(Config_getString(DOCBOOK_OUTPUT), + (Config_getBool(GENERATE_HTML) && + !Config_getBool(USE_MATHJAX)) || + Config_getBool(GENERATE_RTF)); } /************************************************************************** @@ -11056,12 +11024,10 @@ void parseInput() std::shared_ptr<Entry> root = std::make_shared<Entry>(); msg("Reading and parsing tag files\n"); - QStrList &tagFileList = Config_getList(TAGFILES); - char *s=tagFileList.first(); - while (s) + const StringVector &tagFileList = Config_getList(TAGFILES); + for (const auto &s : tagFileList) { - readTagFile(root,s); - s=tagFileList.next(); + readTagFile(root,s.c_str()); } /************************************************************************** @@ -11071,17 +11037,24 @@ void parseInput() addSTLSupport(root); g_s.begin("Parsing files\n"); - parseFiles(root); + if (Config_getInt(NUM_PROC_THREADS)==1) + { + parseFilesSingleThreading(root); + } + else + { + parseFilesMultiThreading(root); + } g_s.end(); - // we are done with input scanning now, so free up the buffers used by flex - // (can be around 4MB) - pyscanFreeScanner(); - /************************************************************************** * Gather information * **************************************************************************/ + g_s.begin("Building macro definition list...\n"); + buildDefineList(); + g_s.end(); + g_s.begin("Building group list...\n"); buildGroupList(root.get()); organizeSubGroups(root.get()); @@ -11251,9 +11224,20 @@ void parseInput() findGroupScope(root.get()); g_s.end(); + auto memberNameComp = [](const MemberNameLinkedMap::Ptr &n1,const MemberNameLinkedMap::Ptr &n2) + { + return qstricmp(n1->memberName()+getPrefixIndex(n1->memberName()), + n2->memberName()+getPrefixIndex(n2->memberName()) + )<0; + }; + g_s.begin("Sorting lists...\n"); - Doxygen::memberNameSDict->sort(); - Doxygen::functionNameSDict->sort(); + std::sort(Doxygen::memberNameLinkedMap->begin(), + Doxygen::memberNameLinkedMap->end(), + memberNameComp); + std::sort(Doxygen::functionNameLinkedMap->begin(), + Doxygen::functionNameLinkedMap->end(), + memberNameComp); Doxygen::hiddenClasses->sort(); Doxygen::classSDict->sort(); g_s.end(); @@ -11299,7 +11283,7 @@ void parseInput() // compute the shortest possible names of all files // without losing the uniqueness of the file names. g_s.begin("Generating disk names...\n"); - Doxygen::inputNameList->generateDiskNames(); + generateDiskNames(); g_s.end(); g_s.begin("Adding source references...\n"); @@ -11326,11 +11310,8 @@ void parseInput() g_s.end(); } - //g_s.begin("Resolving citations...\n"); - //Doxygen::citeDict->resolve(); - g_s.begin("Generating citations page...\n"); - Doxygen::citeDict->generatePage(); + CitationManager::instance().generatePage(); g_s.end(); g_s.begin("Counting members...\n"); @@ -11365,6 +11346,17 @@ void parseInput() vhdlCorrectMemberProperties(); g_s.end(); + if (Config_getBool(SORT_GROUP_NAMES)) + { + Doxygen::groupSDict->sort(); + GroupSDict::Iterator gli(*Doxygen::groupSDict); + GroupDef *gd; + for (gli.toFirst();(gd=gli.current());++gli) + { + gd->sortSubGroups(); + } + } + } void generateOutput() @@ -11480,6 +11472,29 @@ void generateOutput() } g_s.end(); + const FormulaManager &fm = FormulaManager::instance(); + if (fm.hasFormulas() && generateHtml + && !Config_getBool(USE_MATHJAX)) + { + g_s.begin("Generating images for formulas in HTML...\n"); + fm.generateImages(Config_getString(HTML_OUTPUT), Config_getEnum(HTML_FORMULA_FORMAT)=="svg" ? + FormulaManager::Format::Vector : FormulaManager::Format::Bitmap, FormulaManager::HighDPI::On); + g_s.end(); + } + if (fm.hasFormulas() && generateRtf) + { + g_s.begin("Generating images for formulas in RTF...\n"); + fm.generateImages(Config_getString(RTF_OUTPUT),FormulaManager::Format::Bitmap); + g_s.end(); + } + + if (fm.hasFormulas() && generateDocbook) + { + g_s.begin("Generating images for formulas in Docbook...\n"); + fm.generateImages(Config_getString(DOCBOOK_OUTPUT),FormulaManager::Format::Bitmap); + g_s.end(); + } + g_s.begin("Generating example documentation...\n"); generateExampleDocs(); g_s.end(); @@ -11519,38 +11534,6 @@ void generateOutput() generateDirDocs(*g_outputList); g_s.end(); - if (Doxygen::formulaList->count()>0 && generateHtml - && !Config_getBool(USE_MATHJAX)) - { - g_s.begin("Generating bitmaps for formulas in HTML...\n"); - Doxygen::formulaList->generateBitmaps(Config_getString(HTML_OUTPUT)); - g_s.end(); - } - if (Doxygen::formulaList->count()>0 && generateRtf) - { - g_s.begin("Generating bitmaps for formulas in RTF...\n"); - Doxygen::formulaList->generateBitmaps(Config_getString(RTF_OUTPUT)); - g_s.end(); - } - - if (Doxygen::formulaList->count()>0 && generateDocbook) - { - g_s.begin("Generating bitmaps for formulas in Docbook...\n"); - Doxygen::formulaList->generateBitmaps(Config_getString(DOCBOOK_OUTPUT)); - g_s.end(); - } - - if (Config_getBool(SORT_GROUP_NAMES)) - { - Doxygen::groupSDict->sort(); - GroupSDict::Iterator gli(*Doxygen::groupSDict); - GroupDef *gd; - for (gli.toFirst();(gd=gli.current());++gli) - { - gd->sortSubGroups(); - } - } - if (g_outputList->count()>0) { writeIndexHierarchy(*g_outputList); @@ -11572,12 +11555,14 @@ void generateOutput() Doxygen::generatingXmlOutput=FALSE; g_s.end(); } - if (USE_SQLITE3) +#if USE_SQLITE3 + if (Config_getBool(GENERATE_SQLITE3)) { g_s.begin("Generating SQLITE3 output...\n"); generateSqlite3(); g_s.end(); } +#endif if (Config_getBool(GENERATE_AUTOGEN_DEF)) { @@ -11715,7 +11700,7 @@ void generateOutput() if (Debug::isFlagSet(Debug::Time)) { msg("Total elapsed time: %.3f seconds\n(of which %.3f seconds waiting for external tools to finish)\n", - ((double)Doxygen::runningTime.elapsed())/1000.0, + ((double)Debug::elapsedTime()), Portable::getSysElapsedTime() ); g_s.print(); @@ -11733,7 +11718,6 @@ void generateOutput() cleanUpDoxygen(); finalizeSearchIndexer(); -// Doxygen::symbolStorage->close(); QDir thisDir; thisDir.remove(Doxygen::objDBFileName); thisDir.remove(Doxygen::filterDBFileName); @@ -11741,7 +11725,5 @@ void generateOutput() QTextCodec::deleteAllCodecs(); delete Doxygen::symbolMap; delete Doxygen::clangUsrMap; -// delete Doxygen::symbolStorage; g_successfulRun=TRUE; } - diff --git a/src/doxygen.h b/src/doxygen.h index a23a678..dc05750 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -22,12 +22,17 @@ #include <qdict.h> #include <qintdict.h> +#include "containers.h" #include "ftextstream.h" #include "sortdict.h" #include "membergroup.h" #include "dirdef.h" #include "memberlist.h" -#include "docgroup.h" +#include "define.h" + +#define THREAD_LOCAL thread_local +#define AtomicInt std::atomic_int +#define AtomicBool std::atomic_bool class RefList; class PageSList; @@ -35,8 +40,6 @@ class PageSDict; class PageDef; class SearchIndexIntf; class ParserManager; -class ObjCache; -class Store; class QFileInfo; class BufStr; class CiteDict; @@ -47,9 +50,8 @@ class FileDef; class ClassDef; class ClassSDict; class GenericsSDict; -class MemberNameSDict; -class FileNameDict; -class FileNameList; +class MemberNameLinkedMap; +class FileNameLinkedMap; class NamespaceSDict; class NamespaceDef; class DefinitionIntf; @@ -59,7 +61,6 @@ class IndexList; class FormulaList; class FormulaDict; class FormulaNameDict; -class SectionDict; class Preprocessor; struct MemberGroupInfo; @@ -101,34 +102,26 @@ class Doxygen static PageSDict *pageSDict; static PageDef *mainPage; static bool insideMainPage; - static FileNameDict *includeNameDict; - static FileNameDict *exampleNameDict; - static QDict<void> inputPaths; - static FileNameDict *inputNameDict; - static FileNameList *inputNameList; - static FileNameDict *imageNameDict; - static FileNameDict *dotFileNameDict; - static FileNameDict *mscFileNameDict; - static FileNameDict *diaFileNameDict; - static QStrList tagfileList; - static MemberNameSDict *memberNameSDict; - static MemberNameSDict *functionNameSDict; - static SectionDict *sectionDict; - static StringDict namespaceAliasDict; + static FileNameLinkedMap *includeNameLinkedMap; + static FileNameLinkedMap *exampleNameLinkedMap; + static StringSet inputPaths; + static FileNameLinkedMap *inputNameLinkedMap; + static FileNameLinkedMap *imageNameLinkedMap; + static FileNameLinkedMap *dotFileNameLinkedMap; + static FileNameLinkedMap *mscFileNameLinkedMap; + static FileNameLinkedMap *diaFileNameLinkedMap; + static MemberNameLinkedMap *memberNameLinkedMap; + static MemberNameLinkedMap *functionNameLinkedMap; + static StringUnorderedMap namespaceAliasMap; static GroupSDict *groupSDict; static NamespaceSDict *namespaceSDict; - static FormulaList *formulaList; - static FormulaDict *formulaDict; - static FormulaDict *formulaNameDict; static StringDict tagDestinationDict; static StringDict aliasDict; static QIntDict<MemberGroupInfo> memGrpInfoDict; - static QDict<void> expandAsDefinedDict; + static StringUnorderedSet expandAsDefinedSet; static NamespaceDef *globalScope; - static QDict<RefList> *xrefLists; // array of xref lists: todo, test, bug, deprecated ... static QCString htmlFileExtension; static bool parseSourcesNeeded; - static QTime runningTime; static SearchIndexIntf *searchIndex; static QDict<DefinitionIntf> *symbolMap; static QDict<Definition> *clangUsrMap; @@ -139,58 +132,40 @@ class Doxygen static SDict<DirRelation> dirRelations; static ParserManager *parserManager; static bool suppressDocWarnings; - static Store *symbolStorage; static QCString objDBFileName; static QCString entryDBFileName; static QCString filterDBFileName; - static CiteDict *citeDict; - static bool gatherDefines; static bool userComments; static IndexList *indexList; static int subpageNestingLevel; static QCString spaces; static bool generatingXmlOutput; - static bool markdownSupport; static GenericsSDict *genericsDict; - static DocGroup docGroup; - static Preprocessor *preprocessor; + static DefinesPerFileList macroDefinitions; + static bool clangAssistedParsing; }; void initDoxygen(); void readConfiguration(int argc, char **argv); void checkConfiguration(); void adjustConfiguration(); -void searchInputFiles(StringList &inputFiles); void parseInput(); void generateOutput(); void readAliases(); void readFormulaRepository(QCString dir, bool cmp = FALSE); void cleanUpDoxygen(); int readFileOrDirectory(const char *s, - FileNameList *fnList, - FileNameDict *fnDict, - StringDict *exclDict, - QStrList *patList, - QStrList *exclPatList, - StringList *resultList, - StringDict *resultDict, + FileNameLinkedMap *fnDict, + StringUnorderedSet *exclSet, + const StringVector *patList, + const StringVector *exclPatList, + StringVector *resultList, + StringUnorderedSet *resultSet, bool recursive, bool errorIfNotExist=TRUE, - QDict<void> *killDict = 0, - QDict<void> *paths = 0 + StringUnorderedSet *killSet = 0, + StringSet *paths = 0 ); -int readDir(QFileInfo *fi, - FileNameList *fnList, - FileNameDict *fnDict, - StringDict *exclDict, - QStrList *patList, - QStrList *exclPatList, - StringList *resultList, - StringDict *resultDict, - bool errorIfNotExist, - bool recursive, - QDict<void> *killDict - ); void copyAndFilterFile(const char *fileName,BufStr &dest); #endif diff --git a/src/doxygen.md b/src/doxygen.md index c124e09..d8db231 100644 --- a/src/doxygen.md +++ b/src/doxygen.md @@ -223,7 +223,6 @@ Topics TODO - Python - Fortran - VHDL - - TCL - Tag files - Marshaling to/from disk - Portability functions diff --git a/src/entry.cpp b/src/entry.cpp index cc8cd1f..6e343b0 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -24,18 +24,15 @@ #include "doxygen.h" #include "arguments.h" #include "config.h" -//------------------------------------------------------------------ - -#define HEADER ('D'<<24)+('O'<<16)+('X'<<8)+'!' //------------------------------------------------------------------ -int Entry::num=0; +static AtomicInt g_num; Entry::Entry() { //printf("Entry::Entry(%p)\n",this); - num++; + g_num++; m_parent=0; section = EMPTY_SEC; //printf("Entry::Entry() tArgList=0\n"); @@ -50,7 +47,7 @@ Entry::Entry() Entry::Entry(const Entry &e) { //printf("Entry::Entry(%p):copy\n",this); - num++; + g_num++; section = e.section; type = e.type; name = e.name; @@ -95,6 +92,7 @@ Entry::Entry(const Entry &e) exception = e.exception; typeConstr = e.typeConstr; bodyLine = e.bodyLine; + bodyColumn = e.bodyColumn; endBodyLine = e.endBodyLine; mGrpId = e.mGrpId; anchors = e.anchors; @@ -122,11 +120,11 @@ Entry::Entry(const Entry &e) Entry::~Entry() { - //printf("Entry::~Entry(%p) num=%d\n",this,num); + //printf("Entry::~Entry(%p) num=%d\n",this,g_num); //printf("Deleting entry %d name %s type %x children %d\n", // num,name.data(),section,sublist->count()); - num--; + g_num--; } void Entry::moveToSubEntryAndRefresh(Entry *¤t) @@ -149,7 +147,7 @@ void Entry::moveToSubEntryAndKeep(Entry *current) m_sublist.emplace_back(current); } -void Entry::moveToSubEntryAndKeep(std::shared_ptr<Entry> ¤t) +void Entry::moveToSubEntryAndKeep(std::shared_ptr<Entry> current) { current->m_parent=this; m_sublist.push_back(current); @@ -169,21 +167,6 @@ void Entry::copyToSubEntry(const std::shared_ptr<Entry> ¤t) m_sublist.push_back(copy); } -void Entry::moveFromSubEntry(const Entry *child,std::shared_ptr<Entry> &moveTo) -{ - auto it = std::find_if(m_sublist.begin(),m_sublist.end(), - [child](const std::shared_ptr<Entry>&elem) { return elem.get()==child; }); - if (it!=m_sublist.end()) - { - moveTo = *it; - m_sublist.erase(it); - } - else - { - moveTo.reset(); - } -} - void Entry::removeSubEntry(const Entry *e) { auto it = std::find_if(m_sublist.begin(),m_sublist.end(), @@ -197,10 +180,10 @@ void Entry::removeSubEntry(const Entry *e) void Entry::reset() { - static bool entryCallGraph = Config_getBool(CALL_GRAPH); - static bool entryCallerGraph = Config_getBool(CALLER_GRAPH); - static bool entryReferencedByRelation = Config_getBool(REFERENCED_BY_RELATION); - static bool entryReferencesRelation = Config_getBool(REFERENCES_RELATION); + bool entryCallGraph = Config_getBool(CALL_GRAPH); + bool entryCallerGraph = Config_getBool(CALLER_GRAPH); + bool entryReferencedByRelation = Config_getBool(REFERENCED_BY_RELATION); + bool entryReferencesRelation = Config_getBool(REFERENCES_RELATION); //printf("Entry::reset()\n"); name.resize(0); type.resize(0); @@ -228,6 +211,7 @@ void Entry::reset() startLine = 1; startColumn = 1; bodyLine = -1; + bodyColumn = 1; endBodyLine = -1; mGrpId = -1; callGraph = entryCallGraph; @@ -253,9 +237,8 @@ void Entry::reset() extends.clear(); groups.clear(); anchors.clear(); - argList.clear(); - tArgLists.clear(); argList.reset(); + tArgLists.clear(); typeConstr.reset(); sli.clear(); m_fileDef = 0; @@ -270,13 +253,4 @@ void Entry::setFileDef(FileDef *fd) } } -void Entry::addSpecialListItem(const char *listName,int itemId) -{ - ListItemInfo ili; - ili.type = listName; - ili.itemId = itemId; - sli.push_back(ili); -} - - //------------------------------------------------------------------ diff --git a/src/entry.h b/src/entry.h index 0391075..d6c0936 100644 --- a/src/entry.h +++ b/src/entry.h @@ -25,11 +25,11 @@ #include "types.h" #include "arguments.h" +#include "reflist.h" -struct SectionInfo; +class SectionInfo; class QFile; class FileDef; -struct ListItemInfo; /** This class stores information about an inheritance relation */ @@ -194,8 +194,6 @@ class Entry Entry(const Entry &); ~Entry(); - void addSpecialListItem(const char *listName,int index); - /*! Returns the parent for this Entry or 0 if this entry has no parent. */ Entry *parent() const { return m_parent; } @@ -205,20 +203,17 @@ class Entry const std::vector< std::shared_ptr<Entry> > &children() const { return m_sublist; } /*! @name add entry as a child and pass ownership. - * @note This makes the entry passed invalid! (TODO: tclscanner.l still has use after move!) + * @note This makes the entry passed invalid! * @{ */ void moveToSubEntryAndKeep(Entry* e); - void moveToSubEntryAndKeep(std::shared_ptr<Entry> &e); + void moveToSubEntryAndKeep(std::shared_ptr<Entry> e); /*! @} */ /*! @name add entry as a child, pass ownership and reinitialize entry */ void moveToSubEntryAndRefresh(Entry* &e); void moveToSubEntryAndRefresh(std::shared_ptr<Entry> &e); - /*! take \a child of of to list of children and move it into \a moveTo */ - void moveFromSubEntry(const Entry *child,std::shared_ptr<Entry> &moveTo); - /*! make a copy of \a e and add it as a child to this entry */ void copyToSubEntry (Entry* e); void copyToSubEntry (const std::shared_ptr<Entry> &e); @@ -262,7 +257,7 @@ class Entry QCString args; //!< member argument string QCString bitfields; //!< member's bit fields ArgumentList argList; //!< member arguments as a list - std::vector<ArgumentList> tArgLists; //!< template argument declarations + ArgumentLists tArgLists; //!< template argument declarations QGString program; //!< the program text QGString initializer; //!< initial value (for variables) QCString includeFile; //!< include file (2 arg of \\class, must be unique) @@ -283,7 +278,8 @@ class Entry QCString inside; //!< name of the class in which documents are found QCString exception; //!< throw specification ArgumentList typeConstr; //!< where clause (C#) for type constraints - int bodyLine; //!< line number of the definition in the source + int bodyLine; //!< line number of the body in the source + int bodyColumn; //!< column of the body in the source int endBodyLine; //!< line number where the definition ends int mGrpId; //!< member group id std::vector<BaseInfo> extends; //!< list of base classes @@ -292,7 +288,7 @@ class Entry QCString fileName; //!< file this entry was extracted from int startLine; //!< start line of entry in the source int startColumn; //!< start column of entry in the source - std::vector<ListItemInfo> sli; //!< special lists (test/todo/bug/deprecated/..) this entry is in + RefItemVector sli; //!< special lists (test/todo/bug/deprecated/..) this entry is in SrcLangExt lang; //!< programming language in which this entry was found bool hidden; //!< does this represent an entity that is hidden from the output bool artificial; //!< Artificially introduced item @@ -301,9 +297,6 @@ class Entry LocalToc localToc; QCString metaData; //!< Slice metadata - - static int num; //!< counts the total number of entries - /// return the command name used to define GROUPDOC_SEC const char *groupDocCmd() const { @@ -337,4 +330,6 @@ class Entry FileDef *m_fileDef; }; +typedef std::vector< std::shared_ptr<Entry> > EntryList; + #endif diff --git a/src/example.h b/src/example.h index 321982b..2af06ba 100644 --- a/src/example.h +++ b/src/example.h @@ -36,7 +36,7 @@ struct Example class ExampleSDict : public SDict<Example> { public: - ExampleSDict(int size=17) : SDict<Example>(size) { setAutoDelete(TRUE); } + ExampleSDict(uint size=17) : SDict<Example>(size) { setAutoDelete(TRUE); } ~ExampleSDict() {} private: int compareValues(const Example *item1,const Example *item2) const diff --git a/src/filedef.cpp b/src/filedef.cpp index fb0e290..15fd1e5 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -55,7 +55,8 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual ~FileDefImpl(); virtual DefType definitionType() const { return TypeFile; } - virtual QCString name() const; + virtual const QCString &name() const; + virtual QCString displayName(bool=TRUE) const { return name(); } virtual QCString fileName() const { return m_fileName; } virtual QCString getOutputFileBase() const; @@ -81,7 +82,7 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual SDict<Definition> *getUsedClasses() const { return m_usingDeclList; } virtual QList<IncludeInfo> *includeFileList() const { return m_includeList; } virtual QList<IncludeInfo> *includedByFileList() const { return m_includedByList; } - virtual void getAllIncludeFilesRecursively(QStrList &incFiles) const; + virtual void getAllIncludeFilesRecursively(StringVector &incFiles) const; virtual MemberList *getMemberList(MemberListType lt) const; virtual const QList<MemberList> &getMemberLists() const { return m_memberLists; } virtual MemberGroupSDict *getMemberGroupSDict() const { return m_memberGroupSDict; } @@ -100,10 +101,8 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const; virtual void writeSummaryLinks(OutputList &ol) const; virtual void writeTagFile(FTextStream &t); - virtual void startParsing(); - virtual void writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu); - virtual void parseSource(bool sameTu,QStrList &filesInSameTu); - virtual void finishParsing(); + virtual void writeSource(OutputList &ol,ClangTUParser *clangParser); + virtual void parseSource(ClangTUParser *clangParser); virtual void setDiskName(const QCString &name); virtual void insertMember(MemberDef *md); virtual void insertClass(ClassDef *cd); @@ -116,7 +115,7 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void combineUsingRelations(); virtual bool generateSourceFile() const; virtual void sortMemberLists(); - virtual void addIncludeDependency(FileDef *fd,const char *incName,bool local,bool imported,bool indirect); + virtual void addIncludeDependency(FileDef *fd,const char *incName,bool local,bool imported); virtual void addIncludedByDependency(FileDef *fd,const char *incName,bool local,bool imported); virtual void addMembersToMemberGroup(); virtual void distributeMemberGroupDocumentation(); @@ -213,7 +212,7 @@ class DevNullCodeDocInterface : public CodeOutputInterface //--------------------------------------------------------------------------- -/*! create a new file definition, where \a p is the file path, +/*! create a new file definition, where \a p is the file path, \a nm the file name, and \a lref is an HTML anchor name if the file was read from a tag file or 0 otherwise */ @@ -231,16 +230,16 @@ FileDefImpl::FileDefImpl(const char *p,const char *nm, m_structSDict = 0; m_exceptionSDict = 0; m_includeList = 0; - m_includeDict = 0; + m_includeDict = 0; m_includedByList = 0; - m_includedByDict = 0; - m_namespaceSDict = 0; + m_includedByDict = 0; + m_namespaceSDict = 0; m_srcDefDict = 0; m_srcMemberDict = 0; m_usingDirList = 0; m_usingDeclList = 0; m_package = 0; - m_isSource = guessSection(nm)==Entry::SOURCE_SEC; + m_isSource = guessSection(nm)==Entry::SOURCE_SEC; m_docname = nm; m_dir = 0; m_visited = FALSE; @@ -289,7 +288,7 @@ void FileDefImpl::setDiskName(const QCString &name) } } -/*! Compute the HTML anchor names for all members in the class */ +/*! Compute the HTML anchor names for all members in the class */ void FileDefImpl::computeAnchors() { MemberList *ml = getMemberList(MemberListType_allMembersList); @@ -338,7 +337,7 @@ bool FileDefImpl::hasDetailedDescription() const { static bool repeatBrief = Config_getBool(REPEAT_BRIEF); static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); - return ((!briefDescription().isEmpty() && repeatBrief) || + return ((!briefDescription().isEmpty() && repeatBrief) || !documentation().stripWhiteSpace().isEmpty() || // avail empty section (sourceBrowser && getStartBodyLine()!=-1 && getBodyDef()) ); @@ -349,32 +348,29 @@ void FileDefImpl::writeTagFile(FTextStream &tagFile) tagFile << " <compound kind=\"file\">" << endl; tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; tagFile << " <path>" << convertToXML(getPath()) << "</path>" << endl; - tagFile << " <filename>" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase())) << "</filename>" << endl; + tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl; if (m_includeList && m_includeList->count()>0) { QListIterator<IncludeInfo> ili(*m_includeList); IncludeInfo *ii; for (;(ii=ili.current());++ili) { - if (!ii->indirect) + FileDef *fd=ii->fileDef; + if (fd && fd->isLinkable() && !fd->isReference()) { - FileDef *fd=ii->fileDef; - if (fd && fd->isLinkable() && !fd->isReference()) - { - bool isIDLorJava = FALSE; - SrcLangExt lang = fd->getLanguage(); - isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; - const char *locStr = (ii->local || isIDLorJava) ? "yes" : "no"; - const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no"; - tagFile << " <includes id=\"" - << convertToXML(fd->getOutputFileBase()) << "\" " - << "name=\"" << convertToXML(fd->name()) << "\" " - << "local=\"" << locStr << "\" " - << "imported=\"" << impStr << "\">" - << convertToXML(ii->includeName) - << "</includes>" - << endl; - } + bool isIDLorJava = FALSE; + SrcLangExt lang = fd->getLanguage(); + isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; + const char *locStr = (ii->local || isIDLorJava) ? "yes" : "no"; + const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no"; + tagFile << " <includes id=\"" + << convertToXML(fd->getOutputFileBase()) << "\" " + << "name=\"" << convertToXML(fd->name()) << "\" " + << "local=\"" << locStr << "\" " + << "imported=\"" << impStr << "\">" + << convertToXML(ii->includeName) + << "</includes>" + << endl; } } } @@ -467,7 +463,7 @@ void FileDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) ol.popGeneratorState(); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - ol.writeAnchor(0,"details"); + ol.writeAnchor(0,"details"); ol.popGeneratorState(); ol.startGroupHeader(); ol.parseText(title); @@ -476,9 +472,10 @@ void FileDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) ol.startTextBlock(); if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } - if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && + if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && !documentation().isEmpty()) { ol.pushGeneratorState(); @@ -493,23 +490,24 @@ void FileDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) } if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } //printf("Writing source ref for file %s\n",name().data()); - if (Config_getBool(SOURCE_BROWSER)) + if (Config_getBool(SOURCE_BROWSER)) { //if Latex enabled and LATEX_SOURCE_CODE isn't -> skip, bug_738548 ol.pushGeneratorState(); if (ol.isEnabled(OutputGenerator::Latex) && !Config_getBool(LATEX_SOURCE_CODE)) - { + { ol.disable(OutputGenerator::Latex); } if (ol.isEnabled(OutputGenerator::Docbook) && !Config_getBool(DOCBOOK_PROGRAMLISTING)) - { + { ol.disable(OutputGenerator::Docbook); } if (ol.isEnabled(OutputGenerator::RTF) && !Config_getBool(RTF_SOURCE_CODE)) - { + { ol.disable(OutputGenerator::RTF); } @@ -541,7 +539,8 @@ void FileDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { @@ -596,61 +595,58 @@ void FileDefImpl::writeIncludeFiles(OutputList &ol) IncludeInfo *ii; for (;(ii=ili.current());++ili) { - if (!ii->indirect) + FileDef *fd=ii->fileDef; + bool isIDLorJava = FALSE; + if (fd) + { + SrcLangExt lang = fd->getLanguage(); + isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; + } + ol.startTypewriter(); + if (isIDLorJava) // IDL/Java include + { + ol.docify("import "); + } + else if (ii->imported) // Objective-C include + { + ol.docify("#import "); + } + else // C/C++ include + { + ol.docify("#include "); + } + if (ii->local || isIDLorJava) + ol.docify("\""); + else + ol.docify("<"); + ol.disable(OutputGenerator::Html); + ol.docify(ii->includeName); + ol.enableAll(); + ol.disableAllBut(OutputGenerator::Html); + + // Here we use the include file name as it appears in the file. + // we could also we the name as it is used within doxygen, + // then we should have used fd->docName() instead of ii->includeName + if (fd && fd->isLinkable()) + { + ol.writeObjectLink(fd->getReference(), + fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(), + 0,ii->includeName); + } + else { - FileDef *fd=ii->fileDef; - bool isIDLorJava = FALSE; - if (fd) - { - SrcLangExt lang = fd->getLanguage(); - isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; - } - ol.startTypewriter(); - if (isIDLorJava) // IDL/Java include - { - ol.docify("import "); - } - else if (ii->imported) // Objective-C include - { - ol.docify("#import "); - } - else // C/C++ include - { - ol.docify("#include "); - } - if (ii->local || isIDLorJava) - ol.docify("\""); - else - ol.docify("<"); - ol.disable(OutputGenerator::Html); ol.docify(ii->includeName); - ol.enableAll(); - ol.disableAllBut(OutputGenerator::Html); - - // Here we use the include file name as it appears in the file. - // we could also we the name as it is used within doxygen, - // then we should have used fd->docName() instead of ii->includeName - if (fd && fd->isLinkable()) - { - ol.writeObjectLink(fd->getReference(), - fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(), - 0,ii->includeName); - } - else - { - ol.docify(ii->includeName); - } - - ol.enableAll(); - if (ii->local || isIDLorJava) - ol.docify("\""); - else - ol.docify(">"); - if (isIDLorJava) - ol.docify(";"); - ol.endTypewriter(); - ol.lineBreak(); } + + ol.enableAll(); + if (ii->local || isIDLorJava) + ol.docify("\""); + else + ol.docify(">"); + if (isIDLorJava) + ol.docify(";"); + ol.endTypewriter(); + ol.lineBreak(); } ol.endTextBlock(); } @@ -669,7 +665,7 @@ void FileDefImpl::writeIncludeGraph(OutputList &ol) } else if (!incDepGraph.isTrivial()) { - ol.startTextBlock(); + ol.startTextBlock(); ol.disable(OutputGenerator::Man); ol.startInclDepGraph(); ol.parseText(theTranslator->trInclDepGraph(name())); @@ -694,7 +690,7 @@ void FileDefImpl::writeIncludedByGraph(OutputList &ol) } else if (!incDepGraph.isTrivial()) { - ol.startTextBlock(); + ol.startTextBlock(); ol.disable(OutputGenerator::Man); ol.startInclDepGraph(); ol.parseText(theTranslator->trInclByDepGraph()); @@ -786,7 +782,7 @@ void FileDefImpl::writeMemberGroups(OutputList &ol) MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - if ((!mg->allMembersInSameSection() || !m_subGrouping) + if ((!mg->allMembersInSameSection() || !m_subGrouping) && mg->header()!="[NOHEADER]") { mg->writeDeclarations(ol,0,0,this,0); @@ -872,13 +868,13 @@ void FileDefImpl::writeSummaryLinks(OutputList &ol) const } /*! Write the documentation page for this file to the file of output - generators \a ol. + generators \a ol. */ void FileDefImpl::writeDocumentation(OutputList &ol) { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); //funcList->countDecMembers(); - + //QCString fn = name(); //if (Config_getBool(FULL_PATH_NAMES)) //{ @@ -886,7 +882,7 @@ void FileDefImpl::writeDocumentation(OutputList &ol) //} //printf("WriteDocumentation diskname=%s\n",diskname.data()); - + QCString versionTitle; if (!m_fileVersion.isEmpty()) { @@ -938,16 +934,16 @@ void FileDefImpl::writeDocumentation(OutputList &ol) ol.endProjectNumber(); ol.enableAll(); } - + if (Doxygen::searchIndex) { Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); Doxygen::searchIndex->addWord(localName(),TRUE); } - + //---------------------------------------- start flexible part ------------------------------- - + SrcLangExt lang = getLanguage(); QListIterator<LayoutDocEntry> eli( LayoutDocManager::instance().docEntries(LayoutDocManager::File)); @@ -956,12 +952,12 @@ void FileDefImpl::writeDocumentation(OutputList &ol) { switch (lde->kind()) { - case LayoutDocEntry::BriefDesc: + case LayoutDocEntry::BriefDesc: writeBriefDescription(ol); - break; - case LayoutDocEntry::MemberDeclStart: + break; + case LayoutDocEntry::MemberDeclStart: startMemberDeclarations(ol); - break; + break; case LayoutDocEntry::FileIncludes: writeIncludeFiles(ol); break; @@ -974,76 +970,76 @@ void FileDefImpl::writeDocumentation(OutputList &ol) case LayoutDocEntry::FileSourceLink: writeSourceLink(ol); break; - case LayoutDocEntry::FileClasses: + case LayoutDocEntry::FileClasses: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),m_classSDict); } break; - case LayoutDocEntry::FileInterfaces: + case LayoutDocEntry::FileInterfaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),m_interfaceSDict); } break; - case LayoutDocEntry::FileStructs: + case LayoutDocEntry::FileStructs: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),m_structSDict); } break; - case LayoutDocEntry::FileExceptions: + case LayoutDocEntry::FileExceptions: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),m_exceptionSDict); } break; - case LayoutDocEntry::FileNamespaces: + case LayoutDocEntry::FileNamespaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeNamespaceDeclarations(ol,ls->title(lang),false); } - break; + break; case LayoutDocEntry::FileConstantGroups: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeNamespaceDeclarations(ol,ls->title(lang),true); } break; - case LayoutDocEntry::MemberGroups: + case LayoutDocEntry::MemberGroups: writeMemberGroups(ol); - break; - case LayoutDocEntry::MemberDecl: + break; + case LayoutDocEntry::MemberDecl: { LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; writeMemberDeclarations(ol,lmd->type,lmd->title(lang)); } - break; - case LayoutDocEntry::MemberDeclEnd: + break; + case LayoutDocEntry::MemberDeclEnd: endMemberDeclarations(ol); break; - case LayoutDocEntry::DetailedDesc: + case LayoutDocEntry::DetailedDesc: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeDetailedDescription(ol,ls->title(lang)); } break; - case LayoutDocEntry::MemberDefStart: + case LayoutDocEntry::MemberDefStart: startMemberDocumentation(ol); - break; + break; case LayoutDocEntry::FileInlineClasses: writeInlineClasses(ol); break; - case LayoutDocEntry::MemberDef: + case LayoutDocEntry::MemberDef: { LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; writeMemberDocumentation(ol,lmd->type,lmd->title(lang)); } break; - case LayoutDocEntry::MemberDefEnd: + case LayoutDocEntry::MemberDefEnd: endMemberDocumentation(ol); break; - case LayoutDocEntry::AuthorSection: + case LayoutDocEntry::AuthorSection: writeAuthorSection(ol); break; case LayoutDocEntry::ClassIncludes: @@ -1060,13 +1056,13 @@ void FileDefImpl::writeDocumentation(OutputList &ol) case LayoutDocEntry::NamespaceStructs: case LayoutDocEntry::NamespaceExceptions: case LayoutDocEntry::NamespaceInlineClasses: - case LayoutDocEntry::GroupClasses: - case LayoutDocEntry::GroupInlineClasses: + case LayoutDocEntry::GroupClasses: + case LayoutDocEntry::GroupInlineClasses: case LayoutDocEntry::GroupNamespaces: - case LayoutDocEntry::GroupDirs: - case LayoutDocEntry::GroupNestedGroups: + case LayoutDocEntry::GroupDirs: + case LayoutDocEntry::GroupNestedGroups: case LayoutDocEntry::GroupFiles: - case LayoutDocEntry::GroupGraph: + case LayoutDocEntry::GroupGraph: case LayoutDocEntry::GroupPageDocs: case LayoutDocEntry::DirSubDirs: case LayoutDocEntry::DirFiles: @@ -1095,7 +1091,7 @@ void FileDefImpl::writeMemberPages(OutputList &ol) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - + QListIterator<MemberList> mli(m_memberLists); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) @@ -1153,7 +1149,7 @@ void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentM } /*! Write a source listing of this file to the output */ -void FileDefImpl::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu) +void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); @@ -1211,23 +1207,13 @@ void FileDefImpl::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu ol.popGeneratorState(); } - (void)sameTu; - (void)filesInSameTu; #if USE_LIBCLANG - static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); - if (clangAssistedParsing && + if (Doxygen::clangAssistedParsing && clangParser && (getLanguage()==SrcLangExt_Cpp || getLanguage()==SrcLangExt_ObjC)) { ol.startCodeFragment(); - if (!sameTu) - { - ClangParser::instance()->start(absFilePath(),filesInSameTu); - } - else - { - ClangParser::instance()->switchToFile(absFilePath()); - } - ClangParser::instance()->writeSources(ol,this); + clangParser->switchToFile(this); + clangParser->writeSources(ol,this); ol.endCodeFragment(); } else @@ -1236,7 +1222,7 @@ void FileDefImpl::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); intf.resetCodeParserState(); ol.startCodeFragment(); - bool needs2PassParsing = + bool needs2PassParsing = Doxygen::parseSourcesNeeded && // we need to parse (filtered) sources for cross-references !filterSourceFiles && // but user wants to show sources as-is !getFileFilter(absFilePath(),TRUE).isEmpty(); // and there is a filter used while parsing @@ -1271,26 +1257,16 @@ void FileDefImpl::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu ol.enableAll(); } -void FileDefImpl::parseSource(bool sameTu,QStrList &filesInSameTu) +void FileDefImpl::parseSource(ClangTUParser *clangParser) { static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); DevNullCodeDocInterface devNullIntf; - (void)sameTu; - (void)filesInSameTu; #if USE_LIBCLANG - static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); - if (clangAssistedParsing && + if (Doxygen::clangAssistedParsing && clangParser && (getLanguage()==SrcLangExt_Cpp || getLanguage()==SrcLangExt_ObjC)) { - if (!sameTu) - { - ClangParser::instance()->start(absFilePath(),filesInSameTu); - } - else - { - ClangParser::instance()->switchToFile(absFilePath()); - } - ClangParser::instance()->writeSources(devNullIntf,this); + clangParser->switchToFile(this); + clangParser->writeSources(devNullIntf,this); } else #endif @@ -1306,15 +1282,6 @@ void FileDefImpl::parseSource(bool sameTu,QStrList &filesInSameTu) } } -void FileDefImpl::startParsing() -{ -} - -void FileDefImpl::finishParsing() -{ - ClangParser::instance()->finish(); -} - void FileDefImpl::addMembersToMemberGroup() { QListIterator<MemberList> mli(m_memberLists); @@ -1351,7 +1318,7 @@ void FileDefImpl::insertMember(MemberDef *md) // name().data(),md->name().data(),md,allMemberList.count()); MemberList *allMemberList = getMemberList(MemberListType_allMembersList); if (allMemberList && allMemberList->findRef(md)!=-1) // TODO optimize the findRef! - { + { return; } @@ -1360,38 +1327,38 @@ void FileDefImpl::insertMember(MemberDef *md) allMemberList = new MemberList(MemberListType_allMembersList); m_memberLists.append(allMemberList); } - allMemberList->append(md); + allMemberList->append(md); //::addFileMemberNameToIndex(md); switch (md->memberType()) { - case MemberType_Variable: - case MemberType_Property: + case MemberType_Variable: + case MemberType_Property: addMemberToList(MemberListType_decVarMembers,md); addMemberToList(MemberListType_docVarMembers,md); break; - case MemberType_Function: + case MemberType_Function: addMemberToList(MemberListType_decFuncMembers,md); addMemberToList(MemberListType_docFuncMembers,md); break; - case MemberType_Typedef: + case MemberType_Typedef: addMemberToList(MemberListType_decTypedefMembers,md); addMemberToList(MemberListType_docTypedefMembers,md); break; - case MemberType_Sequence: + case MemberType_Sequence: addMemberToList(MemberListType_decSequenceMembers,md); addMemberToList(MemberListType_docSequenceMembers,md); break; - case MemberType_Dictionary: + case MemberType_Dictionary: addMemberToList(MemberListType_decDictionaryMembers,md); addMemberToList(MemberListType_docDictionaryMembers,md); break; - case MemberType_Enumeration: + case MemberType_Enumeration: addMemberToList(MemberListType_decEnumMembers,md); addMemberToList(MemberListType_docEnumMembers,md); break; case MemberType_EnumValue: // enum values are shown inside their enums break; - case MemberType_Define: + case MemberType_Define: addMemberToList(MemberListType_decDefineMembers,md); addMemberToList(MemberListType_docDefineMembers,md); break; @@ -1446,7 +1413,7 @@ void FileDefImpl::insertClass(ClassDef *cd) void FileDefImpl::insertNamespace(NamespaceDef *nd) { if (nd->isHidden()) return; - if (!nd->name().isEmpty() && + if (!nd->name().isEmpty() && (m_namespaceSDict==0 || m_namespaceSDict->find(nd->name())==0)) { if (m_namespaceSDict==0) @@ -1464,13 +1431,13 @@ void FileDefImpl::insertNamespace(NamespaceDef *nd) } } -QCString FileDefImpl::name() const -{ - if (Config_getBool(FULL_PATH_NAMES)) - return m_fileName; - else - return DefinitionImpl::name(); -} +const QCString &FileDefImpl::name() const +{ + if (Config_getBool(FULL_PATH_NAMES)) + return m_fileName; + else + return DefinitionImpl::name(); +} void FileDefImpl::addSourceRef(int line,Definition *d,MemberDef *md) { @@ -1522,10 +1489,10 @@ void FileDefImpl::addUsingDirective(const NamespaceDef *nd) //printf("%p: FileDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); } -NamespaceSDict *FileDefImpl::getUsedNamespaces() const -{ +NamespaceSDict *FileDefImpl::getUsedNamespaces() const +{ //printf("%p: FileDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); - return m_usingDirList; + return m_usingDirList; } void FileDefImpl::addUsingDeclaration(Definition *d) @@ -1540,8 +1507,7 @@ void FileDefImpl::addUsingDeclaration(Definition *d) } } -void FileDefImpl::addIncludeDependency(FileDef *fd,const char *incName,bool local, - bool imported,bool indirect) +void FileDefImpl::addIncludeDependency(FileDef *fd,const char *incName,bool local,bool imported) { //printf("FileDefImpl::addIncludeDependency(%p,%s,%d)\n",fd,incName,local); QCString iName = fd ? fd->absFilePath().data() : incName; @@ -1558,7 +1524,6 @@ void FileDefImpl::addIncludeDependency(FileDef *fd,const char *incName,bool loca ii->includeName = incName; ii->local = local; ii->imported = imported; - ii->indirect = indirect; m_includeList->append(ii); m_includeDict->insert(iName,ii); } @@ -1655,7 +1620,6 @@ void FileDefImpl::addIncludedByDependency(FileDef *fd,const char *incName, ii->includeName = incName; ii->local = local; ii->imported = imported; - ii->indirect = FALSE; m_includedByList->append(ii); m_includedByDict->insert(iName,ii); } @@ -1667,13 +1631,13 @@ bool FileDefImpl::isIncluded(const QCString &name) const return m_includeDict!=0 && m_includeDict->find(name)!=0; } -bool FileDefImpl::generateSourceFile() const -{ +bool FileDefImpl::generateSourceFile() const +{ static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); static bool verbatimHeaders = Config_getBool(VERBATIM_HEADERS); - return !isReference() && - (sourceBrowser || - (verbatimHeaders && guessSection(name())==Entry::HEADER_SEC) + return !isReference() && + (sourceBrowser || + (verbatimHeaders && guessSection(name())==Entry::HEADER_SEC) ) && !isDocumentationFile(); } @@ -1682,7 +1646,7 @@ bool FileDefImpl::generateSourceFile() const void FileDefImpl::addListReferences() { { - const std::vector<ListItemInfo> &xrefItems = xrefListItems(); + const RefItemVector &xrefItems = xrefListItems(); addRefItem(xrefItems, getOutputFileBase(), theTranslator->trFile(TRUE,TRUE), @@ -1754,7 +1718,7 @@ static Directory *findDirNode(Directory *root,const QCString &name) { // recurse into the directory return findDirNode(dir,name.mid(dirName.length()+1)); - } + } else // partial match => we need to split the path into three parts { QCString baseName =dirName.left(sp); @@ -1784,7 +1748,7 @@ static Directory *findDirNode(Directory *root,const QCString &name) // add new branch to the root if (!root->children().isEmpty()) { - root->children().getLast()->setLast(FALSE); + root->children().getLast()->setLast(FALSE); } root->addChild(base); return newBranch; @@ -1797,14 +1761,14 @@ static Directory *findDirNode(Directory *root,const QCString &name) { return root; // put the file under the root node. } - else // need to create a subdir + else // need to create a subdir { QCString baseName = name.left(si); //printf("new subdir %s\n",baseName.data()); Directory *newBranch = new Directory(root,baseName); if (!root->children().isEmpty()) { - root->children().getLast()->setLast(FALSE); + root->children().getLast()->setLast(FALSE); } root->addChild(newBranch); return newBranch; @@ -1818,7 +1782,7 @@ static void mergeFileDef(Directory *root,FileDef *fd) Directory *dirNode = findDirNode(root,filePath); if (!dirNode->children().isEmpty()) { - dirNode->children().getLast()->setLast(FALSE); + dirNode->children().getLast()->setLast(FALSE); } DirEntry *e=new DirEntry(dirNode,fd); dirNode->addChild(e); @@ -1912,7 +1876,7 @@ static void addDirsAsGroups(Directory *root,GroupDef *parent,int level) root->path(), // name root->name() // title ); - if (parent) + if (parent) { parent->addGroup(gd); gd->makePartOfGroup(parent); @@ -1937,15 +1901,11 @@ void generateFileTree() { Directory *root=new Directory(0,"root"); root->setLast(TRUE); - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { - mergeFileDef(root,fd); + mergeFileDef(root,fd.get()); } } //t << "<div class=\"directory\">\n"; @@ -2058,8 +2018,8 @@ QCString FileDefImpl::getOutputFileBase() const } /*! Returns the name of the verbatim copy of this file (if any). */ -QCString FileDefImpl::includeName() const -{ +QCString FileDefImpl::includeName() const +{ return getSourceFileBase(); } @@ -2090,17 +2050,11 @@ void FileDefImpl::addMemberToList(MemberListType lt,MemberDef *md) ((ml->listType()&MemberListType_declarationLists) && sortBriefDocs) || ((ml->listType()&MemberListType_documentationLists) && sortMemberDocs)); ml->append(md); -#if 0 - if (ml->needsSorting()) - ml->inSort(md); - else - ml->append(md); -#endif if (lt&MemberListType_documentationLists) { ml->setInFile(TRUE); } - if (ml->listType()&MemberListType_declarationLists) md->setSectionList(ml); + if (ml->listType()&MemberListType_declarationLists) md->setSectionList(this,ml); } void FileDefImpl::sortMemberLists() @@ -2143,7 +2097,7 @@ void FileDefImpl::writeMemberDeclarations(OutputList &ol,MemberListType lt,const { static bool optVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); MemberList * ml = getMemberList(lt); - if (ml) + if (ml) { if (optVhdl) // use specific declarations function { @@ -2170,7 +2124,7 @@ bool FileDefImpl::isLinkableInProject() const } static void getAllIncludeFilesRecursively( - QDict<void> *filesVisited,const FileDef *fd,QStrList &incFiles) + StringUnorderedSet &filesVisited,const FileDef *fd,StringVector &incFiles) { if (fd->includeFileList()) { @@ -2179,21 +2133,21 @@ static void getAllIncludeFilesRecursively( for (iii.toFirst();(ii=iii.current());++iii) { if (ii->fileDef && !ii->fileDef->isReference() && - !filesVisited->find(ii->fileDef->absFilePath())) + filesVisited.find(ii->fileDef->absFilePath().str())==filesVisited.end()) { //printf("FileDefImpl::addIncludeDependency(%s)\n",ii->fileDef->absFilePath().data()); - incFiles.append(ii->fileDef->absFilePath()); - filesVisited->insert(ii->fileDef->absFilePath(),(void*)0x8); + incFiles.push_back(ii->fileDef->absFilePath().str()); + filesVisited.insert(ii->fileDef->absFilePath().str()); getAllIncludeFilesRecursively(filesVisited,ii->fileDef,incFiles); } } } } -void FileDefImpl::getAllIncludeFilesRecursively(QStrList &incFiles) const +void FileDefImpl::getAllIncludeFilesRecursively(StringVector &incFiles) const { - QDict<void> includes(257); - ::getAllIncludeFilesRecursively(&includes,this,incFiles); + StringUnorderedSet includes; + ::getAllIncludeFilesRecursively(includes,this,incFiles); } QCString FileDefImpl::title() const diff --git a/src/filedef.h b/src/filedef.h index b66d7be..e4bb549 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -25,6 +25,7 @@ #include "definition.h" #include "sortdict.h" #include "memberlist.h" +#include "containers.h" class MemberList; class FileDef; @@ -40,24 +41,24 @@ class MemberGroupSDict; class PackageDef; class DirDef; class FTextStream; +class ClangTUParser; /** Class representing the data associated with a \#include statement. */ struct IncludeInfo { - IncludeInfo() : fileDef(0), local(FALSE), imported(FALSE), indirect(FALSE) {} + IncludeInfo() : fileDef(0), local(FALSE), imported(FALSE) {} ~IncludeInfo() {} FileDef *fileDef; QCString includeName; bool local; bool imported; - bool indirect; }; -/** A model of a file symbol. - * +/** A model of a file symbol. + * * An object of this class contains all file information that is gathered. * This includes the members and compounds defined in the file. - * + * * The member writeDocumentation() can be used to generate the page of * documentation to HTML and LaTeX. */ @@ -71,7 +72,7 @@ class FileDef : virtual public Definition virtual DefType definitionType() const = 0; /*! Returns the unique file name (this may include part of the path). */ - virtual QCString name() const = 0; + virtual const QCString &name() const = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual QCString fileName() const = 0; @@ -119,7 +120,7 @@ class FileDef : virtual public Definition virtual SDict<Definition> *getUsedClasses() const = 0; virtual QList<IncludeInfo> *includeFileList() const = 0; virtual QList<IncludeInfo> *includedByFileList() const = 0; - virtual void getAllIncludeFilesRecursively(QStrList &incFiles) const = 0; + virtual void getAllIncludeFilesRecursively(StringVector &incFiles) const = 0; virtual MemberList *getMemberList(MemberListType lt) const = 0; virtual const QList<MemberList> &getMemberLists() const = 0; @@ -149,10 +150,8 @@ class FileDef : virtual public Definition virtual void writeSummaryLinks(OutputList &ol) const = 0; virtual void writeTagFile(FTextStream &t) = 0; - virtual void startParsing() = 0; - virtual void writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu) = 0; - virtual void parseSource(bool sameTu,QStrList &filesInSameTu) = 0; - virtual void finishParsing() = 0; + virtual void writeSource(OutputList &ol,ClangTUParser *clangParser) = 0; + virtual void parseSource(ClangTUParser *clangParser) = 0; virtual void setDiskName(const QCString &name) = 0; virtual void insertMember(MemberDef *md) = 0; @@ -170,7 +169,7 @@ class FileDef : virtual public Definition virtual bool generateSourceFile() const = 0; virtual void sortMemberLists() = 0; - virtual void addIncludeDependency(FileDef *fd,const char *incName,bool local,bool imported,bool indirect) = 0; + virtual void addIncludeDependency(FileDef *fd,const char *incName,bool local,bool imported) = 0; virtual void addIncludedByDependency(FileDef *fd,const char *incName,bool local,bool imported) = 0; virtual void addMembersToMemberGroup() = 0; @@ -217,7 +216,7 @@ class OutputNameList : public QList<FileList> class OutputNameDict : public QDict<FileList> { public: - OutputNameDict(int size) : QDict<FileList>(size) {} + OutputNameDict(uint size) : QDict<FileList>(size) {} ~OutputNameDict() {} }; @@ -228,11 +227,11 @@ class DirEntry { public: enum EntryKind { Dir, File }; - DirEntry(DirEntry *parent,FileDef *fd) - : m_parent(parent), m_name(fd->name()), m_kind(File), m_fd(fd), + DirEntry(DirEntry *parent,FileDef *fd) + : m_parent(parent), m_name(fd->name()), m_kind(File), m_fd(fd), m_isLast(FALSE) { } - DirEntry(DirEntry *parent,QCString name) - : m_parent(parent), m_name(name), m_kind(Dir), + DirEntry(DirEntry *parent,QCString name) + : m_parent(parent), m_name(name), m_kind(Dir), m_fd(0), m_isLast(FALSE) { } virtual ~DirEntry() { } EntryKind kind() const { return m_kind; } @@ -257,7 +256,7 @@ class DirEntry class Directory : public DirEntry { public: - Directory(Directory *parent,const QCString &name) + Directory(Directory *parent,const QCString &name) : DirEntry(parent,name) { m_children.setAutoDelete(TRUE); } virtual ~Directory() {} diff --git a/src/filename.cpp b/src/filename.cpp deleted file mode 100644 index 637fe33..0000000 --- a/src/filename.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#include "filename.h" -#include "util.h" -#include "config.h" - -FileName::FileName(const char *fn,const char *n) : FileList() -{ - setAutoDelete(TRUE); - fName=fn; - name=n; -} - -FileName::~FileName() -{ -} - - -void FileName::generateDiskNames() -{ - //QCString commonPrefix; - QListIterator<FileDef> it(*this); - FileDef *fd; - int count=0; - for (;(fd=it.current());++it) - { - if (!fd->isReference()) count++; - } - if (count==1) - { - // skip references - for (it.toFirst();(fd=it.current()) && fd->isReference();++it) { } - if (fd) - { - // name if unique, so diskname is simply the name - //printf("!!!!!!!! Unique disk name=%s for fd=%s\n",name.data(),fd->diskname.data()); - fd->setDiskName(name); - } - } - else if (count>1) // multiple occurrences of the same file name - { - //printf("Multiple occurrences of %s\n",name.data()); - int i=0,j=0; - bool found=FALSE; - while (!found) // search for the common prefix of all paths - { - for (it.toFirst();(fd=it.current()) && fd->isReference();++it) { } - if (fd) - { - char c=fd->getPath().at(i); - if (c=='/') j=i; // remember last position of dirname - ++it; - while ((fd=it.current()) && !found) - { - QCString path = fd->getPath(); - if (!fd->isReference()) - { - //printf("i=%d j=%d fd->path='%s' fd->name='%s'\n",i,j,fd->path.left(i).data(),fd->name().data()); - if (i==(int)path.length()) - { - //warning("Input file %s found multiple times!\n" - // " The generated documentation for this file may not be correct!\n",fd->absFilePath().data()); - found=TRUE; - } - else if (path[i]!=c) - { - found=TRUE; - } - } - ++it; - } - i++; - } - } - for (it.toFirst();(fd=it.current());++it) - { - //printf("fd->setName(%s)\n",(fd->path.right(fd->path.length()-j-1)+name).data()); - if (!fd->isReference()) - { - QCString path = fd->getPath(); - QCString prefix = path.right(path.length()-j-1); - fd->setName(prefix+name); - //printf("!!!!!!!! non unique disk name=%s:%s\n",prefix.data(),name.data()); - fd->setDiskName(prefix+name); - } - } - } -} - -int FileName::compareValues(const FileDef *f1, const FileDef *f2) const -{ - return qstricmp(f1->fileName(),f2->fileName()); -} - -FileNameIterator::FileNameIterator(const FileName &fname) : - QListIterator<FileDef>(fname) -{ -} - -FileNameList::FileNameList() : QList<FileName>() -{ -} - -FileNameList::~FileNameList() -{ -} - -void FileNameList::generateDiskNames() -{ - FileNameListIterator it(*this); - FileName *fn; - for (;(fn=it.current());++it) - { - fn->generateDiskNames(); - } -} - -int FileNameList::compareValues(const FileName *f1, const FileName *f2) const -{ - return Config_getBool(FULL_PATH_NAMES) ? - qstricmp(f1->fullName(),f2->fullName()) : - qstricmp(f1->fileName(),f2->fileName()); -} - -FileNameListIterator::FileNameListIterator(const FileNameList &fnlist) : - QListIterator<FileName>(fnlist) -{ -} - -static bool getCaseSenseNames() -{ - static bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); - return caseSenseNames; -} - -FileNameDict::FileNameDict(uint size) : QDict<FileName>(size,getCaseSenseNames()) -{ -} - diff --git a/src/filename.h b/src/filename.h index fbee0e1..c3a0d3e 100644 --- a/src/filename.h +++ b/src/filename.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -18,57 +16,31 @@ #ifndef FILENAME_H #define FILENAME_H -#include <qdict.h> -#include <qlist.h> -#include "filedef.h" +#include <memory> +#include <vector> -/** Class representing all files with a certain base name */ -class FileName : public FileList -{ - public: - FileName(const char *fn,const char *name); - ~FileName(); - const char *fileName() const { return name; } - const char *fullName() const { return fName; } - void generateDiskNames(); +#include "linkedmap.h" - private: - int compareValues(const FileDef *item1,const FileDef *item2) const; - QCString name; - QCString fName; -}; +class FileDef; -/** Iterator for FileDef objects in a FileName list. */ -class FileNameIterator : public QListIterator<FileDef> +/** Class representing all files with a certain base name */ +class FileName : public std::vector< std::unique_ptr<FileDef> > { public: - FileNameIterator(const FileName &list); -}; + FileName(const char *nm,const char *fn) : m_name(nm), m_fName(fn), m_pathName("tmp") {} + const char *fileName() const { return m_name; } + const char *fullName() const { return m_fName; } + const char *path() const { return m_pathName; } -/** Class representing a list of FileName objects. */ -class FileNameList : public QList<FileName> -{ - public: - FileNameList(); - ~FileNameList(); - void generateDiskNames(); private: - int compareValues(const FileName *item1,const FileName *item2) const; + QCString m_name; + QCString m_fName; + QCString m_pathName; }; -/** Iterator for FileName objects in a FileNameList. */ -class FileNameListIterator : public QListIterator<FileName> +/** Ordered dictionary of FileName objects. */ +class FileNameLinkedMap : public LinkedMap<FileName> { - public: - FileNameListIterator( const FileNameList &list ); -}; - -/** Unsorted dictionary of FileName objects. */ -class FileNameDict : public QDict<FileName> -{ - public: - FileNameDict(uint size); - ~FileNameDict() {} }; #endif diff --git a/src/formula.cpp b/src/formula.cpp index 64555c9..ca50c9c 100644 --- a/src/formula.cpp +++ b/src/formula.cpp @@ -1,11 +1,10 @@ /****************************************************************************** - * * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -14,41 +13,137 @@ * */ -#include <stdlib.h> -#include <qfile.h> -#include <qfileinfo.h> -#include <qtextstream.h> -#include <qdir.h> - #include "formula.h" -#include "image.h" -#include "util.h" #include "message.h" #include "config.h" -#include "portable.h" -#include "index.h" -#include "doxygen.h" #include "ftextstream.h" +#include "util.h" +#include "portable.h" +#include "image.h" -Formula::Formula(const char *text) +#include <qfile.h> +#include <qtextstream.h> +#include <qdir.h> + +#include <map> +#include <vector> +#include <string> +#include <utility> + +// TODO: remove these dependencies +#include "doxygen.h" // for Doxygen::indexList +#include "index.h" // for Doxygen::indexList + +static int determineInkscapeVersion(QDir &thisDir); + +// Remove the temporary files +#define RM_TMP_FILES (true) +//#define RM_TMP_FILES (false) + +struct FormulaManager::Private +{ + void storeDisplaySize(int id,int w,int h) + { + displaySizeMap.insert(std::make_pair(id,DisplaySize(w,h))); + } + DisplaySize getDisplaySize(int id) + { + auto it = displaySizeMap.find(id); + if (it!=displaySizeMap.end()) + { + return it->second; + } + return DisplaySize(-1,-1); + } + StringVector formulas; + IntMap formulaMap; + std::map<int,DisplaySize> displaySizeMap; +}; + +FormulaManager::FormulaManager() : p(new Private) { - static int count=0; - number = count++; - form=text; } -Formula::~Formula() +FormulaManager &FormulaManager::instance() { + static FormulaManager fm; + return fm; } -int Formula::getId() +void FormulaManager::readFormulas(const char *dir,bool doCompare) { - return number; + QFile f(QCString(dir)+"/formula.repository"); + if (f.open(IO_ReadOnly)) // open repository + { + uint formulaCount=0; + msg("Reading formula repository...\n"); + QTextStream t(&f); + QCString line; + int lineNr=1; + while (!t.eof()) + { + line=t.readLine().utf8(); + // old format: \_form#<digits>:formula + // new format: \_form#<digits>=<digits>x<digits>:formula + int hi=line.find('#'); + int ei=line.find('='); + int se=line.find(':'); // find name and text separator. + if (hi==-1 || se==-1 || hi>se) + { + warn_uncond("%s/formula.repository is corrupted at line %d!\n",dir,lineNr); + break; + } + else + { + QCString formName = line.left(se); + QCString formText = line.right(line.length()-se-1); + int w=-1,h=-1; + if (ei!=-1 && ei>hi && ei<se) // new format + { + int xi=formName.find('x',ei); + if (xi!=-1) + { + w=formName.mid(ei+1,xi-ei-1).toInt(); + h=formName.mid(xi+1).toInt(); + } + formName = formName.left(ei); + } + else + { + ei=formName.length(); + } + if (doCompare) + { + int formId = formName.mid(hi+1,ei-hi-1).toInt(); + QCString storedFormText = FormulaManager::instance().findFormula(formId); + if (storedFormText!=formText) + { + term("discrepancy between formula repositories! Remove " + "formula.repository and from_* files from output directories.\n"); + } + formulaCount++; + } + else + { + int id = addFormula(formText); + if (w!=-1 && h!=-1) + { + p->storeDisplaySize(id,w,h); + } + } + } + lineNr++; + } + if (doCompare && formulaCount!=p->formulas.size()) + { + term("size discrepancy between formula repositories! Remove " + "formula.repository and from_* files from output directories.\n"); + } + } } -void FormulaList::generateBitmaps(const char *path) +void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) const { - int x1,y1,x2,y2; QDir d(path); // store the original directory if (!d.exists()) @@ -70,10 +165,7 @@ void FormulaList::generateBitmaps(const char *path) QDir thisDir; // generate a latex file containing one formula per page. QCString texName="_formulas.tex"; - QList<int> pagesToGenerate; - pagesToGenerate.setAutoDelete(TRUE); - FormulaListIterator fli(*this); - Formula *formula; + IntVector formulasToGenerate; QFile f(texName); bool formulaError=FALSE; if (f.open(IO_WriteOnly)) @@ -91,34 +183,34 @@ void FormulaList::generateBitmaps(const char *path) copyFile(macroFile,stripMacroFile); t << "\\input{" << stripMacroFile << "}" << endl; } - t << "\\pagestyle{empty}" << endl; + t << "\\pagestyle{empty}" << endl; t << "\\begin{document}" << endl; - int page=0; - for (fli.toFirst();(formula=fli.current());++fli) + for (int i=0; i<(int)p->formulas.size(); i++) { QCString resultName; - resultName.sprintf("form_%d.png",formula->getId()); + resultName.sprintf("form_%d.%s",i,format==Format::Vector?"svg":"png"); // only formulas for which no image exists are generated QFileInfo fi(resultName); if (!fi.exists()) { // we force a pagebreak after each formula - t << formula->getFormulaText() << endl << "\\pagebreak\n\n"; - pagesToGenerate.append(new int(page)); + t << p->formulas[i].c_str() << endl << "\\pagebreak\n\n"; + formulasToGenerate.push_back(i); } Doxygen::indexList->addImageFile(resultName); - page++; } t << "\\end{document}" << endl; f.close(); } - if (pagesToGenerate.count()>0) // there are new formulas + if (!formulasToGenerate.empty()) // there are new formulas { //printf("Running latex...\n"); //system("latex _formulas.tex </dev/null >/dev/null"); QCString latexCmd = "latex"; Portable::sysTimerStart(); - if (Portable::system(latexCmd,"_formulas.tex")!=0) + char args[4096]; + sprintf(args,"-interaction=batchmode _formulas.tex >%s",Portable::devNull()); + if (Portable::system(latexCmd,args)!=0) { err("Problems running latex. Check your installation or look " "for typos in _formulas.tex and check _formulas.log!\n"); @@ -127,23 +219,18 @@ void FormulaList::generateBitmaps(const char *path) } Portable::sysTimerStop(); //printf("Running dvips...\n"); - QListIterator<int> pli(pagesToGenerate); - int *pagePtr; int pageIndex=1; - for (;(pagePtr=pli.current());++pli,++pageIndex) + for (int pageNum : formulasToGenerate) { - int pageNum=*pagePtr; - msg("Generating image form_%d.png for formula\n",pageNum); - char dviArgs[4096]; - char psArgs[4096]; + msg("Generating image form_%d.%s for formula\n",pageNum,(format==Format::Vector) ? "svg" : "png"); QCString formBase; formBase.sprintf("_form%d",pageNum); // run dvips to convert the page with number pageIndex to an // postscript file. - sprintf(dviArgs,"-q -D 600 -n 1 -p %d -o %s_tmp.ps _formulas.dvi", + sprintf(args,"-q -D 600 -n 1 -p %d -o %s_tmp.ps _formulas.dvi", pageIndex,formBase.data()); Portable::sysTimerStart(); - if (Portable::system("dvips",dviArgs)!=0) + if (Portable::system("dvips",args)!=0) { err("Problems running dvips. Check your installation!\n"); Portable::sysTimerStop(); @@ -151,180 +238,215 @@ void FormulaList::generateBitmaps(const char *path) return; } Portable::sysTimerStop(); - // run ps2epsi to convert to an encapsulated postscript file with - // boundingbox (dvips with -E has some problems here). - sprintf(psArgs,"%s_tmp.ps %s.eps",formBase.data(),formBase.data()); + + // extract the bounding box for the postscript file + sprintf(args,"-q -dBATCH -dNOPAUSE -P- -dNOSAFER -sDEVICE=bbox %s_tmp.ps 2>%s_tmp.epsi", + formBase.data(),formBase.data()); Portable::sysTimerStart(); - if (Portable::system("ps2epsi",psArgs)!=0) + if (Portable::system(Portable::ghostScriptCommand(),args)!=0) { - err("Problems running ps2epsi. Check your installation!\n"); + err("Problems running %s. Check your installation!\n",Portable::ghostScriptCommand()); Portable::sysTimerStop(); QDir::setCurrent(oldDir); return; } Portable::sysTimerStop(); - // now we read the generated postscript file to extract the bounding box - QFileInfo fi(formBase+".eps"); + + // extract the bounding box info from the generate .epsi file + int x1=0,y1=0,x2=0,y2=0; + QFileInfo fi(formBase+"_tmp.epsi"); if (fi.exists()) { - QCString eps = fileToString(formBase+".eps"); - int i=eps.find("%%BoundingBox:"); + QString eps = fileToString(formBase+"_tmp.epsi"); + int i = eps.find("%%BoundingBox:"); if (i!=-1) { sscanf(eps.data()+i,"%%%%BoundingBox:%d %d %d %d",&x1,&y1,&x2,&y2); } else { - err("Couldn't extract bounding box!\n"); + err("Couldn't extract bounding box from %s_tmp.epsi",formBase.data()); } - } - // next we generate a postscript file which contains the eps - // and displays it in the right colors and the right bounding box - f.setName(formBase+".ps"); - if (f.open(IO_WriteOnly)) - { - FTextStream t(&f); - t << "1 1 1 setrgbcolor" << endl; // anti-alias to white background - t << "newpath" << endl; - t << "-1 -1 moveto" << endl; - t << (x2-x1+2) << " -1 lineto" << endl; - t << (x2-x1+2) << " " << (y2-y1+2) << " lineto" << endl; - t << "-1 " << (y2-y1+2) << " lineto" <<endl; - t << "closepath" << endl; - t << "fill" << endl; - t << -x1 << " " << -y1 << " translate" << endl; - t << "0 0 0 setrgbcolor" << endl; - t << "(" << formBase << ".eps) run" << endl; - f.close(); } - // scale the image so that it is four times larger than needed. - // and the sizes are a multiple of four. - double scaleFactor = 16.0/3.0; + //printf("Bounding box [%d %d %d %d]\n",x1,y1,x2,y2); + + // convert the corrected EPS to a bitmap + double scaleFactor = 1.25; int zoomFactor = Config_getInt(FORMULA_FONTSIZE); if (zoomFactor<8 || zoomFactor>50) zoomFactor=10; scaleFactor *= zoomFactor/10.0; - int gx = (((int)((x2-x1)*scaleFactor))+3)&~1; - int gy = (((int)((y2-y1)*scaleFactor))+3)&~1; - // Then we run ghostscript to convert the postscript to a pixmap - // The pixmap is a truecolor image, where only black and white are - // used. - char gsArgs[4096]; - sprintf(gsArgs,"-q -g%dx%d -r%dx%d -sDEVICE=ppmraw " - "-sOutputFile=%s.pnm -dNOPAUSE -dBATCH -dNOSAFER %s.ps", - gx,gy,(int)(scaleFactor*72),(int)(scaleFactor*72), - formBase.data(),formBase.data() - ); - Portable::sysTimerStart(); - if (Portable::system(Portable::ghostScriptCommand(),gsArgs)!=0) + int width = (int)((x2-x1)*scaleFactor+0.5); + int height = (int)((y2-y1)*scaleFactor+0.5); + p->storeDisplaySize(pageNum,width,height); + + if (format==Format::Vector) { - err("Problem running ghostscript %s %s. Check your installation!\n",Portable::ghostScriptCommand(),gsArgs); + // crop the image to its bounding box + sprintf(args,"-q -dBATCH -dNOPAUSE -P- -dNOSAFER -sDEVICE=pdfwrite" + " -o %s_tmp.pdf -c \"[/CropBox [%d %d %d %d] /PAGES pdfmark\" -f %s_tmp.ps", + formBase.data(),x1,y1,x2,y2,formBase.data()); + Portable::sysTimerStart(); + if (Portable::system(Portable::ghostScriptCommand(),args)!=0) + { + err("Problems running %s. Check your installation!\n",Portable::ghostScriptCommand()); + Portable::sysTimerStop(); + QDir::setCurrent(oldDir); + return; + } Portable::sysTimerStop(); - QDir::setCurrent(oldDir); - return; + + // if we have pdf2svg available use it to create a SVG image + if (Portable::checkForExecutable("pdf2svg")) + { + sprintf(args,"%s_tmp.pdf form_%d.svg",formBase.data(),pageNum); + Portable::sysTimerStart(); + if (Portable::system("pdf2svg",args)!=0) + { + err("Problems running pdf2svg. Check your installation!\n"); + Portable::sysTimerStop(); + QDir::setCurrent(oldDir); + return; + } + Portable::sysTimerStop(); + } + else if (Portable::checkForExecutable("inkscape")) // alternative is to use inkscape + { + int inkscapeVersion = determineInkscapeVersion(thisDir); + if (inkscapeVersion == -1) + { + err("Problems determining the version of inkscape. Check your installation!\n"); + QDir::setCurrent(oldDir); + return; + } + else if (inkscapeVersion == 0) + { + sprintf(args,"-l form_%d.svg -z %s_tmp.pdf 2>%s",pageNum,formBase.data(),Portable::devNull()); + } + else // inkscapeVersion >= 1 + { + sprintf(args,"--export-type=svg --export-filename=form_%d.svg %s_tmp.pdf 2>%s",pageNum,formBase.data(),Portable::devNull()); + } + Portable::sysTimerStart(); + if (Portable::system("inkscape",args)!=0) + { + err("Problems running inkscape. Check your installation!\n"); + Portable::sysTimerStop(); + QDir::setCurrent(oldDir); + return; + } + Portable::sysTimerStop(); + } + else + { + err("Neither 'pdf2svg' nor 'inkscape' present for conversion of formula to 'svg'\n"); + return; + } + + if (RM_TMP_FILES) + { + thisDir.remove(formBase+"_tmp.pdf"); + } } - Portable::sysTimerStop(); - f.setName(formBase+".pnm"); - uint imageX=0,imageY=0; - // we read the generated image again, to obtain the pixel data. - if (f.open(IO_ReadOnly)) + else // format==Format::Bitmap { - QTextStream t(&f); - QCString s; - if (!t.eof()) - s=t.readLine().utf8(); - if (s.length()<2 || s.left(2)!="P6") - err("ghostscript produced an illegal image format!"); - else + // crop the image to its bounding box + sprintf(args,"-q -dBATCH -dNOPAUSE -P- -dNOSAFER -sDEVICE=eps2write" + " -o %s_tmp.eps -f %s_tmp.ps",formBase.data(),formBase.data()); + Portable::sysTimerStart(); + if (Portable::system(Portable::ghostScriptCommand(),args)!=0) { - // assume the size is after the first line that does not start with - // # excluding the first line of the file. - while (!t.eof() && (s=t.readLine().utf8()) && !s.isEmpty() && s.at(0)=='#') { } - sscanf(s,"%d %d",&imageX,&imageY); + err("Problems running %s. Check your installation!\n",Portable::ghostScriptCommand()); + Portable::sysTimerStop(); + QDir::setCurrent(oldDir); + return; } - if (imageX>0 && imageY>0) + + // read back %s_tmp.eps and replace + // bounding box values with x1,y1,x2,y2 and remove the HiResBoundingBox + QFile epsIn(formBase+"_tmp.eps"); + QFile epsOut(formBase+"_tmp_corr.eps"); + if (epsIn.open(IO_ReadOnly) && epsOut.open(IO_WriteOnly)) { - //printf("Converting image...\n"); - char *data = new char[imageX*imageY*3]; // rgb 8:8:8 format - uint i,x,y,ix,iy; - f.readBlock(data,imageX*imageY*3); - Image srcImage(imageX,imageY), - filteredImage(imageX,imageY), - dstImage(imageX/4,imageY/4); - uchar *ps=srcImage.getData(); - // convert image to black (1) and white (0) index. - for (i=0;i<imageX*imageY;i++) *ps++= (data[i*3]==0 ? 1 : 0); - // apply a simple box filter to the image - static int filterMask[]={1,2,1,2,8,2,1,2,1}; - for (y=0;y<srcImage.getHeight();y++) + int maxLineLen=100*1024; + while (!epsIn.atEnd()) { - for (x=0;x<srcImage.getWidth();x++) + QCString buf(maxLineLen); + FTextStream t(&epsOut); + int numBytes = epsIn.readLine(buf.rawData(),maxLineLen); + if (numBytes>0) { - int s=0; - for (iy=0;iy<2;iy++) + buf.resize(numBytes+1); + if (buf.startsWith("%%BoundingBox")) { - for (ix=0;ix<2;ix++) - { - s+=srcImage.getPixel(x+ix-1,y+iy-1)*filterMask[iy*3+ix]; - } + t << "%%BoundingBox: " << x1 << " " << y1 << " " << x2 << " " << y2 << endl; + } + else if (buf.startsWith("%%HiResBoundingBox")) // skip this one + { + } + else + { + t << buf; } - filteredImage.setPixel(x,y,s); - } - } - // down-sample the image to 1/16th of the area using 16 gray scale - // colors. - // TODO: optimize this code. - for (y=0;y<dstImage.getHeight();y++) - { - for (x=0;x<dstImage.getWidth();x++) - { - int xp=x<<2; - int yp=y<<2; - int c=filteredImage.getPixel(xp+0,yp+0)+ - filteredImage.getPixel(xp+1,yp+0)+ - filteredImage.getPixel(xp+2,yp+0)+ - filteredImage.getPixel(xp+3,yp+0)+ - filteredImage.getPixel(xp+0,yp+1)+ - filteredImage.getPixel(xp+1,yp+1)+ - filteredImage.getPixel(xp+2,yp+1)+ - filteredImage.getPixel(xp+3,yp+1)+ - filteredImage.getPixel(xp+0,yp+2)+ - filteredImage.getPixel(xp+1,yp+2)+ - filteredImage.getPixel(xp+2,yp+2)+ - filteredImage.getPixel(xp+3,yp+2)+ - filteredImage.getPixel(xp+0,yp+3)+ - filteredImage.getPixel(xp+1,yp+3)+ - filteredImage.getPixel(xp+2,yp+3)+ - filteredImage.getPixel(xp+3,yp+3); - // here we scale and clip the color value so the - // resulting image has a reasonable contrast - dstImage.setPixel(x,y,QMIN(15,(c*15)/(16*10))); } } - // save the result as a bitmap - QCString resultName; - resultName.sprintf("form_%d.png",pageNum); - // the option parameter 1 is used here as a temporary hack - // to select the right color palette! - dstImage.save(resultName,1); - delete[] data; + epsIn.close(); + epsOut.close(); + } + else + { + err("Problems correcting the eps files from %s_tmp.eps to %s_tmp_corr.eps\n", + formBase.data(),formBase.data()); + QDir::setCurrent(oldDir); + return; } - f.close(); - } + + if (hd==HighDPI::On) // for high DPI display it looks much better if the + // image resolution is higher than the display resolution + { + scaleFactor*=2; + } + + Portable::sysTimerStop(); + sprintf(args,"-q -dNOSAFER -dBATCH -dNOPAUSE -dEPSCrop -sDEVICE=pnggray -dGraphicsAlphaBits=4 -dTextAlphaBits=4 " + "-r%d -sOutputFile=form_%d.png %s_tmp_corr.eps",(int)(scaleFactor*72),pageNum,formBase.data()); + Portable::sysTimerStart(); + if (Portable::system(Portable::ghostScriptCommand(),args)!=0) + { + err("Problems running %s. Check your installation!\n",Portable::ghostScriptCommand()); + Portable::sysTimerStop(); + QDir::setCurrent(oldDir); + return; + } + Portable::sysTimerStop(); + + if (RM_TMP_FILES) + { + thisDir.remove(formBase+"_tmp.eps"); + thisDir.remove(formBase+"_tmp_corr.eps"); + } + } + // remove intermediate image files - thisDir.remove(formBase+"_tmp.ps"); - thisDir.remove(formBase+".eps"); - thisDir.remove(formBase+".pnm"); - thisDir.remove(formBase+".ps"); + if (RM_TMP_FILES) + { + thisDir.remove(formBase+"_tmp.ps"); + thisDir.remove(formBase+"_tmp.epsi"); + } + pageIndex++; } // remove intermediate files produced by latex - thisDir.remove("_formulas.dvi"); - if (!formulaError) thisDir.remove("_formulas.log"); // keep file in case of errors - thisDir.remove("_formulas.aux"); + if (RM_TMP_FILES) + { + thisDir.remove("_formulas.dvi"); + if (!formulaError) thisDir.remove("_formulas.log"); // keep file in case of errors + thisDir.remove("_formulas.aux"); + } } // remove the latex file itself - if (!formulaError) thisDir.remove("_formulas.tex"); - // write/update the formula repository so we know what text the + if (RM_TMP_FILES && !formulaError) thisDir.remove("_formulas.tex"); + + // write/update the formula repository so we know what text the // generated images represent (we use this next time to avoid regeneration // of the images, and to avoid forcing the user to delete all images in order // to let a browser refresh the images). @@ -332,9 +454,15 @@ void FormulaList::generateBitmaps(const char *path) if (f.open(IO_WriteOnly)) { FTextStream t(&f); - for (fli.toFirst();(formula=fli.current());++fli) + for (int i=0; i<(int)p->formulas.size(); i++) { - t << "\\_form#" << formula->getId() << ":" << formula->getFormulaText() << endl; + DisplaySize size = p->getDisplaySize(i); + t << "\\_form#" << i; + if (size.width!=-1 && size.height!=-1) + { + t << "=" << size.width << "x" << size.height; + } + t << ":" << p->formulas[i].c_str() << endl; } f.close(); } @@ -342,15 +470,115 @@ void FormulaList::generateBitmaps(const char *path) QDir::setCurrent(oldDir); } +void FormulaManager::clear() +{ + p->formulas.clear(); + p->formulaMap.clear(); +} -#ifdef FORMULA_TEST -int main() +int FormulaManager::addFormula(const char *formulaText) { - FormulaList fl; - fl.append(new Formula("$x^2$")); - fl.append(new Formula("$y^2$")); - fl.append(new Formula("$\\sqrt{x_0^2+x_1^2+x_2^2}$")); - fl.generateBitmaps("dest"); - return 0; + std::string key = toStdString(formulaText); + auto it = p->formulaMap.find(key); + if (it!=p->formulaMap.end()) // already stored + { + return it->second; + } + // store new formula + int id = (int)p->formulas.size(); + p->formulaMap.insert(std::pair<std::string,int>(key,id)); + p->formulas.push_back(key); + return id; +} + +QCString FormulaManager::findFormula(int formulaId) const +{ + if (formulaId>=0 && formulaId<(int)p->formulas.size()) + { + return p->formulas[formulaId].c_str(); + } + return QCString(); +} + +bool FormulaManager::hasFormulas() const +{ + return !p->formulas.empty(); +} + +FormulaManager::DisplaySize FormulaManager::displaySize(int formulaId) const +{ + return p->getDisplaySize(formulaId); +} + +// helper function to detect and return the major version of inkscape. +// return -1 if the version cannot be determined. +static int determineInkscapeVersion(QDir &thisDir) +{ + // The command line interface (CLI) of Inkscape 1.0 has changed in comparison to + // previous versions. In order to invokine Inkscape, the used version is detected + // and based on the version the right syntax of the CLI is chosen. + static int inkscapeVersion = -2; + if (inkscapeVersion == -2) // initial one time version check + { + QCString inkscapeVersionFile = "inkscape_version" ; + inkscapeVersion = -1; + QCString args = "-z --version >"+inkscapeVersionFile+" 2>"+Portable::devNull(); + Portable::sysTimerStart(); + if (Portable::system("inkscape",args)!=0) + { + // looks like the old syntax gave problems, lets try the new syntax + args = " --version >"+inkscapeVersionFile+" 2>"+Portable::devNull(); + if (Portable::system("inkscape",args)!=0) + { + Portable::sysTimerStop(); + return -1; + } + } + // read version file and determine major version + QFile inkscapeVersionIn(inkscapeVersionFile); + if (inkscapeVersionIn.open(IO_ReadOnly)) + { + int maxLineLen=1024; + while (!inkscapeVersionIn.atEnd()) + { + QCString buf(maxLineLen); + int numBytes = inkscapeVersionIn.readLine(buf.rawData(),maxLineLen); + if (numBytes>0) + { + buf.resize(numBytes+1); + int dotPos = buf.find('.'); + if (buf.startsWith("Inkscape ") && dotPos>0) + { + // get major version + bool ok; + int version = buf.mid(9,dotPos-9).toInt(&ok); + if (!ok) + { + Portable::sysTimerStop(); + return -1; + } + inkscapeVersion = version; + break; + } + } + else + { + Portable::sysTimerStop(); + return -1; + } + } + inkscapeVersionIn.close(); + } + else // failed to open version file + { + Portable::sysTimerStop(); + return -1; + } + if (RM_TMP_FILES) + { + thisDir.remove(inkscapeVersionFile); + } + Portable::sysTimerStop(); + } + return inkscapeVersion; } -#endif diff --git a/src/formula.h b/src/formula.h index 422030c..4bd90af 100644 --- a/src/formula.h +++ b/src/formula.h @@ -18,45 +18,33 @@ #ifndef FORMULA_H #define FORMULA_H -#include <qlist.h> -#include <qdict.h> +#include <memory> +#include <qcstring.h> -/** Class representing a formula in the output. */ -class Formula +/*! Manager class to handle formulas */ +class FormulaManager { public: - Formula(const char *text); - ~Formula(); - int getId(); - QCString getFormulaText() const { return form; } - + struct DisplaySize + { + DisplaySize(int w,int h) : width(w), height(h) {} + int width; + int height; + }; + enum class Format { Bitmap, Vector }; + enum class HighDPI { On, Off }; + static FormulaManager &instance(); + void readFormulas(const char *dir,bool doCompare=false); + void clear(); + int addFormula(const char *formulaText); + void generateImages(const char *outputDir,Format format,HighDPI hd = HighDPI::Off) const; + QCString findFormula(int formulaId) const; + bool hasFormulas() const; + DisplaySize displaySize(int formulaId) const; private: - int number; - QCString form; -}; - -/** A list of Formula objects. */ -class FormulaList : public QList<Formula> -{ - public: - void generateBitmaps(const char *path); -}; - -/** Iterator for Formula objects in a FormulaList. */ -class FormulaListIterator : public QListIterator<Formula> -{ - public: - FormulaListIterator(const FormulaList &l) : - QListIterator<Formula>(l) {} -}; - -/** Unsorted dictionary of Formula objects. */ -class FormulaDict : public QDict<Formula> -{ - public: - FormulaDict(uint size) : - QDict<Formula>(size) {} - ~FormulaDict() {} + FormulaManager(); + struct Private; + std::unique_ptr<Private> p; }; #endif diff --git a/src/fortrancode.h b/src/fortrancode.h index 8391a0b..7da6a61 100644 --- a/src/fortrancode.h +++ b/src/fortrancode.h @@ -28,7 +28,6 @@ class Definition; void codeFreeScanner(); -const int fixedCommentAfter = 72; class FortranCodeParser : public CodeParserInterface { diff --git a/src/fortrancode.l b/src/fortrancode.l index c4532f3..4951001 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -6,8 +6,8 @@ * based on the work of Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -20,12 +20,16 @@ @todo - continuation lines not always recognized - merging of use-statements with same module name and different only-names - rename part of use-statement - - links to interface functions + - links to interface functions - references to variables **/ %option never-interactive %option case-insensitive %option prefix="fortrancodeYY" +%option noyy_top_state +%top{ +#include <stdint.h> +} %{ @@ -54,6 +58,9 @@ #include "namespacedef.h" #include "tooltip.h" #include "fortrancode.h" +#include "containers.h" + +const int fixedCommentAfter = 72; // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -63,6 +70,8 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + /* * For fixed formatted code position 6 is of importance (continuation character). * The following variables and macros keep track of the column number @@ -73,18 +82,18 @@ int yy_old_start = 0; int yy_my_start = 0; int yy_end = 1; -#define YY_USER_ACTION {yy_old_start = yy_my_start; yy_my_start = yy_end; yy_end += yyleng;} +#define YY_USER_ACTION {yy_old_start = yy_my_start; yy_my_start = yy_end; yy_end += static_cast<int>(yyleng);} #define YY_FTN_RESET {yy_old_start = 0; yy_my_start = 0; yy_end = 1;} #define YY_FTN_REJECT {yy_end = yy_my_start; yy_my_start = yy_old_start; REJECT;} - + //-------------------------------------------------------------------------------- /** data of an use-statement */ -class UseEntry +class UseEntry { - public: + public: QCString module; // just for debug QCStringList onlyNames; /* entries of the ONLY-part */ }; @@ -93,7 +102,7 @@ class UseEntry module name -> list of ONLY/remote entries (module name = name of the module, which can be accessed via use-directive) */ -class UseSDict : public SDict<UseEntry> +class UseSDict : public SDict<UseEntry> { public: UseSDict() : SDict<UseEntry>(17) {} @@ -102,21 +111,19 @@ class UseSDict : public SDict<UseEntry> /** Contains names of used modules and names of local variables. */ -class Scope +class Scope { public: QCStringList useNames; //!< contains names of used modules - QDict<void> localVars; //!< contains names of local variables - QDict<void> externalVars; //!< contains names of external entities - - Scope() : localVars(7, FALSE /*caseSensitive*/), externalVars(7, FALSE /*caseSensitive*/) {} + StringUnorderedSet localVars; //!< contains names of local variables + StringUnorderedSet externalVars; //!< contains names of external entities }; /*===================================================================*/ -/* +/* * statics */ - + static QCString docBlock; //!< contents of all lines of a documentation block static QCString currentModule=0; //!< name of the current enclosing module static QCString currentClass=0; //!< name of the current enclosing class @@ -125,7 +132,7 @@ static UseEntry *useEntry = 0; //!< current use statement info static QList<Scope> scopeStack; static bool g_isExternal = false; // static QCStringList *currentUseNames= new QCStringList; //! contains names of used modules of current program unit -static QCString str=""; //!> contents of fortran string +static QCString g_str=""; //!> contents of fortran string static CodeOutputInterface * g_code; @@ -134,7 +141,7 @@ static QCString g_parmType; static QCString g_parmName; static const char * g_inputString; //!< the code fragment as text -static int g_inputPosition; //!< read offset during parsing +static int g_inputPosition; //!< read offset during parsing static int g_inputLines; //!< number of line in the code fragment static int g_yyLineNr; //!< current line number static int g_contLineNr; //!< current, local, line number for continuation determination @@ -166,7 +173,9 @@ static int inTypeDecl = 0; static bool g_endComment; +#if USE_STATE2STRING static const char *stateToString(int state); +#endif static void endFontClass() { @@ -223,7 +232,7 @@ static void startCodeLine() //QCString lineNumber,lineAnchor; //lineNumber.sprintf("%05d",g_yyLineNr); //lineAnchor.sprintf("l%05d",g_yyLineNr); - + Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); //printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>"); if (!g_includeCodeFragment && d) @@ -256,7 +265,7 @@ static void startCodeLine() g_code->writeLineNumber(0,0,0,g_yyLineNr); } } - g_code->startCodeLine(g_sourceFileDef); + g_code->startCodeLine(g_sourceFileDef); if (g_currentFontClass) { g_code->startFontClass(g_currentFontClass); @@ -291,7 +300,7 @@ static void codifyLines(char *text) *(p-1)='\0'; g_code->codify(sp); endCodeLine(); - if (g_yyLineNr<g_inputLines) + if (g_yyLineNr<g_inputLines) { startCodeLine(); } @@ -317,7 +326,7 @@ static void codifyLines(QCString str) } /*! writes a link to a fragment \a text that may span multiple lines, inserting - * line numbers for each line. If \a text contains newlines, the link will be + * line numbers for each line. If \a text contains newlines, the link will be * split into multiple links with the same destination, one for each line. */ static void writeMultiLineCodeLink(CodeOutputInterface &ol, @@ -328,7 +337,7 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); - QCString tooltip; + QCString tooltip; if (!sourceTooltips) // fall back to simple "title" tooltips { tooltip = d->briefDescriptionAsTooltip(); @@ -347,7 +356,7 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); endCodeLine(); - if (g_yyLineNr<g_inputLines) + if (g_yyLineNr<g_inputLines) { startCodeLine(); } @@ -384,27 +393,27 @@ static bool getFortranNamespaceDefs(const QCString &mname, @param moduleName name of enclosing module or null, if global entry @param cd the entry, if found or null @param usedict dictionary of data of USE-statement - @returns true, if type is found + @returns true, if type is found */ -static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, +static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, ClassDef *&cd, UseSDict *usedict=0) { if (tname.isEmpty()) return FALSE; /* empty name => nothing to link */ //cout << "=== search for type: " << tname << endl; - // search for type - if ((cd=Doxygen::classSDict->find(tname))) + // search for type + if ((cd=Doxygen::classSDict->find(tname))) { //cout << "=== type found in global module" << endl; return TRUE; } - else if (moduleName && (cd= Doxygen::classSDict->find(moduleName+"::"+tname))) + else if (moduleName && (cd= Doxygen::classSDict->find(moduleName+"::"+tname))) { //cout << "=== type found in local module" << endl; return TRUE; } - else + else { UseEntry *use; for (UseSDict::Iterator di(*usedict); (use=di.current()); ++di) @@ -424,96 +433,100 @@ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName searches for definition of function memberName @param memberName the name of the function/variable @param moduleName name of enclosing module or null, if global entry - @param md the entry, if found or null @param usedict array of data of USE-statement - @returns true, if found + @returns MemberDef pointer, if found, or nullptr otherwise */ -static bool getFortranDefs(const QCString &memberName, const QCString &moduleName, - MemberDef *&md, UseSDict *usedict=0) +static MemberDef *getFortranDefs(const QCString &memberName, const QCString &moduleName, + UseSDict *usedict=0) { - if (memberName.isEmpty()) return FALSE; /* empty name => nothing to link */ + if (memberName.isEmpty()) return nullptr; /* empty name => nothing to link */ // look in local variables QListIterator<Scope> it(scopeStack); Scope *scope; for (it.toLast();(scope=it.current());--it) { - if (scope->localVars.find(memberName) && (!scope->externalVars.find(memberName))) - return FALSE; + std::string lowMemName = memberName.lower().str(); + if (scope->localVars.find(lowMemName)!=std::end(scope->localVars) && // local var + scope->externalVars.find(lowMemName)==std::end(scope->externalVars)) // and not external + { + return nullptr; + } } // search for function - MemberName *mn = Doxygen::functionNameSDict->find(memberName); + MemberName *mn = Doxygen::functionNameLinkedMap->find(memberName); if (!mn) { - mn = Doxygen::memberNameSDict->find(memberName); + mn = Doxygen::memberNameLinkedMap->find(memberName); } if (mn) // name is known { - MemberNameIterator mli(*mn); - for (mli.toFirst();(md=mli.current());++mli) // all found functions with given name - { - const FileDef *fd=md->getFileDef(); - const GroupDef *gd=md->getGroupDef(); - const ClassDef *cd=md->getClassDef(); - - //cout << "found link with same name: " << fd->fileName() << " " << memberName; - //if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl; + // all found functions with given name + for (const auto &md : *mn) + { + const FileDef *fd=md->getFileDef(); + const GroupDef *gd=md->getGroupDef(); + const ClassDef *cd=md->getClassDef(); - if ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) - { - const NamespaceDef *nspace= md->getNamespaceDef(); + //cout << "found link with same name: " << fd->fileName() << " " << memberName; + //if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl; - if (nspace == 0) - { // found function in global scope - if(cd == 0) { // Skip if bound to type - return TRUE; + if ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) + { + const NamespaceDef *nspace= md->getNamespaceDef(); + + if (nspace == 0) + { // found function in global scope + if(cd == 0) + { // Skip if bound to type + return md.get(); + } + } + else if (moduleName == nspace->name()) + { // found in local scope + return md.get(); + } + else + { // else search in used modules + QCString usedModuleName= nspace->name(); + UseEntry *ue= usedict->find(usedModuleName); + if (ue) + { + // check if only-list exists and if current entry exists is this list + QCStringList &only= ue->onlyNames; + if (only.isEmpty()) + { + //cout << " found in module " << usedModuleName << " entry " << memberName << endl; + return md.get(); // whole module used + } + else + { + for ( QCStringList::Iterator lit = only.begin(); lit != only.end(); ++lit) + { + //cout << " search in only: " << usedModuleName << ":: " << memberName << "==" << (*it)<< endl; + if (memberName == *lit) + { + return md.get(); // found in ONLY-part of use list + } } - } - else if (moduleName == nspace->name()) - { // found in local scope - return TRUE; - } - else - { // else search in used modules - QCString moduleName= nspace->name(); - UseEntry *ue= usedict->find(moduleName); - if (ue) - { - // check if only-list exists and if current entry exists is this list - QCStringList &only= ue->onlyNames; - if (only.isEmpty()) - { - //cout << " found in module " << moduleName << " entry " << memberName << endl; - return TRUE; // whole module used - } - else - { - for ( QCStringList::Iterator it = only.begin(); it != only.end(); ++it) - { - //cout << " search in only: " << moduleName << ":: " << memberName << "==" << (*it)<< endl; - if (memberName == *it) - { - return TRUE; // found in ONLY-part of use list - } - } - } - } - } - } // if linkable - } // for + } + } + } + } // if linkable + } // for } - return FALSE; + return nullptr; } /** gets the link to a generic procedure which depends not on the name, but on the parameter list @todo implementation */ -static bool getGenericProcedureLink(const ClassDef *cd, - const char *memberText, - CodeOutputInterface &ol) +static bool getGenericProcedureLink(const ClassDef *cd, + const char *memberText, + CodeOutputInterface &ol) { (void)cd; (void)memberText; @@ -529,8 +542,8 @@ static bool getLink(UseSDict *usedict, // dictionary with used modules MemberDef *md=0; QCString memberName= removeRedundantWhiteSpace(memberText); - if (getFortranDefs(memberName, currentModule, md, usedict) && md->isLinkable()) - { + if ((md=getFortranDefs(memberName, currentModule, usedict)) && md->isLinkable()) + { if (md->isVariable() && (md->getLanguage()!=SrcLangExt_Fortran)) return FALSE; // Non Fortran variables aren't handled yet, // see also linkifyText in util.cpp @@ -539,15 +552,15 @@ static bool getLink(UseSDict *usedict, // dictionary with used modules if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { - if (g_currentDefinition && g_currentMemberDef && + if (g_currentDefinition && g_currentMemberDef && md!=g_currentMemberDef && g_insideBody && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,md); - } + { + addDocCrossReference(g_currentMemberDef,md); + } writeMultiLineCodeLink(ol,md,text ? text : memberText); addToSearchIndex(text ? text : memberText); return TRUE; - } + } } return FALSE; } @@ -559,16 +572,16 @@ static void generateLink(CodeOutputInterface &ol, char *lname) NamespaceDef *nsd=0; QCString tmp = lname; tmp = removeRedundantWhiteSpace(tmp.lower()); - + // check if lowercase lname is a linkable type or interface if ( (getFortranTypeDefs(tmp, currentModule, cd, useMembers)) && cd->isLinkable() ) { if ( (cd->compoundType() == ClassDef::Class) && // was Entry::INTERFACE_SEC) && - (getGenericProcedureLink(cd, tmp, ol)) ) + (getGenericProcedureLink(cd, tmp, ol)) ) { - //cout << "=== generic procedure resolved" << endl; - } - else + //cout << "=== generic procedure resolved" << endl; + } + else { // write type or interface link writeMultiLineCodeLink(ol,cd,tmp); addToSearchIndex(tmp.data()); @@ -581,11 +594,11 @@ static void generateLink(CodeOutputInterface &ol, char *lname) addToSearchIndex(tmp.data()); } // check for function/variable - else if (getLink(useMembers, tmp, ol, tmp)) + else if (getLink(useMembers, tmp, ol, tmp)) { //cout << "=== found link for lowercase " << lname << endl; } - else + else { // nothing found, just write out the word //startFontClass("charliteral"); //test @@ -601,23 +614,23 @@ static int countLines() const char *p=g_inputString; char c; int count=1; - while ((c=*p)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; } - if (p>g_inputString && *(p-1)!='\n') + if (p>g_inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. - count++, - g_needsTermination=TRUE; - } + count++, + g_needsTermination=TRUE; + } return count; } //---------------------------------------------------------------------------- /** start scope */ -static void startScope() +static void startScope() { DBG_CTX((stderr, "===> startScope %s",yytext)); Scope *scope = new Scope; @@ -625,36 +638,37 @@ static void startScope() } /** end scope */ -static void endScope() +static void endScope() { DBG_CTX((stderr,"===> endScope %s",yytext)); - if (scopeStack.isEmpty()) + if (scopeStack.isEmpty()) { - DBG_CTX((stderr,"WARNING: fortrancode.l: stack empty!\n")); + DBG_CTX((stderr,"WARNING: fortrancode.l: stack empty!\n")); return; } Scope *scope = scopeStack.getLast(); scopeStack.removeLast(); - for ( QCStringList::Iterator it = scope->useNames.begin(); it != scope->useNames.end(); ++it) + for ( QCStringList::Iterator it = scope->useNames.begin(); it != scope->useNames.end(); ++it) { useMembers->remove(*it); } delete scope; } -static void addUse(const QCString &moduleName) +static void addUse(const QCString &moduleName) { if (!scopeStack.isEmpty()) scopeStack.getLast()->useNames.append(moduleName); } -static void addLocalVar(const QCString &varName) +static void addLocalVar(const QCString &varName) { if (!scopeStack.isEmpty()) { - scopeStack.getLast()->localVars.insert(varName, (void*)1); - if (g_isExternal) scopeStack.getLast()->externalVars.insert(varName, (void*)1); + std::string lowVarName = varName.lower().str(); + scopeStack.getLast()->localVars.insert(lowVarName); + if (g_isExternal) scopeStack.getLast()->externalVars.insert(lowVarName); } } @@ -664,15 +678,15 @@ static void addLocalVar(const QCString &varName) #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -static int yyread(char *buf,int max_size) +static yy_size_t yyread(char *buf,yy_size_t max_size) { - int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; + yy_size_t c=0; + while( c < max_size && g_inputString[g_inputPosition] ) + { + *buf = g_inputString[g_inputPosition++] ; + c++; buf++; + } + return c; } %} @@ -740,7 +754,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") codifyLines(yytext); } /*-------- inner construct ---------------------------------------------------*/ - + <Start>{COMMANDS}/{BS}[,( \t\n] { // highlight /* font class is defined e.g. in doxygen.css */ startFontClass("keyword"); @@ -771,8 +785,8 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") codifyLines(yytext); endFontClass(); } -<Start>"implicit"{BS}("none"|{TYPE_SPEC}) { - startFontClass("keywordtype"); +<Start>"implicit"{BS}("none"|{TYPE_SPEC}) { + startFontClass("keywordtype"); codifyLines(yytext); endFontClass(); } @@ -782,20 +796,20 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") endFontClass(); } /*-------- use statement -------------------------------------------*/ -<Start>"use"{BS_} { - startFontClass("keywordtype"); +<Start>"use"{BS_} { + startFontClass("keywordtype"); codifyLines(yytext); endFontClass(); yy_push_state(YY_START); - BEGIN(Use); + BEGIN(Use); } <Use>"ONLY" { // TODO: rename - startFontClass("keywordtype"); + startFontClass("keywordtype"); codifyLines(yytext); endFontClass(); yy_push_state(YY_START); - BEGIN(UseOnly); - } + BEGIN(UseOnly); + } <Use>{ID} { QCString tmp = yytext; tmp = tmp.lower(); @@ -811,7 +825,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") useEntry->module = tmp; useMembers->append(tmp, useEntry); addUse(tmp); - } + } <Use,UseOnly,Import>{BS},{BS} { codifyLines(yytext); } <UseOnly,Import>{BS}&{BS}"\n" { codifyLines(yytext); g_contLineNr++; @@ -849,11 +863,11 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") /*-------- fortran module -----------------------------------------*/ <Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { // startScope(); - startFontClass("keyword"); + startFontClass("keyword"); codifyLines(yytext); endFontClass(); yy_push_state(YY_START); - BEGIN(ClassName); + BEGIN(ClassName); if (!qstricmp(yytext,"module")) currentModule="module"; } <Start>("enum")/{BS_}|{BS}{COMMA}{BS}{LANGUAGE_BIND_SPEC}|\n { // @@ -914,7 +928,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") startFontClass("keyword"); codifyLines(yytext); endFontClass(); - } + } <Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found startFontClass("keyword"); codifyLines(yytext); @@ -932,7 +946,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") codifyLines(yytext); endFontClass(); } -<Subprog>"("[^)]*")" { // ignore rest of line +<Subprog>"("[^)]*")" { // ignore rest of line codifyLines(yytext); } <Subprog,Subprogend>"\n" { codifyLines(yytext); @@ -968,7 +982,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") g_code->codify(yytext); endFontClass(); } -<Start>{TYPE_SPEC}/[,:( ] { +<Start>{TYPE_SPEC}/[,:( ] { QCString typ = yytext; typ = removeRedundantWhiteSpace(typ.lower()); if (typ.startsWith("real")) YY_FTN_REJECT; @@ -979,7 +993,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") g_code->codify(yytext); endFontClass(); } -<Start>{ATTR_SPEC} { +<Start>{ATTR_SPEC} { if (QCString(yytext) == "external") { yy_push_state(YY_START); @@ -1041,7 +1055,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") if (!g_isFixedForm) { yy_push_state(YY_START); - BEGIN(DeclContLine); + BEGIN(DeclContLine); } } <DeclContLine>"\n" { // declaration not yet finished @@ -1115,7 +1129,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") g_contLineNr++; yy_old_start = 0; yy_my_start = 1; - yy_end = yyleng; + yy_end = static_cast<int>(yyleng); } // Actually we should see if ! on position 6, can be continuation // but the chance is very unlikely, so no effort to solve it here @@ -1136,10 +1150,10 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") g_contLineNr++; yy_old_start = 0; yy_my_start = 1; - yy_end = yyleng; + yy_end = static_cast<int>(yyleng); // Actually we should see if ! on position 6, can be continuation // but the chance is very unlikely, so no effort to solve it here - docBlock+=yytext; + docBlock+=yytext; } <DocBlock>"\n" { // comment block ends at the end of this line // remove special comment (default config) @@ -1193,7 +1207,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") endFontClass(); } - /*------ preprocessor --------------------------------------------*/ + /*------ preprocessor --------------------------------------------*/ <Start>"#".*\n { if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT; g_contLineNr++; @@ -1202,35 +1216,35 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") endFontClass(); YY_FTN_RESET } - /*------ variable references? -------------------------------------*/ + /*------ variable references? -------------------------------------*/ -<Start>"%"{BS}{ID} { // ignore references to elements +<Start>"%"{BS}{ID} { // ignore references to elements g_code->codify(yytext); } -<Start>{ID} { +<Start>{ID} { g_insideBody=TRUE; generateLink(*g_code, yytext); g_insideBody=FALSE; } - /*------ strings --------------------------------------------------*/ + /*------ strings --------------------------------------------------*/ <String>\n { // string with \n inside g_contLineNr++; - str+=yytext; + g_str+=yytext; startFontClass("stringliteral"); - codifyLines(str); + codifyLines(g_str); endFontClass(); - str = ""; + g_str = ""; YY_FTN_RESET - } -<String>\"|\' { // string ends with next quote without previous backspace + } +<String>\"|\' { // string ends with next quote without previous backspace if(yytext[0]!=stringStartSymbol) YY_FTN_REJECT; // single vs double quote - str+=yytext; + g_str+=yytext; startFontClass("stringliteral"); - codifyLines(str); + codifyLines(g_str); endFontClass(); yy_pop_state(); - } -<String>. {str+=yytext;} + } +<String>. {g_str+=yytext;} <*>\"|\' { /* string starts */ /* if(YY_START == StrIgnore) YY_FTN_REJECT; // ignore in simple comments */ @@ -1238,7 +1252,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") yy_push_state(YY_START); stringStartSymbol=yytext[0]; // single or double quote BEGIN(String); - str=yytext; + g_str=yytext; } /*-----------------------------------------------------------------------------*/ @@ -1258,7 +1272,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") } <*>^{BS}"type"{BS}"=" { g_code->codify(yytext); } -<*>. { +<*>. { if (g_isFixedForm && yy_my_start > fixedCommentAfter) { //yy_push_state(YY_START); @@ -1301,7 +1315,6 @@ const char* prepassFixedForm(const char* contents, int *hasContLine); /* prototy static void checkContLines(const char *s) { int numLines = 0; - int curLine = 0; int i = 0; const char *p = s; @@ -1319,7 +1332,7 @@ static void checkContLines(const char *s) g_hasContLine[0] = 0; } -void parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s, +void parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s, bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, const MemberDef *,bool,const Definition *searchCtx, @@ -1353,7 +1366,7 @@ void parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s, else g_inputLines = g_yyLineNr + countLines() - 1; - g_exampleBlock = exBlock; + g_exampleBlock = exBlock; g_exampleName = exName; g_sourceFileDef = fd; if (exBlock && fd==0) @@ -1361,7 +1374,7 @@ void parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s, // create a dummy filedef for the example g_sourceFileDef = createFileDef("",exName); } - if (g_sourceFileDef) + if (g_sourceFileDef) { setCurrentDoc("l00001"); } @@ -1425,4 +1438,6 @@ void FortranCodeParser::resetCodeParserState() //--------------------------------------------------------- +#if USE_STATE2STRING #include "fortrancode.l.h" +#endif diff --git a/src/fortranscanner.h b/src/fortranscanner.h index 7a13f47..0e67bb2 100644 --- a/src/fortranscanner.h +++ b/src/fortranscanner.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -27,19 +27,18 @@ class FortranOutlineParser : public OutlineParserInterface { public: - FortranOutlineParser(FortranFormat format=FortranFormat_Unknown) : m_format(format) { } - void startTranslationUnit(const char *) {} - void finishTranslationUnit() {} + FortranOutlineParser(FortranFormat format=FortranFormat_Unknown); + ~FortranOutlineParser(); void parseInput(const char *fileName, const char *fileBuf, const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList &filesInSameTranslationUnit); + ClangTUParser *clangParser); bool needsPreprocessing(const QCString &extension) const; void parsePrototype(const char *text); private: - FortranFormat m_format; + struct Private; + std::unique_ptr<Private> p; }; class FortranOutlineParserFree : public FortranOutlineParser diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 08c7a6a..cf48a3e 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -21,8 +21,8 @@ * - Consider using startScope(), endScope() functions with module, program, * subroutine or any other scope in fortran program. * - * - Symbol modifiers (attributes) are collected using SymbolModifiers |= operator during - * substructure parsing. When substructure ends all modifiers are applied to actual + * - Symbol yyextra->modifiers (attributes) are collected using SymbolModifiers |= operator during + * substructure parsing. When substructure ends all yyextra->modifiers are applied to actual * entries in applyModifiers() functions. * * - How case insensitiveness should be handled in code? @@ -35,11 +35,16 @@ * "functionA" or "MyInterface". So constructs like '(^|[ \t])interface({BS_}{ID})?/[ \t\n]' * are desired. * - * - Must track yyLineNr when using REJECT, unput() or similar commands. + * - Must track yyextra->lineNr when using REJECT, unput() or similar commands. */ %option never-interactive %option case-insensitive %option prefix="fortranscannerYY" +%option reentrant +%option extra-type="struct fortranscannerYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -63,10 +68,12 @@ #include "defargs.h" #include "language.h" #include "commentscan.h" -#include "fortrancode.h" #include "pre.h" #include "arguments.h" #include "debug.h" +#include "markdown.h" + +const int fixedCommentAfter = 72; // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -79,12 +86,13 @@ enum ScanVar { V_IGNORE, V_VARIABLE, V_PARAMETER, V_RESULT}; enum InterfaceType { IF_NONE, IF_SPECIFIC, IF_GENERIC, IF_ABSTRACT }; // {{{ ----- Helper structs ----- -//! Holds modifiers (ie attributes) for one symbol (variable, function, etc) -struct SymbolModifiers { +//! Holds yyextra->modifiers (ie attributes) for one symbol (variable, function, etc) +struct SymbolModifiers +{ enum Protection {NONE_P, PUBLIC, PRIVATE}; enum Direction {NONE_D, IN, OUT, INOUT}; - //!< This is only used with function return value. + //! This is only used with function return value. QCString type, returnName; Protection protection; Direction direction; @@ -132,115 +140,108 @@ static const char *directionParam[] = // }}} -/* ----------------------------------------------------------------- - * - * statics - */ -static OutlineParserInterface *g_thisParser; -static const char * inputString; -static int inputPosition; -static bool isFixedForm; -static QCString inputStringPrepass; ///< Input string for prepass of line cont. '&' -static QCString inputStringSemi; ///< Input string after command separator ';' -static unsigned int inputPositionPrepass; -static int lineCountPrepass = 0; - -static std::vector< std::shared_ptr<Entry> > subrCurrent; - -struct CommentInPrepass { +struct CommentInPrepass +{ int column; QCString str; - CommentInPrepass(int column, QCString str) : column(column), str(str) {} + CommentInPrepass(int col, QCString s) : column(col), str(s) {} }; -static QList<CommentInPrepass> comments; - -YY_BUFFER_STATE *include_stack = NULL; -int include_stack_ptr = 0; -int include_stack_cnt = 0; - -static QFile inputFile; -static QCString yyFileName; -static int yyLineNr = 1 ; -static int yyColNr = 0 ; -static Entry *current_root = 0; -static Entry *global_scope = 0; -static std::shared_ptr<Entry> global_root; -static std::shared_ptr<Entry> file_root; -static std::shared_ptr<Entry> last_entry; -static std::shared_ptr<Entry> last_enum; -static std::shared_ptr<Entry> current; -static ScanVar v_type = V_IGNORE; // type of parsed variable -static std::vector<std::shared_ptr<Entry> > moduleProcedures; // list of all interfaces which contain unresolved - // module procedures -static QCString docBlock; -static bool docBlockInBody = FALSE; -static bool docBlockJavaStyle; - -static MethodTypes mtype; -static bool gstat; -static Specifier virt; - -static QCString debugStr; -static QCString result; // function result -static Argument *parameter; // element of parameter list -static QCString argType; // fortran type of an argument of a parameter list -static QCString argName; // last identifier name in variable list -static QCString initializer; // initial value of a variable -static int initializerArrayScope; // number if nested array scopes in initializer -static int initializerScope; // number if nested function calls in initializer -static QCString useModuleName; // name of module in the use statement -static Protection defaultProtection; -static Protection typeProtection; -static int typeMode = false; -static InterfaceType ifType = IF_NONE; -static bool functionLine = FALSE; - -static char stringStartSymbol; // single or double quote -static bool parsingPrototype = FALSE; // see parsePrototype() + +/* ----------------------------------------------------------------- + * + * statics + */ + +struct fortranscannerYY_state +{ + OutlineParserInterface * thisParser; + CommentScanner commentScanner; + const char * inputString; + int inputPosition; + bool isFixedForm; + QCString inputStringPrepass; ///< Input string for prepass of line cont. '&' + QCString inputStringSemi; ///< Input string after command separator ';' + unsigned int inputPositionPrepass; + int lineCountPrepass = 0; + EntryList subrCurrent; + QList<CommentInPrepass> comments; + YY_BUFFER_STATE * includeStack = NULL; + int includeStackPtr = 0; + int includeStackCnt = 0; + QCString fileName; + int lineNr = 1 ; + int colNr = 0 ; + Entry *current_root = 0; + Entry *global_scope = 0; + std::shared_ptr<Entry> global_root; + std::shared_ptr<Entry> file_root; + std::shared_ptr<Entry> last_entry; + std::shared_ptr<Entry> last_enum; + std::shared_ptr<Entry> current; + ScanVar vtype = V_IGNORE; // type of parsed variable + EntryList moduleProcedures; // list of all interfaces which contain unresolved module procedures + QCString docBlock; + bool docBlockInBody = FALSE; + bool docBlockJavaStyle; + QCString debugStr; +// Argument *parameter; // element of parameter list + QCString argType; // fortran type of an argument of a parameter list + QCString argName; // last identifier name in variable list + QCString initializer; // initial value of a variable + int initializerArrayScope; // number if nested array scopes in initializer + int initializerScope; // number if nested function calls in initializer + QCString useModuleName; // name of module in the use statement + Protection defaultProtection; + Protection typeProtection; + bool typeMode = false; + InterfaceType ifType = IF_NONE; + bool functionLine = FALSE; + char stringStartSymbol; // single or double quote + bool parsingPrototype = FALSE; // see parsePrototype() //! Accumulated modifiers of current statement, eg variable declaration. -static SymbolModifiers currentModifiers; + SymbolModifiers currentModifiers; //! Holds program scope->symbol name->symbol modifiers. -static QMap<Entry*,QMap<QCString,SymbolModifiers> > modifiers; + QMap<Entry*,QMap<QCString,SymbolModifiers> > modifiers; + int anonCount = 0 ; +}; -static int anonCount = 0 ; //----------------------------------------------------------------------------- - -static int yyread(char *buf,int max_size); -static void startCommentBlock(bool); -static void handleCommentBlock(const QCString &doc,bool brief); -static void subrHandleCommentBlock(const QCString &doc,bool brief); -static void subrHandleCommentBlockResult(const QCString &doc,bool brief); -static void addCurrentEntry(bool case_insens); -static void addModule(const char *name, bool isModule=FALSE); -static void addSubprogram(const char *text); -static void addInterface(QCString name, InterfaceType type); -static Argument *getParameter(const QCString &name); -static void scanner_abort(); - -static void startScope(Entry *scope); -static bool endScope(Entry *scope, bool isGlobalRoot=FALSE); -//static bool isTypeName(QCString name); -static void resolveModuleProcedures(Entry *current_root); static int getAmpersandAtTheStart(const char *buf, int length); static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch); -static void truncatePrepass(int index); -static void pushBuffer(QCString &buffer); -static void popBuffer(); -//static void extractPrefix(QCString& text); static QCString extractFromParens(const QCString name); static QCString extractBind(const QCString name); -static CommentInPrepass* locatePrepassComment(int from, int to); -static void updateVariablePrepassComment(int from, int to); -static void newLine(); -static void initEntry(); + + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void startCommentBlock(yyscan_t yyscanner,bool); +static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief); +static void subrHandleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief); +static void subrHandleCommentBlockResult(yyscan_t yyscanner,const QCString &doc,bool brief); +static void addCurrentEntry(yyscan_t yyscanner,bool case_insens); +static void addModule(yyscan_t yyscanner,const char *name, bool isModule=FALSE); +static void addSubprogram(yyscan_t yyscanner,const char *text); +static void addInterface(yyscan_t yyscanner,QCString name, InterfaceType type); +static Argument *getParameter(yyscan_t yyscanner,const QCString &name); +static void scanner_abort(yyscan_t yyscanner); + +static void startScope(yyscan_t yyscanner,Entry *scope); +static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot=FALSE); +static void resolveModuleProcedures(yyscan_t yyscanner,Entry *current_root); +static void truncatePrepass(yyscan_t yyscanner,int index); +static void pushBuffer(yyscan_t yyscanner,QCString &buffer); +static void popBuffer(yyscan_t yyscanner); +static CommentInPrepass* locatePrepassComment(yyscan_t yyscanner,int from, int to); +static void updateVariablePrepassComment(yyscan_t yyscanner,int from, int to); +static void newLine(yyscan_t yyscanner); +static void initEntry(yyscan_t yyscanner); static const char *stateToString(int state); //----------------------------------------------------------------------------- -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -#define YY_USER_ACTION yyColNr+=(int)yyleng; +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +#define YY_USER_ACTION yyextra->colNr+=(int)yyleng; #define INVALID_ENTRY ((Entry*)0x8) //----------------------------------------------------------------------------- @@ -248,7 +249,7 @@ static const char *stateToString(int state); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -IDSYM [a-z_A-Z0-9] +IDSYM [a-z_A-Z0-9] NOTIDSYM [^a-z_A-Z0-9] SEPARATE [:, \t] ID [a-z_A-Z%]+{IDSYM}* @@ -294,18 +295,18 @@ SCOPENAME ({ID}{BS}"::"{BS})* //--------------------------------------------------------------------------------- /** fortran parsing states */ -%x Subprog -%x SubprogPrefix -%x Parameterlist -%x SubprogBody -%x SubprogBodyContains -%x Start -%x Comment +%x Subprog +%x SubprogPrefix +%x Parameterlist +%x SubprogBody +%x SubprogBodyContains +%x Start +%x Comment %x Module %x Program %x ModuleBody -%x ModuleBodyContains -%x AttributeList +%x ModuleBodyContains +%x AttributeList %x Variable %x Initialization %x ArrayInitializer @@ -323,289 +324,328 @@ SCOPENAME ({ID}{BS}"::"{BS})* %x Prepass /** comment parsing states */ -%x DocBlock -%x DocBackLine -%x EndDoc +%x DocBlock +%x DocBackLine +%x EndDoc %x BlockData /** prototype parsing */ -%x Prototype -%x PrototypeSubprog -%x PrototypeArgs +%x Prototype +%x PrototypeSubprog +%x PrototypeArgs %% /*-----------------------------------------------------------------------------------*/ <Prepass>^{BS}[&]*{BS}!.*\n { /* skip lines with just comment. Note code was in free format or has been converted to it */ - lineCountPrepass ++; + yyextra->lineCountPrepass ++; } <Prepass>^{BS}\n { /* skip empty lines */ - lineCountPrepass ++; + yyextra->lineCountPrepass ++; } <*>^.*\n { // prepass: look for line continuations - functionLine = FALSE; + yyextra->functionLine = FALSE; DBG_CTX((stderr, "---%s", yytext)); - int indexStart = getAmpersandAtTheStart(yytext, (int)yyleng); - int indexEnd = getAmpOrExclAtTheEnd(yytext, (int)yyleng, '\0'); - if (indexEnd>=0 && yytext[indexEnd]!='&') //we are only interested in amp - indexEnd=-1; + int indexStart = getAmpersandAtTheStart(yytext, (int)yyleng); + int indexEnd = getAmpOrExclAtTheEnd(yytext, (int)yyleng, '\0'); + if (indexEnd>=0 && yytext[indexEnd]!='&') //we are only interested in amp + { + indexEnd=-1; + } - if(indexEnd<0){ // ----- no ampersand as line continuation - if(YY_START == Prepass) { // last line in "continuation" + if (indexEnd<0) + { // ----- no ampersand as line continuation + if (YY_START == Prepass) + { // last line in "continuation" - // Only take input after initial ampersand - inputStringPrepass+=(const char*)(yytext+(indexStart+1)); - - //printf("BUFFER:%s\n", (const char*)inputStringPrepass); - pushBuffer(inputStringPrepass); - yyColNr = 0; - yy_pop_state(); - } else { // simple line - yyColNr = 0; - REJECT; - } - - } else { // ----- line with continuation - if(YY_START != Prepass) { - comments.setAutoDelete(TRUE); - comments.clear(); - yy_push_state(Prepass); - } + // Only take input after initial ampersand + yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1)); + + //printf("BUFFER:%s\n", (const char*)yyextra->inputStringPrepass); + pushBuffer(yyscanner,yyextra->inputStringPrepass); + yyextra->colNr = 0; + yy_pop_state(yyscanner); + } + else + { // simple line + yyextra->colNr = 0; + REJECT; + } + } + else + { // ----- line with continuation + if (YY_START != Prepass) + { + yyextra->comments.setAutoDelete(TRUE); + yyextra->comments.clear(); + yy_push_state(Prepass,yyscanner); + } - int length = inputStringPrepass.length(); + int length = yyextra->inputStringPrepass.length(); - // Only take input after initial ampersand - inputStringPrepass+=(const char*)(yytext+(indexStart+1)); - lineCountPrepass ++; - - // cut off & and remove following comment if present - truncatePrepass(length+indexEnd-(indexStart+1)); - } + // Only take input after initial ampersand + yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1)); + yyextra->lineCountPrepass ++; + // cut off & and remove following comment if present + truncatePrepass(yyscanner,length+indexEnd-(indexStart+1)); + } } /*------ ignore strings that are not initialization strings */ <String>\"|\' { // string ends with next quote without previous backspace - if (yytext[0]!=stringStartSymbol) { yyColNr -= (int)yyleng; REJECT; } // single vs double quote - if (yy_top_state() == Initialization - || yy_top_state() == ArrayInitializer) - initializer+=yytext; - yy_pop_state(); - } -<String>. { if (yy_top_state() == Initialization - || yy_top_state() == ArrayInitializer) - initializer+=yytext; - } + if (yytext[0]!=yyextra->stringStartSymbol) + { + yyextra->colNr -= (int)yyleng; + REJECT; + } // single vs double quote + if (yy_top_state(yyscanner) == Initialization || + yy_top_state(yyscanner) == ArrayInitializer) + { + yyextra->initializer+=yytext; + } + yy_pop_state(yyscanner); + } +<String>. { if (yy_top_state(yyscanner) == Initialization || + yy_top_state(yyscanner) == ArrayInitializer) + { + yyextra->initializer+=yytext; + } + } <*>\"|\' { /* string starts */ - if (YY_START == StrIgnore) { yyColNr -= (int)yyleng; REJECT; }; // ignore in simple comments - yy_push_state(YY_START); - if (yy_top_state() == Initialization - || yy_top_state() == ArrayInitializer) - initializer+=yytext; - stringStartSymbol=yytext[0]; // single or double quote + if (YY_START == StrIgnore) + { yyextra->colNr -= (int)yyleng; + REJECT; + }; // ignore in simple yyextra->comments + yy_push_state(YY_START,yyscanner); + if (yy_top_state(yyscanner) == Initialization || + yy_top_state(yyscanner) == ArrayInitializer) + { + yyextra->initializer+=yytext; + } + yyextra->stringStartSymbol=yytext[0]; // single or double quote BEGIN(String); } - /*------ ignore simple comment (not documentation comments) */ + /*------ ignore simple comment (not documentation yyextra->comments) */ -<*>"!"/[^<>\n] { if (YY_START == String) { yyColNr -= (int)yyleng; REJECT; } // "!" is ignored in strings - // skip comment line (without docu comments "!>" "!<" ) - /* ignore further "!" and ignore comments in Strings */ +<*>"!"/[^<>\n] { if (YY_START == String) + { yyextra->colNr -= (int)yyleng; + REJECT; + } // "!" is ignored in strings + // skip comment line (without docu yyextra->comments "!>" "!<" ) + /* ignore further "!" and ignore yyextra->comments in Strings */ if ((YY_START != StrIgnore) && (YY_START != String)) - { - yy_push_state(YY_START); + { + yy_push_state(YY_START,yyscanner); BEGIN(StrIgnore); - debugStr="*!"; - DBG_CTX((stderr,"start comment %d\n",yyLineNr)); + yyextra->debugStr="*!"; + DBG_CTX((stderr,"start comment %d\n",yyextra->lineNr)); } } -<StrIgnore>.?/\n { yy_pop_state(); // comment ends with endline character - DBG_CTX((stderr,"end comment %d %s\n",yyLineNr,debugStr.data())); +<StrIgnore>.?/\n { yy_pop_state(yyscanner); // comment ends with endline character + DBG_CTX((stderr,"end comment %d %s\n",yyextra->lineNr,yyextra->debugStr.data())); } // comment line ends -<StrIgnore>. { debugStr+=yytext; } +<StrIgnore>. { yyextra->debugStr+=yytext; } /*------ use handling ------------------------------------------------------------*/ <Start,ModuleBody,SubprogBody>"use"{BS_} { - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(Use); + yy_push_state(Use,yyscanner); } <Use>{ID} { DBG_CTX((stderr,"using dir %s\n",yytext)); - current->name=yytext; - current->fileName = yyFileName; - current->section=Entry::USINGDIR_SEC; - current_root->moveToSubEntryAndRefresh(current); - current->lang = SrcLangExt_Fortran; - yy_pop_state(); + yyextra->current->name=yytext; + yyextra->current->name=yyextra->current->name.lower(); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current->lang = SrcLangExt_Fortran; + yy_pop_state(yyscanner); } <Use>{ID}/, { - useModuleName=yytext; + yyextra->useModuleName=yytext; + yyextra->useModuleName=yyextra->useModuleName.lower(); } <Use>,{BS}"ONLY" { BEGIN(UseOnly); } <UseOnly>{BS},{BS} {} <UseOnly>{ID} { - current->name= useModuleName+"::"+yytext; - current->fileName = yyFileName; - current->section=Entry::USINGDECL_SEC; - current_root->moveToSubEntryAndRefresh(current); - current->lang = SrcLangExt_Fortran; - } + yyextra->current->name= yyextra->useModuleName+"::"+yytext; + yyextra->current->name=yyextra->current->name.lower(); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current->lang = SrcLangExt_Fortran; + } <Use,UseOnly>"\n" { - yyColNr -= 1; + yyextra->colNr -= 1; unput(*yytext); - yy_pop_state(); + yy_pop_state(yyscanner); } /* INTERFACE definitions */ <Start,ModuleBody,SubprogBody>{ -^{BS}interface{IDSYM}+ { /* variable with interface prefix */ } -^{BS}interface { ifType = IF_SPECIFIC; - yy_push_state(InterfaceBody); +^{BS}interface{IDSYM}+ { /* variable with interface prefix */ } +^{BS}interface { yyextra->ifType = IF_SPECIFIC; + yy_push_state(InterfaceBody,yyscanner); // do not start a scope here, every // interface body is a scope of its own } -^{BS}abstract{BS_}interface { ifType = IF_ABSTRACT; - yy_push_state(InterfaceBody); +^{BS}abstract{BS_}interface { yyextra->ifType = IF_ABSTRACT; + yy_push_state(InterfaceBody,yyscanner); // do not start a scope here, every // interface body is a scope of its own } -^{BS}interface{BS_}{ID}{ARGS}? { ifType = IF_GENERIC; - current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. - yy_push_state(InterfaceBody); +^{BS}interface{BS_}{ID}{ARGS}? { yyextra->ifType = IF_GENERIC; + yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. + yy_push_state(InterfaceBody,yyscanner); // extract generic name QCString name = QCString(yytext).stripWhiteSpace(); name = name.right(name.length() - 9).stripWhiteSpace().lower(); - addInterface(name, ifType); - startScope(last_entry.get()); + addInterface(yyscanner,name, yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); } } <InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? { // end scope only if GENERIC interface - if (ifType == IF_GENERIC) last_entry->parent()->endBodyLine = yyLineNr - 1; - if (ifType == IF_GENERIC && !endScope(current_root)) + if (yyextra->ifType == IF_GENERIC) + { + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1; + } + if (yyextra->ifType == IF_GENERIC && !endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - - ifType = IF_NONE; - yy_pop_state(); + } + yyextra->ifType = IF_NONE; + yy_pop_state(yyscanner); } -<InterfaceBody>module{BS}procedure { yy_push_state(YY_START); +<InterfaceBody>module{BS}procedure { yy_push_state(YY_START,yyscanner); BEGIN(ModuleProcedure); } -<ModuleProcedure>{ID} { if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) +<ModuleProcedure>{ID} { if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) { - addInterface(yytext, ifType); - startScope(last_entry.get()); + addInterface(yyscanner,yytext, yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); } - current->section = Entry::FUNCTION_SEC ; - current->name = yytext; - moduleProcedures.push_back(current); - addCurrentEntry(true); + yyextra->current->section = Entry::FUNCTION_SEC ; + yyextra->current->name = yytext; + yyextra->moduleProcedures.push_back(yyextra->current); + addCurrentEntry(yyscanner,true); } -<ModuleProcedure>"\n" { yyColNr -= 1; - unput(*yytext); - yy_pop_state(); +<ModuleProcedure>"\n" { yyextra->colNr -= 1; + unput(*yytext); + yy_pop_state(yyscanner); } <InterfaceBody>. {} /*-- Contains handling --*/ -<Start>^{BS}{CONTAINS}/({BS}|\n|!|;) { - if(YY_START == Start) +<Start>^{BS}{CONTAINS}/({BS}|\n|!|;) { + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBodyContains); //anon program - } + addModule(yyscanner,NULL); + yy_push_state(ModuleBodyContains,yyscanner); //anon program + } } <ModuleBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(ModuleBodyContains); } <SubprogBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(SubprogBodyContains); } <TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(TypedefBodyContains); } /*------ module handling ------------------------------------------------------------*/ -<Start>block{BS}data{BS}{ID_} { // - v_type = V_IGNORE; - yy_push_state(BlockData); - defaultProtection = Public; - } -<Start>module|program{BS_} { // - v_type = V_IGNORE; - if(yytext[0]=='m' || yytext[0]=='M') - yy_push_state(Module); - else - yy_push_state(Program); - defaultProtection = Public; - } +<Start>block{BS}data{BS}{ID_} { // + yyextra->vtype = V_IGNORE; + yy_push_state(BlockData,yyscanner); + yyextra->defaultProtection = Public; + } +<Start>module|program{BS_} { // + yyextra->vtype = V_IGNORE; + if (yytext[0]=='m' || yytext[0]=='M') + { + yy_push_state(Module,yyscanner); + } + else + { + yy_push_state(Program,yyscanner); + } + yyextra->defaultProtection = Public; + } <BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!|;) { // end block data - //if (!endScope(current_root)) - // yyterminate(); - defaultProtection = Public; - yy_pop_state(); - } + //if (!endScope(yyscanner,yyextra->current_root)) + // yyterminate(); + yyextra->defaultProtection = Public; + yy_pop_state(yyscanner); + } <Start,ModuleBody,ModuleBodyContains>"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) { // end module - resolveModuleProcedures(current_root); - if (!endScope(current_root)) - yyterminate(); - defaultProtection = Public; - if (global_scope) + resolveModuleProcedures(yyscanner,yyextra->current_root); + if (!endScope(yyscanner,yyextra->current_root)) + { + yyterminate(); + } + yyextra->defaultProtection = Public; + if (yyextra->global_scope) + { + if (yyextra->global_scope != INVALID_ENTRY) { - if (global_scope != INVALID_ENTRY) - yy_push_state(Start); - else - yy_pop_state(); // cannot pop artrificial entry + yy_push_state(Start,yyscanner); } else { - yy_push_state(Start); - global_scope = INVALID_ENTRY; // signal that the global_scope has already been used. + yy_pop_state(yyscanner); // cannot pop artrificial entry } - } -<Module>{ID} { - addModule(yytext, TRUE); - BEGIN(ModuleBody); - } - + } + else + { + yy_push_state(Start,yyscanner); + yyextra->global_scope = INVALID_ENTRY; // signal that the yyextra->global_scope has already been used. + } + } +<Module>{ID} { + addModule(yyscanner,yytext, TRUE); + BEGIN(ModuleBody); + } <Program>{ID} { - addModule(yytext, FALSE); - BEGIN(ModuleBody); - } + addModule(yyscanner,yytext, FALSE); + BEGIN(ModuleBody); + } /*------- access specification --------------------------------------------------------------------------*/ -<ModuleBody>private/{BS}(\n|"!") { defaultProtection = Private; - current->protection = defaultProtection ; - } -<ModuleBody>public/{BS}(\n|"!") { defaultProtection = Public; - current->protection = defaultProtection ; - } +<ModuleBody>private/{BS}(\n|"!") { yyextra->defaultProtection = Private; + yyextra->current->protection = yyextra->defaultProtection ; + } +<ModuleBody>public/{BS}(\n|"!") { yyextra->defaultProtection = Public; + yyextra->current->protection = yyextra->defaultProtection ; + } /*------- type definition -------------------------------------------------------------------------------*/ -<Start,ModuleBody>^{BS}type/[^a-z0-9_] { - if(YY_START == Start) +<Start,ModuleBody>^{BS}type/[^a-z0-9_] { + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(Typedef); - current->protection = defaultProtection; - typeProtection = defaultProtection; - typeMode = true; + yy_push_state(Typedef,yyscanner); + yyextra->current->protection = yyextra->defaultProtection; + yyextra->typeProtection = yyextra->defaultProtection; + yyextra->typeMode = true; } <Typedef>{ {COMMA} {} @@ -613,100 +653,104 @@ SCOPENAME ({ID}{BS}"::"{BS})* {BS}"::"{BS} {} abstract { - current->spec |= Entry::AbstractClass; + yyextra->current->spec |= Entry::AbstractClass; } extends{ARGS} { QCString basename = extractFromParens(yytext).lower(); - current->extends.push_back(BaseInfo(basename, Public, Normal)); + yyextra->current->extends.push_back(BaseInfo(basename, Public, Normal)); } public { - current->protection = Public; - typeProtection = Public; + yyextra->current->protection = Public; + yyextra->typeProtection = Public; } private { - current->protection = Private; - typeProtection = Private; + yyextra->current->protection = Private; + yyextra->typeProtection = Private; } {LANGUAGE_BIND_SPEC} { /* ignored for now */ } {ID} { /* type name found */ - current->section = Entry::CLASS_SEC; - current->spec |= Entry::Struct; - current->name = yytext; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; - current->startLine = yyLineNr; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec |= Entry::Struct; + yyextra->current->name = yytext; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; + yyextra->current->startLine = yyextra->lineNr; /* if type is part of a module, mod name is necessary for output */ - if (current_root && - (current_root->section == Entry::CLASS_SEC - || current_root->section == Entry::NAMESPACE_SEC)) + if (yyextra->current_root && + (yyextra->current_root->section == Entry::CLASS_SEC || + yyextra->current_root->section == Entry::NAMESPACE_SEC)) { - current->name = current_root->name + "::" + current->name; + yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name; } - addCurrentEntry(true); - startScope(last_entry.get()); + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); BEGIN(TypedefBody); } } <TypedefBodyContains>{ /* Type Bound Procedures */ ^{BS}PROCEDURE{ARGS}? { - current->type = QCString(yytext).simplifyWhiteSpace(); + yyextra->current->type = QCString(yytext).simplifyWhiteSpace(); } ^{BS}final { - current->spec |= Entry::Final; - current->type = QCString(yytext).simplifyWhiteSpace(); + yyextra->current->spec |= Entry::Final; + yyextra->current->type = QCString(yytext).simplifyWhiteSpace(); } ^{BS}generic { - current->type = QCString(yytext).simplifyWhiteSpace(); + yyextra->current->type = QCString(yytext).simplifyWhiteSpace(); } {COMMA} { } {ATTR_SPEC} { - currentModifiers |= QCString(yytext); + yyextra->currentModifiers |= QCString(yytext); } {BS}"::"{BS} { } {ID} { QCString name = yytext; - modifiers[current_root][name.lower()] |= currentModifiers; - current->section = Entry::FUNCTION_SEC; - current->name = name; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; - current->startLine = yyLineNr; - addCurrentEntry(true); + yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->current->section = Entry::FUNCTION_SEC; + yyextra->current->name = name; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; + yyextra->current->startLine = yyextra->lineNr; + addCurrentEntry(yyscanner,true); } {BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */ QCString args = yytext; - last_entry->args = args.lower(); + yyextra->last_entry->args = args.lower(); } "\n" { - currentModifiers = SymbolModifiers(); - newLine(); - docBlock.resize(0); + yyextra->currentModifiers = SymbolModifiers(); + newLine(yyscanner); + yyextra->docBlock.resize(0); } } <TypedefBody,TypedefBodyContains>{ ^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!|;) { /* end type definition */ - last_entry->parent()->endBodyLine = yyLineNr; - if (!endScope(current_root)) + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr; + if (!endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - typeMode = false; - yy_pop_state(); + } + yyextra->typeMode = false; + yy_pop_state(yyscanner); } ^{BS}"end"{BS}/(\n|!|;) { /* incorrect end type definition */ - warn(yyFileName,yyLineNr, "Found 'END' instead of 'END TYPE'"); - last_entry->parent()->endBodyLine = yyLineNr; - if (!endScope(current_root)) + warn(yyextra->fileName,yyextra->lineNr, "Found 'END' instead of 'END TYPE'"); + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr; + if (!endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - typeMode = false; - yy_pop_state(); + } + yyextra->typeMode = false; + yy_pop_state(yyscanner); } } @@ -718,603 +762,594 @@ private { // in a scope of their own, even if multiple // are group in one INTERFACE/END INTERFACE block. // - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) { - endScope(current_root); - last_entry->endBodyLine = yyLineNr - 1; + endScope(yyscanner,yyextra->current_root); + yyextra->last_entry->endBodyLine = yyextra->lineNr - 1; } - current_root->endBodyLine = yyLineNr - 1; + yyextra->current_root->endBodyLine = yyextra->lineNr - 1; - if (!endScope(current_root)) - yyterminate(); - subrCurrent.pop_back(); - yy_pop_state() ; - } + if (!endScope(yyscanner,yyextra->current_root)) + { + yyterminate(); + } + yyextra->subrCurrent.pop_back(); + yy_pop_state(yyscanner) ; + } <BlockData>{ {ID} { } } <Start,ModuleBody,TypedefBody,SubprogBody,Enum>{ ^{BS}{TYPE_SPEC}/{SEPARATE} { - last_enum.reset(); + yyextra->last_enum.reset(); if (YY_START == Enum) { - argType = "@"; // enum marker + yyextra->argType = "@"; // enum marker } else { - argType = QCString(yytext).simplifyWhiteSpace().lower(); + yyextra->argType = QCString(yytext).simplifyWhiteSpace().lower(); } - current->bodyLine = yyLineNr + 1; - current->endBodyLine = yyLineNr + lineCountPrepass; + yyextra->current->bodyLine = yyextra->lineNr + 1; + yyextra->current->endBodyLine = yyextra->lineNr + yyextra->lineCountPrepass; /* variable declaration starts */ - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(AttributeList); - } - /* Dimitri: macro expansion should already be done during preprocessing not here! -^{BS}{PP_ID}{KIND}? { // check for preprocessor symbol expand to type - QCString str = yytext; - str = str.stripWhiteSpace(); - //DefineDict* defines = getGlobalDefineDict(); - QCString name; - int index = str.find("("); - if (index != -1) - name = str.left(index).stripWhiteSpace(); - else - name = str; - - Define *define = 0; //(*defines)[name]; - if (define != 0 && isTypeName(define->definition)) - { - argType = str; - yy_push_state(AttributeList); - } - else - { - yyColNr -= (int)yyleng; - REJECT; - } - } - */ -{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) { + yy_push_state(AttributeList,yyscanner); + } +{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) { /* external can be a "type" or an attribute */ - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } QCString tmp = yytext; - currentModifiers |= tmp.stripWhiteSpace(); - argType = QCString(yytext).simplifyWhiteSpace().lower(); - yy_push_state(AttributeList); - } -{ATTR_STMT}/{BS_}{ID} | -{ATTR_STMT}/{BS}"::" { + yyextra->currentModifiers |= tmp.stripWhiteSpace(); + yyextra->argType = QCString(yytext).simplifyWhiteSpace().lower(); + yy_push_state(AttributeList,yyscanner); + } +{ATTR_STMT}/{BS_}{ID} | +{ATTR_STMT}/{BS}"::" { /* attribute statement starts */ DBG_CTX((stderr,"5=========> Attribute statement: %s\n", yytext)); QCString tmp = yytext; - currentModifiers |= tmp.stripWhiteSpace(); - argType=""; - yy_push_state(YY_START); - BEGIN( AttributeList ) ; - } -{ID} { - } -^{BS}"type"{BS_}"is"/{BT_} { } -^{BS}"type"{BS}"=" { } -^{BS}"class"{BS_}"is"/{BT_} { } -^{BS}"class"{BS_}"default" { } + yyextra->currentModifiers |= tmp.stripWhiteSpace(); + yyextra->argType=""; + yy_push_state(YY_START,yyscanner); + BEGIN( AttributeList ) ; + } +{ID} { + } +^{BS}"type"{BS_}"is"/{BT_} {} +^{BS}"type"{BS}"=" {} +^{BS}"class"{BS_}"is"/{BT_} {} +^{BS}"class"{BS_}"default" {} } <AttributeList>{ -{COMMA} {} -{BS} {} +{COMMA} {} +{BS} {} {LANGUAGE_BIND_SPEC} { - currentModifiers |= yytext; + yyextra->currentModifiers |= yytext; } -{ATTR_SPEC}. { /* update current modifiers when it is an ATTR_SPEC and not a variable name */ - /* bug_625519 */ +{ATTR_SPEC}. { /* update yyextra->current yyextra->modifiers when it is an ATTR_SPEC and not a variable name */ + /* buyyextra->625519 */ QChar chr = yytext[(int)yyleng-1]; if (chr.isLetter() || chr.isDigit() || (chr == '_')) { - yyColNr -= (int)yyleng; + yyextra->colNr -= (int)yyleng; REJECT; } else { QCString tmp = yytext; tmp = tmp.left(tmp.length() - 1); - yyColNr -= 1; + yyextra->colNr -= 1; unput(yytext[(int)yyleng-1]); - currentModifiers |= (tmp); + yyextra->currentModifiers |= (tmp); } - } -"::" { /* end attribute list */ - BEGIN( Variable ); - } -. { /* unknown attribute, consider variable name */ - //cout<<"start variables, unput "<<*yytext<<endl; - yyColNr -= 1; - unput(*yytext); - BEGIN( Variable ); - } + } +"::" { /* end attribute list */ + BEGIN( Variable ); + } +. { /* unknown attribute, consider variable name */ + //cout<<"start variables, unput "<<*yytext<<endl; + yyextra->colNr -= 1; + unput(*yytext); + BEGIN( Variable ); + } } -<Variable>{BS} { } -<Variable>{ID} { /* parse variable declaration */ - //cout << "5=========> got variable: " << argType << "::" << yytext << endl; - /* work around for bug in QCString.replace (QCString works) */ - QCString name=yytext; +<Variable>{BS} {} +<Variable>{ID} { /* parse variable declaration */ + //cout << "5=========> got variable: " << yyextra->argType << "::" << yytext << endl; + /* work around for bug in QCString.replace (QCString works) */ + QCString name=yytext; name = name.lower(); - /* remember attributes for the symbol */ - modifiers[current_root][name.lower()] |= currentModifiers; - argName= name; + /* remember attributes for the symbol */ + yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->argName= name; - v_type= V_IGNORE; - if (!argType.isEmpty() && current_root->section!=Entry::FUNCTION_SEC) + yyextra->vtype= V_IGNORE; + if (!yyextra->argType.isEmpty() && yyextra->current_root->section!=Entry::FUNCTION_SEC) { // new variable entry - v_type = V_VARIABLE; - current->section = Entry::VARIABLE_SEC; - current->name = argName; - current->type = argType; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; // used for source reference - current->startLine = yyLineNr; - if (argType == "@") + yyextra->vtype = V_VARIABLE; + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->name = yyextra->argName; + yyextra->current->type = yyextra->argType; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; // used for source reference + yyextra->current->startLine = yyextra->lineNr; + if (yyextra->argType == "@") { - current_root->copyToSubEntry(current); + yyextra->current_root->copyToSubEntry(yyextra->current); // add to the scope surrounding the enum (copy!) - last_enum = current; - current_root->parent()->moveToSubEntryAndRefresh(current); - initEntry(); + yyextra->last_enum = yyextra->current; + yyextra->current_root->parent()->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); } else { - addCurrentEntry(true); + addCurrentEntry(yyscanner,true); + } + } + else if (!yyextra->argType.isEmpty()) + { // declaration of parameter list: add type for corr. parameter + Argument *parameter = getParameter(yyscanner,yyextra->argName); + if (parameter) + { + yyextra->vtype= V_PARAMETER; + if (!yyextra->argType.isNull()) parameter->type=yyextra->argType.stripWhiteSpace(); + if (!yyextra->docBlock.isNull()) + { + subrHandleCommentBlock(yyscanner,yyextra->docBlock,TRUE); + } + } + // save, it may be function return type + if (parameter) + { + yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + } + else + { + if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) || + (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower()].returnName.lower() == yyextra->argName.lower())) + { + int strt = yyextra->current_root->type.find("function"); + QCString lft; + QCString rght; + if (strt != -1) + { + yyextra->vtype = V_RESULT; + lft = ""; + rght = ""; + if (strt != 0) lft = yyextra->current_root->type.left(strt).stripWhiteSpace(); + if ((yyextra->current_root->type.length() - strt - strlen("function"))!= 0) + { + rght = yyextra->current_root->type.right(yyextra->current_root->type.length() - strt - (int)strlen("function")).stripWhiteSpace(); + } + yyextra->current_root->type = lft; + if (rght.length() > 0) + { + if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " "; + yyextra->current_root->type += rght; + } + if (yyextra->argType.stripWhiteSpace().length() > 0) + { + if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " "; + yyextra->current_root->type += yyextra->argType.stripWhiteSpace(); + } + if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " "; + yyextra->current_root->type += "function"; + if (!yyextra->docBlock.isNull()) + { + subrHandleCommentBlockResult(yyscanner,yyextra->docBlock,TRUE); + } + } + else + { + yyextra->current_root->type += " " + yyextra->argType.stripWhiteSpace(); + } + yyextra->current_root->type = yyextra->current_root->type.stripWhiteSpace(); + yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->current_root->type; + } + else + { + yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + } } + // any accumulated doc for argument should be emptied, + // because it is handled other way and this doc can be + // unexpectedly passed to the next member. + yyextra->current->doc.resize(0); + yyextra->current->brief.resize(0); } - else if (!argType.isEmpty()) - { // declaration of parameter list: add type for corr. parameter - parameter = getParameter(argName); - if (parameter) - { - v_type= V_PARAMETER; - if (!argType.isNull()) parameter->type=argType.stripWhiteSpace(); - if (!docBlock.isNull()) - { - subrHandleCommentBlock(docBlock,TRUE); - } - } - // save, it may be function return type - if (parameter) - { - modifiers[current_root][name.lower()].type = argType; - } - else - { - if ((current_root->name.lower() == argName.lower()) || - (modifiers[current_root->parent()][current_root->name.lower()].returnName.lower() == argName.lower())) - { - int strt = current_root->type.find("function"); - QCString lft; - QCString rght; - if (strt != -1) - { - v_type = V_RESULT; - lft = ""; - rght = ""; - if (strt != 0) lft = current_root->type.left(strt).stripWhiteSpace(); - if ((current_root->type.length() - strt - strlen("function"))!= 0) - { - rght = current_root->type.right(current_root->type.length() - strt - strlen("function")).stripWhiteSpace(); - } - current_root->type = lft; - if (rght.length() > 0) - { - if (current_root->type.length() > 0) current_root->type += " "; - current_root->type += rght; - } - if (argType.stripWhiteSpace().length() > 0) - { - if (current_root->type.length() > 0) current_root->type += " "; - current_root->type += argType.stripWhiteSpace(); - } - if (current_root->type.length() > 0) current_root->type += " "; - current_root->type += "function"; - if (!docBlock.isNull()) - { - subrHandleCommentBlockResult(docBlock,TRUE); - } - } - else - { - current_root->type += " " + argType.stripWhiteSpace(); - } - current_root->type = current_root->type.stripWhiteSpace(); - modifiers[current_root][name.lower()].type = current_root->type; - } - else - { - modifiers[current_root][name.lower()].type = argType; - } - } - // any accumulated doc for argument should be emptied, - // because it is handled other way and this doc can be - // unexpectedly passed to the next member. - current->doc.resize(0); - current->brief.resize(0); - } - } -<Variable>{ARGS} { /* dimension of the previous entry. */ - QCString name(argName); - QCString attr("dimension"); - attr += yytext; - modifiers[current_root][name.lower()] |= attr; - } -<Variable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyColNr-(int)yyleng, yyColNr); - // locate !< comment - updateVariablePrepassComment(yyColNr-(int)yyleng, yyColNr); - } + } +<Variable>{ARGS} { /* dimension of the previous entry. */ + QCString name(yyextra->argName); + QCString attr("dimension"); + attr += yytext; + yyextra->modifiers[yyextra->current_root][name.lower()] |= attr; + } +<Variable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyextra->colNr-(int)yyleng, yyextra->colNr); + // locate !< comment + updateVariablePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr); + } <Variable>{BS}"=" { - yy_push_state(YY_START); - initializer="="; - initializerScope = initializerArrayScope = 0; - BEGIN(Initialization); - } -<Variable>"\n" { currentModifiers = SymbolModifiers(); - yy_pop_state(); // end variable declaration list - newLine(); - docBlock.resize(0); - } -<Variable>";".*"\n" { currentModifiers = SymbolModifiers(); - yy_pop_state(); // end variable declaration list - docBlock.resize(0); - inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); - yyLineNr--; - pushBuffer(inputStringSemi); + yy_push_state(YY_START,yyscanner); + yyextra->initializer="="; + yyextra->initializerScope = yyextra->initializerArrayScope = 0; + BEGIN(Initialization); + } +<Variable>"\n" { yyextra->currentModifiers = SymbolModifiers(); + yy_pop_state(yyscanner); // end variable declaration list + newLine(yyscanner); + yyextra->docBlock.resize(0); + } +<Variable>";".*"\n" { yyextra->currentModifiers = SymbolModifiers(); + yy_pop_state(yyscanner); // end variable declaration list + yyextra->docBlock.resize(0); + yyextra->inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); + yyextra->lineNr--; + pushBuffer(yyscanner,yyextra->inputStringSemi); } <*>";".*"\n" { - if (YY_START == Variable) REJECT; // Just be on the safe side + if (YY_START == Variable) REJECT; // Just be on the safe side if (YY_START == String) REJECT; // ";" ignored in strings - if (YY_START == StrIgnore) REJECT; // ";" ignored in regular comments - inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); - yyLineNr--; - pushBuffer(inputStringSemi); + if (YY_START == StrIgnore) REJECT; // ";" ignored in regular yyextra->comments + yyextra->inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); + yyextra->lineNr--; + pushBuffer(yyscanner,yyextra->inputStringSemi); } <Initialization,ArrayInitializer>"[" | -<Initialization,ArrayInitializer>"(/" { initializer+=yytext; - initializerArrayScope++; - BEGIN(ArrayInitializer); // initializer may contain comma +<Initialization,ArrayInitializer>"(/" { yyextra->initializer+=yytext; + yyextra->initializerArrayScope++; + BEGIN(ArrayInitializer); // initializer may contain comma } <ArrayInitializer>"]" | -<ArrayInitializer>"/)" { initializer+=yytext; - initializerArrayScope--; - if(initializerArrayScope<=0) - { - initializerArrayScope = 0; // just in case - BEGIN(Initialization); - } +<ArrayInitializer>"/)" { yyextra->initializer+=yytext; + yyextra->initializerArrayScope--; + if (yyextra->initializerArrayScope<=0) + { + yyextra->initializerArrayScope = 0; // just in case + BEGIN(Initialization); + } + } +<ArrayInitializer>. { yyextra->initializer+=yytext; } +<Initialization>"(" { yyextra->initializerScope++; + yyextra->initializer+=yytext; } -<ArrayInitializer>. { initializer+=yytext; } -<Initialization>"(" { initializerScope++; - initializer+=yytext; - } -<Initialization>")" { initializerScope--; - initializer+=yytext; - } -<Initialization>{COMMA} { if (initializerScope == 0) - { - updateVariablePrepassComment(yyColNr-(int)yyleng, yyColNr); - yy_pop_state(); // end initialization - if (last_enum) +<Initialization>")" { yyextra->initializerScope--; + yyextra->initializer+=yytext; + } +<Initialization>{COMMA} { if (yyextra->initializerScope == 0) + { + updateVariablePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr); + yy_pop_state(yyscanner); // end initialization + if (yyextra->last_enum) { - last_enum->initializer= initializer; + yyextra->last_enum->initializer= yyextra->initializer; } else { - if (v_type == V_VARIABLE) last_entry->initializer= initializer; + if (yyextra->vtype == V_VARIABLE) yyextra->last_entry->initializer= yyextra->initializer; } - } - else - initializer+=", "; - } + } + else + { + yyextra->initializer+=", "; + } + } <Initialization>"\n"|"!" { //| - yy_pop_state(); // end initialization - if (last_enum) + yy_pop_state(yyscanner); // end initialization + if (yyextra->last_enum) { - last_enum->initializer= initializer; + yyextra->last_enum->initializer= yyextra->initializer; } else { - if (v_type == V_VARIABLE) last_entry->initializer= initializer; + if (yyextra->vtype == V_VARIABLE) yyextra->last_entry->initializer= yyextra->initializer; } - yyColNr -= 1; - unput(*yytext); + yyextra->colNr -= 1; + unput(*yytext); } -<Initialization>. { initializer+=yytext; } +<Initialization>. { yyextra->initializer+=yytext; } <*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} { - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(Enum); - current->protection = defaultProtection; - typeProtection = defaultProtection; - typeMode = true; - - current->spec |= Entry::Struct; - current->name.resize(0); - current->args.resize(0); - current->name.sprintf("@%d",anonCount++); - - current->section = Entry::ENUM_SEC; - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - if ((current_root) && - (current_root->section == Entry::CLASS_SEC - || current_root->section == Entry::NAMESPACE_SEC)) + yy_push_state(Enum,yyscanner); + yyextra->current->protection = yyextra->defaultProtection; + yyextra->typeProtection = yyextra->defaultProtection; + yyextra->typeMode = true; + + yyextra->current->spec |= Entry::Struct; + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->name.sprintf("@%d",yyextra->anonCount++); + + yyextra->current->section = Entry::ENUM_SEC; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->lineNr; + yyextra->current->bodyLine = yyextra->lineNr; + if ((yyextra->current_root) && + (yyextra->current_root->section == Entry::CLASS_SEC || + yyextra->current_root->section == Entry::NAMESPACE_SEC)) { - current->name = current_root->name + "::" + current->name; + yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name; } - addCurrentEntry(true); - startScope(last_entry.get()); - BEGIN( Enum ) ; + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); + BEGIN( Enum ) ; } <Enum>"end"{BS}"enum" { - last_entry->parent()->endBodyLine = yyLineNr; - if (!endScope(current_root)) + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr; + if (!endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - typeMode = false; - yy_pop_state(); + } + yyextra->typeMode = false; + yy_pop_state(yyscanner); } /*------ fortran subroutine/function handling ------------------------------------------------------------*/ /* Start is initial condition */ <Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} { - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) - { - addInterface("$interface$", ifType); - startScope(last_entry.get()); - } + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) + { + addInterface(yyscanner,"$interface$", yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); + } - // TYPE_SPEC is for old function style function result - result = QCString(yytext).stripWhiteSpace().lower(); - current->type = result; - yy_push_state(SubprogPrefix); - } - -<SubprogPrefix>{BS}{SUBPROG}{BS_} { - // Fortran subroutine or function found - v_type = V_IGNORE; - result=yytext; - result=result.stripWhiteSpace(); - addSubprogram(result); - BEGIN(Subprog); - current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. - current->startLine = yyLineNr; - } + // TYPE_SPEC is for old function style function result + QCString result = QCString(yytext).stripWhiteSpace().lower(); + yyextra->current->type = result; + yy_push_state(SubprogPrefix,yyscanner); + } + +<SubprogPrefix>{BS}{SUBPROG}{BS_} { + // Fortran subroutine or function found + yyextra->vtype = V_IGNORE; + QCString result=yytext; + result=result.stripWhiteSpace(); + addSubprogram(yyscanner,result); + BEGIN(Subprog); + yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. + yyextra->current->startLine = yyextra->lineNr; + } <Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} { - // Fortran subroutine or function found - v_type = V_IGNORE; - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) - { - addInterface("$interface$", ifType); - startScope(last_entry.get()); - } + // Fortran subroutine or function found + yyextra->vtype = V_IGNORE; + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) + { + addInterface(yyscanner,"$interface$", yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); + } + + QCString result = QCString(yytext).stripWhiteSpace(); + addSubprogram(yyscanner,result); + yy_push_state(Subprog,yyscanner); + yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. + yyextra->current->startLine = yyextra->lineNr; + } + +<Subprog>{BS} { /* ignore white space */ } +<Subprog>{ID} { yyextra->current->name = yytext; + //cout << "1a==========> got " << yyextra->current->type << " " << yytext << " " << yyextra->lineNr << endl; + yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower()].returnName = yyextra->current->name.lower(); + + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) + { + yyextra->current_root->name.replace(QRegExp("\\$interface\\$"), yytext); + } - result = QCString(yytext).stripWhiteSpace(); - addSubprogram(result); - yy_push_state(Subprog); - current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. - current->startLine = yyLineNr; - } - -<Subprog>{BS} { /* ignore white space */ } -<Subprog>{ID} { current->name = yytext; - //cout << "1a==========> got " << current->type << " " << yytext << " " << yyLineNr << endl; - modifiers[current_root][current->name.lower()].returnName = current->name.lower(); - - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) - { - current_root->name.replace(QRegExp("\\$interface\\$"), yytext); + BEGIN(Parameterlist); + } +<Parameterlist>"(" { yyextra->current->args = "("; } +<Parameterlist>")" { + yyextra->current->args += ")"; + yyextra->current->args = removeRedundantWhiteSpace(yyextra->current->args); + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); + BEGIN(SubprogBody); + } +<Parameterlist>{COMMA}|{BS} { yyextra->current->args += yytext; + CommentInPrepass *c = locatePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr); + if (c!=NULL) + { + if (!yyextra->current->argList.empty()) + { + yyextra->current->argList.back().docs = c->str; + } + } + } +<Parameterlist>{ID} { + //yyextra->current->type not yet available + QCString param = yytext; + // std::cout << "3=========> got parameter " << param << std::endl; + yyextra->current->args += param; + Argument arg; + arg.name = param; + yyextra->current->argList.push_back(arg); + } +<Parameterlist>{NOARGS} { + newLine(yyscanner); + //printf("3=========> without parameterlist \n"); + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); + BEGIN(SubprogBody); + } +<SubprogBody>result{BS}\({BS}{ID} { + if (yyextra->functionLine) + { + QCString result= yytext; + result= result.right(result.length()-result.find("(")-1); + result= result.stripWhiteSpace(); + yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower()].returnName = result; + } + //cout << "=====> got result " << result << endl; } - BEGIN(Parameterlist); - } -<Parameterlist>"(" { current->args = "("; } -<Parameterlist>")" { - current->args += ")"; - current->args = removeRedundantWhiteSpace(current->args); - addCurrentEntry(true); - startScope(last_entry.get()); - BEGIN(SubprogBody); - } -<Parameterlist>{COMMA}|{BS} { current->args += yytext; - CommentInPrepass *c = locatePrepassComment(yyColNr-(int)yyleng, yyColNr); - if (c!=NULL) - { - if (!current->argList.empty()) - { - current->argList.back().docs = c->str; - } - } - } -<Parameterlist>{ID} { - //current->type not yet available - QCString param = yytext; - // std::cout << "3=========> got parameter " << param << std::endl; - current->args += param; - Argument arg; - arg.name = param; - current->argList.push_back(arg); - } -<Parameterlist>{NOARGS} { - newLine(); - //printf("3=========> without parameterlist \n"); - addCurrentEntry(true); - startScope(last_entry.get()); - BEGIN(SubprogBody); -} -<SubprogBody>result{BS}\({BS}{ID} { - if (functionLine) - { - result= yytext; - result= result.right(result.length()-result.find("(")-1); - result= result.stripWhiteSpace(); - modifiers[current_root->parent()][current_root->name.lower()].returnName = result; - } - //cout << "=====> got result " << result << endl; - } - - /*---- documentation comments --------------------------------------------------------------------*/ + /*---- documentation yyextra->comments --------------------------------------------------------------------*/ <Variable,SubprogBody,ModuleBody,TypedefBody,TypedefBodyContains>"!<" { /* backward docu comment */ - if (v_type != V_IGNORE) { - current->docLine = yyLineNr; - docBlockJavaStyle = FALSE; - docBlock.resize(0); - docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); - startCommentBlock(TRUE); - yy_push_state(DocBackLine); + if (yyextra->vtype != V_IGNORE) + { + yyextra->current->docLine = yyextra->lineNr; + yyextra->docBlockJavaStyle = FALSE; + yyextra->docBlock.resize(0); + yyextra->docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); + startCommentBlock(yyscanner,TRUE); + yy_push_state(DocBackLine,yyscanner); } else { /* handle out of place !< comment as a normal comment */ - if (YY_START == String) { yyColNr -= (int)yyleng; REJECT; } // "!" is ignored in strings - // skip comment line (without docu comments "!>" "!<" ) - /* ignore further "!" and ignore comments in Strings */ - if ((YY_START != StrIgnore) && (YY_START != String)) - { - yy_push_state(YY_START); - BEGIN(StrIgnore); - debugStr="*!"; - } + if (YY_START == String) + { + yyextra->colNr -= (int)yyleng; + REJECT; + } // "!" is ignored in strings + // skip comment line (without docu yyextra->comments "!>" "!<" ) + /* ignore further "!" and ignore yyextra->comments in Strings */ + if ((YY_START != StrIgnore) && (YY_START != String)) + { + yy_push_state(YY_START,yyscanner); + BEGIN(StrIgnore); + yyextra->debugStr="*!"; + } } - } -<DocBackLine>.* { // contents of current comment line - docBlock+=yytext; - } -<DocBackLine>"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line) - docBlock+="\n"; // \n is necessary for lists - newLine(); - } -<DocBackLine>"\n" { // comment block ends at the end of this line - //cout <<"3=========> comment block : "<< docBlock << endl; - yyColNr -= 1; - unput(*yytext); - if (v_type == V_VARIABLE) - { - std::shared_ptr<Entry> tmp_entry = current; + } +<DocBackLine>.* { // contents of yyextra->current comment line + yyextra->docBlock+=yytext; + } +<DocBackLine>"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line) + yyextra->docBlock+="\n"; // \n is necessary for lists + newLine(yyscanner); + } +<DocBackLine>"\n" { // comment block ends at the end of this line + //cout <<"3=========> comment block : "<< yyextra->docBlock << endl; + yyextra->colNr -= 1; + unput(*yytext); + if (yyextra->vtype == V_VARIABLE) + { + std::shared_ptr<Entry> tmp_entry = yyextra->current; // temporarily switch to the previous entry - if (last_enum) + if (yyextra->last_enum) { - current = last_enum; + yyextra->current = yyextra->last_enum; } else { - current = last_entry; + yyextra->current = yyextra->last_entry; } - handleCommentBlock(docBlock,TRUE); + handleCommentBlock(yyscanner,yyextra->docBlock,TRUE); // switch back - current = tmp_entry; + yyextra->current = tmp_entry; } - else if (v_type == V_PARAMETER) - { - subrHandleCommentBlock(docBlock,TRUE); + else if (yyextra->vtype == V_PARAMETER) + { + subrHandleCommentBlock(yyscanner,yyextra->docBlock,TRUE); } - else if (v_type == V_RESULT) - { - subrHandleCommentBlockResult(docBlock,TRUE); + else if (yyextra->vtype == V_RESULT) + { + subrHandleCommentBlockResult(yyscanner,yyextra->docBlock,TRUE); } - yy_pop_state(); - docBlock.resize(0); + yy_pop_state(yyscanner); + yyextra->docBlock.resize(0); } <Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,Enum>"!>" { - yy_push_state(YY_START); - current->docLine = yyLineNr; - docBlockJavaStyle = FALSE; - if (YY_START==SubprogBody) docBlockInBody = TRUE; - docBlock.resize(0); - docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); - startCommentBlock(TRUE); - BEGIN(DocBlock); + yy_push_state(YY_START,yyscanner); + yyextra->current->docLine = yyextra->lineNr; + yyextra->docBlockJavaStyle = FALSE; + if (YY_START==SubprogBody) yyextra->docBlockInBody = TRUE; + yyextra->docBlock.resize(0); + yyextra->docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); + startCommentBlock(yyscanner,TRUE); + BEGIN(DocBlock); //cout << "start DocBlock " << endl; - } - -<DocBlock>.* { // contents of current comment line - docBlock+=yytext; - } -<DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line) - docBlock+="\n"; // \n is necessary for lists - newLine(); - } -<DocBlock>"\n" { // comment block ends at the end of this line - //cout <<"3=========> comment block : "<< docBlock << endl; - yyColNr -= 1; - unput(*yytext); - handleCommentBlock(docBlock,TRUE); - yy_pop_state(); - } + } + +<DocBlock>.* { // contents of yyextra->current comment line + yyextra->docBlock+=yytext; + } +<DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line) + yyextra->docBlock+="\n"; // \n is necessary for lists + newLine(yyscanner); + } +<DocBlock>"\n" { // comment block ends at the end of this line + //cout <<"3=========> comment block : "<< yyextra->docBlock << endl; + yyextra->colNr -= 1; + unput(*yytext); + handleCommentBlock(yyscanner,yyextra->docBlock,TRUE); + yy_pop_state(yyscanner); + } /*-----Prototype parsing -------------------------------------------------------------------------*/ -<Prototype>{BS}{SUBPROG}{BS_} { - BEGIN(PrototypeSubprog); - } +<Prototype>{BS}{SUBPROG}{BS_} { + BEGIN(PrototypeSubprog); + } <Prototype,PrototypeSubprog>{BS}{SCOPENAME}?{BS}{ID} { - current->name = QCString(yytext).lower(); - current->name.stripWhiteSpace(); - BEGIN(PrototypeArgs); - } + yyextra->current->name = QCString(yytext).lower(); + yyextra->current->name.stripWhiteSpace(); + BEGIN(PrototypeArgs); + } <PrototypeArgs>{ -"("|")"|","|{BS_} { current->args += yytext; } -{ID} { current->args += yytext; - Argument a; - a.name = QCString(yytext).lower(); - current->argList.push_back(a); - } +"("|")"|","|{BS_} { yyextra->current->args += yytext; } +{ID} { yyextra->current->args += yytext; + Argument a; + a.name = QCString(yytext).lower(); + yyextra->current->argList.push_back(a); + } } /*------------------------------------------------------------------------------------------------*/ <*>"\n" { - newLine(); - //if (debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << debugStr << " state: " <<YY_START << endl; - debugStr=""; + newLine(yyscanner); + //if (yyextra->debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << yyextra->debugStr << " state: " <<YY_START << endl; + yyextra->debugStr=""; } /*---- error: EOF in wrong state --------------------------------------------------------------------*/ <*><<EOF>> { - if (parsingPrototype) { - yyterminate(); - - } else if ( include_stack_ptr <= 0 ) { - if (YY_START!=INITIAL && YY_START!=Start) { + if (yyextra->parsingPrototype) + { + yyterminate(); + } + else if ( yyextra->includeStackPtr <= 0 ) + { + if (YY_START!=INITIAL && YY_START!=Start) + { DBG_CTX((stderr,"==== Error: EOF reached in wrong state (end missing)")); - scanner_abort(); + scanner_abort(yyscanner); } yyterminate(); - } else { - popBuffer(); + } + else + { + popBuffer(yyscanner); } } <*>{LOG_OPER} { // Fortran logical comparison keywords } -<*>. { - //debugStr+=yytext; - //printf("I:%c\n", *yytext); +<*>. { + //yyextra->debugStr+=yytext; + //printf("I:%c\n", *yytext); } // ignore remaining text /**********************************************************************************/ @@ -1323,63 +1358,53 @@ private { %% //---------------------------------------------------------------------------- -#if 0 -static void extractPrefix(QCString &text) +static void newLine(yyscan_t yyscanner) { - int prefixIndex = 0; - int curIndex = 0; - bool cont = TRUE; - const char* pre[] = {"RECURSIVE","IMPURE","PURE","ELEMENTAL"}; - while(cont) - { - cont = FALSE; - for(unsigned int i=0; i<4; i++) - { - if((prefixIndex=text.find(pre[i], curIndex, FALSE))==0) - { - text.remove(0,strlen(pre[i])); - text.stripWhiteSpace(); - cont = TRUE; - } - } - } -} -#endif - -static void newLine() { - yyLineNr++; - yyLineNr+=lineCountPrepass; - lineCountPrepass=0; - comments.clear(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->lineNr++; + yyextra->lineNr+=yyextra->lineCountPrepass; + yyextra->lineCountPrepass=0; + yyextra->comments.clear(); } -static CommentInPrepass* locatePrepassComment(int from, int to) { +static CommentInPrepass* locatePrepassComment(yyscan_t yyscanner,int from, int to) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("Locate %d-%d\n", from, to); - for(uint i=0; i<comments.count(); i++) { // todo: optimize - int c = comments.at(i)->column; + for (uint i=0; i<yyextra->comments.count(); i++) + { // todo: optimize + int c = yyextra->comments.at(i)->column; //printf("Candidate %d\n", c); - if (c>=from && c<=to) { + if (c>=from && c<=to) + { // comment for previous variable or parameter - return comments.at(i); + return yyextra->comments.at(i); } } return NULL; } -static void updateVariablePrepassComment(int from, int to) { - CommentInPrepass *c = locatePrepassComment(from, to); - if (c!=NULL && v_type == V_VARIABLE) { - last_entry->brief = c->str; - } else if (c!=NULL && v_type == V_PARAMETER) { - Argument *parameter = getParameter(argName); +static void updateVariablePrepassComment(yyscan_t yyscanner,int from, int to) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + CommentInPrepass *c = locatePrepassComment(yyscanner,from, to); + if (c!=NULL && yyextra->vtype == V_VARIABLE) + { + yyextra->last_entry->brief = c->str; + } + else if (c!=NULL && yyextra->vtype == V_PARAMETER) + { + Argument *parameter = getParameter(yyscanner,yyextra->argName); if (parameter) parameter->docs = c->str; } } static int getAmpersandAtTheStart(const char *buf, int length) { - for(int i=0; i<length; i++) { - switch(buf[i]) { + for(int i=0; i<length; i++) + { + switch(buf[i]) + { case ' ': case '\t': break; @@ -1395,7 +1420,7 @@ static int getAmpersandAtTheStart(const char *buf, int length) /* Returns ampersand index, comment start index or -1 if neither exist.*/ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) { - // Avoid ampersands in string and comments + // Avoid ampersands in string and yyextra->comments int parseState = Start; char quoteSymbol = 0; int ampIndex = -1; @@ -1407,9 +1432,9 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) { // When in string, skip backslashes // Legacy code, not sure whether this is correct? - if(parseState==String) + if (parseState==String) { - if(buf[i]=='\\') i++; + if (buf[i]=='\\') i++; } switch(buf[i]) @@ -1418,13 +1443,13 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) case '"': // Close string, if quote symbol matches. // Quote symbol is set iff parseState==String - if(buf[i]==quoteSymbol) + if (buf[i]==quoteSymbol) { parseState = Start; quoteSymbol = 0; } // Start new string, if not already in string or comment - else if(parseState==Start) + else if (parseState==Start) { parseState = String; quoteSymbol = buf[i]; @@ -1433,7 +1458,7 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) break; case '!': // When in string or comment, ignore exclamation mark - if(parseState==Start) + if (parseState==Start) { parseState = Comment; commentIndex = i; @@ -1457,23 +1482,23 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) return commentIndex; } -/* Although comments at the end of continuation line are grabbed by this function, +/* Although yyextra->comments at the end of continuation line are grabbed by this function, * we still do not know how to use them later in parsing. */ -void truncatePrepass(int index) +void truncatePrepass(yyscan_t yyscanner,int index) { - int length = inputStringPrepass.length(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + int length = yyextra->inputStringPrepass.length(); for (int i=index+1; i<length; i++) { - if (inputStringPrepass[i]=='!' && i<length-1 && inputStringPrepass[i+1]=='<') { // save comment - struct CommentInPrepass *c=new CommentInPrepass(index, inputStringPrepass.right(length-i-2)); - comments.append(c); + if (yyextra->inputStringPrepass[i]=='!' && i<length-1 && yyextra->inputStringPrepass[i+1]=='<') { // save comment + struct CommentInPrepass *c=new CommentInPrepass(index, yyextra->inputStringPrepass.right(length-i-2)); + yyextra->comments.append(c); } } - inputStringPrepass.truncate(index); + yyextra->inputStringPrepass.truncate(index); } // simplified way to know if this is fixed form -// duplicate in fortrancode.l bool recognizeFixedForm(const char* contents, FortranFormat format) { int column=0; @@ -1500,16 +1525,16 @@ bool recognizeFixedForm(const char* contents, FortranFormat format) case 'C': case 'c': case '*': - if(column==1) return TRUE; - if(skipLine) break; + if (column==1) return TRUE; + if (skipLine) break; return FALSE; case '!': - if(column>1 && column<7) return FALSE; + if (column>1 && column<7) return FALSE; skipLine=TRUE; break; default: - if(skipLine) break; - if(column==7) return TRUE; + if (skipLine) break; + if (column>=7) return TRUE; return FALSE; } } @@ -1526,7 +1551,7 @@ static void insertCharacter(char *contents, int length, int pos, char c) contents[pos] = c; } -/* change comments and bring line continuation character to previous line */ +/* change yyextra->comments and bring line continuation character to previous line */ /* also used to set continuation marks in case of fortran code usage, done here as it is quite complicated code */ const char* prepassFixedForm(const char* contents, int *hasContLine) { @@ -1544,7 +1569,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) bool fullCommentLine=TRUE; bool artificialComment=FALSE; bool spaces=TRUE; - int newContentsSize = strlen(contents)+3; // \000, \n (when necessary) and one spare character (to avoid reallocation) + int newContentsSize = (int)strlen(contents)+3; // \000, \n (when necessary) and one spare character (to avoid reallocation) char* newContents = (char*)malloc(newContentsSize); int curLine = 1; @@ -1572,7 +1597,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) } j++; - if(j>=newContentsSize-3) { // check for spare characters, which may be eventually used below (by & and '! ') + if (j>=newContentsSize-3) { // check for spare characters, which may be eventually used below (by & and '! ') newContents = (char*)realloc(newContents, newContentsSize+1000); newContentsSize = newContentsSize+1000; } @@ -1603,7 +1628,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) spaces=TRUE; fullCommentLine=TRUE; column=0; - emptyLabel=TRUE; + emptyLabel=TRUE; commented=FALSE; newContents[j]=c; prevQuote = thisQuote; @@ -1620,7 +1645,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) return NULL; } newContents[j]='\000'; - newContentsSize = strlen(newContents); + newContentsSize = (int)strlen(newContents); if (newContents[newContentsSize - 1] != '\n') { // to be on the safe side @@ -1633,10 +1658,10 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) case '\'': case '\\': if ((column <= fixedCommentAfter) && (column!=6) && !commented) - { + { // we have some special cases in respect to strings and escaped string characters fullCommentLine=FALSE; - newContents[j]=c; + newContents[j]=c; if (c == '\\') { inBackslash = !inBackslash; @@ -1671,71 +1696,89 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) case '*': case '!': if ((column <= fixedCommentAfter) && (column!=6)) - { - emptyLabel=FALSE; - if(column==1) + { + emptyLabel=FALSE; + if (column==1) { - newContents[j]='!'; + newContents[j]='!'; commented = TRUE; } - else if ((c == '!') && !inDouble && !inSingle) + else if ((c == '!') && !inDouble && !inSingle) { - newContents[j]=c; + newContents[j]=c; commented = TRUE; } - else + else { if (!commented) fullCommentLine=FALSE; - newContents[j]=c; + newContents[j]=c; } - break; - } + break; + } // fallthrough default: - if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) { // remove numbers, i.e. labels from first 5 positions. + if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) + { // remove numbers, i.e. labels from first 5 positions. newContents[j]=' '; } - else if(column==6 && emptyLabel) { // continuation + else if (column==6 && emptyLabel) + { // continuation if (!commented) fullCommentLine=FALSE; - if (c != '0') { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3 + if (c != '0') + { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3 newContents[j]=' '; - if(prevLineAmpOrExclIndex==-1) { // add & just before end of previous line + if (prevLineAmpOrExclIndex==-1) + { // add & just before end of previous line /* first line is not a continuation line in code, just in snippets etc. */ if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-1, '&'); j++; - } else { // add & just before end of previous line comment + } + else + { // add & just before end of previous line comment /* first line is not a continuation line in code, just in snippets etc. */ if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex+skipped, '&'); skipped = 0; j++; } - if (hasContLine) hasContLine[curLine - 1] = 1; - } else { - newContents[j]=c; // , just handle like space + if (hasContLine) + { + hasContLine[curLine - 1] = 1; + } + } + else + { + newContents[j]=c; // , just handle like space } prevLineLength=0; - } else if ((column > fixedCommentAfter) && !commented) { + } + else if ((column > fixedCommentAfter) && !commented) + { // first non commented non blank character after position fixedCommentAfter - if (c == '&') { - newContents[j]=' '; + if (c == '&') + { + newContents[j]=' '; } - else if (c != '!') { + else if (c != '!') + { // I'm not a possible start of doxygen comment - newContents[j]=' '; + newContents[j]=' '; artificialComment = TRUE; spaces=TRUE; skipped = 0; } - else { - newContents[j]=c; + else + { + newContents[j]=c; commented = TRUE; } - } else { + } + else + { if (!commented) fullCommentLine=FALSE; - newContents[j]=c; - emptyLabel=FALSE; - } + newContents[j]=c; + emptyLabel=FALSE; + } break; } } @@ -1745,7 +1788,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) free(newContents); return NULL; } - newContentsSize = strlen(newContents); + newContentsSize = (int)strlen(newContents); if (newContents[newContentsSize - 1] != '\n') { // to be on the safe side @@ -1756,25 +1799,28 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) return newContents; } -static void pushBuffer(QCString& buffer) +static void pushBuffer(yyscan_t yyscanner,QCString& buffer) { - if (include_stack_cnt <= include_stack_ptr) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->includeStackCnt <= yyextra->includeStackPtr) { - include_stack_cnt++; - include_stack = (YY_BUFFER_STATE *)realloc(include_stack, include_stack_cnt * sizeof(YY_BUFFER_STATE)); + yyextra->includeStackCnt++; + yyextra->includeStack = (YY_BUFFER_STATE *)realloc(yyextra->includeStack, yyextra->includeStackCnt * sizeof(YY_BUFFER_STATE)); } - include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; - yy_switch_to_buffer(yy_scan_string(buffer)); + yyextra->includeStack[yyextra->includeStackPtr++] = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_scan_string(buffer,yyscanner),yyscanner); DBG_CTX((stderr, "--PUSH--%s", (const char *)buffer)); buffer = NULL; } -static void popBuffer() { +static void popBuffer(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr, "--POP--")); - include_stack_ptr --; - yy_delete_buffer( YY_CURRENT_BUFFER ); - yy_switch_to_buffer( include_stack[include_stack_ptr] ); + yyextra->includeStackPtr --; + yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner ); + yy_switch_to_buffer( yyextra->includeStack[yyextra->includeStackPtr], yyscanner ); } /** used to copy entry to an interface module procedure */ @@ -1795,9 +1841,10 @@ static void copyEntry(std::shared_ptr<Entry> dest, const std::shared_ptr<Entry> corresponding module subprogs @TODO: handle procedures in used modules */ -void resolveModuleProcedures(Entry *current_root) +void resolveModuleProcedures(yyscan_t yyscanner,Entry *current_root) { - for (const auto &ce1 : moduleProcedures) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + for (const auto &ce1 : yyextra->moduleProcedures) { // check all entries in this module for (const auto &ce2 : current_root->children()) @@ -1806,19 +1853,10 @@ void resolveModuleProcedures(Entry *current_root) { copyEntry(ce1, ce2); } - } // for procedures in current module + } // for procedures in yyextra->current module } // for all interface module procedures - moduleProcedures.clear(); -} - -#if 0 -static bool isTypeName(QCString name) -{ - name = name.lower(); - return name=="integer" || name == "real" || - name=="complex" || name == "logical"; + yyextra->moduleProcedures.clear(); } -#endif /*! Extracts string which resides within parentheses of provided string. */ static QCString extractFromParens(const QCString name) @@ -1863,7 +1901,7 @@ static QCString extractBind(const QCString name) } } -/*! Adds passed modifiers to these modifiers.*/ +/*! Adds passed yyextra->modifiers to these yyextra->modifiers.*/ SymbolModifiers& SymbolModifiers::operator|=(const SymbolModifiers &mdfs) { if (mdfs.protection!=NONE_P) protection = mdfs.protection; @@ -1890,7 +1928,7 @@ SymbolModifiers& SymbolModifiers::operator|=(const SymbolModifiers &mdfs) return *this; } -/*! Extracts and adds passed modifier to these modifiers.*/ +/*! Extracts and adds passed modifier to these yyextra->modifiers.*/ SymbolModifiers& SymbolModifiers::operator|=(QCString mdfStringArg) { QCString mdfString = mdfStringArg.lower(); @@ -2012,7 +2050,7 @@ static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = F for (Argument &arg : subprog->argList) { if ((!byTypeName && arg.name.lower() == cname) || - (byTypeName && arg.type.lower() == cname) + (byTypeName && arg.type.lower() == cname) ) { return &arg; @@ -2022,7 +2060,7 @@ static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = F } -/*! Apply modifiers stored in \a mdfs to the \a typeName string. */ +/*! Apply yyextra->modifiers stored in \a mdfs to the \a typeName string. */ static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) { if (!mdfs.dimension.isNull()) @@ -2139,14 +2177,14 @@ static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) return typeName; } -/*! Apply modifiers stored in \a mdfs to the \a arg argument. */ +/*! Apply yyextra->modifiers stored in \a mdfs to the \a arg argument. */ static void applyModifiers(Argument *arg, SymbolModifiers& mdfs) { QCString tmp = arg->type; arg->type = applyModifiers(tmp, mdfs); } -/*! Apply modifiers stored in \a mdfs to the \a ent entry. */ +/*! Apply yyextra->modifiers stored in \a mdfs to the \a ent entry. */ static void applyModifiers(Entry *ent, SymbolModifiers& mdfs) { QCString tmp = ent->type; @@ -2162,47 +2200,49 @@ static void applyModifiers(Entry *ent, SymbolModifiers& mdfs) * starting module, interface, function or other program block. * \see endScope() */ -static void startScope(Entry *scope) +static void startScope(yyscan_t yyscanner,Entry *scope) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //cout<<"start scope: "<<scope->name<<endl; - current_root= scope; /* start substructure */ + yyextra->current_root= scope; /* start substructure */ QMap<QCString,SymbolModifiers> mdfMap; - modifiers.insert(scope, mdfMap); + yyextra->modifiers.insert(scope, mdfMap); } /*! Ends scope in fortran program: may update subprogram arguments or module variable attributes. * \see startScope() */ -static bool endScope(Entry *scope, bool isGlobalRoot) +static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) { - if (global_scope == scope) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->global_scope == scope) { - global_scope = 0; + yyextra->global_scope = 0; return TRUE; } - if (global_scope == INVALID_ENTRY) + if (yyextra->global_scope == INVALID_ENTRY) { return TRUE; } //cout<<"end scope: "<<scope->name<<endl; - if (current_root->parent() || isGlobalRoot) + if (yyextra->current_root->parent() || isGlobalRoot) { - current_root= current_root->parent(); /* end substructure */ + yyextra->current_root= yyextra->current_root->parent(); /* end substructure */ } - else // if (current_root != scope) + else // if (yyextra->current_root != scope) { fprintf(stderr,"parse error in end <scopename>\n"); - scanner_abort(); + scanner_abort(yyscanner); return FALSE; } - // update variables or subprogram arguments with modifiers - QMap<QCString,SymbolModifiers>& mdfsMap = modifiers[scope]; + // update variables or subprogram arguments with yyextra->modifiers + QMap<QCString,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope]; if (scope->section == Entry::FUNCTION_SEC) { - // iterate all symbol modifiers of the scope + // iterate all symbol yyextra->modifiers of the scope for (QMap<QCString,SymbolModifiers>::Iterator it=mdfsMap.begin(); it!=mdfsMap.end(); it++) { //cout<<it.key()<<": "<<it.data()<<endl; @@ -2215,12 +2255,12 @@ static bool endScope(Entry *scope, bool isGlobalRoot) } // find return type for function - //cout<<"RETURN NAME "<<modifiers[current_root][scope->name.lower()].returnName<<endl; - QCString returnName = modifiers[current_root][scope->name.lower()].returnName.lower(); - if (modifiers[scope].contains(returnName)) + //cout<<"RETURN NAME "<<yyextra->modifiers[yyextra->current_root][scope->name.lower()].returnName<<endl; + QCString returnName = yyextra->modifiers[yyextra->current_root][scope->name.lower()].returnName.lower(); + if (yyextra->modifiers[scope].contains(returnName)) { - scope->type = modifiers[scope][returnName].type; // returning type works - applyModifiers(scope, modifiers[scope][returnName]); // returning array works + scope->type = yyextra->modifiers[scope][returnName].type; // returning type works + applyModifiers(scope, yyextra->modifiers[scope][returnName]); // returning array works } } @@ -2241,17 +2281,17 @@ static bool endScope(Entry *scope, bool isGlobalRoot) Argument *arg = findArgument(scope->parent(), ce->name, TRUE); if (arg != 0) - { + { // set type of dummy procedure argument to interface - arg->name = arg->type; + arg->name = arg->type; arg->type = scope->name; } if (ce->name.lower() == scope->name.lower()) found = TRUE; } if ((count == 1) && found) { - // clear all modifiers of the scope - modifiers.remove(scope); + // clear all yyextra->modifiers of the scope + yyextra->modifiers.remove(scope); scope->parent()->removeSubEntry(scope); scope = 0; return TRUE; @@ -2260,7 +2300,7 @@ static bool endScope(Entry *scope, bool isGlobalRoot) } if (scope->section!=Entry::FUNCTION_SEC) { // not function section - // iterate variables: get and apply modifiers + // iterate variables: get and apply yyextra->modifiers for (const auto &ce : scope->children()) { if (ce->section != Entry::VARIABLE_SEC && ce->section != Entry::FUNCTION_SEC) @@ -2272,165 +2312,156 @@ static bool endScope(Entry *scope, bool isGlobalRoot) } } - // clear all modifiers of the scope - modifiers.remove(scope); + // clear all yyextra->modifiers of the scope + yyextra->modifiers.remove(scope); return TRUE; } -#if 0 -//! Return full name of the entry. Sometimes we must combine several names recursively. -static QCString getFullName(Entry *e) -{ - QCString name = e->name; - if (e->section == Entry::CLASS_SEC // || e->section == Entry::INTERFACE_SEC - || !e->parent() || e->parent()->name.isEmpty()) - return name; - - return getFullName(e->parent())+"::"+name; -} -#endif - -static int yyread(char *buf,int max_size) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { - int c=0; - - while ( c < max_size && inputString[inputPosition] ) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t c=0; + while ( c < max_size && yyextra->inputString[yyextra->inputPosition] ) { - *buf = inputString[inputPosition++] ; + *buf = yyextra->inputString[yyextra->inputPosition++] ; c++; buf++; } return c; } -static void initParser() +static void initParser(yyscan_t yyscanner) { - last_entry.reset(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->last_entry.reset(); } -static void initEntry() +static void initEntry(yyscan_t yyscanner) { - if (typeMode) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->typeMode) { - current->protection = typeProtection; + yyextra->current->protection = yyextra->typeProtection; } else { - current->protection = defaultProtection; + yyextra->current->protection = yyextra->defaultProtection; } - current->mtype = mtype; - current->virt = virt; - current->stat = gstat; - current->lang = SrcLangExt_Fortran; - Doxygen::docGroup.initGroupInfo(current.get()); + yyextra->current->mtype = Method; + yyextra->current->virt = Normal; + yyextra->current->stat = FALSE; + yyextra->current->lang = SrcLangExt_Fortran; + yyextra->commentScanner.initGroupInfo(yyextra->current.get()); } /** - adds current entry to current_root and creates new current + adds yyextra->current entry to yyextra->current_root and creates new yyextra->current */ -static void addCurrentEntry(bool case_insens) +static void addCurrentEntry(yyscan_t yyscanner,bool case_insens) { - if (case_insens) current->name = current->name.lower(); - //printf("===Adding entry %s to %s\n", current->name.data(), current_root->name.data()); - last_entry = current; - current_root->moveToSubEntryAndRefresh(current); - initEntry(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (case_insens) yyextra->current->name = yyextra->current->name.lower(); + //printf("===Adding entry %s to %s\n", yyextra->current->name.data(), yyextra->current_root->name.data()); + yyextra->last_entry = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); } -static int max(int a, int b) {return a>b?a:b;} - -static void addModule(const char *name, bool isModule) +static void addModule(yyscan_t yyscanner,const char *name, bool isModule) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr, "0=========> got module %s\n", name)); if (isModule) - current->section = Entry::NAMESPACE_SEC; + yyextra->current->section = Entry::NAMESPACE_SEC; else - current->section = Entry::FUNCTION_SEC; + yyextra->current->section = Entry::FUNCTION_SEC; if (name!=NULL) { - current->name = name; + yyextra->current->name = name; } else { - QCString fname = yyFileName; - int index = max(fname.findRev('/'), fname.findRev('\\')); + QCString fname = yyextra->fileName; + int index = QMAX(fname.findRev('/'), fname.findRev('\\')); fname = fname.right(fname.length()-index-1); fname = fname.prepend("__").append("__"); - current->name = fname; - } - current->type = "program"; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; // used for source reference - current->startLine = yyLineNr; - current->protection = Public ; - addCurrentEntry(true); - startScope(last_entry.get()); + yyextra->current->name = fname; + } + yyextra->current->type = "program"; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; // used for source reference + yyextra->current->startLine = yyextra->lineNr; + yyextra->current->protection = Public ; + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); } -static void addSubprogram(const char *text) +static void addSubprogram(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr,"1=========> got subprog, type: %s\n",text)); - subrCurrent.push_back(current); - current->section = Entry::FUNCTION_SEC ; + yyextra->subrCurrent.push_back(yyextra->current); + yyextra->current->section = Entry::FUNCTION_SEC ; QCString subtype = text; subtype=subtype.lower().stripWhiteSpace(); - functionLine = (subtype.find("function") != -1); - current->type += " " + subtype; - current->type = current->type.stripWhiteSpace(); - current->fileName = yyFileName; - current->bodyLine = yyLineNr; // used for source reference start of body of routine - current->startLine = yyLineNr; // used for source reference start of definition - current->args.resize(0); - current->argList.clear(); - docBlock.resize(0); + yyextra->functionLine = (subtype.find("function") != -1); + yyextra->current->type += " " + subtype; + yyextra->current->type = yyextra->current->type.stripWhiteSpace(); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; // used for source reference start of body of routine + yyextra->current->startLine = yyextra->lineNr; // used for source reference start of definition + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + yyextra->docBlock.resize(0); } /*! Adds interface to the root entry. * \note Code was brought to this procedure from the parser, * because there was/is idea to use it in several parts of the parser. */ -static void addInterface(QCString name, InterfaceType type) +static void addInterface(yyscan_t yyscanner,QCString name, InterfaceType type) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - current->section = Entry::CLASS_SEC; // was Entry::INTERFACE_SEC; - current->spec = Entry::Interface; - current->name = name; + yyextra->current->section = Entry::CLASS_SEC; // was Entry::INTERFACE_SEC; + yyextra->current->spec = Entry::Interface; + yyextra->current->name = name; switch (type) { case IF_ABSTRACT: - current->type = "abstract"; + yyextra->current->type = "abstract"; break; case IF_GENERIC: - current->type = "generic"; + yyextra->current->type = "generic"; break; case IF_SPECIFIC: case IF_NONE: default: - current->type = ""; + yyextra->current->type = ""; } /* if type is part of a module, mod name is necessary for output */ - if ((current_root) && - (current_root->section == Entry::CLASS_SEC || - current_root->section == Entry::NAMESPACE_SEC)) + if ((yyextra->current_root) && + (yyextra->current_root->section == Entry::CLASS_SEC || + yyextra->current_root->section == Entry::NAMESPACE_SEC)) { - current->name= current_root->name + "::" + current->name; + yyextra->current->name= yyextra->current_root->name + "::" + yyextra->current->name; } - current->fileName = yyFileName; - current->bodyLine = yyLineNr; - current->startLine = yyLineNr; - addCurrentEntry(true); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; + yyextra->current->startLine = yyextra->lineNr; + addCurrentEntry(yyscanner,true); } @@ -2438,11 +2469,12 @@ static void addInterface(QCString name, InterfaceType type) /*! Get the argument \a name. */ -static Argument *getParameter(const QCString &name) +static Argument *getParameter(yyscan_t yyscanner,const QCString &name) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; // std::cout<<"addFortranParameter(): "<<name<<" DOCS:"<<(docs.isNull()?QCString("null"):docs)<<std::endl; Argument *ret = 0; - for (Argument &a:current_root->argList) + for (Argument &a:yyextra->current_root->argList) { if (a.name.lower()==name.lower()) { @@ -2455,70 +2487,75 @@ static Argument *getParameter(const QCString &name) } //---------------------------------------------------------------------------- -static void startCommentBlock(bool brief) +static void startCommentBlock(yyscan_t yyscanner,bool brief) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (brief) { - current->briefFile = yyFileName; - current->briefLine = yyLineNr; + yyextra->current->briefFile = yyextra->fileName; + yyextra->current->briefLine = yyextra->lineNr; } else { - current->docFile = yyFileName; - current->docLine = yyLineNr; + yyextra->current->docFile = yyextra->fileName; + yyextra->current->docLine = yyextra->lineNr; } } //---------------------------------------------------------------------------- -static void handleCommentBlock(const QCString &doc,bool brief) +static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief) { - static bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); - if (docBlockInBody && hideInBodyDocs) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); + if (yyextra->docBlockInBody && hideInBodyDocs) { - docBlockInBody = FALSE; + yyextra->docBlockInBody = FALSE; return; } DBG_CTX((stderr,"call parseCommentBlock [%s]\n",doc.data())); - int lineNr = brief ? current->briefLine : current->docLine; + int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine; int position=0; bool needsEntry = FALSE; - QCString processedDoc = preprocessCommentBlock(doc,yyFileName,lineNr); - while (parseCommentBlock( - g_thisParser, - docBlockInBody ? subrCurrent.back().get() : current.get(), - processedDoc, // text - yyFileName, // file - lineNr, - docBlockInBody ? FALSE : brief, - docBlockInBody ? FALSE : docBlockJavaStyle, - docBlockInBody, - defaultProtection, + Markdown markdown(yyextra->fileName,lineNr); + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc,lineNr) : doc; + while (yyextra->commentScanner.parseCommentBlock( + yyextra->thisParser, + yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(), + processedDoc, // text + yyextra->fileName, // file + lineNr, + yyextra->docBlockInBody ? FALSE : brief, + yyextra->docBlockInBody ? FALSE : yyextra->docBlockJavaStyle, + yyextra->docBlockInBody, + yyextra->defaultProtection, position, - needsEntry - )) + needsEntry, + Config_getBool(MARKDOWN_SUPPORT) + )) { - DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry)); - if (needsEntry) addCurrentEntry(false); + DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry)); + if (needsEntry) addCurrentEntry(yyscanner,false); } DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry)); - if (needsEntry) addCurrentEntry(false); - docBlockInBody = FALSE; + if (needsEntry) addCurrentEntry(yyscanner,false); + yyextra->docBlockInBody = FALSE; } //---------------------------------------------------------------------------- /// Handle parameter description as defined after the declaration of the parameter -static void subrHandleCommentBlock(const QCString &doc,bool brief) +static void subrHandleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString loc_doc; loc_doc = doc.stripWhiteSpace(); - std::shared_ptr<Entry> tmp_entry = current; - current = subrCurrent.back(); // temporarily switch to the entry of the subroutine / function + std::shared_ptr<Entry> tmp_entry = yyextra->current; + yyextra->current = yyextra->subrCurrent.back(); // temporarily switch to the entry of the subroutine / function // Still in the specification section so no inbodyDocs yet, but parameter documentation - current->inbodyDocs = ""; + yyextra->current->inbodyDocs = ""; // strip \\param or @param, so we can do some extra checking. We will add it later on again. if (!loc_doc.stripPrefix("\\param") && @@ -2527,7 +2564,7 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) loc_doc.stripWhiteSpace(); // direction as defined with the declaration of the parameter - int dir1 = modifiers[current_root][argName.lower()].direction; + int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower()].direction; // in description [in] is specified if (loc_doc.lower().find(directionParam[SymbolModifiers::IN]) == 0) { @@ -2536,22 +2573,22 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) (directionParam[dir1] == directionParam[SymbolModifiers::IN])) { // strip direction - loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::IN])); + loc_doc = loc_doc.right(loc_doc.length()-(int)strlen(directionParam[SymbolModifiers::IN])); loc_doc.stripWhiteSpace(); // in case of empty documentation or (now) just name, consider it as no documentation - if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " + + yyextra->argName + " " + loc_doc,brief); } } else { // something different specified, give warning and leave error. - warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args + - " inconsistency between intent attribute and documentation for parameter: " + argName); - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + warn(yyextra->fileName,yyextra->lineNr, "%s", ("Routine: " + yyextra->current->name + yyextra->current->args + + " inconsistency between intent attribute and documentation for parameter: " + yyextra->argName).data()); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } } // analogous to the [in] case, here [out] direction specified @@ -2560,22 +2597,22 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) if ((directionParam[dir1] == directionParam[SymbolModifiers::NONE_D]) || (directionParam[dir1] == directionParam[SymbolModifiers::OUT])) { - loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::OUT])); + loc_doc = loc_doc.right(loc_doc.length()-(int)strlen(directionParam[SymbolModifiers::OUT])); loc_doc.stripWhiteSpace(); - if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower())) + if (loc_doc.isEmpty() || (loc_doc.lower() == yyextra->argName.lower())) { - current = tmp_entry; + yyextra->current = tmp_entry; return; } - handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::OUT] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::OUT] + " " + + yyextra->argName + " " + loc_doc,brief); } else { - warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args + - " inconsistency between intent attribute and documentation for parameter: " + argName); - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + warn(yyextra->fileName,yyextra->lineNr, "%s", ("Routine: " + yyextra->current->name + yyextra->current->args + + " inconsistency between intent attribute and documentation for parameter: " + yyextra->argName).data()); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } } // analogous to the [in] case, here [in,out] direction specified @@ -2584,44 +2621,45 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) if ((directionParam[dir1] == directionParam[SymbolModifiers::NONE_D]) || (directionParam[dir1] == directionParam[SymbolModifiers::INOUT])) { - loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::INOUT])); + loc_doc = loc_doc.right(loc_doc.length()-(int)strlen(directionParam[SymbolModifiers::INOUT])); loc_doc.stripWhiteSpace(); - if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " + + yyextra->argName + " " + loc_doc,brief); } } else { - warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args + - " inconsistency between intent attribute and documentation for parameter: " + argName); - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + warn(yyextra->fileName,yyextra->lineNr, "%s", ("Routine: " + yyextra->current->name + yyextra->current->args + + " inconsistency between intent attribute and documentation for parameter: " + yyextra->argName).data()); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } } // analogous to the [in] case; here no direction specified - else if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + else if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } - // reset current back to the part inside the routine - current = tmp_entry; + // reset yyextra->current back to the part inside the routine + yyextra->current = tmp_entry; } //---------------------------------------------------------------------------- /// Handle result description as defined after the declaration of the parameter -static void subrHandleCommentBlockResult(const QCString &doc,bool brief) +static void subrHandleCommentBlockResult(yyscan_t yyscanner,const QCString &doc,bool brief) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString loc_doc; loc_doc = doc.stripWhiteSpace(); - std::shared_ptr<Entry> tmp_entry = current; - current = subrCurrent.back(); // temporarily switch to the entry of the subroutine / function + std::shared_ptr<Entry> tmp_entry = yyextra->current; + yyextra->current = yyextra->subrCurrent.back(); // temporarily switch to the entry of the subroutine / function // Still in the specification section so no inbodyDocs yet, but parameter documentation - current->inbodyDocs = ""; + yyextra->current->inbodyDocs = ""; // strip \\returns or @returns. We will add it later on again. if (!loc_doc.stripPrefix("\\returns") && @@ -2631,140 +2669,151 @@ static void subrHandleCommentBlockResult(const QCString &doc,bool brief) ) (void)loc_doc; // Do nothing work has been done by stripPrefix; (void)loc_doc: to overcome 'empty controlled statement' warning loc_doc.stripWhiteSpace(); - if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@returns ") + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@returns ") + loc_doc,brief); } - // reset current back to the part inside the routine - current = tmp_entry; + // reset yyextra->current back to the part inside the routine + yyextra->current = tmp_entry; } //---------------------------------------------------------------------------- -#if 0 -static int level=0; -static void debugCompounds(Entry *rt) // print Entry structure (for debugging) +static void parseMain(yyscan_t yyscanner, const char *fileName,const char *fileBuf, + const std::shared_ptr<Entry> &rt, FortranFormat format) { - level++; - printf("%d) debugCompounds(%s) line %d\n",level, rt->name.data(), rt->bodyLine); - for (const auto &ce : rt->children()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + char *tmpBuf = NULL; + initParser(yyscanner); + + yyextra->defaultProtection = Public; + yyextra->inputString = fileBuf; + yyextra->inputPosition = 0; + yyextra->inputStringPrepass = NULL; + yyextra->inputPositionPrepass = 0; + + //yyextra->anonCount = 0; // don't reset per file + yyextra->current_root = rt.get(); + yyextra->global_root = rt; + + yyextra->isFixedForm = recognizeFixedForm(fileBuf,format); + + if (yyextra->isFixedForm) { - debugCompounds(ce.get()); + msg("Prepassing fixed form of %s\n", fileName); + //printf("---strlen=%d\n", strlen(fileBuf)); + //clock_t start=clock(); + + //printf("Input fixed form string:\n%s\n", fileBuf); + //printf("===========================\n"); + yyextra->inputString = prepassFixedForm(fileBuf, NULL); + Debug::print(Debug::FortranFixed2Free,0,"======== Fixed to Free format =========\n---- Input fixed form string ------- \n%s\n", fileBuf); + Debug::print(Debug::FortranFixed2Free,0,"---- Resulting free form string ------- \n%s\n", yyextra->inputString); + //printf("Resulting free form string:\n%s\n", yyextra->inputString); + //printf("===========================\n"); + + //clock_t end=clock(); + //printf("CPU time used=%f\n", ((double) (end-start))/CLOCKS_PER_SEC); + } + else if (yyextra->inputString[strlen(fileBuf)-1] != '\n') + { + tmpBuf = (char *)malloc(strlen(fileBuf)+2); + strcpy(tmpBuf,fileBuf); + tmpBuf[strlen(fileBuf)]= '\n'; + tmpBuf[strlen(fileBuf)+1]= '\000'; + yyextra->inputString = tmpBuf; } -level--; -} -#endif + yyextra->lineNr= 1 ; + yyextra->fileName = fileName; + msg("Parsing file %s...\n",yyextra->fileName.data()); -static void parseMain(const char *fileName,const char *fileBuf, - const std::shared_ptr<Entry> &rt, FortranFormat format) -{ - char *tmpBuf = NULL; - initParser(); - - defaultProtection = Public; - inputString = fileBuf; - inputPosition = 0; - inputStringPrepass = NULL; - inputPositionPrepass = 0; - - //anonCount = 0; // don't reset per file - mtype = Method; - gstat = FALSE; - virt = Normal; - current_root = rt.get(); - global_root = rt; - inputFile.setName(fileName); - if (inputFile.open(IO_ReadOnly)) - { - isFixedForm = recognizeFixedForm(fileBuf,format); - - if (isFixedForm) - { - msg("Prepassing fixed form of %s\n", fileName); - //printf("---strlen=%d\n", strlen(fileBuf)); - //clock_t start=clock(); - - //printf("Input fixed form string:\n%s\n", fileBuf); - //printf("===========================\n"); - inputString = prepassFixedForm(fileBuf, NULL); - Debug::print(Debug::FortranFixed2Free,0,"======== Fixed to Free format =========\n---- Input fixed form string ------- \n%s\n", fileBuf); - Debug::print(Debug::FortranFixed2Free,0,"---- Resulting free form string ------- \n%s\n", inputString); - //printf("Resulting free form string:\n%s\n", inputString); - //printf("===========================\n"); - - //clock_t end=clock(); - //printf("CPU time used=%f\n", ((double) (end-start))/CLOCKS_PER_SEC); - } - else if (inputString[strlen(fileBuf)-1] != '\n') - { - tmpBuf = (char *)malloc(strlen(fileBuf)+2); - strcpy(tmpBuf,fileBuf); - tmpBuf[strlen(fileBuf)]= '\n'; - tmpBuf[strlen(fileBuf)+1]= '\000'; - inputString = tmpBuf; - } + yyextra->global_scope = rt.get(); + startScope(yyscanner,rt.get()); // implies yyextra->current_root = rt + initParser(yyscanner); + yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->lineNr); - yyLineNr= 1 ; - yyFileName = fileName; - msg("Parsing file %s...\n",yyFileName.data()); - - global_scope = rt.get(); - startScope(rt.get()); // implies current_root = rt - initParser(); - Doxygen::docGroup.enterFile(yyFileName,yyLineNr); - - // add entry for the file - current = std::make_shared<Entry>(); - current->lang = SrcLangExt_Fortran; - current->name = yyFileName; - current->section = Entry::SOURCE_SEC; - file_root = current; - current_root->moveToSubEntryAndRefresh(current); - current->lang = SrcLangExt_Fortran; - - fortranscannerYYrestart( fortranscannerYYin ); - { - BEGIN( Start ); - } + // add entry for the file + yyextra->current = std::make_shared<Entry>(); + yyextra->current->lang = SrcLangExt_Fortran; + yyextra->current->name = yyextra->fileName; + yyextra->current->section = Entry::SOURCE_SEC; + yyextra->file_root = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current->lang = SrcLangExt_Fortran; - fortranscannerYYlex(); - Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); + fortranscannerYYrestart( 0, yyscanner ); + { + BEGIN( Start ); + } - if (global_scope && global_scope != INVALID_ENTRY) endScope(current_root, TRUE); // TRUE - global root + fortranscannerYYlex(yyscanner); + yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->lineNr); - //debugCompounds(rt); //debug + if (yyextra->global_scope && yyextra->global_scope != INVALID_ENTRY) + { + endScope(yyscanner,yyextra->current_root, TRUE); // TRUE - global root + } - rt->program.resize(0); - //delete current; current=0; - moduleProcedures.clear(); - if (tmpBuf) { - free((char*)tmpBuf); - inputString=NULL; - } - if (isFixedForm) { - free((char*)inputString); - inputString=NULL; - } + //debugCompounds(rt); //debug - inputFile.close(); + rt->program.resize(0); + //delete yyextra->current; yyextra->current=0; + yyextra->moduleProcedures.clear(); + if (tmpBuf) + { + free((char*)tmpBuf); + yyextra->inputString=NULL; } + if (yyextra->isFixedForm) + { + free((char*)yyextra->inputString); + yyextra->inputString=NULL; + } + } //---------------------------------------------------------------------------- +struct FortranOutlineParser::Private +{ + yyscan_t yyscanner; + fortranscannerYY_state extra; + FortranFormat format; + Private(FortranFormat fmt) : format(fmt) + { + fortranscannerYYlex_init_extra(&extra,&yyscanner); +#ifdef FLEX_DEBUG + fortranscannerYYset_debug(1,yyscanner); +#endif + } + ~Private() + { + fortranscannerYYlex_destroy(yyscanner); + } +}; + +FortranOutlineParser::FortranOutlineParser(FortranFormat format) + : p(std::make_unique<Private>(format)) +{ +} + +FortranOutlineParser::~FortranOutlineParser() +{ +} + void FortranOutlineParser::parseInput(const char *fileName, const char *fileBuf, const std::shared_ptr<Entry> &root, - bool /*sameTranslationUnit*/, - QStrList & /*filesInSameTranslationUnit*/) + ClangTUParser * /*clangParser*/) { - g_thisParser = this; + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->thisParser = this; printlex(yy_flex_debug, TRUE, __FILE__, fileName); - ::parseMain(fileName,fileBuf,root,m_format); + ::parseMain(p->yyscanner,fileName,fileBuf,root,p->format); printlex(yy_flex_debug, FALSE, __FILE__, fileName); } @@ -2773,35 +2822,38 @@ bool FortranOutlineParser::needsPreprocessing(const QCString &extension) const { return extension!=extension.lower(); // use preprocessor only for upper case extensions } + void FortranOutlineParser::parsePrototype(const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; QCString buffer = QCString(text); - pushBuffer(buffer); - parsingPrototype = TRUE; + pushBuffer(p->yyscanner,buffer); + yyextra->parsingPrototype = TRUE; BEGIN(Prototype); - fortranscannerYYlex(); - parsingPrototype = FALSE; - popBuffer(); + fortranscannerYYlex(p->yyscanner); + yyextra->parsingPrototype = FALSE; + popBuffer(p->yyscanner); } //---------------------------------------------------------------------------- -static void scanner_abort() +static void scanner_abort(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; fprintf(stderr,"********************************************************************\n"); - fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",yyFileName.data(),yyLineNr,YY_START,stateToString(YY_START)); + fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",yyextra->fileName.data(),yyextra->lineNr,YY_START,stateToString(YY_START)); fprintf(stderr,"********************************************************************\n"); bool start=FALSE; - for (const auto &ce : global_root->children()) + for (const auto &ce : yyextra->global_root->children()) { - if (ce == file_root) start=TRUE; + if (ce == yyextra->file_root) start=TRUE; if (start) ce->reset(); } // dummy call to avoid compiler warning - (void)yy_top_state(); + (void)yy_top_state(yyscanner); return; //exit(-1); diff --git a/src/ftextstream.h b/src/ftextstream.h index bfc5bd5..5b6a9ca 100644 --- a/src/ftextstream.h +++ b/src/ftextstream.h @@ -60,7 +60,8 @@ inline FTextStream &FTextStream::operator<<( const char* s) inline FTextStream &FTextStream::operator<<( const QCString &s) { - return operator<<(s.data()); + if (m_dev) m_dev->writeBlock( s, s.length() ); + return *this; } typedef FTextStream & (*FTSFUNC)(FTextStream &);// manipulator function diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index 149f43c..6fc14bf 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -43,6 +43,32 @@ static int folderId=1; +const char *JAVASCRIPT_LICENSE_TEXT = R"LIC(/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file +*/ +)LIC"; + struct FTVNode { FTVNode(bool dir,const char *r,const char *f,const char *a, @@ -233,7 +259,7 @@ static QCString node2URL(const FTVNode *n,bool overruleFile=FALSE,bool srcLink=F url = fd->getOutputFileBase(); } } - url+=Doxygen::htmlFileExtension; + url = addHtmlExtensionIfMissing(url); if (!n->anchor.isEmpty()) url+="#"+n->anchor; } return url; @@ -322,7 +348,8 @@ static void generateBriefDoc(FTextStream &t,const Definition *def) if (!brief.isEmpty()) { DocNode *root = validatingParseDoc(def->briefFile(),def->briefLine(), - def,0,brief,FALSE,FALSE,0,TRUE,TRUE); + def,0,brief,FALSE,FALSE, + 0,TRUE,TRUE,Config_getBool(MARKDOWN_SUPPORT)); QCString relPath = relativePathToRoot(def->getOutputFileBase()); HtmlCodeGenerator htmlGen(t,relPath); HtmlDocVisitor *visitor = new HtmlDocVisitor(t,htmlGen,def); @@ -451,6 +478,10 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in char icon=compoundIcon(dynamic_cast<const ClassDef*>(n->def)); t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>"; } + else if (n->def && n->def->definitionType()==Definition::TypeDir) + { + t << "<span class=\"iconfclosed\"></span>"; + } else { t << "<span class=\"icondoc\"></span>"; @@ -639,7 +670,7 @@ static void generateJSNavTree(const QList<FTVNode> &nodeList) t << "var NAVTREE =" << endl; t << "[" << endl; t << " [ "; - QCString &projName = Config_getString(PROJECT_NAME); + QCString projName = Config_getString(PROJECT_NAME); if (projName.isEmpty()) { if (mainPageHasTitle()) // Use title of main page as root @@ -689,7 +720,7 @@ static void generateJSNavTree(const QList<FTVNode> &nodeList) tsidx << "{" << endl; QListIterator<NavIndexEntry> li(navIndex); NavIndexEntry *e; - bool first=TRUE; + first=TRUE; for (li.toFirst();(e=li.current());) // for each entry { if (elemCount==0) @@ -781,8 +812,7 @@ void FTVHelp::generateTreeViewInline(FTextStream &t) t << "<div class=\"levels\">["; t << theTranslator->trDetailLevel(); t << " "; - int i; - for (i=1;i<=depth;i++) + for (int i=1;i<=depth;i++) { t << "<span onclick=\"javascript:toggleLevel(" << i << ");\">" << i << "</span>"; } @@ -794,9 +824,7 @@ void FTVHelp::generateTreeViewInline(FTextStream &t) for (int i=1;i<=depth;i++) { int num=0; - QListIterator<FTVNode> li(m_indentNodes[0]); - FTVNode *n; - for (;(n=li.current());++li) + for (li.toFirst();(n=li.current());++li) { num+=n->numNodesAtLevel(0,i); } diff --git a/src/ftvhelp.h b/src/ftvhelp.h index 9bcaa5b..42fe707 100644 --- a/src/ftvhelp.h +++ b/src/ftvhelp.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -72,22 +72,7 @@ class FTVHelp : public IndexIntf bool m_topLevelIndex; }; -#define JAVASCRIPT_LICENSE_TEXT \ - "/*\n@licstart The following is the entire license notice for the\n" \ - "JavaScript code in this file.\n\nCopyright (C) 1997-2019 by Dimitri van Heesch\n\n" \ - "This program is free software; you can redistribute it and/or modify\n" \ - "it under the terms of version 2 of the GNU General Public License as published by\n" \ - "the Free Software Foundation\n\n" \ - "This program is distributed in the hope that it will be useful,\n" \ - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \ - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \ - "GNU General Public License for more details.\n\n" \ - "You should have received a copy of the GNU General Public License along\n" \ - "with this program; if not, write to the Free Software Foundation, Inc.,\n" \ - "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n" \ - "@licend The above is the entire license notice\n" \ - "for the JavaScript code in this file\n" \ - "*/\n" +extern const char *JAVASCRIPT_LICENSE_TEXT; #endif /* FTVHELP_H */ diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 0d6d43f..9b33356 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -54,17 +54,17 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef virtual DefType definitionType() const { return TypeGroup; } virtual QCString getOutputFileBase() const; virtual QCString anchor() const { return QCString(); } - virtual QCString displayName(bool=TRUE) const { return hasGroupTitle() ? title : DefinitionImpl::name(); } - virtual const char *groupTitle() const { return title; } + virtual QCString displayName(bool=TRUE) const { return hasGroupTitle() ? m_title : DefinitionImpl::name(); } + virtual const char *groupTitle() const { return m_title; } virtual void setGroupTitle( const char *newtitle ); - virtual bool hasGroupTitle( ) const { return titleSet; } - virtual void addFile(const FileDef *def); + virtual bool hasGroupTitle( ) const { return m_titleSet; } + virtual void addFile(const FileDef *def); virtual bool addClass(const ClassDef *def); virtual bool addNamespace(const NamespaceDef *def); virtual void addGroup(const GroupDef *def); virtual void addPage(PageDef *def); virtual void addExample(const PageDef *def); - virtual void addDir(const DirDef *dd); + virtual void addDir(DirDef *dd); virtual bool insertMember(MemberDef *def,bool docOnly=FALSE); virtual void removeMember(MemberDef *md); virtual bool findGroup(const GroupDef *def) const; // true if def is a subgroup of this group @@ -87,26 +87,26 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef virtual void sortMemberLists(); virtual bool subGrouping() const { return m_subGrouping; } - virtual void setGroupScope(Definition *d) { groupScope = d; } - virtual Definition *getGroupScope() const { return groupScope; } + virtual void setGroupScope(Definition *d) { m_groupScope = d; } + virtual Definition *getGroupScope() const { return m_groupScope; } virtual MemberList *getMemberList(MemberListType lt) const; virtual const QList<MemberList> &getMemberLists() const { return m_memberLists; } /* user defined member groups */ - virtual MemberGroupSDict *getMemberGroupSDict() const { return memberGroupSDict; } - - virtual FileList * getFiles() const { return fileList; } - virtual ClassSDict * getClasses() const { return classSDict; } - virtual NamespaceSDict * getNamespaces() const { return namespaceSDict; } - virtual GroupList * getSubGroups() const { return groupList; } - virtual PageSDict * getPages() const { return pageDict; } - virtual DirList * getDirs() const { return dirList; } - virtual PageSDict * getExamples() const { return exampleDict; } + virtual MemberGroupSDict *getMemberGroupSDict() const { return m_memberGroupSDict; } + + virtual FileList * getFiles() const { return m_fileList; } + virtual ClassSDict * getClasses() const { return m_classSDict; } + virtual NamespaceSDict * getNamespaces() const { return m_namespaceSDict; } + virtual GroupList * getSubGroups() const { return m_groupList; } + virtual PageSDict * getPages() const { return m_pageDict; } + virtual const DirList & getDirs() const { return m_dirList; } + virtual PageSDict * getExamples() const { return m_exampleDict; } virtual bool hasDetailedDescription() const; virtual void sortSubGroups(); - - private: + + private: void addMemberListToGroup(MemberList *,bool (MemberDef::*)() const); MemberList *createMemberList(MemberListType lt); void addMemberToList(MemberListType lt,MemberDef *md); @@ -132,25 +132,22 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef void writeSummaryLinks(OutputList &ol) const; void updateLanguage(const Definition *); - QCString title; // title of the group - bool titleSet; // true if title is not the same as the name - QCString fileName; // base name of the generated file - FileList *fileList; // list of files in the group - ClassSDict *classSDict; // list of classes in the group - NamespaceSDict *namespaceSDict; // list of namespaces in the group - GroupList *groupList; // list of sub groups. - PageSDict *pageDict; // list of pages in the group - PageSDict *exampleDict; // list of examples in the group - DirList *dirList; // list of directories in the group - - MemberList *allMemberList; - MemberNameInfoSDict *allMemberNameInfoSDict; - - Definition *groupScope; - - QList<MemberList> m_memberLists; - MemberGroupSDict *memberGroupSDict; - bool m_subGrouping; + QCString m_title; // title of the group + bool m_titleSet; // true if title is not the same as the name + QCString m_fileName; // base name of the generated file + FileList * m_fileList; // list of files in the group + ClassSDict * m_classSDict; // list of classes in the group + NamespaceSDict * m_namespaceSDict; // list of namespaces in the group + GroupList * m_groupList; // list of sub groups. + PageSDict * m_pageDict; // list of pages in the group + PageSDict * m_exampleDict; // list of examples in the group + DirList m_dirList; // list of directories in the group + MemberList * m_allMemberList; + MemberNameInfoLinkedMap m_allMemberNameInfoLinkedMap; + Definition * m_groupScope; + QList<MemberList> m_memberLists; + MemberGroupSDict * m_memberGroupSDict; + bool m_subGrouping; }; @@ -166,67 +163,62 @@ GroupDef *createGroupDef(const char *fileName,int line,const char *name, GroupDefImpl::GroupDefImpl(const char *df,int dl,const char *na,const char *t, const char *refFileName) : DefinitionImpl(df,dl,1,na) { - fileList = new FileList; - classSDict = new ClassSDict(17); - groupList = new GroupList; - namespaceSDict = new NamespaceSDict(17); - pageDict = new PageSDict(17); - exampleDict = new PageSDict(17); - dirList = new DirList; - allMemberNameInfoSDict = new MemberNameInfoSDict(17); - allMemberNameInfoSDict->setAutoDelete(TRUE); + m_fileList = new FileList; + m_classSDict = new ClassSDict(17); + m_groupList = new GroupList; + m_namespaceSDict = new NamespaceSDict(17); + m_pageDict = new PageSDict(17); + m_exampleDict = new PageSDict(17); if (refFileName) { - fileName=stripExtension(refFileName); + m_fileName=stripExtension(refFileName); } else { - fileName = convertNameToFile(QCString("group_")+na); + m_fileName = convertNameToFile(QCString("group_")+na); } setGroupTitle( t ); - memberGroupSDict = new MemberGroupSDict; - memberGroupSDict->setAutoDelete(TRUE); + m_memberGroupSDict = new MemberGroupSDict; + m_memberGroupSDict->setAutoDelete(TRUE); - allMemberList = new MemberList(MemberListType_allMembersList); + m_allMemberList = new MemberList(MemberListType_allMembersList); //visited = 0; - groupScope = 0; + m_groupScope = 0; m_subGrouping=Config_getBool(SUBGROUPING); } GroupDefImpl::~GroupDefImpl() { - delete fileList; - delete classSDict; - delete groupList; - delete namespaceSDict; - delete pageDict; - delete exampleDict; - delete allMemberList; - delete allMemberNameInfoSDict; - delete memberGroupSDict; - delete dirList; + delete m_fileList; + delete m_classSDict; + delete m_groupList; + delete m_namespaceSDict; + delete m_pageDict; + delete m_exampleDict; + delete m_allMemberList; + delete m_memberGroupSDict; } void GroupDefImpl::setGroupTitle( const char *t ) { - if ( t && qstrlen(t) ) + if ( t && *t ) { - title = t; - titleSet = TRUE; + m_title = t; + m_titleSet = TRUE; } else { - title = name(); - title.at(0)=toupper(title.at(0)); - titleSet = FALSE; + m_title = name(); + m_title[0]=(char)toupper(m_title[0]); + m_titleSet = FALSE; } } void GroupDefImpl::distributeMemberGroupDocumentation() { - MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -237,7 +229,7 @@ void GroupDefImpl::distributeMemberGroupDocumentation() void GroupDefImpl::findSectionsInDocumentation() { docFindSections(documentation(),this,docFile()); - MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -261,9 +253,9 @@ void GroupDefImpl::addFile(const FileDef *def) if (def->isHidden()) return; updateLanguage(def); if (sortBriefDocs) - fileList->inSort(def); + m_fileList->inSort(def); else - fileList->append(def); + m_fileList->append(def); } bool GroupDefImpl::addClass(const ClassDef *cd) @@ -272,12 +264,12 @@ bool GroupDefImpl::addClass(const ClassDef *cd) if (cd->isHidden()) return FALSE; updateLanguage(cd); QCString qn = cd->name(); - if (classSDict->find(qn)==0) + if (m_classSDict->find(qn)==0) { //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs); if (sortBriefDocs) { - classSDict->inSort(qn,cd); + m_classSDict->inSort(qn,cd); } else { @@ -287,26 +279,26 @@ bool GroupDefImpl::addClass(const ClassDef *cd) //printf("i=%d\n",i); if (i>0) { - // add nested classes (e.g. A::B, A::C) after their parent (A) in + // add nested classes (e.g. A::B, A::C) after their parent (A) in // order of insertion QCString scope = qn.left(i); - int j=classSDict->findAt(scope); + int j=m_classSDict->findAt(scope); if (j!=-1) { - while (j<(int)classSDict->count() && - classSDict->at(j)->qualifiedName().left(i)==scope) + while (j<(int)m_classSDict->count() && + m_classSDict->at(j)->qualifiedName().left(i)==scope) { //printf("skipping over %s\n",classSDict->at(j)->qualifiedName().data()); j++; } //printf("Found scope at index %d\n",j); - classSDict->insertAt(j,qn,cd); + m_classSDict->insertAt(j,qn,cd); found=TRUE; } } if (!found) // no insertion point found -> just append { - classSDict->append(qn,cd); + m_classSDict->append(qn,cd); } } return TRUE; @@ -319,38 +311,35 @@ bool GroupDefImpl::addNamespace(const NamespaceDef *def) static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS); if (def->isHidden()) return FALSE; updateLanguage(def); - if (namespaceSDict->find(def->name())==0) + if (m_namespaceSDict->find(def->name())==0) { if (sortBriefDocs) - namespaceSDict->inSort(def->name(),def); + m_namespaceSDict->inSort(def->name(),def); else - namespaceSDict->append(def->name(),def); + m_namespaceSDict->append(def->name(),def); return TRUE; } return FALSE; } -void GroupDefImpl::addDir(const DirDef *def) +void GroupDefImpl::addDir(DirDef *def) { if (def->isHidden()) return; - if (Config_getBool(SORT_BRIEF_DOCS)) - dirList->inSort(def); - else - dirList->append(def); + m_dirList.push_back(def); } void GroupDefImpl::addPage(PageDef *def) { if (def->isHidden()) return; //printf("Making page %s part of a group\n",def->name.data()); - pageDict->append(def->name(),def); + m_pageDict->append(def->name(),def); def->makePartOfGroup(this); } void GroupDefImpl::addExample(const PageDef *def) { if (def->isHidden()) return; - exampleDict->append(def->name(),def); + m_exampleDict->append(def->name(),def); } @@ -362,12 +351,12 @@ void GroupDefImpl::addMembersToMemberGroup() { if (ml->listType()&MemberListType_declarationLists) { - ::addMembersToMemberGroup(ml,&memberGroupSDict,this); + ::addMembersToMemberGroup(ml,&m_memberGroupSDict,this); } } //printf("GroupDefImpl::addMembersToMemberGroup() memberGroupList=%d\n",memberGroupList->count()); - MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -381,108 +370,97 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly) if (md->isHidden()) return FALSE; updateLanguage(md); //printf("GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data()); - MemberNameInfo *mni=0; - if ((mni=(*allMemberNameInfoSDict)[md->name()])) - { // member with this name already found - MemberNameInfoIterator srcMnii(*mni); - const MemberInfo *srcMi; - for ( ; (srcMi=srcMnii.current()) ; ++srcMnii ) + MemberNameInfo *mni = m_allMemberNameInfoLinkedMap.add(md->name()); + for (auto &srcMi : *mni) + { + const MemberDef *srcMd = srcMi->memberDef(); + if (srcMd==md) return FALSE; // already added before! + + bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace + // both inside a file => definition and declaration do not have to be in the same file + (srcMd->getOuterScope()->definitionType()==Definition::TypeFile && + md->getOuterScope()->definitionType()==Definition::TypeFile); + + const ArgumentList &srcMdAl = srcMd->argumentList(); + const ArgumentList &mdAl = md->argumentList(); + const ArgumentList &tSrcMdAl = srcMd->templateArguments(); + const ArgumentList &tMdAl = md->templateArguments(); + + if (srcMd->isFunction() && md->isFunction() && // both are a function + (tSrcMdAl.size()==tMdAl.size()) && // same number of template arguments + matchArguments2(srcMd->getOuterScope(),srcMd->getFileDef(),&srcMdAl, + md->getOuterScope(),md->getFileDef(),&mdAl, + TRUE + ) && // matching parameters + sameScope // both are found in the same scope + ) { - const MemberDef *srcMd = srcMi->memberDef; - if (srcMd==md) return FALSE; // already added before! - - bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace - // both inside a file => definition and declaration do not have to be in the same file - (srcMd->getOuterScope()->definitionType()==Definition::TypeFile && - md->getOuterScope()->definitionType()==Definition::TypeFile); - - const ArgumentList &srcMdAl = srcMd->argumentList(); - const ArgumentList &mdAl = md->argumentList(); - const ArgumentList &tSrcMdAl = srcMd->templateArguments(); - const ArgumentList &tMdAl = md->templateArguments(); - - if (srcMd->isFunction() && md->isFunction() && // both are a function - (tSrcMdAl.size()==tMdAl.size()) && // same number of template arguments - matchArguments2(srcMd->getOuterScope(),srcMd->getFileDef(),srcMdAl, - md->getOuterScope(),md->getFileDef(),mdAl, - TRUE - ) && // matching parameters - sameScope // both are found in the same scope - ) + if (srcMd->getGroupAlias()==0) { - if (srcMd->getGroupAlias()==0) - { - md->setGroupAlias(srcMd); - } - else if (md!=srcMd->getGroupAlias()) - { - md->setGroupAlias(srcMd->getGroupAlias()); - } - return FALSE; // member is the same as one that is already added + md->setGroupAlias(srcMd); + } + else if (md!=srcMd->getGroupAlias()) + { + md->setGroupAlias(srcMd->getGroupAlias()); } + return FALSE; // member is the same as one that is already added } - mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE)); - } - else - { - mni = new MemberNameInfo(md->name()); - mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE)); - allMemberNameInfoSDict->append(mni->memberName(),mni); } + mni->push_back(std::make_unique<MemberInfo>(md,md->protection(),md->virtualness(),FALSE)); //printf("Added member!\n"); - allMemberList->append(md); + m_allMemberList->append(md); switch(md->memberType()) { - case MemberType_Variable: + case MemberType_Variable: if (!docOnly) { addMemberToList(MemberListType_decVarMembers,md); } addMemberToList(MemberListType_docVarMembers,md); break; - case MemberType_Function: + case MemberType_Function: if (!docOnly) { addMemberToList(MemberListType_decFuncMembers,md); } addMemberToList(MemberListType_docFuncMembers,md); break; - case MemberType_Typedef: + case MemberType_Typedef: if (!docOnly) { addMemberToList(MemberListType_decTypedefMembers,md); } addMemberToList(MemberListType_docTypedefMembers,md); break; - case MemberType_Enumeration: + case MemberType_Enumeration: if (!docOnly) { addMemberToList(MemberListType_decEnumMembers,md); } addMemberToList(MemberListType_docEnumMembers,md); break; - case MemberType_EnumValue: + case MemberType_EnumValue: if (!docOnly) { addMemberToList(MemberListType_decEnumValMembers,md); } addMemberToList(MemberListType_docEnumValMembers,md); break; - case MemberType_Define: + case MemberType_Define: if (!docOnly) { addMemberToList(MemberListType_decDefineMembers,md); } addMemberToList(MemberListType_docDefineMembers,md); break; - case MemberType_Signal: + case MemberType_Signal: if (!docOnly) { addMemberToList(MemberListType_decSignalMembers,md); } addMemberToList(MemberListType_docSignalMembers,md); break; - case MemberType_Slot: + case MemberType_Slot: if (md->protection()==Public) { if (!docOnly) @@ -508,21 +486,21 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly) addMemberToList(MemberListType_docPriSlotMembers,md); } break; - case MemberType_Event: + case MemberType_Event: if (!docOnly) { addMemberToList(MemberListType_decEventMembers,md); } addMemberToList(MemberListType_docEventMembers,md); break; - case MemberType_Property: + case MemberType_Property: if (!docOnly) { addMemberToList(MemberListType_decPropMembers,md); } addMemberToList(MemberListType_docPropMembers,md); break; - case MemberType_Friend: + case MemberType_Friend: if (!docOnly) { addMemberToList(MemberListType_decFriendMembers,md); @@ -542,23 +520,10 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly) void GroupDefImpl::removeMember(MemberDef *md) { // fprintf(stderr, "GroupDef(%s)::removeMember( %s )\n", title.data(), md->name().data()); - MemberNameInfo *mni = allMemberNameInfoSDict->find(md->name()); + MemberNameInfo *mni = m_allMemberNameInfoLinkedMap.find(md->name()); if (mni) { - MemberNameInfoIterator mnii(*mni); - while( mnii.current() ) - { - if( mnii.current()->memberDef == md ) - { - mni->remove(mnii.current()); - break; - } - ++mnii; - } - if( mni->isEmpty() ) - { - allMemberNameInfoSDict->remove(md->name()); - } + m_allMemberNameInfoLinkedMap.del(md->name()); removeMemberFromList(MemberListType_allMembersList,md); switch(md->memberType()) @@ -567,31 +532,31 @@ void GroupDefImpl::removeMember(MemberDef *md) removeMemberFromList(MemberListType_decVarMembers,md); removeMemberFromList(MemberListType_docVarMembers,md); break; - case MemberType_Function: + case MemberType_Function: removeMemberFromList(MemberListType_decFuncMembers,md); removeMemberFromList(MemberListType_docFuncMembers,md); break; - case MemberType_Typedef: + case MemberType_Typedef: removeMemberFromList(MemberListType_decTypedefMembers,md); removeMemberFromList(MemberListType_docTypedefMembers,md); break; - case MemberType_Enumeration: + case MemberType_Enumeration: removeMemberFromList(MemberListType_decEnumMembers,md); removeMemberFromList(MemberListType_docEnumMembers,md); break; - case MemberType_EnumValue: + case MemberType_EnumValue: removeMemberFromList(MemberListType_decEnumValMembers,md); removeMemberFromList(MemberListType_docEnumValMembers,md); break; - case MemberType_Define: + case MemberType_Define: removeMemberFromList(MemberListType_decDefineMembers,md); removeMemberFromList(MemberListType_docDefineMembers,md); break; - case MemberType_Signal: + case MemberType_Signal: removeMemberFromList(MemberListType_decSignalMembers,md); removeMemberFromList(MemberListType_docSignalMembers,md); break; - case MemberType_Slot: + case MemberType_Slot: if (md->protection()==Public) { removeMemberFromList(MemberListType_decPubSlotMembers,md); @@ -608,15 +573,15 @@ void GroupDefImpl::removeMember(MemberDef *md) removeMemberFromList(MemberListType_docPriSlotMembers,md); } break; - case MemberType_Event: + case MemberType_Event: removeMemberFromList(MemberListType_decEventMembers,md); removeMemberFromList(MemberListType_docEventMembers,md); break; - case MemberType_Property: + case MemberType_Property: removeMemberFromList(MemberListType_decPropMembers,md); removeMemberFromList(MemberListType_docPropMembers,md); break; - case MemberType_Friend: + case MemberType_Friend: removeMemberFromList(MemberListType_decFriendMembers,md); removeMemberFromList(MemberListType_docFriendMembers,md); break; @@ -632,9 +597,9 @@ bool GroupDefImpl::findGroup(const GroupDef *def) const { return TRUE; } - else if (groupList) + else if (m_groupList) { - GroupListIterator it(*groupList); + GroupListIterator it(*m_groupList); GroupDef *gd; for (;(gd=it.current());++it) { @@ -653,7 +618,7 @@ void GroupDefImpl::addGroup(const GroupDef *def) //if (Config_getBool(SORT_MEMBER_DOCS)) // groupList->inSort(def); //else - groupList->append(def); + m_groupList->append(def); } bool GroupDefImpl::isASubGroup() const @@ -671,9 +636,9 @@ void GroupDefImpl::countMembers() ml->countDecMembers(); ml->countDocMembers(); } - if (memberGroupSDict) + if (m_memberGroupSDict) { - MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -685,27 +650,27 @@ void GroupDefImpl::countMembers() int GroupDefImpl::numDocMembers() const { - return fileList->count()+ - classSDict->count()+ - namespaceSDict->count()+ - groupList->count()+ - allMemberList->count()+ - pageDict->count()+ - exampleDict->count(); + return m_fileList->count()+ + m_classSDict->count()+ + m_namespaceSDict->count()+ + m_groupList->count()+ + m_allMemberList->count()+ + m_pageDict->count()+ + m_exampleDict->count(); } -/*! Compute the HTML anchor names for all members in the group */ +/*! Compute the HTML anchor names for all members in the group */ void GroupDefImpl::computeAnchors() { //printf("GroupDefImpl::computeAnchors()\n"); - setAnchors(allMemberList); + setAnchors(m_allMemberList); } void GroupDefImpl::writeTagFile(FTextStream &tagFile) { tagFile << " <compound kind=\"group\">" << endl; tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; - tagFile << " <title>" << convertToXML(title) << "</title>" << endl; + tagFile << " <title>" << convertToXML(m_title) << "</title>" << endl; tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl; QListIterator<LayoutDocEntry> eli( LayoutDocManager::instance().docEntries(LayoutDocManager::Group)); @@ -716,9 +681,9 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) { case LayoutDocEntry::GroupClasses: { - if (classSDict) + if (m_classSDict) { - SDict<ClassDef>::Iterator ci(*classSDict); + SDict<ClassDef>::Iterator ci(*m_classSDict); ClassDef *cd; for (ci.toFirst();(cd=ci.current());++ci) { @@ -733,9 +698,9 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) break; case LayoutDocEntry::GroupNamespaces: { - if (namespaceSDict) + if (m_namespaceSDict) { - SDict<NamespaceDef>::Iterator ni(*namespaceSDict); + SDict<NamespaceDef>::Iterator ni(*m_namespaceSDict); NamespaceDef *nd; for (ni.toFirst();(nd=ni.current());++ni) { @@ -750,9 +715,9 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) break; case LayoutDocEntry::GroupFiles: { - if (fileList) + if (m_fileList) { - QListIterator<FileDef> it(*fileList); + QListIterator<FileDef> it(*m_fileList); FileDef *fd; for (;(fd=it.current());++it) { @@ -766,9 +731,9 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) break; case LayoutDocEntry::GroupPageDocs: { - if (pageDict) + if (m_pageDict) { - PageSDict::Iterator pdi(*pageDict); + PageSDict::Iterator pdi(*m_pageDict); PageDef *pd=0; for (pdi.toFirst();(pd=pdi.current());++pdi) { @@ -783,25 +748,20 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) break; case LayoutDocEntry::GroupDirs: { - if (dirList) + for(const auto dd : m_dirList) { - QListIterator<DirDef> it(*dirList); - DirDef *dd; - for (;(dd=it.current());++it) + if (dd->isLinkableInProject()) { - if (dd->isLinkableInProject()) - { - tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl; - } + tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl; } } } break; case LayoutDocEntry::GroupNestedGroups: { - if (groupList) + if (m_groupList) { - QListIterator<GroupDef> it(*groupList); + QListIterator<GroupDef> it(*m_groupList); GroupDef *gd; for (;(gd=it.current());++it) { @@ -825,9 +785,9 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) break; case LayoutDocEntry::MemberGroups: { - if (memberGroupSDict) + if (m_memberGroupSDict) { - MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -846,12 +806,12 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) { - if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) + if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) || !documentation().isEmpty() || !inbodyDocumentation().isEmpty() ) { ol.pushGeneratorState(); - if (pageDict->count()!=numDocMembers()) // not only pages -> classical layout + if (m_pageDict->count()!=(uint)numDocMembers()) // not only pages -> classical layout { ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); @@ -874,7 +834,8 @@ void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title // repeat brief description if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // write separator between brief and details if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && @@ -894,13 +855,15 @@ void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title // write detailed documentation if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // write inbody documentation if (!inbodyDocumentation().isEmpty()) { - ol.generateDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE); + ol.generateDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } } @@ -910,7 +873,8 @@ void GroupDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startParagraph(); @@ -953,7 +917,7 @@ void GroupDefImpl::writeGroupGraph(OutputList &ol) ol.disable(OutputGenerator::Man); //ol.startParagraph(); ol.startGroupCollaboration(); - ol.parseText(theTranslator->trCollaborationDiagram(title)); + ol.parseText(theTranslator->trCollaborationDiagram(m_title)); ol.endGroupCollaboration(graph); //ol.endParagraph(); ol.popGeneratorState(); @@ -964,13 +928,13 @@ void GroupDefImpl::writeGroupGraph(OutputList &ol) void GroupDefImpl::writeFiles(OutputList &ol,const QCString &title) { // write list of files - if (fileList->count()>0) + if (m_fileList->count()>0) { ol.startMemberHeader("files"); ol.parseText(title); ol.endMemberHeader(); ol.startMemberList(); - QListIterator<FileDef> it(*fileList); + QListIterator<FileDef> it(*m_fileList); FileDef *fd; for (;(fd=it.current());++it) { @@ -984,7 +948,8 @@ void GroupDefImpl::writeFiles(OutputList &ol,const QCString &title) if (!fd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(fd->getOutputFileBase()); - ol.generateDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); @@ -996,16 +961,16 @@ void GroupDefImpl::writeFiles(OutputList &ol,const QCString &title) void GroupDefImpl::writeNamespaces(OutputList &ol,const QCString &title) { // write list of namespaces - namespaceSDict->writeDeclaration(ol,title); + m_namespaceSDict->writeDeclaration(ol,title); } void GroupDefImpl::writeNestedGroups(OutputList &ol,const QCString &title) { // write list of groups int count=0; - if (groupList->count()>0) + if (m_groupList->count()>0) { - QListIterator<GroupDef> it(*groupList); + QListIterator<GroupDef> it(*m_groupList); GroupDef *gd; for (;(gd=it.current());++it) { @@ -1020,9 +985,9 @@ void GroupDefImpl::writeNestedGroups(OutputList &ol,const QCString &title) ol.startMemberList(); if (Config_getBool(SORT_GROUP_NAMES)) { - groupList->sort(); + m_groupList->sort(); } - QListIterator<GroupDef> it(*groupList); + QListIterator<GroupDef> it(*m_groupList); GroupDef *gd; for (;(gd=it.current());++it) { @@ -1039,7 +1004,8 @@ void GroupDefImpl::writeNestedGroups(OutputList &ol,const QCString &title) if (!gd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(gd->getOutputFileBase()); - ol.generateDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); @@ -1052,15 +1018,13 @@ void GroupDefImpl::writeNestedGroups(OutputList &ol,const QCString &title) void GroupDefImpl::writeDirs(OutputList &ol,const QCString &title) { // write list of directories - if (dirList->count()>0) + if (!m_dirList.empty()) { ol.startMemberHeader("dirs"); ol.parseText(title); ol.endMemberHeader(); ol.startMemberList(); - QListIterator<DirDef> it(*dirList); - DirDef *dd; - for (;(dd=it.current());++it) + for(const auto dd : m_dirList) { if (!dd->hasDocumentation()) continue; ol.startMemberDeclaration(); @@ -1072,7 +1036,8 @@ void GroupDefImpl::writeDirs(OutputList &ol,const QCString &title) if (!dd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(dd->getOutputFileBase()); - ol.generateDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); @@ -1085,32 +1050,33 @@ void GroupDefImpl::writeDirs(OutputList &ol,const QCString &title) void GroupDefImpl::writeClasses(OutputList &ol,const QCString &title) { // write list of classes - classSDict->writeDeclaration(ol,0,title,FALSE); + m_classSDict->writeDeclaration(ol,0,title,FALSE); } void GroupDefImpl::writeInlineClasses(OutputList &ol) { - classSDict->writeDocumentation(ol); + m_classSDict->writeDocumentation(ol); } void GroupDefImpl::writePageDocumentation(OutputList &ol) { PageDef *pd=0; - PageSDict::Iterator pdi(*pageDict); + PageSDict::Iterator pdi(*m_pageDict); for (pdi.toFirst();(pd=pdi.current());++pdi) { if (!pd->isReference()) { - SectionInfo *si=0; + const SectionInfo *si=0; if (pd->hasTitle() && !pd->name().isEmpty() && - (si=Doxygen::sectionDict->find(pd->name()))!=0) + (si=SectionManager::instance().find(pd->name()))!=0) { - ol.startSection(si->label,si->title,SectionInfo::Subsection); - ol.docify(si->title); - ol.endSection(si->label,SectionInfo::Subsection); + ol.startSection(si->label(),si->title(),SectionType::Subsection); + ol.docify(si->title()); + ol.endSection(si->label(),SectionType::Subsection); } ol.startTextBlock(); - ol.generateDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE,0,TRUE,FALSE); + ol.generateDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endTextBlock(); } } @@ -1119,11 +1085,11 @@ void GroupDefImpl::writePageDocumentation(OutputList &ol) void GroupDefImpl::writeMemberGroups(OutputList &ol) { /* write user defined member groups */ - if (memberGroupSDict) + if (m_memberGroupSDict) { - memberGroupSDict->sort(); + m_memberGroupSDict->sort(); /* write user defined member groups */ - MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -1186,15 +1152,15 @@ void GroupDefImpl::writeSummaryLinks(OutputList &ol) const SrcLangExt lang = getLanguage(); for (eli.toFirst();(lde=eli.current());++eli) { - if ((lde->kind()==LayoutDocEntry::GroupClasses && classSDict->declVisible()) || - (lde->kind()==LayoutDocEntry::GroupNamespaces && namespaceSDict->declVisible()) || - (lde->kind()==LayoutDocEntry::GroupFiles && fileList->count()>0) || - (lde->kind()==LayoutDocEntry::GroupNestedGroups && groupList->count()>0) || - (lde->kind()==LayoutDocEntry::GroupDirs && dirList->count()>0) + if ((lde->kind()==LayoutDocEntry::GroupClasses && m_classSDict->declVisible()) || + (lde->kind()==LayoutDocEntry::GroupNamespaces && m_namespaceSDict->declVisible()) || + (lde->kind()==LayoutDocEntry::GroupFiles && m_fileList->count()>0) || + (lde->kind()==LayoutDocEntry::GroupNestedGroups && m_groupList->count()>0) || + (lde->kind()==LayoutDocEntry::GroupDirs && !m_dirList.empty()) ) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" : + QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" : lde->kind()==LayoutDocEntry::GroupNamespaces ? "namespaces" : lde->kind()==LayoutDocEntry::GroupFiles ? "files" : lde->kind()==LayoutDocEntry::GroupNestedGroups ? "groups" : @@ -1224,23 +1190,28 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) { //static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); ol.pushGeneratorState(); - startFile(ol,getOutputFileBase(),name(),title,HLI_Modules); + startFile(ol,getOutputFileBase(),name(),m_title,HLI_Modules); ol.startHeaderSection(); writeSummaryLinks(ol); ol.startTitleHead(getOutputFileBase()); ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); - ol.parseText(title); + ol.parseText(m_title); ol.popGeneratorState(); addGroupListToTitle(ol,this); ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); - ol.endTitleHead(getOutputFileBase(),title); + ol.endTitleHead(getOutputFileBase(),m_title); ol.popGeneratorState(); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Man); ol.endTitleHead(getOutputFileBase(),name()); + if (!m_title.isEmpty()) + { + ol.writeString(" - "); + ol.parseText(m_title); + } ol.popGeneratorState(); ol.endHeaderSection(); ol.startContents(); @@ -1250,14 +1221,14 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); static QRegExp we("[a-zA-Z_][-a-zA-Z_0-9]*"); int i=0,p=0,l=0; - while ((i=we.match(title,p,&l))!=-1) // foreach word in the title + while ((i=we.match(m_title,p,&l))!=-1) // foreach word in the title { - Doxygen::searchIndex->addWord(title.mid(i,l),TRUE); + Doxygen::searchIndex->addWord(m_title.mid(i,l),TRUE); p=i+l; } } - Doxygen::indexList->addIndexItem(this,0,0,title); + Doxygen::indexList->addIndexItem(this,0,0,m_title); //---------------------------------------- start flexible part ------------------------------- @@ -1269,84 +1240,84 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) { switch (lde->kind()) { - case LayoutDocEntry::BriefDesc: + case LayoutDocEntry::BriefDesc: writeBriefDescription(ol); - break; - case LayoutDocEntry::MemberDeclStart: + break; + case LayoutDocEntry::MemberDeclStart: startMemberDeclarations(ol); - break; - case LayoutDocEntry::GroupClasses: + break; + case LayoutDocEntry::GroupClasses: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClasses(ol,ls->title(lang)); } - break; - case LayoutDocEntry::GroupInlineClasses: + break; + case LayoutDocEntry::GroupInlineClasses: { writeInlineClasses(ol); } break; - case LayoutDocEntry::GroupNamespaces: + case LayoutDocEntry::GroupNamespaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeNamespaces(ol,ls->title(lang)); } - break; - case LayoutDocEntry::MemberGroups: + break; + case LayoutDocEntry::MemberGroups: writeMemberGroups(ol); - break; - case LayoutDocEntry::MemberDecl: + break; + case LayoutDocEntry::MemberDecl: { LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; writeMemberDeclarations(ol,lmd->type,lmd->title(lang)); } - break; - case LayoutDocEntry::MemberDeclEnd: + break; + case LayoutDocEntry::MemberDeclEnd: endMemberDeclarations(ol); break; - case LayoutDocEntry::DetailedDesc: + case LayoutDocEntry::DetailedDesc: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeDetailedDescription(ol,ls->title(lang)); } break; - case LayoutDocEntry::MemberDefStart: + case LayoutDocEntry::MemberDefStart: startMemberDocumentation(ol); - break; - case LayoutDocEntry::MemberDef: + break; + case LayoutDocEntry::MemberDef: { LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; writeMemberDocumentation(ol,lmd->type,lmd->title(lang)); } break; - case LayoutDocEntry::MemberDefEnd: + case LayoutDocEntry::MemberDefEnd: endMemberDocumentation(ol); break; - case LayoutDocEntry::GroupNestedGroups: + case LayoutDocEntry::GroupNestedGroups: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeNestedGroups(ol,ls->title(lang)); } break; - case LayoutDocEntry::GroupPageDocs: + case LayoutDocEntry::GroupPageDocs: writePageDocumentation(ol); break; - case LayoutDocEntry::GroupDirs: + case LayoutDocEntry::GroupDirs: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeDirs(ol,ls->title(lang)); } break; - case LayoutDocEntry::GroupFiles: + case LayoutDocEntry::GroupFiles: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeFiles(ol,ls->title(lang)); } break; - case LayoutDocEntry::GroupGraph: + case LayoutDocEntry::GroupGraph: writeGroupGraph(ol); break; - case LayoutDocEntry::AuthorSection: + case LayoutDocEntry::AuthorSection: writeAuthorSection(ol); break; case LayoutDocEntry::ClassIncludes: @@ -1371,7 +1342,7 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) case LayoutDocEntry::FileConstantGroups: case LayoutDocEntry::FileIncludes: case LayoutDocEntry::FileIncludeGraph: - case LayoutDocEntry::FileIncludedByGraph: + case LayoutDocEntry::FileIncludedByGraph: case LayoutDocEntry::FileSourceLink: case LayoutDocEntry::FileInlineClasses: case LayoutDocEntry::DirSubDirs: @@ -1385,13 +1356,13 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) //---------------------------------------- end flexible part ------------------------------- - endFile(ol); + endFile(ol); ol.popGeneratorState(); if (Config_getBool(SEPARATE_MEMBER_PAGES)) { - allMemberList->sort(); + m_allMemberList->sort(); writeMemberPages(ol); } @@ -1401,7 +1372,7 @@ void GroupDefImpl::writeMemberPages(OutputList &ol) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - + QListIterator<MemberList> mli(m_memberLists); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) @@ -1422,7 +1393,7 @@ void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current ol.writeString(" <div class=\"navtab\">\n"); ol.writeString(" <table>\n"); - MemberListIterator mli(*allMemberList); + MemberListIterator mli(*m_allMemberList); MemberDef *md; for (mli.toFirst();(md=mli.current());++mli) { @@ -1465,7 +1436,7 @@ void addClassToGroups(const Entry *root,ClassDef *cd) GroupDef *gd=0; if (!g.groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g.groupname))) { - if (gd->addClass(cd)) + if (gd->addClass(cd)) { cd->makePartOfGroup(gd); } @@ -1535,7 +1506,7 @@ void addGroupToGroups(const Entry *root,GroupDef *subGroup) /*! Add a member to the group with the highest priority */ void addMemberToGroups(const Entry *root,MemberDef *md) { - //printf("addMemberToGroups: Root %p = %s, md %p=%s groups=%d\n", + //printf("addMemberToGroups: Root %p = %s, md %p=%s groups=%d\n", // root, root->name.data(), md, md->name().data(), root->groups->count() ); // Search entry's group list for group with highest pri. @@ -1548,7 +1519,7 @@ void addMemberToGroups(const Entry *root,MemberDef *md) (gd=Doxygen::groupSDict->find(g.groupname)) && g.pri >= pri) { - if (fgd && gd!=fgd && g.pri==pri) + if (fgd && gd!=fgd && g.pri==pri) { warn(root->fileName.data(), root->startLine, "Member %s found in multiple %s groups! " @@ -1578,7 +1549,7 @@ void addMemberToGroups(const Entry *root,MemberDef *md) { bool moveit = FALSE; - // move member from one group to another if + // move member from one group to another if // - the new one has a higher priority // - the new entry has the same priority, but with docs where the old one had no docs if (md->getGroupPri()<pri) @@ -1627,7 +1598,7 @@ void addMemberToGroups(const Entry *root,MemberDef *md) md->setGroupDef(fgd,pri,root->fileName,root->startLine, !root->doc.isEmpty()); ClassDef *cd = md->getClassDefOfAnonymousType(); - if (cd) + if (cd) { cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0); } @@ -1653,13 +1624,13 @@ void addExampleToGroups(const Entry *root,PageDef *eg) QCString GroupDefImpl::getOutputFileBase() const { - return fileName; + return m_fileName; } void GroupDefImpl::addListReferences() { { - const std::vector<ListItemInfo> &xrefItems = xrefListItems(); + const RefItemVector &xrefItems = xrefListItems(); addRefItem(xrefItems, getOutputFileBase(), theTranslator->trGroup(TRUE,TRUE), @@ -1668,7 +1639,7 @@ void GroupDefImpl::addListReferences() 0 ); } - MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -1723,6 +1694,10 @@ void GroupDefImpl::sortMemberLists() { if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); } } + if (Config_getBool(SORT_BRIEF_DOCS)) + { + std::sort(m_dirList.begin(), m_dirList.end(), compareDirDefs); + } } MemberList *GroupDefImpl::getMemberList(MemberListType lt) const @@ -1744,12 +1719,12 @@ void GroupDefImpl::writeMemberDeclarations(OutputList &ol,MemberListType lt,cons static bool optimizeVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); MemberList * ml = getMemberList(lt); - if (optimizeVhdl && ml) + if (optimizeVhdl && ml) { VhdlDocGen::writeVhdlDeclarations(ml,ol,this,0,0,0); return; } - if (ml) + if (ml) { ml->writeDeclarations(ol,0,0,0,this,title,0); } @@ -1763,13 +1738,13 @@ void GroupDefImpl::writeMemberDocumentation(OutputList &ol,MemberListType lt,con void GroupDefImpl::removeMemberFromList(MemberListType lt,MemberDef *md) { - MemberList *ml = getMemberList(lt); - if (ml) ml->remove(md); + MemberList *ml = getMemberList(lt); + if (ml) ml->remove(md); } -void GroupDefImpl::sortSubGroups() -{ - groupList->sort(); +void GroupDefImpl::sortSubGroups() +{ + m_groupList->sort(); } bool GroupDefImpl::isLinkableInProject() const diff --git a/src/groupdef.h b/src/groupdef.h index 8a84a98..82fa004 100644 --- a/src/groupdef.h +++ b/src/groupdef.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -22,6 +22,7 @@ #include "sortdict.h" #include "definition.h" +#include "dirdef.h" class MemberList; class FileList; @@ -33,11 +34,9 @@ class GroupList; class OutputList; class NamespaceSDict; class MemberGroupSDict; -class MemberNameInfoSDict; class PageSDict; class PageDef; class DirDef; -class DirList; class FTVHelp; class Entry; class MemberDef; @@ -62,7 +61,7 @@ class GroupDef : virtual public Definition virtual void addGroup(const GroupDef *def) = 0; virtual void addPage(PageDef *def) = 0; virtual void addExample(const PageDef *def) = 0; - virtual void addDir(const DirDef *dd) = 0; + virtual void addDir(DirDef *dd) = 0; virtual bool insertMember(MemberDef *def,bool docOnly=FALSE) = 0; virtual void removeMember(MemberDef *md) = 0; virtual bool findGroup(const GroupDef *def) const = 0; @@ -99,7 +98,7 @@ class GroupDef : virtual public Definition virtual NamespaceSDict * getNamespaces() const = 0; virtual GroupList * getSubGroups() const = 0; virtual PageSDict * getPages() const = 0; - virtual DirList * getDirs() const = 0; + virtual const DirList & getDirs() const = 0; virtual PageSDict * getExamples() const = 0; virtual bool hasDetailedDescription() const = 0; virtual void sortSubGroups() = 0; diff --git a/src/growbuf.h b/src/growbuf.h index bf6d74e..2f8075b 100644 --- a/src/growbuf.h +++ b/src/growbuf.h @@ -10,49 +10,50 @@ 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; + GrowBuf() : m_str(0), m_pos(0), m_len(0) {} + GrowBuf(uint initialSize) : m_pos(0), m_len(initialSize) { m_str=(char*)malloc(m_len); } + ~GrowBuf() { free(m_str); } + void reserve(uint size) { if (m_len<size) { m_len = size; m_str = (char*)realloc(m_str,m_len); } } + void clear() { m_pos=0; } + void addChar(char c) { if (m_pos>=m_len) { m_len+=GROW_AMOUNT; m_str = (char*)realloc(m_str,m_len); } + m_str[m_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; + uint l=s.length(); + if (m_pos+l>=m_len) { m_len+=l+GROW_AMOUNT; m_str = (char*)realloc(m_str,m_len); } + strcpy(&m_str[m_pos],s.data()); + m_pos+=l; } } void addStr(const char *s) { if (s) { - int l=strlen(s); - if (pos+l>=len) { len+=l+GROW_AMOUNT; str = (char*)realloc(str,len); } - strcpy(&str[pos],s); - pos+=l; + uint l=(uint)strlen(s); + if (m_pos+l>=m_len) { m_len+=l+GROW_AMOUNT; m_str = (char*)realloc(m_str,m_len); } + strcpy(&m_str[m_pos],s); + m_pos+=l; } } - void addStr(const char *s,int n) { + void addStr(const char *s,uint n) { if (s) { - int l=strlen(s); + uint l=(uint)strlen(s); if (n<l) l=n; - if (pos+l>=len) { len+=l+GROW_AMOUNT; str = (char*)realloc(str,len); } - strncpy(&str[pos],s,n); - pos+=l; + if (m_pos+l>=m_len) { m_len+=l+GROW_AMOUNT; m_str = (char*)realloc(m_str,m_len); } + strncpy(&m_str[m_pos],s,n); + m_pos+=l; } } - const char *get() { return str; } - int getPos() const { return pos; } - void setPos(const int newPos) { pos = newPos; } - char at(int i) const { return str[i]; } + const char *get() { return m_str; } + uint getPos() const { return m_pos; } + void setPos(uint newPos) { m_pos = newPos; } + char at(uint i) const { return m_str[i]; } private: - char *str; - int pos; - int len; + char *m_str; + uint m_pos; + uint m_len; }; #endif diff --git a/src/htags.cpp b/src/htags.cpp index 1a240b1..0c3a9af 100644 --- a/src/htags.cpp +++ b/src/htags.cpp @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -36,25 +36,25 @@ static QDict<QCString> g_symbolDict(10007); */ bool Htags::execute(const QCString &htmldir) { - static QStrList &inputSource = Config_getList(INPUT); - static bool quiet = Config_getBool(QUIET); - static bool warnings = Config_getBool(WARNINGS); - static QCString htagsOptions = ""; //Config_getString(HTAGS_OPTIONS); - static QCString projectName = Config_getString(PROJECT_NAME); - static QCString projectNumber = Config_getString(PROJECT_NUMBER); + const StringVector &inputSource = Config_getList(INPUT); + bool quiet = Config_getBool(QUIET); + bool warnings = Config_getBool(WARNINGS); + QCString htagsOptions = ""; //Config_getString(HTAGS_OPTIONS); + QCString projectName = Config_getString(PROJECT_NAME); + QCString projectNumber = Config_getString(PROJECT_NUMBER); QCString cwd = QDir::currentDirPath().utf8(); - if (inputSource.isEmpty()) + if (inputSource.empty()) { g_inputDir.setPath(cwd); } - else if (inputSource.count()==1) + else if (inputSource.size()==1) { - g_inputDir.setPath(inputSource.first()); + g_inputDir.setPath(inputSource.back().c_str()); if (!g_inputDir.exists()) err("Cannot find directory %s. " "Check the value of the INPUT tag in the configuration file.\n", - inputSource.first() + inputSource.back().c_str() ); } else @@ -69,16 +69,16 @@ bool Htags::execute(const QCString &htmldir) QCString commandLine = " -g -s -a -n "; if (!quiet) commandLine += "-v "; if (warnings) commandLine += "-w "; - if (!htagsOptions.isEmpty()) + if (!htagsOptions.isEmpty()) { commandLine += ' '; commandLine += htagsOptions; } - if (!projectName.isEmpty()) + if (!projectName.isEmpty()) { commandLine += "-t \""; commandLine += projectName; - if (!projectNumber.isEmpty()) + if (!projectNumber.isEmpty()) { commandLine += '-'; commandLine += projectNumber; @@ -150,7 +150,7 @@ bool Htags::loadFilemap(const QCString &htmlDir) } else { - err("file %s cannot be opened\n",fileMapName.data()); + err("file %s cannot be opened\n",fileMapName.data()); } } return FALSE; diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 424fead..ea2dffb 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -36,6 +36,7 @@ #include "htmlentity.h" #include "emoji.h" #include "plantuml.h" +#include "formula.h" static const int NUM_HTML_LIST_TYPES = 4; static const char types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"}; @@ -180,6 +181,10 @@ static bool isDocIncludeVisible(DocInclude *s) { case DocInclude::DontInclude: case DocInclude::LatexInclude: + case DocInclude::RtfInclude: + case DocInclude::ManInclude: + case DocInclude::XmlInclude: + case DocInclude::DocbookInclude: return FALSE; default: return TRUE; @@ -715,6 +720,10 @@ void HtmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::DontInclude: case DocInclude::LatexInclude: + case DocInclude::RtfInclude: + case DocInclude::ManInclude: + case DocInclude::XmlInclude: + case DocInclude::DocbookInclude: case DocInclude::DontIncWithLines: break; case DocInclude::HtmlInclude: @@ -880,10 +889,25 @@ void HtmlDocVisitor::visit(DocFormula *f) m_t << "\" alt=\""; filterQuotedCdataAttr(f->text()); m_t << "\""; - // TODO: cache image dimensions on formula generation and give height/width - // for faster preloading and better rendering of the page - m_t << " src=\"" << f->relPath() << f->name() << ".png\"/>"; - + m_t << " src=\"" << f->relPath() << f->name(); + if (Config_getEnum(HTML_FORMULA_FORMAT)=="svg") + { + m_t << ".svg"; + } + else + { + m_t << ".png"; + } + FormulaManager::DisplaySize size = FormulaManager::instance().displaySize(f->id()); + if (size.width!=-1) + { + m_t << "\" width=\"" << size.width; + } + if (size.height!=-1) + { + m_t << "\" height=\"" << size.height; + } + m_t << "\"/>"; } if (bDisplay) { @@ -1726,7 +1750,7 @@ void HtmlDocVisitor::visitPre(DocImage *img) { src = correctURL(url,img->relPath()); } - if (typeSVG) + if (typeSVG && !inlineImage) { m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src) << "\"" << sizeAttribs << attrs; @@ -1765,14 +1789,7 @@ void HtmlDocVisitor::visitPre(DocImage *img) } else if (inlineImage) { - if (typeSVG) - { - m_t << ">" << alt << "</object>"; - } - else - { - m_t << "/>"; - } + m_t << "/>"; } } else // other format -> skip @@ -1792,16 +1809,7 @@ void HtmlDocVisitor::visitPost(DocImage *img) { if (inlineImage) { - if (img->isSVG()) - { - QCString alt; - QCString attrs = htmlAttribsToString(img->attribs(),&alt); - m_t << "\">" << alt << "</object>"; - } - else - { - m_t << "\"/>"; - } + m_t << "\"/>"; } else // end <div class="caption"> { @@ -2218,6 +2226,11 @@ void HtmlDocVisitor::filter(const char *str) case '<': m_t << "<"; break; case '>': m_t << ">"; break; case '&': m_t << "&"; break; + case '\\': if ((*p == '(') || (*p == ')')) + m_t << "\\‍" << *p++; + else + m_t << c; + break; default: m_t << c; } } @@ -2239,6 +2252,11 @@ void HtmlDocVisitor::filterQuotedCdataAttr(const char* str) case '"': m_t << """; break; case '<': m_t << "<"; break; case '>': m_t << ">"; break; + case '\\': if ((*p == '(') || (*p == ')')) + m_t << "\\‍" << *p++; + else + m_t << c; + break; default: m_t << c; } } @@ -2437,7 +2455,7 @@ void HtmlDocVisitor::forceEndParagraph(DocNode *n) nodeIndex--; } if (nodeIndex<0) return; // first visible node in paragraph - DocNode *n = para->children().at(nodeIndex); + n = para->children().at(nodeIndex); if (mustBeOutsideParagraph(n)) return; // previous node already outside paragraph context nodeIndex--; bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,nodeIndex); @@ -2474,7 +2492,7 @@ void HtmlDocVisitor::forceStartParagraph(DocNode *n) } if (nodeIndex<numNodes) { - DocNode *n = para->children().at(nodeIndex); + n = para->children().at(nodeIndex); if (mustBeOutsideParagraph(n)) return; // next element also outside paragraph } else diff --git a/src/htmlentity.cpp b/src/htmlentity.cpp index 543f86b..ae2d8f1 100644 --- a/src/htmlentity.cpp +++ b/src/htmlentity.cpp @@ -263,7 +263,7 @@ static struct htmlEntityInfo { SYM(clubs), "\xe2\x99\xa3", "♣", "<clubs/>", "♣", "{$\\clubsuit$}", NULL, "\\u9827?", { NULL, DocSymbol::Perl_unknown }}, { SYM(hearts), "\xe2\x99\xa5", "♥", "<hearts/>", "♥", "{$\\heartsuit$}", NULL, "\\u9829?", { NULL, DocSymbol::Perl_unknown }}, { SYM(diams), "\xe2\x99\xa6", "♦", "<diams/>", "♦", "{$\\diamondsuit$}", NULL, "\\u9830?", { NULL, DocSymbol::Perl_unknown }}, - { SYM(quot), "\"", """, "\"", """, "\"", "\"", "\"", { "\"", DocSymbol::Perl_char }}, + { SYM(quot), "\"", """, "\"", """, "\"{}", "\"", "\"", { "\"", DocSymbol::Perl_char }}, { SYM(amp), "&", "&", "&", "&", "\\&", "&", "&", { "&", DocSymbol::Perl_char }}, { SYM(lt), "<", "<", "<", "<", "<", "<", "<", { "<", DocSymbol::Perl_char }}, { SYM(gt), ">", ">", ">", ">", ">", ">", ">", { ">", DocSymbol::Perl_char }}, @@ -311,7 +311,7 @@ static struct htmlEntityInfo { SYM(DoubleColon), "::", "::", "::", "::", "::", "::", "::", { "::", DocSymbol::Perl_string }}, { SYM(Percent), "%", "%", "%", "%", "\\%", "%", "%", { "%", DocSymbol::Perl_char }}, { SYM(Pipe), "|", "|", "|", "|", "$|$", "|", "|", { "|", DocSymbol::Perl_char }}, - { SYM(Quot), "\"", "\"", "\"", """, "\"", "\"", "\"", { "\"", DocSymbol::Perl_char }}, + { SYM(Quot), "\"", "\"", "\"", """, "\"{}", "\"", "\"", { "\"", DocSymbol::Perl_char }}, { SYM(Minus), "-", "-", "-", "-", "-\\/", "-", "-", { "-", DocSymbol::Perl_char }}, { SYM(Plus), "+", "+", "+", "+", "+", "+", "+", { "+", DocSymbol::Perl_char }}, { SYM(Dot), ".", ".", ".", ".", ".", ".", ".", { ".", DocSymbol::Perl_char }}, diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index bf52eed..7b125af 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -67,7 +67,7 @@ static void writeClientSearchBox(FTextStream &t,const char *relPath) { t << " <div id=\"MSearchBox\" class=\"MSearchBoxInactive\">\n"; t << " <span class=\"left\">\n"; - t << " <img id=\"MSearchSelect\" src=\"" << relPath << "search/mag_sel.png\"\n"; + t << " <img id=\"MSearchSelect\" src=\"" << relPath << "search/mag_sel.svg\"\n"; t << " onmouseover=\"return searchBox.OnSearchSelectShow()\"\n"; t << " onmouseout=\"return searchBox.OnSearchSelectHide()\"\n"; t << " alt=\"\"/>\n"; @@ -78,7 +78,7 @@ static void writeClientSearchBox(FTextStream &t,const char *relPath) t << " onkeyup=\"searchBox.OnSearchFieldChange(event)\"/>\n"; t << " </span><span class=\"right\">\n"; t << " <a id=\"MSearchClose\" href=\"javascript:searchBox.CloseResultsWindow()\">" - << "<img id=\"MSearchCloseImg\" border=\"0\" src=\"" << relPath << "search/close.png\" alt=\"\"/></a>\n"; + << "<img id=\"MSearchCloseImg\" border=\"0\" src=\"" << relPath << "search/close.svg\" alt=\"\"/></a>\n"; t << " </span>\n"; t << " </div>\n"; } @@ -100,7 +100,7 @@ static void writeServerSearchBox(FTextStream &t,const char *relPath,bool highlig t << "search.php"; } t << "\" method=\"get\">\n"; - t << " <img id=\"MSearchSelect\" src=\"" << relPath << "search/mag.png\" alt=\"\"/>\n"; + t << " <img id=\"MSearchSelect\" src=\"" << relPath << "search/mag.svg\" alt=\"\"/>\n"; if (!highlightSearch) { t << " <input type=\"text\" id=\"MSearchField\" name=\"query\" value=\"" @@ -114,20 +114,28 @@ static void writeServerSearchBox(FTextStream &t,const char *relPath,bool highlig } //------------------------------------------------------------------------ -/// Convert a set of LaTeX `\(re)newcommand` to a form readable by MathJax +/// Convert a set of LaTeX commands `\(re)newcommand` to a form readable by MathJax /// LaTeX syntax: +/// ``` /// \newcommand{\cmd}{replacement} /// or /// \renewcommand{\cmd}{replacement} +/// ``` /// MathJax syntax: +/// ``` /// cmd: "{replacement}" +/// ``` /// /// LaTeX syntax: +/// ``` /// \newcommand{\cmd}[nr]{replacement} /// or /// \renewcommand{\cmd}[nr]{replacement} +/// ``` /// MathJax syntax: +/// ``` /// cmd: ["{replacement}",nr] +/// ``` static QCString getConvertLatexMacro() { QCString macrofile = Config_getString(FORMULA_MACROFILE); @@ -158,8 +166,14 @@ static QCString getConvertLatexMacro() return ""; } i++; - if (!qstrncmp(data + i, "newcommand", strlen("newcommand"))) i += strlen("newcommand"); - else if (!qstrncmp(data + i, "renewcommand", strlen("renewcommand"))) i += strlen("renewcommand"); + if (!qstrncmp(data + i, "newcommand", (uint)strlen("newcommand"))) + { + i += (int)strlen("newcommand"); + } + else if (!qstrncmp(data + i, "renewcommand", (uint)strlen("renewcommand"))) + { + i += (int)strlen("renewcommand"); + } else { warn(macrofile,line, "file contains non valid code, expected 'newcommand' or 'renewcommand'"); @@ -394,14 +408,13 @@ static QCString removeEmptyLines(const QCString &s) return out.data(); } -static QCString substituteHtmlKeywords(const QCString &s, +static QCString substituteHtmlKeywords(const QCString &str, const QCString &title, const QCString &relPath, const QCString &navPath=QCString()) { // Build CSS/JavaScript tags depending on treeview, search engine settings QCString cssFile; - QStrList extraCssFile; QCString generatedBy; QCString treeViewCssJs; QCString searchCssJs; @@ -442,10 +455,10 @@ static QCString substituteHtmlKeywords(const QCString &s, } extraCssText = ""; - extraCssFile = Config_getList(HTML_EXTRA_STYLESHEET); - for (uint i=0; i<extraCssFile.count(); ++i) + const StringVector &extraCssFile = Config_getList(HTML_EXTRA_STYLESHEET); + for (const auto &extraFile : extraCssFile) { - QCString fileName(extraCssFile.at(i)); + QCString fileName = extraFile.c_str(); if (!fileName.isEmpty()) { QFileInfo fi(fileName); @@ -527,12 +540,10 @@ static QCString substituteHtmlKeywords(const QCString &s, mathJaxJs = "<script type=\"text/x-mathjax-config\">\n" " MathJax.Hub.Config({\n" " extensions: [\"tex2jax.js\""; - QStrList &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS); - const char *s = mathJaxExtensions.first(); - while (s) + const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS); + for (const auto &s : mathJaxExtensions) { - mathJaxJs+= ", \""+QCString(s)+".js\""; - s = mathJaxExtensions.next(); + mathJaxJs+= ", \""+QCString(s.c_str())+".js\""; } if (mathJaxFormat.isEmpty()) { @@ -562,7 +573,7 @@ static QCString substituteHtmlKeywords(const QCString &s, } // first substitute generic keywords - QCString result = substituteKeywords(s,title, + QCString result = substituteKeywords(str,title, convertToHtml(Config_getString(PROJECT_NAME)), convertToHtml(Config_getString(PROJECT_NUMBER)), convertToHtml(Config_getString(PROJECT_BRIEF))); @@ -654,6 +665,10 @@ void HtmlCodeGenerator::codify(const char *str) { m_t << "<"; p++; } else if (*p=='>') { m_t << ">"; p++; } + else if (*p=='(') + { m_t << "\\‍("; m_col++;p++; } + else if (*p==')') + { m_t << "\\‍)"; m_col++;p++; } else m_t << "\\"; m_col++; @@ -668,7 +683,7 @@ void HtmlCodeGenerator::codify(const char *str) void HtmlCodeGenerator::docify(const char *str) { - m_t << getHtmlDirEmbeddingChar(getTextDirByConfig(str)); + //m_t << getHtmlDirEmbeddingChar(getTextDirByConfig(str)); if (str && m_streamSet) { @@ -688,6 +703,10 @@ void HtmlCodeGenerator::docify(const char *str) { m_t << "<"; p++; } else if (*p=='>') { m_t << ">"; p++; } + else if (*p=='(') + { m_t << "\\‍("; p++; } + else if (*p==')') + { m_t << "\\‍)"; p++; } else m_t << "\\"; break; @@ -997,7 +1016,7 @@ void HtmlGenerator::writeTabData() mgr.copyResource("nav_h.lum",dname); mgr.copyResource("nav_f.lum",dname); mgr.copyResource("bc_s.luma",dname); - mgr.copyResource("doxygen.luma",dname); + mgr.copyResource("doxygen.svg",dname); mgr.copyResource("closed.luma",dname); mgr.copyResource("open.luma",dname); mgr.copyResource("bdwn.luma",dname); @@ -1027,15 +1046,15 @@ void HtmlGenerator::writeSearchData(const char *dir) Doxygen::indexList->addImageFile("search/search_r.png"); if (serverBasedSearch) { - mgr.copyResource("mag.png",dir); - Doxygen::indexList->addImageFile("search/mag.png"); + mgr.copyResource("mag.svg",dir); + Doxygen::indexList->addImageFile("search/mag.svg"); } else { - mgr.copyResource("close.png",dir); - Doxygen::indexList->addImageFile("search/close.png"); - mgr.copyResource("mag_sel.png",dir); - Doxygen::indexList->addImageFile("search/mag_sel.png"); + mgr.copyResource("close.svg",dir); + Doxygen::indexList->addImageFile("search/close.svg"); + mgr.copyResource("mag_sel.svg",dir); + Doxygen::indexList->addImageFile("search/mag_sel.svg"); } QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search"; @@ -1056,7 +1075,7 @@ void HtmlGenerator::writeSearchData(const char *dir) { searchCss = mgr.getAsString("search.css"); } - searchCss = substitute(replaceColorMarkers(searchCss),"$doxygenversion",getVersion()); + searchCss = substitute(replaceColorMarkers(searchCss),"$doxygenversion",getDoxygenVersion()); t << searchCss; Doxygen::indexList->addStyleSheetFile("search/search.css"); } @@ -1065,20 +1084,20 @@ void HtmlGenerator::writeSearchData(const char *dir) void HtmlGenerator::writeStyleSheetFile(QFile &file) { FTextStream t(&file); - t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",getVersion())); + t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",getDoxygenVersion())); } void HtmlGenerator::writeHeaderFile(QFile &file, const char * /*cssname*/) { FTextStream t(&file); - t << "<!-- HTML header for doxygen " << getVersion() << "-->" << endl; + t << "<!-- HTML header for doxygen " << getDoxygenVersion() << "-->" << endl; t << ResourceMgr::instance().getAsString("header.html"); } void HtmlGenerator::writeFooterFile(QFile &file) { FTextStream t(&file); - t << "<!-- HTML footer for doxygen " << getVersion() << "-->" << endl; + t << "<!-- HTML footer for doxygen " << getDoxygenVersion() << "-->" << endl; t << ResourceMgr::instance().getAsString("footer.html"); } @@ -1099,7 +1118,7 @@ void HtmlGenerator::startFile(const char *name,const char *, t << substituteHtmlKeywords(g_header,convertToHtml(filterTitle(title)),m_relPath); t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " - << getVersion() << " -->" << endl; + << getDoxygenVersion() << " -->" << endl; //static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); static bool searchEngine = Config_getBool(SEARCHENGINE); if (searchEngine /*&& !generateTreeView*/) @@ -1162,8 +1181,8 @@ QCString HtmlGenerator::writeLogoAsString(const char *path) result += " \n<a href=\"http://www.doxygen.org/index.html\">\n" "<img class=\"footer\" src=\""; result += path; - result += "doxygen.png\" alt=\"doxygen\"/></a> "; - result += getVersion(); + result += "doxygen.svg\" width=\"104\" height=\"31\" alt=\"doxygen\"/></a> "; + result += getDoxygenVersion(); result += " "; return result; } @@ -1216,7 +1235,7 @@ void HtmlGenerator::writeStyleInfo(int part) //t << "H1 { text-align: center; border-width: thin none thin none;" << endl; //t << " border-style : double; border-color : blue; padding-left : 1em; padding-right : 1em }" << endl; - t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",getVersion())); + t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",getDoxygenVersion())); endPlainFile(); Doxygen::indexList->addStyleSheetFile("doxygen.css"); } @@ -1239,10 +1258,10 @@ void HtmlGenerator::writeStyleInfo(int part) } Doxygen::indexList->addStyleSheetFile(cssfi.fileName().utf8()); } - static QStrList extraCssFile = Config_getList(HTML_EXTRA_STYLESHEET); - for (uint i=0; i<extraCssFile.count(); ++i) + const StringVector &extraCssFiles = Config_getList(HTML_EXTRA_STYLESHEET); + for (const auto &extraCss : extraCssFiles) { - QCString fileName(extraCssFile.at(i)); + QCString fileName = extraCss.c_str(); if (!fileName.isEmpty()) { QFileInfo fi(fileName); @@ -1435,29 +1454,29 @@ void HtmlGenerator::endGroupHeader(int extraIndentLevel) } } -void HtmlGenerator::startSection(const char *lab,const char *,SectionInfo::SectionType type) +void HtmlGenerator::startSection(const char *lab,const char *,SectionType type) { switch(type) { - case SectionInfo::Page: t << "\n\n<h1>"; break; - case SectionInfo::Section: t << "\n\n<h2>"; break; - case SectionInfo::Subsection: t << "\n\n<h3>"; break; - case SectionInfo::Subsubsection: t << "\n\n<h4>"; break; - case SectionInfo::Paragraph: t << "\n\n<h5>"; break; + case SectionType::Page: t << "\n\n<h1>"; break; + case SectionType::Section: t << "\n\n<h2>"; break; + case SectionType::Subsection: t << "\n\n<h3>"; break; + case SectionType::Subsubsection: t << "\n\n<h4>"; break; + case SectionType::Paragraph: t << "\n\n<h5>"; break; default: ASSERT(0); break; } t << "<a id=\"" << lab << "\"></a>"; } -void HtmlGenerator::endSection(const char *,SectionInfo::SectionType type) +void HtmlGenerator::endSection(const char *,SectionType type) { switch(type) { - case SectionInfo::Page: t << "</h1>"; break; - case SectionInfo::Section: t << "</h2>"; break; - case SectionInfo::Subsection: t << "</h3>"; break; - case SectionInfo::Subsubsection: t << "</h4>"; break; - case SectionInfo::Paragraph: t << "</h5>"; break; + case SectionType::Page: t << "</h1>"; break; + case SectionType::Section: t << "</h2>"; break; + case SectionType::Subsection: t << "</h3>"; break; + case SectionType::Subsubsection: t << "</h4>"; break; + case SectionType::Paragraph: t << "</h5>"; break; default: ASSERT(0); break; } } @@ -1488,6 +1507,10 @@ void HtmlGenerator::docify(const char *str,bool inHtmlComment) { t << "<"; p++; } else if (*p=='>') { t << ">"; p++; } + else if (*p=='(') + { t << "\\‍("; p++; } + else if (*p==')') + { t << "\\‍)"; p++; } else t << "\\"; break; @@ -2634,7 +2657,7 @@ void HtmlGenerator::writeSearchPage() t << substituteHtmlKeywords(g_header,"Search",""); t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " - << getVersion() << " -->" << endl; + << getDoxygenVersion() << " -->" << endl; t << "<script type=\"text/javascript\">\n"; t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "var searchBox = new SearchBox(\"searchBox\", \"" @@ -2679,7 +2702,6 @@ void HtmlGenerator::writeSearchPage() void HtmlGenerator::writeExternalSearchPage() { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - static bool disableIndex = Config_getBool(DISABLE_INDEX); QCString fileName = Config_getString(HTML_OUTPUT)+"/search"+Doxygen::htmlFileExtension; QFile f(fileName); if (f.open(IO_WriteOnly)) @@ -2688,7 +2710,7 @@ void HtmlGenerator::writeExternalSearchPage() t << substituteHtmlKeywords(g_header,"Search",""); t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " - << getVersion() << " -->" << endl; + << getDoxygenVersion() << " -->" << endl; t << "<script type=\"text/javascript\">\n"; t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "var searchBox = new SearchBox(\"searchBox\", \"" @@ -2743,11 +2765,10 @@ void HtmlGenerator::writeExternalSearchPage() t << "var tagMap = {" << endl; bool first=TRUE; // add search mappings - QStrList &extraSearchMappings = Config_getList(EXTRA_SEARCH_MAPPINGS); - char *ml=extraSearchMappings.first(); - while (ml) + const StringVector &extraSearchMappings = Config_getList(EXTRA_SEARCH_MAPPINGS); + for (const auto &ml : extraSearchMappings) { - QCString mapLine = ml; + QCString mapLine = ml.c_str(); int eqPos = mapLine.find('='); if (eqPos!=-1) // tag command contains a destination { @@ -2760,7 +2781,6 @@ void HtmlGenerator::writeExternalSearchPage() first=FALSE; } } - ml=extraSearchMappings.next(); } if (!first) t << endl; t << "};" << endl << endl; diff --git a/src/htmlgen.h b/src/htmlgen.h index fe84061..a8268da 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -250,8 +250,8 @@ class HtmlGenerator : public OutputGenerator void endExamples(); void startParamList(ParamListTypes,const char *); void endParamList(); - void startSection(const char *,const char *,SectionInfo::SectionType); - void endSection(const char *,SectionInfo::SectionType); + void startSection(const char *,const char *,SectionType); + void endSection(const char *,SectionType); void addIndexItem(const char *,const char *); void startIndent(); void endIndent(); diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index 066e6f7..a1b0deb 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -17,15 +15,14 @@ * Harm van der Heijden. */ +#include <algorithm> + #include <stdio.h> #include <stdlib.h> -#include <qlist.h> -#include <qdict.h> #include <qregexp.h> #include <qfile.h> +#include <qfileinfo.h> -#include "qtextcodec.h" -#include "sortdict.h" #include "htmlhelp.h" #include "config.h" #include "message.h" @@ -36,12 +33,75 @@ #include "memberdef.h" #include "filedef.h" #include "util.h" +#include "linkedmap.h" + +//---------------------------------------------------------------------------- + +/** Helper class to deal with recoding the UTF8 encoded text back to the native encoding + * specified by CHM_INDEX_ENCODING. + */ +class HtmlHelpRecoder +{ + public: + HtmlHelpRecoder() {} + ~HtmlHelpRecoder() { finalize(); } + HtmlHelpRecoder(const HtmlHelpRecoder &) = delete; + HtmlHelpRecoder &operator=(const HtmlHelpRecoder &) = delete; + + void initialize() + { + const char *str = Config_getString(CHM_INDEX_ENCODING); + if (!str) str = "CP1250"; // use safe and likely default + m_fromUtf8 = portable_iconv_open(str,"UTF-8"); + if (m_fromUtf8==m_iconv_null) + { + term("unsupported character conversion for CHM_INDEX_ENCODING: '%s'->'UTF-8'\n", str); + } + } + void finalize() + { + if (m_fromUtf8!=m_iconv_null) + { + portable_iconv_close(m_fromUtf8); + m_fromUtf8 = m_iconv_null; + } + } + + QCString recode(const QCString &s) + { + int iSize = s.length(); + int oSize = iSize*4+1; + QCString output(oSize); + size_t iLeft = iSize; + size_t oLeft = oSize; + char *iPtr = s.rawData(); + char *oPtr = output.rawData(); + if (!portable_iconv(m_fromUtf8,&iPtr,&iLeft,&oPtr,&oLeft)) + { + oSize -= (int)oLeft; + output.resize(oSize+1); + output.at(oSize)='\0'; + return output; + } + else + { + return s; + } + } + private: + void *m_iconv_null = (void*)(-1); + void *m_fromUtf8 = m_iconv_null; + +}; //---------------------------------------------------------------------------- /** Class representing a field in the HTML help index. */ struct IndexField { + IndexField(const char *k,const char *n,const char *u,const char *a,bool l,bool r) : + key(k), name(n), url(u), anchor(a), link(l), reversed(r) {} + QCString key; QCString name; QCString url; QCString anchor; @@ -62,37 +122,35 @@ class IndexFieldSDict : public SDict<IndexField> } }; -/** A helper class for HtmlHelp that manages a two level index in +/** A helper class for HtmlHelp that manages a two level index in * alphabetical order. */ class HtmlHelpIndex { public: - HtmlHelpIndex(HtmlHelp *help); + HtmlHelpIndex(HtmlHelpRecoder &recoder); ~HtmlHelpIndex(); - void addItem(const char *first,const char *second, + void addItem(const char *first,const char *second, const char *url, const char *anchor, bool hasLink,bool reversed); void writeFields(FTextStream &t); + size_t size() const { return m_map.size(); } private: - IndexFieldSDict *dict; - HtmlHelp *m_help; + LinkedMap<IndexField> m_map; + HtmlHelpRecoder &m_recoder; }; /*! Constructs a new HtmlHelp index */ -HtmlHelpIndex::HtmlHelpIndex(HtmlHelp *help) : m_help(help) +HtmlHelpIndex::HtmlHelpIndex(HtmlHelpRecoder &recoder) : m_recoder(recoder) { - dict = new IndexFieldSDict; - dict->setAutoDelete(TRUE); } /*! Destroys the HtmlHelp index */ HtmlHelpIndex::~HtmlHelpIndex() { - delete dict; } -/*! Stores an item in the index if it is not already present. +/*! Stores an item in the index if it is not already present. * Items are stored in alphabetical order, by sorting on the * concatenation of \a level1 and \a level2 (if present). * @@ -100,7 +158,7 @@ HtmlHelpIndex::~HtmlHelpIndex() * \param level2 the string at level 2 in the index (or 0 if not applicable). * \param url the url of the documentation (without .html extension). * \param anchor the anchor of the documentation within the page. - * \param hasLink if true, the url (without anchor) can be used in the + * \param hasLink if true, the url (without anchor) can be used in the * level1 item, when writing the header of a list of level2 items. * \param reversed TRUE if level1 is the member name and level2 the compound * name. @@ -109,30 +167,19 @@ void HtmlHelpIndex::addItem(const char *level1,const char *level2, const char *url,const char *anchor,bool hasLink, bool reversed) { - QCString key = level1; + QCString key = level1; if (level2) key+= (QCString)"?" + level2; if (key.find(QRegExp("@[0-9]+"))!=-1) // skip anonymous stuff { return; } - if (dict->find(key+anchor)==0) // new key - { - //printf(">>>>>>>>> HtmlHelpIndex::addItem(%s,%s,%s,%s)\n", - // level1,level2,url,anchor); - IndexField *f = new IndexField; - f->name = key; - f->url = url; - f->anchor = anchor; - f->link = hasLink; - f->reversed = reversed; - dict->append(key+anchor,f); - } + m_map.add(key+anchor,key,url,anchor,hasLink,reversed); } static QCString field2URL(const IndexField *f,bool checkReversed) { QCString result = f->url + Doxygen::htmlFileExtension; - if (!f->anchor.isEmpty() && (!checkReversed || f->reversed)) + if (!f->anchor.isEmpty() && (!checkReversed || f->reversed)) { // HTML Help needs colons in link anchors to be escaped in the .hhk file. result+="#"+substitute(f->anchor,":","%3A"); @@ -163,31 +210,32 @@ static QCString field2URL(const IndexField *f,bool checkReversed) * b2 -> link to url#anchor * a3 -> link to url if hasLink==TRUE * a4 -> link to url if hasLink==TRUE - * b1 -> link to url#anchor + * b1 -> link to url#anchor * </pre> */ void HtmlHelpIndex::writeFields(FTextStream &t) { - dict->sort(); - IndexFieldSDict::Iterator ifli(*dict); - IndexField *f; - QCString lastLevel1; + std::sort(std::begin(m_map), + std::end(m_map), + [](const auto &e1,const auto &e2) { return e1->name < e2->name; } + ); + QCString prevLevel1; bool level2Started=FALSE; - for (;(f=ifli.current());++ifli) + for (auto it = std::begin(m_map); it!=std::end(m_map); ++it) { + auto &f = *it; QCString level1,level2; int i; if ((i=f->name.find('?'))!=-1) { level1 = f->name.left(i); - level2 = f->name.right(f->name.length()-i-1); + level2 = f->name.right(f->name.length()-i-1); } else { - level1 = f->name.copy(); + level1 = f->name; } - //if (level1!=lastLevel1) { // finish old list at level 2 if (level2Started) t << " </UL>" << endl; level2Started=FALSE; @@ -200,24 +248,25 @@ void HtmlHelpIndex::writeFields(FTextStream &t) // a2, b2 // a2, b3 QCString nextLevel1; - IndexField* fnext = ++ifli; - if (fnext) + auto it_next = std::next(it); + if (it_next!=std::end(m_map)) { + auto &fnext = *it_next; nextLevel1 = fnext->name.left(fnext->name.find('?')); - --ifli; } - if (level1 != nextLevel1) + if (!(level1 == prevLevel1 || level1 == nextLevel1)) { level2 = ""; } + prevLevel1 = level1; // </Antony> if (level2.isEmpty()) { t << " <LI><OBJECT type=\"text/sitemap\">"; - t << "<param name=\"Local\" value=\"" << field2URL(f,FALSE); + t << "<param name=\"Local\" value=\"" << field2URL(f.get(),FALSE); t << "\">"; - t << "<param name=\"Name\" value=\"" << m_help->recode(level1) << "\">" + t << "<param name=\"Name\" value=\"" << m_recoder.recode(level1) << "\">" "</OBJECT>\n"; } else @@ -225,16 +274,16 @@ void HtmlHelpIndex::writeFields(FTextStream &t) if (f->link) { t << " <LI><OBJECT type=\"text/sitemap\">"; - t << "<param name=\"Local\" value=\"" << field2URL(f,TRUE); + t << "<param name=\"Local\" value=\"" << field2URL(f.get(),TRUE); t << "\">"; - t << "<param name=\"Name\" value=\"" << m_help->recode(level1) << "\">" + t << "<param name=\"Name\" value=\"" << m_recoder.recode(level1) << "\">" "</OBJECT>\n"; } else { t << " <LI><OBJECT type=\"text/sitemap\">"; - t << "<param name=\"See Also\" value=\"" << m_help->recode(level1) << "\">"; - t << "<param name=\"Name\" value=\"" << m_help->recode(level1) << "\">" + t << "<param name=\"See Also\" value=\"" << m_recoder.recode(level1) << "\">"; + t << "<param name=\"Name\" value=\"" << m_recoder.recode(level1) << "\">" "</OBJECT>\n"; } } @@ -252,195 +301,185 @@ void HtmlHelpIndex::writeFields(FTextStream &t) if (level2Started) { t << " <LI><OBJECT type=\"text/sitemap\">"; - t << "<param name=\"Local\" value=\"" << field2URL(f,FALSE); + t << "<param name=\"Local\" value=\"" << field2URL(f.get(),FALSE); t << "\">"; - t << "<param name=\"Name\" value=\"" << m_help->recode(level2) << "\">" + t << "<param name=\"Name\" value=\"" << m_recoder.recode(level2) << "\">" "</OBJECT>\n"; } - lastLevel1 = level1.copy(); - } + } if (level2Started) t << " </UL>" << endl; } //---------------------------------------------------------------------------- +// +class HtmlHelp::Private +{ + public: + Private() : index(recoder) {} + void createProjectFile(); + QFile cf; + QFile kf; + FTextStream cts,kts; + bool ctsItemPresent = false; + int dc = 0; + StringSet indexFiles; + StringSet imageFiles; + HtmlHelpIndex index; + HtmlHelpRecoder recoder; +}; -HtmlHelp *HtmlHelp::theInstance = 0; -/*! Constructs an html object. - * The object has to be \link initialize() initialized\endlink before it can +/*! Constructs an html object. + * The object has to be \link initialize() initialized\endlink before it can * be used. */ -HtmlHelp::HtmlHelp() : indexFileDict(1009) +HtmlHelp::HtmlHelp() : p(std::make_unique<Private>()) { - /* initial depth */ - dc = 0; - cf = kf = 0; - index = new HtmlHelpIndex(this); - m_fromUtf8 = (void *)(-1); } HtmlHelp::~HtmlHelp() { - if (m_fromUtf8!=(void *)(-1)) portable_iconv_close(m_fromUtf8); - delete index; } -#if 0 -/*! return a reference to the one and only instance of this class. - */ -HtmlHelp *HtmlHelp::getInstance() -{ - if (theInstance==0) theInstance = new HtmlHelp; - return theInstance; -} -#endif -static QDict<QCString> s_languageDict; +/* language codes for Html help + 0x405 Czech + 0x406 Danish + 0x413 Dutch + 0xC09 English (Australia) + 0x809 English (Britain) + 0x1009 English (Canada) + 0x1809 English (Ireland) + 0x1409 English (New Zealand) + 0x1C09 English (South Africa) + 0x409 English (United States) + 0x40B Finnish + 0x40C French + 0x407 German + 0x408 Greece + 0x40E Hungarian + 0x410 Italian + 0x814 Norwegian + 0x415 Polish + 0x816 Portuguese(Portugal) + 0x416 Portuguese(Brazil) + 0x419 Russian + 0x80A Spanish(Mexico) + 0xC0A Spanish(Modern Sort) + 0x40A Spanish(Traditional Sort) + 0x41D Swedish + 0x41F Turkey + 0x411 Japanese + 0x412 Korean + 0x804 Chinese (PRC) + 0x404 Chinese (Taiwan) + + New LCIDs: + 0x421 Indonesian + 0x41A Croatian + 0x418 Romanian + 0x424 Slovenian + 0x41B Slovak + 0x422 Ukrainian + 0x81A Serbian (Serbia, Latin) + 0x403 Catalan + 0x426 Latvian + 0x427 Lithuanian + 0x436 Afrikaans + 0x42A Vietnamese + 0x429 Persian (Iran) + 0xC01 Arabic (Egypt) - I don't know which version of arabic is used inside translator_ar.h , + so I have chosen Egypt at random + +*/ +static StringUnorderedMap s_languageDict = +{ + { "czech", "0x405 Czech" }, + { "danish", "0x406 Danish" }, + { "dutch", "0x413 Dutch" }, + { "finnish", "0x40B Finnish" }, + { "french", "0x40C French" }, + { "german", "0x407 German" }, + { "greek", "0x408 Greece" }, + { "hungarian", "0x40E Hungarian" }, + { "italian", "0x410 Italian" }, + { "norwegian", "0x814 Norwegian" }, + { "polish", "0x415 Polish" }, + { "portuguese", "0x816 Portuguese(Portugal)" }, + { "brazilian", "0x416 Portuguese(Brazil)" }, + { "russian", "0x419 Russian" }, + { "spanish", "0x40A Spanish(Traditional Sort)" }, + { "swedish", "0x41D Swedish" }, + { "turkish", "0x41F Turkey" }, + { "japanese", "0x411 Japanese" }, + { "japanese-en", "0x411 Japanese" }, + { "korean", "0x412 Korean" }, + { "korean-en", "0x412 Korean" }, + { "chinese", "0x804 Chinese (PRC)" }, + { "chinese-traditional", "0x404 Chinese (Taiwan)" }, + { "indonesian", "0x421 Indonesian" }, + { "croatian", "0x41A Croatian" }, + { "romanian", "0x418 Romanian" }, + { "slovene", "0x424 Slovenian" }, + { "slovak", "0x41B Slovak" }, + { "ukrainian", "0x422 Ukrainian" }, + { "serbian", "0x81A Serbian (Serbia, Latin)" }, + { "catalan", "0x403 Catalan" }, + { "lithuanian", "0x427 Lithuanian" }, + { "afrikaans", "0x436 Afrikaans" }, + { "vietnamese", "0x42A Vietnamese" }, + { "persian", "0x429 Persian (Iran)" }, + { "arabic", "0xC01 Arabic (Egypt)" }, + { "latvian", "0x426 Latvian" }, + { "macedonian", "0x042f Macedonian (Former Yugoslav Republic of Macedonia)" }, + { "armenian", "0x42b Armenian" }, + //Code for Esperanto should be as shown below but the htmlhelp compiler 1.3 does not support this + // (and no newer version is available). + //So do a fallback to the default language (see getLanguageString()) + //{ "esperanto", "0x48f Esperanto" }, + { "serbian-cyrillic", "0xC1A Serbian (Serbia, Cyrillic)" } +}; /*! This will create a contents file (index.hhc) and a index file (index.hhk) - * and write the header of those files. + * and write the header of those files. * It also creates a project file (index.hhp) * \sa finalize() */ void HtmlHelp::initialize() { - const char *str = Config_getString(CHM_INDEX_ENCODING); - if (!str) str = "CP1250"; // use safe and likely default - m_fromUtf8 = portable_iconv_open(str,"UTF-8"); - if (m_fromUtf8==(void *)(-1)) - { - term("unsupported character conversion for CHM_INDEX_ENCODING: '%s'->'UTF-8'\n", str); - } + p->recoder.initialize(); /* open the contents file */ QCString fName = Config_getString(HTML_OUTPUT) + "/index.hhc"; - cf = new QFile(fName); - if (!cf->open(IO_WriteOnly)) + p->cf.setName(fName); + if (!p->cf.open(IO_WriteOnly)) { term("Could not open file %s for writing\n",fName.data()); } /* Write the header of the contents file */ - cts.setDevice(cf); - cts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n" + p->cts.setDevice(&p->cf); + p->cts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n" "<HTML><HEAD></HEAD><BODY>\n" "<OBJECT type=\"text/site properties\">\n" "<param name=\"FrameName\" value=\"right\">\n" "</OBJECT>\n" "<UL>\n"; - + /* open the contents file */ fName = Config_getString(HTML_OUTPUT) + "/index.hhk"; - kf = new QFile(fName); - if (!kf->open(IO_WriteOnly)) + p->kf.setName(fName); + if (!p->kf.open(IO_WriteOnly)) { term("Could not open file %s for writing\n",fName.data()); } /* Write the header of the contents file */ - kts.setDevice(kf); - kts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n" + p->kts.setDevice(&p->kf); + p->kts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n" "<HTML><HEAD></HEAD><BODY>\n" "<OBJECT type=\"text/site properties\">\n" "<param name=\"FrameName\" value=\"right\">\n" "</OBJECT>\n" "<UL>\n"; - /* language codes for Html help - 0x405 Czech - 0x406 Danish - 0x413 Dutch - 0xC09 English (Australia) - 0x809 English (Britain) - 0x1009 English (Canada) - 0x1809 English (Ireland) - 0x1409 English (New Zealand) - 0x1C09 English (South Africa) - 0x409 English (United States) - 0x40B Finnish - 0x40C French - 0x407 German - 0x408 Greece - 0x40E Hungarian - 0x410 Italian - 0x814 Norwegian - 0x415 Polish - 0x816 Portuguese(Portugal) - 0x416 Portuguese(Brazil) - 0x419 Russian - 0x80A Spanish(Mexico) - 0xC0A Spanish(Modern Sort) - 0x40A Spanish(Traditional Sort) - 0x41D Swedish - 0x41F Turkey - 0x411 Japanese - 0x412 Korean - 0x804 Chinese (PRC) - 0x404 Chinese (Taiwan) - - New LCIDs: - 0x421 Indonesian - 0x41A Croatian - 0x418 Romanian - 0x424 Slovenian - 0x41B Slovak - 0x422 Ukrainian - 0x81A Serbian (Serbia, Latin) - 0x403 Catalan - 0x426 Latvian - 0x427 Lithuanian - 0x436 Afrikaans - 0x42A Vietnamese - 0x429 Persian (Iran) - 0xC01 Arabic (Egypt) - I don't know which version of arabic is used inside translator_ar.h , - so I have chosen Egypt at random - - */ - s_languageDict.setAutoDelete(TRUE); - s_languageDict.clear(); - s_languageDict.insert("czech", new QCString("0x405 Czech")); - s_languageDict.insert("danish", new QCString("0x406 Danish")); - s_languageDict.insert("dutch", new QCString("0x413 Dutch")); - s_languageDict.insert("finnish", new QCString("0x40B Finnish")); - s_languageDict.insert("french", new QCString("0x40C French")); - s_languageDict.insert("german", new QCString("0x407 German")); - s_languageDict.insert("greek", new QCString("0x408 Greece")); - s_languageDict.insert("hungarian", new QCString("0x40E Hungarian")); - s_languageDict.insert("italian", new QCString("0x410 Italian")); - s_languageDict.insert("norwegian", new QCString("0x814 Norwegian")); - s_languageDict.insert("polish", new QCString("0x415 Polish")); - s_languageDict.insert("portuguese", new QCString("0x816 Portuguese(Portugal)")); - s_languageDict.insert("brazilian", new QCString("0x416 Portuguese(Brazil)")); - s_languageDict.insert("russian", new QCString("0x419 Russian")); - s_languageDict.insert("spanish", new QCString("0x40A Spanish(Traditional Sort)")); - s_languageDict.insert("swedish", new QCString("0x41D Swedish")); - s_languageDict.insert("turkish", new QCString("0x41F Turkey")); - s_languageDict.insert("japanese", new QCString("0x411 Japanese")); - s_languageDict.insert("japanese-en", new QCString("0x411 Japanese")); - s_languageDict.insert("korean", new QCString("0x412 Korean")); - s_languageDict.insert("korean-en", new QCString("0x412 Korean")); - s_languageDict.insert("chinese", new QCString("0x804 Chinese (PRC)")); - s_languageDict.insert("chinese-traditional", new QCString("0x404 Chinese (Taiwan)")); - - // new LCIDs - s_languageDict.insert("indonesian", new QCString("0x412 Indonesian")); - s_languageDict.insert("croatian", new QCString("0x41A Croatian")); - s_languageDict.insert("romanian", new QCString("0x418 Romanian")); - s_languageDict.insert("slovene", new QCString("0x424 Slovenian")); - s_languageDict.insert("slovak", new QCString("0x41B Slovak")); - s_languageDict.insert("ukrainian", new QCString("0x422 Ukrainian")); - s_languageDict.insert("serbian", new QCString("0x81A Serbian (Serbia, Latin)")); - s_languageDict.insert("catalan", new QCString("0x403 Catalan")); - s_languageDict.insert("lithuanian", new QCString("0x427 Lithuanian")); - s_languageDict.insert("afrikaans", new QCString("0x436 Afrikaans")); - s_languageDict.insert("vietnamese", new QCString("0x42A Vietnamese")); - s_languageDict.insert("persian", new QCString("0x429 Persian (Iran)")); - s_languageDict.insert("arabic", new QCString("0xC01 Arabic (Egypt)")); - s_languageDict.insert("latvian", new QCString("0x426 Latvian")); - s_languageDict.insert("macedonian", new QCString("0x042f Macedonian (Former Yugoslav Republic of Macedonia)")); - s_languageDict.insert("armenian", new QCString("0x42b Armenian")); - //Code for Esperanto should be as shown below but the htmlhelp compiler 1.3 does not support this - // (and no newer version is available). - //So do a fallback to the default language (see getLanguageString()) - //s_languageDict.insert("esperanto", new QCString("0x48f Esperanto")); - s_languageDict.insert("serbian-cyrillic", new QCString("0xC1A Serbian (Serbia, Cyrillic)")); } @@ -448,19 +487,19 @@ QCString HtmlHelp::getLanguageString() { if (!theTranslator->idLanguage().isEmpty()) { - QCString *s = s_languageDict[theTranslator->idLanguage()]; - if (s) + auto it = s_languageDict.find(theTranslator->idLanguage().str()); + if (it!=s_languageDict.end()) { - return *s; + return it->second; } } // default language return "0x409 English (United States)"; } - -void HtmlHelp::createProjectFile() + +void HtmlHelp::Private::createProjectFile() { /* Write the project file */ QCString fName = Config_getString(HTML_OUTPUT) + "/index.hhp"; @@ -468,7 +507,13 @@ void HtmlHelp::createProjectFile() if (f.open(IO_WriteOnly)) { FTextStream t(&f); - + + const char *hhcFile = "\"index.hhc\""; + const char *hhkFile = "\"index.hhk\""; + bool hhkPresent = index.size()>0; + if (!ctsItemPresent) hhcFile = ""; + if (!hhkPresent) hhkFile = ""; + QCString indexName="index"+Doxygen::htmlFileExtension; t << "[OPTIONS]\n"; if (!Config_getString(CHM_FILE).isEmpty()) @@ -476,16 +521,16 @@ void HtmlHelp::createProjectFile() t << "Compiled file=" << Config_getString(CHM_FILE) << "\n"; } t << "Compatibility=1.1\n" - "Full-text search=Yes\n" - "Contents file=index.hhc\n" - "Default Window=main\n" - "Default topic=" << indexName << "\n" - "Index file=index.hhk\n" - "Language=" << getLanguageString() << endl; + "Full-text search=Yes\n"; + if (ctsItemPresent) t << "Contents file=index.hhc\n"; + t << "Default Window=main\n" + "Default topic=" << indexName << "\n"; + if (hhkPresent) t << "Index file=index.hhk\n"; + t << "Language=" << getLanguageString() << endl; if (Config_getBool(BINARY_TOC)) t << "Binary TOC=YES\n"; if (Config_getBool(GENERATE_CHI)) t << "Create CHI file=YES\n"; - t << "Title=" << recode(Config_getString(PROJECT_NAME)) << endl << endl; - + t << "Title=" << recoder.recode(Config_getString(PROJECT_NAME)) << endl << endl; + t << "[WINDOWS]" << endl; // NOTE: the 0x10387e number is a set of bits specifying the buttons @@ -500,28 +545,25 @@ void HtmlHelp::createProjectFile() // Value has been taken from htmlhelp.h file of the HTML Help Workshop if (Config_getBool(BINARY_TOC)) { - t << "main=\"" << recode(Config_getString(PROJECT_NAME)) << "\",\"index.hhc\"," - "\"index.hhk\",\"" << indexName << "\",\"" << + t << "main=\"" << recoder.recode(Config_getString(PROJECT_NAME)) << "\"," << hhcFile << "," + << hhkFile << ",\"" << indexName << "\",\"" << indexName << "\",,,,,0x23520,,0x70387e,,,,,,,,0" << endl << endl; } else { - t << "main=\"" << recode(Config_getString(PROJECT_NAME)) << "\",\"index.hhc\"," - "\"index.hhk\",\"" << indexName << "\",\"" << + t << "main=\"" << recoder.recode(Config_getString(PROJECT_NAME)) << "\"," << hhcFile << "," + << hhkFile << ",\"" << indexName << "\",\"" << indexName << "\",,,,,0x23520,,0x10387e,,,,,,,,0" << endl << endl; } - + t << "[FILES]" << endl; - char *s = indexFiles.first(); - while (s) + for (auto &s : indexFiles) { - t << s << endl; - s = indexFiles.next(); + t << s.c_str() << endl; } - uint i; - for (i=0;i<imageFiles.count();i++) + for (auto &s : imageFiles) { - t << imageFiles.at(i) << endl; + t << QFileInfo(s.c_str()).fileName().data() << endl; } f.close(); } @@ -533,11 +575,7 @@ void HtmlHelp::createProjectFile() void HtmlHelp::addIndexFile(const char *s) { - if (indexFileDict.find(s)==0) - { - indexFiles.append(s); - indexFileDict.insert(s,(void *)0x8); - } + p->indexFiles.insert(s); } /*! Finalizes the HTML help. This will finish and close the @@ -547,36 +585,35 @@ void HtmlHelp::addIndexFile(const char *s) void HtmlHelp::finalize() { // end the contents file - cts << "</UL>\n"; - cts << "</BODY>\n"; - cts << "</HTML>\n"; - cts.unsetDevice(); - cf->close(); - delete cf; - - index->writeFields(kts); - + p->cts << "</UL>\n"; + p->cts << "</BODY>\n"; + p->cts << "</HTML>\n"; + p->cts.unsetDevice(); + p->cf.close(); + + p->index.writeFields(p->kts); + // end the index file - kts << "</UL>\n"; - kts << "</BODY>\n"; - kts << "</HTML>\n"; - kts.unsetDevice(); - kf->close(); - delete kf; - - createProjectFile(); - s_languageDict.clear(); + p->kts << "</UL>\n"; + p->kts << "</BODY>\n"; + p->kts << "</HTML>\n"; + p->kts.unsetDevice(); + p->kf.close(); + + p->createProjectFile(); + + p->recoder.finalize(); } -/*! Increase the level of the contents hierarchy. +/*! Increase the level of the contents hierarchy. * This will start a new unnumbered HTML list in contents file. * \sa decContentsDepth() */ void HtmlHelp::incContentsDepth() { - int i; for (i=0;i<dc+1;i++) cts << " "; - cts << "<UL>\n"; - ++dc; + int i; for (i=0;i<p->dc+1;i++) p->cts << " "; + p->cts << "<UL>\n"; + ++p->dc; } /*! Decrease the level of the contents hierarchy. @@ -585,31 +622,9 @@ void HtmlHelp::incContentsDepth() */ void HtmlHelp::decContentsDepth() { - int i; for (i=0;i<dc;i++) cts << " "; - cts << "</UL>\n"; - --dc; -} - -QCString HtmlHelp::recode(const QCString &s) -{ - int iSize = s.length(); - int oSize = iSize*4+1; - QCString output(oSize); - size_t iLeft = iSize; - size_t oLeft = oSize; - char *iPtr = s.rawData(); - char *oPtr = output.rawData(); - if (!portable_iconv(m_fromUtf8,&iPtr,&iLeft,&oPtr,&oLeft)) - { - oSize -= (int)oLeft; - output.resize(oSize+1); - output.at(oSize)='\0'; - return output; - } - else - { - return s; - } + int i; for (i=0;i<p->dc;i++) p->cts << " "; + p->cts << "</UL>\n"; + --p->dc; } /*! Add an list item to the contents file. @@ -624,53 +639,54 @@ QCString HtmlHelp::recode(const QCString &s) */ void HtmlHelp::addContentsItem(bool isDir, const char *name, - const char * /*ref*/, + const char * /*ref*/, const char *file, const char *anchor, bool /* separateIndex */, bool /* addToNavIndex */, const Definition * /* def */) { - // If we're using a binary toc then folders cannot have links. + // If we're using a binary toc then folders cannot have links. // Tried this and I didn't see any problems, when not using // the resetting of file and anchor the TOC works better // (prev / next button) - //if(Config_getBool(BINARY_TOC) && isDir) + //if(Config_getBool(BINARY_TOC) && isDir) //{ //file = 0; //anchor = 0; //} - int i; for (i=0;i<dc;i++) cts << " "; - cts << "<LI><OBJECT type=\"text/sitemap\">"; - cts << "<param name=\"Name\" value=\"" << convertToHtml(recode(name),TRUE) << "\">"; + p->ctsItemPresent = true; + int i; for (i=0;i<p->dc;i++) p->cts << " "; + p->cts << "<LI><OBJECT type=\"text/sitemap\">"; + p->cts << "<param name=\"Name\" value=\"" << convertToHtml(p->recoder.recode(name),TRUE) << "\">"; if (file) // made file optional param - KPW { if (file && (file[0]=='!' || file[0]=='^')) // special markers for user defined URLs { - cts << "<param name=\""; - if (file[0]=='^') cts << "URL"; else cts << "Local"; - cts << "\" value=\""; - cts << &file[1]; + p->cts << "<param name=\""; + if (file[0]=='^') p->cts << "URL"; else p->cts << "Local"; + p->cts << "\" value=\""; + p->cts << &file[1]; } else { - cts << "<param name=\"Local\" value=\""; - cts << file << Doxygen::htmlFileExtension; - if (anchor) cts << "#" << anchor; + p->cts << "<param name=\"Local\" value=\""; + p->cts << file << Doxygen::htmlFileExtension; + if (anchor) p->cts << "#" << anchor; } - cts << "\">"; + p->cts << "\">"; } - cts << "<param name=\"ImageNumber\" value=\""; + p->cts << "<param name=\"ImageNumber\" value=\""; if (isDir) // added - KPW { - cts << (int)BOOK_CLOSED ; + p->cts << (int)BOOK_CLOSED ; } else { - cts << (int)TEXT; + p->cts << (int)TEXT; } - cts << "\">"; - cts << "</OBJECT>\n"; + p->cts << "\">"; + p->cts << "</OBJECT>\n"; } @@ -696,18 +712,18 @@ void HtmlHelp::addIndexItem(const Definition *context,const MemberDef *md, QCString contRef = separateMemberPages ? cfname : cfiname; QCString memRef = cfname; QCString anchor = sectionAnchor ? QCString(sectionAnchor) : md->anchor(); - index->addItem(level1,level2,contRef,anchor,TRUE,FALSE); - index->addItem(level2,level1,memRef,anchor,TRUE,TRUE); + p->index.addItem(level1,level2,contRef,anchor,TRUE,FALSE); + p->index.addItem(level2,level1,memRef,anchor,TRUE,TRUE); } else if (context) { QCString level1 = word ? QCString(word) : context->name(); - index->addItem(level1,0,context->getOutputFileBase(),sectionAnchor,TRUE,FALSE); + p->index.addItem(level1,0,context->getOutputFileBase(),sectionAnchor,TRUE,FALSE); } } void HtmlHelp::addImageFile(const char *fileName) { - if (!imageFiles.contains(fileName)) imageFiles.append(fileName); + p->imageFiles.insert(fileName); } diff --git a/src/htmlhelp.h b/src/htmlhelp.h index 184b929..421320e 100644 --- a/src/htmlhelp.h +++ b/src/htmlhelp.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -21,14 +19,10 @@ #ifndef HTMLHELP_H #define HTMLHELP_H -#include <qstrlist.h> -#include <qdict.h> +#include <memory> #include "index.h" -#include "ftextstream.h" -class QFile; class Definition; -class HtmlHelpIndex; /** A class that generated the HTML Help specific files. * @@ -37,10 +31,10 @@ class HtmlHelpIndex; */ class HtmlHelp : public IndexIntf { - /*! used in imageNumber param of HTMLHelp::addContentsItem() function - to specify document icon in tree view. + /*! used in imageNumber param of HTMLHelp::addContentsItem() function + to specify document icon in tree view. Writes \<param name="ImageNumber" value="xx"\> in .HHC file. */ - enum ImageNumber { + enum ImageNumber { BOOK_CLOSED=1, BOOK_OPEN, BOOK_CLOSED_NEW, BOOK_OPEN_NEW, FOLDER_CLOSED, FOLDER_OPEN, @@ -72,8 +66,8 @@ class HtmlHelp : public IndexIntf void incContentsDepth(); void decContentsDepth(); void addContentsItem(bool isDir, - const char *name, - const char *ref, + const char *name, + const char *ref, const char *file, const char *anchor, bool separateIndex, @@ -87,19 +81,10 @@ class HtmlHelp : public IndexIntf static QCString getLanguageString(); private: - friend class HtmlHelpIndex; - void createProjectFile(); - - QFile *cf,*kf; - FTextStream cts,kts; - HtmlHelpIndex *index; - int dc; - QStrList indexFiles; - QStrList imageFiles; - QDict<void> indexFileDict; - static HtmlHelp *theInstance; + class Private; + std::unique_ptr<Private> p; QCString recode(const QCString &s); - void *m_fromUtf8; + }; #endif /* HTMLHELP_H */ diff --git a/src/image.cpp b/src/image.cpp index afc67ef..2a8108b 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -207,7 +207,7 @@ static Color palette3[] = }; -Image::Image(int w,int h) +Image::Image(uint w,uint h) { static int hue = Config_getInt(HTML_COLORSTYLE_HUE); static int sat = Config_getInt(HTML_COLORSTYLE_SAT); @@ -236,49 +236,49 @@ Image::Image(int w,int h) palette[3].green = (int)(green2 * 255.0); palette[3].blue = (int)(blue2 * 255.0); - data = new uchar[w*h]; - memset(data,0,w*h); - width = w; - height = h; + m_data = new uchar[w*h]; + memset(m_data,0,w*h); + m_width = w; + m_height = h; } Image::~Image() { - delete[] data; + delete[] m_data; } -void Image::setPixel(int x,int y,uchar val) +void Image::setPixel(uint x,uint y,uchar val) { - if (x>=0 && x<width && y>=0 && y<height) - data[y*width+x] = val; + if (x<m_width && y<m_height) + m_data[y*m_width+x] = val; } -uchar Image::getPixel(int x,int y) const +uchar Image::getPixel(uint x,uint y) const { - if (x>=0 && x<width && y>=0 && y<height) - return data[y*width+x]; + if (x<m_width && y<m_height) + return m_data[y*m_width+x]; else return 0; } -void Image::writeChar(int x,int y,char c,uchar fg) +void Image::writeChar(uint x,uint y,char c,uchar fg) { if (c>=' ') { - int xf,yf,ci=c-' '; - int rowOffset=0; - int cw = charWidth[ci]; - int cp = charPos[ci]; + uint xf,yf,ci=c-' '; + uint rowOffset=0; + uint cw = charWidth[ci]; + uint cp = charPos[ci]; for (yf=0;yf<charHeight;yf++) { unsigned short bitPattern=0; - int bitsLeft=cw; - int byteOffset = rowOffset+(cp>>3); - int bitOffset = cp&7; + uint bitsLeft=cw; + uint byteOffset = rowOffset+(cp>>3); + uint bitOffset = cp&7; // get the bit pattern for row yf of the character from the font data while (bitsLeft>0) { - int bits=8-bitOffset; + uint bits=8-bitOffset; if (bits>bitsLeft) bits=bitsLeft; bitPattern<<=bits; bitPattern|=((fontRaw[byteOffset]<<bitOffset)&0xff)>>(8-bits); @@ -286,7 +286,7 @@ void Image::writeChar(int x,int y,char c,uchar fg) bitOffset=0; byteOffset++; } - int mask=1<<(cw-1); + uint mask=1<<(cw-1); // draw character row yf for (xf=0;xf<cw;xf++) { @@ -298,7 +298,7 @@ void Image::writeChar(int x,int y,char c,uchar fg) } } -void Image::writeString(int x,int y,const char *s,uchar fg) +void Image::writeString(uint x,uint y,const char *s,uchar fg) { if (s) { @@ -313,7 +313,7 @@ void Image::writeString(int x,int y,const char *s,uchar fg) uint Image::stringLength(const char *s) { - int w=0; + uint w=0; if (s) { char c; @@ -322,9 +322,9 @@ uint Image::stringLength(const char *s) return w; } -void Image::drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask) +void Image::drawHorzLine(uint y,uint xs,uint xe,uchar colIndex,uint mask) { - int x,i=0,j=0; + uint x,i=0,j=0; for (x=xs;x<=xe;x++,j++) { if (j&1) i++; @@ -332,38 +332,38 @@ void Image::drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask) } } -void Image::drawHorzArrow(int y,int xs,int xe,uchar colIndex,uint mask) +void Image::drawHorzArrow(uint y,uint xs,uint xe,uchar colIndex,uint mask) { drawHorzLine(y,xs,xe,colIndex,mask); - int i; + uint i; for (i=0;i<6;i++) { - int h=i>>1; + uint h=i>>1; drawVertLine(xe-i,y-h,y+h,colIndex,0xffffffff); } } -void Image::drawVertLine(int x,int ys,int ye,uchar colIndex,uint mask) +void Image::drawVertLine(uint x,uint ys,uint ye,uchar colIndex,uint mask) { - int y,i=0; + uint y,i=0; for (y=ys;y<=ye;y++,i++) { if (mask&(1<<(i&0x1f))) setPixel(x,y,colIndex); } } -void Image::drawVertArrow(int x,int ys,int ye,uchar colIndex,uint mask) +void Image::drawVertArrow(uint x,uint ys,uint ye,uchar colIndex,uint mask) { drawVertLine(x,ys,ye,colIndex,mask); - int i; + uint i; for (i=0;i<6;i++) { - int h=i>>1; + uint h=i>>1; drawHorzLine(ys+i,x-h,x+h,colIndex,0xffffffff); } } -void Image::drawRect(int x,int y,int w,int h,uchar colIndex,uint mask) +void Image::drawRect(uint x,uint y,uint w,uint h,uchar colIndex,uint mask) { drawHorzLine(y,x,x+w-1,colIndex,mask); drawHorzLine(y+h-1,x,x+w-1,colIndex,mask); @@ -371,44 +371,27 @@ void Image::drawRect(int x,int y,int w,int h,uchar colIndex,uint mask) drawVertLine(x+w-1,y,y+h-1,colIndex,mask); } -void Image::fillRect(int x,int y,int lwidth,int lheight,uchar colIndex,uint mask) +void Image::fillRect(uint x,uint y,uint width,uint height,uchar colIndex,uint mask) { - int xp,yp,xi,yi; - for (yp=y,yi=0;yp<y+lheight;yp++,yi++) - for (xp=x,xi=0;xp<x+lwidth;xp++,xi++) + uint xp,yp,xi,yi; + for (yp=y,yi=0;yp<y+height;yp++,yi++) + for (xp=x,xi=0;xp<x+width;xp++,xi++) if (mask&(1<<((xi+yi)&0x1f))) setPixel(xp,yp,colIndex); } bool Image::save(const char *fileName,int mode) { -#if 0 - GifEncoder gifenc(data, - mode==0 ? palette : palette2, - width,height, - mode==0 ? 3 : 4, - 0); - QFile file(fileName); - if (file.open(IO_WriteOnly)) - { - gifenc.writeGIF(file); - return TRUE; - } - else - { - return FALSE; - } -#endif static bool useTransparency = Config_getBool(FORMULA_TRANSPARENT); uchar* buffer; size_t bufferSize; LodePNG_Encoder encoder; LodePNG_Encoder_init(&encoder); - int numCols = mode==0 ? 8 : 16; + uint numCols = mode==0 ? 8 : 16; Color *pPal = mode==0 ? palette : useTransparency ? palette2 : palette3 ; - int i; + uint i; for (i=0;i<numCols;i++,pPal++) { LodePNG_InfoColor_addPalette(&encoder.infoPng.color, @@ -416,7 +399,7 @@ bool Image::save(const char *fileName,int mode) } encoder.infoPng.color.colorType = 3; encoder.infoRaw.color.colorType = 3; - LodePNG_encode(&encoder, &buffer, &bufferSize, data, width, height); + LodePNG_encode(&encoder, &buffer, &bufferSize, m_data, m_width, m_height); LodePNG_saveFile(buffer, bufferSize, fileName); free(buffer); LodePNG_Encoder_cleanup(&encoder); @@ -489,7 +472,7 @@ void ColoredImage::hsl2rgb(double h,double s,double l, *pBlue = b; } -ColoredImage::ColoredImage(int width,int height, +ColoredImage::ColoredImage(uint width,uint height, const uchar *greyLevels,const uchar *alphaLevels, int saturation,int hue,int gamma) { @@ -497,7 +480,7 @@ ColoredImage::ColoredImage(int width,int height, m_width = width; m_height = height; m_data = (uchar*)malloc(width*height*4); - int i; + uint i; for (i=0;i<width*height;i++) { uchar r,g,b,a; diff --git a/src/image.h b/src/image.h index 35e6ae3..435321a 100644 --- a/src/image.h +++ b/src/image.h @@ -24,37 +24,37 @@ class Image { public: - Image(int w,int h); + Image(uint w,uint h); ~Image(); - void setPixel(int x,int y,uchar val); - uchar getPixel(int x,int y) const; - void writeChar(int x,int y,char c,uchar fg); - void writeString(int x,int y,const char *s,uchar fg); - void drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask); - void drawHorzArrow(int y,int xs,int xe,uchar colIndex,uint mask); - void drawVertLine(int x,int ys,int ye,uchar colIndex,uint mask); - void drawVertArrow(int x,int ys,int ye,uchar colIndex,uint mask); - void drawRect(int x,int y,int width,int height,uchar colIndex,uint mask); - void fillRect(int x,int y,int width,int height,uchar colIndex,uint mask); + void setPixel(uint x,uint y,uchar val); + uchar getPixel(uint x,uint y) const; + void writeChar(uint x,uint y,char c,uchar fg); + void writeString(uint x,uint y,const char *s,uchar fg); + void drawHorzLine(uint y,uint xs,uint xe,uchar colIndex,uint mask); + void drawHorzArrow(uint y,uint xs,uint xe,uchar colIndex,uint mask); + void drawVertLine(uint x,uint ys,uint ye,uchar colIndex,uint mask); + void drawVertArrow(uint x,uint ys,uint ye,uchar colIndex,uint mask); + void drawRect(uint x,uint y,uint width,uint height,uchar colIndex,uint mask); + void fillRect(uint x,uint y,uint width,uint height,uchar colIndex,uint mask); bool save(const char *fileName,int mode=0); friend uint stringLength(const char *s); - uint getWidth() const { return width; } - uint getHeight() const { return height; } - uchar *getData() const { return data; } + uint width() const { return m_width; } + uint height() const { return m_height; } + uchar *data() const { return m_data; } static uint stringLength(const char *s); private: - int width; - int height; - uchar *data; + uint m_width; + uint m_height; + uchar *m_data; }; /** Class representing a bitmap image colored based on hue/sat/gamma settings. */ class ColoredImage { public: - ColoredImage(int width,int height, + ColoredImage(uint width,uint height, const uchar *greyLevels,const uchar *alphaLevels, int saturation,int hue,int gamma); ~ColoredImage(); @@ -62,8 +62,8 @@ class ColoredImage static void hsl2rgb(double h,double s,double l, double *pRed,double *pGreen,double *pBlue); private: - int m_width; - int m_height; + uint m_width; + uint m_height; uchar *m_data; bool m_hasAlpha; }; diff --git a/src/index.cpp b/src/index.cpp index edc302b..12f35f2 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -587,9 +587,7 @@ static bool dirHasVisibleChildren(DirDef *dd) } } - QListIterator<DirDef> dli(dd->subDirs()); - DirDef *subdd; - for (dli.toFirst();(subdd=dli.current());++dli) + for(const auto subdd : dd->subDirs()) { if (dirHasVisibleChildren(subdd)) { @@ -617,7 +615,7 @@ static void writeDirTreeNode(OutputList &ol, DirDef *dd, int level, FTVHelp* ftv } static bool tocExpand = TRUE; //Config_getBool(TOC_EXPAND); - bool isDir = dd->subDirs().count()>0 || // there are subdirs + bool isDir = dd->subDirs().size()>0 || // there are subdirs (tocExpand && // or toc expand and dd->getFiles() && dd->getFiles()->count()>0 // there are files ); @@ -646,12 +644,10 @@ static void writeDirTreeNode(OutputList &ol, DirDef *dd, int level, FTVHelp* ftv } // write sub directories - if (dd->subDirs().count()>0) + if (dd->subDirs().size()>0) { startIndexHierarchy(ol,level+1); - QListIterator<DirDef> dli(dd->subDirs()); - DirDef *subdd = 0; - for (dli.toFirst();(subdd=dli.current());++dli) + for(const auto subdd : dd->subDirs()) { writeDirTreeNode(ol,subdd,level+1,ftv,addToIndex); } @@ -760,7 +756,7 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); } - static bool fullPathNames = Config_getBool(FULL_PATH_NAMES); + bool fullPathNames = Config_getBool(FULL_PATH_NAMES); startIndexHierarchy(ol,0); if (fullPathNames) { @@ -776,19 +772,14 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) } if (ftv) { - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { - static bool fullPathNames = Config_getBool(FULL_PATH_NAMES); if (!fullPathNames || fd->getDirDef()==0) // top level file { - bool doc,src; - doc = fileVisibleInIndex(fd,src); + bool src; + bool doc = fileVisibleInIndex(fd.get(),src); QCString reference, outputBase; if (doc) { @@ -799,19 +790,19 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) { ftv->addContentsItem(FALSE,fd->displayName(), reference, outputBase, 0, - FALSE,FALSE,fd); + FALSE,FALSE,fd.get()); } if (addToIndex) { if (doc) { - addMembersToIndex(fd,LayoutDocManager::File,fd->displayName(),QCString(),TRUE); + addMembersToIndex(fd.get(),LayoutDocManager::File,fd->displayName(),QCString(),TRUE); } else if (src) { Doxygen::indexList->addContentsItem( FALSE, convertToHtml(fd->name(),TRUE), 0, - fd->getSourceFileBase(), 0, FALSE, TRUE, fd); + fd->getSourceFileBase(), 0, FALSE, TRUE, fd.get()); } } } @@ -1321,16 +1312,12 @@ static void countFiles(int &htmlFiles,int &files) { htmlFiles=0; files=0; - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd: *fn) { bool doc,src; - doc = fileVisibleInIndex(fd,src); + doc = fileVisibleInIndex(fd.get(),src); if (doc || src) { htmlFiles++; @@ -1409,7 +1396,8 @@ static void writeSingleFileIndex(OutputList &ol,FileDef *fd) FALSE, // isExample 0, // example name TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); //ol.docify(")"); } @@ -1470,27 +1458,23 @@ static void writeFileIndex(OutputList &ol) if (Config_getBool(FULL_PATH_NAMES)) { // re-sort input files in (dir,file) output order instead of (file,dir) input order - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { QCString path=fd->getPath(); if (path.isEmpty()) path="[external]"; FileList *fl = outputNameDict.find(path); if (fl) { - fl->append(fd); + fl->append(fd.get()); //printf("+ inserting %s---%s\n",fd->getPath().data(),fd->name().data()); } else { //printf("o inserting %s---%s\n",fd->getPath().data(),fd->name().data()); fl = new FileList(path); - fl->append(fd); + fl->append(fd.get()); outputNameList.append(fl); outputNameDict.insert(path,fl); } @@ -1517,15 +1501,11 @@ static void writeFileIndex(OutputList &ol) } else { - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { - writeSingleFileIndex(ol,fd); + writeSingleFileIndex(ol,fd.get()); } } } @@ -1789,7 +1769,8 @@ static void writeNamespaceIndex(OutputList &ol) FALSE, // isExample 0, // example name TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); //ol.docify(")"); } @@ -1923,7 +1904,8 @@ static void writeAnnotatedClassList(OutputList &ol,ClassDef::CompoundType ct) FALSE, // isExample 0, // example name TRUE, // single line - TRUE // link from index + TRUE, // link from index + Config_getBool(MARKDOWN_SUPPORT) ); } ol.endIndexValue(cd->getOutputFileBase(),hasBrief); @@ -2008,20 +1990,20 @@ class PrefixIgnoreClassList : public ClassList class AlphaIndexTableCell { public: - AlphaIndexTableCell(int row,int col,uint letter,ClassDef *cd) : + AlphaIndexTableCell(int row,int col,uint letter,const ClassDef *cd) : m_letter(letter), m_class(cd), m_row(row), m_col(col) { //printf("AlphaIndexTableCell(%d,%d,%c,%s)\n",row,col,letter!=0 ? letter: '-', // cd!=(ClassDef*)0x8 ? cd->name().data() : "<null>"); } - ClassDef *classDef() const { return m_class; } + const ClassDef *classDef() const { return m_class; } uint letter() const { return m_letter; } int row() const { return m_row; } int column() const { return m_col; } private: uint m_letter; - ClassDef *m_class; + const ClassDef *m_class; int m_row; int m_col; }; @@ -2037,8 +2019,8 @@ class AlphaIndexTableRows : public QList<AlphaIndexTableCell> class AlphaIndexTableRowsIterator : public QListIterator<AlphaIndexTableCell> { public: - AlphaIndexTableRowsIterator(const AlphaIndexTableRows &list) : - QListIterator<AlphaIndexTableCell>(list) {} + AlphaIndexTableRowsIterator(const AlphaIndexTableRows &list_) : + QListIterator<AlphaIndexTableCell>(list_) {} }; /** Class representing the columns in the alphabetical class index. */ @@ -2190,7 +2172,7 @@ static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct row++; ClassListIterator cit(*cl); cit.toFirst(); - ClassDef *cd = cit.current(); + cd = cit.current(); ++cit; tableRows->append(new AlphaIndexTableCell(row,col,0,cd)); row++; @@ -2847,9 +2829,9 @@ static void writeMemberList(OutputList &ol,bool useSections,int page, QCString cl = letterToString(ml->letter()); QCString anchor=(QCString)"index_"+convertToId(cs); QCString title=(QCString)"- "+cl+" -"; - ol.startSection(anchor,title,SectionInfo::Subsection); + ol.startSection(anchor,title,SectionType::Subsection); ol.docify(title); - ol.endSection(anchor,SectionInfo::Subsection); + ol.endSection(anchor,SectionType::Subsection); ol.startItemList(); firstSection=FALSE; firstItem=TRUE; @@ -3929,14 +3911,14 @@ void writeGraphInfo(OutputList &ol) DotLegendGraph gd; gd.writeGraph(Config_getString(HTML_OUTPUT)); - bool &stripCommentsStateRef = Config_getBool(STRIP_CODE_COMMENTS); + bool stripCommentsStateRef = Config_getBool(STRIP_CODE_COMMENTS); bool oldStripCommentsState = stripCommentsStateRef; - bool &createSubdirs = Config_getBool(CREATE_SUBDIRS); + bool createSubdirs = Config_getBool(CREATE_SUBDIRS); bool oldCreateSubdirs = createSubdirs; // temporarily disable the stripping of comments for our own code example! - stripCommentsStateRef = FALSE; + stripCommentsStateRef = Config_updateBool(STRIP_CODE_COMMENTS,FALSE); // temporarily disable create subdirs for linking to our example - createSubdirs = FALSE; + createSubdirs = Config_updateBool(CREATE_SUBDIRS,FALSE); startFile(ol,"graph_legend",0,theTranslator->trLegendTitle().data()); startTitle(ol,0); @@ -3953,12 +3935,13 @@ void writeGraphInfo(OutputList &ol) //printf("legendDocs=%s\n",legendDocs.data()); } FileDef *fd = createFileDef("","graph_legend.dox"); - ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE); + ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE, + 0,FALSE,FALSE,FALSE); delete fd; // restore config settings - stripCommentsStateRef = oldStripCommentsState; - createSubdirs = oldCreateSubdirs; + Config_updateBool(STRIP_CODE_COMMENTS,oldStripCommentsState); + Config_updateBool(CREATE_SUBDIRS,oldCreateSubdirs); endFile(ol); ol.popGeneratorState(); @@ -4009,7 +3992,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* numSubItems += gd->getNamespaces()->count(); numSubItems += gd->getClasses()->count(); numSubItems += gd->getFiles()->count(); - numSubItems += gd->getDirs()->count(); + numSubItems += static_cast<int>(gd->getDirs().size()); numSubItems += gd->getPages()->count(); } @@ -4059,7 +4042,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* for (mi.toFirst();(md=mi.current());++mi) { const MemberList *enumList = md->enumFieldList(); - bool isDir = enumList!=0 && md->isEnumerate(); + isDir = enumList!=0 && md->isEnumerate(); if (md->isVisible() && !md->isAnonymous()) { Doxygen::indexList->addContentsItem(isDir, @@ -4142,9 +4125,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* } else if (lde->kind()==LayoutDocEntry::GroupDirs && addToIndex) { - QListIterator<DirDef> it(*gd->getDirs()); - DirDef *dd; - for (;(dd=it.current());++it) + for (const auto dd : gd->getDirs()) { if (dd->isVisible()) { @@ -4160,16 +4141,16 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* PageDef *pd; for (;(pd=it.current());++it) { - SectionInfo *si=0; - if (!pd->name().isEmpty()) si=Doxygen::sectionDict->find(pd->name()); - bool hasSubPages = pd->hasSubPages(); + const SectionInfo *si=0; + if (!pd->name().isEmpty()) si=SectionManager::instance().find(pd->name()); + hasSubPages = pd->hasSubPages(); bool hasSections = pd->hasSections(); Doxygen::indexList->addContentsItem( hasSubPages || hasSections, convertToHtml(pd->title(),TRUE), gd->getReference(), gd->getOutputFileBase(), - si ? si->label.data() : 0, + si ? si->label().data() : 0, hasSubPages || hasSections, TRUE); // addToNavIndex if (hasSections || hasSubPages) @@ -4519,8 +4500,8 @@ static void writeIndex(OutputList &ol) ol.startHeaderSection(); ol.startTitleHead(0); ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->docLine(), - Doxygen::mainPage,0,Doxygen::mainPage->title(), - TRUE,FALSE,0,TRUE,FALSE); + Doxygen::mainPage,0,Doxygen::mainPage->title(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); headerWritten = TRUE; } } @@ -4556,8 +4537,8 @@ static void writeIndex(OutputList &ol) ol.startTextBlock(); ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0, - Doxygen::mainPage->documentation(),TRUE,FALSE - /*,Doxygen::mainPage->sectionDict*/); + Doxygen::mainPage->documentation(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endTextBlock(); ol.endPageDoc(); @@ -4594,7 +4575,8 @@ static void writeIndex(OutputList &ol) if (!Config_getString(PROJECT_NUMBER).isEmpty()) { ol.startProjectNumber(); - ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0,Config_getString(PROJECT_NUMBER),FALSE,FALSE); + ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0,Config_getString(PROJECT_NUMBER),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endProjectNumber(); } ol.endIndexSection(isTitlePageStart); @@ -4639,7 +4621,7 @@ static void writeIndex(OutputList &ol) ol.pushGeneratorState(); ol.disable(OutputGenerator::Latex); } - QCString title = pd->title(); + title = pd->title(); if (title.isEmpty()) title=pd->name(); ol.disable(OutputGenerator::Docbook); @@ -4807,7 +4789,8 @@ static void writeIndex(OutputList &ol) ol.startContents(); ol.startTextBlock(); ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0, - Doxygen::mainPage->documentation(),FALSE,FALSE + Doxygen::mainPage->documentation(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT) ); ol.endTextBlock(); endFile(ol); diff --git a/src/language.cpp b/src/language.cpp index 7457676..299c452 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -417,6 +417,6 @@ bool setTranslator(const char *langName) } QCString msg = theTranslator->updateNeededMessage(); - if (!msg.isEmpty()) warn_uncond(msg); + if (!msg.isEmpty()) warn_uncond("%s", msg.data()); return TRUE; } diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index 730f083..19f01b0 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,7 +16,7 @@ * */ #include "htmlattrib.h" -#include <qfileinfo.h> +#include <qfileinfo.h> #include "latexdocvisitor.h" #include "latexgen.h" #include "docparser.h" @@ -37,7 +37,7 @@ #include "plantuml.h" const int maxLevels=5; -static const char *secLabels[maxLevels] = +static const char *secLabels[maxLevels] = { "doxysection","doxysubsection","doxysubsubsection","doxyparagraph","doxysubparagraph" }; static const char *getSectionName(int level) @@ -176,8 +176,8 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s) LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const char *langExt,bool insideTabbing) - : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE), + const char *langExt,bool insideTabbing) + : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE), m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE), m_insideTabbing(insideTabbing), m_langExt(langExt) { @@ -322,7 +322,7 @@ void LatexDocVisitor::visit(DocStyleChange *s) if (s->enable()) m_t << "\n\\footnotesize "; else m_t << "\n\\normalsize "; break; case DocStyleChange::Preformatted: - if (s->enable()) + if (s->enable()) { m_t << "\n\\begin{DoxyPre}"; m_insidePre=TRUE; @@ -349,7 +349,7 @@ void LatexDocVisitor::visit(DocVerbatim *s) SrcLangExt langExt = getLanguageFromFileName(lang); switch(s->type()) { - case DocVerbatim::Code: + case DocVerbatim::Code: { m_t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n"; LatexCodeGenerator::setDoxyCodeOpen(TRUE); @@ -360,28 +360,28 @@ void LatexDocVisitor::visit(DocVerbatim *s) m_t << "\\end{DoxyCode}\n"; } break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: m_t << "\\begin{DoxyVerb}"; m_t << s->text(); m_t << "\\end{DoxyVerb}\n"; break; - case DocVerbatim::HtmlOnly: - case DocVerbatim::XmlOnly: - case DocVerbatim::ManOnly: + case DocVerbatim::HtmlOnly: + case DocVerbatim::XmlOnly: + case DocVerbatim::ManOnly: case DocVerbatim::RtfOnly: case DocVerbatim::DocbookOnly: - /* nothing */ + /* nothing */ break; - case DocVerbatim::LatexOnly: - m_t << s->text(); + case DocVerbatim::LatexOnly: + m_t << s->text(); break; - case DocVerbatim::Dot: + case DocVerbatim::Dot: { static int dotindex = 1; QCString fileName(4096); - fileName.sprintf("%s%d%s", - (Config_getString(LATEX_OUTPUT)+"/inline_dotgraph_").data(), + fileName.sprintf("%s%d%s", + (Config_getString(LATEX_OUTPUT)+"/inline_dotgraph_").data(), dotindex++, ".dot" ); @@ -403,13 +403,13 @@ void LatexDocVisitor::visit(DocVerbatim *s) } } break; - case DocVerbatim::Msc: + case DocVerbatim::Msc: { static int mscindex = 1; QCString baseName(4096); - baseName.sprintf("%s%d", - (Config_getString(LATEX_OUTPUT)+"/inline_mscgraph_").data(), + baseName.sprintf("%s%d", + (Config_getString(LATEX_OUTPUT)+"/inline_mscgraph_").data(), mscindex++ ); QFile file(baseName+".msc"); @@ -431,7 +431,7 @@ void LatexDocVisitor::visit(DocVerbatim *s) } } break; - case DocVerbatim::PlantUML: + case DocVerbatim::PlantUML: { QCString latexOutput = Config_getString(LATEX_OUTPUT); QCString baseName = PlantumlManager::instance()->writePlantUMLSource(latexOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_EPS); @@ -446,11 +446,11 @@ void LatexDocVisitor::visit(DocAnchor *anc) { if (m_hide) return; m_t << "\\label{" << stripPath(anc->file()) << "_" << anc->anchor() << "}%" << endl; - if (!anc->file().isEmpty() && Config_getBool(PDF_HYPERLINKS)) + if (!anc->file().isEmpty() && Config_getBool(PDF_HYPERLINKS)) { - m_t << "\\Hypertarget{" << stripPath(anc->file()) << "_" << anc->anchor() + m_t << "\\Hypertarget{" << stripPath(anc->file()) << "_" << anc->anchor() << "}%" << endl; - } + } } void LatexDocVisitor::visit(DocInclude *inc) @@ -460,7 +460,7 @@ void LatexDocVisitor::visit(DocInclude *inc) switch(inc->type()) { case DocInclude::IncWithLines: - { + { m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; LatexCodeGenerator::setDoxyCodeOpen(TRUE); QFileInfo cfi( inc->file() ); @@ -482,8 +482,8 @@ void LatexDocVisitor::visit(DocInclude *inc) LatexCodeGenerator::setDoxyCodeOpen(FALSE); m_t << "\\end{DoxyCodeInclude}" << endl; } - break; - case DocInclude::Include: + break; + case DocInclude::Include: m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; LatexCodeGenerator::setDoxyCodeOpen(TRUE); Doxygen::parserManager->getCodeParser(inc->extension()) @@ -503,11 +503,15 @@ void LatexDocVisitor::visit(DocInclude *inc) case DocInclude::DontInclude: case DocInclude::DontIncWithLines: case DocInclude::HtmlInclude: + case DocInclude::RtfInclude: + case DocInclude::ManInclude: + case DocInclude::XmlInclude: + case DocInclude::DocbookInclude: break; case DocInclude::LatexInclude: m_t << inc->text(); break; - case DocInclude::VerbInclude: + case DocInclude::VerbInclude: m_t << "\n\\begin{DoxyVerbInclude}\n"; m_t << inc->text(); m_t << "\\end{DoxyVerbInclude}\n"; @@ -540,7 +544,7 @@ void LatexDocVisitor::visit(DocInclude *inc) extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -553,8 +557,8 @@ void LatexDocVisitor::visit(DocInclude *inc) m_t << "\\end{DoxyCodeInclude}" << endl; } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -565,7 +569,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) { //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n", // op->type(),op->isFirst(),op->isLast(),op->text().data()); - if (op->isFirst()) + if (op->isFirst()) { if (!m_hide) m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; LatexCodeGenerator::setDoxyCodeOpen(TRUE); @@ -575,10 +579,10 @@ void LatexDocVisitor::visit(DocIncOperator *op) QCString locLangExt = getFileNameExtension(op->includeFileName()); if (locLangExt.isEmpty()) locLangExt = m_langExt; SrcLangExt langExt = getLanguageFromFileName(locLangExt); - if (op->type()!=DocIncOperator::Skip) + if (op->type()!=DocIncOperator::Skip) { popEnabled(); - if (!m_hide) + if (!m_hide) { FileDef *fd = 0; if (!op->includeFileName().isEmpty()) @@ -602,7 +606,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); LatexCodeGenerator::setDoxyCodeOpen(FALSE); @@ -617,7 +621,8 @@ void LatexDocVisitor::visit(DocIncOperator *op) void LatexDocVisitor::visit(DocFormula *f) { if (m_hide) return; - const char *p=f->text(); + QCString s = f->text(); + const char *p = s.data(); char c; if (p) { @@ -649,11 +654,12 @@ void LatexDocVisitor::visit(DocSimpleSectSep *) void LatexDocVisitor::visit(DocCite *cite) { if (m_hide) return; - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { //startLink(cite->ref(),cite->file(),cite->anchor()); QCString anchor = cite->anchor(); - anchor = anchor.mid(CiteConsts::anchorPrefix.length()); // strip prefix + QCString anchorPrefix = CitationManager::instance().anchorPrefix(); + anchor = anchor.mid(anchorPrefix.length()); // strip prefix m_t << "\\cite{" << anchor << "}"; } else @@ -700,11 +706,11 @@ void LatexDocVisitor::visitPre(DocAutoListItem *) m_t << "\n\\item "; } -void LatexDocVisitor::visitPost(DocAutoListItem *) +void LatexDocVisitor::visitPost(DocAutoListItem *) { } -void LatexDocVisitor::visitPre(DocPara *) +void LatexDocVisitor::visitPre(DocPara *) { } @@ -794,7 +800,7 @@ void LatexDocVisitor::visitPre(DocSimpleSect *s) case DocSimpleSect::User: m_t << "\\begin{DoxyParagraph}{"; break; - case DocSimpleSect::Rcs: + case DocSimpleSect::Rcs: m_t << "\\begin{DoxyParagraph}{"; break; case DocSimpleSect::Unknown: break; @@ -864,7 +870,7 @@ void LatexDocVisitor::visitPost(DocSimpleSect *s) case DocSimpleSect::User: m_t << "\n\\end{DoxyParagraph}\n"; break; - case DocSimpleSect::Rcs: + case DocSimpleSect::Rcs: m_t << "\n\\end{DoxyParagraph}\n"; break; default: @@ -901,7 +907,7 @@ void LatexDocVisitor::visitPre(DocSimpleListItem *) m_t << "\\item "; } -void LatexDocVisitor::visitPost(DocSimpleListItem *) +void LatexDocVisitor::visitPost(DocSimpleListItem *) { } @@ -917,25 +923,25 @@ void LatexDocVisitor::visitPre(DocSection *s) m_t << "}\\label{" << stripPath(s->file()) << "_" << s->anchor() << "}" << endl; } -void LatexDocVisitor::visitPost(DocSection *) +void LatexDocVisitor::visitPost(DocSection *) { } void LatexDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) m_t << "\n\\begin{DoxyEnumerate}"; - else + else m_t << "\n\\begin{DoxyItemize}"; } -void LatexDocVisitor::visitPost(DocHtmlList *s) +void LatexDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) m_t << "\n\\end{DoxyEnumerate}"; - else + else m_t << "\n\\end{DoxyItemize}"; } @@ -945,7 +951,7 @@ void LatexDocVisitor::visitPre(DocHtmlListItem *) m_t << "\n\\item "; } -void LatexDocVisitor::visitPost(DocHtmlListItem *) +void LatexDocVisitor::visitPost(DocHtmlListItem *) { } @@ -955,7 +961,7 @@ void LatexDocVisitor::visitPost(DocHtmlListItem *) // m_insidePre=TRUE; //} -//void LatexDocVisitor::visitPost(DocHtmlPre *) +//void LatexDocVisitor::visitPost(DocHtmlPre *) //{ // m_insidePre=FALSE; // m_t << "\\end{alltt}\\normalsize " << endl; @@ -975,7 +981,7 @@ void LatexDocVisitor::visitPre(DocHtmlDescList *dl) } } -void LatexDocVisitor::visitPost(DocHtmlDescList *dl) +void LatexDocVisitor::visitPost(DocHtmlDescList *dl) { if (m_hide) return; QCString val = dl->attribs().find("class"); @@ -996,7 +1002,7 @@ void LatexDocVisitor::visitPre(DocHtmlDescTitle *) m_insideItem=TRUE; } -void LatexDocVisitor::visitPost(DocHtmlDescTitle *) +void LatexDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_insideItem=FALSE; @@ -1007,7 +1013,7 @@ void LatexDocVisitor::visitPre(DocHtmlDescData *) { } -void LatexDocVisitor::visitPost(DocHtmlDescData *) +void LatexDocVisitor::visitPost(DocHtmlDescData *) { } @@ -1115,7 +1121,7 @@ void LatexDocVisitor::visitPre(DocHtmlRow *r) setCurrentColumn(0); } -void LatexDocVisitor::visitPost(DocHtmlRow *row) +void LatexDocVisitor::visitPost(DocHtmlRow *row) { if (m_hide) return; @@ -1150,7 +1156,7 @@ void LatexDocVisitor::visitPost(DocHtmlRow *row) } m_t << "\\\\"; - + int col = 1; uint i; for (i=0;i<rowSpans().count();i++) @@ -1284,7 +1290,7 @@ void LatexDocVisitor::visitPre(DocHtmlCell *c) } } -void LatexDocVisitor::visitPost(DocHtmlCell *c) +void LatexDocVisitor::visitPost(DocHtmlCell *c) { if (m_hide) return; if (c->isHeading()) @@ -1312,7 +1318,7 @@ void LatexDocVisitor::visitPre(DocInternal *) //m_t << "}\n"; } -void LatexDocVisitor::visitPost(DocInternal *) +void LatexDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //m_t << "\\end{DoxyInternal}" << endl; @@ -1330,7 +1336,7 @@ void LatexDocVisitor::visitPre(DocHRef *href) m_t << "{\\texttt{ "; } -void LatexDocVisitor::visitPost(DocHRef *) +void LatexDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "}}"; @@ -1342,7 +1348,7 @@ void LatexDocVisitor::visitPre(DocHtmlHeader *header) m_t << "\\" << getSectionName(header->level()) << "*{"; } -void LatexDocVisitor::visitPost(DocHtmlHeader *) +void LatexDocVisitor::visitPost(DocHtmlHeader *) { if (m_hide) return; m_t << "}"; @@ -1367,7 +1373,7 @@ void LatexDocVisitor::visitPre(DocImage *img) } } -void LatexDocVisitor::visitPost(DocImage *img) +void LatexDocVisitor::visitPost(DocImage *img) { if (img->type()==DocImage::Latex) { @@ -1386,7 +1392,7 @@ void LatexDocVisitor::visitPre(DocDotFile *df) startDotFile(df->file(),df->width(),df->height(),df->hasCaption()); } -void LatexDocVisitor::visitPost(DocDotFile *df) +void LatexDocVisitor::visitPost(DocDotFile *df) { if (m_hide) return; endDotFile(df->hasCaption()); @@ -1397,7 +1403,7 @@ void LatexDocVisitor::visitPre(DocMscFile *df) startMscFile(df->file(),df->width(),df->height(),df->hasCaption()); } -void LatexDocVisitor::visitPost(DocMscFile *df) +void LatexDocVisitor::visitPost(DocMscFile *df) { if (m_hide) return; endMscFile(df->hasCaption()); @@ -1420,7 +1426,7 @@ void LatexDocVisitor::visitPre(DocLink *lnk) startLink(lnk->ref(),lnk->file(),lnk->anchor()); } -void LatexDocVisitor::visitPost(DocLink *lnk) +void LatexDocVisitor::visitPost(DocLink *lnk) { if (m_hide) return; endLink(lnk->ref(),lnk->file(),lnk->anchor()); @@ -1442,7 +1448,7 @@ void LatexDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void LatexDocVisitor::visitPost(DocRef *ref) +void LatexDocVisitor::visitPost(DocRef *ref) { if (m_hide) return; if (ref->isSubPage()) @@ -1466,7 +1472,7 @@ void LatexDocVisitor::visitPre(DocSecRefItem *ref) } } -void LatexDocVisitor::visitPost(DocSecRefItem *ref) +void LatexDocVisitor::visitPost(DocSecRefItem *ref) { if (m_hide) return; static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); @@ -1485,7 +1491,7 @@ void LatexDocVisitor::visitPre(DocSecRefList *) m_t << "\\begin{DoxyCompactList}" << endl; } -void LatexDocVisitor::visitPost(DocSecRefList *) +void LatexDocVisitor::visitPost(DocSecRefList *) { if (m_hide) return; m_t << "\\end{DoxyCompactList}" << endl; @@ -1512,11 +1518,11 @@ void LatexDocVisitor::visitPre(DocParamSect *s) m_t << "\n\\begin{DoxyRetVals}{"; filter(theTranslator->trReturnValues()); break; - case DocParamSect::Exception: + case DocParamSect::Exception: m_t << "\n\\begin{DoxyExceptions}{"; filter(theTranslator->trExceptions()); break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: m_t << "\n\\begin{DoxyTemplParams}{"; filter(theTranslator->trTemplateParameters()); break; @@ -1538,10 +1544,10 @@ void LatexDocVisitor::visitPost(DocParamSect *s) case DocParamSect::RetVal: m_t << "\\end{DoxyRetVals}\n"; break; - case DocParamSect::Exception: + case DocParamSect::Exception: m_t << "\\end{DoxyExceptions}\n"; break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: m_t << "\\end{DoxyTemplParams}\n"; break; default: @@ -1596,11 +1602,11 @@ void LatexDocVisitor::visitPre(DocParamList *pl) { if (type->kind()==DocNode::Kind_Word) { - visit((DocWord*)type); + visit((DocWord*)type); } else if (type->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)type); + visit((DocLinkedWord*)type); } else if (type->kind()==DocNode::Kind_Sep) { @@ -1621,11 +1627,11 @@ void LatexDocVisitor::visitPre(DocParamList *pl) m_insideItem=TRUE; if (param->kind()==DocNode::Kind_Word) { - visit((DocWord*)param); + visit((DocWord*)param); } else if (param->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)param); + visit((DocLinkedWord*)param); } m_insideItem=FALSE; } @@ -1700,7 +1706,7 @@ void LatexDocVisitor::visitPre(DocInternalRef *ref) startLink(0,ref->file(),ref->anchor()); } -void LatexDocVisitor::visitPost(DocInternalRef *ref) +void LatexDocVisitor::visitPost(DocInternalRef *ref) { if (m_hide) return; endLink(0,ref->file(),ref->anchor()); @@ -1747,7 +1753,7 @@ void LatexDocVisitor::visitPost(DocParBlock *) } void LatexDocVisitor::filter(const char *str) -{ +{ filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem); } @@ -1828,7 +1834,7 @@ void LatexDocVisitor::startDotFile(const QCString &fileName, if ((i=baseName.findRev('/'))!=-1) { baseName=baseName.right(baseName.length()-i-1); - } + } if ((i=baseName.find('.'))!=-1) { baseName=baseName.left(i); @@ -1857,7 +1863,7 @@ void LatexDocVisitor::startMscFile(const QCString &fileName, if ((i=baseName.findRev('/'))!=-1) { baseName=baseName.right(baseName.length()-i-1); - } + } if ((i=baseName.find('.'))!=-1) { baseName=baseName.left(i); @@ -1865,7 +1871,7 @@ void LatexDocVisitor::startMscFile(const QCString &fileName, baseName.prepend("msc_"); QCString outDir = Config_getString(LATEX_OUTPUT); - writeMscGraphFromFile(fileName,outDir,baseName,MSC_EPS); + writeMscGraphFromFile(fileName,outDir,baseName,MSC_EPS); visitPreStart(m_t,hasCaption, baseName, width, height); } @@ -1883,7 +1889,7 @@ void LatexDocVisitor::writeMscFile(const QCString &baseName, DocVerbatim *s) if ((i=shortName.findRev('/'))!=-1) { shortName=shortName.right(shortName.length()-i-1); - } + } QCString outDir = Config_getString(LATEX_OUTPUT); writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_EPS); visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height()); diff --git a/src/latexgen.cpp b/src/latexgen.cpp index cdda22c..cb42863 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -42,6 +42,7 @@ #include "namespacedef.h" #include "filename.h" #include "resourcemgr.h" +#include "portable.h" static bool DoxyCodeOpen = FALSE; static bool DoxyCodeLineOpen = FALSE; @@ -79,12 +80,12 @@ void LatexCodeGenerator::codify(const char *str) { if (str) { - const char *p=str; - char c; + const signed char *p=(const signed char*)str; + signed char c; //char cs[5]; int spacesToNextTabStop; static int tabSize = Config_getInt(TAB_SIZE); - static char *result = NULL; + static signed char *result = NULL; static int lresult = 0; int i; while ((c=*p)) @@ -118,7 +119,7 @@ void LatexCodeGenerator::codify(const char *str) if (lresult < (i + 5)) \ { \ lresult += 512; \ - result = (char *)realloc(result, lresult); \ + result = (signed char *)realloc(result, lresult); \ } \ result[i++]=c; p++; \ if (c<0) /* multibyte utf-8 character */ \ @@ -150,7 +151,7 @@ void LatexCodeGenerator::codify(const char *str) result[i]=0; // add terminator //if (m_prettyCode) //{ - filterLatexString(m_t,result,FALSE,TRUE); + filterLatexString(m_t,(const char *)result,FALSE,TRUE); //} //else //{ @@ -174,8 +175,8 @@ void LatexCodeGenerator::writeCodeLink(const char *ref,const char *f, { m_t << "\\mbox{\\hyperlink{"; if (f) m_t << stripPath(f); - if (f && anchor) m_t << "_"; - if (anchor) m_t << anchor; + if (f && anchor) m_t << "_"; + if (anchor) m_t << anchor; m_t << "}{"; codify(name); m_t << "}}"; @@ -282,7 +283,7 @@ LatexGenerator::~LatexGenerator() static void writeLatexMakefile() { - bool generateBib = !Doxygen::citeDict->isEmpty(); + bool generateBib = !CitationManager::instance().isEmpty(); QCString dir=Config_getString(LATEX_OUTPUT); QCString fileName=dir+"/Makefile"; QFile file(fileName); @@ -371,7 +372,7 @@ static void writeLatexMakefile() t << endl << "clean:" << endl - << "\trm -f " + << "\trm -f " << "*.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf" << endl; } @@ -383,7 +384,7 @@ static void writeMakeBat() QCString latex_command = theTranslator->latexCommandName(); QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME); QFile file(fileName); - bool generateBib = !Doxygen::citeDict->isEmpty(); + bool generateBib = !CitationManager::instance().isEmpty(); if (!file.open(IO_WriteOnly)) { term("Could not open file %s for writing\n",fileName.data()); @@ -421,7 +422,8 @@ static void writeMakeBat() t << mkidx_command << " refman.idx\n"; t << "%LATEX_CMD% refman.tex\n"; t << "dvips -o refman.ps refman.dvi\n"; - t << "gswin32c -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite " + t << Portable::ghostScriptCommand(); + t << " -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite " "-sOutputFile=refman.pdf -c save pop -f refman.ps\n"; } else // use pdflatex @@ -509,19 +511,19 @@ static void writeDefaultHeaderPart1(FTextStream &t) "\\usepackage{fixltx2e}\n" // for \textsubscript "\\usepackage{calc}\n" "\\usepackage{doxygen}\n"; - QStrList extraLatexStyle = Config_getList(LATEX_EXTRA_STYLESHEET); - for (uint i=0; i<extraLatexStyle.count(); ++i) + const StringVector &extraLatexStyles = Config_getList(LATEX_EXTRA_STYLESHEET); + for (const auto &extraStyle : extraLatexStyles) { - QCString fileName(extraLatexStyle.at(i)); + QCString fileName = extraStyle.c_str(); if (!fileName.isEmpty()) { QFileInfo fi(fileName); if (fi.exists()) { - if (checkExtension(fi.fileName().data(), latexStyleExtension)) + if (checkExtension(fi.fileName().data(), LATEX_STYLE_EXTENSION)) { // strip the extension, it will be added by the usepackage in the tex conversion process - t << "\\usepackage{" << stripExtensionGeneral(fi.fileName().data(), latexStyleExtension) << "}\n"; + t << "\\usepackage{" << stripExtensionGeneral(fi.fileName().data(), LATEX_STYLE_EXTENSION) << "}\n"; } else { @@ -558,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" @@ -621,7 +625,7 @@ static void writeDefaultHeaderPart1(FTextStream &t) "}\n" "\\makeatother\n" "\n"; - // + // t << "\\makeatletter\n" "\\newcommand\\hrulefilll{\\leavevmode\\leaders\\hrule\\hskip 0pt plus 1filll\\kern\\z@}\n" "\\makeatother\n" @@ -789,7 +793,7 @@ static void writeDefaultHeaderPart3(FTextStream &t) { // part 3 // Finalize project number - t << " Doxygen " << getVersion() << "}\\\\\n"; + t << " Doxygen " << getDoxygenVersion() << "}\\\\\n"; if (Config_getBool(LATEX_TIMESTAMP)) t << "\\vspace*{0.5cm}\n" "{\\small " << dateToString(TRUE) << "}\\\\\n"; @@ -827,7 +831,7 @@ static void writeDefaultFooter(FTextStream &t) "\n"; // Bibliography - Doxygen::citeDict->writeLatexBibliography(t); + CitationManager::instance().writeLatexBibliography(t); // Index t << "% Index\n"; @@ -858,7 +862,7 @@ static void writeDefaultFooter(FTextStream &t) void LatexGenerator::writeHeaderFile(QFile &f) { FTextStream t(&f); - t << "% Latex header for doxygen " << getVersion() << endl; + t << "% Latex header for doxygen " << getDoxygenVersion() << endl; writeDefaultHeaderPart1(t); t << "Your title here"; writeDefaultHeaderPart2(t); @@ -869,14 +873,14 @@ void LatexGenerator::writeHeaderFile(QFile &f) void LatexGenerator::writeFooterFile(QFile &f) { FTextStream t(&f); - t << "% Latex footer for doxygen " << getVersion() << endl; + t << "% Latex footer for doxygen " << getDoxygenVersion() << endl; writeDefaultFooter(t); } void LatexGenerator::writeStyleSheetFile(QFile &f) { FTextStream t(&f); - t << "% stylesheet for doxygen " << getVersion() << endl; + t << "% stylesheet for doxygen " << getDoxygenVersion() << endl; writeDefaultStyleSheet(t); } @@ -903,17 +907,17 @@ void LatexGenerator::endFile() //void LatexGenerator::writeIndex() //{ // startFile("refman.tex"); -//} - +//} + void LatexGenerator::startProjectNumber() { - t << "\\\\[1ex]\\large "; + t << "\\\\[1ex]\\large "; } void LatexGenerator::startIndexSection(IndexSections is) { - bool &compactLatex = Config_getBool(COMPACT_LATEX); - QCString &latexHeader = Config_getString(LATEX_HEADER); + bool compactLatex = Config_getBool(COMPACT_LATEX); + QCString latexHeader = Config_getString(LATEX_HEADER); switch (is) { case isTitlePageStart: @@ -1019,7 +1023,7 @@ void LatexGenerator::startIndexSection(IndexSections is) t << "{"; // Namespace Documentation}\n": found=TRUE; } - } + } } break; case isClassDocumentation: @@ -1029,7 +1033,7 @@ void LatexGenerator::startIndexSection(IndexSections is) bool found=FALSE; for (cli.toFirst();(cd=cli.current()) && !found;++cli) { - if (cd->isLinkableInProject() && + if (cd->isLinkableInProject() && cd->templateMaster()==0 && !cd->isEmbeddedInOuterScope() ) @@ -1044,13 +1048,9 @@ void LatexGenerator::startIndexSection(IndexSections is) case isFileDocumentation: { bool isFirst=TRUE; - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->isLinkableInProject()) { @@ -1149,7 +1149,7 @@ void LatexGenerator::endIndexSection(IndexSections is) if (!gd->isReference()) { //if (compactLatex) t << "\\input"; else t << "\\include"; - t << "\\include"; + t << "\\include"; t << "{" << gd->getOutputFileBase() << "}\n"; } } @@ -1173,7 +1173,7 @@ void LatexGenerator::endIndexSection(IndexSections is) if (dd->isLinkableInProject()) { //if (compactLatex) t << "\\input"; else t << "\\include"; - t << "\\input"; + t << "\\input"; t << "{" << dd->getOutputFileBase() << "}\n"; } } @@ -1197,7 +1197,7 @@ void LatexGenerator::endIndexSection(IndexSections is) if (nd->isLinkableInProject()) { //if (compactLatex) t << "\\input"; else t << "\\include"; - t << "\\input"; + t << "\\input"; t << "{" << nd->getOutputFileBase() << "}\n"; } ++nli; @@ -1211,7 +1211,7 @@ void LatexGenerator::endIndexSection(IndexSections is) bool found=FALSE; for (cli.toFirst();(cd=cli.current()) && !found;++cli) { - if (cd->isLinkableInProject() && + if (cd->isLinkableInProject() && cd->templateMaster()==0 && !cd->isEmbeddedInOuterScope() ) @@ -1222,28 +1222,24 @@ void LatexGenerator::endIndexSection(IndexSections is) } for (;(cd=cli.current());++cli) { - if (cd->isLinkableInProject() && + if (cd->isLinkableInProject() && cd->templateMaster()==0 && !cd->isEmbeddedInOuterScope() ) { //if (compactLatex) t << "\\input"; else t << "\\include"; - t << "\\input"; + t << "\\input"; t << "{" << cd->getOutputFileBase() << "}\n"; - } + } } } break; case isFileDocumentation: { bool isFirst=TRUE; - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->isLinkableInProject()) { @@ -1260,7 +1256,7 @@ void LatexGenerator::endIndexSection(IndexSections is) else { //if (compactLatex) t << "\\input" ; else t << "\\include"; - t << "\\input" ; + t << "\\input" ; t << "{" << fd->getOutputFileBase() << "}\n"; if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) { @@ -1285,7 +1281,7 @@ void LatexGenerator::endIndexSection(IndexSections is) for (++pdi;(pd=pdi.current());++pdi) { //if (compactLatex) t << "\\input" ; else t << "\\include"; - t << "\\input"; + t << "\\input"; t << "{" << pd->getOutputFileBase() << "}\n"; } } @@ -1304,7 +1300,7 @@ void LatexGenerator::endIndexSection(IndexSections is) if (compactLatex) t << "\\doxysection"; else t << "\\chapter"; t << "{" << pd->title(); t << "}\n"; - + if (compactLatex || first) t << "\\input" ; else t << "\\include"; t << "{" << pd->getOutputFileBase() << "}\n"; first=FALSE; @@ -1337,7 +1333,7 @@ void LatexGenerator::writePageLink(const char *name, bool /*first*/) //bool &compactLatex = Config_getBool(COMPACT_LATEX); // next is remove for bug615957 //if (compactLatex || first) t << "\\input" ; else t << "\\include"; - t << "\\input" ; + t << "\\input" ; t << "{" << name << "}\n"; } @@ -1440,7 +1436,7 @@ void LatexGenerator::writeStartAnnoItem(const char *,const char *, { t << "\\item\\contentsline{section}\\textbf{ "; if (path) docify(path); - docify(name); + docify(name); t << "} "; } @@ -1475,7 +1471,7 @@ void LatexGenerator::endIndexValue(const char *name,bool /*hasBrief*/) //{ // t << "\\textbf{ "; // docify(name); -// t << "}"; +// t << "}"; //} void LatexGenerator::startTextLink(const char *f,const char *anchor) @@ -1485,7 +1481,7 @@ void LatexGenerator::startTextLink(const char *f,const char *anchor) { t << "\\mbox{\\hyperlink{"; if (f) t << stripPath(f); - if (anchor) t << "_" << anchor; + if (anchor) t << "_" << anchor; t << "}{"; } else @@ -1512,8 +1508,8 @@ void LatexGenerator::writeObjectLink(const char *ref, const char *f, { t << "\\mbox{\\hyperlink{"; if (f) t << stripPath(f); - if (f && anchor) t << "_"; - if (anchor) t << anchor; + if (f && anchor) t << "_"; + if (anchor) t << anchor; t << "}{"; docify(text); t << "}}"; @@ -1523,7 +1519,7 @@ void LatexGenerator::writeObjectLink(const char *ref, const char *f, t << "\\textbf{ "; docify(text); t << "}"; - } + } } void LatexGenerator::startPageRef() @@ -1534,7 +1530,7 @@ void LatexGenerator::startPageRef() void LatexGenerator::endPageRef(const char *clname, const char *anchor) { t << "}{"; - if (clname) t << clname; + if (clname) t << clname; if (anchor) t << "_" << anchor; t << "}"; } @@ -1548,13 +1544,13 @@ void LatexGenerator::startTitleHead(const char *fileName) { t << "\\hypertarget{" << stripPath(fileName) << "}{}"; } - if (Config_getBool(COMPACT_LATEX)) + if (Config_getBool(COMPACT_LATEX)) { - t << "\\doxysubsection{"; + t << "\\doxysubsection{"; } - else + else { - t << "\\doxysection{"; + t << "\\doxysection{"; } } @@ -1573,26 +1569,26 @@ void LatexGenerator::endTitleHead(const char *fileName,const char *name) void LatexGenerator::startTitle() { - if (Config_getBool(COMPACT_LATEX)) + if (Config_getBool(COMPACT_LATEX)) { - t << "\\doxysubsection{"; + t << "\\doxysubsection{"; } - else + else { - t << "\\doxysection{"; + t << "\\doxysection{"; } } void LatexGenerator::startGroupHeader(int extraIndentLevel) { - if (Config_getBool(COMPACT_LATEX)) + if (Config_getBool(COMPACT_LATEX)) { extraIndentLevel++; } if (extraIndentLevel==3) { - t << "\\doxysubparagraph*{"; + t << "\\doxysubparagraph*{"; } else if (extraIndentLevel==2) { @@ -1617,11 +1613,11 @@ void LatexGenerator::endGroupHeader(int) void LatexGenerator::startMemberHeader(const char *,int) { - if (Config_getBool(COMPACT_LATEX)) + if (Config_getBool(COMPACT_LATEX)) { - t << "\\doxysubsubsection*{"; + t << "\\doxysubsubsection*{"; } - else + else { t << "\\doxysubsection*{"; } @@ -1731,9 +1727,9 @@ void LatexGenerator::endDoxyAnchor(const char *fName,const char *anchor) } void LatexGenerator::writeAnchor(const char *fName,const char *name) -{ +{ //printf("LatexGenerator::writeAnchor(%s,%s)\n",fName,name); - t << "\\label{" << stripPath(name) << "}" << endl; + t << "\\label{" << stripPath(name) << "}" << endl; static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); static bool usePDFLatex = Config_getBool(USE_PDFLATEX); if (usePDFLatex && pdfHyperlinks) @@ -1777,7 +1773,7 @@ void LatexGenerator::addIndexItem(const char *s1,const char *s2) } -void LatexGenerator::startSection(const char *lab,const char *,SectionInfo::SectionType type) +void LatexGenerator::startSection(const char *lab,const char *,SectionType type) { static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); static bool usePDFLatex = Config_getBool(USE_PDFLATEX); @@ -1790,11 +1786,11 @@ void LatexGenerator::startSection(const char *lab,const char *,SectionInfo::Sect { switch(type) { - case SectionInfo::Page: t << "doxysubsection"; break; - case SectionInfo::Section: t << "doxysubsubsection"; break; - case SectionInfo::Subsection: t << "doxyparagraph"; break; - case SectionInfo::Subsubsection: t << "doxysubparagraph"; break; - case SectionInfo::Paragraph: t << "doxysubparagraph"; break; + case SectionType::Page: t << "doxysubsection"; break; + case SectionType::Section: t << "doxysubsubsection"; break; + case SectionType::Subsection: t << "doxyparagraph"; break; + case SectionType::Subsubsection: t << "doxysubparagraph"; break; + case SectionType::Paragraph: t << "doxysubparagraph"; break; default: ASSERT(0); break; } t << "{"; @@ -1803,18 +1799,18 @@ void LatexGenerator::startSection(const char *lab,const char *,SectionInfo::Sect { switch(type) { - case SectionInfo::Page: t << "doxysection"; break; - case SectionInfo::Section: t << "doxysubsection"; break; - case SectionInfo::Subsection: t << "doxysubsubsection"; break; - case SectionInfo::Subsubsection: t << "doxyparagraph"; break; - case SectionInfo::Paragraph: t << "doxysubparagraph"; break; + case SectionType::Page: t << "doxysection"; break; + case SectionType::Section: t << "doxysubsection"; break; + case SectionType::Subsection: t << "doxysubsubsection"; break; + case SectionType::Subsubsection: t << "doxyparagraph"; break; + case SectionType::Paragraph: t << "doxysubparagraph"; break; default: ASSERT(0); break; } t << "{"; } } -void LatexGenerator::endSection(const char *lab,SectionInfo::SectionType) +void LatexGenerator::endSection(const char *lab,SectionType) { t << "}\\label{" << lab << "}" << endl; } @@ -1883,31 +1879,31 @@ void LatexGenerator::endMemberTemplateParams(const char *,const char *) } } -void LatexGenerator::startMemberItem(const char *,int annoType,const char *) -{ +void LatexGenerator::startMemberItem(const char *,int annoType,const char *) +{ //printf("LatexGenerator::startMemberItem(%d)\n",annType); if (!m_insideTabbing) { - t << "\\item " << endl; + t << "\\item " << endl; templateMemberItem = (annoType == 3); } } -void LatexGenerator::endMemberItem() +void LatexGenerator::endMemberItem() { if (m_insideTabbing) { t << "\\\\"; - } + } templateMemberItem = FALSE; - t << endl; + t << endl; } -void LatexGenerator::startMemberDescription(const char *,const char *,bool) +void LatexGenerator::startMemberDescription(const char *,const char *,bool) { if (!m_insideTabbing) - { - t << "\\begin{DoxyCompactList}\\small\\item\\em "; + { + t << "\\begin{DoxyCompactList}\\small\\item\\em "; } else { @@ -1916,12 +1912,12 @@ void LatexGenerator::startMemberDescription(const char *,const char *,bool) } } -void LatexGenerator::endMemberDescription() -{ +void LatexGenerator::endMemberDescription() +{ if (!m_insideTabbing) { - //t << "\\item\\end{DoxyCompactList}"; - t << "\\end{DoxyCompactList}"; + //t << "\\item\\end{DoxyCompactList}"; + t << "\\end{DoxyCompactList}"; } else { @@ -1930,7 +1926,7 @@ void LatexGenerator::endMemberDescription() } -void LatexGenerator::writeNonBreakableSpace(int) +void LatexGenerator::writeNonBreakableSpace(int) { //printf("writeNonBreakableSpace()\n"); if (m_insideTabbing) @@ -1939,7 +1935,7 @@ void LatexGenerator::writeNonBreakableSpace(int) } else { - t << "~"; + t << "~"; } } @@ -1999,25 +1995,25 @@ void LatexGenerator::endDescTableData() t << "\\\\\n\\hline\n" << endl; } -void LatexGenerator::lastIndexPage() +void LatexGenerator::lastIndexPage() { } -void LatexGenerator::startMemberList() -{ +void LatexGenerator::startMemberList() +{ if (!m_insideTabbing) { - t << "\\begin{DoxyCompactItemize}" << endl; + t << "\\begin{DoxyCompactItemize}" << endl; } } -void LatexGenerator::endMemberList() +void LatexGenerator::endMemberList() { //printf("LatexGenerator::endMemberList(%d)\n",m_insideTabbing); if (!m_insideTabbing) { - t << "\\end{DoxyCompactItemize}" << endl; + t << "\\end{DoxyCompactItemize}" << endl; } } @@ -2027,7 +2023,7 @@ void LatexGenerator::startMemberGroupHeader(bool hasHeader) if (hasHeader) t << "\\begin{Indent}"; t << "\\textbf{ "; // changed back to rev 756 due to bug 660501 - //if (Config_getBool(COMPACT_LATEX)) + //if (Config_getBool(COMPACT_LATEX)) //{ // t << "\\doxysubparagraph*{"; //} @@ -2060,80 +2056,80 @@ void LatexGenerator::startMemberGroup() void LatexGenerator::endMemberGroup(bool hasHeader) { - if (hasHeader)t << "\\end{Indent}"; + if (hasHeader)t << "\\end{Indent}"; t << endl; } -void LatexGenerator::startDotGraph() +void LatexGenerator::startDotGraph() { newParagraph(); } -void LatexGenerator::endDotGraph(DotClassGraph &g) +void LatexGenerator::endDotGraph(DotClassGraph &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); } -void LatexGenerator::startInclDepGraph() +void LatexGenerator::startInclDepGraph() { } -void LatexGenerator::endInclDepGraph(DotInclDepGraph &g) +void LatexGenerator::endInclDepGraph(DotInclDepGraph &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); } -void LatexGenerator::startGroupCollaboration() +void LatexGenerator::startGroupCollaboration() { } -void LatexGenerator::endGroupCollaboration(DotGroupCollaboration &g) +void LatexGenerator::endGroupCollaboration(DotGroupCollaboration &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); } -void LatexGenerator::startCallGraph() +void LatexGenerator::startCallGraph() { } -void LatexGenerator::endCallGraph(DotCallGraph &g) +void LatexGenerator::endCallGraph(DotCallGraph &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); } -void LatexGenerator::startDirDepGraph() +void LatexGenerator::startDirDepGraph() { } -void LatexGenerator::endDirDepGraph(DotDirDeps &g) +void LatexGenerator::endDirDepGraph(DotDirDeps &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); } -void LatexGenerator::startDescription() -{ - t << "\\begin{description}" << endl; +void LatexGenerator::startDescription() +{ + t << "\\begin{description}" << endl; } -void LatexGenerator::endDescription() -{ - t << "\\end{description}" << endl; +void LatexGenerator::endDescription() +{ + t << "\\end{description}" << endl; m_firstDescItem=TRUE; } -void LatexGenerator::startDescItem() -{ +void LatexGenerator::startDescItem() +{ m_firstDescItem=TRUE; - t << "\\item["; + t << "\\item["; } -void LatexGenerator::endDescItem() -{ - if (m_firstDescItem) +void LatexGenerator::endDescItem() +{ + if (m_firstDescItem) { t << "]" << endl; m_firstDescItem=FALSE; - } + } else { lineBreak(); @@ -2276,11 +2272,11 @@ void LatexGenerator::endCodeFragment() void LatexGenerator::startInlineHeader() { - if (Config_getBool(COMPACT_LATEX)) + if (Config_getBool(COMPACT_LATEX)) { - t << "\\doxyparagraph*{"; + t << "\\doxyparagraph*{"; } - else + else { t << "\\doxysubsubsection*{"; } diff --git a/src/latexgen.h b/src/latexgen.h index 7d4cae8..2c32388 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -22,7 +22,7 @@ class QFile; -static const char *latexStyleExtension = ".sty"; +#define LATEX_STYLE_EXTENSION ".sty" class LatexCodeGenerator : public CodeOutputInterface { @@ -241,8 +241,8 @@ class LatexGenerator : public OutputGenerator void endParamList(); void startDescForItem() { t << "\\par" << endl; } void endDescForItem() {} - void startSection(const char *,const char *,SectionInfo::SectionType); - void endSection(const char *,SectionInfo::SectionType); + void startSection(const char *,const char *,SectionType); + void endSection(const char *,SectionType); void addIndexItem(const char *,const char *); void startIndent() {} void endIndent() {} diff --git a/src/layout.cpp b/src/layout.cpp index 946b612..fd31803 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -63,7 +63,7 @@ static bool elemIsVisible(const QXmlAttributes &attrib,bool defVal=TRUE) const ConfigValues::Info *opt = ConfigValues::instance().get(id); if (opt && opt->type==ConfigValues::Info::Bool) { - return ConfigValues::instance().*((ConfigValues::InfoBool*)opt)->item; + return ConfigValues::instance().*(opt->value.b); } else if (!opt) { @@ -84,7 +84,7 @@ LayoutNavEntry *LayoutNavEntry::find(LayoutNavEntry::Kind kind, LayoutNavEntry *entry; for (li.toFirst();(entry=li.current());++li) { - // depth first search, needed to find the entry furthest from the + // depth first search, needed to find the entry furthest from the // root in case an entry is in the tree twice result = entry->find(kind,file); if (result) return result; @@ -99,7 +99,7 @@ LayoutNavEntry *LayoutNavEntry::find(LayoutNavEntry::Kind kind, QCString LayoutNavEntry::url() const { QCString url = baseFile().stripWhiteSpace(); - if ((kind()!=LayoutNavEntry::User && kind()!=LayoutNavEntry::UserGroup) || + if ((kind()!=LayoutNavEntry::User && kind()!=LayoutNavEntry::UserGroup) || (kind()==LayoutNavEntry::UserGroup && url.left(9)=="usergroup")) { url+=Doxygen::htmlFileExtension; @@ -111,7 +111,7 @@ QCString LayoutNavEntry::url() const bool found=FALSE; if (resolveLink(0,url.mid(5).stripWhiteSpace(),TRUE,&d,anchor)) { - if (d && d->isLinkable()) + if (d && d->isLinkable()) { url=d->getOutputFileBase()+Doxygen::htmlFileExtension; if (!anchor.isEmpty()) @@ -137,14 +137,14 @@ class LayoutParser : public QXmlDefaultHandler private: class StartElementHandler { - typedef void (LayoutParser::*Handler)(const QXmlAttributes &attrib); + typedef void (LayoutParser::*Handler)(const QXmlAttributes &attrib); public: - StartElementHandler(LayoutParser *parent, Handler h) + StartElementHandler(LayoutParser *parent, Handler h) : m_parent(parent), m_handler(h) {} virtual ~StartElementHandler() {} - virtual void operator()(const QXmlAttributes &attrib) - { - (m_parent->*m_handler)(attrib); + virtual void operator()(const QXmlAttributes &attrib) + { + (m_parent->*m_handler)(attrib); } protected: StartElementHandler() : m_parent(0), m_handler(0) {} @@ -156,13 +156,13 @@ class LayoutParser : public QXmlDefaultHandler class StartElementHandlerKind : public StartElementHandler { typedef void (LayoutParser::*Handler)(LayoutDocEntry::Kind kind, - const QXmlAttributes &attrib); + const QXmlAttributes &attrib); public: - StartElementHandlerKind(LayoutParser *parent, LayoutDocEntry::Kind k,Handler h) + StartElementHandlerKind(LayoutParser *parent, LayoutDocEntry::Kind k,Handler h) : m_parent(parent), m_kind(k), m_handler(h) {} - void operator()(const QXmlAttributes &attrib) - { - (m_parent->*m_handler)(m_kind,attrib); + void operator()(const QXmlAttributes &attrib) + { + (m_parent->*m_handler)(m_kind,attrib); } private: LayoutParser *m_parent; @@ -174,14 +174,14 @@ class LayoutParser : public QXmlDefaultHandler { typedef void (LayoutParser::*Handler)(LayoutDocEntry::Kind kind, const QXmlAttributes &attrib, - const QCString &title); + const QCString &title); public: StartElementHandlerSection(LayoutParser *parent, LayoutDocEntry::Kind k,Handler h, - const QCString &title) + const QCString &title) : m_parent(parent), m_kind(k), m_handler(h), m_title(title) {} - void operator()(const QXmlAttributes &attrib) - { - (m_parent->*m_handler)(m_kind,attrib,m_title); + void operator()(const QXmlAttributes &attrib) + { + (m_parent->*m_handler)(m_kind,attrib,m_title); } private: LayoutParser *m_parent; @@ -195,19 +195,19 @@ class LayoutParser : public QXmlDefaultHandler typedef void (LayoutParser::*Handler)(const QXmlAttributes &attrib, MemberListType type, const QCString &title, - const QCString &subtitle); + const QCString &subtitle); public: - StartElementHandlerMember(LayoutParser *parent, + StartElementHandlerMember(LayoutParser *parent, Handler h, MemberListType type, const QCString &tl, const QCString &ss = QCString() - ) + ) : m_parent(parent), m_handler(h), m_type(type), m_title(tl), m_subscript(ss) {} - void operator()(const QXmlAttributes &attrib) - { - (m_parent->*m_handler)(attrib,m_type,m_title,m_subscript); + void operator()(const QXmlAttributes &attrib) + { + (m_parent->*m_handler)(attrib,m_type,m_title,m_subscript); } private: LayoutParser *m_parent; @@ -221,17 +221,17 @@ class LayoutParser : public QXmlDefaultHandler { typedef void (LayoutParser::*Handler)(LayoutNavEntry::Kind kind, const QXmlAttributes &attrib, - const QCString &title); + const QCString &title); public: StartElementHandlerNavEntry(LayoutParser *parent, - LayoutNavEntry::Kind kind, + LayoutNavEntry::Kind kind, Handler h, const QCString &tl - ) + ) : m_parent(parent), m_kind(kind), m_handler(h), m_title(tl) {} - void operator()(const QXmlAttributes &attrib) - { - (m_parent->*m_handler)(m_kind,attrib,m_title); + void operator()(const QXmlAttributes &attrib) + { + (m_parent->*m_handler)(m_kind,attrib,m_title); } private: LayoutParser *m_parent; @@ -242,7 +242,7 @@ class LayoutParser : public QXmlDefaultHandler class EndElementHandler { - typedef void (LayoutParser::*Handler)(); + typedef void (LayoutParser::*Handler)(); public: EndElementHandler(LayoutParser *parent, Handler h) : m_parent(parent), m_handler(h) {} void operator()() { (m_parent->*m_handler)(); } @@ -266,51 +266,51 @@ class LayoutParser : public QXmlDefaultHandler m_rootNav = 0; //bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - //bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); + //bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); //bool javaOpt = Config_getBool(OPTIMIZE_OUTPUT_JAVA); bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); // start & end handlers - m_sHandler.insert("doxygenlayout", + m_sHandler.insert("doxygenlayout", new StartElementHandler(this,&LayoutParser::startLayout)); - m_eHandler.insert("doxygenlayout", + m_eHandler.insert("doxygenlayout", new EndElementHandler(this,&LayoutParser::endLayout)); // class layout handlers - m_sHandler.insert("navindex", + m_sHandler.insert("navindex", new StartElementHandler(this,&LayoutParser::startNavIndex)); - m_sHandler.insert("navindex/tab", + m_sHandler.insert("navindex/tab", new StartElementHandler(this,&LayoutParser::startNavEntry)); - m_eHandler.insert("navindex/tab", + m_eHandler.insert("navindex/tab", new EndElementHandler(this,&LayoutParser::endNavEntry)); - m_eHandler.insert("navindex", + m_eHandler.insert("navindex", new EndElementHandler(this,&LayoutParser::endNavIndex)); // class layout handlers - m_sHandler.insert("class", + m_sHandler.insert("class", new StartElementHandler(this,&LayoutParser::startClass)); - m_sHandler.insert("class/briefdescription", + m_sHandler.insert("class/briefdescription", new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/detaileddescription", + m_sHandler.insert("class/detaileddescription", new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, theTranslator->trDetailedDescription())); - m_sHandler.insert("class/authorsection", + m_sHandler.insert("class/authorsection", new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/includes", + m_sHandler.insert("class/includes", new StartElementHandlerKind(this,LayoutDocEntry::ClassIncludes,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/inheritancegraph", + m_sHandler.insert("class/inheritancegraph", new StartElementHandlerKind(this,LayoutDocEntry::ClassInheritanceGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/collaborationgraph", + m_sHandler.insert("class/collaborationgraph", new StartElementHandlerKind(this,LayoutDocEntry::ClassCollaborationGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/allmemberslink", + m_sHandler.insert("class/allmemberslink", new StartElementHandlerKind(this,LayoutDocEntry::ClassAllMembersLink,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/usedfiles", + m_sHandler.insert("class/usedfiles", new StartElementHandlerKind(this,LayoutDocEntry::ClassUsedFiles,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/memberdecl", + m_sHandler.insert("class/memberdecl", new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("class/memberdecl/membergroups", + m_sHandler.insert("class/memberdecl/membergroups", new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/memberdecl/nestedclasses", + m_sHandler.insert("class/memberdecl/nestedclasses", new StartElementHandlerSection(this,LayoutDocEntry::ClassNestedClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_2_OPTIONS( theTranslator->trCompounds(), @@ -323,118 +323,118 @@ class LayoutParser : public QXmlDefaultHandler m_sHandler.insert("class/memberdecl/interfaces", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_interfaces,theTranslator->trInterfaces())); - m_sHandler.insert("class/memberdecl/publictypes", + m_sHandler.insert("class/memberdecl/publictypes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_pubTypes,theTranslator->trPublicTypes())); - m_sHandler.insert("class/memberdecl/publicslots", + m_sHandler.insert("class/memberdecl/publicslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pubSlots,theTranslator->trPublicSlots())); - m_sHandler.insert("class/memberdecl/signals", + MemberListType_pubSlots,theTranslator->trPublicSlots())); + m_sHandler.insert("class/memberdecl/signals", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_signals,theTranslator->trSignals())); - m_sHandler.insert("class/memberdecl/publicmethods", + MemberListType_signals,theTranslator->trSignals())); + m_sHandler.insert("class/memberdecl/publicmethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_pubMethods, COMPILE_FOR_2_OPTIONS( theTranslator->trPublicMembers(), SrcLangExt_ObjC,theTranslator->trInstanceMethods(), SrcLangExt_Slice,theTranslator->trOperations() - ))); - m_sHandler.insert("class/memberdecl/publicstaticmethods", + ))); + m_sHandler.insert("class/memberdecl/publicstaticmethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_pubStaticMethods, COMPILE_FOR_1_OPTION( theTranslator->trStaticPublicMembers(), SrcLangExt_ObjC,theTranslator->trClassMethods() - ))); - m_sHandler.insert("class/memberdecl/publicattributes", + ))); + m_sHandler.insert("class/memberdecl/publicattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_pubAttribs, COMPILE_FOR_1_OPTION( theTranslator->trPublicAttribs(), SrcLangExt_Slice,theTranslator->trDataMembers() - ))); - m_sHandler.insert("class/memberdecl/publicstaticattributes", + ))); + m_sHandler.insert("class/memberdecl/publicstaticattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs())); - m_sHandler.insert("class/memberdecl/protectedtypes", + MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs())); + m_sHandler.insert("class/memberdecl/protectedtypes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_proTypes,theTranslator->trProtectedTypes())); - m_sHandler.insert("class/memberdecl/protectedslots", + MemberListType_proTypes,theTranslator->trProtectedTypes())); + m_sHandler.insert("class/memberdecl/protectedslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_proSlots,theTranslator->trProtectedSlots())); - m_sHandler.insert("class/memberdecl/protectedmethods", + MemberListType_proSlots,theTranslator->trProtectedSlots())); + m_sHandler.insert("class/memberdecl/protectedmethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_proMethods,theTranslator->trProtectedMembers())); - m_sHandler.insert("class/memberdecl/protectedstaticmethods", + MemberListType_proMethods,theTranslator->trProtectedMembers())); + m_sHandler.insert("class/memberdecl/protectedstaticmethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers())); - m_sHandler.insert("class/memberdecl/protectedattributes", + m_sHandler.insert("class/memberdecl/protectedattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_proAttribs,theTranslator->trProtectedAttribs())); - m_sHandler.insert("class/memberdecl/protectedstaticattributes", + MemberListType_proAttribs,theTranslator->trProtectedAttribs())); + m_sHandler.insert("class/memberdecl/protectedstaticattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs())); - m_sHandler.insert("class/memberdecl/packagetypes", + MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs())); + m_sHandler.insert("class/memberdecl/packagetypes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pacTypes,theTranslator->trPackageTypes())); - m_sHandler.insert("class/memberdecl/packagemethods", + MemberListType_pacTypes,theTranslator->trPackageTypes())); + m_sHandler.insert("class/memberdecl/packagemethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pacMethods,theTranslator->trPackageMembers())); - m_sHandler.insert("class/memberdecl/packagestaticmethods", + MemberListType_pacMethods,theTranslator->trPackageMembers())); + m_sHandler.insert("class/memberdecl/packagestaticmethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers())); - m_sHandler.insert("class/memberdecl/packageattributes", + MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers())); + m_sHandler.insert("class/memberdecl/packageattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pacAttribs,theTranslator->trPackageAttribs())); - m_sHandler.insert("class/memberdecl/packagestaticattributes", + MemberListType_pacAttribs,theTranslator->trPackageAttribs())); + m_sHandler.insert("class/memberdecl/packagestaticattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs())); - m_sHandler.insert("class/memberdecl/properties", + MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs())); + m_sHandler.insert("class/memberdecl/properties", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_properties,theTranslator->trProperties())); - m_sHandler.insert("class/memberdecl/events", + MemberListType_properties,theTranslator->trProperties())); + m_sHandler.insert("class/memberdecl/events", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_events,theTranslator->trEvents())); - m_sHandler.insert("class/memberdecl/privatetypes", + MemberListType_events,theTranslator->trEvents())); + m_sHandler.insert("class/memberdecl/privatetypes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_priTypes,theTranslator->trPrivateTypes())); - m_sHandler.insert("class/memberdecl/privateslots", + MemberListType_priTypes,theTranslator->trPrivateTypes())); + m_sHandler.insert("class/memberdecl/privateslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_priSlots,theTranslator->trPrivateSlots())); - m_sHandler.insert("class/memberdecl/privatemethods", + MemberListType_priSlots,theTranslator->trPrivateSlots())); + m_sHandler.insert("class/memberdecl/privatemethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_priMethods,theTranslator->trPrivateMembers())); - m_sHandler.insert("class/memberdecl/privatestaticmethods", + MemberListType_priMethods,theTranslator->trPrivateMembers())); + m_sHandler.insert("class/memberdecl/privatestaticmethods", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers())); - m_sHandler.insert("class/memberdecl/privateattributes", + MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers())); + m_sHandler.insert("class/memberdecl/privateattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_priAttribs,theTranslator->trPrivateAttribs())); - m_sHandler.insert("class/memberdecl/privatestaticattributes", + MemberListType_priAttribs,theTranslator->trPrivateAttribs())); + m_sHandler.insert("class/memberdecl/privatestaticattributes", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs())); - m_sHandler.insert("class/memberdecl/friends", + MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs())); + m_sHandler.insert("class/memberdecl/friends", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_friends,theTranslator->trFriends())); - m_sHandler.insert("class/memberdecl/related", + m_sHandler.insert("class/memberdecl/related", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_related,theTranslator->trRelatedFunctions(), - theTranslator->trRelatedSubscript())); - m_eHandler.insert("class/memberdecl", + theTranslator->trRelatedSubscript())); + m_eHandler.insert("class/memberdecl", new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("class/memberdef", + m_sHandler.insert("class/memberdef", new StartElementHandler(this,&LayoutParser::startMemberDef)); - m_sHandler.insert("class/memberdef/inlineclasses", + m_sHandler.insert("class/memberdef/inlineclasses", new StartElementHandlerSection(this,LayoutDocEntry::ClassInlineClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_1_OPTION( theTranslator->trClassDocumentation(), SrcLangExt_Fortran,theTranslator->trTypeDocumentation() ))); - m_sHandler.insert("class/memberdef/typedefs", + m_sHandler.insert("class/memberdef/typedefs", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation())); - m_sHandler.insert("class/memberdef/enums", + m_sHandler.insert("class/memberdef/enums", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation())); m_sHandler.insert("class/memberdef/services", @@ -443,10 +443,10 @@ class LayoutParser : public QXmlDefaultHandler m_sHandler.insert("class/memberdef/interfaces", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_interfaceMembers,theTranslator->trInterfaces())); - m_sHandler.insert("class/memberdef/constructors", + m_sHandler.insert("class/memberdef/constructors", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_constructors,theTranslator->trConstructorDocumentation())); - m_sHandler.insert("class/memberdef/functions", + m_sHandler.insert("class/memberdef/functions", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_functionMembers, COMPILE_FOR_3_OPTIONS( @@ -455,41 +455,41 @@ class LayoutParser : public QXmlDefaultHandler SrcLangExt_Fortran,theTranslator->trMemberFunctionDocumentationFortran(), SrcLangExt_Slice,theTranslator->trOperationDocumentation() ))); - m_sHandler.insert("class/memberdef/related", + m_sHandler.insert("class/memberdef/related", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation())); - m_sHandler.insert("class/memberdef/variables", + m_sHandler.insert("class/memberdef/variables", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_variableMembers, COMPILE_FOR_1_OPTION( theTranslator->trMemberDataDocumentation(), SrcLangExt_Slice,theTranslator->trDataMemberDocumentation() - ))); - m_sHandler.insert("class/memberdef/properties", + ))); + m_sHandler.insert("class/memberdef/properties", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_propertyMembers,theTranslator->trPropertyDocumentation())); - m_sHandler.insert("class/memberdef/events", + m_sHandler.insert("class/memberdef/events", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_eventMembers,theTranslator->trEventDocumentation())); - m_eHandler.insert("class/memberdef", + m_eHandler.insert("class/memberdef", new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("class", + m_eHandler.insert("class", new EndElementHandler(this,&LayoutParser::endClass)); // namespace layout handlers - m_sHandler.insert("namespace", + m_sHandler.insert("namespace", new StartElementHandler(this,&LayoutParser::startNamespace)); - m_sHandler.insert("namespace/briefdescription", + m_sHandler.insert("namespace/briefdescription", new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("namespace/detaileddescription", + m_sHandler.insert("namespace/detaileddescription", new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, theTranslator->trDetailedDescription())); - m_sHandler.insert("namespace/authorsection", + m_sHandler.insert("namespace/authorsection", new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("namespace/memberdecl", + m_sHandler.insert("namespace/memberdecl", new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("namespace/memberdecl/nestednamespaces", + m_sHandler.insert("namespace/memberdecl/nestednamespaces", new StartElementHandlerSection(this,LayoutDocEntry::NamespaceNestedNamespaces,&LayoutParser::startSectionEntry, COMPILE_FOR_5_OPTIONS( theTranslator->trNamespaces(), @@ -503,37 +503,37 @@ class LayoutParser : public QXmlDefaultHandler m_sHandler.insert("namespace/memberdecl/constantgroups", new StartElementHandlerSection(this,LayoutDocEntry::NamespaceNestedConstantGroups,&LayoutParser::startSectionEntry, theTranslator->trConstantGroups())); - m_sHandler.insert("namespace/memberdecl/interfaces", + m_sHandler.insert("namespace/memberdecl/interfaces", new StartElementHandlerSection(this,LayoutDocEntry::NamespaceInterfaces,&LayoutParser::startSectionEntry, theTranslator->trSliceInterfaces())); - m_sHandler.insert("namespace/memberdecl/classes", + m_sHandler.insert("namespace/memberdecl/classes", new StartElementHandlerSection(this,LayoutDocEntry::NamespaceClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_2_OPTIONS( theTranslator->trCompounds(), SrcLangExt_VHDL,theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), SrcLangExt_Fortran,theTranslator->trDataTypes() ))); - m_sHandler.insert("namespace/memberdecl/structs", + m_sHandler.insert("namespace/memberdecl/structs", new StartElementHandlerSection(this,LayoutDocEntry::NamespaceStructs,&LayoutParser::startSectionEntry, theTranslator->trStructs())); - m_sHandler.insert("namespace/memberdecl/exceptions", + m_sHandler.insert("namespace/memberdecl/exceptions", new StartElementHandlerSection(this,LayoutDocEntry::NamespaceExceptions,&LayoutParser::startSectionEntry, theTranslator->trExceptions())); - m_sHandler.insert("namespace/memberdecl/membergroups", + m_sHandler.insert("namespace/memberdecl/membergroups", new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("namespace/memberdecl/typedefs", + m_sHandler.insert("namespace/memberdecl/typedefs", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decTypedefMembers,theTranslator->trTypedefs())); - m_sHandler.insert("namespace/memberdecl/sequences", + m_sHandler.insert("namespace/memberdecl/sequences", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decSequenceMembers,theTranslator->trSequences())); - m_sHandler.insert("namespace/memberdecl/dictionaries", + m_sHandler.insert("namespace/memberdecl/dictionaries", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decDictionaryMembers,theTranslator->trDictionaries())); - m_sHandler.insert("namespace/memberdecl/enums", + m_sHandler.insert("namespace/memberdecl/enums", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decEnumMembers,theTranslator->trEnumerations())); - m_sHandler.insert("namespace/memberdecl/functions", + m_sHandler.insert("namespace/memberdecl/functions", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decFuncMembers, COMPILE_FOR_2_OPTIONS( @@ -541,89 +541,89 @@ class LayoutParser : public QXmlDefaultHandler SrcLangExt_Fortran,theTranslator->trSubprograms(), SrcLangExt_VHDL,theTranslator->trFunctionAndProc() ))); - m_sHandler.insert("namespace/memberdecl/variables", + m_sHandler.insert("namespace/memberdecl/variables", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables())); - m_eHandler.insert("namespace/memberdecl", + m_eHandler.insert("namespace/memberdecl", new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("namespace/memberdef", + m_sHandler.insert("namespace/memberdef", new StartElementHandler(this,&LayoutParser::startMemberDef)); - m_sHandler.insert("namespace/memberdef/inlineclasses", + m_sHandler.insert("namespace/memberdef/inlineclasses", new StartElementHandlerSection(this,LayoutDocEntry::NamespaceInlineClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_1_OPTION( theTranslator->trClassDocumentation(), SrcLangExt_Fortran,theTranslator->trTypeDocumentation() ))); - m_sHandler.insert("namespace/memberdef/typedefs", + m_sHandler.insert("namespace/memberdef/typedefs", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation())); - m_sHandler.insert("namespace/memberdef/sequences", + m_sHandler.insert("namespace/memberdef/sequences", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation())); - m_sHandler.insert("namespace/memberdef/dictionaries", + m_sHandler.insert("namespace/memberdef/dictionaries", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docDictionaryMembers, theTranslator->trDictionaryDocumentation())); - m_sHandler.insert("namespace/memberdef/enums", + m_sHandler.insert("namespace/memberdef/enums", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation())); - m_sHandler.insert("namespace/memberdef/functions", + m_sHandler.insert("namespace/memberdef/functions", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docFuncMembers, COMPILE_FOR_1_OPTION( theTranslator->trFunctionDocumentation(), SrcLangExt_Fortran,theTranslator->trSubprogramDocumentation() ))); - m_sHandler.insert("namespace/memberdef/variables", + m_sHandler.insert("namespace/memberdef/variables", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docVarMembers, sliceOpt ? theTranslator->trConstantDocumentation() : theTranslator->trVariableDocumentation())); - m_eHandler.insert("namespace/memberdef", + m_eHandler.insert("namespace/memberdef", new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("namespace", + m_eHandler.insert("namespace", new EndElementHandler(this,&LayoutParser::endNamespace)); // file layout handlers - m_sHandler.insert("file", + m_sHandler.insert("file", new StartElementHandler(this,&LayoutParser::startFile)); - m_sHandler.insert("file/briefdescription", + m_sHandler.insert("file/briefdescription", new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/detaileddescription", + m_sHandler.insert("file/detaileddescription", new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, theTranslator->trDetailedDescription())); - m_sHandler.insert("file/authorsection", + m_sHandler.insert("file/authorsection", new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/includes", + m_sHandler.insert("file/includes", new StartElementHandlerKind(this,LayoutDocEntry::FileIncludes,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/includegraph", + m_sHandler.insert("file/includegraph", new StartElementHandlerKind(this,LayoutDocEntry::FileIncludeGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/includedbygraph", + m_sHandler.insert("file/includedbygraph", new StartElementHandlerKind(this,LayoutDocEntry::FileIncludedByGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/sourcelink", + m_sHandler.insert("file/sourcelink", new StartElementHandlerKind(this,LayoutDocEntry::FileSourceLink,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/memberdecl/membergroups", + m_sHandler.insert("file/memberdecl/membergroups", new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/memberdecl", + m_sHandler.insert("file/memberdecl", new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("file/memberdecl/interfaces", + m_sHandler.insert("file/memberdecl/interfaces", new StartElementHandlerSection(this,LayoutDocEntry::FileInterfaces,&LayoutParser::startSectionEntry, theTranslator->trSliceInterfaces())); - m_sHandler.insert("file/memberdecl/classes", + m_sHandler.insert("file/memberdecl/classes", new StartElementHandlerSection(this,LayoutDocEntry::FileClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_2_OPTIONS( theTranslator->trCompounds(), SrcLangExt_VHDL,theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), SrcLangExt_Fortran,theTranslator->trDataTypes() ))); - m_sHandler.insert("file/memberdecl/structs", + m_sHandler.insert("file/memberdecl/structs", new StartElementHandlerSection(this,LayoutDocEntry::FileStructs,&LayoutParser::startSectionEntry, theTranslator->trStructs())); - m_sHandler.insert("file/memberdecl/exceptions", + m_sHandler.insert("file/memberdecl/exceptions", new StartElementHandlerSection(this,LayoutDocEntry::FileExceptions,&LayoutParser::startSectionEntry, theTranslator->trExceptions())); - m_sHandler.insert("file/memberdecl/namespaces", + m_sHandler.insert("file/memberdecl/namespaces", new StartElementHandlerSection(this,LayoutDocEntry::FileNamespaces,&LayoutParser::startSectionEntry, COMPILE_FOR_4_OPTIONS( theTranslator->trNamespaces(), @@ -635,22 +635,22 @@ class LayoutParser : public QXmlDefaultHandler m_sHandler.insert("file/memberdecl/constantgroups", new StartElementHandlerSection(this,LayoutDocEntry::FileConstantGroups,&LayoutParser::startSectionEntry, theTranslator->trConstantGroups())); - m_sHandler.insert("file/memberdecl/defines", + m_sHandler.insert("file/memberdecl/defines", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decDefineMembers,theTranslator->trDefines())); - m_sHandler.insert("file/memberdecl/typedefs", + m_sHandler.insert("file/memberdecl/typedefs", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decTypedefMembers,theTranslator->trTypedefs())); - m_sHandler.insert("file/memberdecl/sequences", + m_sHandler.insert("file/memberdecl/sequences", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decSequenceMembers,theTranslator->trSequences())); - m_sHandler.insert("file/memberdecl/dictionaries", + m_sHandler.insert("file/memberdecl/dictionaries", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decDictionaryMembers,theTranslator->trDictionaries())); - m_sHandler.insert("file/memberdecl/enums", + m_sHandler.insert("file/memberdecl/enums", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decEnumMembers,theTranslator->trEnumerations())); - m_sHandler.insert("file/memberdecl/functions", + m_sHandler.insert("file/memberdecl/functions", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decFuncMembers, COMPILE_FOR_2_OPTIONS( @@ -658,115 +658,115 @@ class LayoutParser : public QXmlDefaultHandler SrcLangExt_Fortran,theTranslator->trSubprograms(), SrcLangExt_VHDL,theTranslator->trFunctionAndProc() ))); - m_sHandler.insert("file/memberdecl/variables", + m_sHandler.insert("file/memberdecl/variables", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables())); - m_eHandler.insert("file/memberdecl", + m_eHandler.insert("file/memberdecl", new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("file/memberdef", + m_sHandler.insert("file/memberdef", new StartElementHandler(this,&LayoutParser::startMemberDef)); - m_sHandler.insert("file/memberdef/inlineclasses", + m_sHandler.insert("file/memberdef/inlineclasses", new StartElementHandlerSection(this,LayoutDocEntry::FileInlineClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_1_OPTION( theTranslator->trClassDocumentation(), SrcLangExt_Fortran,theTranslator->trTypeDocumentation() ))); - m_sHandler.insert("file/memberdef/defines", + m_sHandler.insert("file/memberdef/defines", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docDefineMembers,theTranslator->trDefineDocumentation())); - m_sHandler.insert("file/memberdef/typedefs", + m_sHandler.insert("file/memberdef/typedefs", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation())); - m_sHandler.insert("file/memberdef/sequences", + m_sHandler.insert("file/memberdef/sequences", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation())); - m_sHandler.insert("file/memberdef/dictionaries", + m_sHandler.insert("file/memberdef/dictionaries", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docDictionaryMembers, theTranslator->trDictionaryDocumentation())); - m_sHandler.insert("file/memberdef/enums", + m_sHandler.insert("file/memberdef/enums", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docEnumMembers, theTranslator->trEnumerationTypeDocumentation())); - m_sHandler.insert("file/memberdef/functions", + m_sHandler.insert("file/memberdef/functions", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docFuncMembers, COMPILE_FOR_1_OPTION( theTranslator->trFunctionDocumentation(), SrcLangExt_Fortran,theTranslator->trSubprogramDocumentation() ))); - m_sHandler.insert("file/memberdef/variables", + m_sHandler.insert("file/memberdef/variables", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docVarMembers,theTranslator->trVariableDocumentation())); - m_eHandler.insert("file/memberdef", + m_eHandler.insert("file/memberdef", new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("file", + m_eHandler.insert("file", new EndElementHandler(this,&LayoutParser::endFile)); // group layout handlers - m_sHandler.insert("group", + m_sHandler.insert("group", new StartElementHandler(this,&LayoutParser::startGroup)); - m_sHandler.insert("group/briefdescription", + m_sHandler.insert("group/briefdescription", new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/detaileddescription", + m_sHandler.insert("group/detaileddescription", new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, theTranslator->trDetailedDescription())); - m_sHandler.insert("group/authorsection", + m_sHandler.insert("group/authorsection", new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/groupgraph", + m_sHandler.insert("group/groupgraph", new StartElementHandlerKind(this,LayoutDocEntry::GroupGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/memberdecl/membergroups", + m_sHandler.insert("group/memberdecl/membergroups", new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/memberdecl", + m_sHandler.insert("group/memberdecl", new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("group/memberdecl/classes", + m_sHandler.insert("group/memberdecl/classes", new StartElementHandlerSection(this,LayoutDocEntry::GroupClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_2_OPTIONS( theTranslator->trCompounds(), SrcLangExt_VHDL,theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), SrcLangExt_Fortran,theTranslator->trDataTypes() ))); - m_sHandler.insert("group/memberdecl/namespaces", + m_sHandler.insert("group/memberdecl/namespaces", new StartElementHandlerSection(this,LayoutDocEntry::GroupNamespaces,&LayoutParser::startSectionEntry, COMPILE_FOR_2_OPTIONS( theTranslator->trNamespaces(), SrcLangExt_Java,theTranslator->trPackages(), SrcLangExt_Fortran,theTranslator->trModules() ))); - m_sHandler.insert("group/memberdecl/dirs", + m_sHandler.insert("group/memberdecl/dirs", new StartElementHandlerSection(this,LayoutDocEntry::GroupDirs,&LayoutParser::startSectionEntry, theTranslator->trDirectories() )); - m_sHandler.insert("group/memberdecl/nestedgroups", + m_sHandler.insert("group/memberdecl/nestedgroups", new StartElementHandlerSection(this,LayoutDocEntry::GroupNestedGroups,&LayoutParser::startSectionEntry, theTranslator->trModules() )); - m_sHandler.insert("group/memberdecl/files", + m_sHandler.insert("group/memberdecl/files", new StartElementHandlerSection(this,LayoutDocEntry::GroupFiles,&LayoutParser::startSectionEntry, theTranslator->trFile(TRUE,FALSE) )); - m_sHandler.insert("group/memberdecl/defines", + m_sHandler.insert("group/memberdecl/defines", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decDefineMembers,theTranslator->trDefines())); - m_sHandler.insert("group/memberdecl/typedefs", + m_sHandler.insert("group/memberdecl/typedefs", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decTypedefMembers,theTranslator->trTypedefs())); - m_sHandler.insert("group/memberdecl/sequences", + m_sHandler.insert("group/memberdecl/sequences", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decSequenceMembers,theTranslator->trSequences())); - m_sHandler.insert("group/memberdecl/dictionaries", + m_sHandler.insert("group/memberdecl/dictionaries", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decDictionaryMembers,theTranslator->trDictionaries())); - m_sHandler.insert("group/memberdecl/enums", + m_sHandler.insert("group/memberdecl/enums", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decEnumMembers,theTranslator->trEnumerations())); - m_sHandler.insert("group/memberdecl/enumvalues", + m_sHandler.insert("group/memberdecl/enumvalues", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decEnumValMembers,theTranslator->trEnumerationValues())); - m_sHandler.insert("group/memberdecl/functions", + m_sHandler.insert("group/memberdecl/functions", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decFuncMembers, COMPILE_FOR_2_OPTIONS( @@ -774,116 +774,116 @@ class LayoutParser : public QXmlDefaultHandler SrcLangExt_Fortran,theTranslator->trSubprograms(), SrcLangExt_VHDL,theTranslator->trFunctionAndProc() ))); - m_sHandler.insert("group/memberdecl/variables", + m_sHandler.insert("group/memberdecl/variables", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decVarMembers,theTranslator->trVariables())); - m_sHandler.insert("group/memberdecl/signals", + m_sHandler.insert("group/memberdecl/signals", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decSignalMembers,theTranslator->trSignals())); - m_sHandler.insert("group/memberdecl/publicslots", + m_sHandler.insert("group/memberdecl/publicslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decPubSlotMembers,theTranslator->trPublicSlots())); - m_sHandler.insert("group/memberdecl/protectedslots", + m_sHandler.insert("group/memberdecl/protectedslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decProSlotMembers,theTranslator->trProtectedSlots())); - m_sHandler.insert("group/memberdecl/privateslots", + m_sHandler.insert("group/memberdecl/privateslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decPriSlotMembers,theTranslator->trPrivateSlots())); - m_sHandler.insert("group/memberdecl/events", + m_sHandler.insert("group/memberdecl/events", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decEventMembers,theTranslator->trEvents())); - m_sHandler.insert("group/memberdecl/properties", + m_sHandler.insert("group/memberdecl/properties", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decPropMembers,theTranslator->trProperties())); - m_sHandler.insert("group/memberdecl/friends", + m_sHandler.insert("group/memberdecl/friends", new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, MemberListType_decFriendMembers,theTranslator->trFriends())); - m_eHandler.insert("group/memberdecl", + m_eHandler.insert("group/memberdecl", new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("group/memberdef", + m_sHandler.insert("group/memberdef", new StartElementHandler(this,&LayoutParser::startMemberDef)); - m_sHandler.insert("group/memberdef/pagedocs", + m_sHandler.insert("group/memberdef/pagedocs", new StartElementHandlerKind(this,LayoutDocEntry::GroupPageDocs,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/memberdef/inlineclasses", + m_sHandler.insert("group/memberdef/inlineclasses", new StartElementHandlerSection(this,LayoutDocEntry::GroupInlineClasses,&LayoutParser::startSectionEntry, COMPILE_FOR_1_OPTION( theTranslator->trClassDocumentation(), SrcLangExt_Fortran,theTranslator->trTypeDocumentation() ))); - m_sHandler.insert("group/memberdef/defines", + m_sHandler.insert("group/memberdef/defines", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docDefineMembers,theTranslator->trDefineDocumentation())); - m_sHandler.insert("group/memberdef/typedefs", + m_sHandler.insert("group/memberdef/typedefs", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation())); - m_sHandler.insert("group/memberdef/sequences", + m_sHandler.insert("group/memberdef/sequences", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation())); - m_sHandler.insert("group/memberdef/dictionaries", + m_sHandler.insert("group/memberdef/dictionaries", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docDictionaryMembers, theTranslator->trDictionaryDocumentation())); - m_sHandler.insert("group/memberdef/enums", + m_sHandler.insert("group/memberdef/enums", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation())); - m_sHandler.insert("group/memberdef/enumvalues", + m_sHandler.insert("group/memberdef/enumvalues", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation())); - m_sHandler.insert("group/memberdef/functions", + m_sHandler.insert("group/memberdef/functions", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docFuncMembers, COMPILE_FOR_1_OPTION( theTranslator->trFunctionDocumentation(), SrcLangExt_Fortran,theTranslator->trSubprogramDocumentation() ))); - m_sHandler.insert("group/memberdef/variables", + m_sHandler.insert("group/memberdef/variables", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docVarMembers,theTranslator->trVariableDocumentation())); - m_sHandler.insert("group/memberdef/signals", + m_sHandler.insert("group/memberdef/signals", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docSignalMembers,theTranslator->trSignals())); - m_sHandler.insert("group/memberdef/publicslots", + MemberListType_docSignalMembers,theTranslator->trSignals())); + m_sHandler.insert("group/memberdef/publicslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docPubSlotMembers,theTranslator->trPublicSlots())); - m_sHandler.insert("group/memberdef/protectedslots", + m_sHandler.insert("group/memberdef/protectedslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docProSlotMembers,theTranslator->trProtectedSlots())); - m_sHandler.insert("group/memberdef/privateslots", + m_sHandler.insert("group/memberdef/privateslots", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots())); - m_sHandler.insert("group/memberdef/events", + m_sHandler.insert("group/memberdef/events", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docEventMembers,theTranslator->trEvents())); - m_sHandler.insert("group/memberdef/properties", + m_sHandler.insert("group/memberdef/properties", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docPropMembers,theTranslator->trProperties())); - m_sHandler.insert("group/memberdef/friends", + m_sHandler.insert("group/memberdef/friends", new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, MemberListType_docFriendMembers,theTranslator->trFriends())); - m_eHandler.insert("group/memberdef", + m_eHandler.insert("group/memberdef", new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("group", + m_eHandler.insert("group", new EndElementHandler(this,&LayoutParser::endGroup)); // directory layout handlers - m_sHandler.insert("directory", + m_sHandler.insert("directory", new StartElementHandler(this,&LayoutParser::startDirectory)); - m_sHandler.insert("directory/briefdescription", + m_sHandler.insert("directory/briefdescription", new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("directory/detaileddescription", + m_sHandler.insert("directory/detaileddescription", new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, theTranslator->trDetailedDescription())); - m_sHandler.insert("directory/directorygraph", + m_sHandler.insert("directory/directorygraph", new StartElementHandlerKind(this,LayoutDocEntry::DirGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("directory/memberdecl", + m_sHandler.insert("directory/memberdecl", new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("directory/memberdecl/dirs", + m_sHandler.insert("directory/memberdecl/dirs", new StartElementHandlerKind(this,LayoutDocEntry::DirSubDirs,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("directory/memberdecl/files", + m_sHandler.insert("directory/memberdecl/files", new StartElementHandlerKind(this,LayoutDocEntry::DirFiles,&LayoutParser::startSimpleEntry)); - m_eHandler.insert("directory/memberdecl", + m_eHandler.insert("directory/memberdecl", new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_eHandler.insert("directory", + m_eHandler.insert("directory", new EndElementHandler(this,&LayoutParser::endDirectory)); } @@ -964,7 +964,7 @@ class LayoutParser : public QXmlDefaultHandler if (m_rootNav && !m_rootNav->find(LayoutNavEntry::MainPage)) { // no MainPage node... add one as the first item of the root node... - new LayoutNavEntry(m_rootNav,LayoutNavEntry::MainPage, TRUE, + new LayoutNavEntry(m_rootNav,LayoutNavEntry::MainPage, TRUE, /*Config_getBool(GENERATE_TREEVIEW) ? "main" :*/ "index", theTranslator->trMainPage(),"",TRUE); } @@ -974,8 +974,8 @@ class LayoutParser : public QXmlDefaultHandler { static bool javaOpt = Config_getBool(OPTIMIZE_OUTPUT_JAVA); static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); + static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); static bool hasGraphicalHierarchy = Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY); static bool extractAll = Config_getBool(EXTRACT_ALL); @@ -1213,7 +1213,7 @@ class LayoutParser : public QXmlDefaultHandler } i++; } - if (mapping[i].typeStr==0) + if (mapping[i].typeStr==0) { if (type.isEmpty()) { @@ -1230,7 +1230,7 @@ class LayoutParser : public QXmlDefaultHandler QCString title = attrib.value("title").utf8(); bool isVisible = elemIsVisible(attrib); if (title.isEmpty()) // use default title - { + { title = mapping[i].mainName; // use title for main row if (m_rootNav!=LayoutDocManager::instance().rootNavEntry() && !mapping[i].subName.isEmpty()) { @@ -1384,7 +1384,7 @@ class LayoutParser : public QXmlDefaultHandler } // reimplemented from QXmlDefaultHandler - bool startElement( const QString&, const QString&, + bool startElement( const QString&, const QString&, const QString& name, const QXmlAttributes& attrib ) { //printf("startElement [%s]::[%s]\n",m_scope.data(),name.data()); @@ -1424,15 +1424,15 @@ class LayoutParser : public QXmlDefaultHandler } private: - LayoutParser() : m_sHandler(163), m_eHandler(17), m_invalidEntry(FALSE), m_part(0), m_rootNav(NULL) { } + LayoutParser() : m_sHandler(163), m_eHandler(17) { } ~LayoutParser() { delete m_rootNav; } QDict<StartElementHandler> m_sHandler; QDict<EndElementHandler> m_eHandler; QCString m_scope; - int m_part; - LayoutNavEntry *m_rootNav; - bool m_invalidEntry; + int m_part = 0; + LayoutNavEntry *m_rootNav = 0; + bool m_invalidEntry = false; static int m_userGroupCount; }; @@ -1562,13 +1562,13 @@ void writeDefaultLayoutFile(const char *fileName) } QTextStream t(&f); t.setEncoding(QTextStream::UnicodeUTF8); - t << substitute(layout_default,"$doxygenversion",getVersion()); + t << substitute(layout_default,"$doxygenversion",getDoxygenVersion()); } //---------------------------------------------------------------------------------- // Convert input to a title. -// The format of input can be a simple title "A title" or in case there are different +// The format of input can be a simple title "A title" or in case there are different // titles for some programming languages they can take the following form: // "A title|16=Another title|8=Yet Another title" // where the number is a value of SrcLangExt in decimal notation (i.e. 16=Java, 8=IDL). diff --git a/src/linkedmap.h b/src/linkedmap.h new file mode 100644 index 0000000..84dcf26 --- /dev/null +++ b/src/linkedmap.h @@ -0,0 +1,177 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef LINKEDMAP_H +#define LINKEDMAP_H + +#include <unordered_map> +#include <vector> +#include <memory> +#include <string> +#include <algorithm> + +//! @brief Container class representing a vector of objects with unique keys. +//! @details Objects can efficiently be looked up given the key. +//! Objects are owned by the container. +//! When adding objects the order of addition is kept, and used while iterating. +template<class T> +class LinkedMap +{ + public: + using Ptr = std::unique_ptr<T>; + using Vec = std::vector<Ptr>; + using Map = std::unordered_map<std::string,T*>; + using iterator = typename Vec::iterator; + using const_iterator = typename Vec::const_iterator; + + //! Find an object given the key. + //! Returns a pointer to the element if found or nullptr if it is not found. + const T *find(const char *k) const + { + std::string key = k ? std::string(k) : std::string(); + auto it = m_lookup.find(key); + return it!=m_lookup.end() ? it->second : nullptr; + } + + //! A non-const wrapper for find() const + T* find(const char *key) + { + return const_cast<T*>(static_cast<const LinkedMap&>(*this).find(key)); + } + + //! Adds a new object to the ordered set if it was not added already. + //! Return a non-owning pointer to the newly added object, or to the existing object if + //! it was already inserted before under the given key. + template<class...Args> + T *add(const char *k, Args&&... args) + { + T *result = find(k); + if (result==nullptr) + { + std::string key = k ? std::string(k) : std::string(); + Ptr ptr = std::make_unique<T>(k,std::forward<Args>(args)...); + result = ptr.get(); + m_lookup.insert({key,result}); + m_entries.push_back(std::move(ptr)); + } + return result; + } + + //! Removes an object from the container and deletes it. + //! Returns true if the object was delete or false it is was not found. + bool del(const char *k) + { + std::string key = k ? std::string(k) : std::string(); + auto it = m_lookup.find(key); + if (it!=m_lookup.end()) + { + auto vecit = std::find_if(m_entries.begin(),m_entries.end(),[obj=it->second](auto &el) { return el.get()==obj; }); + if (vecit!=m_entries.end()) // should always be true + { + m_entries.erase(vecit); + m_lookup.erase(it); + return true; + } + } + return false; + } + + iterator begin() { return m_entries.begin(); } + iterator end() { return m_entries.end(); } + const_iterator begin() const { return m_entries.cbegin(); } + const_iterator end() const { return m_entries.cend(); } + bool empty() const { return m_entries.empty(); } + size_t size() const { return m_entries.size(); } + + void clear() + { + m_entries.clear(); + m_lookup.clear(); + } + + private: + Map m_lookup; + Vec m_entries; +}; + +#if 0 // not yet used +//! @brief Container class representing a vector of objects with unique keys. +//! @details Objects can be efficiently be looked up given the key. +//! Objects are \e not owned by the container, the container will only hold references. +//! When adding objects the order of addition is kept, and used while iterating. +template<class T> +class LinkedRefMap +{ + public: + using Ptr = T*; + using Vec = std::vector<Ptr>; + using Map = std::unordered_map<std::string,T*>; + using iterator = typename Vec::iterator; + using const_iterator = typename Vec::const_iterator; + + //! find an object given the key. + //! Returns a pointer to the object if found or nullptr if it is not found. + const T *find(const char *k) const + { + std::string key = k ? std::string(k) : std::string(); + auto it = m_lookup.find(key); + return it!=m_lookup.end() ? it->second : nullptr; + } + + //! non-const wrapper for find() const + T* find(const char *key) + { + return const_cast<T*>(static_cast<const LinkedRefMap&>(*this).find(key)); + } + + //! Adds a new object to the ordered set if it was not added already. + //! Return true if the object was added, and false if an object with the same key + //! was already added before + bool add(const char *k, T* obj) + { + if (find(k)==nullptr) // new element + { + std::string key = k ? std::string(k) : std::string(); + m_lookup.insert({key,obj}); + m_entries.push_back(obj); + return true; + } + else // already existing, don't add + { + return false; + } + } + + iterator begin() { return m_entries.begin(); } + iterator end() { return m_entries.end(); } + const_iterator begin() const { return m_entries.cbegin(); } + const_iterator end() const { return m_entries.cend(); } + bool empty() const { return m_entries.empty(); } + size_t size() const { return m_entries.size(); } + + void clear() + { + m_entries.clear(); + m_lookup.clear(); + } + + private: + Map m_lookup; + Vec m_entries; +}; +#endif + + +#endif diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index 6b76008..fef857e 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -304,6 +304,12 @@ void ManDocVisitor::visit(DocInclude *inc) case DocInclude::DontIncWithLines: case DocInclude::HtmlInclude: case DocInclude::LatexInclude: + case DocInclude::RtfInclude: + case DocInclude::XmlInclude: + case DocInclude::DocbookInclude: + break; + case DocInclude::ManInclude: + m_t << inc->text(); break; case DocInclude::VerbInclude: if (!m_firstCol) m_t << endl; diff --git a/src/mangen.cpp b/src/mangen.cpp index 5f07932..1faa296 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -41,7 +41,7 @@ static QCString getExtension() QCString ext = Config_getString(MAN_EXTENSION); if (ext.isEmpty()) { - ext = "3"; + ext = "3"; } else { @@ -49,7 +49,7 @@ static QCString getExtension() { if (ext.length()==1) { - ext = "3"; + ext = "3"; } else // strip . { @@ -91,8 +91,8 @@ ManGenerator::~ManGenerator() void ManGenerator::init() { - QCString &manOutput = Config_getString(MAN_OUTPUT); - + QCString manOutput = Config_getString(MAN_OUTPUT); + QDir d(manOutput); if (!d.exists() && !d.mkdir(manOutput)) { @@ -139,7 +139,7 @@ static QCString buildFileName(const char *name) } QCString manExtension = "." + getExtension(); - if (fileName.right(manExtension.length())!=manExtension) + if (fileName.right(manExtension.length())!=manExtension) { fileName+=manExtension; } @@ -161,11 +161,11 @@ void ManGenerator::endFile() void ManGenerator::endTitleHead(const char *,const char *name) { - t << ".TH \"" << name << "\" " << getExtension() << " \"" + t << ".TH \"" << name << "\" " << getExtension() << " \"" << dateToString(FALSE) << "\" \""; if (!Config_getString(PROJECT_NUMBER).isEmpty()) t << "Version " << Config_getString(PROJECT_NUMBER) << "\" \""; - if (Config_getString(PROJECT_NAME).isEmpty()) + if (Config_getString(PROJECT_NAME).isEmpty()) t << "Doxygen"; else t << Config_getString(PROJECT_NAME); @@ -284,7 +284,7 @@ void ManGenerator::docify(const char *str) { const char *p=str; char c=0; - while ((c=*p++)) + while ((c=*p++)) { switch(c) { @@ -318,8 +318,8 @@ void ManGenerator::codify(const char *str) case '.': t << "\\&."; break; // see bug652277 case '\t': spacesToNextTabStop = Config_getInt(TAB_SIZE) - (m_col%Config_getInt(TAB_SIZE)); - t << Doxygen::spaces.left(spacesToNextTabStop); - m_col+=spacesToNextTabStop; + t << Doxygen::spaces.left(spacesToNextTabStop); + m_col+=spacesToNextTabStop; break; case '\n': t << "\n"; m_firstCol=TRUE; m_col=0; break; case '\\': t << "\\"; m_col++; break; @@ -346,21 +346,21 @@ void ManGenerator::writeChar(char c) m_paragraph=FALSE; } -void ManGenerator::startDescList(SectionTypes) +void ManGenerator::startDescList(SectionTypes) { - if (!m_firstCol) - { t << endl << ".PP" << endl; - m_firstCol=TRUE; m_paragraph=TRUE; + if (!m_firstCol) + { t << endl << ".PP" << endl; + m_firstCol=TRUE; m_paragraph=TRUE; m_col=0; } m_paragraph=FALSE; startBold(); } -void ManGenerator::startTitle() -{ - if (!m_firstCol) t << endl; - t << ".SH \""; +void ManGenerator::startTitle() +{ + if (!m_firstCol) t << endl; + t << ".SH \""; m_firstCol=FALSE; m_paragraph=FALSE; } @@ -370,40 +370,40 @@ void ManGenerator::endTitle() t << "\""; } -void ManGenerator::startItemListItem() -{ - if (!m_firstCol) t << endl; - t << ".TP" << endl; +void ManGenerator::startItemListItem() +{ + if (!m_firstCol) t << endl; + t << ".TP" << endl; m_firstCol=TRUE; m_paragraph=FALSE; m_col=0; -} +} void ManGenerator::endItemListItem() { } -void ManGenerator::startCodeFragment() -{ +void ManGenerator::startCodeFragment() +{ newParagraph(); - t << ".nf" << endl; + t << ".nf" << endl; m_firstCol=TRUE; m_paragraph=FALSE; } -void ManGenerator::endCodeFragment() -{ +void ManGenerator::endCodeFragment() +{ if (!m_firstCol) t << endl; - t << ".fi" << endl; + t << ".fi" << endl; m_firstCol=TRUE; m_paragraph=FALSE; m_col=0; } -void ManGenerator::startMemberDoc(const char *,const char *,const char *,const char *,int,int,bool) -{ +void ManGenerator::startMemberDoc(const char *,const char *,const char *,const char *,int,int,bool) +{ if (!m_firstCol) t << endl; - t << ".SS \""; + t << ".SS \""; m_firstCol=FALSE; m_paragraph=FALSE; } @@ -413,7 +413,7 @@ void ManGenerator::startDoxyAnchor(const char *,const char *manName, const char *) { // something to be done? - if( !Config_getBool(MAN_LINKS) ) + if( !Config_getBool(MAN_LINKS) ) { return; // no } @@ -426,14 +426,14 @@ void ManGenerator::startDoxyAnchor(const char *,const char *manName, //printf("Converting man link '%s'->'%s'->'%s'\n", // name,baseName.data(),buildFileName(baseName).data()); - + // - remove dangerous characters and append suffix, then add dir prefix QCString fileName=m_dir+"/"+buildFileName( baseName ); QFile linkfile( fileName ); // - only create file if it doesn't exist already - if ( !linkfile.open( IO_ReadOnly ) ) + if ( !linkfile.open( IO_ReadOnly ) ) { - if ( linkfile.open( IO_WriteOnly ) ) + if ( linkfile.open( IO_WriteOnly ) ) { FTextStream linkstream; linkstream.setDevice(&linkfile); @@ -449,10 +449,10 @@ void ManGenerator::endMemberDoc(bool) t << "\"\n"; } -void ManGenerator::startSubsection() -{ +void ManGenerator::startSubsection() +{ if (!m_firstCol) t << endl; - t << ".SS \""; + t << ".SS \""; m_firstCol=FALSE; m_paragraph=FALSE; } @@ -463,10 +463,10 @@ void ManGenerator::endSubsection() } -void ManGenerator::startSubsubsection() -{ +void ManGenerator::startSubsubsection() +{ if (!m_firstCol) t << endl; - t << "\n.SS \""; + t << "\n.SS \""; m_firstCol=FALSE; m_paragraph=FALSE; } @@ -476,10 +476,10 @@ void ManGenerator::endSubsubsection() t << "\""; } -void ManGenerator::writeSynopsis() -{ +void ManGenerator::writeSynopsis() +{ if (!m_firstCol) t << endl; - t << ".SH SYNOPSIS\n.br\n.PP\n"; + t << ".SH SYNOPSIS\n.br\n.PP\n"; m_firstCol=TRUE; m_paragraph=FALSE; } @@ -534,31 +534,31 @@ void ManGenerator::endAnonTypeScope(int indentLevel) } -void ManGenerator::startMemberItem(const char *,int,const char *) -{ +void ManGenerator::startMemberItem(const char *,int,const char *) +{ if (m_firstCol && !m_insideTabbing) t << ".in +1c\n"; - t << "\n.ti -1c\n.RI \""; + t << "\n.ti -1c\n.RI \""; m_firstCol=FALSE; } -void ManGenerator::endMemberItem() -{ - t << "\"\n.br"; +void ManGenerator::endMemberItem() +{ + t << "\"\n.br"; } -void ManGenerator::startMemberList() -{ +void ManGenerator::startMemberList() +{ if (!m_insideTabbing) { - t << "\n.in +1c"; m_firstCol=FALSE; + t << "\n.in +1c"; m_firstCol=FALSE; } } -void ManGenerator::endMemberList() -{ +void ManGenerator::endMemberList() +{ if (!m_insideTabbing) { - t << "\n.in -1c"; m_firstCol=FALSE; + t << "\n.in -1c"; m_firstCol=FALSE; } } @@ -593,33 +593,33 @@ void ManGenerator::endMemberGroup(bool) m_firstCol=FALSE; } -void ManGenerator::startSection(const char *,const char *,SectionInfo::SectionType type) +void ManGenerator::startSection(const char *,const char *,SectionType type) { - if( !m_inHeader ) + if( !m_inHeader ) { switch(type) { - case SectionInfo::Page: startGroupHeader(FALSE); break; - case SectionInfo::Section: startGroupHeader(FALSE); break; - case SectionInfo::Subsection: startMemberHeader(0, -1); break; - case SectionInfo::Subsubsection: startMemberHeader(0, -1); break; - case SectionInfo::Paragraph: startMemberHeader(0, -1); break; + case SectionType::Page: startGroupHeader(FALSE); break; + case SectionType::Section: startGroupHeader(FALSE); break; + case SectionType::Subsection: startMemberHeader(0, -1); break; + case SectionType::Subsubsection: startMemberHeader(0, -1); break; + case SectionType::Paragraph: startMemberHeader(0, -1); break; default: ASSERT(0); break; } } } -void ManGenerator::endSection(const char *,SectionInfo::SectionType type) +void ManGenerator::endSection(const char *,SectionType type) { if( !m_inHeader ) { switch(type) { - case SectionInfo::Page: endGroupHeader(0); break; - case SectionInfo::Section: endGroupHeader(0); break; - case SectionInfo::Subsection: endMemberHeader(); break; - case SectionInfo::Subsubsection: endMemberHeader(); break; - case SectionInfo::Paragraph: endMemberHeader(); break; + case SectionType::Page: endGroupHeader(0); break; + case SectionType::Section: endGroupHeader(0); break; + case SectionType::Subsection: endMemberHeader(); break; + case SectionType::Subsubsection: endMemberHeader(); break; + case SectionType::Paragraph: endMemberHeader(); break; default: ASSERT(0); break; } } @@ -634,9 +634,9 @@ void ManGenerator::endSection(const char *,SectionInfo::SectionType type) void ManGenerator::startExamples() { - if (!m_firstCol) - { t << endl << ".PP" << endl; - m_firstCol=TRUE; m_paragraph=TRUE; + if (!m_firstCol) + { t << endl << ".PP" << endl; + m_firstCol=TRUE; m_paragraph=TRUE; m_col=0; } m_paragraph=FALSE; @@ -652,9 +652,9 @@ void ManGenerator::endExamples() void ManGenerator::startDescTable(const char *title) { - if (!m_firstCol) - { t << endl << ".PP" << endl; - m_firstCol=TRUE; m_paragraph=TRUE; + if (!m_firstCol) + { t << endl << ".PP" << endl; + m_firstCol=TRUE; m_paragraph=TRUE; m_col=0; } m_paragraph=FALSE; @@ -672,9 +672,9 @@ void ManGenerator::endDescTable() void ManGenerator::startParamList(ParamListTypes,const char *title) { - if (!m_firstCol) - { t << endl << ".PP" << endl; - m_firstCol=TRUE; m_paragraph=TRUE; + if (!m_firstCol) + { t << endl << ".PP" << endl; + m_firstCol=TRUE; m_paragraph=TRUE; m_col=0; } m_paragraph=FALSE; @@ -692,16 +692,16 @@ void ManGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { ManDocVisitor *visitor = new ManDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); - delete visitor; + delete visitor; m_firstCol=FALSE; m_paragraph = FALSE; } void ManGenerator::startConstraintList(const char *header) { - if (!m_firstCol) - { t << endl << ".PP" << endl; - m_firstCol=TRUE; m_paragraph=TRUE; + if (!m_firstCol) + { t << endl << ".PP" << endl; + m_firstCol=TRUE; m_paragraph=TRUE; m_col=0; } m_paragraph=FALSE; @@ -748,16 +748,16 @@ void ManGenerator::endConstraintList() } -void ManGenerator::startInlineHeader() +void ManGenerator::startInlineHeader() { - if (!m_firstCol) + if (!m_firstCol) { t << endl << ".PP" << endl << ".in -1c" << endl; } - t << ".RI \"\\fB"; + t << ".RI \"\\fB"; } -void ManGenerator::endInlineHeader() +void ManGenerator::endInlineHeader() { t << "\\fP\"" << endl << ".in +1c" << endl; m_firstCol = FALSE; @@ -765,7 +765,7 @@ void ManGenerator::endInlineHeader() void ManGenerator::startMemberDocSimple(bool isEnum) { - if (!m_firstCol) + if (!m_firstCol) { t << endl << ".PP" << endl; } diff --git a/src/mangen.h b/src/mangen.h index eba6c8d..a3a2a33 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -176,8 +176,8 @@ class ManGenerator : public OutputGenerator //void writeDescItem(); void startDescForItem(); void endDescForItem(); - void startSection(const char *,const char *,SectionInfo::SectionType); - void endSection(const char *,SectionInfo::SectionType); + void startSection(const char *,const char *,SectionType); + void endSection(const char *,SectionType); void addIndexItem(const char *,const char *) {} void startIndent() {} void endIndent() {} diff --git a/src/markdown.cpp b/src/markdown.cpp index 8594a15..00c0723 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -13,7 +13,7 @@ * */ -/* Note: part of the code below is inspired by libupskirt written by +/* Note: part of the code below is inspired by libupskirt written by * Natacha Porté. Original copyright message follows: * * Copyright (c) 2008, Natacha Porté @@ -35,9 +35,9 @@ #include <qglobal.h> #include <qregexp.h> #include <qfileinfo.h> -#include <qdict.h> -#include <qvector.h> -//#define USE_ORIGINAL_TABLES + +#include <unordered_map> +#include <functional> #include "markdown.h" #include "growbuf.h" @@ -46,13 +46,96 @@ #include "doxygen.h" #include "commentscan.h" #include "entry.h" -#include "bufstr.h" #include "commentcnv.h" #include "config.h" #include "section.h" #include "message.h" #include "portable.h" +#if !defined(NDEBUG) +#define ENABLE_TRACING +#endif + +#ifdef ENABLE_TRACING +#define IOSTREAM stdout +#define DATA_BUFSIZE 20 +#if defined(_WIN32) && !defined(CYGWIN) +#define PRETTY_FUNC __FUNCSIG__ +#else +#define PRETTY_FUNC __PRETTY_FUNCTION__ +#endif + +class Trace +{ + public: + Trace(const char *func) : m_func(func) + { + if (Debug::isFlagSet(Debug::Markdown)) + { + fprintf(IOSTREAM,"> %s\n",func); + s_indent++; + } + } + Trace(const char *func,const char *data) : m_func(func) + { + if (Debug::isFlagSet(Debug::Markdown)) + { + indent(); + char data_s[DATA_BUFSIZE*2+1] = ""; // worst case each input char outputs 2 chars + 0 terminator. + int j=0; + if (data) + { + for (int i=0;i<DATA_BUFSIZE;i++) + { + char c=data[i]; + if (c==0) break; + else if (c=='\n') { data_s[j++]='\\'; data_s[j++]='n'; } + else if (c=='\t') { data_s[j++]='\\'; data_s[j++]='t'; } + else if (c=='\r') { data_s[j++]='\\'; data_s[j++]='r'; } + else if (c=='\\') { data_s[j++]='\\'; data_s[j++]='\\'; } + else data_s[j++]=c; + } + } + data_s[j++]=0; + fprintf(IOSTREAM,"> %s data=[%s…]\n",func,data_s); + s_indent++; + } + } + ~Trace() + { + if (Debug::isFlagSet(Debug::Markdown)) + { + s_indent--; + indent(); + fprintf(IOSTREAM,"< %s\n",m_func); + } + } + void trace(const char *fmt,...) + { + if (Debug::isFlagSet(Debug::Markdown)) + { + indent(); + fprintf(IOSTREAM,": %s: ",m_func); + va_list args; + va_start(args,fmt); + vfprintf(IOSTREAM, fmt, args); + va_end(args); + } + } + private: + void indent() { for (int i=0;i<s_indent;i++) fputs(" ",IOSTREAM); } + const char *m_func; + static int s_indent; +}; + +int Trace::s_indent = 0; +#define TRACE(data) Trace trace_(PRETTY_FUNC,data); +#define TRACE_MORE(...) trace_.trace(__VA_ARGS__); +#else +#define TRACE(data) do {} while(false) +#define TRACE_MORE(...) do {} while(false) +#endif + //----------- // is character at position i in data part of an identifier? @@ -70,25 +153,18 @@ // is character at position i in data allowed before an emphasis section #define isOpenEmphChar(i) \ (data[i]=='\n' || data[i]==' ' || data[i]=='\'' || data[i]=='<' || \ - data[i]=='{' || data[i]=='(' || data[i]=='[' || data[i]==',' || \ - data[i]==':' || data[i]==';') + data[i]=='>' || data[i]=='{' || data[i]=='(' || data[i]=='[' || \ + data[i]==',' || data[i]==':' || data[i]==';') // is character at position i in data an escape that prevents ending an emphasis section // so for example *bla (*.txt) is cool* #define ignoreCloseEmphChar(i) \ - (data[i]=='(' || data[i]=='{' || data[i]=='[' || data[i]=='<' || \ + (data[i]=='(' || data[i]=='{' || data[i]=='[' || (data[i]=='<' && data[i+1]!='/') || \ data[i]=='\\' || \ data[i]=='@') //---------- -struct LinkRef -{ - LinkRef(const QCString &l,const QCString &t) : link(l), title(t) {} - QCString link; - QCString title; -}; - struct TableCell { TableCell() : colSpan(false) {} @@ -96,30 +172,51 @@ struct TableCell bool colSpan; }; -typedef int (*action_t)(GrowBuf &out,const char *data,int offset,int size); +Markdown::Markdown(const char *fileName,int lineNr,int indentLevel) + : m_fileName(fileName), m_lineNr(lineNr), m_indentLevel(indentLevel) +{ + using namespace std::placeholders; + // setup callback table for special characters + m_actions[(unsigned int)'_'] = std::bind(&Markdown::processEmphasis, this,_1,_2,_3); + m_actions[(unsigned int)'*'] = std::bind(&Markdown::processEmphasis, this,_1,_2,_3); + m_actions[(unsigned int)'~'] = std::bind(&Markdown::processEmphasis, this,_1,_2,_3); + m_actions[(unsigned int)'`'] = std::bind(&Markdown::processCodeSpan, this,_1,_2,_3); + m_actions[(unsigned int)'\\']= std::bind(&Markdown::processSpecialCommand,this,_1,_2,_3); + m_actions[(unsigned int)'@'] = std::bind(&Markdown::processSpecialCommand,this,_1,_2,_3); + m_actions[(unsigned int)'['] = std::bind(&Markdown::processLink, this,_1,_2,_3); + m_actions[(unsigned int)'!'] = std::bind(&Markdown::processLink, this,_1,_2,_3); + m_actions[(unsigned int)'<'] = std::bind(&Markdown::processHtmlTag, this,_1,_2,_3); + m_actions[(unsigned int)'-'] = std::bind(&Markdown::processNmdash, this,_1,_2,_3); + m_actions[(unsigned int)'"'] = std::bind(&Markdown::processQuoted, this,_1,_2,_3); + (void)m_lineNr; // not used yet +} enum Alignment { AlignNone, AlignLeft, AlignCenter, AlignRight }; -//---------- - -static QDict<LinkRef> g_linkRefs(257); -static action_t g_actions[256]; -static Entry *g_current; -static QCString g_fileName; -static int g_lineNr; -static int g_indentLevel=0; // 0 is outside markdown, -1=page level -static const char g_utf8_nbsp[3] = {'\xc2', '\xa0', '\0'}; // UTF-8 nbsp -static const char *g_doxy_nsbp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp -//---------- - +//---------- constants ------- +// +const uchar g_utf8_nbsp[3] = { 0xc2, 0xa0, 0}; // UTF-8 nbsp +const char *g_doxy_nsbp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp const int codeBlockIndent = 4; -static void processInline(GrowBuf &out,const char *data,int size); +//---------- helpers ------- + +// test if the next characters in data represent a new line (which can be character \n or string \ilinebr). +// returns 0 if no newline is found, or the number of characters that make up the newline if found. +inline int isNewline(const char *data) +{ + // normal newline + if (data[0] == '\n') return 1; + // artificial new line from ^^ in ALIASES + if (data[0] == '\\' && qstrncmp(data+1,"ilinebr",7)==0) return 8; + return 0; +} // escape characters that have a special meaning later on. static QCString escapeSpecialChars(const QCString &s) { + TRACE(s.data()); if (s.isEmpty()) return ""; bool insideQuote=FALSE; GrowBuf growBuf; @@ -145,6 +242,7 @@ static QCString escapeSpecialChars(const QCString &s) static void convertStringFragment(QCString &result,const char *data,int size) { + TRACE(result.data()); if (size<0) size=0; result.resize(size+1); memcpy(result.rawData(),data,size); @@ -194,8 +292,9 @@ static Alignment markersToAlignment(bool leftMarker,bool rightMarker) // \xmlonly..\endxmlonly // \rtfonly..\endrtfonly // \manonly..\endmanonly -static QCString isBlockCommand(const char *data,int offset,int size) +QCString Markdown::isBlockCommand(const char *data,int offset,int size) { + TRACE(data); bool openBracket = offset>0 && data[-1]=='{'; bool isEscaped = offset>0 && (data[-1]=='\\' || data[-1]=='@'); if (isEscaped) return QCString(); @@ -209,11 +308,11 @@ static QCString isBlockCommand(const char *data,int offset,int size) { return "}"; } - else if (blockName=="dot" || - blockName=="code" || + else if (blockName=="dot" || + blockName=="code" || blockName=="msc" || - blockName=="verbatim" || - blockName=="latexonly" || + blockName=="verbatim" || + blockName=="latexonly" || blockName=="htmlonly" || blockName=="xmlonly" || blockName=="rtfonly" || @@ -248,20 +347,22 @@ static QCString isBlockCommand(const char *data,int offset,int size) /** looks for the next emph char, skipping other constructs, and * stopping when either it is found, or we are at the end of a paragraph. */ -static int findEmphasisChar(const char *data, int size, char c, int c_size) +int Markdown::findEmphasisChar(const char *data, int size, char c, int c_size) { + TRACE(data); int i = 1; while (i<size) { - while (i<size && data[i]!=c && data[i]!='`' && + while (i<size && data[i]!=c && data[i]!='`' && data[i]!='\\' && data[i]!='@' && + !(data[i]=='/' && data[i-1]=='<') && // html end tag also ends emphasis data[i]!='\n') i++; //printf("findEmphasisChar: data=[%s] i=%d c=%c\n",data,i,data[i]); - // not counting escaped chars or characters that are unlikely + // not counting escaped chars or characters that are unlikely // to appear as the end of the emphasis char - if (i>0 && ignoreCloseEmphChar(i-1)) + if (ignoreCloseEmphChar(i-1)) { i++; continue; @@ -330,6 +431,10 @@ static int findEmphasisChar(const char *data, int size, char c, int c_size) i++; } } + else if (data[i-1]=='<' && data[i]=='/') // html end tag invalidates emphasis + { + return 0; + } else if (data[i]=='\n') // end * or _ at paragraph boundary { i++; @@ -346,8 +451,9 @@ static int findEmphasisChar(const char *data, int size, char c, int c_size) } /** process single emphasis */ -static int processEmphasis1(GrowBuf &out, const char *data, int size, char c) +int Markdown::processEmphasis1(const char *data, int size, char c) { + TRACE(data); int i = 0, len; /* skipping one symbol if coming from emph3 */ @@ -356,9 +462,9 @@ static int processEmphasis1(GrowBuf &out, const char *data, int size, char c) while (i<size) { len = findEmphasisChar(data+i, size-i, c, 1); - if (len==0) return 0; + if (len==0) return 0; i+=len; - if (i>=size) return 0; + if (i>=size) return 0; if (i+1<size && data[i+1]==c) { @@ -367,9 +473,9 @@ static int processEmphasis1(GrowBuf &out, const char *data, int size, char c) } if (data[i]==c && data[i-1]!=' ' && data[i-1]!='\n') { - out.addStr("<em>"); - processInline(out,data,i); - out.addStr("</em>"); + m_out.addStr("<em>"); + processInline(data,i); + m_out.addStr("</em>"); return i+1; } } @@ -377,8 +483,9 @@ static int processEmphasis1(GrowBuf &out, const char *data, int size, char c) } /** process double emphasis */ -static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) +int Markdown::processEmphasis2(const char *data, int size, char c) { + TRACE(data); int i = 0, len; while (i<size) @@ -389,15 +496,15 @@ static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) return 0; } i += len; - if (i+1<size && data[i]==c && data[i+1]==c && i && data[i-1]!=' ' && + if (i+1<size && data[i]==c && data[i+1]==c && i && data[i-1]!=' ' && data[i-1]!='\n' ) { - if (c == '~') out.addStr("<strike>"); - else out.addStr("<strong>"); - processInline(out,data,i); - if (c == '~') out.addStr("</strike>"); - else out.addStr("</strong>"); + if (c == '~') m_out.addStr("<strike>"); + else m_out.addStr("<strong>"); + processInline(data,i); + if (c == '~') m_out.addStr("</strike>"); + else m_out.addStr("</strong>"); return i + 2; } i++; @@ -406,10 +513,11 @@ static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) } /** Parsing triple emphasis. - * Finds the first closing tag, and delegates to the other emph + * Finds the first closing tag, and delegates to the other emph */ -static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) +int Markdown::processEmphasis3(const char *data, int size, char c) { + TRACE(data); int i = 0, len; while (i<size) @@ -429,15 +537,15 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) if (i+2<size && data[i+1]==c && data[i+2]==c) { - out.addStr("<em><strong>"); - processInline(out,data,i); - out.addStr("</strong></em>"); + m_out.addStr("<em><strong>"); + processInline(data,i); + m_out.addStr("</strong></em>"); return i+3; } else if (i+1<size && data[i+1]==c) { // double symbol found, handing over to emph1 - len = processEmphasis1(out, data-2, size+2, c); + len = processEmphasis1(data-2, size+2, c); if (len==0) { return 0; @@ -450,7 +558,7 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) else { // single symbol found, handing over to emph2 - len = processEmphasis2(out, data-1, size+1, c); + len = processEmphasis2(data-1, size+1, c); if (len==0) { return 0; @@ -465,8 +573,9 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) } /** Process ndash and mdashes */ -static int processNmdash(GrowBuf &out,const char *data,int off,int size) +int Markdown::processNmdash(const char *data,int off,int size) { + TRACE(data); // precondition: data[0]=='-' int i=1; int count=1; @@ -486,12 +595,12 @@ static int processNmdash(GrowBuf &out,const char *data,int off,int size) if (count==2 && (data[2]=='>')) return 0; // end HTML comment if (count==2 && (off<8 || qstrncmp(data-8,"operator",8)!=0)) // -- => ndash { - out.addStr("–"); + m_out.addStr("–"); return 2; } else if (count==3) // --- => ndash { - out.addStr("—"); + m_out.addStr("—"); return 3; } // not an ndash or mdash @@ -499,18 +608,19 @@ static int processNmdash(GrowBuf &out,const char *data,int off,int size) } /** Process quoted section "...", can contain one embedded newline */ -static int processQuoted(GrowBuf &out,const char *data,int,int size) +int Markdown::processQuoted(const char *data,int,int size) { + TRACE(data); int i=1; int nl=0; - while (i<size && data[i]!='"' && nl<2) + while (i<size && data[i]!='"' && nl<2) { if (data[i]=='\n') nl++; i++; } if (i<size && data[i]=='"' && nl<2) { - out.addStr(data,i+1); + m_out.addStr(data,i+1); return i+1; } // not a quoted section @@ -520,8 +630,9 @@ static int processQuoted(GrowBuf &out,const char *data,int,int size) /** Process a HTML tag. Note that <pre>..</pre> are treated specially, in * the sense that all code inside is written unprocessed */ -static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size,bool doWrite) +int Markdown::processHtmlTagWrite(const char *data,int offset,int size,bool doWrite) { + TRACE(data); if (offset>0 && data[-1]=='\\') return 0; // escaped < // find the end of the html tag @@ -543,7 +654,7 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size tolower(data[i+2])=='p' && tolower(data[i+3])=='r' && tolower(data[i+4])=='e' && tolower(data[i+5])=='>') { // found </pre> tag, copy from start to end of tag - if (doWrite) out.addStr(data,i+6); + if (doWrite) m_out.addStr(data,i+6); //printf("found <pre>..</pre> [%d..%d]\n",0,i+6); return i+6; } @@ -566,13 +677,13 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size if (data[i]=='/' && i<size-1 && data[i+1]=='>') // <bla/> { //printf("Found htmlTag={%s}\n",QCString(data).left(i+2).data()); - if (doWrite) out.addStr(data,i+2); + if (doWrite) m_out.addStr(data,i+2); return i+2; } else if (data[i]=='>') // <bla> { //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data()); - if (doWrite) out.addStr(data,i+1); + if (doWrite) m_out.addStr(data,i+1); return i+1; } else if (data[i]==' ') // <bla attr=... @@ -592,7 +703,7 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size else if (!insideAttr && data[i]=='>') // found end of tag { //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data()); - if (doWrite) out.addStr(data,i+1); + if (doWrite) m_out.addStr(data,i+1); return i+1; } i++; @@ -603,13 +714,16 @@ static int processHtmlTagWrite(GrowBuf &out,const char *data,int offset,int size //printf("Not a valid html tag\n"); return 0; } -static int processHtmlTag(GrowBuf &out,const char *data,int offset,int size) + +int Markdown::processHtmlTag(const char *data,int offset,int size) { - return processHtmlTagWrite(out,data,offset,size,true); + TRACE(data); + return processHtmlTagWrite(data,offset,size,true); } -static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) +int Markdown::processEmphasis(const char *data,int offset,int size) { + TRACE(data); if ((offset>0 && !isOpenEmphChar(-1)) || // invalid char before * or _ (size>1 && data[0]!=data[1] && !(isIdChar(1) || extraChar(1) || data[1]=='[')) || // invalid char after * or _ (size>2 && data[0]==data[1] && !(isIdChar(2) || extraChar(2) || data[2]=='['))) // invalid char after ** or __ @@ -622,8 +736,8 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) if (size>2 && c!='~' && data[1]!=c) // _bla or *bla { // whitespace cannot follow an opening emphasis - if (data[1]==' ' || data[1]=='\n' || - (ret = processEmphasis1(out, data+1, size-1, c)) == 0) + if (data[1]==' ' || data[1]=='\n' || + (ret = processEmphasis1(data+1, size-1, c)) == 0) { return 0; } @@ -631,8 +745,8 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) } if (size>3 && data[1]==c && data[2]!=c) // __bla or **bla { - if (data[2]==' ' || data[2]=='\n' || - (ret = processEmphasis2(out, data+2, size-2, c)) == 0) + if (data[2]==' ' || data[2]=='\n' || + (ret = processEmphasis2(data+2, size-2, c)) == 0) { return 0; } @@ -640,8 +754,8 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) } if (size>4 && c!='~' && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla { - if (data[3]==' ' || data[3]=='\n' || - (ret = processEmphasis3(out, data+3, size-3, c)) == 0) + if (data[3]==' ' || data[3]=='\n' || + (ret = processEmphasis3(data+3, size-3, c)) == 0) { return 0; } @@ -650,29 +764,32 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) return 0; } -static void writeMarkdownImage(GrowBuf &out, const char *fmt, bool explicitTitle, QCString title, QCString content, QCString link, FileDef *fd) +void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle, + const QCString &title, const QCString &content, + const QCString &link, const FileDef *fd) { - out.addStr("@image "); - out.addStr(fmt); - out.addStr(" "); - out.addStr(link.mid(fd ? 0 : 5)); + m_out.addStr("@image{inline} "); + m_out.addStr(fmt); + m_out.addStr(" "); + m_out.addStr(link.mid(fd ? 0 : 5)); if (!explicitTitle && !content.isEmpty()) { - out.addStr(" \""); - out.addStr(content); - out.addStr("\""); + m_out.addStr(" \""); + m_out.addStr(content); + m_out.addStr("\""); } else if ((content.isEmpty() || explicitTitle) && !title.isEmpty()) { - out.addStr(" \""); - out.addStr(title); - out.addStr("\""); + m_out.addStr(" \""); + m_out.addStr(title); + m_out.addStr("\""); } - out.addStr("\n"); + m_out.addStr("\n"); } -static int processLink(GrowBuf &out,const char *data,int,int size) +int Markdown::processLink(const char *data,int,int size) { + TRACE(data); QCString content; QCString link; QCString title; @@ -826,14 +943,15 @@ static int processLink(GrowBuf &out,const char *data,int,int size) link=content; } // lookup reference - LinkRef *lr = g_linkRefs.find(link.lower()); - if (lr) // found it + QCString link_lower = link.lower(); + auto lr_it=m_linkRefs.find(link_lower.str()); + if (lr_it!=m_linkRefs.end()) // found it { - link = lr->link; - title = lr->title; + link = lr_it->second.link; + title = lr_it->second.title; //printf("processLink: ref: link={%s} title={%s}\n",link.data(),title.data()); } - else // reference not found! + else // reference not found! { //printf("processLink: ref {%s} do not exist\n",link.lower().data()); return 0; @@ -842,12 +960,13 @@ static int processLink(GrowBuf &out,const char *data,int,int size) } else if (i<size && data[i]!=':' && !content.isEmpty()) // minimal link ref notation [some id] { - LinkRef *lr = g_linkRefs.find(content.lower()); + QCString content_lower = content.lower(); + auto lr_it = m_linkRefs.find(content_lower.str()); //printf("processLink: minimal link {%s} lr=%p",content.data(),lr); - if (lr) // found it + if (lr_it!=m_linkRefs.end()) // found it { - link = lr->link; - title = lr->title; + link = lr_it->second.link; + title = lr_it->second.title; explicitTitle=TRUE; i=contentEnd; } @@ -868,83 +987,95 @@ static int processLink(GrowBuf &out,const char *data,int,int size) } if (isToc) // special case for [TOC] { - int level = Config_getInt(TOC_INCLUDE_HEADINGS); - if (level > 0 && level <=5) + int toc_level = Config_getInt(TOC_INCLUDE_HEADINGS); + if (toc_level > 0 && toc_level <=5) { - char levStr[10]; - sprintf(levStr,"%d",level); - out.addStr("@tableofcontents{html:"); - out.addStr(levStr); - out.addStr("}"); + m_out.addStr("@tableofcontents{html:"); + m_out.addStr(QCString().setNum(toc_level)); + m_out.addStr("}"); } } - else if (isImageLink) + else if (isImageLink) { bool ambig; FileDef *fd=0; if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1 || - (fd=findFileDef(Doxygen::imageNameDict,link,ambig))) + (fd=findFileDef(Doxygen::imageNameLinkedMap,link,ambig))) // assume doxygen symbol link or local image link { - writeMarkdownImage(out, "html", explicitTitle, title, content, link, fd); - writeMarkdownImage(out, "latex", explicitTitle, title, content, link, fd); - writeMarkdownImage(out, "rtf", explicitTitle, title, content, link, fd); - writeMarkdownImage(out, "docbook", explicitTitle, title, content, link, fd); + writeMarkdownImage("html", explicitTitle, title, content, link, fd); + writeMarkdownImage("latex", explicitTitle, title, content, link, fd); + writeMarkdownImage("rtf", explicitTitle, title, content, link, fd); + writeMarkdownImage("docbook", explicitTitle, title, content, link, fd); } else { - out.addStr("<img src=\""); - out.addStr(link); - out.addStr("\" alt=\""); - out.addStr(content); - out.addStr("\""); + m_out.addStr("<img src=\""); + m_out.addStr(link); + m_out.addStr("\" alt=\""); + m_out.addStr(content); + m_out.addStr("\""); if (!title.isEmpty()) { - out.addStr(" title=\""); - out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); - out.addStr("\""); + m_out.addStr(" title=\""); + m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); + m_out.addStr("\""); } - out.addStr("/>"); + m_out.addStr("/>"); } } else { SrcLangExt lang = getLanguageFromFileName(link); int lp=-1; - if ((lp=link.find("@ref "))!=-1 || (lp=link.find("\\ref "))!=-1 || (lang==SrcLangExt_Markdown && !isURL(link))) + if ((lp=link.find("@ref "))!=-1 || (lp=link.find("\\ref "))!=-1 || (lang==SrcLangExt_Markdown && !isURL(link))) // assume doxygen symbol link { if (lp==-1) // link to markdown page { - out.addStr("@ref "); + m_out.addStr("@ref "); + if (!(Portable::isAbsolutePath(link) || isURL(link))) + { + QFileInfo forg(link); + if (!(forg.exists() && forg.isReadable())) + { + QFileInfo fi(m_fileName); + QCString mdFile = m_fileName.left(m_fileName.length()-fi.fileName().length()) + link; + QFileInfo fmd(mdFile); + if (fmd.exists() && fmd.isReadable()) + { + link = fmd.absFilePath().data(); + } + } + } } - out.addStr(link); - out.addStr(" \""); + m_out.addStr(link); + m_out.addStr(" \""); if (explicitTitle && !title.isEmpty()) { - out.addStr(title); + m_out.addStr(title); } else { - out.addStr(content); + m_out.addStr(content); } - out.addStr("\""); + m_out.addStr("\""); } - else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1) + else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1) { // file/url link - out.addStr("<a href=\""); - out.addStr(link); - out.addStr("\""); + m_out.addStr("<a href=\""); + m_out.addStr(link); + m_out.addStr("\""); if (!title.isEmpty()) { - out.addStr(" title=\""); - out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); - out.addStr("\""); + m_out.addStr(" title=\""); + m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); + m_out.addStr("\""); } - out.addStr(">"); + m_out.addStr(">"); content = content.simplifyWhiteSpace(); - processInline(out,content,content.length()); - out.addStr("</a>"); + processInline(content,content.length()); + m_out.addStr("</a>"); } else // avoid link to e.g. F[x](y) { @@ -956,8 +1087,9 @@ static int processLink(GrowBuf &out,const char *data,int,int size) } /** '`' parsing a code span (assuming codespan != 0) */ -static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int size) +int Markdown::processCodeSpan(const char *data, int /*offset*/, int size) { + TRACE(data); int end, nb = 0, i, f_begin, f_end; /* counting the number of backticks in the delimiter */ @@ -971,9 +1103,9 @@ static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int s int nl=0; for (end=nb; end<size && i<nb && nl<2; end++) { - if (data[end]=='`') + if (data[end]=='`') { - i++; + i++; } else if (data[end]=='\n') { @@ -984,14 +1116,14 @@ static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int s { // look for quoted strings like 'some word', but skip strings like `it's cool` QCString textFragment; convertStringFragment(textFragment,data+nb,end-nb); - out.addStr("‘"); - out.addStr(textFragment); - out.addStr("’"); + m_out.addStr("‘"); + m_out.addStr(textFragment); + m_out.addStr("’"); return end+1; } else { - i=0; + i=0; } } if (i < nb && end >= size) @@ -1022,32 +1154,35 @@ static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int s { QCString codeFragment; convertStringFragment(codeFragment,data+f_begin,f_end-f_begin); - out.addStr("<tt>"); - //out.addStr(convertToHtml(codeFragment,TRUE)); - out.addStr(escapeSpecialChars(codeFragment)); - out.addStr("</tt>"); + m_out.addStr("<tt>"); + //m_out.addStr(convertToHtml(codeFragment,TRUE)); + m_out.addStr(escapeSpecialChars(codeFragment)); + m_out.addStr("</tt>"); } return end; } -static void addStrEscapeUtf8Nbsp(GrowBuf &out,const char *s,int len) +void Markdown::addStrEscapeUtf8Nbsp(const char *s,int len) { + TRACE(s); if (Portable::strnstr(s,g_doxy_nsbp,len)==0) // no escape needed -> fast { - out.addStr(s,len); + m_out.addStr(s,len); } else // escape needed -> slow { - out.addStr(substitute(QCString(s).left(len),g_doxy_nsbp,g_utf8_nbsp)); + m_out.addStr(substitute(QCString(s).left(len),g_doxy_nsbp,(const char *)g_utf8_nbsp)); } } -static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int size) +int Markdown::processSpecialCommand(const char *data, int offset, int size) { + TRACE(data); int i=1; QCString endBlockName = isBlockCommand(data,offset,size); if (!endBlockName.isEmpty()) { + TRACE_MORE("endBlockName=%s\n",qPrint(endBlockName)); int l = endBlockName.length(); while (i<size-l) { @@ -1057,7 +1192,8 @@ static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int if (qstrncmp(&data[i+1],endBlockName,l)==0) { //printf("found end at %d\n",i); - addStrEscapeUtf8Nbsp(out,data,i+1+l); + addStrEscapeUtf8Nbsp(data,i+1+l); + TRACE_MORE("result=%d\n",i+1+l); return i+1+l; } } @@ -1069,34 +1205,39 @@ static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int char c=data[1]; if (c=='[' || c==']' || c=='*' || c=='!' || c=='(' || c==')' || c=='`' || c=='_') { - out.addChar(data[1]); + m_out.addChar(data[1]); + TRACE_MORE("result=2\n"); return 2; } else if (c=='-' && size>3 && data[2]=='-' && data[3]=='-') // \--- { - out.addStr(&data[1],3); + m_out.addStr(&data[1],3); + TRACE_MORE("result=4\n"); return 4; } else if (c=='-' && size>2 && data[2]=='-') // \-- { - out.addStr(&data[1],2); + m_out.addStr(&data[1],2); + TRACE_MORE("result=3\n"); return 3; } } + TRACE_MORE("result=0\n"); return 0; } -static void processInline(GrowBuf &out,const char *data,int size) +void Markdown::processInline(const char *data,int size) { + TRACE(data); int i=0, end=0; - action_t action = 0; + Action_t action; while (i<size) { - while (end<size && ((action=g_actions[(uchar)data[end]])==0)) end++; - out.addStr(data+i,end-i); + while (end<size && ((action=m_actions[(uchar)data[end]])==0)) end++; + m_out.addStr(data+i,end-i); if (end>=size) break; i=end; - end = action(out,data+i,i,size-i); + end = action(data+i,i,size-i); if (end<=0) { end=i+1-end; @@ -1110,8 +1251,9 @@ static void processInline(GrowBuf &out,const char *data,int size) } /** returns whether the line is a setext-style hdr underline */ -static int isHeaderline(const char *data, int size, bool allowAdjustLevel) +int Markdown::isHeaderline(const char *data, int size, bool allowAdjustLevel) { + TRACE(data); int i=0, c=0; while (i<size && data[i]==' ') i++; @@ -1121,44 +1263,45 @@ static int isHeaderline(const char *data, int size, bool allowAdjustLevel) while (i<size && data[i]=='=') i++,c++; while (i<size && data[i]==' ') i++; int level = (c>1 && (i>=size || data[i]=='\n')) ? 1 : 0; - if (allowAdjustLevel && level==1 && g_indentLevel==-1) + if (allowAdjustLevel && level==1 && m_indentLevel==-1) { // In case a page starts with a header line we use it as title, promoting it to @page. - // We set g_indentLevel to -1 to promoting the other sections if they have a deeper + // We set g_indentLevel to -1 to promoting the other sections if they have a deeper // nesting level than the page header, i.e. @section..@subsection becomes @page..@section. - // In case a section at the same level is found (@section..@section) however we need + // In case a section at the same level is found (@section..@section) however we need // to undo this (and the result will be @page..@section). - g_indentLevel=0; + m_indentLevel=0; } - return g_indentLevel+level; + return m_indentLevel+level; } // test of level 2 header if (data[i]=='-') { while (i<size && data[i]=='-') i++,c++; while (i<size && data[i]==' ') i++; - return (c>1 && (i>=size || data[i]=='\n')) ? g_indentLevel+2 : 0; + return (c>1 && (i>=size || data[i]=='\n')) ? m_indentLevel+2 : 0; } return 0; } /** returns TRUE if this line starts a block quote */ -static bool isBlockQuote(const char *data,int size,int indent) +bool isBlockQuote(const char *data,int size,int indent) { + TRACE(data); int i = 0; while (i<size && data[i]==' ') i++; if (i<indent+codeBlockIndent) // could be a quotation { // count >'s and skip spaces int level=0; - while (i<size && (data[i]=='>' || data[i]==' ')) + while (i<size && (data[i]=='>' || data[i]==' ')) { if (data[i]=='>') level++; i++; } - // last characters should be a space or newline, + // last characters should be a space or newline, // so a line starting with >= does not match - return level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n'); + return level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n'); } else // too much indentation -> code block { @@ -1171,6 +1314,7 @@ static bool isBlockQuote(const char *data,int size,int indent) static int isLinkRef(const char *data,int size, QCString &refid,QCString &link,QCString &title) { + TRACE(data); //printf("isLinkRef data={%s}\n",data); // format: start with [some text]: int i = 0; @@ -1224,7 +1368,7 @@ static int isLinkRef(const char *data,int size, i++; while (i<size && data[i]==' ') i++; } - if (i>=size) + if (i>=size) { //printf("end of isLinkRef while looking for title! i=%d\n",i); return i; // end of buffer while looking for the optional title @@ -1260,12 +1404,13 @@ static int isLinkRef(const char *data,int size, static int isHRuler(const char *data,int size) { + TRACE(data); int i=0; if (size>0 && data[size-1]=='\n') size--; // ignore newline character while (i<size && data[i]==' ') i++; if (i>=size) return 0; // empty line char c=data[i]; - if (c!='*' && c!='-' && c!='_') + if (c!='*' && c!='-' && c!='_') { return 0; // not a hrule character } @@ -1287,6 +1432,7 @@ static int isHRuler(const char *data,int size) static QCString extractTitleId(QCString &title, int level) { + TRACE(title.data()); //static QRegExp r1("^[a-z_A-Z][a-z_A-Z0-9\\-]*:"); static QRegExp r2("\\{#[a-z_A-Z][a-z_A-Z0-9\\-]*\\}"); int l=0; @@ -1300,7 +1446,7 @@ static QCString extractTitleId(QCString &title, int level) } if ((level > 0) && (level <= Config_getInt(TOC_INCLUDE_HEADINGS))) { - static int autoId = 0; + static AtomicInt autoId { 0 }; QCString id; id.sprintf("autotoc_md%d",autoId++); //printf("auto-generated id='%s' title='%s'\n",id.data(),title.data()); @@ -1311,21 +1457,22 @@ static QCString extractTitleId(QCString &title, int level) } -static int isAtxHeader(const char *data,int size, +int Markdown::isAtxHeader(const char *data,int size, QCString &header,QCString &id,bool allowAdjustLevel) { + TRACE(data); int i = 0, end; int level = 0, blanks=0; // find start of header text and determine heading level while (i<size && data[i]==' ') i++; - if (i>=size || data[i]!='#') + if (i>=size || data[i]!='#') { return 0; } while (i<size && level<6 && data[i]=='#') i++,level++; while (i<size && data[i]==' ') i++,blanks++; - if (level==1 && blanks==0) + if (level==1 && blanks==0) { return 0; // special case to prevent #someid seen as a header (see bug 671395) } @@ -1345,7 +1492,7 @@ static int isAtxHeader(const char *data,int size, header=header.left(i+1); } - if (allowAdjustLevel && level==1 && g_indentLevel==-1) + if (allowAdjustLevel && level==1 && m_indentLevel==-1) { // in case we find a `# Section` on a markdown page that started with the same level // header, we no longer need to artificially decrease the paragraph level. @@ -1365,13 +1512,14 @@ static int isAtxHeader(const char *data,int size, // @section autotoc_md1 Heading 2 // ------------------- - g_indentLevel=0; + m_indentLevel=0; } - return level+g_indentLevel; + return level+m_indentLevel; } static int isEmptyLine(const char *data,int size) { + TRACE(data); int i=0; while (i<size) { @@ -1392,12 +1540,13 @@ static int isEmptyLine(const char *data,int size) // such as -, -#, *, +, 1., and <li> static int computeIndentExcludingListMarkers(const char *data,int size) { + TRACE(data); int i=0; int indent=0; bool isDigit=FALSE; bool isLi=FALSE; bool listMarkerSkipped=FALSE; - while (i<size && + while (i<size && (data[i]==' ' || // space (!listMarkerSkipped && // first list marker (data[i]=='+' || data[i]=='-' || data[i]=='*' || // unordered list char @@ -1407,7 +1556,7 @@ static int computeIndentExcludingListMarkers(const char *data,int size) ) ) ) - ) + ) { if (isDigit) // skip over ordered list marker '10. ' { @@ -1460,6 +1609,7 @@ static int computeIndentExcludingListMarkers(const char *data,int size) static bool isFencedCodeBlock(const char *data,int size,int refIndent, QCString &lang,int &start,int &end,int &offset) { + TRACE(data); // rules: at least 3 ~~~, end of the block same amount of ~~~'s, otherwise // return FALSE int i=0; @@ -1485,10 +1635,13 @@ static bool isFencedCodeBlock(const char *data,int size,int refIndent, int endTildes=0; while (i<size && data[i]==tildaChar) endTildes++,i++; while (i<size && data[i]==' ') i++; - if (i==size || data[i]=='\n') + if (i==size || data[i]=='\n') { - offset=i; - return endTildes==startTildes; + if (endTildes==startTildes) + { + offset=i; + return TRUE; + } } } i++; @@ -1498,6 +1651,7 @@ static bool isFencedCodeBlock(const char *data,int size,int refIndent, static bool isCodeBlock(const char *data,int offset,int size,int &indent) { + TRACE(data); //printf("<isCodeBlock(offset=%d,size=%d,indent=%d)\n",offset,size,indent); // determine the indent of this line int i=0; @@ -1514,7 +1668,7 @@ static bool isCodeBlock(const char *data,int offset,int size,int &indent) //printf("only spaces at the end of a comment block\n"); return FALSE; } - + i=offset; int nl=0; int nl_pos[3]; @@ -1544,7 +1698,7 @@ static bool isCodeBlock(const char *data,int offset,int size,int &indent) // determine the indent of line -2 indent=computeIndentExcludingListMarkers(data+nl_pos[2],nl_pos[1]-nl_pos[2]); - + //printf(">isCodeBlock local_indent %d>=%d+4=%d\n", // indent0,indent2,indent0>=indent2+4); // if the difference is >4 spaces -> code block @@ -1574,6 +1728,7 @@ static bool isCodeBlock(const char *data,int offset,int size,int &indent) */ int findTableColumns(const char *data,int size,int &start,int &end,int &columns) { + TRACE(data); int i=0,n=0; int eol; // find start character of the table line @@ -1582,8 +1737,12 @@ int findTableColumns(const char *data,int size,int &start,int &end,int &columns) start = i; // find end character of the table line - while (i<size && data[i]!='\n') i++; - eol=i+1; + //while (i<size && data[i]!='\n') i++; + //eol=i+1; + int j = 0; + while (i<size && (j = isNewline(data + i))==0) i++; + eol=i+j; + i--; while (i>0 && data[i]==' ') i--; if (i>0 && data[i-1]!='\\' && data[i]=='|') i--,n++; // trailing or escaped | does not count @@ -1613,11 +1772,12 @@ int findTableColumns(const char *data,int size,int &start,int &end,int &columns) /** Returns TRUE iff data points to the start of a table block */ static bool isTableBlock(const char *data,int size) { + TRACE(data); int cc0,start,end; // the first line should have at least two columns separated by '|' int i = findTableColumns(data,size,start,end,cc0); - if (i>=size || cc0<1) + if (i>=size || cc0<1) { //printf("isTableBlock: no |'s in the header\n"); return FALSE; @@ -1649,8 +1809,9 @@ static bool isTableBlock(const char *data,int size) return cc1==cc2; } -static int writeTableBlock(GrowBuf &out,const char *data,int size) +int Markdown::writeTableBlock(const char *data,int size) { + TRACE(data); int i=0,j,k; int columns,start,end,cc; @@ -1659,17 +1820,10 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) int headerStart = start; int headerEnd = end; -#ifdef USE_ORIGINAL_TABLES - out.addStr("<table>"); - - // write table header, in range [start..end] - out.addStr("<tr>"); -#endif - // read cell alignments int ret = findTableColumns(data+i,size-i,start,end,cc); k=0; - Alignment *columnAlignment = new Alignment[columns]; + std::vector<int> columnAlignment(columns); bool leftMarker=FALSE,rightMarker=FALSE; bool startFound=FALSE; @@ -1679,12 +1833,12 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) if (!startFound) { if (data[j]==':') { leftMarker=TRUE; startFound=TRUE; } - if (data[j]=='-') startFound=TRUE; + if (data[j]=='-') startFound=TRUE; //printf(" data[%d]=%c startFound=%d\n",j,data[j],startFound); } if (data[j]=='-') rightMarker=FALSE; else if (data[j]==':') rightMarker=TRUE; - if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) + if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) { if (k<columns) { @@ -1706,142 +1860,62 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) // proceed to next line i+=ret; -#ifdef USE_ORIGINAL_TABLES - - int m=headerStart; - for (k=0;k<columns;k++) - { - out.addStr("<th"); - switch (columnAlignment[k]) - { - case AlignLeft: out.addStr(" align=\"left\""); break; - case AlignRight: out.addStr(" align=\"right\""); break; - case AlignCenter: out.addStr(" align=\"center\""); break; - case AlignNone: break; - } - out.addStr(">"); - while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\'))) - { - out.addChar(data[m++]); - } - m++; - } - out.addStr("\n</th>\n"); - - // write table cells - while (i<size) - { - int ret = findTableColumns(data+i,size-i,start,end,cc); - //printf("findTableColumns cc=%d\n",cc); - if (cc!=columns) break; // end of table - - out.addStr("<tr>"); - j=start+i; - int columnStart=j; - k=0; - while (j<=end+i) - { - if (j==columnStart) - { - out.addStr("<td"); - switch (columnAlignment[k]) - { - case AlignLeft: out.addStr(" align=\"left\""); break; - case AlignRight: out.addStr(" align=\"right\""); break; - case AlignCenter: out.addStr(" align=\"center\""); break; - case AlignNone: break; - } - out.addStr(">"); - } - if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) - { - columnStart=j+1; - k++; - } - else - { - out.addChar(data[j]); - } - j++; - } - out.addChar('\n'); - - // proceed to next line - i+=ret; - } - - out.addStr("</table> "); -#else // Store the table cell information by row then column. This // allows us to handle row spanning. - QVector<QVector<TableCell> > tableContents; - tableContents.setAutoDelete(TRUE); + std::vector<std::vector<TableCell> > tableContents; int m=headerStart; - QVector<TableCell> *headerContents = new QVector<TableCell>(columns); - headerContents->setAutoDelete(TRUE); + std::vector<TableCell> headerContents(columns); for (k=0;k<columns;k++) { - headerContents->insert(k, new TableCell); while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\'))) { - headerContents->at(k)->cellText += data[m++]; + headerContents[k].cellText += data[m++]; } m++; // do the column span test before stripping white space // || is spanning columns, | | is not - headerContents->at(k)->colSpan = headerContents->at(k)->cellText.isEmpty(); - headerContents->at(k)->cellText = headerContents->at(k)->cellText.stripWhiteSpace(); + headerContents[k].colSpan = headerContents[k].cellText.isEmpty(); + headerContents[k].cellText = headerContents[k].cellText.stripWhiteSpace(); } - // qvector doesn't have an append like std::vector, so we gotta do - // extra work - tableContents.resize(1); - tableContents.insert(0, headerContents); + tableContents.push_back(headerContents); // write table cells - int rowNum = 1; while (i<size) { - int ret = findTableColumns(data+i,size-i,start,end,cc); + ret = findTableColumns(data+i,size-i,start,end,cc); if (cc!=columns) break; // end of table j=start+i; k=0; - QVector<TableCell> *rowContents = new QVector<TableCell>(columns); - rowContents->setAutoDelete(TRUE); - rowContents->insert(k, new TableCell); + std::vector<TableCell> rowContents(columns); while (j<=end+i) { - if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) + if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) { // do the column span test before stripping white space // || is spanning columns, | | is not - rowContents->at(k)->colSpan = rowContents->at(k)->cellText.isEmpty(); - rowContents->at(k)->cellText = rowContents->at(k)->cellText.stripWhiteSpace(); + rowContents[k].colSpan = rowContents[k].cellText.isEmpty(); + rowContents[k].cellText = rowContents[k].cellText.stripWhiteSpace(); k++; - rowContents->insert(k, new TableCell); - } // if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) + } // if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) else { - rowContents->at(k)->cellText += data[j]; + rowContents[k].cellText += data[j]; } // else { if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) } j++; } // while (j<=end+i) // do the column span test before stripping white space // || is spanning columns, | | is not - rowContents->at(k)->colSpan = rowContents->at(k)->cellText.isEmpty(); - rowContents->at(k)->cellText = rowContents->at(k)->cellText.stripWhiteSpace(); - // qvector doesn't have an append like std::vector, so we gotta do - // extra work - tableContents.resize(tableContents.size()+1); - tableContents.insert(rowNum++, rowContents); + rowContents[k].colSpan = rowContents[k].cellText.isEmpty(); + rowContents[k].cellText = rowContents[k].cellText.stripWhiteSpace(); + tableContents.push_back(rowContents); // proceed to next line i+=ret; } - - out.addStr("<table class=\"markdownTable\">"); + m_out.addStr("<table class=\"markdownTable\">"); QCString cellTag("th"), cellClass("class=\"markdownTableHead"); for (unsigned row = 0; row < tableContents.size(); row++) { @@ -1849,58 +1923,57 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) { if (row % 2) { - out.addStr("<tr class=\"markdownTableRowOdd\">"); + m_out.addStr("<tr class=\"markdownTableRowOdd\">"); } else { - out.addStr("<tr class=\"markdownTableRowEven\">"); + m_out.addStr("<tr class=\"markdownTableRowEven\">"); } } else { - out.addStr(" <tr class=\"markdownTableHead\">"); + m_out.addStr(" <tr class=\"markdownTableHead\">"); } for (int c = 0; c < columns; c++) { // save the cell text for use after column span computation - QCString cellText(tableContents[row]->at(c)->cellText); + QCString cellText(tableContents[row][c].cellText); // Row span handling. Spanning rows will contain a caret ('^'). // If the current cell contains just a caret, this is part of an // earlier row's span and the cell should not be added to the // output. - if (tableContents[row]->at(c)->cellText == "^") + if (tableContents[row][c].cellText == "^") continue; unsigned rowSpan = 1, spanRow = row+1; while ((spanRow < tableContents.size()) && - (tableContents[spanRow]->at(c)->cellText == "^")) + (tableContents[spanRow][c].cellText == "^")) { spanRow++; rowSpan++; } - out.addStr(" <" + cellTag + " " + cellClass); + m_out.addStr(" <" + cellTag + " " + cellClass); // use appropriate alignment style switch (columnAlignment[c]) { - case AlignLeft: out.addStr("Left\""); break; - case AlignRight: out.addStr("Right\""); break; - case AlignCenter: out.addStr("Center\""); break; - case AlignNone: out.addStr("None\""); break; + case AlignLeft: m_out.addStr("Left\""); break; + case AlignRight: m_out.addStr("Right\""); break; + case AlignCenter: m_out.addStr("Center\""); break; + case AlignNone: m_out.addStr("None\""); break; } if (rowSpan > 1) { QCString spanStr; spanStr.setNum(rowSpan); - out.addStr(" rowspan=\"" + spanStr + "\""); + m_out.addStr(" rowspan=\"" + spanStr + "\""); } // Column span handling, assumes that column spans will have // empty strings, which would indicate the sequence "||", used // to signify spanning columns. unsigned colSpan = 1; - while ((c < columns-1) && - tableContents[row]->at(c+1)->colSpan) + while ((c < columns-1) && tableContents[row][c+1].colSpan) { c++; colSpan++; @@ -1909,26 +1982,25 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size) { QCString spanStr; spanStr.setNum(colSpan); - out.addStr(" colspan=\"" + spanStr + "\""); + m_out.addStr(" colspan=\"" + spanStr + "\""); } // need at least one space on either side of the cell text in // order for doxygen to do other formatting - out.addStr("> " + cellText + "</" + cellTag + ">"); + m_out.addStr("> " + cellText + "\\ilinebr </" + cellTag + ">"); } cellTag = "td"; cellClass = "class=\"markdownTableBody"; - out.addStr(" </tr>\n"); + m_out.addStr(" </tr>\n"); } - out.addStr("</table>\n"); -#endif + m_out.addStr("</table>\n"); - delete[] columnAlignment; return i; } static int hasLineBreak(const char *data,int size) { + TRACE(data); int i=0; int j=0; // search for end of line and also check if it is not a completely blank @@ -1943,65 +2015,62 @@ static int hasLineBreak(const char *data,int size) } -void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size) +void Markdown::writeOneLineHeaderOrRuler(const char *data,int size) { + TRACE(data); int level; QCString header; QCString id; if (isHRuler(data,size)) { - out.addStr("\n<hr>\n"); + m_out.addStr("\n<hr>\n"); } else if ((level=isAtxHeader(data,size,header,id,TRUE))) { QCString hTag; if (level<5 && !id.isEmpty()) { - SectionInfo::SectionType type = SectionInfo::Anchor; switch(level) { - case 1: out.addStr("@section "); - type=SectionInfo::Section; + case 1: m_out.addStr("@section "); break; - case 2: out.addStr("@subsection "); - type=SectionInfo::Subsection; + case 2: m_out.addStr("@subsection "); break; - case 3: out.addStr("@subsubsection "); - type=SectionInfo::Subsubsection; + case 3: m_out.addStr("@subsubsection "); break; - default: out.addStr("@paragraph "); - type=SectionInfo::Paragraph; + default: m_out.addStr("@paragraph "); break; } - out.addStr(id); - out.addStr(" "); - out.addStr(header); - out.addStr("\n"); + m_out.addStr(id); + m_out.addStr(" "); + m_out.addStr(header); + m_out.addStr("\n"); } else { if (!id.isEmpty()) { - out.addStr("\\anchor "+id+"\n"); + m_out.addStr("\\anchor "+id+"\n"); } hTag.sprintf("h%d",level); - out.addStr("<"+hTag+">"); - out.addStr(header); - out.addStr("</"+hTag+">\n"); + m_out.addStr("<"+hTag+">"); + m_out.addStr(header); + m_out.addStr("</"+hTag+">\n"); } } else // nothing interesting -> just output the line { - out.addStr(data,size); + m_out.addStr(data,size); if (hasLineBreak(data,size)) { - out.addStr("<br>\n"); + m_out.addStr("<br>\n"); } } } -static int writeBlockQuote(GrowBuf &out,const char *data,int size) +int Markdown::writeBlockQuote(const char *data,int size) { + TRACE(data); int l; int i=0; int curLevel=0; @@ -2021,7 +2090,7 @@ static int writeBlockQuote(GrowBuf &out,const char *data,int size) else if (j>0 && data[j-1]=='>') indent=j+1; j++; } - if (j>0 && data[j-1]=='>' && + if (j>0 && data[j-1]=='>' && !(j==size || data[j]=='\n')) // disqualify last > if not followed by space { indent--; @@ -2031,36 +2100,37 @@ static int writeBlockQuote(GrowBuf &out,const char *data,int size) { for (l=curLevel;l<level;l++) { - out.addStr("<blockquote>\n"); + m_out.addStr("<blockquote>\n"); } } else if (level<curLevel) // quote level decreased => add end markers { for (l=level;l<curLevel;l++) { - out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>\n"); } } curLevel=level; if (level==0) break; // end of quote block // copy line without quotation marks - out.addStr(data+indent,end-indent); + m_out.addStr(data+indent,end-indent); // proceed with next line i=end; } // end of comment within blockquote => add end markers for (l=0;l<curLevel;l++) { - out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>\n"); } return i; } -static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) +int Markdown::writeCodeBlock(const char *data,int size,int refIndent) { + TRACE(data); int i=0,end; //printf("writeCodeBlock: data={%s}\n",QCString(data).left(size).data()); - out.addStr("@verbatim\n"); + m_out.addStr("@verbatim\n"); int emptyLines=0; while (i<size) { @@ -2072,7 +2142,7 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) while (j<end && data[j]==' ') j++,indent++; //printf("j=%d end=%d indent=%d refIndent=%d tabSize=%d data={%s}\n", // j,end,indent,refIndent,Config_getInt(TAB_SIZE),QCString(data+i).left(end-i-1).data()); - if (j==end-1) // empty line + if (j==end-1) // empty line { emptyLines++; i=end; @@ -2082,11 +2152,11 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) while (emptyLines>0) // write skipped empty lines { // add empty line - out.addStr("\n"); + m_out.addStr("\n"); emptyLines--; } // add code line minus the indent - out.addStr(data+i+refIndent+codeBlockIndent,end-i-refIndent-codeBlockIndent); + m_out.addStr(data+i+refIndent+codeBlockIndent,end-i-refIndent-codeBlockIndent); i=end; } else // end of code block @@ -2094,11 +2164,11 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) break; } } - out.addStr("@endverbatim\n"); + m_out.addStr("@endverbatim\n"); while (emptyLines>0) // write skipped empty lines { // add empty line - out.addStr("\n"); + m_out.addStr("\n"); emptyLines--; } //printf("i=%d\n",i); @@ -2107,13 +2177,16 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) // start searching for the end of the line start at offset \a i // keeping track of possible blocks that need to be skipped. -static void findEndOfLine(GrowBuf &out,const char *data,int size, +void Markdown::findEndOfLine(const char *data,int size, int &pi,int&i,int &end) { + TRACE(data); // find end of the line int nb=0; end=i+1; - while (end<=size && data[end-1]!='\n') + //while (end<=size && data[end-1]!='\n') + int j=0; + while (end<=size && (j=isNewline(data+end-1))==0) { // while looking for the end of the line we might encounter a block // that needs to be passed unprocessed. @@ -2135,7 +2208,7 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size, if (qstrncmp(&data[end+1],endBlockName,l)==0) { // found end marker, skip over this block - //printf("feol.block out={%s}\n",QCString(data+i).left(end+l+1-i).data()); + //printf("feol.block m_out={%s}\n",QCString(data+i).left(end+l+1-i).data()); end = end + l + 2; break; } @@ -2151,7 +2224,7 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size, tolower(data[end+2])=='e' && data[end+3]=='>') // <pre> tag { // skip part until including </pre> - end = end + processHtmlTagWrite(out,data+end-1,end-1,size-end+1,false) + 2; + end = end + processHtmlTagWrite(data+end-1,end-1,size-end+1,false) + 2; break; } else @@ -2159,7 +2232,7 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size, end++; } } - else if (nb==0 && data[end-1]=='`') + else if (nb==0 && data[end-1]=='`') { while (end<=size && data[end-1]=='`') end++,nb++; } @@ -2174,27 +2247,30 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size, end++; } } + if (j>0) end+=j-1; //printf("findEndOfLine pi=%d i=%d end=%d {%s}\n",pi,i,end,QCString(data+i).left(end-i).data()); } -static void writeFencedCodeBlock(GrowBuf &out,const char *data,const char *lng, +void Markdown::writeFencedCodeBlock(const char *data,const char *lng, int blockStart,int blockEnd) { + TRACE(data); QCString lang = lng; if (!lang.isEmpty() && lang.at(0)=='.') lang=lang.mid(1); - out.addStr("@code"); + m_out.addStr("@code"); if (!lang.isEmpty()) { - out.addStr("{"+lang+"}"); + m_out.addStr("{"+lang+"}"); } - addStrEscapeUtf8Nbsp(out,data+blockStart,blockEnd-blockStart); - out.addStr("\n"); - out.addStr("@endcode\n"); + addStrEscapeUtf8Nbsp(data+blockStart,blockEnd-blockStart); + m_out.addStr("\n"); + m_out.addStr("@endcode\n"); } -static QCString processQuotations(const QCString &s,int refIndent) +QCString Markdown::processQuotations(const QCString &s,int refIndent) { - GrowBuf out; + TRACE(s.data()); + m_out.clear(); const char *data = s.data(); int size = s.length(); int i=0,end=0,pi=-1; @@ -2202,14 +2278,14 @@ static QCString processQuotations(const QCString &s,int refIndent) QCString lang; while (i<size) { - findEndOfLine(out,data,size,pi,i,end); + findEndOfLine(data,size,pi,i,end); // line is now found at [i..end) if (pi!=-1) { if (isFencedCodeBlock(data+pi,size-pi,refIndent,lang,blockStart,blockEnd,blockOffset)) { - writeFencedCodeBlock(out,data+pi,lang,blockStart,blockEnd); + writeFencedCodeBlock(data+pi,lang,blockStart,blockEnd); i=pi+blockOffset; pi=-1; end=i+1; @@ -2217,15 +2293,15 @@ static QCString processQuotations(const QCString &s,int refIndent) } else if (isBlockQuote(data+pi,i-pi,refIndent)) { - i = pi+writeBlockQuote(out,data+pi,size-pi); + i = pi+writeBlockQuote(data+pi,size-pi); pi=-1; end=i+1; continue; } else { - //printf("quote out={%s}\n",QCString(data+pi).left(i-pi).data()); - out.addStr(data+pi,i-pi); + //printf("quote m_out={%s}\n",QCString(data+pi).left(i-pi).data()); + m_out.addStr(data+pi,i-pi); } } pi=i; @@ -2235,24 +2311,25 @@ static QCString processQuotations(const QCString &s,int refIndent) { if (isBlockQuote(data+pi,size-pi,refIndent)) { - writeBlockQuote(out,data+pi,size-pi); + writeBlockQuote(data+pi,size-pi); } else { - out.addStr(data+pi,size-pi); + m_out.addStr(data+pi,size-pi); } } - out.addChar(0); + m_out.addChar(0); //printf("Process quotations\n---- input ----\n%s\n---- output ----\n%s\n------------\n", - // s.data(),out.get()); + // s.data(),m_out.get()); - return out.get(); + return m_out.get(); } -static QCString processBlocks(const QCString &s,int indent) +QCString Markdown::processBlocks(const QCString &s,int indent) { - GrowBuf out; + TRACE(s.data()); + m_out.clear(); const char *data = s.data(); int size = s.length(); int i=0,end=0,pi=-1,ref,level; @@ -2262,20 +2339,20 @@ static QCString processBlocks(const QCString &s,int indent) // get indent for the first line end = i+1; int sp=0; - while (end<=size && data[end-1]!='\n') + while (end<=size && data[end-1]!='\n') { if (data[end-1]==' ') sp++; end++; } -#if 0 // commented out, since starting with a comment block is probably a usage error +#if 0 // commented m_out, since starting with a comment block is probably a usage error // see also http://stackoverflow.com/q/20478611/784672 // special case when the documentation starts with a code block // since the first line is skipped when looking for a code block later on. if (end>codeBlockIndent && isCodeBlock(data,0,end,blockIndent)) { - i=writeCodeBlock(out,data,size,blockIndent); + i=writeCodeBlock(m_out,data,size,blockIndent); end=i+1; pi=-1; } @@ -2284,7 +2361,7 @@ static QCString processBlocks(const QCString &s,int indent) // process each line while (i<size) { - findEndOfLine(out,data,size,pi,i,end); + findEndOfLine(data,size,pi,i,end); // line is now found at [i..end) //printf("findEndOfLine: pi=%d i=%d end=%d\n",pi,i,end); @@ -2299,7 +2376,7 @@ static QCString processBlocks(const QCString &s,int indent) { //printf("Found header at %d-%d\n",i,end); while (pi<size && data[pi]==' ') pi++; - QCString header,id; + QCString header; convertStringFragment(header,data+pi,i-pi-1); id = extractTitleId(header, level); //printf("header='%s' is='%s'\n",header.data(),id.data()); @@ -2307,22 +2384,22 @@ static QCString processBlocks(const QCString &s,int indent) { if (!id.isEmpty()) { - out.addStr(level==1?"@section ":"@subsection "); - out.addStr(id); - out.addStr(" "); - out.addStr(header); - out.addStr("\n\n"); + m_out.addStr(level==1?"@section ":"@subsection "); + m_out.addStr(id); + m_out.addStr(" "); + m_out.addStr(header); + m_out.addStr("\n\n"); } else { - out.addStr(level==1?"<h1>":"<h2>"); - out.addStr(header); - out.addStr(level==1?"\n</h1>\n":"\n</h2>\n"); + m_out.addStr(level==1?"<h1>":"<h2>"); + m_out.addStr(header); + m_out.addStr(level==1?"\n</h1>\n":"\n</h2>\n"); } } else { - out.addStr("\n<hr>\n"); + m_out.addStr("\n<hr>\n"); } pi=-1; i=end; @@ -2333,7 +2410,7 @@ static QCString processBlocks(const QCString &s,int indent) { //printf("found link ref: id='%s' link='%s' title='%s'\n", // id.data(),link.data(),title.data()); - g_linkRefs.insert(id.lower(),new LinkRef(link,title)); + m_linkRefs.insert({id.lower().str(),LinkRef(link,title)}); i=ref+pi; pi=-1; end=i+1; @@ -2342,7 +2419,7 @@ static QCString processBlocks(const QCString &s,int indent) { //printf("Found FencedCodeBlock lang='%s' start=%d end=%d code={%s}\n", // lang.data(),blockStart,blockEnd,QCString(data+pi+blockStart).left(blockEnd-blockStart).data()); - writeFencedCodeBlock(out,data+pi,lang,blockStart,blockEnd); + writeFencedCodeBlock(data+pi,lang,blockStart,blockEnd); i=pi+blockOffset; pi=-1; end=i+1; @@ -2351,21 +2428,21 @@ static QCString processBlocks(const QCString &s,int indent) else if (isCodeBlock(data+i,i,end-i,blockIndent)) { // skip previous line (it is empty anyway) - i+=writeCodeBlock(out,data+i,size-i,blockIndent); + i+=writeCodeBlock(data+i,size-i,blockIndent); pi=-1; end=i+1; continue; } else if (isTableBlock(data+pi,size-pi)) { - i=pi+writeTableBlock(out,data+pi,size-pi); + i=pi+writeTableBlock(data+pi,size-pi); pi=-1; end=i+1; continue; } else { - writeOneLineHeaderOrRuler(out,data+pi,i-pi); + writeOneLineHeaderOrRuler(data+pi,i-pi); } } pi=i; @@ -2378,21 +2455,22 @@ static QCString processBlocks(const QCString &s,int indent) { //printf("found link ref: id='%s' link='%s' title='%s'\n", // id.data(),link.data(),title.data()); - g_linkRefs.insert(id.lower(),new LinkRef(link,title)); + m_linkRefs.insert({id.lower().str(),LinkRef(link,title)}); } else { - writeOneLineHeaderOrRuler(out,data+pi,size-pi); + writeOneLineHeaderOrRuler(data+pi,size-pi); } } - out.addChar(0); - return out.get(); + m_out.addChar(0); + return m_out.get(); } /** returns TRUE if input string docs starts with \@page or \@mainpage command */ static bool isExplicitPage(const QCString &docs) { + TRACE(docs.data()); int i=0; const char *data = docs.data(); if (data) @@ -2413,15 +2491,16 @@ static bool isExplicitPage(const QCString &docs) return FALSE; } -static QCString extractPageTitle(QCString &docs,QCString &id) +QCString Markdown::extractPageTitle(QCString &docs,QCString &id) { + TRACE(docs.data()); int ln=0; // first first non-empty line QCString title; const char *data = docs.data(); int i=0; int size=docs.size(); - while (i<size && (data[i]==' ' || data[i]=='\n')) + while (i<size && (data[i]==' ' || data[i]=='\n')) { if (data[i]=='\n') ln++; i++; @@ -2460,11 +2539,13 @@ static QCString extractPageTitle(QCString &docs,QCString &id) return title; } -static QCString detab(const QCString &s,int &refIndent) +QCString Markdown::detab(const QCString &s,int &refIndent) { - static int tabSize = Config_getInt(TAB_SIZE); + TRACE(s.data()); + int tabSize = Config_getInt(TAB_SIZE); int size = s.length(); - GrowBuf out(size); + m_out.clear(); + m_out.reserve(size); const char *data = s.data(); int i=0; int col=0; @@ -2472,7 +2553,7 @@ static QCString detab(const QCString &s,int &refIndent) int minIndent=maxIndent; while (i<size) { - char c = data[i++]; + signed char c = (signed char)data[i++]; switch(c) { case '\t': // expand tab @@ -2480,120 +2561,129 @@ static QCString detab(const QCString &s,int &refIndent) int stop = tabSize - (col%tabSize); //printf("expand at %d stop=%d\n",col,stop); col+=stop; - while (stop--) out.addChar(' '); + while (stop--) m_out.addChar(' '); } break; case '\n': // reset column counter - out.addChar(c); + m_out.addChar(c); col=0; break; case ' ': // increment column counter - out.addChar(c); + m_out.addChar(c); col++; break; default: // non-whitespace => update minIndent if (c<0 && i<size) // multibyte sequence { - // special handling of the UTF-8 nbsp character 0xc2 0xa0 - if (c == '\xc2' && data[i] == '\xa0') + // special handling of the UTF-8 nbsp character 0xC2 0xA0 + if ((uchar)c == 0xC2 && (uchar)(data[i]) == 0xA0) { - out.addStr(g_doxy_nsbp); + m_out.addStr(g_doxy_nsbp); i++; } else { - out.addChar(c); - out.addChar(data[i++]); // >= 2 bytes + m_out.addChar(c); + m_out.addChar(data[i++]); // >= 2 bytes if (((uchar)c&0xE0)==0xE0 && i<size) { - out.addChar(data[i++]); // 3 bytes + m_out.addChar(data[i++]); // 3 bytes } if (((uchar)c&0xF0)==0xF0 && i<size) { - out.addChar(data[i++]); // 4 byres + m_out.addChar(data[i++]); // 4 byres } } } else { - out.addChar(c); + m_out.addChar(c); } if (col<minIndent) minIndent=col; col++; } } if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0; - out.addChar(0); + m_out.addChar(0); //printf("detab refIndent=%d\n",refIndent); - return out.get(); + return m_out.get(); } //--------------------------------------------------------------------------- -QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,const QCString &input) +QCString Markdown::process(const QCString &input, int &startNewlines) { - static bool init=FALSE; - if (!init) - { - // setup callback table for special characters - g_actions[(unsigned int)'_']=processEmphasis; - g_actions[(unsigned int)'*']=processEmphasis; - g_actions[(unsigned int)'~']=processEmphasis; - g_actions[(unsigned int)'`']=processCodeSpan; - g_actions[(unsigned int)'\\']=processSpecialCommand; - g_actions[(unsigned int)'@']=processSpecialCommand; - g_actions[(unsigned int)'[']=processLink; - g_actions[(unsigned int)'!']=processLink; - g_actions[(unsigned int)'<']=processHtmlTag; - g_actions[(unsigned int)'-']=processNmdash; - g_actions[(unsigned int)'"']=processQuoted; - init=TRUE; - } - - g_linkRefs.setAutoDelete(TRUE); - g_linkRefs.clear(); - g_current = e; - g_fileName = fileName; - g_lineNr = lineNr; - static GrowBuf out; if (input.isEmpty()) return input; - out.clear(); int refIndent; + // for replace tabs by spaces QCString s = input; if (s.at(s.length()-1)!='\n') s += "\n"; // see PR #6766 s = detab(s,refIndent); //printf("======== DeTab =========\n---- output -----\n%s\n---------\n",s.data()); + // then process quotation blocks (as these may contain other blocks) s = processQuotations(s,refIndent); //printf("======== Quotations =========\n---- output -----\n%s\n---------\n",s.data()); + // then process block items (headers, rules, and code blocks, references) s = processBlocks(s,refIndent); //printf("======== Blocks =========\n---- output -----\n%s\n---------\n",s.data()); + // finally process the inline markup (links, emphasis and code spans) - processInline(out,s,s.length()); - out.addChar(0); - Debug::print(Debug::Markdown,0,"======== Markdown =========\n---- input ------- \n%s\n---- output -----\n%s\n=========\n",qPrint(input),qPrint(out.get())); - return substitute(out.get(),g_doxy_nsbp," "); + m_out.clear(); + processInline(s,s.length()); + m_out.addChar(0); + Debug::print(Debug::Markdown,0,"======== Markdown =========\n---- input ------- \n%s\n---- output -----\n%s\n=========\n",qPrint(input),qPrint(m_out.get())); + + // post processing + QCString result = substitute(m_out.get(),g_doxy_nsbp," "); + const char *p = result.data(); + if (p) + { + while (*p==' ') p++; // skip over spaces + while (*p=='\n') {startNewlines++;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; } //--------------------------------------------------------------------------- QCString markdownFileNameToId(const QCString &fileName) { + TRACE(fileName.data()); QCString baseFn = stripFromPath(QFileInfo(fileName).absFilePath().utf8()); int i = baseFn.findRev('.'); if (i!=-1) baseFn = baseFn.left(i); - QCString baseName = substitute(substitute(baseFn," ","_"),"/","_"); + QCString baseName = substitute(substitute(substitute(baseFn," ","_"),"/","_"),":","_"); return "md_"+baseName; } +//--------------------------------------------------------------------------- + +struct MarkdownOutlineParser::Private +{ + CommentScanner commentScanner; +}; + +MarkdownOutlineParser::MarkdownOutlineParser() : p(std::make_unique<Private>()) +{ +} + +MarkdownOutlineParser::~MarkdownOutlineParser() +{ +} -void MarkdownOutlineParser::parseInput(const char *fileName, - const char *fileBuf, +void MarkdownOutlineParser::parseInput(const char *fileName, + const char *fileBuf, const std::shared_ptr<Entry> &root, - bool /*sameTranslationUnit*/, - QStrList & /*filesInSameTranslationUnit*/) + ClangTUParser* /*clangParser*/) { std::shared_ptr<Entry> current = std::make_shared<Entry>(); current->lang = SrcLangExt_Markdown; @@ -2602,13 +2692,16 @@ void MarkdownOutlineParser::parseInput(const char *fileName, current->docLine = 1; QCString docs = fileBuf; QCString id; - QCString title=extractPageTitle(docs,id).stripWhiteSpace(); + Markdown markdown(fileName,1,0); + QCString title=markdown.extractPageTitle(docs,id).stripWhiteSpace(); if (id.startsWith("autotoc_md")) id = ""; - g_indentLevel=title.isEmpty() ? 0 : -1; + int indentLevel=title.isEmpty() ? 0 : -1; + markdown.setIndentLevel(indentLevel); QCString titleFn = QFileInfo(fileName).baseName().utf8(); QCString fn = QFileInfo(fileName).fileName().utf8(); - static QCString mdfileAsMainPage = Config_getString(USE_MDFILE_AS_MAINPAGE); - if (id.isEmpty()) id = markdownFileNameToId(fileName); + QCString mdfileAsMainPage = Config_getString(USE_MDFILE_AS_MAINPAGE); + bool wasEmpty = id.isEmpty(); + if (wasEmpty) id = markdownFileNameToId(fileName); if (!isExplicitPage(docs)) { if (!mdfileAsMainPage.isEmpty() && @@ -2617,31 +2710,29 @@ void MarkdownOutlineParser::parseInput(const char *fileName, QFileInfo(mdfileAsMainPage).absFilePath()) // file reference with path ) { + docs.prepend("@anchor " + id + "\n"); docs.prepend("@mainpage "+title+"\n"); } else if (id=="mainpage" || id=="index") { if (title.isEmpty()) title = titleFn; + docs.prepend("@anchor " + id + "\n"); docs.prepend("@mainpage "+title+"\n"); } else { if (title.isEmpty()) title = titleFn; + if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\n"); docs.prepend("@page "+id+" "+title+"\n"); } } int lineNr=1; - // even without markdown support enabled, we still - // parse markdown files as such - bool markdownEnabled = Doxygen::markdownSupport; - Doxygen::markdownSupport = TRUE; - Protection prot=Public; bool needsEntry = FALSE; int position=0; - QCString processedDocs = preprocessCommentBlock(docs,fileName,lineNr); - while (parseCommentBlock( + QCString processedDocs = markdown.process(docs,lineNr); + while (p->commentScanner.parseCommentBlock( this, current.get(), processedDocs, @@ -2652,7 +2743,8 @@ void MarkdownOutlineParser::parseInput(const char *fileName, FALSE, // inBodyDocs prot, // protection position, - needsEntry)) + needsEntry, + true)) { if (needsEntry) { @@ -2667,19 +2759,11 @@ void MarkdownOutlineParser::parseInput(const char *fileName, { root->moveToSubEntryAndKeep(current); } - - // restore setting - Doxygen::markdownSupport = markdownEnabled; - g_indentLevel=0; } void MarkdownOutlineParser::parsePrototype(const char *text) { - OutlineParserInterface &intf = Doxygen::parserManager->getOutlineParser("*.cpp"); - if (&intf!=this) - { - intf.parsePrototype(text); - } + Doxygen::parserManager->getOutlineParser("*.cpp")->parsePrototype(text); } //------------------------------------------------------------------------ diff --git a/src/markdown.h b/src/markdown.h index 3ffd155..1210967 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,28 +16,92 @@ #ifndef MARKDOWN_H #define MARKDOWN_H +#include <functional> + #include <qcstring.h> #include "parserintf.h" +#include "growbuf.h" class Entry; /** processes string \a s and converts markdown into doxygen/html commands. */ -QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,const QCString &s); +//QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,const QCString &s); QCString markdownFileNameToId(const QCString &fileName); +/// Helper class to process markdown formatted text +class Markdown +{ + public: + Markdown(const char *fileName,int lineNr,int indentLevel=0); + QCString process(const QCString &input, int &startNewlines); + QCString extractPageTitle(QCString &docs,QCString &id); + void setIndentLevel(int level) { m_indentLevel = level; } + + private: + QCString detab(const QCString &s,int &refIndent); + QCString processQuotations(const QCString &s,int refIndent); + QCString processBlocks(const QCString &s,int indent); + QCString isBlockCommand(const char *data,int offset,int size); + void findEndOfLine(const char *data,int size,int &pi,int&i,int &end); + int processHtmlTagWrite(const char *data,int offset,int size,bool doWrite); + int processHtmlTag(const char *data,int offset,int size); + int processEmphasis(const char *data,int offset,int size); + int processEmphasis1(const char *data, int size, char c); + int processEmphasis2(const char *data, int size, char c); + int processEmphasis3(const char *data, int size, char c); + int processNmdash(const char *data,int off,int size); + int processQuoted(const char *data,int,int size); + int processCodeSpan(const char *data, int /*offset*/, int size); + void addStrEscapeUtf8Nbsp(const char *s,int len); + int processSpecialCommand(const char *data, int offset, int size); + int processLink(const char *data,int,int size); + int findEmphasisChar(const char *data, int size, char c, int c_size); + void processInline(const char *data,int size); + void writeMarkdownImage(const char *fmt, bool explicitTitle, + const QCString &title, const QCString &content, + const QCString &link, const FileDef *fd); + int isHeaderline(const char *data, int size, bool allowAdjustLevel); + int isAtxHeader(const char *data,int size, + QCString &header,QCString &id,bool allowAdjustLevel); + void writeOneLineHeaderOrRuler(const char *data,int size); + void writeFencedCodeBlock(const char *data,const char *lng, + int blockStart,int blockEnd); + int writeBlockQuote(const char *data,int size); + int writeCodeBlock(const char *data,int size,int refIndent); + int writeTableBlock(const char *data,int size); + + private: + struct LinkRef + { + LinkRef(const char *l,const char *t) : link(l), title(t) {} + QCString link; + QCString title; + }; + using Action_t = std::function<int(const char *,int,int)>; + + std::unordered_map<std::string,LinkRef> m_linkRefs; + QCString m_fileName; + int m_lineNr = 0; + int m_indentLevel=0; // 0 is outside markdown, -1=page level + GrowBuf m_out; + Markdown::Action_t m_actions[256]; +}; + + class MarkdownOutlineParser : public OutlineParserInterface { public: - virtual ~MarkdownOutlineParser() {} - void startTranslationUnit(const char *) {} - void finishTranslationUnit() {} - void parseInput(const char *fileName, - const char *fileBuf, + MarkdownOutlineParser(); + virtual ~MarkdownOutlineParser(); + void parseInput(const char *fileName, + const char *fileBuf, const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList &filesInSameTranslationUnit); + ClangTUParser *clangParser); bool needsPreprocessing(const QCString &) const { return FALSE; } void parsePrototype(const char *text); + private: + struct Private; + std::unique_ptr<Private> p; }; diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 1c935ac..464dbd0 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -36,7 +36,6 @@ #include "dotcallgraph.h" #include "searchindex.h" #include "parserintf.h" -#include "objcache.h" #include "vhdldocgen.h" #include "arguments.h" @@ -76,7 +75,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual const QCString &initializer() const; virtual int initializerLines() const; virtual uint64 getMemberSpecifiers() const; - virtual const MemberList *getSectionList() const; + virtual const MemberList *getSectionList(const Definition *) const; virtual QCString displayDefinition() const; virtual const ClassDef *getClassDef() const; virtual ClassDef *getClassDef(); @@ -94,7 +93,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual int getGroupStartLine() const; virtual bool getGroupHasDocs() const; virtual QCString qualifiedName() const; - virtual QCString objCMethodName(bool localLink,bool showStatic) const; + virtual QCString objCMethodName(bool localLink,bool showStatic) const; virtual Protection protection() const; virtual Specifier virtualness(int count=0) const; virtual MemberType memberType() const; @@ -206,7 +205,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual ArgumentList &argumentList(); virtual const ArgumentList &declArgumentList() const; virtual const ArgumentList &templateArguments() const; - virtual const std::vector<ArgumentList> &definitionTemplateParameterLists() const; + virtual const ArgumentLists &definitionTemplateParameterLists() const; virtual int getMemberGroupId() const; virtual MemberGroup *getMemberGroup() const; virtual bool fromAnonymousScope() const; @@ -252,7 +251,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setBitfields(const char *s); virtual void setMaxInitLines(int lines); virtual void setMemberClass(ClassDef *cd); - virtual void setSectionList(MemberList *sl); + virtual void setSectionList(const Definition *container,MemberList *sl); virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine,bool hasDocs, MemberDef *member=0); @@ -276,9 +275,9 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setPrototype(bool p,const QCString &df,int line, int column); virtual void setExplicitExternal(bool b,const QCString &df,int line,int column); virtual void setDeclFile(const QCString &df,int line,int column); - virtual void setArgumentList(const ArgumentList &al); - virtual void setDeclArgumentList(const ArgumentList &al); - virtual void setDefinitionTemplateParameterLists(const std::vector<ArgumentList> &lists); + virtual void moveArgumentList(std::unique_ptr<ArgumentList> al); + virtual void moveDeclArgumentList(std::unique_ptr<ArgumentList> al); + virtual void setDefinitionTemplateParameterLists(const ArgumentLists &lists); virtual void setTypeConstraints(const ArgumentList &al); virtual void setType(const char *t); virtual void setAccessorType(ClassDef *cd,const char *t); @@ -325,7 +324,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void warnIfUndocumentedParams() const; virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const; virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, - const ArgumentList &actualArgs) const; + const std::unique_ptr<ArgumentList> &actualArgs) const; virtual void findSectionsInDocumentation(); virtual void writeLink(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, @@ -379,7 +378,7 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { public: - MemberDefAliasImpl(const Definition *newScope,const MemberDef *md) + MemberDefAliasImpl(const Definition *newScope,const MemberDef *md) : DefinitionAliasImpl(newScope,md), m_memberGroup(0) {} virtual ~MemberDefAliasImpl() {} virtual DefType definitionType() const { return TypeMember; } @@ -419,8 +418,8 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { return getMdAlias()->initializerLines(); } virtual uint64 getMemberSpecifiers() const { return getMdAlias()->getMemberSpecifiers(); } - virtual const MemberList *getSectionList() const - { return getMdAlias()->getSectionList(); } + virtual const MemberList *getSectionList(const Definition *container) const + { return getMdAlias()->getSectionList(container); } virtual QCString displayDefinition() const { return getMdAlias()->displayDefinition(); } virtual const ClassDef *getClassDef() const @@ -667,7 +666,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { return getMdAlias()->declArgumentList(); } virtual const ArgumentList &templateArguments() const { return getMdAlias()->templateArguments(); } - virtual const std::vector<ArgumentList> &definitionTemplateParameterLists() const + virtual const ArgumentLists &definitionTemplateParameterLists() const { return getMdAlias()->definitionTemplateParameterLists(); } virtual int getMemberGroupId() const { return getMdAlias()->getMemberGroupId(); } @@ -764,7 +763,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef virtual void setBitfields(const char *s) {} virtual void setMaxInitLines(int lines) {} virtual void setMemberClass(ClassDef *cd) {} - virtual void setSectionList(MemberList *sl) {} + virtual void setSectionList(const Definition *c,MemberList *sl) {} virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine,bool hasDocs, MemberDef *member=0) {} @@ -788,9 +787,9 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef virtual void setPrototype(bool p,const QCString &df,int line, int column) {} virtual void setExplicitExternal(bool b,const QCString &df,int line,int column) {} virtual void setDeclFile(const QCString &df,int line,int column) {} - virtual void setArgumentList(const ArgumentList &al) {} - virtual void setDeclArgumentList(const ArgumentList &al) {} - virtual void setDefinitionTemplateParameterLists(const std::vector<ArgumentList> &lists) {} + virtual void moveArgumentList(std::unique_ptr<ArgumentList> al) {} + virtual void moveDeclArgumentList(std::unique_ptr<ArgumentList> al) {} + virtual void setDefinitionTemplateParameterLists(const ArgumentLists &lists) {} virtual void setTypeConstraints(const ArgumentList &al) {} virtual void setType(const char *t) {} virtual void setAccessorType(ClassDef *cd,const char *t) {} @@ -824,7 +823,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef virtual void addToSearchIndex() const {} virtual void findSectionsInDocumentation() {} virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, - const ArgumentList &actualArgs) const + const std::unique_ptr<ArgumentList> &actualArgs) const { return getMdAlias()->createTemplateInstanceMember(formalArgs,actualArgs); } virtual void incrementFlowKeyWordCount() {} @@ -944,30 +943,6 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me return FALSE; // member has no function like argument list } - // simple argument list for tcl - if (md->getLanguage()==SrcLangExt_Tcl) - { - if (defArgList.empty()) return FALSE; - ol.endMemberDocName(); - ol.startParameterList(FALSE); - ol.startParameterType(TRUE,0); - ol.endParameterType(); - ol.startParameterName(FALSE); - for (const Argument &a : defArgList) - { - if (a.defval.isEmpty()) - { - ol.docify(a.name+" "); - } - else - { - ol.docify("?"+a.name+"? "); - } - } - ol.endParameterName(TRUE,FALSE,FALSE); - return TRUE; - } - if (!md->isDefine()) ol.docify(" "); //printf("writeDefArgList(%d)\n",defArgList->count()); @@ -1173,29 +1148,29 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me { ol.docify(md->extraTypeChars()); } - if (defArgList.constSpecifier) + if (defArgList.constSpecifier()) { ol.docify(" const"); } - if (defArgList.volatileSpecifier) + if (defArgList.volatileSpecifier()) { ol.docify(" volatile"); } - if (defArgList.refQualifier==RefQualifierLValue) + if (defArgList.refQualifier()==RefQualifierLValue) { ol.docify(" &"); } - else if (defArgList.refQualifier==RefQualifierRValue) + else if (defArgList.refQualifier()==RefQualifierRValue) { ol.docify(" &&"); } - if (!defArgList.trailingReturnType.isEmpty()) + if (!defArgList.trailingReturnType().isEmpty()) { linkifyText(TextGeneratorOLImpl(ol), // out scope, // scope md->getBodyDef(), // fileScope md, // self - defArgList.trailingReturnType, // text + defArgList.trailingReturnType(), // text FALSE // autoBreak ); @@ -1349,7 +1324,7 @@ class MemberDefImpl::IMPL ArgumentList tArgList; // template argument list of function template ArgumentList typeConstraints; // type constraints for template parameters MemberDef *templateMaster; - std::vector<ArgumentList> defTmpArgLists; // lists of template argument lists + ArgumentLists defTmpArgLists; // lists of template argument lists // (for template functions in nested template classes) QCString metaData; // Slice metadata. @@ -1438,7 +1413,7 @@ MemberDefImpl::IMPL::~IMPL() delete classSectionSDict; } -void MemberDefImpl::IMPL::init(Definition *def, +void MemberDefImpl::IMPL::init(Definition *d, const char *t,const char *a,const char *e, Protection p,Specifier v,bool s,Relationship r, MemberType mt,const ArgumentList &tal, @@ -1473,7 +1448,7 @@ void MemberDefImpl::IMPL::init(Definition *def, type=removeRedundantWhiteSpace(type); args=a; args=removeRedundantWhiteSpace(args); - if (type.isEmpty()) decl=def->name()+args; else decl=type+" "+def->name()+args; + if (type.isEmpty()) decl=d->name()+args; else decl=type+" "+d->name()+args; memberGroup=0; virt=v; @@ -1503,7 +1478,7 @@ void MemberDefImpl::IMPL::init(Definition *def, // convert function declaration arguments (if any) if (!args.isEmpty()) { - stringToArgumentList(def->getLanguage(),args,declArgList,&extraTypeChars); + declArgList = *stringToArgumentList(d->getLanguage(),args,&extraTypeChars); //printf("setDeclArgList %s to %s const=%d\n",args.data(), // argListToString(declArgList).data(),declArgList->constSpecifier); } @@ -1519,7 +1494,7 @@ void MemberDefImpl::IMPL::init(Definition *def, hasDocumentedParams = FALSE; hasDocumentedReturnType = FALSE; docProvider = 0; - isDMember = def->getDefFileName().right(2).lower()==".d"; + isDMember = d->getDefFileName().right(2).lower()==".d"; } @@ -1985,7 +1960,7 @@ bool MemberDefImpl::isLinkable() const } -void MemberDefImpl::setDefinitionTemplateParameterLists(const std::vector<ArgumentList> &lists) +void MemberDefImpl::setDefinitionTemplateParameterLists(const ArgumentLists &lists) { m_impl->defTmpArgLists = lists; } @@ -2559,7 +2534,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ol.docify(" [implementation]"); ol.endTypewriter(); } - + bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); if (isProperty() && (isSettable() || isGettable() || @@ -2570,7 +2545,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ol.startTypewriter(); ol.docify(" ["); QStrList sl; - + if (isGettable()) sl.append("get"); if (isProtectedGettable()) sl.append("protected get"); if (isSettable()) sl.append("set"); @@ -2631,8 +2606,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(), - getOuterScope()?getOuterScope():d,this,briefDescription(), - TRUE,FALSE,0,TRUE,FALSE); + getOuterScope()?getOuterScope():d,this,briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { @@ -2640,7 +2615,6 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ol.writeDoc(rootNode,getOuterScope()?getOuterScope():d,this); if (detailsVisible) { - static bool separateMemberPages = Config_getBool(SEPARATE_MEMBER_PAGES); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); //ol.endEmphasis(); @@ -2759,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 ) @@ -2771,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)); @@ -2782,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"); @@ -3172,7 +3147,8 @@ void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, { ol.generateDoc(fmd->briefFile(),fmd->briefLine(), getOuterScope()?getOuterScope():container, - fmd,fmd->briefDescription(),TRUE,FALSE); + fmd,fmd->briefDescription(),TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } // FIXME:PARA //if (!fmd->briefDescription().isEmpty() && @@ -3184,7 +3160,8 @@ void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, { ol.generateDoc(fmd->docFile(),fmd->docLine(), getOuterScope()?getOuterScope():container, - fmd,fmd->documentation()+"\n",TRUE,FALSE); + fmd,fmd->documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } ol.endDescTableData(); ol.endDescTableRow(); @@ -3337,8 +3314,6 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { // if this member is in a group find the real scope name. bool hasParameterList = FALSE; - bool inFile = container->definitionType()==Definition::TypeFile; - bool hasDocs = isDetailedSectionVisible(inGroup,inFile); //printf("MemberDefImpl::writeDocumentation(): name='%s' hasDocs='%d' containerType=%d inGroup=%d sectionLinkable=%d\n", // name().data(),hasDocs,container->definitionType(),inGroup,isDetailedSectionLinkable()); @@ -3494,7 +3469,6 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, if (!Config_getBool(HIDE_SCOPE_NAMES)) { bool first=TRUE; - SrcLangExt lang = getLanguage(); if (!m_impl->defTmpArgLists.empty() && lang==SrcLangExt_Cpp) // definition has explicit template parameter declarations { @@ -3567,9 +3541,9 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { ldef=ldef.left(dp+1); } - int l=ldef.length(); + int dl=ldef.length(); //printf("start >%s<\n",ldef.data()); - int i=l-1; + i=dl-1; while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--; while (i>=0 && isspace((uchar)ldef.at(i))) i--; if (i>0) @@ -3735,7 +3709,8 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, ol.startParagraph(); ol.generateDoc(briefFile(),briefLine(), scopedContainer,this, - brief,FALSE,FALSE,0,TRUE,FALSE); + brief,FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endParagraph(); } @@ -3751,14 +3726,16 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, } else { - ol.generateDoc(docFile(),docLine(),scopedContainer,this,detailed+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),scopedContainer,this,detailed+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } if (!inbodyDocumentation().isEmpty()) { ol.generateDoc(inbodyFile(),inbodyLine(), - scopedContainer,this, - inbodyDocumentation()+"\n",TRUE,FALSE); + scopedContainer,this, + inbodyDocumentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } else if (!brief.isEmpty() && (Config_getBool(REPEAT_BRIEF) || @@ -3766,7 +3743,8 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { if (!inbodyDocumentation().isEmpty()) { - ol.generateDoc(inbodyFile(),inbodyLine(),scopedContainer,this,inbodyDocumentation()+"\n",TRUE,FALSE); + ol.generateDoc(inbodyFile(),inbodyLine(),scopedContainer,this,inbodyDocumentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } } @@ -3783,7 +3761,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { QCString docsWithoutDir = a.docs; QCString direction = extractDirection(docsWithoutDir); - paramDocs+="@param"+direction+" "+a.name+" "+a.docs; + paramDocs+="@param"+direction+" "+a.name+" "+docsWithoutDir; } } // feed the result to the documentation parser @@ -3793,7 +3771,8 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, this, // memberDef paramDocs, // docStr TRUE, // indexWords - FALSE // isExample + FALSE, // isExample + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT) ); } @@ -3987,7 +3966,8 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *conta { ol.generateDoc(briefFile(),briefLine(), getOuterScope()?getOuterScope():container,this, - brief,FALSE,FALSE,0,TRUE,FALSE); + brief,FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } /* write detailed description */ @@ -3995,7 +3975,8 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *conta { ol.generateDoc(docFile(),docLine(), getOuterScope()?getOuterScope():container,this, - detailed+"\n",FALSE,FALSE,0,FALSE,FALSE); + detailed+"\n",FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } @@ -4037,16 +4018,13 @@ void MemberDefImpl::warnIfUndocumented() const const FileDef *fd = getFileDef(); const GroupDef *gd = getGroupDef(); const Definition *d=0; - const char *t=0; + QCString t; if (cd) - t="class", d=cd; + t=cd->compoundTypeString(), d=cd; else if (nd) { d=nd; - if (d->getLanguage() == SrcLangExt_Fortran) - t="module"; - else - t="namespace"; + t=nd->compoundTypeString(); } else if (gd) t="group", d=gd; @@ -4065,7 +4043,7 @@ void MemberDefImpl::warnIfUndocumented() const ) { warn_undoc(getDefFileName(),getDefLine(),"Member %s%s (%s) of %s %s is not documented.", - qPrint(name()),qPrint(argsString()),qPrint(memberTypeName()),t,qPrint(d->name())); + qPrint(name()),qPrint(argsString()),qPrint(memberTypeName()),qPrint(t),qPrint(d->name())); } else if (!isDetailedSectionLinkable()) { @@ -4076,8 +4054,11 @@ void MemberDefImpl::warnIfUndocumented() const void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const { if (!Config_getBool(WARN_NO_PARAMDOC)) return; - QCString returnType = typeString(); + QCString returnType = typeString(); bool isPython = getLanguage()==SrcLangExt_Python; + bool isFortran = getLanguage()==SrcLangExt_Fortran; + bool isFortranSubroutine = isFortran && returnType.find("subroutine")!=-1; + bool isVoidReturn = (returnType=="void") || (returnType.right(5)==" void"); if (!m_impl->hasDocumentedParams && hasParamCommand) { @@ -4139,8 +4120,8 @@ void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturn else if ( // see if return type is documented in a function w/o return type hasReturnCommand && ( - returnType=="void" || // void return type - returnType.find("subroutine")!=-1 || // fortran subroutine + isVoidReturn || // void return type + isFortranSubroutine || // fortran subroutine isConstructor() || // a constructor isDestructor() // or destructor ) @@ -4149,12 +4130,12 @@ void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturn warn_doc_error(getDefFileName(),getDefLine(),"documented empty return type of %s", qualifiedName().data()); } - else if ( // see if return needs to documented + else if ( // see if return needs to documented m_impl->hasDocumentedReturnType || - returnType=="void" || // void return type - returnType.find("subroutine")!=-1 || // fortran subroutine - isConstructor() || // a constructor - isDestructor() // or destructor + isVoidReturn || // void return type + isFortranSubroutine || // fortran subroutine + isConstructor() || // a constructor + isDestructor() // or destructor ) { m_impl->hasDocumentedReturnType = TRUE; @@ -4166,6 +4147,7 @@ void MemberDefImpl::warnIfUndocumentedParams() const if (!Config_getBool(EXTRACT_ALL) && Config_getBool(WARN_IF_UNDOCUMENTED) && Config_getBool(WARN_NO_PARAMDOC) && + isFunction() && !isDeleted() && !isReference() && !Doxygen::suppressDocWarnings) @@ -4178,7 +4160,7 @@ void MemberDefImpl::warnIfUndocumentedParams() const qPrint(qualifiedName())); } if (!m_impl->hasDocumentedReturnType && - isFunction() && hasDocumentation() && !returnType.isEmpty()) + hasDocumentation() && !returnType.isEmpty()) { warn_doc_error(getDefFileName(),getDefLine(), "return type of member %s is not documented", @@ -4199,7 +4181,7 @@ bool MemberDefImpl::isDocumentedFriendClass() const bool MemberDefImpl::isDeleted() const { - return m_impl->defArgList.isDeleted; + return m_impl->defArgList.isDeleted(); } bool MemberDefImpl::hasDocumentation() const @@ -4334,21 +4316,25 @@ void MemberDefImpl::setNamespace(NamespaceDef *nd) } MemberDef *MemberDefImpl::createTemplateInstanceMember( - const ArgumentList &formalArgs,const ArgumentList &actualArgs) const + const ArgumentList &formalArgs,const std::unique_ptr<ArgumentList> &actualArgs) const { //printf(" Member %s %s %s\n",typeString(),name().data(),argsString()); - ArgumentList actualArgList; + std::unique_ptr<ArgumentList> actualArgList; if (!m_impl->defArgList.empty()) { - actualArgList = m_impl->defArgList; + actualArgList = std::make_unique<ArgumentList>(m_impl->defArgList); // replace formal arguments with actuals - for (Argument &arg : actualArgList) + for (Argument &arg : *actualArgList) { arg.type = substituteTemplateArgumentsInString(arg.type,formalArgs,actualArgs); } - actualArgList.trailingReturnType = - substituteTemplateArgumentsInString(actualArgList.trailingReturnType,formalArgs,actualArgs); + actualArgList->setTrailingReturnType( + substituteTemplateArgumentsInString(actualArgList->trailingReturnType(),formalArgs,actualArgs)); + } + else + { + actualArgList = std::make_unique<ArgumentList>(); } QCString methodName=name(); @@ -4363,13 +4349,13 @@ MemberDef *MemberDefImpl::createTemplateInstanceMember( methodName, substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs), m_impl->exception, m_impl->prot, - m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, + m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, ArgumentList(), ArgumentList(), "" ); - imd->setArgumentList(actualArgList); + imd->moveArgumentList(std::move(actualArgList)); imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs)); imd->setBodyDef(getBodyDef()); - imd->setBodySegment(getStartBodyLine(),getEndBodyLine()); + imd->setBodySegment(getDefLine(),getStartBodyLine(),getEndBodyLine()); //imd->setBodyMember(this); // TODO: init other member variables (if needed). @@ -4456,27 +4442,27 @@ void MemberDefImpl::addListReference(Definition *) memArgs = argsString(); } } - const std::vector<ListItemInfo> &xrefItems = xrefListItems(); + const RefItemVector &xrefItems = xrefListItems(); addRefItem(xrefItems, qualifiedName()+argsString(), // argsString is needed for overloaded functions (see bug 609624) memLabel, getOutputFileBase()+"#"+anchor(),memName,memArgs,pd); } -const MemberList *MemberDefImpl::getSectionList() const +const MemberList *MemberDefImpl::getSectionList(const Definition *container) const { - const Definition *d= resolveAlias()->getOuterScope(); + const Definition *d = container; char key[20]; - sprintf(key,"%p",d); + sprintf(key,"%p",(void*)d); return (d!=0 && m_impl->classSectionSDict) ? m_impl->classSectionSDict->find(key) : 0; } -void MemberDefImpl::setSectionList(MemberList *sl) +void MemberDefImpl::setSectionList(const Definition *container,MemberList *sl) { - //printf("MemberDefImpl::setSectionList(%p,%p) name=%s\n",d,sl,name().data()); - const Definition *d= resolveAlias()->getOuterScope(); + //printf("MemberDefImpl::setSectionList(%s,%p) name=%s\n",d->name().data(),sl,name().data()); + const Definition *d= container; char key[20]; - sprintf(key,"%p",d); + sprintf(key,"%p",(void*)d); if (m_impl->classSectionSDict==0) { m_impl->classSectionSDict = new SDict<MemberList>(7); @@ -4550,7 +4536,7 @@ void MemberDefImpl::writeTagFile(FTextStream &tagFile) const tagFile << " <type>" << convertToXML(typeString()) << "</type>" << endl; } tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; - tagFile << " <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl; + tagFile << " <anchorfile>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</anchorfile>" << endl; tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>" << endl; QCString idStr = id(); if (!idStr.isEmpty()) @@ -4571,7 +4557,7 @@ void MemberDefImpl::writeTagFile(FTextStream &tagFile) const { tagFile << " <enumvalue file=\"" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension); tagFile << "\" anchor=\"" << convertToXML(fmd->anchor()); - QCString idStr = fmd->id(); + idStr = fmd->id(); if (!idStr.isEmpty()) { tagFile << "\" clangid=\"" << convertToXML(idStr); @@ -4606,11 +4592,6 @@ void MemberDefImpl::_computeIsConstructor() m_isConstructorCached = 2; // TRUE return; } - else if (getLanguage()==SrcLangExt_Tcl) // for Tcl - { - m_isConstructorCached = name()=="constructor" ? 2 : 1; - return; - } else // for other languages { QCString locName = getClassDef()->localName(); @@ -4651,10 +4632,6 @@ void MemberDefImpl::_computeIsDestructor() { isDestructor = name()=="__destruct"; } - else if (getLanguage()==SrcLangExt_Tcl) // for Tcl - { - isDestructor = name()=="destructor"; - } else if (name()=="__del__" && getLanguage()==SrcLangExt_Python) // for Python { @@ -4804,14 +4781,14 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, } } -void MemberDefImpl::setArgumentList(const ArgumentList &al) +void MemberDefImpl::moveArgumentList(std::unique_ptr<ArgumentList> al) { - m_impl->defArgList = al; + m_impl->defArgList = *al; } -void MemberDefImpl::setDeclArgumentList(const ArgumentList &al) +void MemberDefImpl::moveDeclArgumentList(std::unique_ptr<ArgumentList> al) { - m_impl->declArgList = al; + m_impl->declArgList = *al; } void MemberDefImpl::setTypeConstraints(const ArgumentList &al) @@ -5491,7 +5468,7 @@ const ArgumentList &MemberDefImpl::templateArguments() const return m_impl->tArgList; } -const std::vector<ArgumentList> &MemberDefImpl::definitionTemplateParameterLists() const +const ArgumentLists &MemberDefImpl::definitionTemplateParameterLists() const { return m_impl->defTmpArgLists; } @@ -5942,8 +5919,8 @@ static void transferArgumentDocumentation(ArgumentList &decAl,ArgumentList &defA decIt!= decAl.end() && defIt!= defAl.end(); ++decIt, ++defIt) { - Argument decA = *decIt; - Argument defA = *defIt; + Argument &decA = *decIt; + Argument &defA = *defIt; if (decA.docs.isEmpty() && !defA.docs.isEmpty()) { decA.docs = defA.docs; @@ -5971,8 +5948,8 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) const MemberDef *cmdef = const_cast<const MemberDef*>(mdef); ArgumentList &mdefAl = mdef->argumentList(); ArgumentList &mdecAl = mdec->argumentList(); - if (matchArguments2(cmdef->getOuterScope(),cmdef->getFileDef(),mdefAl, - cmdec->getOuterScope(),cmdec->getFileDef(),mdecAl, + if (matchArguments2(cmdef->getOuterScope(),cmdef->getFileDef(),&mdefAl, + cmdec->getOuterScope(),cmdec->getFileDef(),&mdecAl, TRUE ) ) /* match found */ @@ -6002,10 +5979,9 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) mdec->setDocsForDefinition(mdef->isDocsForDefinition()); if (mdefAl.hasParameters()) { - ArgumentList mdefAlComb; - stringToArgumentList(mdef->getLanguage(),mdef->argsString(),mdefAlComb); - transferArgumentDocumentation(mdefAl,mdefAlComb); - mdec->setArgumentList(mdefAlComb); + auto mdefAlComb = stringToArgumentList(mdef->getLanguage(),mdef->argsString()); + transferArgumentDocumentation(mdefAl,*mdefAlComb); + mdec->moveArgumentList(std::move(mdefAlComb)); } } else if (!mdec->documentation().isEmpty()) @@ -6015,10 +5991,9 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) mdef->setDocsForDefinition(mdec->isDocsForDefinition()); if (mdecAl.hasParameters()) { - ArgumentList mdecAlComb; - stringToArgumentList(mdec->getLanguage(),mdec->argsString(),mdecAlComb); - transferArgumentDocumentation(mdecAl,mdecAlComb); - mdef->setDeclArgumentList(mdecAlComb); + auto mdecAlComb = stringToArgumentList(mdec->getLanguage(),mdec->argsString()); + transferArgumentDocumentation(mdecAl,*mdecAlComb); + mdef->moveDeclArgumentList(std::move(mdecAlComb)); } } if (!mdef->inbodyDocumentation().isEmpty()) @@ -6032,14 +6007,14 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) if (mdec->getStartBodyLine()!=-1 && mdef->getStartBodyLine()==-1) { //printf("body mdec->mdef %d-%d\n",mdec->getStartBodyLine(),mdef->getEndBodyLine()); - mdef->setBodySegment(mdec->getStartBodyLine(),mdec->getEndBodyLine()); + mdef->setBodySegment(mdec->getDefLine(),mdec->getStartBodyLine(),mdec->getEndBodyLine()); mdef->setBodyDef(mdec->getBodyDef()); //mdef->setBodyMember(mdec); } else if (mdef->getStartBodyLine()!=-1 && mdec->getStartBodyLine()==-1) { //printf("body mdef->mdec %d-%d\n",mdef->getStartBodyLine(),mdec->getEndBodyLine()); - mdec->setBodySegment(mdef->getStartBodyLine(),mdef->getEndBodyLine()); + mdec->setBodySegment(mdef->getDefLine(),mdef->getStartBodyLine(),mdef->getEndBodyLine()); mdec->setBodyDef(mdef->getBodyDef()); //mdec->setBodyMember(mdef); } diff --git a/src/memberdef.h b/src/memberdef.h index a9103e1..f15c31e 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,12 +19,14 @@ #define MEMBERDEF_H #include <vector> +#include <memory> #include <qlist.h> #include <sys/types.h> #include "types.h" #include "definition.h" +#include "arguments.h" class ClassDef; class NamespaceDef; @@ -36,7 +38,6 @@ class ExampleSDict; class OutputList; class GroupDef; class QTextStream; -class ArgumentList; class QStrList; struct TagInfo; @@ -72,7 +73,7 @@ class MemberDef : virtual public Definition virtual const QCString &initializer() const = 0; virtual int initializerLines() const = 0; virtual uint64 getMemberSpecifiers() const = 0; - virtual const MemberList *getSectionList() const = 0; + virtual const MemberList *getSectionList(const Definition *container) const = 0; virtual QCString displayDefinition() const = 0; // scope query members @@ -93,16 +94,16 @@ class MemberDef : virtual public Definition // grabbing the property read/write accessor names virtual const char *getReadAccessor() const = 0; virtual const char *getWriteAccessor() const = 0; - + // querying the grouping definition virtual Grouping::GroupPri_t getGroupPri() const = 0; virtual const char *getGroupFileName() const = 0; virtual int getGroupStartLine() const = 0; virtual bool getGroupHasDocs() const = 0; virtual QCString qualifiedName() const = 0; - virtual QCString objCMethodName(bool localLink,bool showStatic) const = 0; + virtual QCString objCMethodName(bool localLink,bool showStatic) const = 0; - // direct kind info + // direct kind info virtual Protection protection() const = 0; virtual Specifier virtualness(int count=0) const = 0; virtual MemberType memberType() const = 0; @@ -227,7 +228,7 @@ class MemberDef : virtual public Definition virtual ArgumentList &argumentList() = 0; virtual const ArgumentList &declArgumentList() const = 0; virtual const ArgumentList &templateArguments() const = 0; - virtual const std::vector<ArgumentList> &definitionTemplateParameterLists() const = 0; + virtual const ArgumentLists &definitionTemplateParameterLists() const = 0; // member group related members virtual int getMemberGroupId() const = 0; @@ -296,7 +297,7 @@ class MemberDef : virtual public Definition virtual void setBitfields(const char *s) = 0; virtual void setMaxInitLines(int lines) = 0; virtual void setMemberClass(ClassDef *cd) = 0; - virtual void setSectionList(MemberList *sl) = 0; + virtual void setSectionList(const Definition *container,MemberList *sl) = 0; virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine,bool hasDocs, MemberDef *member=0) = 0; @@ -326,16 +327,16 @@ class MemberDef : virtual public Definition // example related members virtual bool addExample(const char *anchor,const char *name,const char *file) = 0; - + // prototype related members virtual void setPrototype(bool p,const QCString &df,int line, int column) = 0; virtual void setExplicitExternal(bool b,const QCString &df,int line,int column) = 0; virtual void setDeclFile(const QCString &df,int line,int column) = 0; // argument related members - virtual void setArgumentList(const ArgumentList &al) = 0; - virtual void setDeclArgumentList(const ArgumentList &al) = 0; - virtual void setDefinitionTemplateParameterLists(const std::vector<ArgumentList> &lists) = 0; + virtual void moveArgumentList(std::unique_ptr<ArgumentList> al) = 0; + virtual void moveDeclArgumentList(std::unique_ptr<ArgumentList> al) = 0; + virtual void setDefinitionTemplateParameterLists(const ArgumentLists &lists) = 0; virtual void setTypeConstraints(const ArgumentList &al) = 0; virtual void setType(const char *t) = 0; virtual void setAccessorType(ClassDef *cd,const char *t) = 0; @@ -387,7 +388,7 @@ class MemberDef : virtual public Definition //----------------------------------------------------------------------------------- virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, - const ArgumentList &actualArgs) const = 0; + const std::unique_ptr<ArgumentList> &actualArgs) const = 0; virtual void findSectionsInDocumentation() = 0; virtual void addToSearchIndex() const = 0; diff --git a/src/membergroup.cpp b/src/membergroup.cpp index 05c38c3..e229835 100644 --- a/src/membergroup.cpp +++ b/src/membergroup.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -29,33 +29,14 @@ #include "entry.h" #include "md5.h" -//static QCString idToName(int id) -//{ -// QCString result; -// result.sprintf("mgroup_%d",id); -// return result; -//} - -MemberGroup::MemberGroup() -{ -} - -MemberGroup::MemberGroup(int id,const char *hdr,const char *d,const char *docFile,int docLine) +MemberGroup::MemberGroup(const Definition *container,int id,const char *hdr,const char *d,const char *docFile,int docLine) + : m_container(container), grpId(id), grpHeader(hdr), doc(d), m_docFile(docFile), m_docLine(docLine) { static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS); //printf("New member group id=%d header=%s desc=%s\n",id,hdr,d); memberList = new MemberList(MemberListType_memberGroup); memberList->setNeedsSorting(sortBriefDocs); // detailed sections are already sorted elsewhere. - grpId = id; - grpHeader = hdr; - doc = d; - inSameSection = TRUE; - inDeclSection = 0; - m_numDecMembers = -1; - m_numDocMembers = -1; - m_docFile = docFile; - m_docLine = docLine; //printf("Member group docs='%s'\n",doc.data()); } @@ -74,13 +55,14 @@ void MemberGroup::insertMember(MemberDef *md) // md,md->name().data()); MemberDef *firstMd = memberList->getFirst(); - if (inSameSection && firstMd && firstMd->getSectionList()!=md->getSectionList()) + if (inSameSection && firstMd && + firstMd->getSectionList(m_container)!=md->getSectionList(m_container)) { inSameSection=FALSE; } else if (inDeclSection==0) { - inDeclSection = const_cast<MemberList*>(md->getSectionList()); + inDeclSection = const_cast<MemberList*>(md->getSectionList(m_container)); //printf("inDeclSection=%p type=%d\n",inDeclSection,inDeclSection->listType()); } memberList->append(md); @@ -125,6 +107,7 @@ void MemberGroup::writePlainDeclarations(OutputList &ol, void MemberGroup::writeDocumentation(OutputList &ol,const char *scopeName, const Definition *container,bool showEnumValues,bool showInline) const { + //printf("MemberGroup::writeDocumentation() %s\n",grpHeader.data()); memberList->writeDocumentation(ol,scopeName,container,0,showEnumValues,showInline); } @@ -149,13 +132,13 @@ void MemberGroup::addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd, for (li.toFirst();(md=li.current());++li) { //printf("matching %d == %d\n",lt,md->getSectionList()->listType()); - const MemberList *ml = md->getSectionList(); + const MemberList *ml = md->getSectionList(m_container); if (ml && lt==ml->listType()) { - MemberList ml(lt); - ml.append(md); - ml.countDecMembers(); - ml.writePlainDeclarations(ol,cd,0,0,0,inheritedFrom,inheritId); + MemberList mml(lt); + mml.append(md); + mml.countDecMembers(); + mml.writePlainDeclarations(ol,cd,0,0,0,inheritedFrom,inheritId); } } } @@ -169,7 +152,7 @@ int MemberGroup::countGroupedInheritedMembers(MemberListType lt) for (li.toFirst();(md=li.current());++li) { //printf("matching %d == %d\n",lt,md->getSectionList()->listType()); - const MemberList *ml = md->getSectionList(); + const MemberList *ml = md->getSectionList(m_container); if (ml && lt==ml->listType()) { count++; @@ -202,6 +185,10 @@ void MemberGroup::countDocMembers() memberList->countDocMembers(); } +const Definition *MemberGroup::container() const +{ + return m_container; +} int MemberGroup::countInheritableMembers(const ClassDef *inheritedFrom) const { @@ -253,49 +240,49 @@ int MemberGroup::varCount() const return memberList->varCount(); } -int MemberGroup::funcCount() const -{ - return memberList->funcCount(); +int MemberGroup::funcCount() const +{ + return memberList->funcCount(); } -int MemberGroup::enumCount() const -{ - return memberList->enumCount(); +int MemberGroup::enumCount() const +{ + return memberList->enumCount(); } -int MemberGroup::enumValueCount() const -{ - return memberList->enumValueCount(); +int MemberGroup::enumValueCount() const +{ + return memberList->enumValueCount(); } -int MemberGroup::typedefCount() const -{ - return memberList->typedefCount(); +int MemberGroup::typedefCount() const +{ + return memberList->typedefCount(); } -int MemberGroup::sequenceCount() const -{ - return memberList->sequenceCount(); +int MemberGroup::sequenceCount() const +{ + return memberList->sequenceCount(); } -int MemberGroup::dictionaryCount() const -{ - return memberList->dictionaryCount(); +int MemberGroup::dictionaryCount() const +{ + return memberList->dictionaryCount(); } -int MemberGroup::protoCount() const -{ - return memberList->protoCount(); +int MemberGroup::protoCount() const +{ + return memberList->protoCount(); } -int MemberGroup::defineCount() const -{ - return memberList->defineCount(); +int MemberGroup::defineCount() const +{ + return memberList->defineCount(); } -int MemberGroup::friendCount() const -{ - return memberList->friendCount(); +int MemberGroup::friendCount() const +{ + return memberList->friendCount(); } #endif @@ -356,7 +343,7 @@ void MemberGroup::findSectionsInDocumentation(const Definition *d) memberList->findSectionsInDocumentation(d); } -void MemberGroup::setRefItems(const std::vector<ListItemInfo> &sli) +void MemberGroup::setRefItems(const RefItemVector &sli) { m_xrefListItems.insert(m_xrefListItems.end(), sli.cbegin(), sli.cend()); } @@ -368,7 +355,7 @@ void MemberGroup::writeTagFile(FTextStream &tagFile) //-------------------------------------------------------------------------- -void MemberGroupInfo::setRefItems(const std::vector<ListItemInfo> &sli) +void MemberGroupInfo::setRefItems(const RefItemVector &sli) { m_sli.insert(m_sli.end(), sli.cbegin(), sli.cend()); } diff --git a/src/membergroup.h b/src/membergroup.h index aa30063..c10e421 100644 --- a/src/membergroup.h +++ b/src/membergroup.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -23,6 +23,7 @@ #include <qlist.h> #include "sortdict.h" #include "types.h" +#include "reflist.h" #define DOX_NOGROUP -1 @@ -35,14 +36,14 @@ class GroupDef; class OutputList; class Definition; class FTextStream; -struct ListItemInfo; +class RefItem; /** A class representing a group of members. */ -class MemberGroup +class MemberGroup { public: - MemberGroup(); - MemberGroup(int id,const char *header, + //MemberGroup(); + MemberGroup(const Definition *container,int id,const char *header, const char *docs,const char *docFile,int docLine); ~MemberGroup(); QCString header() const { return grpHeader; } @@ -77,31 +78,30 @@ class MemberGroup int numDecEnumValues() const; int numDocMembers() const; int numDocEnumValues() const; + const Definition *container() const; int countInheritableMembers(const ClassDef *inheritedFrom) const; void setInGroup(bool b); void addListReferences(Definition *d); - void setRefItems(const std::vector<ListItemInfo> &sli); + void setRefItems(const RefItemVector &sli); MemberList *members() const { return memberList; } QCString anchor() const; QCString docFile() const { return m_docFile; } int docLine() const { return m_docLine; } - private: + private: + const Definition *m_container; MemberList *memberList = 0; // list of all members in the group MemberList *inDeclSection = 0; int grpId = 0; QCString grpHeader; QCString fileName; // base name of the generated file QCString doc; - bool inSameSection = 0; - int m_numDecMembers = 0; - int m_numDocMembers = 0; - const Definition *m_parent = 0; + bool inSameSection = true; QCString m_docFile; - int m_docLine = 0; - std::vector<ListItemInfo> m_xrefListItems; + int m_docLine; + RefItemVector m_xrefListItems; }; /** A list of MemberGroup objects. */ @@ -113,7 +113,7 @@ class MemberGroupList : public QList<MemberGroup> class MemberGroupListIterator : public QListIterator<MemberGroup> { public: - MemberGroupListIterator(const MemberGroupList &l) : + MemberGroupListIterator(const MemberGroupList &l) : QListIterator<MemberGroup>(l) {} }; @@ -133,13 +133,13 @@ class MemberGroupSDict : public SIntDict<MemberGroup> /** Data collected for a member group */ struct MemberGroupInfo { - void setRefItems(const std::vector<ListItemInfo> &sli); + void setRefItems(const RefItemVector &sli); QCString header; QCString doc; QCString docFile; int docLine = -1; QCString compoundName; - std::vector<ListItemInfo> m_sli; + RefItemVector m_sli; }; #endif diff --git a/src/memberlist.cpp b/src/memberlist.cpp index 278023b..b8e5e89 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -63,10 +63,11 @@ MemberList::~MemberList() delete memberGroupList; } -int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const +static int genericCompareMembers(const MemberDef *c1,const MemberDef *c2) { - static bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST); - if (sortConstructorsFirst) { + bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST); + if (sortConstructorsFirst) + { int ord1 = c1->isConstructor() ? 2 : (c1->isDestructor() ? 1 : 0); int ord2 = c2->isConstructor() ? 2 : (c2->isDestructor() ? 1 : 0); if (ord1 > ord2) @@ -74,9 +75,29 @@ int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const else if (ord2 > ord1) return 1; } + // sort on name int cmp = qstricmp(c1->name(),c2->name()); - if (cmp==0) cmp = qstricmp(c1->argsString(),c2->argsString()); - return cmp!=0 ? cmp : c1->getDefLine()-c2->getDefLine(); + // then on argument list + if (cmp==0 && c1->argsString() && c2->argsString()) + { + cmp = qstricmp(c1->argsString(),c2->argsString()); + } + // then on file in which the item is defined + if (cmp==0) + { + cmp = qstricmp(c1->getDefFileName(),c2->getDefFileName()); + } + // then on line number at which the member is defined + if (cmp==0) + { + cmp = c1->getDefLine()-c2->getDefLine(); + } + return cmp; +} + +int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const +{ + return genericCompareMembers(c1,c2); } int MemberList::countInheritableMembers(const ClassDef *inheritedFrom) const @@ -288,7 +309,7 @@ MemberDef *MemberList::take(uint index) } MemberListIterator::MemberListIterator(const MemberList &l) : - QListIterator<MemberDef>(l) + QListIterator<MemberDef>(l) { } @@ -378,9 +399,9 @@ bool MemberList::declVisible() const case MemberType_Service: // fall through case MemberType_Sequence: // fall through case MemberType_Dictionary: // fall through - case MemberType_Event: + case MemberType_Event: return TRUE; - case MemberType_Enumeration: + case MemberType_Enumeration: { // if this is an anonymous enum and there are variables of this // enum type (i.e. enumVars>0), then we do not show the enum here. @@ -392,7 +413,7 @@ bool MemberList::declVisible() const break; case MemberType_Friend: return TRUE; - case MemberType_EnumValue: + case MemberType_EnumValue: { if (m_inGroup) { @@ -412,7 +433,6 @@ void MemberList::writePlainDeclarations(OutputList &ol, ) const { //printf("----- writePlainDeclaration() ----\n"); - static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); if (numDecMembers()==-1) { err("MemberList::numDecMembers()==-1, so the members of this list have not been counted. Please report as a bug.\n"); @@ -425,7 +445,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, } //printf(" --> writePlainDeclaration() numDecMembers()=%d\n", // numDecMembers()); - + ol.pushGeneratorState(); bool first=TRUE; @@ -454,13 +474,13 @@ void MemberList::writePlainDeclarations(OutputList &ol, case MemberType_Service: // fall through case MemberType_Sequence: // fall through case MemberType_Dictionary: // fall through - case MemberType_Event: + case MemberType_Event: { if (first) ol.startMemberList(),first=FALSE; md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId); break; } - case MemberType_Enumeration: + case MemberType_Enumeration: { // if this is an anonymous enum and there are variables of this // enum type (i.e. enumVars>0), then we do not show the enum here. @@ -497,7 +517,8 @@ void MemberList::writePlainDeclarations(OutputList &ol, md->briefFile(),md->briefLine(), cd,md, md->briefDescription(), - TRUE,FALSE,0,TRUE,FALSE + TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT) ); if (rootNode && !rootNode->isEmpty()) { @@ -525,7 +546,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, case MemberType_Friend: if (inheritedFrom==0) { - if (first) + if (first) { ol.startMemberList(); first=FALSE; @@ -533,7 +554,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId); break; } - case MemberType_EnumValue: + case MemberType_EnumValue: { if (m_inGroup) { @@ -551,8 +572,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, // no variables of the anonymous compound type exist. if (cd) { - MemberListIterator mli(*this); - for ( ; (md=mli.current()) ; ++mli ) + for ( mli.toFirst(); (md=mli.current()) ; ++mli ) { if (md->fromAnonymousScope() && !md->anonymousDeclShown()) { @@ -560,7 +580,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, //printf("anonymous compound members\n"); if (md->isBriefSectionVisible()) { - if (first) + if (first) { ol.startMemberList(); first=FALSE; @@ -571,10 +591,10 @@ void MemberList::writePlainDeclarations(OutputList &ol, } } } - - if (!first) + + if (!first) { - ol.endMemberList(); + ol.endMemberList(); } ol.popGeneratorState(); @@ -630,7 +650,7 @@ void MemberList::writeDeclarations(OutputList &ol, if (title) { ol.writeInheritedSectionTitle(inheritId,cd->getReference(), - cd->getOutputFileBase(), + cd->getOutputFileBase(), cd->anchor(),title,cd->displayName()); } ol.popGeneratorState(); @@ -638,7 +658,7 @@ void MemberList::writeDeclarations(OutputList &ol, } else if (num>numEnumValues) { - if (title) + if (title) { if (showInline) { @@ -658,14 +678,15 @@ void MemberList::writeDeclarations(OutputList &ol, ol.endMemberHeader(); } } - if (subtitle) + if (subtitle) { QCString st=subtitle; st = st.stripWhiteSpace(); if (!st.isEmpty()) { ol.startMemberSubtitle(); - ol.generateDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE,0,FALSE,FALSE); + ol.generateDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberSubtitle(); } } @@ -708,7 +729,8 @@ void MemberList::writeDeclarations(OutputList &ol, { //printf("Member group has docs!\n"); ol.startMemberGroupDocs(); - ol.generateDoc(mg->docFile(),mg->docLine(),ctx,0,mg->documentation()+"\n",FALSE,FALSE); + ol.generateDoc(mg->docFile(),mg->docLine(),ctx,0,mg->documentation()+"\n",FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberGroupDocs(); } ol.startMemberGroup(); @@ -723,7 +745,7 @@ void MemberList::writeDeclarations(OutputList &ol, } } } - if (inheritedFrom && cd) + if (inheritedFrom && cd) { // also add members that of this list type, that are grouped together // in a separate list in class 'inheritedFrom' @@ -767,7 +789,7 @@ void MemberList::writeDocumentation(OutputList &ol, overloadCountDict.setAutoDelete(TRUE); for (mli.toFirst() ; (md=mli.current()) ; ++mli) { - if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && + if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && !(md->isEnumValue() && !showInline)) { uint *pCount = overloadTotalDict.find(md->name()); @@ -785,7 +807,7 @@ void MemberList::writeDocumentation(OutputList &ol, for (mli.toFirst() ; (md=mli.current()) ; ++mli) { - if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && + if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && !(md->isEnumValue() && !showInline)) { uint overloadCount = *overloadTotalDict.find(md->name()); @@ -944,7 +966,7 @@ void MemberList::addListReferences(Definition *def) MemberDef *vmd; for ( ; (vmd=vmli.current()) ; ++vmli) { - //printf(" adding %s\n",vmd->name().data()); + //printf(" adding %s\n",vmd->name().data()); vmd->addListReference(def); } } @@ -985,7 +1007,7 @@ void MemberList::setNeedsSorting(bool b) m_needsSorting = b; } -QCString MemberList::listTypeAsString(MemberListType type) +QCString MemberList::listTypeAsString(MemberListType type) { switch(type) { @@ -1082,16 +1104,7 @@ void MemberList::writeTagFile(FTextStream &tagFile) int MemberSDict::compareValues(const MemberDef *c1, const MemberDef *c2) const { - //printf("MemberSDict::compareValues(%s,%s)\n",c1->name().data(),c2->name().data()); - int cmp = qstricmp(c1->name(),c2->name()); - if (cmp) - { - return cmp; - } - else - { - return c1->getDefLine()-c2->getDefLine(); - } + return genericCompareMembers(c1,c2); } diff --git a/src/memberlist.h b/src/memberlist.h index 422c162..4038453 100644 --- a/src/memberlist.h +++ b/src/memberlist.h @@ -131,7 +131,7 @@ class MemberListIterator : public QListIterator<MemberDef> class MemberDict : public QDict<MemberDef> { public: - MemberDict(int size) : QDict<MemberDef>(size) {} + MemberDict(uint size) : QDict<MemberDef>(size) {} virtual ~MemberDict() {} }; @@ -139,7 +139,7 @@ class MemberDict : public QDict<MemberDef> class MemberSDict : public SDict<MemberDef> { public: - MemberSDict(int size=17) : SDict<MemberDef>(size) {} + MemberSDict(uint size=17) : SDict<MemberDef>(size) {} virtual ~MemberSDict() {} private: int compareValues(const MemberDef *item1,const MemberDef *item2) const; diff --git a/src/membername.cpp b/src/membername.cpp deleted file mode 100644 index 72809b3..0000000 --- a/src/membername.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#include "membername.h" -#include "classdef.h" -#include "util.h" -#include "filedef.h" - -MemberName::MemberName(const char *n) : QList<MemberDef>() -{ - name=n; - setAutoDelete(TRUE); -} - -MemberName::~MemberName() -{ -} - -int MemberName::compareValues(const MemberDef *m1, const MemberDef *m2) const -{ - const ClassDef *c1=m1->getClassDef(); - const ClassDef *c2=m2->getClassDef(); - const FileDef *f1=m1->getFileDef(); - const FileDef *f2=m2->getFileDef(); - if (c1 && c2) - return qstrcmp(c1->name(),c2->name()); - else if (f1 && f2) - return qstrcmp(f1->name(),f2->name()); - else - return 0; -} - -MemberNameInfo::MemberNameInfo(const char *n) : QList<MemberInfo>() -{ - name=n; - setAutoDelete(TRUE); -} - -int MemberNameInfo::compareValues(const MemberInfo *m1,const MemberInfo *m2) const -{ - const ClassDef *c1=m1->memberDef->getClassDef(); - const ClassDef *c2=m2->memberDef->getClassDef(); - const FileDef *f1=m1->memberDef->getFileDef(); - const FileDef *f2=m2->memberDef->getFileDef(); - if (c1 && c2) - return qstrcmp(c1->name(),c2->name()); - else if (f1 && f2) - return qstrcmp(f1->name(),f2->name()); - else - return 0; -} -MemberNameIterator::MemberNameIterator(const MemberName &mnlist) : - QListIterator<MemberDef>(mnlist) -{ -} - -int MemberNameSDict::compareValues(const MemberName *n1,const MemberName *n2) const -{ - return qstricmp(n1->memberName()+getPrefixIndex(n1->memberName()), - n2->memberName()+getPrefixIndex(n2->memberName()) - ); -} - diff --git a/src/membername.h b/src/membername.h index 143dca1..88d8832 100644 --- a/src/membername.h +++ b/src/membername.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -21,84 +21,112 @@ #include <qlist.h> #include "memberdef.h" #include "sortdict.h" +#include "linkedmap.h" -/** Class representing all MemberDef objects with the same name */ -class MemberName : public QList<MemberDef> +class MemberName { public: - MemberName(const char *name); - ~MemberName(); - const char *memberName() const { return name; } + using Ptr = std::unique_ptr<MemberDef>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; + using const_iterator = typename Vec::const_iterator; + using reverse_iterator = typename Vec::reverse_iterator; + using const_reverse_iterator = typename Vec::const_reverse_iterator; + + MemberName(const char *name) : m_name(name) {} + const char *memberName() const { return m_name; } + + iterator begin() { return m_members.begin(); } + iterator end() { return m_members.end(); } + const_iterator begin() const { return m_members.begin(); } + const_iterator end() const { return m_members.end(); } + const_iterator cbegin() const { return m_members.cbegin(); } + const_iterator cend() const { return m_members.cend(); } + reverse_iterator rbegin() { return m_members.rbegin(); } + reverse_iterator rend() { return m_members.rend(); } + const_reverse_iterator crbegin() const { return m_members.crbegin(); } + const_reverse_iterator crend() const { return m_members.crend(); } + bool empty() const { return m_members.empty(); } + size_t size() const { return m_members.size(); } + Ptr &back() { return m_members.back(); } + const Ptr &back() const { return m_members.back(); } + Ptr &front() { return m_members.front(); } + const Ptr &front() const { return m_members.front(); } + void push_back(Ptr &&p) { m_members.push_back(std::move(p)); } private: - int compareValues(const MemberDef *item1,const MemberDef *item2) const; - QCString name; + QCString m_name; + Vec m_members; }; -/** Iterator for MemberDef objects in a MemberName list. */ -class MemberNameIterator : public QListIterator<MemberDef> +/** Ordered dictionary of MemberName objects. */ +class MemberNameLinkedMap : public LinkedMap<MemberName> { - public: - MemberNameIterator( const MemberName &list); }; -/** Sorted dictionary of MemberName objects. */ -class MemberNameSDict : public SDict<MemberName> +/** Data associated with a MemberDef in an inheritance relation. */ +class MemberInfo { public: - MemberNameSDict(int size) : SDict<MemberName>(size) {} - ~MemberNameSDict() {} + MemberInfo(MemberDef *md,Protection p,Specifier v,bool inh) : + m_memberDef(md), m_prot(p), m_virt(v), m_inherited(inh) {} + ~MemberInfo() {} - private: - int compareValues(const MemberName *item1,const MemberName *item2) const; -}; + // getters + MemberDef *memberDef() { return m_memberDef; } + const MemberDef *memberDef() const { return m_memberDef; } + Protection prot() const { return m_prot; } + Specifier virt() const { return m_virt; } + bool inherited() const { return m_inherited; } + QCString scopePath() const { return m_scopePath; } + QCString ambiguityResolutionScope() const { return m_ambiguityResolutionScope; } + const ClassDef *ambigClass() const { return m_ambigClass; } -/** Data associated with a MemberDef in an inheritance relation. */ -struct MemberInfo -{ - MemberInfo(MemberDef *md,Protection p,Specifier v,bool inh) : - memberDef(md), prot(p), virt(v), inherited(inh), ambigClass(0) {} - ~MemberInfo() {} - MemberDef *memberDef; - Protection prot; - Specifier virt; - bool inherited; - QCString scopePath; - QCString ambiguityResolutionScope; - ClassDef *ambigClass; -}; + // setters + void setAmbiguityResolutionScope(const QCString &s) { m_ambiguityResolutionScope = s; } + void setScopePath(const QCString &s) { m_scopePath = s; } + void setAmbigClass(const ClassDef *cd) { m_ambigClass = cd; } -/** Class representing all MemberInfo objects with the same name */ -class MemberNameInfo : public QList<MemberInfo> -{ - public: - MemberNameInfo(const char *name); - ~MemberNameInfo() {} - const char *memberName() const { return name; } private: - int compareValues(const MemberInfo *item1,const MemberInfo *item2) const; - QCString name; + MemberDef *m_memberDef; + Protection m_prot; + Specifier m_virt; + bool m_inherited; + QCString m_scopePath; + QCString m_ambiguityResolutionScope; + const ClassDef *m_ambigClass = 0; }; -/** Iterator for MemberInfo objects in a MemberNameInfo list. */ -class MemberNameInfoIterator : public QListIterator<MemberInfo> +class MemberNameInfo { public: - MemberNameInfoIterator(const MemberNameInfo &mnii) - : QListIterator<MemberInfo>(mnii) {} + using Ptr = std::unique_ptr<MemberInfo>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; + using const_iterator = typename Vec::const_iterator; + + MemberNameInfo(const char *name) : m_name(name) {} + const char *memberName() const { return m_name; } + + iterator begin() { return m_members.begin(); } + iterator end() { return m_members.end(); } + const_iterator begin() const { return m_members.begin(); } + const_iterator end() const { return m_members.end(); } + bool empty() const { return m_members.empty(); } + size_t size() const { return m_members.size(); } + Ptr &back() { return m_members.back(); } + const Ptr &back() const { return m_members.back(); } + Ptr &front() { return m_members.front(); } + const Ptr &front() const { return m_members.front(); } + void push_back(Ptr &&p) { m_members.push_back(std::move(p)); } + + private: + QCString m_name; + Vec m_members; }; -/** Sorted dictionary of MemberNameInfo objects. */ -class MemberNameInfoSDict : public SDict<MemberNameInfo> +class MemberNameInfoLinkedMap : public LinkedMap<MemberNameInfo> { - public: - MemberNameInfoSDict(int size) : SDict<MemberNameInfo>(size) {} - ~MemberNameInfoSDict() {} - private: - int compareValues(const MemberNameInfo *item1,const MemberNameInfo *item2) const - { - return qstricmp(item1->memberName(), item2->memberName()); - } }; #endif diff --git a/src/message.cpp b/src/message.cpp index d8f83ef..984a00f 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby @@ -14,14 +14,13 @@ */ #include <stdio.h> -#include <qdatetime.h> #include "config.h" -#include "util.h" #include "debug.h" -#include "doxygen.h" #include "portable.h" -#include "filedef.h" #include "message.h" +#include "doxygen.h" + +#include <mutex> static QCString outputFormat; static const char *warning_str = "warning: "; @@ -35,6 +34,9 @@ static const char *error_str = "error: "; static FILE *warnFile = stderr; + +static std::mutex g_mutex; + void initWarningFormat() { // int filePos = Config_getString(WARN_FORMAT).find("$file"); @@ -108,9 +110,10 @@ void msg(const char *fmt, ...) { if (!Config_getBool(QUIET)) { + std::unique_lock<std::mutex> lock(g_mutex); if (Debug::isFlagSet(Debug::Time)) { - printf("%.3f sec: ",((double)Doxygen::runningTime.elapsed())/1000.0); + printf("%.3f sec: ",((double)Debug::elapsedTime())); } va_list args; va_start(args, fmt); @@ -125,15 +128,6 @@ static void format_warn(const char *file,int line,const char *text) QCString lineSubst; lineSubst.setNum(line); QCString textSubst = text; QCString versionSubst; - if (file) // get version from file name - { - bool ambig; - FileDef *fd=findFileDef(Doxygen::inputNameDict,file,ambig); - if (fd) - { - versionSubst = fd->getVersion(); - } - } // substitute markers by actual values bool warnAsError = Config_getBool(WARN_AS_ERROR); QCString msgText = @@ -156,14 +150,29 @@ static void format_warn(const char *file,int line,const char *text) } msgText += '\n'; - // print resulting message - fwrite(msgText.data(),1,msgText.length(),warnFile); + { + std::unique_lock<std::mutex> lock(g_mutex); + // print resulting message + fwrite(msgText.data(),1,msgText.length(),warnFile); + } if (warnAsError) { exit(1); } } +static void handle_warn_as_error(void) +{ + static bool warnAsError = Config_getBool(WARN_AS_ERROR); + if (warnAsError) + { + std::unique_lock<std::mutex> lock(g_mutex); + QCString msgText = " (warning treated as error, aborting now)\n"; + fwrite(msgText.data(),1,msgText.length(),warnFile); + exit(1); + } +} + static void do_warn(bool enabled, const char *file, int line, const char *prefix, const char *fmt, va_list args) { if (!enabled) return; // warning type disabled @@ -174,7 +183,7 @@ static void do_warn(bool enabled, const char *file, int line, const char *prefix int l=0; if (prefix) { - l=strlen(prefix); + l=(int)strlen(prefix); } // determine needed buffersize based on: // format + arguments @@ -233,6 +242,7 @@ void warn_uncond(const char *fmt, ...) va_start(args, fmt); vfprintf(warnFile, (QCString(warning_str) + fmt).data(), args); va_end(args); + handle_warn_as_error(); } void err(const char *fmt, ...) @@ -241,6 +251,7 @@ void err(const char *fmt, ...) va_start(args, fmt); vfprintf(warnFile, (QCString(error_str) + fmt).data(), args); va_end(args); + handle_warn_as_error(); } extern void err_full(const char *file,int line,const char *fmt, ...) @@ -253,14 +264,17 @@ extern void err_full(const char *file,int line,const char *fmt, ...) void term(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(warnFile, (QCString(error_str) + fmt).data(), args); - va_end(args); - if (warnFile != stderr) { - for (int i = 0; i < strlen(error_str); i++) fprintf(warnFile, " "); - fprintf(warnFile, "%s\n", "Exiting..."); + std::unique_lock<std::mutex> lock(g_mutex); + va_list args; + va_start(args, fmt); + vfprintf(warnFile, (QCString(error_str) + fmt).data(), args); + va_end(args); + if (warnFile != stderr) + { + for (int i = 0; i < (int)strlen(error_str); i++) fprintf(warnFile, " "); + fprintf(warnFile, "%s\n", "Exiting..."); + } } exit(1); } @@ -276,6 +290,7 @@ void printlex(int dbg, bool enter, const char *lexName, const char *fileName) enter_txt_uc = "Finished"; } + std::unique_lock<std::mutex> lock(g_mutex); if (dbg) { if (fileName) diff --git a/src/message.h b/src/message.h index 7b12ba8..e84344b 100644 --- a/src/message.h +++ b/src/message.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -18,20 +16,28 @@ #ifndef MESSAGE_H #define MESSAGE_H -#include <stdio.h> -#include <stdarg.h> +#include <cstdarg> + +#ifdef __GNUC__ +#define PRINTFLIKE(FORMAT, PARAM ) __attribute__((format(printf, FORMAT, PARAM))) +#else +#define PRINTFLIKE(FORMAT, PARAM ) +#endif -extern void msg(const char *fmt, ...); -extern void warn(const char *file,int line,const char *fmt, ...); -extern void va_warn(const char *file,int line,const char *fmt, va_list args); +extern void msg(const char *fmt, ...) PRINTFLIKE(1,2); +extern void warn(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); +extern void va_warn(const char* file, int line, const char* fmt, va_list args); extern void warn_simple(const char *file,int line,const char *text); -extern void warn_undoc(const char *file,int line,const char *fmt, ...); -extern void warn_doc_error(const char *file,int line,const char *fmt, ...); -extern void warn_uncond(const char *fmt, ...); -extern void err(const char *fmt, ...); -extern void err_full(const char *file,int line,const char *fmt, ...); -extern void term(const char *fmt, ...); +extern void warn_undoc(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); +extern void warn_doc_error(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); +extern void warn_uncond(const char *fmt, ...) PRINTFLIKE(1, 2); +extern void err(const char *fmt, ...) PRINTFLIKE(1, 2); +extern void err_full(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); +extern void term(const char *fmt, ...) PRINTFLIKE(1, 2); void initWarningFormat(); extern void printlex(int dbg, bool enter, const char *lexName, const char *fileName); + +#undef PRINTFLIKE + #endif diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 220f300..88eea5d 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -370,7 +370,7 @@ void NamespaceDefImpl::findSectionsInDocumentation() void NamespaceDefImpl::insertUsedFile(FileDef *fd) { if (fd==0) return; - if (files.find(fd)==-1) + if (files.find(fd)==-1) { if (Config_getBool(SORT_MEMBER_DOCS)) files.inSort(fd); @@ -471,7 +471,7 @@ void NamespaceDefImpl::insertMember(MemberDef *md) // isInline(),hasDocumentation()); if (md->isHidden()) return; - // if this is an inline namespace that is not documented, then insert the + // if this is an inline namespace that is not documented, then insert the // member in the parent scope instead if (isInline() && !hasDocumentation()) { @@ -501,44 +501,44 @@ void NamespaceDefImpl::insertMember(MemberDef *md) allMemberList = new MemberList(MemberListType_allMembersList); m_memberLists.append(allMemberList); } - allMemberList->append(md); + allMemberList->append(md); if (m_allMembersDict==0) { m_allMembersDict = new MemberSDict; } //printf("%s::m_allMembersDict->append(%s)\n",name().data(),md->localName().data()); - m_allMembersDict->append(md->localName(),md); + m_allMembersDict->append(md->localName(),md); //::addNamespaceMemberNameToIndex(md); //static bool sortBriefDocs=Config_getBool(SORT_BRIEF_DOCS); switch(md->memberType()) { - case MemberType_Variable: + case MemberType_Variable: addMemberToList(MemberListType_decVarMembers,md); addMemberToList(MemberListType_docVarMembers,md); break; - case MemberType_Function: + case MemberType_Function: addMemberToList(MemberListType_decFuncMembers,md); addMemberToList(MemberListType_docFuncMembers,md); break; - case MemberType_Typedef: + case MemberType_Typedef: addMemberToList(MemberListType_decTypedefMembers,md); addMemberToList(MemberListType_docTypedefMembers,md); break; - case MemberType_Sequence: + case MemberType_Sequence: addMemberToList(MemberListType_decSequenceMembers,md); addMemberToList(MemberListType_docSequenceMembers,md); break; - case MemberType_Dictionary: + case MemberType_Dictionary: addMemberToList(MemberListType_decDictionaryMembers,md); addMemberToList(MemberListType_docDictionaryMembers,md); break; - case MemberType_Enumeration: + case MemberType_Enumeration: addMemberToList(MemberListType_decEnumMembers,md); addMemberToList(MemberListType_docEnumMembers,md); break; - case MemberType_EnumValue: + case MemberType_EnumValue: break; - case MemberType_Define: + case MemberType_Define: addMemberToList(MemberListType_decDefineMembers,md); addMemberToList(MemberListType_docDefineMembers,md); break; @@ -555,31 +555,23 @@ void NamespaceDefImpl::insertMember(MemberDef *md) Definition *outerScope = getOuterScope(); if (outerScope) { - MemberDef *aliasMd = 0; + std::unique_ptr<MemberDef> aliasMd; if (outerScope->definitionType()==Definition::TypeNamespace) { - aliasMd = createMemberDefAlias(outerScope,md); - dynamic_cast<NamespaceDef*>(outerScope)->insertMember(aliasMd); + aliasMd.reset(createMemberDefAlias(outerScope,md)); + dynamic_cast<NamespaceDef*>(outerScope)->insertMember(aliasMd.get()); } else if (outerScope->definitionType()==Definition::TypeFile) { - aliasMd = createMemberDefAlias(outerScope,md); - dynamic_cast<FileDef*>(outerScope)->insertMember(aliasMd); + aliasMd.reset(createMemberDefAlias(outerScope,md)); + dynamic_cast<FileDef*>(outerScope)->insertMember(aliasMd.get()); } if (aliasMd) { MemberName *mn; QCString name = md->name(); - if ((mn=Doxygen::functionNameSDict->find(name))) - { - mn->append(aliasMd); - } - else - { - mn = new MemberName(name); - mn->append(aliasMd); - Doxygen::functionNameSDict->append(name,mn); - } + mn = Doxygen::functionNameLinkedMap->add(name); + mn->push_back(std::move(aliasMd)); } } } @@ -697,7 +689,7 @@ void NamespaceDefImpl::writeDetailedDescription(OutputList &ol,const QCString &t ol.popGeneratorState(); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - ol.writeAnchor(0,"details"); + ol.writeAnchor(0,"details"); ol.popGeneratorState(); ol.startGroupHeader(); ol.parseText(title); @@ -706,7 +698,8 @@ void NamespaceDefImpl::writeDetailedDescription(OutputList &ol,const QCString &t ol.startTextBlock(); if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) { - ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) && !documentation().isEmpty()) @@ -723,7 +716,8 @@ void NamespaceDefImpl::writeDetailedDescription(OutputList &ol,const QCString &t } if (!documentation().isEmpty()) { - ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); } ol.endTextBlock(); } @@ -734,7 +728,8 @@ void NamespaceDefImpl::writeBriefDescription(OutputList &ol) if (hasBriefDescription()) { DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0, - briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + briefDescription(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (rootNode && !rootNode->isEmpty()) { ol.startParagraph(); @@ -841,7 +836,7 @@ void NamespaceDefImpl::writeMemberGroups(OutputList &ol) MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - if ((!mg->allMembersInSameSection() || !m_subGrouping) + if ((!mg->allMembersInSameSection() || !m_subGrouping) && mg->header()!="[NOHEADER]") { mg->writeDeclarations(ol,0,this,0,0); @@ -849,7 +844,7 @@ void NamespaceDefImpl::writeMemberGroups(OutputList &ol) } } } - + void NamespaceDefImpl::writeAuthorSection(OutputList &ol) { // write Author section (Man only) @@ -978,7 +973,7 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol) addNamespaceAttributes(ol); endTitle(ol,getOutputFileBase(),displayName()); ol.startContents(); - + if (Doxygen::searchIndex) { Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); @@ -997,82 +992,82 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol) { switch (lde->kind()) { - case LayoutDocEntry::BriefDesc: + case LayoutDocEntry::BriefDesc: writeBriefDescription(ol); - break; - case LayoutDocEntry::MemberDeclStart: + break; + case LayoutDocEntry::MemberDeclStart: startMemberDeclarations(ol); - break; - case LayoutDocEntry::NamespaceClasses: + break; + case LayoutDocEntry::NamespaceClasses: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),classSDict); } - break; - case LayoutDocEntry::NamespaceInterfaces: + break; + case LayoutDocEntry::NamespaceInterfaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),interfaceSDict); } - break; - case LayoutDocEntry::NamespaceStructs: + break; + case LayoutDocEntry::NamespaceStructs: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),structSDict); } - break; - case LayoutDocEntry::NamespaceExceptions: + break; + case LayoutDocEntry::NamespaceExceptions: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title(lang),exceptionSDict); } - break; - case LayoutDocEntry::NamespaceNestedNamespaces: + break; + case LayoutDocEntry::NamespaceNestedNamespaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeNamespaceDeclarations(ol,ls->title(lang),false); } - break; + break; case LayoutDocEntry::NamespaceNestedConstantGroups: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeNamespaceDeclarations(ol,ls->title(lang),true); } break; - case LayoutDocEntry::MemberGroups: + case LayoutDocEntry::MemberGroups: writeMemberGroups(ol); - break; - case LayoutDocEntry::MemberDecl: + break; + case LayoutDocEntry::MemberDecl: { LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; writeMemberDeclarations(ol,lmd->type,lmd->title(lang)); } - break; - case LayoutDocEntry::MemberDeclEnd: + break; + case LayoutDocEntry::MemberDeclEnd: endMemberDeclarations(ol); break; - case LayoutDocEntry::DetailedDesc: + case LayoutDocEntry::DetailedDesc: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeDetailedDescription(ol,ls->title(lang)); } break; - case LayoutDocEntry::MemberDefStart: + case LayoutDocEntry::MemberDefStart: startMemberDocumentation(ol); - break; + break; case LayoutDocEntry::NamespaceInlineClasses: writeInlineClasses(ol); break; - case LayoutDocEntry::MemberDef: + case LayoutDocEntry::MemberDef: { LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; writeMemberDocumentation(ol,lmd->type,lmd->title(lang)); } break; - case LayoutDocEntry::MemberDefEnd: + case LayoutDocEntry::MemberDefEnd: endMemberDocumentation(ol); break; - case LayoutDocEntry::AuthorSection: + case LayoutDocEntry::AuthorSection: writeAuthorSection(ol); break; case LayoutDocEntry::ClassIncludes: @@ -1090,16 +1085,16 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol) case LayoutDocEntry::FileConstantGroups: case LayoutDocEntry::FileIncludes: case LayoutDocEntry::FileIncludeGraph: - case LayoutDocEntry::FileIncludedByGraph: + case LayoutDocEntry::FileIncludedByGraph: case LayoutDocEntry::FileSourceLink: case LayoutDocEntry::FileInlineClasses: - case LayoutDocEntry::GroupClasses: - case LayoutDocEntry::GroupInlineClasses: + case LayoutDocEntry::GroupClasses: + case LayoutDocEntry::GroupInlineClasses: case LayoutDocEntry::GroupNamespaces: - case LayoutDocEntry::GroupDirs: - case LayoutDocEntry::GroupNestedGroups: + case LayoutDocEntry::GroupDirs: + case LayoutDocEntry::GroupNestedGroups: case LayoutDocEntry::GroupFiles: - case LayoutDocEntry::GroupGraph: + case LayoutDocEntry::GroupGraph: case LayoutDocEntry::GroupPageDocs: case LayoutDocEntry::DirSubDirs: case LayoutDocEntry::DirFiles: @@ -1224,10 +1219,10 @@ void NamespaceDefImpl::addUsingDirective(const NamespaceDef *nd) //printf("%p: NamespaceDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); } -const NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const -{ +const NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const +{ //printf("%p: NamespaceDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); - return usingDirList; + return usingDirList; } void NamespaceDefImpl::addUsingDeclaration(const Definition *d) @@ -1269,11 +1264,11 @@ void NamespaceDefImpl::addListReferences() { //bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); { - const std::vector<ListItemInfo> &xrefItems = xrefListItems(); + const RefItemVector &xrefItems = xrefListItems(); addRefItem(xrefItems, qualifiedName(), - getLanguage()==SrcLangExt_Fortran ? - theTranslator->trModule(TRUE,TRUE) : + getLanguage()==SrcLangExt_Fortran ? + theTranslator->trModule(TRUE,TRUE) : theTranslator->trNamespace(TRUE,TRUE), getOutputFileBase(),displayName(), 0, @@ -1307,7 +1302,7 @@ QCString NamespaceDefImpl::displayName(bool includeScope) const result = substitute(result,"::",sep); } //printf("NamespaceDefImpl::displayName() %s->%s lang=%d\n",name().data(),result.data(),lang); - return result; + return result; } QCString NamespaceDefImpl::localName() const @@ -1378,12 +1373,12 @@ bool NamespaceSDict::declVisible() const void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title, bool const isConstantGroup,bool localName) { - + if (count()==0) return; // no namespaces in the list if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) return; - + SDict<NamespaceDef>::Iterator ni(*this); NamespaceDef *nd; @@ -1448,7 +1443,8 @@ void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title, if (!nd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC)) { ol.startMemberDescription(nd->getOutputFileBase()); - ol.generateDoc(nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription(),FALSE,FALSE,0,TRUE); + ol.generateDoc(nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription(),FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberDescription(); } ol.endMemberDeclaration(0,0); @@ -1487,7 +1483,7 @@ void NamespaceDefImpl::addMemberToList(MemberListType lt,MemberDef *md) if (ml->listType()&MemberListType_declarationLists) { - md->setSectionList(ml); + md->setSectionList(this,ml); } } diff --git a/src/namespacedef.h b/src/namespacedef.h index 3be54f2..a35f0b1 100644 --- a/src/namespacedef.h +++ b/src/namespacedef.h @@ -146,7 +146,7 @@ class NamespaceListIterator : public QListIterator<NamespaceDef> class NamespaceDict : public QDict<NamespaceDef> { public: - NamespaceDict(int size) : QDict<NamespaceDef>(size) {} + NamespaceDict(uint size) : QDict<NamespaceDef>(size) {} ~NamespaceDict() {} }; @@ -154,7 +154,7 @@ class NamespaceDict : public QDict<NamespaceDef> class NamespaceSDict : public SDict<NamespaceDef> { public: - NamespaceSDict(int size=17) : SDict<NamespaceDef>(size) {} + NamespaceSDict(uint size=17) : SDict<NamespaceDef>(size) {} ~NamespaceSDict() {} void writeDeclaration(OutputList &ol,const char *title, bool isConstantGroup=false, bool localName=FALSE); diff --git a/src/objcache.cpp b/src/objcache.cpp deleted file mode 100644 index a5180d6..0000000 --- a/src/objcache.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#include <stdio.h> -#include <assert.h> -#include <qglobal.h> -#include "objcache.h" -#if !defined(_OS_WIN32_) || defined(__MINGW32__) -#include <stdint.h> -#endif - -//---------------------------------------------------------------------- - -ObjCache::ObjCache(unsigned int logSize) - : m_head(-1), m_tail(-1), //m_numEntries(0), - m_size(1<<logSize), m_count(0), m_freeHashNodes(0), m_freeCacheNodes(0), - m_lastHandle(-1) -{ - int i; - m_cache = new CacheNode[m_size]; - m_hash = new HashNode[m_size]; - // add all items to list of free buckets - for (i=0;i<m_size-1;i++) - { - m_hash[i].nextHash = i+1; - m_cache[i].next = i+1; - } - m_misses = 0; - m_hits = 0; -} - -ObjCache::~ObjCache() -{ - delete[] m_cache; - delete[] m_hash; -} - -int ObjCache::add(void *obj,void **victim) -{ - *victim=0; - - HashNode *hnode = hashFind(obj); - //printf("hnode=%p\n",hnode); - if (hnode) // move object to the front of the LRU list, since it is used - // most recently - { - //printf("moveToFront=%d\n",hnode->index); - moveToFront(hnode->index); - m_hits++; - } - else // object not in the cache. - { - void *lruObj=0; - if (m_freeCacheNodes!=-1) // cache not full -> add element to the cache - { - // remove element from free list - int index = m_freeCacheNodes; - m_freeCacheNodes = m_cache[index].next; - - // add to head of the list - if (m_tail==-1) - { - m_tail = index; - } - m_cache[index].prev = -1; - m_cache[index].next = m_head; - if (m_head!=-1) - { - m_cache[m_head].prev = index; - } - m_head = index; - m_count++; - } - else // cache full -> replace element in the cache - { - //printf("Cache full!\n"); - lruObj = m_cache[m_tail].obj; - hashRemove(lruObj); - moveToFront(m_tail); // m_tail indexes the emptied element, which becomes m_head - } - //printf("numEntries=%d size=%d\n",m_numEntries,m_size); - m_cache[m_head].obj = obj; - hnode = hashInsert(obj); - hnode->index = m_head; - *victim = lruObj; - m_misses++; - } - return m_head; -} - -void ObjCache::del(int index) -{ - assert(index!=-1); - assert(m_cache[index].obj!=0); - hashRemove(m_cache[index].obj); - moveToFront(index); - m_head = m_cache[index].next; - if (m_head==-1) - m_tail=-1; - else - m_cache[m_head].prev=-1; - m_cache[index].obj=0; - m_cache[index].prev=-1; - m_cache[index].next = m_freeCacheNodes; - m_freeCacheNodes = index; - m_count--; -} - -#ifdef CACHE_DEBUG -#define cache_debug_printf printf -void ObjCache::printLRU() -{ - cache_debug_printf("MRU->LRU: "); - int index = m_head; - while (index!=-1) - { - cache_debug_printf("%d=%p ",index,m_cache[index].obj); - index = m_cache[index].next; - } - cache_debug_printf("\n"); - - cache_debug_printf("LRU->MRU: "); - index = m_tail; - while (index!=-1) - { - cache_debug_printf("%d=%p ",index,m_cache[index].obj); - index = m_cache[index].prev; - } - cache_debug_printf("\n"); -} -#endif - -#ifdef CACHE_STATS -#define cache_stats_printf printf -void ObjCache::printStats() -{ - cache_stats_printf("ObjCache: hits=%d misses=%d hit ratio=%f\n",m_hits,m_misses,m_hits*100.0/(m_hits+m_misses)); -} -#endif - -void ObjCache::moveToFront(int index) -{ - int prev,next; - if (m_head!=index) - { - next = m_cache[index].next; - prev = m_cache[index].prev; - - // de-chain node at index - m_cache[prev].next = next; - if (next!=-1) m_cache[next].prev = prev; else m_tail = prev; - - // add to head - m_cache[index].prev = -1; - m_cache[index].next = m_head; - m_cache[m_head].prev = index; - m_head = index; - } -} - -unsigned int ObjCache::hash(void *addr) -{ - static bool isPtr64 = sizeof(addr)==8; - if (isPtr64) - { - uint64 key = (uint64)addr; - // Thomas Wang's 64 bit Mix Function - key += ~(key << 32); - key ^= (key >> 22); - key += ~(key << 13); - key ^= (key >> 8); - key += (key << 3); - key ^= (key >> 15); - key += ~(key << 27); - key ^= (key >> 31); - return (unsigned int)(key & (m_size-1)); - } - else - { - // Thomas Wang's 32 bit Mix Function - uintptr_t key = (uintptr_t)addr; - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return (unsigned int)(key & (m_size-1)); - } -} - -ObjCache::HashNode *ObjCache::hashFind(void *obj) -{ - HashNode *node = 0; - int index = m_hash[hash(obj)].head; - //printf("hashFind: obj=%p index=%d\n",obj,index); - while (index!=-1 && - m_hash[index].obj!=obj - ) // search for right object in the list - { - index = m_hash[index].nextHash; - } - // found the obj at index, so it is in the cache! - if (index!=-1) - { - node = &m_hash[index]; - } - return node; -} - -ObjCache::HashNode *ObjCache::hashInsert(void *obj) -{ - int index = hash(obj); - //printf("Inserting %p index=%d\n",obj,index); - - // remove element from empty list - int newElement = m_freeHashNodes; - assert(newElement!=-1); - m_freeHashNodes = m_hash[m_freeHashNodes].nextHash; - - if (m_hash[index].head!=-1) // hash collision -> goto end of the list - { - index = m_hash[index].head; - while (m_hash[index].nextHash!=-1) - { - index = m_hash[index].nextHash; - } - // add to end of the list - m_hash[index].nextHash = newElement; - } - else // first element in the hash list - { - m_hash[index].head = newElement; - } - // add to the end of the list - m_hash[newElement].nextHash = -1; - m_hash[newElement].obj = obj; - return &m_hash[newElement]; -} - -void ObjCache::hashRemove(void *obj) -{ - int index = hash(obj); - - // find element - int curIndex = m_hash[index].head; - int prevIndex=-1; - while (m_hash[curIndex].obj!=obj) - { - prevIndex = curIndex; - curIndex = m_hash[curIndex].nextHash; - } - - if (prevIndex==-1) // remove from start - { - m_hash[index].head = m_hash[curIndex].nextHash; - } - else // remove in the middle - { - m_hash[prevIndex].nextHash = m_hash[curIndex].nextHash; - } - - // add curIndex element to empty list - m_hash[curIndex].nextHash = m_freeHashNodes; - m_hash[curIndex].index = -1; - m_hash[curIndex].obj = 0; - m_freeHashNodes = curIndex; -} - -#ifdef CACHE_TEST -int main() -{ - int i; - struct obj - { - obj() : handle(-1) {} - int handle; - }; - obj *objs = new obj[100]; - ObjCache c(3); - for (i=0;i<32;i++) - { - int objId=(i%3)+(i>>2)*4; - printf("------- use(%d=%p)--------\n",objId,&objs[objId]); -#ifdef CACHE_DEBUG - c.printLRU(); -#endif - obj *victim=0; - if (objs[objId].handle==-1) - { - objs[objId].handle = c.add(&objs[objId],(void**)&victim); - if (victim) victim->handle=-1; - } - else - { - c.use(objs[objId].handle); - } - printf("i=%d objId=%d using %p victim=%p\n",i,objId,&objs[objId],victim); - } - for (i=0;i<100;i++) - { - if (objs[i].handle!=-1) - { - printf("------ del objId=%d handle=%d ------\n",i,objs[i].handle); - c.del(objs[i].handle); - objs[i].handle=-1; -#ifdef CACHE_DEBUG - c.printLRU(); -#endif - } - } - c.printStats(); - return 0; -} -#endif diff --git a/src/objcache.h b/src/objcache.h deleted file mode 100644 index 224b34b..0000000 --- a/src/objcache.h +++ /dev/null @@ -1,127 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#ifndef OBJCACHE_H -#define OBJCACHE_H - -//#define CACHE_TEST -//#define CACHE_DEBUG -#define CACHE_STATS - -/** @brief Cache for objects. - * - * This cache is used to decide which objects should remain in - * memory. It uses a least recently used policy (LRU) to decide - * which object should make room for a new object when the cache - * is full. An object should be added using add(), and then use() - * should be called when the object is used. - */ -class ObjCache -{ - private: - struct CacheNode - { - CacheNode() : next(-1), prev(-1), obj(0) {} - int next; - int prev; - void *obj; - }; - struct HashNode - { - HashNode() : head(-1), nextHash(-1), index(-1), obj(0) {} - int head; - int nextHash; - int index; - void *obj; - }; - - public: - /*! Creates the cache. The number of elements in the cache is 2 to - * the power of \a logSize. - */ - ObjCache(unsigned int logSize); - - /*! Deletes the cache and free all internal data-structures used. */ - ~ObjCache(); - - /*! Adds \a obj to the cache. When victim is not null, this object is - * removed from the cache to make room for \a obj. - * Returns a handle to the object, which can be used by the use() - * function, each time the object is used. - */ - int add(void *obj,void **victim); - - /*! Indicates that this object is used. This will move the object - * to the front of the internal LRU list to make sure it is removed last. - * The parameter \a handle is returned when called add(). - */ - void use(int handle) - { - if (handle==m_lastHandle) return; - m_lastHandle = handle; - m_hits++; - moveToFront(handle); - } - - /*! Removes the item identified by \a handle from the cache. - * @see add() - */ - void del(int handle); - - /*! Debug function. Prints the LRU list */ - void printLRU(); - /*! Print miss/hits statistics */ - void printStats(); - - /*! total size of the cache */ - int size() const { return m_size; } - - /*! number of elements in the cache */ - int count() const { return m_count; } - - int hits() const - { - return m_hits; - } - int misses() const - { - return m_misses; - } - - - private: - void moveToFront(int index); - unsigned int hash(void *addr); - HashNode *hashFind(void *obj); - HashNode *hashInsert(void *obj); - void hashRemove(void *obj); - - CacheNode *m_cache; - HashNode *m_hash; - int m_head; - int m_tail; - int m_size; - int m_count; - int m_freeHashNodes; - int m_freeCacheNodes; - int m_lastHandle; - int m_misses; - int m_hits; -}; - -#endif // OBJCACHE_H - diff --git a/src/outputgen.h b/src/outputgen.h index 576e950..009225f 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -150,7 +150,7 @@ class BaseOutputDocInterface : public CodeOutputInterface Examples }; - virtual void parseText(const QCString &s) {} + virtual void parseText(const QCString &) {} /*! Start of a bullet list: e.g. \c \<ul\> in html. startItemListItem() is * Used for the bullet items. @@ -290,8 +290,8 @@ class BaseOutputDocInterface : public CodeOutputInterface virtual void endTitle() = 0; virtual void writeAnchor(const char *fileName,const char *name) = 0; - virtual void startSection(const char *,const char *,SectionInfo::SectionType) = 0; - virtual void endSection(const char *,SectionInfo::SectionType) = 0; + virtual void startSection(const char *,const char *,SectionType) = 0; + virtual void endSection(const char *,SectionType) = 0; virtual void lineBreak(const char *style) = 0; virtual void addIndexItem(const char *s1,const char *s2) = 0; @@ -447,8 +447,8 @@ class OutputGenerator : public BaseOutputDocInterface virtual void writeSummaryLink(const char *file,const char *anchor,const char *title,bool first) = 0; virtual void startContents() = 0; virtual void endContents() = 0; - virtual void startPageDoc(const char *pageTitle) {}; - virtual void endPageDoc() {}; + virtual void startPageDoc(const char *) {} + virtual void endPageDoc() {} virtual void startTextBlock(bool) = 0; virtual void endTextBlock(bool) = 0; virtual void lastIndexPage() = 0; diff --git a/src/outputlist.cpp b/src/outputlist.cpp index c47c1c9..e942465 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -33,7 +33,6 @@ OutputList::OutputList(bool) { //printf("OutputList::OutputList()\n"); - m_outputs.setAutoDelete(TRUE); } OutputList::~OutputList() @@ -41,16 +40,14 @@ OutputList::~OutputList() //printf("OutputList::~OutputList()\n"); } -void OutputList::add(const OutputGenerator *og) +void OutputList::add(OutputGenerator *og) { - if (og) m_outputs.append(og); + if (og) m_outputs.emplace_back(og); } void OutputList::disableAllBut(OutputGenerator::OutputType o) { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { og->disableIfNot(o); } @@ -58,9 +55,7 @@ void OutputList::disableAllBut(OutputGenerator::OutputType o) void OutputList::enableAll() { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { og->enable(); } @@ -68,9 +63,7 @@ void OutputList::enableAll() void OutputList::disableAll() { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { og->disable(); } @@ -78,9 +71,7 @@ void OutputList::disableAll() void OutputList::disable(OutputGenerator::OutputType o) { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { og->disableIf(o); } @@ -88,9 +79,7 @@ void OutputList::disable(OutputGenerator::OutputType o) void OutputList::enable(OutputGenerator::OutputType o) { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { og->enableIf(o); } @@ -99,9 +88,7 @@ void OutputList::enable(OutputGenerator::OutputType o) bool OutputList::isEnabled(OutputGenerator::OutputType o) { bool result=FALSE; - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { result=result || og->isEnabled(o); } @@ -110,9 +97,7 @@ bool OutputList::isEnabled(OutputGenerator::OutputType o) void OutputList::pushGeneratorState() { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { og->pushGeneratorState(); } @@ -120,9 +105,7 @@ void OutputList::pushGeneratorState() void OutputList::popGeneratorState() { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { og->popGeneratorState(); } @@ -132,14 +115,13 @@ void OutputList::generateDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef * md, const QCString &docStr,bool indexWords, bool isExample,const char *exampleName, - bool singleLine,bool linkFromIndex) + bool singleLine,bool linkFromIndex, + bool markdownSupport) { int count=0; if (docStr.isEmpty()) return; - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { if (og->isEnabled()) count++; } @@ -151,16 +133,14 @@ void OutputList::generateDoc(const char *fileName,int startLine, DocRoot *root=0; root = validatingParseDoc(fileName,startLine, ctx,md,docStr,indexWords,isExample,exampleName, - singleLine,linkFromIndex); + singleLine,linkFromIndex,markdownSupport); if (count>0) writeDoc(root,ctx,md); delete root; } void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md) { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { //printf("og->printDoc(extension=%s)\n", // ctx?ctx->getDefFileExtension().data():"<null>"); @@ -172,9 +152,7 @@ void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *m void OutputList::parseText(const QCString &textStr) { int count=0; - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { if (og->isEnabled()) count++; } @@ -187,7 +165,7 @@ void OutputList::parseText(const QCString &textStr) if (count>0) { - for (it.toFirst();(og=it.current());++it) + for (const auto &og : m_outputs) { if (og->isEnabled()) og->writeDoc(root,0,0); } diff --git a/src/outputlist.h b/src/outputlist.h index cfd3773..9393a59 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,38 +17,22 @@ #define OUTPUTLIST_H #include <utility> -#include <qlist.h> +#include <vector> +#include <memory> + #include "index.h" // for IndexSections #include "outputgen.h" -#define FORALLPROTO1(arg1) \ - void forall(void (OutputGenerator::*func)(arg1),arg1) -#define FORALLPROTO2(arg1,arg2) \ - void forall(void (OutputGenerator::*func)(arg1,arg2),arg1,arg2) -#define FORALLPROTO3(arg1,arg2,arg3) \ - void forall(void (OutputGenerator::*func)(arg1,arg2,arg3),arg1,arg2,arg3) -#define FORALLPROTO4(arg1,arg2,arg3,arg4) \ - void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4),arg1,arg2,arg3,arg4) -#define FORALLPROTO5(arg1,arg2,arg3,arg4,arg5) \ - void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4,arg5),arg1,arg2,arg3,arg4,arg5) -#define FORALLPROTO6(arg1,arg2,arg3,arg4,arg5,arg6) \ - void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4,arg5,arg6),arg1,arg2,arg3,arg4,arg5,arg6) -#define FORALLPROTO7(arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ - void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4,arg5,arg6,arg7),arg1,arg2,arg3,arg4,arg5,arg6,arg7) -#define FORALLPROTO8(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) \ - void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8),arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) - class ClassDiagram; class DotClassGraph; class DotDirDeps; class DotInclDepGraph; class DotGfxHierarchyTable; -class SectionDict; class DotGroupCollaboration; class DocRoot; /** Class representing a list of output generators that are written to - * in parallel. + * in parallel. */ class OutputList : public OutputDocInterface { @@ -58,9 +40,9 @@ class OutputList : public OutputDocInterface OutputList(bool); virtual ~OutputList(); - void add(const OutputGenerator *); - uint count() const { return m_outputs.count(); } - + void add(OutputGenerator *); + uint count() const { return static_cast<uint>(m_outputs.size()); } + void disableAllBut(OutputGenerator::OutputType o); void enableAll(); void disableAll(); @@ -77,8 +59,9 @@ class OutputList : public OutputDocInterface void generateDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef *md,const QCString &docStr, - bool indexWords,bool isExample,const char *exampleName=0, - bool singleLine=FALSE,bool linkFromIndex=FALSE); + bool indexWords,bool isExample,const char *exampleName /*=0*/, + bool singleLine /*=FALSE*/,bool linkFromIndex /*=FALSE*/, + bool markdownSupport /*=FALSE*/); void writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md); void parseText(const QCString &textStr); @@ -92,7 +75,7 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startProjectNumber); } void endProjectNumber() { forall(&OutputGenerator::endProjectNumber); } - void writeStyleInfo(int part) + void writeStyleInfo(int part) { forall(&OutputGenerator::writeStyleInfo,part); } void startFile(const char *name,const char *manName,const char *title) { forall(&OutputGenerator::startFile,name,manName,title); } @@ -100,29 +83,29 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::writeSearchInfo); } void writeFooter(const char *navPath) { forall(&OutputGenerator::writeFooter,navPath); } - void endFile() + void endFile() { forall(&OutputGenerator::endFile); } - void startTitleHead(const char *fileName) + void startTitleHead(const char *fileName) { forall(&OutputGenerator::startTitleHead,fileName); } void endTitleHead(const char *fileName,const char *name) { forall(&OutputGenerator::endTitleHead,fileName,name); } - void startTitle() + void startTitle() { forall(&OutputGenerator::startTitle); } - void endTitle() + void endTitle() { forall(&OutputGenerator::endTitle); } void startParagraph(const char *classDef=0) { forall(&OutputGenerator::startParagraph,classDef); } - void endParagraph() + void endParagraph() { forall(&OutputGenerator::endParagraph); } - void writeString(const char *text) + void writeString(const char *text) { forall(&OutputGenerator::writeString,text); } - void startIndexListItem() + void startIndexListItem() { forall(&OutputGenerator::startIndexListItem); } - void endIndexListItem() + void endIndexListItem() { forall(&OutputGenerator::endIndexListItem); } - void startIndexList() + void startIndexList() { forall(&OutputGenerator::startIndexList); } - void endIndexList() + void endIndexList() { forall(&OutputGenerator::endIndexList); } void startIndexKey() { forall(&OutputGenerator::startIndexKey); } @@ -132,9 +115,9 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startIndexValue,b); } void endIndexValue(const char *name,bool b) { forall(&OutputGenerator::endIndexValue,name,b); } - void startItemList() + void startItemList() { forall(&OutputGenerator::startItemList); } - void endItemList() + void endItemList() { forall(&OutputGenerator::endItemList); } void startIndexItem(const char *ref,const char *file) { forall(&OutputGenerator::startIndexItem,ref,file); } @@ -162,22 +145,22 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startHtmlLink,url); } void endHtmlLink() { forall(&OutputGenerator::endHtmlLink); } - void writeStartAnnoItem(const char *type,const char *file, + void writeStartAnnoItem(const char *type,const char *file, const char *path,const char *name) { forall(&OutputGenerator::writeStartAnnoItem,type,file,path,name); } void writeEndAnnoItem(const char *name) { forall(&OutputGenerator::writeEndAnnoItem,name); } - void startTypewriter() + void startTypewriter() { forall(&OutputGenerator::startTypewriter); } - void endTypewriter() + void endTypewriter() { forall(&OutputGenerator::endTypewriter); } void startGroupHeader(int extraLevels=0) { forall(&OutputGenerator::startGroupHeader,extraLevels); } void endGroupHeader(int extraLevels=0) { forall(&OutputGenerator::endGroupHeader,extraLevels); } - void startItemListItem() + void startItemListItem() { forall(&OutputGenerator::startItemListItem); } - void endItemListItem() + void endItemListItem() { forall(&OutputGenerator::endItemListItem); } void startMemberSections() { forall(&OutputGenerator::startMemberSections); } @@ -195,31 +178,31 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startMemberSubtitle); } void endMemberSubtitle() { forall(&OutputGenerator::endMemberSubtitle); } - void startMemberDocList() + void startMemberDocList() { forall(&OutputGenerator::startMemberDocList); } - void endMemberDocList() + void endMemberDocList() { forall(&OutputGenerator::endMemberDocList); } - void startMemberList() + void startMemberList() { forall(&OutputGenerator::startMemberList); } - void endMemberList() + void endMemberList() { forall(&OutputGenerator::endMemberList); } void startInlineHeader() { forall(&OutputGenerator::startInlineHeader); } void endInlineHeader() { forall(&OutputGenerator::endInlineHeader); } - void startAnonTypeScope(int i1) + void startAnonTypeScope(int i1) { forall(&OutputGenerator::startAnonTypeScope,i1); } - void endAnonTypeScope(int i1) + void endAnonTypeScope(int i1) { forall(&OutputGenerator::endAnonTypeScope,i1); } - void startMemberItem(const char *anchor,int i1,const char *id=0) + void startMemberItem(const char *anchor,int i1,const char *id=0) { forall(&OutputGenerator::startMemberItem,anchor,i1,id); } - void endMemberItem() + void endMemberItem() { forall(&OutputGenerator::endMemberItem); } - void startMemberTemplateParams() + void startMemberTemplateParams() { forall(&OutputGenerator::startMemberTemplateParams); } - void endMemberTemplateParams(const char *anchor,const char *inheritId) + void endMemberTemplateParams(const char *anchor,const char *inheritId) { forall(&OutputGenerator::endMemberTemplateParams,anchor,inheritId); } - void startMemberGroupHeader(bool b) + void startMemberGroupHeader(bool b) { forall(&OutputGenerator::startMemberGroupHeader,b); } void endMemberGroupHeader() { forall(&OutputGenerator::endMemberGroupHeader); } @@ -231,28 +214,28 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startMemberGroup); } void endMemberGroup(bool last) { forall(&OutputGenerator::endMemberGroup,last); } - void insertMemberAlign(bool templ=FALSE) + void insertMemberAlign(bool templ=FALSE) { forall(&OutputGenerator::insertMemberAlign,templ); } - void insertMemberAlignLeft(int typ=0, bool templ=FALSE) + void insertMemberAlignLeft(int typ=0, bool templ=FALSE) { forall(&OutputGenerator::insertMemberAlignLeft,typ,templ); } - void writeRuler() + void writeRuler() { forall(&OutputGenerator::writeRuler); } void writeAnchor(const char *fileName,const char *name) { forall(&OutputGenerator::writeAnchor,fileName,name); } - void startCodeFragment() + void startCodeFragment() { forall(&OutputGenerator::startCodeFragment); } - void endCodeFragment() + void endCodeFragment() { forall(&OutputGenerator::endCodeFragment); } - void startCodeLine(bool hasLineNumbers) + void startCodeLine(bool hasLineNumbers) { forall(&OutputGenerator::startCodeLine,hasLineNumbers); } - void endCodeLine() + void endCodeLine() { forall(&OutputGenerator::endCodeLine); } void writeLineNumber(const char *ref,const char *file,const char *anchor, - int lineNumber) + int lineNumber) { forall(&OutputGenerator::writeLineNumber,ref,file,anchor,lineNumber); } - void startEmphasis() + void startEmphasis() { forall(&OutputGenerator::startEmphasis); } - void endEmphasis() + void endEmphasis() { forall(&OutputGenerator::endEmphasis); } void writeChar(char c) { forall(&OutputGenerator::writeChar,c); } @@ -260,7 +243,7 @@ class OutputList : public OutputDocInterface const char *anchor,const char *title, int memCount,int memTotal,bool showInline) { forall(&OutputGenerator::startMemberDoc,clName,memName,anchor,title,memCount,memTotal,showInline); } - void endMemberDoc(bool hasArgs) + void endMemberDoc(bool hasArgs) { forall(&OutputGenerator::endMemberDoc,hasArgs); } void startDoxyAnchor(const char *fName,const char *manName, const char *anchor, const char *name, @@ -268,45 +251,45 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startDoxyAnchor,fName,manName,anchor,name,args); } void endDoxyAnchor(const char *fn,const char *anchor) { forall(&OutputGenerator::endDoxyAnchor,fn,anchor); } - void writeLatexSpacing() + void writeLatexSpacing() { forall(&OutputGenerator::writeLatexSpacing); } - void startDescription() + void startDescription() { forall(&OutputGenerator::startDescription); } - void endDescription() + void endDescription() { forall(&OutputGenerator::endDescription); } - void startDescItem() + void startDescItem() { forall(&OutputGenerator::startDescItem); } - void endDescItem() + void endDescItem() { forall(&OutputGenerator::endDescItem); } - void startDescForItem() + void startDescForItem() { forall(&OutputGenerator::startDescForItem); } - void endDescForItem() + void endDescForItem() { forall(&OutputGenerator::endDescForItem); } - void startSubsection() + void startSubsection() { forall(&OutputGenerator::startSubsection); } - void endSubsection() + void endSubsection() { forall(&OutputGenerator::endSubsection); } - void startSubsubsection() + void startSubsubsection() { forall(&OutputGenerator::startSubsubsection); } - void endSubsubsection() + void endSubsubsection() { forall(&OutputGenerator::endSubsubsection); } - void startCenter() + void startCenter() { forall(&OutputGenerator::startCenter); } - void endCenter() + void endCenter() { forall(&OutputGenerator::endCenter); } - void startSmall() + void startSmall() { forall(&OutputGenerator::startSmall); } - void endSmall() + void endSmall() { forall(&OutputGenerator::endSmall); } - void lineBreak(const char *style=0) + void lineBreak(const char *style=0) { forall(&OutputGenerator::lineBreak,style); } - void startBold() + void startBold() { forall(&OutputGenerator::startBold); } - void endBold() + void endBold() { forall(&OutputGenerator::endBold); } - void startMemberDescription(const char *anchor,const char *inheritId=0, bool typ = false) + void startMemberDescription(const char *anchor,const char *inheritId=0, bool typ = false) { forall(&OutputGenerator::startMemberDescription,anchor,inheritId, typ); } - void endMemberDescription() + void endMemberDescription() { forall(&OutputGenerator::endMemberDescription); } void startMemberDeclaration() { forall(&OutputGenerator::startMemberDeclaration); } @@ -321,21 +304,21 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startExamples); } void endExamples() { forall(&OutputGenerator::endExamples); } - void startParamList(ParamListTypes t,const char *title) + void startParamList(ParamListTypes t,const char *title) { forall(&OutputGenerator::startParamList,t,title); } - void endParamList() + void endParamList() { forall(&OutputGenerator::endParamList); } - void startIndent() + void startIndent() { forall(&OutputGenerator::startIndent); } - void endIndent() + void endIndent() { forall(&OutputGenerator::endIndent); } - void startSection(const char *lab,const char *title,SectionInfo::SectionType t) + void startSection(const char *lab,const char *title,SectionType t) { forall(&OutputGenerator::startSection,lab,title,t); } - void endSection(const char *lab,SectionInfo::SectionType t) + void endSection(const char *lab,SectionType t) { forall(&OutputGenerator::endSection,lab,t); } void addIndexItem(const char *s1,const char *s2) { forall(&OutputGenerator::addIndexItem,s1,s2); } - void writeSynopsis() + void writeSynopsis() { forall(&OutputGenerator::writeSynopsis); } void startClassDiagram() { forall(&OutputGenerator::startClassDiagram); } @@ -436,11 +419,11 @@ class OutputList : public OutputDocInterface void exceptionEntry(const char* prefix,bool closeBracket) { forall(&OutputGenerator::exceptionEntry,prefix,closeBracket); } - void startConstraintList(const char *header) + void startConstraintList(const char *header) { forall(&OutputGenerator::startConstraintList,header); } - void startConstraintParam() + void startConstraintParam() { forall(&OutputGenerator::startConstraintParam); } - void endConstraintParam() + void endConstraintParam() { forall(&OutputGenerator::endConstraintParam); } void startConstraintType() { forall(&OutputGenerator::startConstraintType); } @@ -470,7 +453,7 @@ class OutputList : public OutputDocInterface void endInlineMemberDoc() { forall(&OutputGenerator::endInlineMemberDoc); } - void startLabels() + void startLabels() { forall(&OutputGenerator::startLabels); } void writeLabel(const char *l,bool isLast) { forall(&OutputGenerator::writeLabel,l,isLast); } @@ -504,16 +487,14 @@ class OutputList : public OutputDocInterface template<typename T,class... Ts,class... As> void forall(void (T::*methodPtr)(Ts...),As&&... args) { - QListIterator<OutputGenerator> li(m_outputs); - OutputGenerator *og; - for (li.toFirst();(og=li.current());++li) + for (const auto &og : m_outputs) { - if (og->isEnabled()) (og->*methodPtr)(std::forward<As>(args)...); + if (og->isEnabled()) (og.get()->*methodPtr)(std::forward<As>(args)...); } } OutputList(const OutputList &ol); - QList<OutputGenerator> m_outputs; + std::vector< std::unique_ptr<OutputGenerator> > m_outputs; }; #endif diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 8b6228f..09152de 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -47,7 +47,7 @@ class PageDefImpl : public DefinitionImpl, public PageDef virtual QCString title() const { return m_title; } virtual GroupDef * getGroupDef() const; virtual PageSDict * getSubPages() const { return m_subPageDict; } - virtual void addInnerCompound(Definition *d); + virtual void addInnerCompound(const Definition *d); virtual bool visibleInIndex() const; virtual bool documentedPage() const; virtual bool hasSubPages() const; @@ -102,18 +102,18 @@ void PageDefImpl::findSectionsInDocumentation() docFindSections(documentation(),this,docFile()); } -GroupDef *PageDefImpl::getGroupDef() const -{ +GroupDef *PageDefImpl::getGroupDef() const +{ GroupList *groups = partOfGroups(); - return groups!=0 ? groups->getFirst() : 0; + return groups!=0 ? groups->getFirst() : 0; } -QCString PageDefImpl::getOutputFileBase() const -{ - if (getGroupDef()) +QCString PageDefImpl::getOutputFileBase() const +{ + if (getGroupDef()) return getGroupDef()->getOutputFileBase(); - else - return m_fileName; + else + return m_fileName; } void PageDefImpl::setFileName(const char *name) @@ -121,10 +121,11 @@ void PageDefImpl::setFileName(const char *name) m_fileName = name; } -void PageDefImpl::addInnerCompound(Definition *def) +void PageDefImpl::addInnerCompound(const Definition *const_def) { - if (def->definitionType()==Definition::TypePage) + if (const_def->definitionType()==Definition::TypePage) { + Definition *def = const_cast<Definition*>(const_def); // uck: fix me PageDef *pd = dynamic_cast<PageDef*>(def); m_subPageDict->append(pd->name(),pd); def->setOuterScope(this); @@ -141,16 +142,14 @@ void PageDefImpl::addInnerCompound(Definition *def) bool PageDefImpl::hasParentPage() const { - return getOuterScope() && + return getOuterScope() && getOuterScope()->definitionType()==Definition::TypePage; } void PageDefImpl::writeTagFile(FTextStream &tagFile) { bool found = name()=="citelist"; - QDictIterator<RefList> rli(*Doxygen::xrefLists); - RefList *rl; - for (rli.toFirst();(rl=rli.current()) && !found;++rli) + for (RefListManager::Ptr &rl : RefListManager::instance()) { if (rl->listName()==name()) { @@ -163,7 +162,7 @@ void PageDefImpl::writeTagFile(FTextStream &tagFile) tagFile << " <compound kind=\"page\">" << endl; tagFile << " <name>" << name() << "</name>" << endl; tagFile << " <title>" << convertToXML(title()) << "</title>" << endl; - tagFile << " <filename>" << convertToXML(getOutputFileBase()) << "</filename>" << endl; + tagFile << " <filename>" << convertToXML(getOutputFileBase())<< Doxygen::htmlFileExtension << "</filename>" << endl; writeDocAnchorsToTagFile(tagFile); tagFile << " </compound>" << endl; } @@ -181,9 +180,9 @@ void PageDefImpl::writeDocumentation(OutputList &ol) //printf("PageDefImpl::writeDocumentation: %s\n",getOutputFileBase().data()); ol.pushGeneratorState(); - //1.{ + //1.{ - if (m_nestingLevel>0 + if (m_nestingLevel>0 //&& // a sub page //(Doxygen::mainPage==0 || getOuterScope()!=Doxygen::mainPage) // and not a subpage of the mainpage ) @@ -196,14 +195,14 @@ void PageDefImpl::writeDocumentation(OutputList &ol) } ol.pushGeneratorState(); - //2.{ + //2.{ ol.disableAllBut(OutputGenerator::Man); startFile(ol,getOutputFileBase(),manPageName,title(),HLI_Pages,!generateTreeView); ol.enableAll(); ol.disable(OutputGenerator::Man); startFile(ol,getOutputFileBase(),pageName,title(),HLI_Pages,!generateTreeView); ol.popGeneratorState(); - //2.} + //2.} if (!generateTreeView) { @@ -213,7 +212,7 @@ void PageDefImpl::writeDocumentation(OutputList &ol) } ol.endQuickIndices(); } - SectionInfo *si=Doxygen::sectionDict->find(name()); + const SectionInfo *si=SectionManager::instance().find(name()); // save old generator state and write title only to Man generator ol.pushGeneratorState(); @@ -228,10 +227,11 @@ void PageDefImpl::writeDocumentation(OutputList &ol) ol.writeString(" - "); ol.popGeneratorState(); - if (si->title != manPageName) + if (si->title() != manPageName) { - ol.generateDoc(docFile(),docLine(),this,0,si->title,TRUE,FALSE,0,TRUE,FALSE); - ol.endSection(si->label,si->type); + ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); + ol.endSection(si->label(),si->type()); } } ol.popGeneratorState(); @@ -246,10 +246,11 @@ void PageDefImpl::writeDocumentation(OutputList &ol) ol.disable(OutputGenerator::Man); if (hasTitle() && !name().isEmpty() && si!=0) { - ol.startPageDoc(si->title); + ol.startPageDoc(si->title()); //ol.startSection(si->label,si->title,si->type); startTitle(ol,getOutputFileBase(),this); - ol.generateDoc(docFile(),docLine(),this,0,si->title,TRUE,FALSE,0,TRUE,FALSE); + ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); //stringToSearchIndex(getOutputFileBase(), // theTranslator->trPage(TRUE,TRUE)+" "+si->title, // si->title); @@ -288,16 +289,9 @@ void PageDefImpl::writeDocumentation(OutputList &ol) void PageDefImpl::writePageDocumentation(OutputList &ol) { - - bool markdownEnabled = Doxygen::markdownSupport; - if (getLanguage()==SrcLangExt_Markdown) - { - Doxygen::markdownSupport = TRUE; - } - ol.startTextBlock(); QCString docStr = documentation()+inbodyDocumentation(); - if (hasBriefDescription() && !Doxygen::sectionDict->find(name())) + if (hasBriefDescription() && !SectionManager::instance().find(name())) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Man); @@ -311,12 +305,14 @@ void PageDefImpl::writePageDocumentation(OutputList &ol) 0, // memberdef docStr, // docStr TRUE, // index words - FALSE // not an example + FALSE, // not an example + 0, // exampleName + FALSE, // singleLine + FALSE, // linkFromIndex + TRUE // markdown support ); ol.endTextBlock(); - Doxygen::markdownSupport = markdownEnabled; - if (hasSubPages()) { // for printed documentation we write subpages as section's of the @@ -331,14 +327,14 @@ void PageDefImpl::writePageDocumentation(OutputList &ol) PageDef *subPage=pdi.toFirst(); for (pdi.toFirst();(subPage=pdi.current());++pdi) { - SectionInfo::SectionType sectionType = SectionInfo::Paragraph; + SectionType sectionType = SectionType::Paragraph; switch (m_nestingLevel) { - case 0: sectionType = SectionInfo::Page; break; - case 1: sectionType = SectionInfo::Section; break; - case 2: sectionType = SectionInfo::Subsection; break; - case 3: sectionType = SectionInfo::Subsubsection; break; - default: sectionType = SectionInfo::Paragraph; break; + case 0: sectionType = SectionType::Page; break; + case 1: sectionType = SectionType::Section; break; + case 2: sectionType = SectionType::Subsection; break; + case 3: sectionType = SectionType::Subsubsection; break; + default: sectionType = SectionType::Paragraph; break; } QCString title = subPage->title(); if (title.isEmpty()) title = subPage->name(); @@ -358,16 +354,16 @@ bool PageDefImpl::visibleInIndex() const { static bool externalPages = Config_getBool(EXTERNAL_PAGES); return // not part of a group - !getGroupDef() && + !getGroupDef() && // not an externally defined page - (!isReference() || externalPages) + (!isReference() || externalPages) ; } bool PageDefImpl::documentedPage() const { return // not part of a group - !getGroupDef() && + !getGroupDef() && // not an externally defined page !isReference(); } diff --git a/src/pagedef.h b/src/pagedef.h index f0b68d1..e4d0268 100644 --- a/src/pagedef.h +++ b/src/pagedef.h @@ -46,22 +46,22 @@ class PageDef : virtual public Definition virtual QCString title() const = 0; virtual GroupDef * getGroupDef() const = 0; virtual PageSDict * getSubPages() const = 0; - virtual void addInnerCompound(Definition *d) = 0; + virtual void addInnerCompound(const Definition *) = 0; virtual bool visibleInIndex() const = 0; virtual bool documentedPage() const = 0; virtual bool hasSubPages() const = 0; virtual bool hasParentPage() const = 0; virtual bool hasTitle() const = 0; virtual LocalToc localToc() const = 0; - virtual void setPageScope(Definition *d) = 0; + virtual void setPageScope(Definition *) = 0; virtual Definition *getPageScope() const = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual bool showLineNo() const = 0; - virtual void writeDocumentation(OutputList &ol) = 0; + virtual void writeDocumentation(OutputList &) = 0; virtual void writeTagFile(FTextStream &) = 0; - virtual void setNestingLevel(int l) = 0; - virtual void writePageDocumentation(OutputList &ol) = 0; + virtual void setNestingLevel(int) = 0; + virtual void writePageDocumentation(OutputList &) = 0; }; @@ -70,7 +70,7 @@ PageDef *createPageDef(const char *f,int l,const char *n,const char *d,const cha class PageSDict : public SDict<PageDef> { public: - PageSDict(int size) : SDict<PageDef>(size) {} + PageSDict(uint size) : SDict<PageDef>(size) {} virtual ~PageSDict() {} private: int compareValues(const PageDef *i1,const PageDef *i2) const diff --git a/src/parserintf.h b/src/parserintf.h index 5095a1e..911b707 100644 --- a/src/parserintf.h +++ b/src/parserintf.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -20,22 +20,25 @@ #include <qstrlist.h> +#include <functional> #include <memory> #include <map> #include <string> #include "types.h" +#include "containers.h" class Entry; class FileDef; class CodeOutputInterface; class MemberDef; class Definition; +class ClangTUParser; /** \brief Abstract interface for outline parsers. * * By implementing the methods of this interface one can add - * a new language parser to doxygen. The parser implementation can make use of the + * a new language parser to doxygen. The parser implementation can make use of the * comment block parser to parse the contents of special comment blocks. */ class OutlineParserInterface @@ -43,36 +46,18 @@ class OutlineParserInterface public: virtual ~OutlineParserInterface() {} - /** Starts processing a translation unit (source files + headers). - * After this call parseInput() is called with sameTranslationUnit - * set to FALSE. If parseInput() returns additional include files, - * these are also processed using parseInput() with - * sameTranslationUnit set to TRUE. After that - * finishTranslationUnit() is called. - */ - virtual void startTranslationUnit(const char *fileName) = 0; - - /** Called after all files in a translation unit have been - * processed. - */ - virtual void finishTranslationUnit() = 0; - - /** Parses a single input file with the goal to build an Entry tree. + /** Parses a single input file with the goal to build an Entry tree. * @param[in] fileName The full name of the file. * @param[in] fileBuf The contents of the file (zero terminated). - * @param[in,out] root The root of the tree of Entry *nodes + * @param[in,out] root The root of the tree of Entry *nodes * representing the information extracted from the file. - * @param[in] sameTranslationUnit TRUE if this file was found in the same - * translation unit (in the filesInSameTranslationUnit list - * returned for another file). - * @param[in,out] filesInSameTranslationUnit other files expected to be - * found in the same translation unit (used for libclang) + * @param[in] clangParser The clang translation unit parser object + * or nullptr if disabled. */ virtual void parseInput(const char *fileName, const char *fileBuf, const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList &filesInSameTranslationUnit) = 0; + ClangTUParser *clangParser) = 0; /** Returns TRUE if the language identified by \a extension needs * the C preprocessor to be run before feed the result to the input @@ -80,7 +65,7 @@ class OutlineParserInterface * @see parseInput() */ virtual bool needsPreprocessing(const QCString &extension) const = 0; - + /** Callback function called by the comment block scanner. * It provides a string \a text containing the prototype of a function * or variable. The parser should parse this and store the information @@ -110,14 +95,14 @@ class CodeParserInterface * @param[in] input Actual code in the form of a string * @param[in] isExampleBlock TRUE iff the code is part of an example. * @param[in] exampleName Name of the example. - * @param[in] fileDef File definition to which the code + * @param[in] fileDef File definition to which the code * is associated. - * @param[in] startLine Starting line in case of a code fragment. + * @param[in] startLine Starting line in case of a code fragment. * @param[in] endLine Ending line of the code fragment. - * @param[in] inlineFragment Code fragment that is to be shown inline + * @param[in] inlineFragment Code fragment that is to be shown inline * as part of the documentation. * @param[in] memberDef Member definition to which the code - * is associated (non null in case of an inline fragment + * is associated (non null in case of an inline fragment * for a member). * @param[in] showLineNumbers if set to TRUE and also fileDef is not 0, * line numbers will be added to the source fragment @@ -151,46 +136,50 @@ class CodeParserInterface //----------------------------------------------------------------------------- +using OutlineParserFactory = std::function<std::unique_ptr<OutlineParserInterface>()>; + /** \brief Manages programming language parsers. * - * This class manages the language parsers in the system. One can + * This class manages the language parsers in the system. One can * register parsers, and obtain a parser given a file extension. */ class ParserManager { public: + struct ParserPair { - ParserPair(std::unique_ptr<OutlineParserInterface> oli, - std::unique_ptr<CodeParserInterface> cpi) - : outlineParser(std::move(oli)), codeParser(std::move(cpi)) + ParserPair(OutlineParserFactory opf, std::unique_ptr<CodeParserInterface> cpi) + : outlineParserFactory(opf), codeParserInterface(std::move(cpi)) { } - std::unique_ptr<OutlineParserInterface> outlineParser; - std::unique_ptr<CodeParserInterface> codeParser; + OutlineParserFactory outlineParserFactory; + std::unique_ptr<CodeParserInterface> codeParserInterface; }; - ParserManager(std::unique_ptr<OutlineParserInterface> outlineParser, - std::unique_ptr<CodeParserInterface> codeParser) - : m_defaultParsers(std::move(outlineParser),std::move(codeParser)) + ParserManager(OutlineParserFactory outlineParserFactory, + std::unique_ptr<CodeParserInterface> codeParserInterface) + : m_defaultParsers(outlineParserFactory,std::move(codeParserInterface)) { } /** Registers an additional parser. - * @param[in] name A symbolic name of the parser, i.e. "c", - * "python", "fortran", "vhdl", ... - * @param[in] parser The parser that is to be used for the - * given name. + * @param[in] name A symbolic name of the parser, i.e. "c", + * "python", "fortran", "vhdl", ... + * @param[in] outlineParser The language parser (scanner) that is to be used for the + * given name. + * @param[in] codeParser The code parser that is to be used for the + * given name. */ - void registerParser(const char *name,std::unique_ptr<OutlineParserInterface> outlineParser, - std::unique_ptr<CodeParserInterface> codeParser) + void registerParser(const char *name,OutlineParserFactory outlineParserFactory, + std::unique_ptr<CodeParserInterface> codeParserInterface) { m_parsers.emplace(std::string(name), - ParserPair(std::move(outlineParser),std::move(codeParser))); + ParserPair(outlineParserFactory,std::move(codeParserInterface))); } - /** Registers a file \a extension with a parser with name \a parserName. + /** Registers a file \a extension with a parser with name \a parserName. * Returns TRUE if the extension was successfully registered. */ bool registerExtension(const char *extension, const char *parserName) @@ -210,21 +199,21 @@ class ParserManager } /** Gets the interface to the parser associated with given \a extension. - * If there is no parser explicitly registered for the supplied extension, + * If there is no parser explicitly registered for the supplied extension, * the interface to the default parser will be returned. */ - OutlineParserInterface &getOutlineParser(const char *extension) + std::unique_ptr<OutlineParserInterface> getOutlineParser(const char *extension) { - return *getParsers(extension).outlineParser; + return getParsers(extension).outlineParserFactory(); } /** Gets the interface to the parser associated with given \a extension. - * If there is no parser explicitly registered for the supplied extension, + * If there is no parser explicitly registered for the supplied extension, * the interface to the default parser will be returned. */ CodeParserInterface &getCodeParser(const char *extension) { - return *getParsers(extension).codeParser; + return *getParsers(extension).codeParserInterface; } private: diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index 7da71ce..eceff59 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -92,7 +92,7 @@ void PerlModOutputStream::add(int n) if (m_t != 0) (*m_t) << n; else - m_s += n; + m_s += QCString().setNum(n); } void PerlModOutputStream::add(unsigned int n) @@ -100,7 +100,7 @@ void PerlModOutputStream::add(unsigned int n) if (m_t != 0) (*m_t) << n; else - m_s += n; + m_s += QCString().setNum(n); } class PerlModOutput @@ -171,10 +171,10 @@ public: inline PerlModOutput &closeHash() { close('}'); return *this; } protected: - + void iopenSave(); void icloseSave(QCString &); - + void incIndent(); void decIndent(); @@ -187,7 +187,7 @@ protected: void iclose(char); private: - + PerlModOutputStream *m_stream; int m_indentation; bool m_blockstart; @@ -226,7 +226,7 @@ void PerlModOutput::decIndent() m_spaces[m_indentation * 2] = 0; } -void PerlModOutput::iaddQuoted(const char *s) +void PerlModOutput::iaddQuoted(const char *s) { char c; while ((c = *s++) != 0) { @@ -235,7 +235,7 @@ void PerlModOutput::iaddQuoted(const char *s) m_stream->add(c); } } - + void PerlModOutput::iaddField(const char *s) { continueBlock(); @@ -276,10 +276,10 @@ void PerlModOutput::iopen(char c, const char *s) void PerlModOutput::iclose(char c) { - decIndent(); + decIndent(); indent(); if (c != 0) - m_stream->add(c); + m_stream->add(c); m_blockstart = false; } @@ -291,11 +291,11 @@ public: virtual ~PerlModDocVisitor() { } void finish(); - + //-------------------------------------- // visitor functions for leaf nodes //-------------------------------------- - + void visit(DocWord *); void visit(DocLinkedWord *); void visit(DocWhiteSpace *); @@ -317,7 +317,7 @@ public: //-------------------------------------- // visitor functions for compound nodes //-------------------------------------- - + void visitPre(DocAutoList *); void visitPost(DocAutoList *); void visitPre(DocAutoListItem *); @@ -405,7 +405,7 @@ private: void addLink(const QCString &ref, const QCString &file, const QCString &anchor); - + void enterText(); void leaveText(); @@ -653,7 +653,7 @@ void PerlModDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Preformatted: style = "preformatted"; break; case DocStyleChange::Div: style = "div"; break; case DocStyleChange::Span: style = "span"; break; - + } openItem("style"); m_output.addFieldQuotedString("style", style) @@ -712,12 +712,12 @@ void PerlModDocVisitor::visit(DocInclude *inc) { case DocInclude::IncWithLines: #if 0 - { + { m_t << "<div class=\"fragment\"><pre>"; QFileInfo cfi( inc->file() ); FileDef fd( cfi.dirPath(), cfi.fileName() ); parseCode(m_ci,inc->context(),inc->text().latin1(),inc->isExample(),inc->exampleFile(), &fd); - m_t << "</pre></div>"; + m_t << "</pre></div>"; } break; #endif @@ -733,11 +733,15 @@ void PerlModDocVisitor::visit(DocInclude *inc) case DocInclude::DontIncWithLines: return; case DocInclude::HtmlInclude: type = "htmlonly"; break; case DocInclude::LatexInclude: type = "latexonly"; break; + case DocInclude::RtfInclude: type = "rtfonly"; break; + case DocInclude::ManInclude: type = "manonly"; break; + case DocInclude::XmlInclude: type = "xmlonly"; break; + case DocInclude::DocbookInclude: type = "docbookonly"; break; case DocInclude::VerbInclude: type = "preformatted"; break; case DocInclude::Snippet: return; case DocInclude::SnipWithLines: return; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -760,7 +764,7 @@ void PerlModDocVisitor::visit(DocIncOperator *) { parseCode(m_ci,op->context(),op->text(),FALSE,0); } - if (op->isLast()) + if (op->isLast()) { m_output.add("</programlisting>"); } @@ -775,7 +779,7 @@ void PerlModDocVisitor::visit(DocFormula *f) { openItem("formula"); QCString id; - id += f->id(); + id += QCString().setNum(f->id()); m_output.addFieldQuotedString("id", id).addFieldQuotedString("content", f->text()); closeItem(); } @@ -910,7 +914,7 @@ void PerlModDocVisitor::visitPost(DocTitle *) closeItem(); } -void PerlModDocVisitor::visitPre(DocSimpleList *) +void PerlModDocVisitor::visitPre(DocSimpleList *) { openItem("list"); m_output.addFieldQuotedString("style", "itemized"); @@ -1122,7 +1126,7 @@ void PerlModDocVisitor::visitPre(DocImage *) case DocImage::Rtf: m_output.add("rtf"); break; } m_output.add("\""); - + QCString baseName=img->name(); int i; if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1) @@ -1442,16 +1446,6 @@ static void addTemplateArgumentList(const ArgumentList &al,PerlModOutput &output output.closeList(); } -#if 0 -static void addMemberTemplateLists(MemberDef *md,PerlModOutput &output) -{ - ClassDef *cd = md->getClassDef(); - const char *cname = cd ? cd->name().data() : 0; - if (md->templateArguments()) // function template prefix - addTemplateArgumentList(md->templateArguments(),output,cname); -} -#endif - static void addTemplateList(const ClassDef *cd,PerlModOutput &output) { addTemplateArgumentList(cd->templateArguments(),output,cd->name()); @@ -1469,7 +1463,8 @@ static void addPerlModDocBlock(PerlModOutput &output, if (stext.isEmpty()) output.addField(name).add("{}"); else { - DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,stext,FALSE,0); + DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,stext,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); output.openHash(name); PerlModDocVisitor *visitor = new PerlModDocVisitor(output); root->accept(visitor); @@ -1480,7 +1475,7 @@ static void addPerlModDocBlock(PerlModOutput &output, } } -static const char *getProtectionName(Protection prot) +static const char *getProtectionName(Protection prot) { switch (prot) { @@ -1534,6 +1529,7 @@ public: inline PerlModGenerator(bool pretty) : m_output(pretty) { } void generatePerlModForMember(const MemberDef *md, const Definition *); + void generatePerlUserDefinedSection(const Definition *d, const MemberGroupSDict *gsd); void generatePerlModSection(const Definition *d, MemberList *ml, const char *name, const char *header=0); void addListOfAllMembers(const ClassDef *cd); @@ -1542,7 +1538,7 @@ public: void generatePerlModForFile(const FileDef *fd); void generatePerlModForGroup(const GroupDef *gd); void generatePerlModForPage(PageDef *pi); - + bool createOutputFile(QFile &f, const char *s); bool createOutputDir(QDir &perlModDir); bool generateDoxyLatexTex(); @@ -1571,7 +1567,7 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini // - body code // - template arguments // (templateArguments(), definitionTemplateParameterLists()) - + QCString memType; QCString name; bool isFunc=FALSE; @@ -1605,18 +1601,18 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness())) .addFieldQuotedString("protection", getProtectionName(md->protection())) .addFieldBoolean("static", md->isStatic()); - + addPerlModDocBlock(m_output,"brief",md->getDefFileName(),md->getDefLine(),md->getOuterScope(),md,md->briefDescription()); addPerlModDocBlock(m_output,"detailed",md->getDefFileName(),md->getDefLine(),md->getOuterScope(),md,md->documentation()); if (md->memberType()!=MemberType_Define && md->memberType()!=MemberType_Enumeration) m_output.addFieldQuotedString("type", md->typeString()); - + const ArgumentList &al = md->argumentList(); if (isFunc) //function { - m_output.addFieldBoolean("const", al.constSpecifier) - .addFieldBoolean("volatile", al.volatileSpecifier); + m_output.addFieldBoolean("const", al.constSpecifier()) + .addFieldBoolean("volatile", al.volatileSpecifier()); m_output.openList("parameters"); const ArgumentList &declAl = md->declArgumentList(); @@ -1650,7 +1646,7 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini if (!a.attrib.isEmpty()) m_output.addFieldQuotedString("attributes", a.attrib); - + m_output.closeHash(); } } @@ -1668,17 +1664,17 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini } m_output.closeList(); } - else if (md->argsString()!=0) + else if (md->argsString()!=0) { m_output.addFieldQuotedString("arguments", md->argsString()); } if (!md->initializer().isEmpty()) m_output.addFieldQuotedString("initializer", md->initializer()); - + if (md->excpString()) m_output.addFieldQuotedString("exceptions", md->excpString()); - + if (md->memberType()==MemberType_Enumeration) // enum { const MemberList *enumFields = md->enumFieldList(); @@ -1691,7 +1687,7 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini { m_output.openHash() .addFieldQuotedString("name", emd->name()); - + if (!emd->initializer().isEmpty()) m_output.addFieldQuotedString("initializer", emd->initializer()); @@ -1705,6 +1701,15 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini } } + /* DGA: fix #7495 Perlmod does not generate bitfield */ + if (md->memberType() == MemberType_Variable && md->bitfieldString()) + { + QCString bitfield = md->bitfieldString(); + if (bitfield.at(0) == ':') bitfield = bitfield.mid(1); + m_output.addFieldQuotedString("bitfield", bitfield); + } + /* DGA: end of fix #7495 */ + const MemberDef *rmd = md->reimplements(); if (rmd) m_output.openHash("reimplements") @@ -1722,7 +1727,7 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini .closeHash(); m_output.closeList(); } - + m_output.closeHash(); } @@ -1735,7 +1740,7 @@ void PerlModGenerator::generatePerlModSection(const Definition *d, if (header) m_output.addFieldQuotedString("header", header); - + m_output.openList("members"); MemberListIterator mli(*ml); const MemberDef *md; @@ -1750,37 +1755,62 @@ void PerlModGenerator::generatePerlModSection(const Definition *d, void PerlModGenerator::addListOfAllMembers(const ClassDef *cd) { m_output.openList("all_members"); - if (cd->memberNameInfoSDict()) + for (auto &mni : cd->memberNameInfoLinkedMap()) { - MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict()); - MemberNameInfo *mni; - for (mnii.toFirst();(mni=mnii.current());++mnii) + for (auto &mi : *mni) { - MemberNameInfoIterator mii(*mni); - MemberInfo *mi; - for (mii.toFirst();(mi=mii.current());++mii) - { - const MemberDef *md=mi->memberDef; - const ClassDef *cd=md->getClassDef(); - const Definition *d=md->getGroupDef(); - if (d==0) d = cd; + const MemberDef *md=mi->memberDef(); + const ClassDef *mcd=md->getClassDef(); + const Definition *d=md->getGroupDef(); + if (d==0) d = mcd; - m_output.openHash() - .addFieldQuotedString("name", md->name()) - .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness())) - .addFieldQuotedString("protection", getProtectionName(mi->prot)); + m_output.openHash() + .addFieldQuotedString("name", md->name()) + .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness())) + .addFieldQuotedString("protection", getProtectionName(mi->prot())); - if (!mi->ambiguityResolutionScope.isEmpty()) - m_output.addFieldQuotedString("ambiguity_scope", mi->ambiguityResolutionScope); + if (!mi->ambiguityResolutionScope().isEmpty()) + m_output.addFieldQuotedString("ambiguity_scope", mi->ambiguityResolutionScope()); - m_output.addFieldQuotedString("scope", cd->name()) - .closeHash(); - } + m_output.addFieldQuotedString("scope", mcd->name()) + .closeHash(); } } m_output.closeList(); } +/* DGA: fix #7490 Perlmod generation issue with multiple grouped functions (member groups) */ +void PerlModGenerator::generatePerlUserDefinedSection(const Definition *d, const MemberGroupSDict *gsd) +{ + if (gsd) + { + MemberGroupSDict::Iterator mgli(*gsd); + MemberGroup *mg; + m_output.openList("user_defined"); + for (; (mg = mgli.current()); ++mgli) + { + m_output.openHash(); + if (mg->header()) + m_output.addFieldQuotedString("header", mg->header()); + + if (mg->members()) + { + m_output.openList("members"); + MemberListIterator mli(*mg->members()); + const MemberDef *md; + for (mli.toFirst(); (md = mli.current()); ++mli) + { + generatePerlModForMember(md, d); + } + m_output.closeList(); + } + m_output.closeHash(); + } + m_output.closeList(); + } +} +/* DGA: end of fix #7490 */ + void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) { // + brief description @@ -1805,7 +1835,7 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) m_output.openHash() .addFieldQuotedString("name", cd->name()); - + if (cd->baseClasses()) { m_output.openList("base"); @@ -1839,10 +1869,10 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) { m_output.openList("inner"); ClassSDict::Iterator cli(*cl); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + const ClassDef *icd; + for (cli.toFirst();(icd=cli.current());++cli) m_output.openHash() - .addFieldQuotedString("name", cd->name()) + .addFieldQuotedString("name", icd->name()) .closeHash(); m_output.closeList(); } @@ -1867,13 +1897,7 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) addTemplateList(cd,m_output); addListOfAllMembers(cd); - if (cd->getMemberGroupSDict()) - { - MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict()); - MemberGroup *mg; - for (;(mg=mgli.current());++mgli) - generatePerlModSection(cd,mg->members(),"user_defined",mg->header()); - } + generatePerlUserDefinedSection(cd, cd->getMemberGroupSDict()); generatePerlModSection(cd,cd->getMemberList(MemberListType_pubTypes),"public_typedefs"); generatePerlModSection(cd,cd->getMemberList(MemberListType_pubMethods),"public_methods"); @@ -1917,12 +1941,12 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) collaborationGraph.writePerlMod(t); t << " </collaborationgraph>" << endl; } - t << " <location file=\"" - << cd->getDefFileName() << "\" line=\"" + t << " <location file=\"" + << cd->getDefFileName() << "\" line=\"" << cd->getDefLine() << "\""; if (cd->getStartBodyLine()!=-1) { - t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" + t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" << cd->getEndBodyLine() << "\""; } t << "/>" << endl; @@ -1946,7 +1970,7 @@ void PerlModGenerator::generatePerlModForNamespace(const NamespaceDef *nd) m_output.openHash() .addFieldQuotedString("name", nd->name()); - + ClassSDict *cl = nd->getClassSDict(); if (cl) { @@ -1965,21 +1989,15 @@ void PerlModGenerator::generatePerlModForNamespace(const NamespaceDef *nd) { m_output.openList("namespaces"); NamespaceSDict::Iterator nli(*nl); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + const NamespaceDef *ind; + for (nli.toFirst();(ind=nli.current());++nli) m_output.openHash() - .addFieldQuotedString("name", nd->name()) + .addFieldQuotedString("name", ind->name()) .closeHash(); m_output.closeList(); } - if (nd->getMemberGroupSDict()) - { - MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict()); - const MemberGroup *mg; - for (;(mg=mgli.current());++mgli) - generatePerlModSection(nd,mg->members(),"user-defined",mg->header()); - } + generatePerlUserDefinedSection(nd, nd->getMemberGroupSDict()); generatePerlModSection(nd,nd->getMemberList(MemberListType_decDefineMembers),"defines"); generatePerlModSection(nd,nd->getMemberList(MemberListType_decProtoMembers),"prototypes"); @@ -2009,12 +2027,12 @@ void PerlModGenerator::generatePerlModForFile(const FileDef *fd) // - source code // - location // - number of lines - + if (fd->isReference()) return; m_output.openHash() .addFieldQuotedString("name", fd->name()); - + IncludeInfo *inc; m_output.openList("includes"); if (fd->includeFileList()) @@ -2032,7 +2050,7 @@ void PerlModGenerator::generatePerlModForFile(const FileDef *fd) } } m_output.closeList(); - + m_output.openList("included_by"); if (fd->includedByFileList()) { @@ -2049,7 +2067,10 @@ void PerlModGenerator::generatePerlModForFile(const FileDef *fd) } } m_output.closeList(); - + + /* DGA: fix #7494 Perlmod does not generate grouped members from files */ + generatePerlUserDefinedSection(fd, fd->getMemberGroupSDict()); + generatePerlModSection(fd,fd->getMemberList(MemberListType_decDefineMembers),"defines"); generatePerlModSection(fd,fd->getMemberList(MemberListType_decProtoMembers),"prototypes"); generatePerlModSection(fd,fd->getMemberList(MemberListType_decTypedefMembers),"typedefs"); @@ -2148,13 +2169,7 @@ void PerlModGenerator::generatePerlModForGroup(const GroupDef *gd) m_output.closeList(); } - if (gd->getMemberGroupSDict()) - { - MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict()); - MemberGroup *mg; - for (;(mg=mgli.current());++mgli) - generatePerlModSection(gd,mg->members(),"user-defined",mg->header()); - } + generatePerlUserDefinedSection(gd, gd->getMemberGroupSDict()); generatePerlModSection(gd,gd->getMemberList(MemberListType_decDefineMembers),"defines"); generatePerlModSection(gd,gd->getMemberList(MemberListType_decProtoMembers),"prototypes"); @@ -2179,10 +2194,10 @@ void PerlModGenerator::generatePerlModForPage(PageDef *pd) m_output.openHash() .addFieldQuotedString("name", pd->name()); - - SectionInfo *si = Doxygen::sectionDict->find(pd->name()); + + const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) - m_output.addFieldQuotedString("title4", filterTitle(si->title)); + m_output.addFieldQuotedString("title4", filterTitle(si->title())); addPerlModDocBlock(m_output,"detailed",pd->docFile(),pd->docLine(),0,0,pd->documentation()); m_output.closeHash(); @@ -2193,12 +2208,12 @@ bool PerlModGenerator::generatePerlModOutput() QFile outputFile; if (!createOutputFile(outputFile, pathDoxyDocsPM)) return false; - + FTextStream outputTextStream(&outputFile); PerlModOutputStream outputStream(&outputTextStream); m_output.setPerlModOutputStream(&outputStream); m_output.add("$doxydocs=").openHash(); - + m_output.openList("classes"); ClassSDict::Iterator cli(*Doxygen::classSDict); const ClassDef *cd; @@ -2214,14 +2229,12 @@ bool PerlModGenerator::generatePerlModOutput() m_output.closeList(); m_output.openList("files"); - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - const FileDef *fd; - for (;(fd=fni.current());++fni) - generatePerlModForFile(fd); + for (const auto &fd : *fn) + { + generatePerlModForFile(fd.get()); + } } m_output.closeList(); @@ -2300,7 +2313,7 @@ bool PerlModGenerator::createOutputDir(QDir &perlModDir) return false; } } - + perlModDir.setPath(outputDirectory+"/perlmod"); if (!perlModDir.exists() && !perlModDir.mkdir(outputDirectory+"/perlmod")) { @@ -2317,7 +2330,7 @@ bool PerlModGenerator::generateDoxyStructurePM() return false; FTextStream doxyModelPMStream(&doxyModelPM); - doxyModelPMStream << + doxyModelPMStream << "sub memberlist($) {\n" " my $prefix = $_[0];\n" " return\n" @@ -2447,7 +2460,7 @@ bool PerlModGenerator::generateDoxyStructurePM() "\t\tclasses =>\n" "\t\t [ \"list\", \"Classes\",\n" "\t\t [ \"hash\", \"Class\",\n" - "\t\t {\n" + "\t\t {\n" "\t\t name => [ \"string\", \"Classname\" ]\n" "\t\t }\n" "\t\t ],\n" @@ -2455,7 +2468,7 @@ bool PerlModGenerator::generateDoxyStructurePM() "\t\tnamespaces =>\n" "\t\t [ \"list\", \"Namespaces\",\n" "\t\t [ \"hash\", \"Namespace\",\n" - "\t\t {\n" + "\t\t {\n" "\t\t name => [ \"string\", \"NamespaceName\" ]\n" "\t\t }\n" "\t\t ],\n" @@ -2625,7 +2638,7 @@ bool PerlModGenerator::generateDoxyLatexStructurePL() return false; FTextStream doxyLatexStructurePLStream(&doxyLatexStructurePL); - doxyLatexStructurePLStream << + doxyLatexStructurePLStream << "use DoxyStructure;\n" "\n" "sub process($) {\n" @@ -2659,7 +2672,7 @@ bool PerlModGenerator::generateDoxyLatexPL() return false; FTextStream doxyLatexPLStream(&doxyLatexPL); - doxyLatexPLStream << + doxyLatexPLStream << "use DoxyStructure;\n" "use DoxyDocs;\n" "\n" @@ -2782,7 +2795,7 @@ bool PerlModGenerator::generateDoxyFormatTex() return false; FTextStream doxyFormatTexStream(&doxyFormatTex); - doxyFormatTexStream << + doxyFormatTexStream << "\\def\\Defcs#1{\\long\\expandafter\\def\\csname#1\\endcsname}\n" "\\Defcs{Empty}{}\n" "\\def\\IfEmpty#1{\\expandafter\\ifx\\csname#1\\endcsname\\Empty}\n" @@ -3028,12 +3041,12 @@ void generatePerlMod() (global-set-key '(control z) (lambda () (interactive) (save-excursion (if (< (mark) (point)) (exchange-point-and-mark)) - (let ((start (point)) (replacers + (let ((start (point)) (replacers '(("\\\\" "\\\\\\\\") ("\"" "\\\\\"") ("\t" "\\\\t") ("^.*$" "\"\\&\\\\n\"")))) - (while replacers + (while replacers (while (re-search-forward (caar replacers) (mark) t) (replace-match (cadar replacers) t)) (goto-char start) diff --git a/src/plantuml.cpp b/src/plantuml.cpp index fa50f2d..d020da0 100644 --- a/src/plantuml.cpp +++ b/src/plantuml.cpp @@ -27,16 +27,24 @@ #include <qlist.h> -QCString PlantumlManager::writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content,OutputFormat format) +QCString PlantumlManager::writePlantUMLSource(const QCString &outDirArg,const QCString &fileName,const QCString &content,OutputFormat format) { QCString baseName; QCString puName; QCString imgName; + QCString outDir(outDirArg); 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)); + // strip any trailing slashes and backslashes + uint l; + while ((l=outDir.length())>0 && (outDir.at(l-1)=='/' || outDir.at(l-1)=='\\')) + { + outDir = outDir.left(l-1); + } + if (fileName.isEmpty()) // generate name { puName = "inline_umlgraph_"+QCString().setNum(umlindex); @@ -76,7 +84,7 @@ QCString PlantumlManager::writePlantUMLSource(const QCString &outDir,const QCStr 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); + PlantumlManager::instance()->insert(generateType,puName,outDir,format,text); Debug::print(Debug::Plantuml,0,"*** %s generateType: %s\n","writePlantUMLSource",qPrint(generateType)); return baseName; @@ -178,16 +186,16 @@ PlantumlManager::~PlantumlManager() } static void runPlantumlContent(const QDict< QList <QCString> > &plantumlFiles, - const QDict< QCString > &plantumlContent, + const QDict< PlantumlContent > &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 + /* 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; @@ -200,21 +208,23 @@ static void runPlantumlContent(const QDict< QList <QCString> > &plantumlFiles, QCString pumlType = ""; QCString pumlOutDir = ""; - QStrList &pumlIncludePathList = Config_getList(PLANTUML_INCLUDE_PATH); - char *s=pumlIncludePathList.first(); - if (s) + const StringVector &pumlIncludePathList = Config_getList(PLANTUML_INCLUDE_PATH); { - pumlArgs += "-Dplantuml.include.path=\""; - pumlArgs += s; - s = pumlIncludePathList.next(); - } - while (s) - { - pumlArgs += Portable::pathListSeparator(); - pumlArgs += s; - s = pumlIncludePathList.next(); + auto it = pumlIncludePathList.begin(); + if (it!=pumlIncludePathList.end()) + { + pumlArgs += "-Dplantuml.include.path=\""; + pumlArgs += it->c_str(); + ++it; + } + while (it!=pumlIncludePathList.end()) + { + pumlArgs += Portable::pathListSeparator(); + pumlArgs += it->c_str(); + ++it; + } } - if (pumlIncludePathList.first()) pumlArgs += "\" "; + if (!pumlIncludePathList.empty()) pumlArgs += "\" "; pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" "; if (!plantumlConfigFile.isEmpty()) { @@ -244,25 +254,21 @@ static void runPlantumlContent(const QDict< QList <QCString> > &plantumlFiles, } { - QDictIterator< QCString > it( plantumlContent); // See QDictIterator - QCString *nb; + QDictIterator< PlantumlContent > it( plantumlContent); // See QDictIterator + PlantumlContent *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+=nb->outDir.data(); pumlArguments+="\" "; pumlArguments+="-charset UTF-8 -t"; pumlArguments+=pumlType; pumlArguments+=" "; QCString puFileName(""); - puFileName+=Config_getString(OUTPUT_DIRECTORY); - puFileName+="/"; - puFileName+=it.currentKey(); + puFileName+=nb->outDir.data(); puFileName+="/"; pumlOutDir=puFileName; puFileName+="inline_umlgraph_"; @@ -279,7 +285,7 @@ static void runPlantumlContent(const QDict< QList <QCString> > &plantumlFiles, { err("Could not open file %s for writing\n",puFileName.data()); } - file.writeBlock( *nb, nb->length() ); + file.writeBlock( nb->content, nb->content.length() ); file.close(); Debug::print(Debug::Plantuml,0,"*** %s Running Plantuml arguments:%s\n","PlantumlManager::runPlantumlContent",qPrint(pumlArguments)); @@ -303,12 +309,12 @@ static void runPlantumlContent(const QDict< QList <QCString> > &plantumlFiles, if (list) { QListIterator<QCString> li(*list); - QCString *nb; - for (li.toFirst();(nb=li.current());++li) + QCString *str_p; + for (li.toFirst();(str_p=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)); + epstopdfArgs.sprintf("\"%s%s.eps\" --outfile=\"%s%s.pdf\"",qPrint(pumlOutDir),qPrint(*str_p),qPrint(pumlOutDir),qPrint(*str_p)); Portable::sysTimerStart(); if ((exitCode=Portable::system("epstopdf",epstopdfArgs))!=0) { @@ -358,16 +364,16 @@ static void print(const QDict< QList <QCString> > &plantumlFiles) } } -static void print(const QDict<QCString> &plantumlContent) +static void print(const QDict<PlantumlContent> &plantumlContent) { if (Debug::isFlagSet(Debug::Plantuml)) { - QDictIterator< QCString > it( plantumlContent); // See QDictIterator - QCString *nb; + QDictIterator< PlantumlContent > it( plantumlContent); // See QDictIterator + PlantumlContent *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)); + Debug::print(Debug::Plantuml,0,"*** %s Content :%s\n","PlantumlManager::print",qPrint(nb->content)); } } } @@ -384,22 +390,22 @@ static void addPlantumlFiles(QDict< QList<QCString> > &plantumlFiles, list->append(new QCString(value)); } -static void addPlantumlContent(QDict< QCString > &plantumlContent, - const QCString &key, const QCString &puContent) +static void addPlantumlContent(QDict< PlantumlContent > &plantumlContent, + const QCString &key, const QCString &outDir, const QCString &puContent) { - QCString* content = plantumlContent.find(key); + PlantumlContent* content = plantumlContent.find(key); if (content == 0) { - content = new QCString(""); + content = new PlantumlContent("",outDir); plantumlContent.insert(key,content); } - (*content)+=puContent; + (content->content)+=puContent; } void PlantumlManager::insert(const QCString &key, const QCString &value, - OutputFormat format,const QCString &puContent) + const QCString &outDir,OutputFormat format,const QCString &puContent) { int find; @@ -419,19 +425,19 @@ void PlantumlManager::insert(const QCString &key, const QCString &value, case PUML_BITMAP: addPlantumlFiles(m_pngPlantumlFiles,key,value); print(m_pngPlantumlFiles); - addPlantumlContent(m_pngPlantumlContent,key,puContent); + addPlantumlContent(m_pngPlantumlContent,key,outDir,puContent); print(m_pngPlantumlContent); break; case PUML_EPS: addPlantumlFiles(m_epsPlantumlFiles,key,value); print(m_epsPlantumlFiles); - addPlantumlContent(m_epsPlantumlContent,key,puContent); + addPlantumlContent(m_epsPlantumlContent,key,outDir,puContent); print(m_epsPlantumlContent); break; case PUML_SVG: addPlantumlFiles(m_svgPlantumlFiles,key,value); print(m_svgPlantumlFiles); - addPlantumlContent(m_svgPlantumlContent,key,puContent); + addPlantumlContent(m_svgPlantumlContent,key,outDir,puContent); print(m_svgPlantumlContent); break; } diff --git a/src/plantuml.h b/src/plantuml.h index d3a01f5..f2e9dec 100644 --- a/src/plantuml.h +++ b/src/plantuml.h @@ -24,6 +24,17 @@ #define MIN_PLANTUML_COUNT 8 class QCString; +struct PlantumlContent +{ + QCString outDir; + QCString content; + PlantumlContent(const QCString Content, const QCString OutDir) + { + outDir = OutDir; + content = Content; + }; + ~PlantumlContent(){}; +}; /** Singleton that manages plantuml relation actions */ class PlantumlManager @@ -58,15 +69,16 @@ class PlantumlManager ~PlantumlManager(); void insert(const QCString &key, const QCString &value, + const QCString &outDir, 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-processor (multi threading) - QDict< QCString > m_svgPlantumlContent; - QDict< QCString > m_epsPlantumlContent; + QDict< PlantumlContent > m_pngPlantumlContent; // use circular queue for using multi-processor (multi threading) + QDict< PlantumlContent > m_svgPlantumlContent; + QDict< PlantumlContent > 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 }; diff --git a/src/portable.cpp b/src/portable.cpp index 3ee1081..d3799c7 100644 --- a/src/portable.cpp +++ b/src/portable.cpp @@ -207,11 +207,6 @@ unsigned int Portable::pid(void) return pid; } -#if defined(_WIN32) && !defined(__CYGWIN__) -#else - static char **last_environ; -#endif - #if !defined(_WIN32) || defined(__CYGWIN__) void loadEnvironment() { @@ -251,7 +246,7 @@ void Portable::setenv(const char *name,const char *value) loadEnvironment(); } - proc_env[name] = std::string(value); // create or replace exisiting value + proc_env[name] = std::string(value); // create or replace existing value #endif } @@ -261,9 +256,6 @@ void Portable::unsetenv(const char *variable) SetEnvironmentVariable(variable,0); #else /* Some systems don't have unsetenv(), so we do it ourselves */ - size_t len; - char **ep; - if (variable == NULL || *variable == '\0' || strchr (variable, '=') != NULL) { return; // not properly formatted @@ -348,10 +340,71 @@ char Portable::pathListSeparator(void) #endif } +static bool ExistsOnPath(const char *fileName) +{ + QFileInfo fi1(fileName); + if (fi1.exists()) return true; + + const char *p = Portable::getenv("PATH"); + char listSep = Portable::pathListSeparator(); + char pathSep = Portable::pathSeparator(); + QCString paths(p); + int strt = 0; + int idx; + while ((idx = paths.find(listSep,strt)) != -1) + { + QCString locFile(paths.mid(strt,idx-strt)); + locFile += pathSep; + locFile += fileName; + QFileInfo fi(locFile); + if (fi.exists()) return true; + strt = idx + 1; + } + // to be sure the last path component is checked as well + QCString locFile(paths.mid(strt)); + if (!locFile.isEmpty()) + { + locFile += pathSep; + locFile += fileName; + QFileInfo fi(locFile); + if (fi.exists()) return true; + } + return false; +} + +bool Portable::checkForExecutable(const char *fileName) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char *extensions[] = {".bat",".com",".exe"}; + for (int i = 0; i < sizeof(extensions) / sizeof(*extensions); i++) + { + if (ExistsOnPath(QCString(fileName) + extensions[i])) return true; + } + return false; +#else + return ExistsOnPath(fileName); +#endif +} + const char *Portable::ghostScriptCommand(void) { #if defined(_WIN32) && !defined(__CYGWIN__) - return "gswin32c.exe"; + static char *gsexe = NULL; + if (!gsexe) + { + char *gsExec[] = {"gswin32c.exe","gswin64c.exe"}; + for (int i = 0; i < sizeof(gsExec) / sizeof(*gsExec); i++) + { + if (ExistsOnPath(gsExec[i])) + { + gsexe = gsExec[i]; + return gsexe; + } + } + gsexe = gsExec[0]; + return gsexe; + } + return gsexe; #else return "gs"; #endif @@ -518,3 +571,12 @@ const char *Portable::strnstr(const char *haystack, const char *needle, size_t h } return 0; } + +const char *Portable::devNull() +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + return "NUL"; +#else + return "/dev/null"; +#endif +} diff --git a/src/portable.h b/src/portable.h index 771108e..bf6cfea 100644 --- a/src/portable.h +++ b/src/portable.h @@ -43,6 +43,8 @@ namespace Portable void correct_path(void); void setShortDir(void); const char * strnstr(const char *haystack, const char *needle, size_t haystack_len); + const char * devNull(); + bool checkForExecutable(const char *fileName); } @@ -18,6 +18,8 @@ #ifndef PRE_H #define PRE_H +#include <memory> + class BufStr; class Preprocessor @@ -29,7 +31,7 @@ class Preprocessor void addSearchDir(const char *dir); private: struct Private; - Private *p; + std::unique_ptr<Private> p; }; #endif @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -18,6 +16,9 @@ %option prefix="preYY" %option reentrant %option extra-type="struct preYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -25,24 +26,28 @@ * includes */ +#include "doxygen.h" + +#include <stack> +#include <deque> +#include <algorithm> +#include <utility> +#include <mutex> +#include <thread> + #include <stdio.h> #include <assert.h> #include <ctype.h> #include <errno.h> -#include <qarray.h> -#include <qstack.h> -#include <qfile.h> -#include <qstrlist.h> -#include <qdict.h> +#include <qcstring.h> #include <qregexp.h> #include <qfileinfo.h> -#include <qdir.h> - + +#include "containers.h" #include "pre.h" #include "constexp.h" #include "define.h" -#include "doxygen.h" #include "message.h" #include "util.h" #include "defargs.h" @@ -55,20 +60,22 @@ #include "condparser.h" #include "config.h" #include "filedef.h" -#include "memberdef.h" -#include "membername.h" #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + // Toggle for some debugging info //#define DBG_CTX(x) fprintf x #define DBG_CTX(x) do { } while(0) +#if USE_STATE2STRING static const char *stateToString(int state); +#endif struct CondCtx { - CondCtx(int line,QCString id,bool b) + CondCtx(int line,QCString id,bool b) : lineNr(line),sectionId(id), skip(b) {} int lineNr; QCString sectionId; @@ -77,247 +84,160 @@ struct CondCtx struct FileState { - FileState(int size) : lineNr(1), curlyCount(0),fileBuf(size), - oldFileBuf(0), oldFileBufPos(0), bufState(0) {} - int lineNr; - int curlyCount; + FileState(int size) : fileBuf(size) {} + int lineNr = 1; + int curlyCount = 0; BufStr fileBuf; - BufStr *oldFileBuf; - int oldFileBufPos; - YY_BUFFER_STATE bufState; + BufStr *oldFileBuf = 0; + yy_size_t oldFileBufPos = 0; + YY_BUFFER_STATE bufState = 0; QCString fileName; -}; +}; -/** @brief Singleton that manages the defines available while - * preprocessing files. - */ -class DefineManager +struct PreIncludeInfo { - /** Local class used to hold the defines for a single file */ - class DefinesPerFile + PreIncludeInfo(const char *fn,FileDef *srcFd, FileDef *dstFd,const char *iName,bool loc, bool imp) + : fileName(fn), fromFileDef(srcFd), toFileDef(dstFd), includeName(iName), local(loc), imported(imp) { - public: - /** Creates an empty container for defines */ - DefinesPerFile(DefineManager *parent) - : m_parent(parent), m_defines(257), m_includedFiles(17) - { - m_defines.setAutoDelete(TRUE); - } - /** Destroys the object */ - virtual ~DefinesPerFile() - { - } - /** Adds a define in the context of a file. Will replace - * an existing define with the same name (redefinition) - * @param def The Define object to add. - */ - void addDefine(Define *def) - { - Define *d = m_defines.find(def->name); - if (d!=0) // redefine - { - m_defines.remove(d->name); - } - m_defines.insert(def->name,def); - } - /** Adds an include file for this file - * @param fileName The name of the include file - */ - void addInclude(const char *fileName) - { - m_includedFiles.insert(fileName,(void*)0x8); - } - void collectDefines(DefineDict *dict,QDict<void> &includeStack); - private: - DefineManager *m_parent; - DefineDict m_defines; - QDict<void> m_includedFiles; - }; + } + QCString fileName; // file name in which the include statement was found + FileDef *fromFileDef; // filedef in which the include statement was found + FileDef *toFileDef; // filedef to which the include is pointing + QCString includeName; // name used in the #include statement + bool local; // is it a "local" or <global> include + bool imported; // include via "import" keyword (Objective-C) +}; - public: - friend class DefinesPerFile; +/** A dictionary of managed Define objects. */ +typedef std::map< std::string, Define > DefineMap; - /** Creates a new DefineManager object */ - DefineManager() : m_fileMap(1009), m_contextDefines(1009) +/** @brief Class that manages the defines available while + * preprocessing files. + */ +class DefineManager +{ + private: + /** Local class used to hold the defines for a single file */ + class DefinesPerFile { - m_fileMap.setAutoDelete(TRUE); - } + public: + /** Creates an empty container for defines */ + DefinesPerFile(DefineManager *parent) + : m_parent(parent) + { + } + void addInclude(std::string fileName) + { + m_includedFiles.insert(fileName); + } + void store(const DefineMap &fromMap) + { + for (auto &kv : fromMap) + { + m_defines.emplace(kv.first,kv.second); + } + //printf(" m_defines.size()=%zu\n",m_defines.size()); + m_stored=true; + } + void retrieve(DefineMap &toMap) + { + StringSet includeStack; + retrieveRec(toMap,includeStack); + } + void retrieveRec(DefineMap &toMap,StringSet &includeStack) + { + //printf(" retrieveRec #includedFiles=%zu\n",m_includedFiles.size()); + for (auto incFile : m_includedFiles) + { + DefinesPerFile *dpf = m_parent->find(incFile); + if (dpf && includeStack.find(incFile)==includeStack.end()) + { + includeStack.insert(incFile); + dpf->retrieveRec(toMap,includeStack); + //printf(" retrieveRec: processing include %s: #toMap=%zu\n",incFile.data(),toMap.size()); + } + } + for (auto &kv : m_defines) + { + toMap.emplace(kv.first,kv.second); + } + } + bool stored() const { return m_stored; } + private: + DefineManager *m_parent; + DefineMap m_defines; + StringSet m_includedFiles; + bool m_stored = false; + }; - /** Destroys the object */ - virtual ~DefineManager() - { - } + friend class DefinesPerFile; + public: - /** Starts a context in which defines are collected. - * Called at the start of a new file that is preprocessed. - * @param fileName the name of the file to process. - */ - void startContext(const char *fileName) - { - //printf("DefineManager::startContext()\n"); - m_contextDefines.clear(); - if (fileName==0) return; - DefinesPerFile *dpf = m_fileMap.find(fileName); - if (dpf==0) - { - //printf("New file!\n"); - dpf = new DefinesPerFile(this); - m_fileMap.insert(fileName,dpf); - } - } - /** Ends the context started with startContext() freeing any - * defines collected within in this context. - */ - void endContext() + void addInclude(std::string fromFileName,std::string toFileName) { - //printf("DefineManager::endContext()\n"); - m_contextDefines.clear(); - } - /** Add an included file to the current context. - * If the file has been pre-processed already, all defines are added - * to the context. - * @param fileName The name of the include file to add to the context. - */ - void addFileToContext(const char *fileName) - { - if (fileName==0) return; - //printf("DefineManager::addFileToContext(%s)\n",fileName); - DefinesPerFile *dpf = m_fileMap.find(fileName); - if (dpf==0) - { - //printf("New file!\n"); - dpf = new DefinesPerFile(this); - m_fileMap.insert(fileName,dpf); - } - else + //printf("DefineManager::addInclude('%s'->'%s')\n",fromFileName.c_str(),toFileName.c_str()); + auto it = m_fileMap.find(fromFileName); + if (it==m_fileMap.end()) { - //printf("existing file!\n"); - QDict<void> includeStack(17); - dpf->collectDefines(&m_contextDefines,includeStack); + it = m_fileMap.emplace(fromFileName,std::make_unique<DefinesPerFile>(this)).first; } + auto &dpf = it->second; + dpf->addInclude(toFileName); } - /** Add a define to the manager object. - * @param fileName The file in which the define was found - * @param def The Define object to add. - */ - void addDefine(const char *fileName,Define *def) + void store(std::string fileName,const DefineMap &fromMap) { - if (fileName==0) return; - //printf("DefineManager::addDefine(%s,%s)\n",fileName,def->name.data()); - Define *d = m_contextDefines.find(def->name); - if (d!=0) // redefine + //printf("DefineManager::store(%s,#=%zu)\n",fileName.c_str(),fromMap.size()); + auto it = m_fileMap.find(fileName); + if (it==m_fileMap.end()) { - m_contextDefines.remove(d->name); + it = m_fileMap.emplace(fileName,std::make_unique<DefinesPerFile>(this)).first; } - m_contextDefines.insert(def->name,def); - - DefinesPerFile *dpf = m_fileMap.find(fileName); - if (dpf==0) - { - dpf = new DefinesPerFile(this); - m_fileMap.insert(fileName,dpf); - } - dpf->addDefine(def); + it->second->store(fromMap); } - /** Add an include relation to the manager object. - * @param fromFileName file name in which the include was found. - * @param toFileName file name that is included. - */ - void addInclude(const char *fromFileName,const char *toFileName) + void retrieve(std::string fileName,DefineMap &toMap) { - //printf("DefineManager::addInclude(%s,%s)\n",fromFileName,toFileName); - if (fromFileName==0 || toFileName==0) return; - DefinesPerFile *dpf = m_fileMap.find(fromFileName); - if (dpf==0) + auto it = m_fileMap.find(fileName); + if (it!=m_fileMap.end()) { - dpf = new DefinesPerFile(this); - m_fileMap.insert(fromFileName,dpf); + auto &dpf = it->second; + dpf->retrieve(toMap); } - dpf->addInclude(toFileName); - } - /** Returns a Define object given its name or 0 if the Define does - * not exist. - */ - Define *isDefined(const char *name) const - { - Define *d = m_contextDefines.find(name); - if (d && d->undef) d=0; - //printf("isDefined(%s)=%p\n",name,d); - return d; - } - /** Returns a reference to the defines found in the current context. */ - const DefineDict &defineContext() const - { - return m_contextDefines; + //printf("DefineManager::retrieve(%s,#=%zu)\n",fileName.c_str(),toMap.size()); } - private: - /** Helper function to collect all define for a given file */ - void collectDefinesForFile(const char *fileName,DefineDict *dict) + bool alreadyProcessed(std::string fileName) const { - if (fileName==0) return; - DefinesPerFile *dpf = m_fileMap.find(fileName); - if (dpf) + auto it = m_fileMap.find(fileName); + if (it!=m_fileMap.end()) { - QDict<void> includeStack(17); - dpf->collectDefines(dict,includeStack); + return it->second->stored(); } + return false; } + private: /** Helper function to return the DefinesPerFile object for a given file name. */ - DefinesPerFile *find(const char *fileName) const + DefinesPerFile *find(std::string fileName) const { - if (fileName==0) return 0; - return m_fileMap.find(fileName); + auto it = m_fileMap.find(fileName); + return it!=m_fileMap.end() ? it->second.get() : nullptr; } - QDict<DefinesPerFile> m_fileMap; - DefineDict m_contextDefines; + std::unordered_map< std::string, std::unique_ptr<DefinesPerFile> > m_fileMap; }; -/** Collects all defines for a file and all files that the file includes. - * This function will recursively call itself for each file. - * @param dict The dictionary to fill with the defines. A redefine will - * replace a previous definition. - * @param includeStack The stack of includes, used to stop recursion in - * case there is a cyclic include dependency. +/* ----------------------------------------------------------------- + * + * global state */ -void DefineManager::DefinesPerFile::collectDefines( - DefineDict *dict,QDict<void> &includeStack) -{ - //printf("DefinesPerFile::collectDefines #defines=%d\n",m_defines.count()); - { - QDictIterator<void> di(m_includedFiles); - for (di.toFirst();(di.current());++di) - { - QCString incFile = di.currentKey(); - DefinesPerFile *dpf = m_parent->find(incFile); - if (dpf && includeStack.find(incFile)==0) - { - //printf(" processing include %s\n",incFile.data()); - includeStack.insert(incFile,(void*)0x8); - dpf->collectDefines(dict,includeStack); - } - } - } - { - QDictIterator<Define> di(m_defines); - Define *def; - for (di.toFirst();(def=di.current());++di) - { - Define *d = dict->find(def->name); - if (d!=0) // redefine - { - dict->remove(d->name); - } - dict->insert(def->name,def); - //printf(" adding define %s\n",def->name.data()); - } - } -} +static std::mutex g_debugMutex; +static std::mutex g_globalDefineMutex; +static std::mutex g_updateGlobals; +static DefineManager g_defineManager; + /* ----------------------------------------------------------------- * @@ -326,62 +246,64 @@ void DefineManager::DefinesPerFile::collectDefines( struct preYY_state { - preYY_state() : allIncludes(10009) {} - int yyLineNr = 1; - int yyMLines = 1; - int yyColNr = 1; + int yyLineNr = 1; + int yyMLines = 1; + int yyColNr = 1; QCString yyFileName; - FileDef *yyFileDef; - FileDef *inputFileDef; - int ifcount = 0; - QStrList *pathList = 0; - QStack<FileState> includeStack; - QDict<int> *argDict = 0; - int defArgs = -1; + FileDef *yyFileDef = 0; + FileDef *inputFileDef = 0; + int ifcount = 0; + int defArgs = -1; QCString defName; QCString defText; QCString defLitText; QCString defArgsStr; QCString defExtraSpacing; - bool defVarArgs; - int level; - int lastCContext; - int lastCPPContext; - QArray<int> levelGuard; - BufStr *inputBuf = 0; - int inputBufPos; - BufStr *outputBuf = 0; - int roundCount; - bool quoteArg; - DefineDict *expandedDict = 0; - int findDefArgContext; - bool expectGuard; + bool defVarArgs = false; + int lastCContext = 0; + int lastCPPContext = 0; + BufStr *inputBuf = 0; + yy_size_t inputBufPos = 0; + BufStr *outputBuf = 0; + int roundCount = 0; + bool quoteArg = false; + int findDefArgContext = 0; + bool expectGuard = false; QCString guardName; QCString lastGuardName; QCString incName; QCString guardExpr; - int curlyCount; - bool nospaces; // add extra spaces during macro expansion - - bool macroExpansion; // from the configuration - bool expandOnlyPredef; // from the configuration - int commentCount; - bool insideComment; - bool isImported; + int curlyCount = 0; + bool nospaces = false; // add extra spaces during macro expansion + + bool macroExpansion = false; // from the configuration + bool expandOnlyPredef = false; // from the configuration + int commentCount = 0; + bool insideComment = false; + bool isImported = false; QCString blockName; - int condCtx; - bool skip; - QStack<CondCtx> condStack; - bool insideCS; // C# has simpler preprocessor - bool isSource; - - int fenceSize = 0; - bool ccomment; + int condCtx = 0; + bool skip = false; + bool insideCS = false; // C# has simpler preprocessor + bool insideFtn = false; + bool isSource = false; + + yy_size_t fenceSize = 0; + bool ccomment = false; QCString delimiter; - QDict<void> allIncludes; - QDict<void> expansionDict; - DefineManager defineManager; - ConstExpressionParser constExpParser; + bool isSpecialComment = false; + StringVector pathList; + IntMap argMap; + BoolStack levelGuard; + std::stack< std::unique_ptr<CondCtx> > condStack; + std::deque< std::unique_ptr<FileState> > includeStack; + std::unordered_map<std::string,Define*> expandedDict; + StringUnorderedSet expanded; + ConstExpressionParser constExpParser; + DefineMap contextDefines; // macros imported from other files + DefineMap localDefines; // macros defined in this file + DefineList macroDefinitions; + LinkedMap<PreIncludeInfo> includeRelations; }; // stateless functions @@ -401,10 +323,11 @@ static bool otherCaseDone(yyscan_t yyscanner); static bool computeExpression(yyscan_t yyscanner,const QCString &expr); static void startCondSection(yyscan_t yyscanner,const char *sectId); static void endCondSection(yyscan_t yyscanner); +static void addMacroDefinition(yyscan_t yyscanner); static void addDefine(yyscan_t yyscanner); -static Define * newDefine(yyscan_t yyscanner); static void setFileName(yyscan_t yyscanner,const char *name); -static int yyread(yyscan_t yyscanner,char *buf,int max_size); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static Define * isDefined(yyscan_t yyscanner,const char *name); /* ----------------------------------------------------------------- */ @@ -472,7 +395,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <*>"??"[=/'()!<>-] { // Trigraph unput(resolveTrigraph(yytext[2])); } -<Start>^{B}*"#" { BEGIN(Command); yyextra->yyColNr+=yyleng; yyextra->yyMLines=0;} +<Start>^{B}*"#" { BEGIN(Command); yyextra->yyColNr+=(int)yyleng; yyextra->yyMLines=0;} <Start>^{B}*/[^#] { outputArray(yyscanner,yytext,(int)yyleng); BEGIN(CopyLine); @@ -492,12 +415,12 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) name=name.left(name.find('(')).stripWhiteSpace(); Define *def=0; - if (skipFuncMacros && + if (skipFuncMacros && !yyextra->insideFtn && name!="Q_PROPERTY" && !( - (yyextra->includeStack.isEmpty() || yyextra->curlyCount>0) && + (yyextra->includeStack.empty() || yyextra->curlyCount>0) && yyextra->macroExpansion && - (def=yyextra->defineManager.isDefined(name)) && + (def=isDefined(yyscanner,name)) && /*macroIsAccessible(def) &&*/ (!yyextra->expandOnlyPredef || def->isPredefined) ) @@ -528,14 +451,14 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(CopyRawString); } <CopyLine>"{" { // count brackets inside the main file - if (yyextra->includeStack.isEmpty()) + if (yyextra->includeStack.empty()) { yyextra->curlyCount++; } outputChar(yyscanner,*yytext); } <CopyLine>"}" { // count brackets inside the main file - if (yyextra->includeStack.isEmpty() && yyextra->curlyCount>0) + if (yyextra->includeStack.empty() && yyextra->curlyCount>0) { yyextra->curlyCount--; } @@ -623,16 +546,16 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->expectGuard = FALSE; Define *def=0; //def=yyextra->globalDefineDict->find(yytext); - //def=yyextra->defineManager.isDefined(yytext); - //printf("Search for define %s found=%d yyextra->includeStack.isEmpty()=%d " + //def=isDefined(yyscanner,yytext); + //printf("Search for define %s found=%d yyextra->includeStack.empty()=%d " // "yyextra->curlyCount=%d yyextra->macroExpansion=%d yyextra->expandOnlyPredef=%d " // "isPreDefined=%d\n",yytext,def ? 1 : 0, - // yyextra->includeStack.isEmpty(),yyextra->curlyCount,yyextra->macroExpansion,yyextra->expandOnlyPredef, + // yyextra->includeStack.empty(),yyextra->curlyCount,yyextra->macroExpansion,yyextra->expandOnlyPredef, // def ? def->isPredefined : -1 // ); - if ((yyextra->includeStack.isEmpty() || yyextra->curlyCount>0) && + if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) && yyextra->macroExpansion && - (def=yyextra->defineManager.isDefined(yytext)) && + (def=isDefined(yyscanner,yytext)) && /*(def->isPredefined || macroIsAccessible(def)) && */ (!yyextra->expandOnlyPredef || def->isPredefined) ) @@ -658,9 +581,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <CopyLine>{ID} { Define *def=0; - if ((yyextra->includeStack.isEmpty() || yyextra->curlyCount>0) && + if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) && yyextra->macroExpansion && - (def=yyextra->defineManager.isDefined(yytext)) && + (def=isDefined(yyscanner,yytext)) && def->nargs==-1 && /*(def->isPredefined || macroIsAccessible(def)) &&*/ (!yyextra->expandOnlyPredef || def->isPredefined) @@ -792,7 +715,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <Command>("cmake")?"define"{B}+ { //printf("!!!DefName\n"); - yyextra->yyColNr+=yyleng; + yyextra->yyColNr+=(int)yyleng; BEGIN(DefName); } <Command>"ifdef"/{B}*"(" { @@ -834,7 +757,6 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } } <Command>"else"/[^a-z_A-Z0-9\x80-\xFF] { - //printf("else yyextra->levelGuard[%d]=%d\n",yyextra->level-1,yyextra->levelGuard[yyextra->level-1]); if (otherCaseDone(yyscanner)) { yyextra->ifcount=0; @@ -843,7 +765,6 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) else { setCaseDone(yyscanner,TRUE); - //yyextra->levelGuard[yyextra->level-1]=TRUE; } } <Command>"undef"{B}+ { @@ -876,10 +797,10 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->yyLineNr++; } <IgnoreLine>. -<Command>. {yyextra->yyColNr+=yyleng;} +<Command>. {yyextra->yyColNr+=(int)yyleng;} <UndefName>{ID} { Define *def; - if ((def=yyextra->defineManager.isDefined(yytext)) + if ((def=isDefined(yyscanner,yytext)) /*&& !def->isPredefined*/ && !def->nonRecursive ) @@ -909,7 +830,6 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) // yyextra->guardExpr.data()); bool guard=computeExpression(yyscanner,yyextra->guardExpr); setCaseDone(yyscanner,guard); - //printf("if yyextra->levelGuard[%d]=%d\n",yyextra->level-1,yyextra->levelGuard[yyextra->level-1]); if (guard) { BEGIN(Start); @@ -922,7 +842,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <DefinedExpr1,DefinedExpr2>\\\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } <DefinedExpr1>{ID} { - if (yyextra->defineManager.isDefined(yytext) || yyextra->guardName==yytext) + if (isDefined(yyscanner,yytext) || yyextra->guardName==yytext) yyextra->guardExpr+=" 1L "; else yyextra->guardExpr+=" 0L "; @@ -930,7 +850,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(Guard); } <DefinedExpr2>{ID} { - if (yyextra->defineManager.isDefined(yytext) || yyextra->guardName==yytext) + if (isDefined(yyscanner,yytext) || yyextra->guardName==yytext) yyextra->guardExpr+=" 1L "; else yyextra->guardExpr+=" 0L "; @@ -1060,10 +980,8 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <DefName>{ID}/("\\\n")*"(" { // define with argument //printf("Define() '%s'\n",yytext); - delete yyextra->argDict; - yyextra->argDict = new QDict<int>(31); - yyextra->argDict->setAutoDelete(TRUE); - yyextra->defArgs = 0; + yyextra->argMap.clear(); + yyextra->defArgs = 0; yyextra->defArgsStr.resize(0); yyextra->defText.resize(0); yyextra->defLitText.resize(0); @@ -1074,7 +992,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <DefName>{ID}{B}+"1"/[ \r\t\n] { // special case: define with 1 -> can be "guard" //printf("Define '%s'\n",yytext); - delete yyextra->argDict; yyextra->argDict=0; + yyextra->argMap.clear(); yyextra->defArgs = -1; yyextra->defArgsStr.resize(0); yyextra->defName = yytext; @@ -1103,7 +1021,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->expectGuard=FALSE; } <DefName>{ID}/{B}*"\n" { // empty define - delete yyextra->argDict; yyextra->argDict=0; + yyextra->argMap.clear(); yyextra->defArgs = -1; yyextra->defName = yytext; yyextra->defArgsStr.resize(0); @@ -1132,7 +1050,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <DefName>{ID}/{B}* { // define with content //printf("Define '%s'\n",yytext); - delete yyextra->argDict; yyextra->argDict=0; + yyextra->argMap.clear(); yyextra->defArgs = -1; yyextra->defArgsStr.resize(0); yyextra->defText.resize(0); @@ -1162,7 +1080,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefineArg>"..." { // Variadic macro yyextra->defVarArgs = TRUE; yyextra->defArgsStr+=yytext; - yyextra->argDict->insert("__VA_ARGS__",new int(yyextra->defArgs)); + yyextra->argMap.emplace(std::string("__VA_ARGS__"),yyextra->defArgs); yyextra->defArgs++; } <DefineArg>{ID}{B}*("..."?) { @@ -1175,7 +1093,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } argName = argName.stripWhiteSpace(); yyextra->defArgsStr+=yytext; - yyextra->argDict->insert(argName,new int(yyextra->defArgs)); + yyextra->argMap.emplace(toStdString(argName),yyextra->defArgs); yyextra->defArgs++; } /* @@ -1229,27 +1147,27 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <SkipCComment>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT); - if (!markdownSupport) + if (!markdownSupport || !yyextra->isSpecialComment) { REJECT; } else { outputArray(yyscanner,yytext,(int)yyleng); - yyextra->fenceSize=yyleng; + yyextra->fenceSize=(int)yyleng; BEGIN(SkipVerbatim); } } <SkipCComment>^({B}*"*"+)?{B}{0,3}"```"[`]* { bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT); - if (!markdownSupport) + if (!markdownSupport || !yyextra->isSpecialComment) { REJECT; } else { outputArray(yyscanner,yytext,(int)yyleng); - yyextra->fenceSize=yyleng; + yyextra->fenceSize=(int)yyleng; BEGIN(SkipVerbatim); } } @@ -1389,14 +1307,14 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <SkipVerbatim>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { outputArray(yyscanner,yytext,(int)yyleng); - if (yyextra->fenceSize==yyleng) + if (yyextra->fenceSize==(yy_size_t)yyleng) { BEGIN(SkipCComment); } } <SkipVerbatim>^({B}*"*"+)?{B}{0,3}"```"[`]* { outputArray(yyscanner,yytext,(int)yyleng); - if (yyextra->fenceSize==yyleng) + if (yyextra->fenceSize==(yy_size_t)yyleng) { BEGIN(SkipCComment); } @@ -1485,15 +1403,12 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } if (yyextra->defArgs>0) { - int *n; - if ((n=(*yyextra->argDict)[yytext])) + auto it = yyextra->argMap.find(yytext); + if (it!=yyextra->argMap.end()) { - //if (!yyextra->quoteArg) yyextra->defText+=' '; + int n = it->second; yyextra->defText+='@'; - QCString numStr; - numStr.sprintf("%d",*n); - yyextra->defText+=numStr; - //if (!yyextra->quoteArg) yyextra->defText+=' '; + yyextra->defText+=QCString().setNum(n); } else { @@ -1532,22 +1447,15 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputChar(yyscanner,'\n'); Define *def=0; //printf("Define name='%s' text='%s' litTexti='%s'\n",yyextra->defName.data(),yyextra->defText.data(),yyextra->defLitText.data()); - if (yyextra->includeStack.isEmpty() || yyextra->curlyCount>0) + if (yyextra->includeStack.empty() || yyextra->curlyCount>0) { - addDefine(yyscanner); + addMacroDefinition(yyscanner); } - def=yyextra->defineManager.isDefined(yyextra->defName); + def=isDefined(yyscanner,yyextra->defName); if (def==0) // new define { //printf("new define '%s'!\n",yyextra->defName.data()); - Define *nd = newDefine(yyscanner); - yyextra->defineManager.addDefine(yyextra->yyFileName,nd); - - // also add it to the local file list if it is a source file - //if (yyextra->isSource && yyextra->includeStack.isEmpty()) - //{ - // yyextra->fileDefineDict->insert(yyextra->defName,nd); - //} + addDefine(yyscanner); } else if (def /*&& macroIsAccessible(def)*/) // name already exists @@ -1569,7 +1477,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) //printf("error: define %s is defined more than once!\n",yyextra->defName.data()); } } - delete yyextra->argDict; yyextra->argDict=0; + yyextra->argMap.clear(); yyextra->yyLineNr++; yyextra->yyColNr=1; yyextra->lastGuardName.resize(0); @@ -1611,15 +1519,16 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefineText>. { yyextra->defText += *yytext; yyextra->defLitText+=yytext; } <<EOF>> { DBG_CTX((stderr,"End of include file\n")); - //printf("Include stack depth=%d\n",yyextra->includeStack.count()); - if (yyextra->includeStack.isEmpty()) + //printf("Include stack depth=%d\n",yyextra->includeStack.size()); + if (yyextra->includeStack.empty()) { DBG_CTX((stderr,"Terminating scanner!\n")); yyterminate(); } else { - FileState *fs=yyextra->includeStack.pop(); + QCString toFileName = yyextra->yyFileName; + const std::unique_ptr<FileState> &fs=yyextra->includeStack.back(); //fileDefineCache->merge(yyextra->yyFileName,fs->fileName); YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER; yy_switch_to_buffer( fs->bufState, yyscanner ); @@ -1628,21 +1537,53 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) //preYYin = fs->oldYYin; yyextra->inputBuf = fs->oldFileBuf; yyextra->inputBufPos = fs->oldFileBufPos; - yyextra->curlyCount = fs->curlyCount; + yyextra->curlyCount = fs->curlyCount; setFileName(yyscanner,fs->fileName); DBG_CTX((stderr,"######## FileName %s\n",yyextra->yyFileName.data())); - + // Deal with file changes due to // #include's within { .. } blocks QCString lineStr(15+yyextra->yyFileName.length()); lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,yyextra->yyFileName.data()); outputArray(yyscanner,lineStr.data(),lineStr.length()); - - delete fs; fs=0; + + yyextra->includeStack.pop_back(); + + { + std::lock_guard<std::mutex> lock(g_globalDefineMutex); + // to avoid deadlocks we allow multiple threads to process the same header file. + // The first one to finish will store the results globally. After that the + // next time the same file is encountered, the stored data is used and the file + // is not processed again. + if (!g_defineManager.alreadyProcessed(toFileName.str())) + { + // now that the file is completely processed, prevent it from processing it again + g_defineManager.addInclude(yyextra->yyFileName.str(),toFileName.str()); + g_defineManager.store(toFileName.str(),yyextra->localDefines); + } + else + { + if (Debug::isFlagSet(Debug::Preprocessor)) + { + Debug::print(Debug::Preprocessor,0,"#include %s: was already processed by another thread! not storing data...\n",qPrint(toFileName)); + } + } + } + // move the local macros definitions for in this file to the translation unit context + for (const auto &kv : yyextra->localDefines) + { + auto pair = yyextra->contextDefines.insert(kv); + if (!pair.second) // define already in context -> replace with local version + { + yyextra->contextDefines.erase(pair.first); + yyextra->contextDefines.insert(kv); + } + } + yyextra->localDefines.clear(); } } <*>"/*"/"*/" | -<*>"/*"[*]? { +<*>"/*"[*!]? { if (YY_START==SkipVerbatim || YY_START==SkipCond) { REJECT; @@ -1652,11 +1593,19 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); yyextra->lastCContext=YY_START; yyextra->commentCount=1; - if (yyleng==3) yyextra->lastGuardName.resize(0); // reset guard in case the #define is documented! + if (yyleng==3) + { + yyextra->isSpecialComment = true; + yyextra->lastGuardName.resize(0); // reset guard in case the #define is documented! + } + else + { + yyextra->isSpecialComment = false; + } BEGIN(SkipCComment); } } -<*>"//"[/]? { +<*>"//"[/!]? { if (YY_START==SkipVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran) { REJECT; @@ -1665,7 +1614,15 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) { outputArray(yyscanner,yytext,(int)yyleng); yyextra->lastCPPContext=YY_START; - if (yyleng==3) yyextra->lastGuardName.resize(0); // reset guard in case the #define is documented! + if (yyleng==3) + { + yyextra->isSpecialComment = true; + yyextra->lastGuardName.resize(0); // reset guard in case the #define is documented! + } + else + { + yyextra->isSpecialComment = false; + } BEGIN(SkipCPPComment); } } @@ -1682,11 +1639,11 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) ///////////////////////////////////////////////////////////////////////////////////// -static int yyread(yyscan_t yyscanner,char *buf,int max_size) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - int bytesInBuf = state->inputBuf->curPos()-state->inputBufPos; - int bytesToCopy = QMIN(max_size,bytesInBuf); + yy_size_t bytesInBuf = state->inputBuf->curPos()-state->inputBufPos; + yy_size_t bytesToCopy = QMIN(max_size,bytesInBuf); memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy); state->inputBufPos+=bytesToCopy; return bytesToCopy; @@ -1698,36 +1655,34 @@ static void setFileName(yyscan_t yyscanner,const char *name) bool ambig; QFileInfo fi(name); state->yyFileName=fi.absFilePath().utf8(); - state->yyFileDef=findFileDef(Doxygen::inputNameDict,state->yyFileName,ambig); + state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->yyFileName,ambig); if (state->yyFileDef==0) // if this is not an input file check if it is an // include file { - state->yyFileDef=findFileDef(Doxygen::includeNameDict,state->yyFileName,ambig); + state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->yyFileName,ambig); } //printf("setFileName(%s) state->yyFileName=%s state->yyFileDef=%p\n", // name,state->yyFileName.data(),state->yyFileDef); if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=0; state->insideCS = getLanguageFromFileName(state->yyFileName)==SrcLangExt_CSharp; + state->insideFtn = getLanguageFromFileName(state->yyFileName)==SrcLangExt_Fortran; state->isSource = guessSection(state->yyFileName); } static void incrLevel(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - state->level++; - state->levelGuard.resize(state->level); - state->levelGuard[state->level-1]=FALSE; - //printf("%s line %d: incrLevel %d\n",yyextra->yyFileName.data(),yyextra->yyLineNr,yyextra->level); + state->levelGuard.push(false); + //printf("%s line %d: incrLevel %d\n",yyextra->yyFileName.data(),yyextra->yyLineNr,yyextra->levelGuard.size()); } static void decrLevel(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - //printf("%s line %d: decrLevel %d\n",state->yyFileName.data(),state->yyLineNr,state->level); - if (state->level > 0) + //printf("%s line %d: decrLevel %d\n",state->yyFileName.data(),state->yyLineNr,state->levelGuard.size()); + if (!state->levelGuard.empty()) { - state->level--; - state->levelGuard.resize(state->level); + state->levelGuard.pop(); } else { @@ -1738,65 +1693,59 @@ static void decrLevel(yyscan_t yyscanner) static bool otherCaseDone(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - if (state->level==0) + if (state->levelGuard.empty()) { warn(state->yyFileName,state->yyLineNr,"Found an #else without a preceding #if.\n"); return TRUE; } else { - return state->levelGuard[state->level-1]; + return state->levelGuard.top(); } } static void setCaseDone(yyscan_t yyscanner,bool value) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - state->levelGuard[state->level-1]=value; + state->levelGuard.top()=value; } -static FileState *checkAndOpenFile(yyscan_t yyscanner,const QCString &fileName,bool &alreadyIncluded) +static FileState *checkAndOpenFile(yyscan_t yyscanner,const QCString &fileName,bool &alreadyProcessed) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - alreadyIncluded = FALSE; + alreadyProcessed = FALSE; FileState *fs = 0; //printf("checkAndOpenFile(%s)\n",fileName.data()); QFileInfo fi(fileName); if (fi.exists() && fi.isFile()) { - const QStrList &exclPatterns = Config_getList(EXCLUDE_PATTERNS); - if (patternMatch(fi,&exclPatterns)) return 0; + const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS); + if (patternMatch(fi,exclPatterns)) return 0; QCString absName = fi.absFilePath().utf8(); // global guard if (state->curlyCount==0) // not #include inside { ... } { - if (state->allIncludes.find(absName)!=0) + std::lock_guard<std::mutex> lock(g_globalDefineMutex); + if (g_defineManager.alreadyProcessed(absName.str())) { - alreadyIncluded = TRUE; + alreadyProcessed = TRUE; //printf(" already included 1\n"); return 0; // already done } - state->allIncludes.insert(absName,(void *)0x8); } // check include stack for absName - QStack<FileState> tmpStack; - state->includeStack.setAutoDelete(FALSE); - while ((fs=state->includeStack.pop())) - { - if (fs->fileName==absName) alreadyIncluded=TRUE; - tmpStack.push(fs); - } - while ((fs=tmpStack.pop())) - { - state->includeStack.push(fs); - } - state->includeStack.setAutoDelete(TRUE); + alreadyProcessed = std::any_of( + state->includeStack.begin(), + state->includeStack.end(), + [absName](const std::unique_ptr<FileState> &lfs) + { return lfs->fileName==absName; } + ); - if (alreadyIncluded) + if (alreadyProcessed) { //printf(" already included 2\n"); return 0; @@ -1804,7 +1753,6 @@ static FileState *checkAndOpenFile(yyscan_t yyscanner,const QCString &fileName,b //printf("#include %s\n",absName.data()); fs = new FileState(fi.size()+4096); - alreadyIncluded = FALSE; if (!readInputFile(absName,fs->fileBuf)) { // error //printf(" error reading\n"); @@ -1820,20 +1768,20 @@ static FileState *checkAndOpenFile(yyscan_t yyscanner,const QCString &fileName,b return fs; } -static FileState *findFile(yyscan_t yyscanner, const char *fileName,bool localInclude,bool &alreadyIncluded) +static FileState *findFile(yyscan_t yyscanner, const char *fileName,bool localInclude,bool &alreadyProcessed) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); //printf("** findFile(%s,%d) state->yyFileName=%s\n",fileName,localInclude,state->yyFileName.data()); if (Portable::isAbsolutePath(fileName)) { - FileState *fs = checkAndOpenFile(yyscanner,fileName,alreadyIncluded); + FileState *fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed); if (fs) { setFileName(yyscanner,fileName); state->yyLineNr=1; return fs; } - else if (alreadyIncluded) + else if (alreadyProcessed) { return 0; } @@ -1844,50 +1792,47 @@ static FileState *findFile(yyscan_t yyscanner, const char *fileName,bool localIn if (fi.exists()) { QCString absName = QCString(fi.dirPath(TRUE).data())+"/"+fileName; - FileState *fs = checkAndOpenFile(yyscanner,absName,alreadyIncluded); + FileState *fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed); if (fs) { setFileName(yyscanner,absName); state->yyLineNr=1; return fs; } - else if (alreadyIncluded) + else if (alreadyProcessed) { return 0; } } } - if (state->pathList==0) + if (state->pathList.empty()) { return 0; } - char *s=state->pathList->first(); - while (s) + for (auto path : state->pathList) { - QCString absName = (QCString)s+"/"+fileName; - //printf(" Looking for %s in %s\n",fileName,s); - FileState *fs = checkAndOpenFile(yyscanner,absName,alreadyIncluded); + std::string absName = path+"/"+fileName; + //printf(" Looking for %s in %s\n",fileName,path.c_str()); + FileState *fs = checkAndOpenFile(yyscanner,absName.c_str(),alreadyProcessed); if (fs) { - setFileName(yyscanner,absName); + setFileName(yyscanner,absName.c_str()); state->yyLineNr=1; //printf(" -> found it\n"); return fs; } - else if (alreadyIncluded) + else if (alreadyProcessed) { return 0; } - - s=state->pathList->next(); - } + } return 0; } static QCString extractTrailingComment(const char *s) { if (s==0) return ""; - int i=strlen(s)-1; + int i=(int)strlen(s)-1; while (i>=0) { char c=s[i]; @@ -1989,7 +1934,7 @@ static QCString stringize(const QCString &s) pc=0; while (i<s.length() && inString) { - char c=s.at(i++); + c=s.at(i++); if (c=='"') { result+="\\\""; @@ -2070,7 +2015,7 @@ static inline void addTillEndOfString(yyscan_t yyscanner,const QCString &expr,QC static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCString *rest,int pos,int &len,const Define *def,QCString &result,int level) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - //printf(">replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s') level=%d\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),state->level); + //printf(">replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s') level=%d\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),state->levelGuard.size()); uint j=pos; len=0; result.resize(0); @@ -2082,13 +2027,12 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin } if (cc!='(') { - unputChar(yyscanner,expr,rest,j,cc); + unputChar(yyscanner,expr,rest,j,(char)cc); return FALSE; } getNextChar(yyscanner,expr,rest,j); // eat the '(' character - QDict<QCString> argTable; // list of arguments - argTable.setAutoDelete(TRUE); + std::map<std::string,std::string> argTable; // list of arguments QCString arg; int argCount=0; bool done=FALSE; @@ -2111,12 +2055,12 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin char c=(char)cc; if (c=='(') // argument is a function => search for matching ) { - int level=1; + int lvl=1; arg+=c; //char term='\0'; while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0) { - char c=(char)cc; + c=(char)cc; //printf("processing %c: term=%c (%d)\n",c,term,term); if (c=='\'' || c=='\"') // skip ('s and )'s inside strings { @@ -2125,13 +2069,13 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin } if (c==')') { - level--; + lvl--; arg+=c; - if (level==0) break; + if (lvl==0) break; } else if (c=='(') { - level++; + lvl++; arg+=c; } else @@ -2151,7 +2095,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin argKey.sprintf("@%d",argCount++); // key name arg=arg.stripWhiteSpace(); // add argument to the lookup table - argTable.insert(argKey, new QCString(arg)); + argTable.emplace(toStdString(argKey), toStdString(arg)); arg.resize(0); if (c==')') // end of the argument list { @@ -2243,7 +2187,6 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin else // argument marker => read the argument number { QCString key="@"; - QCString *subst=0; bool hash=FALSE; int l=k-1; // search for ## backward @@ -2262,9 +2205,10 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=TRUE; } //printf("request key %s result %s\n",key.data(),argTable[key]->data()); - if (key.length()>1 && (subst=argTable[key])) + auto it = argTable.find(key.data()); + if (it!=argTable.end()) { - QCString substArg=*subst; + QCString substArg = it->second.c_str(); //printf("substArg='%s'\n",substArg.data()); // only if no ## operator is before or after the argument // marker we do macro expansion. @@ -2313,10 +2257,10 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin } len=j-pos; result=resExpr; - //printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%d return=TRUE\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),result.data(),state->level); + //printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%d return=TRUE\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),result.data(),state->levelGuard.size()); return TRUE; } - //printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%d return=FALSE\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),result.data(),state->level); + //printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%d return=FALSE\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),result.data(),state->levelGuard.size()); return FALSE; } @@ -2379,6 +2323,8 @@ static int getNextId(const QCString &expr,int p,int *l) return -1; } +#define MAX_EXPANSION_DEPTH 50 + /*! performs recursive macro expansion on the string \a expr * starting at position \a pos. * May read additional characters from the input while re-scanning! @@ -2392,19 +2338,22 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in //printf("<expandExpression: empty\n"); return TRUE; } - if (state->expansionDict.find(expr)!=0) // check for recursive expansions + if (state->expanded.find(expr.data())!=state->expanded.end() && + level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions { //printf("<expandExpression: already expanded expr='%s'\n",expr.data()); return FALSE; } else { - state->expansionDict.insert(expr,(void*)0x8); + state->expanded.insert(expr.data()); } QCString macroName; QCString expMacro; bool definedTest=FALSE; int i=pos,l,p,len; + int startPos = pos; + int samePosCount=0; while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name { bool replaced=FALSE; @@ -2412,9 +2361,9 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in //printf(" p=%d macroName=%s\n",p,macroName.data()); if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker? { - if (state->expandedDict->find(macroName)==0) // expand macro + if (state->expandedDict.find(macroName.data())==state->expandedDict.end()) // expand macro { - Define *def=state->defineManager.isDefined(macroName); + Define *def=isDefined(yyscanner,macroName); if (macroName=="defined") { //printf("found defined inside macro definition '%s'\n",expr.right(expr.length()-p).data()); @@ -2463,9 +2412,9 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in bool expanded=false; if (def && !def->nonRecursive) { - state->expandedDict->insert(macroName,def); + state->expandedDict.emplace(toStdString(macroName),def); expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1); - state->expandedDict->remove(macroName); + state->expandedDict.erase(toStdString(macroName)); } if (expanded) { @@ -2492,6 +2441,20 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in i=p+l+2; //i=p+l; } + // check for too many inplace expansions without making progress + if (i==startPos) + { + samePosCount++; + } + else + { + startPos=i; + samePosCount=0; + } + if (samePosCount>MAX_EXPANSION_DEPTH) + { + break; + } } else // no re-scan marker found, skip the macro name { @@ -2650,7 +2613,7 @@ static QCString removeIdsAndMarkers(const char *s) { nextChar: result+=c; - char lc=tolower(c); + char lc=(char)tolower(c); if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=FALSE; p++; } @@ -2729,7 +2692,7 @@ static bool computeExpression(yyscan_t yyscanner,const QCString &expr) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); QCString e=expr; - state->expansionDict.clear(); + state->expanded.clear(); expandExpression(yyscanner,e,0,0,0); //printf("after expansion '%s'\n",e.data()); e = removeIdsAndMarkers(e); @@ -2746,118 +2709,138 @@ static QCString expandMacro(yyscan_t yyscanner,const QCString &name) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); QCString n=name; - state->expansionDict.clear(); + state->expanded.clear(); expandExpression(yyscanner,n,0,0,0); n=removeMarkers(n); //printf("expandMacro '%s'->'%s'\n",name.data(),n.data()); return n; } -static Define *newDefine(yyscan_t yyscanner) +static void addDefine(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - Define *def=new Define; - def->name = state->defName; - def->definition = state->defText.stripWhiteSpace(); - def->nargs = state->defArgs; - def->fileName = state->yyFileName; - def->fileDef = state->yyFileDef; - def->lineNr = state->yyLineNr-state->yyMLines; - def->columnNr = state->yyColNr; - def->varArgs = state->defVarArgs; - //printf("newDefine: %s %s file: %s\n",def->name.data(),def->definition.data(), - // def->fileDef ? def->fileDef->name().data() : def->fileName.data()); - //printf("newDefine: '%s'->'%s'\n",def->name.data(),def->definition.data()); - if (!def->name.isEmpty() && Doxygen::expandAsDefinedDict[def->name]) + Define def; + def.name = state->defName; + def.definition = state->defText.stripWhiteSpace(); + def.nargs = state->defArgs; + def.fileName = state->yyFileName; + def.fileDef = state->yyFileDef; + def.lineNr = state->yyLineNr-state->yyMLines; + def.columnNr = state->yyColNr; + def.varArgs = state->defVarArgs; + //printf("newDefine: %s %s file: %s\n",def.name.data(),def.definition.data(), + // def.fileDef ? def.fileDef->name().data() : def.fileName.data()); + //printf("newDefine: '%s'->'%s'\n",def.name.data(),def.definition.data()); + if (!def.name.isEmpty() && + Doxygen::expandAsDefinedSet.find(def.name.str())!=Doxygen::expandAsDefinedSet.end()) { - def->isPredefined=TRUE; + def.isPredefined=TRUE; } - return def; + auto it = state->localDefines.find(def.name.str()); + if (it!=state->localDefines.end()) // redefine + { + state->localDefines.erase(it); + } + state->localDefines.insert(std::make_pair(def.name.str(),def)); } -static void addDefine(yyscan_t yyscanner) +static void addMacroDefinition(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); if (state->skip) return; // do not add this define as it is inside a // conditional section (cond command) that is disabled. - if (!Doxygen::gatherDefines) return; - - //printf("addDefine '%s' '%s'\n",state->defName.data(),state->defArgsStr.data()); - //ArgumentList *al = new ArgumentList; - //stringToArgumentList(state->defArgsStr,al); - MemberDef *md=createMemberDef( - state->yyFileName,state->yyLineNr-state->yyMLines,state->yyColNr, - "#define",state->defName,state->defArgsStr,0, - Public,Normal,FALSE,Member,MemberType_Define,ArgumentList(),ArgumentList(),""); - if (!state->defArgsStr.isEmpty()) - { - ArgumentList argList; - //printf("addDefine() state->defName='%s' state->defArgsStr='%s'\n",state->defName.data(),state->defArgsStr.data()); - stringToArgumentList(SrcLangExt_Cpp, state->defArgsStr,argList); - md->setArgumentList(argList); - } - //printf("Setting initializer for '%s' to '%s'\n",state->defName.data(),state->defText.data()); - int l=state->defLitText.find('\n'); - if (l>0 && state->defLitText.left(l).stripWhiteSpace()=="\\") + + Define define; + define.fileName = state->yyFileName; + define.lineNr = state->yyLineNr - state->yyMLines; + define.columnNr = state->yyColNr; + define.name = state->defName; + define.args = state->defArgsStr; + define.fileDef = state->inputFileDef; + + QCString litText = state->defLitText; + int l=litText.find('\n'); + if (l>0 && litText.left(l).stripWhiteSpace()=="\\") { // strip first line if it only contains a slash - state->defLitText = state->defLitText.right(state->defLitText.length()-l-1); + litText = litText.right(litText.length()-l-1); } else if (l>0) { // align the items on the first line with the items on the second line int k=l+1; - const char *p=state->defLitText.data()+k; + const char *p=litText.data()+k; char c; while ((c=*p++) && (c==' ' || c=='\t')) k++; - state->defLitText=state->defLitText.mid(l+1,k-l-1)+state->defLitText.stripWhiteSpace(); + litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace(); } - QCString defLitTextStripped = state->defLitText.stripWhiteSpace(); - if (defLitTextStripped.contains('\n')>=1) + QCString litTextStripped = state->defLitText.stripWhiteSpace(); + if (litTextStripped.contains('\n')>=1) { - md->setInitializer(state->defLitText); + define.definition = litText; } else { - md->setInitializer(defLitTextStripped); - } - - //printf("pre.l: md->setFileDef(%p)\n",state->inputFileDef); - md->setFileDef(state->inputFileDef); - md->setDefinition("#define "+state->defName); - - MemberName *mn=Doxygen::functionNameSDict->find(state->defName); - if (mn==0) - { - mn = new MemberName(state->defName); - Doxygen::functionNameSDict->append(state->defName,mn); + define.definition = litTextStripped; } - mn->append(md); - if (state->yyFileDef) { - state->yyFileDef->insertMember(md); + state->macroDefinitions.push_back(define); } - - //Define *d; - //if ((d=defineDict[state->defName])==0) defineDict.insert(state->defName,newDefine()); } static inline void outputChar(yyscan_t yyscanner,char c) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - if (state->includeStack.isEmpty() || state->curlyCount>0) state->outputBuf->addChar(c); + if (state->includeStack.empty() || state->curlyCount>0) state->outputBuf->addChar(c); } static inline void outputArray(yyscan_t yyscanner,const char *a,int len) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - if (state->includeStack.isEmpty() || state->curlyCount>0) state->outputBuf->addArray(a,len); + if (state->includeStack.empty() || state->curlyCount>0) state->outputBuf->addArray(a,len); +} + +static QCString determineAbsoluteIncludeName(const QCString &curFile,const QCString &incFileName) +{ + bool searchIncludes = Config_getBool(SEARCH_INCLUDES); + QCString absIncFileName = incFileName; + QFileInfo fi(curFile); + if (fi.exists()) + { + QCString absName = QCString(fi.dirPath(TRUE).data())+"/"+incFileName; + QFileInfo fi2(absName); + if (fi2.exists()) + { + absIncFileName=fi2.absFilePath().utf8(); + } + else if (searchIncludes) // search in INCLUDE_PATH as well + { + const StringVector &includePath = Config_getList(INCLUDE_PATH); + for (const auto &incPath : includePath) + { + QFileInfo fi3(incPath.c_str()); + if (fi3.exists() && fi3.isDir()) + { + absName = QCString(fi3.absFilePath().utf8())+"/"+incFileName; + //printf("trying absName=%s\n",absName.data()); + QFileInfo fi4(absName); + if (fi4.exists()) + { + absIncFileName=fi4.absFilePath().utf8(); + break; + } + //printf( "absIncFileName = %s\n", absIncFileName.data() ); + } + } + } + //printf( "absIncFileName = %s\n", absIncFileName.data() ); + } + return absIncFileName; } static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - static bool searchIncludes = Config_getBool(SEARCH_INCLUDES); uint i=0; // find the start of the include file name @@ -2889,79 +2872,47 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) int oldLineNr = state->yyLineNr; //printf("Searching for '%s'\n",incFileName.data()); - // absIncFileName avoids difficulties for incFileName starting with "../" (bug 641336) - QCString absIncFileName = incFileName; - { - QFileInfo fi(state->yyFileName); - if (fi.exists()) - { - QCString absName = QCString(fi.dirPath(TRUE).data())+"/"+incFileName; - QFileInfo fi2(absName); - if (fi2.exists()) - { - absIncFileName=fi2.absFilePath().utf8(); - } - else if (searchIncludes) // search in INCLUDE_PATH as well - { - QStrList &includePath = Config_getList(INCLUDE_PATH); - char *s=includePath.first(); - while (s) - { - QFileInfo fi(s); - if (fi.exists() && fi.isDir()) - { - QCString absName = QCString(fi.absFilePath().utf8())+"/"+incFileName; - //printf("trying absName=%s\n",absName.data()); - QFileInfo fi2(absName); - if (fi2.exists()) - { - absIncFileName=fi2.absFilePath().utf8(); - break; - } - //printf( "absIncFileName = %s\n", absIncFileName.data() ); - } - s=includePath.next(); - } - } - //printf( "absIncFileName = %s\n", absIncFileName.data() ); - } - } - state->defineManager.addInclude(state->yyFileName,absIncFileName); - state->defineManager.addFileToContext(absIncFileName); + QCString absIncFileName = determineAbsoluteIncludeName(state->yyFileName,incFileName); // findFile will overwrite state->yyFileDef if found FileState *fs; - bool alreadyIncluded = FALSE; + bool alreadyProcessed = FALSE; //printf("calling findFile(%s)\n",incFileName.data()); - if ((fs=findFile(yyscanner,incFileName,localInclude,alreadyIncluded))) // see if the include file can be found + if ((fs=findFile(yyscanner,incFileName,localInclude,alreadyProcessed))) // see if the include file can be found { + { + std::lock_guard<std::mutex> lock(g_globalDefineMutex); + g_defineManager.addInclude(oldFileName.str(),absIncFileName.str()); + } + //printf("Found include file!\n"); if (Debug::isFlagSet(Debug::Preprocessor)) { - for (i=0;i<state->includeStack.count();i++) + for (i=0;i<state->includeStack.size();i++) { Debug::print(Debug::Preprocessor,0," "); } - //msg("#include %s: parsing...\n",incFileName.data()); + Debug::print(Debug::Preprocessor,0,"#include %s: parsing...\n",incFileName.data()); } - if (oldFileDef) + + if (state->includeStack.empty() && oldFileDef) { - // add include dependency to the file in which the #include was found - bool ambig; - // change to absolute name for bug 641336 - FileDef *incFd = findFileDef(Doxygen::inputNameDict,absIncFileName,ambig); - oldFileDef->addIncludeDependency(ambig ? 0 : incFd,incFileName,localInclude,state->isImported,FALSE); - // add included by dependency - if (state->yyFileDef) + PreIncludeInfo *ii = state->includeRelations.find(absIncFileName); + if (ii==0) { - //printf("Adding include dependency %s->%s\n",oldFileDef->name().data(),incFileName.data()); - state->yyFileDef->addIncludedByDependency(oldFileDef,oldFileDef->docName(),localInclude,state->isImported); + bool ambig; + FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig); + state->includeRelations.add( + absIncFileName, + oldFileDef, + ambig?nullptr:incFd, + incFileName, + localInclude, + state->isImported + ); } } - else if (state->inputFileDef) - { - state->inputFileDef->addIncludeDependency(0,absIncFileName,localInclude,state->isImported,TRUE); - } + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; fs->bufState = YY_CURRENT_BUFFER; fs->lineNr = oldLineNr; @@ -2969,7 +2920,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) fs->curlyCount = state->curlyCount; state->curlyCount = 0; // push the state on the stack - state->includeStack.push(fs); + state->includeStack.emplace_back(fs); // set the scanner to the include file // Deal with file changes due to @@ -2986,38 +2937,40 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) } else { - //printf(" calling findFile(%s) alreadyInc=%d\n",incFileName.data(),alreadyIncluded); - if (oldFileDef) + if (alreadyProcessed) // if this header was already process we can just copy the stored macros + // in the local context { - bool ambig; - //QCString absPath = incFileName; - //if (QDir::isRelativePath(incFileName)) - //{ - // absPath = QDir::cleanDirPath(oldFileDef->getPath()+"/"+incFileName); - // //printf("%s + %s -> resolved path %s\n",oldFileDef->getPath().data(),incFileName.data(),absPath.data()); - //} - - // change to absolute name for bug 641336 - FileDef *fd = findFileDef(Doxygen::inputNameDict,absIncFileName,ambig); - //printf("%s::findFileDef(%s)=%p\n",oldFileDef->name().data(),incFileName.data(),fd); - // add include dependency to the file in which the #include was found - oldFileDef->addIncludeDependency(ambig ? 0 : fd,incFileName,localInclude,state->isImported,FALSE); - // add included by dependency - if (fd) - { - //printf("Adding include dependency (2) %s->%s ambig=%d\n",oldFileDef->name().data(),fd->name().data(),ambig); - fd->addIncludedByDependency(oldFileDef,oldFileDef->docName(),localInclude,state->isImported); - } + std::lock_guard<std::mutex> lock(g_globalDefineMutex); + g_defineManager.addInclude(state->yyFileName.str(),absIncFileName.str()); + g_defineManager.retrieve(absIncFileName.str(),state->contextDefines); } - else if (state->inputFileDef) + + if (state->includeStack.empty() && oldFileDef) { - state->inputFileDef->addIncludeDependency(0,absIncFileName,localInclude,state->isImported,TRUE); + PreIncludeInfo *ii = state->includeRelations.find(absIncFileName); + if (ii==0) + { + bool ambig; + FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig); + ii = state->includeRelations.add(absIncFileName, + oldFileDef, + ambig?0:incFd, + incFileName, + localInclude, + state->isImported + ); + } } + if (Debug::isFlagSet(Debug::Preprocessor)) { - if (alreadyIncluded) + for (i=0;i<state->includeStack.size();i++) + { + Debug::print(Debug::Preprocessor,0," "); + } + if (alreadyProcessed) { - Debug::print(Debug::Preprocessor,0,"#include %s: already included! skipping...\n",qPrint(incFileName)); + Debug::print(Debug::Preprocessor,0,"#include %s: already processed! skipping...\n",qPrint(incFileName)); } else { @@ -3025,7 +2978,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) } //printf("error: include file %s not found\n",yytext); } - if (state->curlyCount>0 && !alreadyIncluded) // failed to find #include inside { ... } + if (state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... } { warn(state->yyFileName,state->yyLineNr,"include file %s not found, perhaps you forgot to add its directory to INCLUDE_PATH?",incFileName.data()); } @@ -3038,10 +2991,10 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) static void startCondSection(yyscan_t yyscanner,const char *sectId) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count()); + //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size()); CondParser prs; bool expResult = prs.parse(state->yyFileName,state->yyLineNr,sectId); - state->condStack.push(new CondCtx(state->yyLineNr,sectId,state->skip)); + state->condStack.emplace(std::make_unique<CondCtx>(state->yyLineNr,sectId,state->skip)); if (!expResult) { state->skip=TRUE; @@ -3052,15 +3005,15 @@ static void startCondSection(yyscan_t yyscanner,const char *sectId) static void endCondSection(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - if (state->condStack.isEmpty()) + if (state->condStack.empty()) { state->skip=FALSE; } else { - CondCtx *ctx = state->condStack.pop(); + const std::unique_ptr<CondCtx> &ctx = state->condStack.top(); state->skip=ctx->skip; - delete ctx; + state->condStack.pop(); } //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count()); } @@ -3068,9 +3021,9 @@ static void endCondSection(yyscan_t yyscanner) static void forceEndCondSection(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - while (!state->condStack.isEmpty()) + while (!state->condStack.empty()) { - delete state->condStack.pop(); + state->condStack.pop(); } state->skip=FALSE; } @@ -3150,8 +3103,7 @@ static int getCurrentChar(yyscan_t yyscanner,const QCString &expr,QCString *rest else { int cc=yyinput(yyscanner); - returnCharToStream(yyscanner,cc); - //unput((char)cc); + returnCharToStream(yyscanner,(char)cc); //printf("%c=yyinput()\n",cc); return cc; } @@ -3178,45 +3130,184 @@ static void unputChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,uin //printf("result: unputChar(%s,%s,%d,%c)\n",expr.data(),rest ? rest->data() : 0,pos,c); } +/** Returns a reference to a Define object given its name or 0 if the Define does + * not exist. + */ +static Define *isDefined(yyscan_t yyscanner,const char *name) +{ + YY_EXTRA_TYPE state = preYYget_extra(yyscanner); + + bool undef = false; + auto findDefine = [&undef,&name](DefineMap &map) + { + Define *d=0; + auto it = map.find(name); + if (it!=map.end()) + { + d = &it->second; + if (d->undef) + { + undef=true; + d=0; + } + } + return d; + }; + + Define *def = findDefine(state->localDefines); + if (def==0 && !undef) + { + def = findDefine(state->contextDefines); + } + return def; +} + +static void initPredefined(yyscan_t yyscanner,const char *fileName) +{ + YY_EXTRA_TYPE state = preYYget_extra(yyscanner); + + // add predefined macros + const StringVector &predefList = Config_getList(PREDEFINED); + for (const auto &defStr : predefList) + { + QCString ds = defStr.c_str(); + int i_equals=ds.find('='); + int i_obrace=ds.find('('); + int i_cbrace=ds.find(')'); + bool nonRecursive = i_equals>0 && ds.at(i_equals-1)==':'; + + if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds.at(i_equals-1)==':')) + { + continue; // no define name + } + + if (i_obrace<i_equals && i_cbrace<i_equals && + i_obrace!=-1 && i_cbrace!=-1 && + i_obrace<i_cbrace + ) // predefined function macro definition + { + //printf("predefined function macro '%s'\n",defStr); + QRegExp reId("[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*"); // regexp matching an id + std::map<std::string,int> argMap; + int i=i_obrace+1,pi,l,count=0; + // gather the formal arguments in a dictionary + while (i<i_cbrace && (pi=reId.match(ds,i,&l))) + { + if (l>0) // see bug375037 + { + argMap.emplace(toStdString(ds.mid(pi,l)),count); + count++; + i=pi+l; + } + else + { + i++; + } + } + // strip definition part + QCString tmp=ds.right(ds.length()-i_equals-1); + QCString definition; + i=0; + // substitute all occurrences of formal arguments by their + // corresponding markers + while ((pi=reId.match(tmp,i,&l))!=-1) + { + if (pi>i) definition+=tmp.mid(i,pi-i); + auto it = argMap.find(tmp.mid(pi,l).data()); + if (it!=argMap.end()) + { + int argIndex = it->second; + QCString marker; + marker.sprintf(" @%d ",argIndex); + definition+=marker; + } + else + { + definition+=tmp.mid(pi,l); + } + i=pi+l; + } + if (i<(int)tmp.length()) definition+=tmp.mid(i,tmp.length()-i); + + // add define definition to the dictionary of defines for this file + QCString dname = ds.left(i_obrace); + if (!dname.isEmpty()) + { + Define def; + def.name = dname; + def.definition = definition; + def.nargs = count; + def.isPredefined = TRUE; + def.nonRecursive = nonRecursive; + def.fileDef = state->yyFileDef; + def.fileName = fileName; + state->contextDefines.insert(std::make_pair(def.name.str(),def)); + + //printf("#define '%s' '%s' #nargs=%d\n", + // def->name.data(),def->definition.data(),def->nargs); + } + + } + else if ((i_obrace==-1 || i_obrace>i_equals) && + (i_cbrace==-1 || i_cbrace>i_equals) && + !ds.isEmpty() && (int)ds.length()>i_equals + ) // predefined non-function macro definition + { + //printf("predefined normal macro '%s'\n",defStr); + Define def; + if (i_equals==-1) // simple define without argument + { + def.name = ds; + def.definition = "1"; // substitute occurrences by 1 (true) + } + else // simple define with argument + { + int ine=i_equals - (nonRecursive ? 1 : 0); + def.name = ds.left(ine); + def.definition = ds.right(ds.length()-i_equals-1); + } + if (!def.name.isEmpty()) + { + def.nargs = -1; + def.isPredefined = TRUE; + def.nonRecursive = nonRecursive; + def.fileDef = state->yyFileDef; + def.fileName = fileName; + state->contextDefines.insert(std::make_pair(def.name.str(),def)); + } + } + } +} + /////////////////////////////////////////////////////////////////////////////////////////////// struct Preprocessor::Private { yyscan_t yyscanner; preYY_state state; - bool firstTime = FALSE; }; void Preprocessor::addSearchDir(const char *dir) { YY_EXTRA_TYPE state = preYYget_extra(p->yyscanner); QFileInfo fi(dir); - if (fi.isDir()) state->pathList->append(fi.absFilePath().utf8()); -} + if (fi.isDir()) state->pathList.push_back(fi.absFilePath().utf8().data()); +} -Preprocessor::Preprocessor() +Preprocessor::Preprocessor() : p(std::make_unique<Private>()) { - p = new Private; preYYlex_init_extra(&p->state,&p->yyscanner); - YY_EXTRA_TYPE state = preYYget_extra(p->yyscanner); - state->pathList = new QStrList; addSearchDir("."); - state->expandedDict = new DefineDict(17); } Preprocessor::~Preprocessor() { - YY_EXTRA_TYPE state = preYYget_extra(p->yyscanner); - delete state->expandedDict; - state->expandedDict=0; - delete state->pathList; - state->pathList=0; preYYlex_destroy(p->yyscanner); - delete p; } void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output) { +// printf("Preprocessor::processFile(%s)\n",fileName); yyscan_t yyscanner = p->yyscanner; YY_EXTRA_TYPE state = preYYget_extra(p->yyscanner); struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; @@ -3238,146 +3329,20 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output state->inputBuf=&input; state->inputBufPos=0; state->outputBuf=&output; - state->includeStack.setAutoDelete(TRUE); state->includeStack.clear(); - state->expandedDict->setAutoDelete(FALSE); - state->expandedDict->clear(); - state->condStack.setAutoDelete(TRUE); - state->condStack.clear(); - //state->fileDefineDict->clear(); + state->expandedDict.clear(); + state->contextDefines.clear(); + while (!state->condStack.empty()) state->condStack.pop(); setFileName(yyscanner,fileName); + state->inputFileDef = state->yyFileDef; - state->defineManager.startContext(state->yyFileName); + //yyextra->defineManager.startContext(state->yyFileName); - p->firstTime=TRUE; - if (p->firstTime) - { - // add predefined macros - char *defStr; - QStrList &predefList = Config_getList(PREDEFINED); - QStrListIterator sli(predefList); - for (sli.toFirst();(defStr=sli.current());++sli) - { - QCString ds = defStr; - int i_equals=ds.find('='); - int i_obrace=ds.find('('); - int i_cbrace=ds.find(')'); - bool nonRecursive = i_equals>0 && ds.at(i_equals-1)==':'; - - if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds.at(i_equals-1)==':')) - { - continue; // no define name - } - - if (i_obrace<i_equals && i_cbrace<i_equals && - i_obrace!=-1 && i_cbrace!=-1 && - i_obrace<i_cbrace - ) // predefined function macro definition - { - //printf("predefined function macro '%s'\n",defStr); - QRegExp reId("[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*"); // regexp matching an id - QDict<int> argDict(17); - argDict.setAutoDelete(TRUE); - int i=i_obrace+1,p,l,count=0; - // gather the formal arguments in a dictionary - while (i<i_cbrace && (p=reId.match(ds,i,&l))) - { - if (l>0) // see bug375037 - { - argDict.insert(ds.mid(p,l),new int(count++)); - i=p+l; - } - else - { - i++; - } - } - // strip definition part - QCString tmp=ds.right(ds.length()-i_equals-1); - QCString definition; - i=0; - // substitute all occurrences of formal arguments by their - // corresponding markers - while ((p=reId.match(tmp,i,&l))!=-1) - { - if (p>i) definition+=tmp.mid(i,p-i); - int *argIndex; - if ((argIndex=argDict[tmp.mid(p,l)])!=0) - { - QCString marker; - marker.sprintf(" @%d ",*argIndex); - definition+=marker; - } - else - { - definition+=tmp.mid(p,l); - } - i=p+l; - } - if (i<(int)tmp.length()) definition+=tmp.mid(i,tmp.length()-i); - - // add define definition to the dictionary of defines for this file - QCString dname = ds.left(i_obrace); - if (!dname.isEmpty()) - { - Define *def = new Define; - def->name = dname; - def->definition = definition; - def->nargs = count; - def->isPredefined = TRUE; - def->nonRecursive = nonRecursive; - def->fileDef = state->yyFileDef; - def->fileName = fileName; - state->defineManager.addDefine(state->yyFileName,def); - - //printf("#define '%s' '%s' #nargs=%d\n", - // def->name.data(),def->definition.data(),def->nargs); - } - - } - else if ((i_obrace==-1 || i_obrace>i_equals) && - (i_cbrace==-1 || i_cbrace>i_equals) && - !ds.isEmpty() && (int)ds.length()>i_equals - ) // predefined non-function macro definition - { - //printf("predefined normal macro '%s'\n",defStr); - Define *def = new Define; - if (i_equals==-1) // simple define without argument - { - def->name = ds; - def->definition = "1"; // substitute occurrences by 1 (true) - } - else // simple define with argument - { - int ine=i_equals - (nonRecursive ? 1 : 0); - def->name = ds.left(ine); - def->definition = ds.right(ds.length()-i_equals-1); - } - if (!def->name.isEmpty()) - { - def->nargs = -1; - def->isPredefined = TRUE; - def->nonRecursive = nonRecursive; - def->fileDef = state->yyFileDef; - def->fileName = fileName; - state->defineManager.addDefine(state->yyFileName,def); - } - else - { - delete def; - } - - //printf("#define '%s' '%s' #nargs=%d\n", - // def->name.data(),def->definition.data(),def->nargs); - } - } - //firstTime=FALSE; - } + initPredefined(yyscanner,fileName); state->yyLineNr = 1; state->yyColNr = 1; - state->level = 0; state->ifcount = 0; BEGIN( Start ); @@ -3389,35 +3354,24 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output preYYlex(yyscanner); - while (!state->condStack.isEmpty()) + while (!state->condStack.empty()) { - CondCtx *ctx = state->condStack.pop(); + const std::unique_ptr<CondCtx> &ctx = state->condStack.top(); QCString sectionInfo = " "; if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx->sectionId.stripWhiteSpace().data()); warn(fileName,ctx->lineNr,"Conditional section%sdoes not have " "a corresponding \\endcond command within this file.",sectionInfo.data()); - delete ctx; + state->condStack.pop(); } // make sure we don't extend a \cond with missing \endcond over multiple files (see bug 624829) forceEndCondSection(yyscanner); - // remove locally defined macros so they can be redefined in another source file - //if (state->fileDefineDict->count()>0) - //{ - // QDictIterator<Define> di(*state->fileDefineDict); - // Define *d; - // for (di.toFirst();(d=di.current());++di) - // { - // state->globalDefineDict->remove(di.currentKey()); - // } - // state->fileDefineDict->clear(); - //} - if (Debug::isFlagSet(Debug::Preprocessor)) { + std::lock_guard<std::mutex> lock(g_debugMutex); char *orgPos=output.data()+orgOffset; char *newPos=output.data()+output.curPos(); - Debug::print(Debug::Preprocessor,0,"Preprocessor output (size: %d bytes):\n",newPos-orgPos); + Debug::print(Debug::Preprocessor,0,"Preprocessor output of %s (size: %d bytes):\n",fileName,newPos-orgPos); int line=1; Debug::print(Debug::Preprocessor,0,"---------\n00001 "); while (orgPos<newPos) @@ -3427,26 +3381,48 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output orgPos++; } Debug::print(Debug::Preprocessor,0,"\n---------\n"); - if (state->defineManager.defineContext().count()>0) + if (yyextra->contextDefines.size()>0) { - Debug::print(Debug::Preprocessor,0,"Macros accessible in this file:\n"); + Debug::print(Debug::Preprocessor,0,"Macros accessible in this file (%s):\n", fileName); Debug::print(Debug::Preprocessor,0,"---------\n"); - QDictIterator<Define> di(state->defineManager.defineContext()); - Define *def; - for (di.toFirst();(def=di.current());++di) + for (auto &kv : yyextra->contextDefines) { - Debug::print(Debug::Preprocessor,0,"%s ",qPrint(def->name)); + Debug::print(Debug::Preprocessor,0,"%s ",qPrint(kv.second.name)); + } + for (auto &kv : yyextra->localDefines) + { + Debug::print(Debug::Preprocessor,0,"%s ",qPrint(kv.second.name)); } Debug::print(Debug::Preprocessor,0,"\n---------\n"); } else { - Debug::print(Debug::Preprocessor,0,"No macros accessible in this file.\n"); + Debug::print(Debug::Preprocessor,0,"No macros accessible in this file (%s).\n", fileName); + } + } + + { + std::lock_guard<std::mutex> lock(g_updateGlobals); + for (const auto &inc : state->includeRelations) + { + if (inc->fromFileDef) + { + inc->fromFileDef->addIncludeDependency(inc->toFileDef,inc->includeName,inc->local,inc->imported); + } + if (inc->toFileDef && inc->fromFileDef) + { + inc->toFileDef->addIncludedByDependency(inc->fromFileDef,inc->fromFileDef->docName(),inc->local,inc->imported); + } } + // add the macro definition for this file to the global map + Doxygen::macroDefinitions.emplace(std::make_pair(state->yyFileName.str(),std::move(state->macroDefinitions))); } - state->defineManager.endContext(); + + //yyextra->defineManager.endContext(); printlex(yy_flex_debug, FALSE, __FILE__, fileName); +// printf("Preprocessor::processFile(%s) finished\n",fileName); } - +#if USE_STATE2STRING #include "pre.l.h" +#endif diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h index ed4e76b..7bc5821 100644 --- a/src/printdocvisitor.h +++ b/src/printdocvisitor.h @@ -202,6 +202,10 @@ class PrintDocVisitor : public DocVisitor if (inc->isBlock()) printf(" block=\"yes\""); break; case DocInclude::LatexInclude: printf("latexinclude"); break; + case DocInclude::RtfInclude: printf("rtfinclude"); break; + case DocInclude::DocbookInclude: printf("docbookinclude"); break; + case DocInclude::ManInclude: printf("maninclude"); break; + case DocInclude::XmlInclude: printf("xmlinclude"); break; case DocInclude::VerbInclude: printf("verbinclude"); break; case DocInclude::Snippet: printf("snippet"); break; case DocInclude::SnipWithLines: printf("snipwithlines"); break; diff --git a/src/pycode.l b/src/pycode.l index f7e255f..8cb85a3 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -23,6 +23,10 @@ %option never-interactive %option prefix="pycodeYY" +%option noyy_top_state +%top{ +#include <stdint.h> +} %{ @@ -53,6 +57,8 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + static ClassSDict g_codeClassSDict(17); static QCString g_curClassName; static QStrList g_curClassBases; @@ -97,7 +103,10 @@ static bool g_endComment; static void endFontClass(); static void adjustScopesAndSuites(unsigned indentLength); + +#if USE_STATE2STRING static const char *stateToString(int state); +#endif /*! Represents a stack of variable to class mappings as found in the @@ -685,19 +694,19 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, DBG_CTX((stderr,"scope=%s locName=%s mcd=%p\n",scope.data(),locName.data(),mcd)); if (mcd) { - MemberDef *md = mcd->getMemberByName(locName); - if (md) + MemberDef *mmd = mcd->getMemberByName(locName); + if (mmd) { - g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope())); - writeMultiLineCodeLink(ol,md,clName); + g_theCallContext.setClass(stripClassName(mmd->typeString(),mmd->getOuterScope())); + writeMultiLineCodeLink(ol,mmd,clName); addToSearchIndex(className); - const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); - if (md->getGroupDef()) d = md->getGroupDef(); - if (d && d->isLinkable() && md->isLinkable() && + const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? + mmd->getBodyDef() : mmd->getOuterScope(); + if (mmd->getGroupDef()) d = mmd->getGroupDef(); + if (d && d->isLinkable() && mmd->isLinkable() && g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,mmd); } return; } @@ -707,20 +716,20 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, const NamespaceDef *mnd = getResolvedNamespace(scope); if (mnd) { - MemberDef *md=mnd->getMemberByName(locName); - if (md) + MemberDef *mmd=mnd->getMemberByName(locName); + if (mmd) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope())); - writeMultiLineCodeLink(ol,md,clName); + g_theCallContext.setClass(stripClassName(mmd->typeString(),mmd->getOuterScope())); + writeMultiLineCodeLink(ol,mmd,clName); addToSearchIndex(className); - const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); - if (md->getGroupDef()) d = md->getGroupDef(); - if (d && d->isLinkable() && md->isLinkable() && + const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? + mmd->getBodyDef() : mmd->getOuterScope(); + if (mmd->getGroupDef()) d = mmd->getGroupDef(); + if (d && d->isLinkable() && mmd->isLinkable() && g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,mmd); } return; } @@ -843,9 +852,9 @@ static void findMemberLink(CodeOutputInterface &ol,char *symName) #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -static int yyread(char *buf,int max_size) +static yy_size_t yyread(char *buf,yy_size_t max_size) { - int c=0; + yy_size_t c=0; while( c < max_size && g_inputString[g_inputPosition] ) { *buf = g_inputString[g_inputPosition++] ; @@ -1266,7 +1275,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT // level that is about to be // used. codifyLines(yytext); - g_indents.push(yyleng); + g_indents.push(static_cast<int>(yyleng)); // printf("Captured indent of %d [line %d]\n", yyleng, g_yyLineNr); BEGIN( Suite ); } @@ -1280,7 +1289,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT // should be improved. // (translate tabs to space, etc) codifyLines(yytext); - adjustScopesAndSuites((int)yyleng); + adjustScopesAndSuites(static_cast<int>(yyleng)); } "\n"|({BB}"\n") { @@ -1666,5 +1675,6 @@ void PythonCodeParser::resetCodeParserState() ::resetPythonCodeParserState(); } - +#if USE_STATE2STRING #include "pycode.l.h" +#endif diff --git a/src/pyscanner.h b/src/pyscanner.h index 6cfadf6..4f0ae38 100644 --- a/src/pyscanner.h +++ b/src/pyscanner.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -34,17 +34,17 @@ class PythonOutlineParser : public OutlineParserInterface { public: - void startTranslationUnit(const char *) {} - void finishTranslationUnit() {} - void parseInput(const char * fileName, - const char *fileBuf, + PythonOutlineParser(); + virtual ~PythonOutlineParser(); + void parseInput(const char * fileName, + const char *fileBuf, const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList &filesInSameTranslationUnit); + ClangTUParser *clangParser); bool needsPreprocessing(const QCString &extension) const; void parsePrototype(const char *text); + private: + struct Private; + std::unique_ptr<Private> p; }; -void pyscanFreeScanner(); - #endif diff --git a/src/pyscanner.l b/src/pyscanner.l index efdc943..d7996b4 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -23,6 +23,11 @@ %option never-interactive %option prefix="pyscannerYY" +%option reentrant +%option extra-type="struct pyscannerYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -49,8 +54,8 @@ #include "defargs.h" #include "language.h" #include "commentscan.h" -#include "pycode.h" #include "arguments.h" +#include "markdown.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -59,358 +64,90 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 -/* ----------------------------------------------------------------- - * - * statics - */ - - -static OutlineParserInterface *g_thisParser; -static const char * inputString; -static int inputPosition; -static QFile inputFile; - -static Protection protection; - -static std::shared_ptr<Entry> current_root; -static std::shared_ptr<Entry> current; -static std::shared_ptr<Entry> previous; -static std::shared_ptr<Entry> bodyEntry; -static int yyLineNr = 1 ; -static QCString yyFileName; -static MethodTypes mtype; -static bool gstat; -static Specifier virt; - -static int docBlockContext; -static QCString docBlock; -static bool docBlockInBody; -static bool docBlockJavaStyle; -static bool docBrief; -static bool docBlockSpecial; - -static bool g_doubleQuote; -static bool g_specialBlock; -static int g_stringContext; -static QGString * g_copyString; -static int g_indent = 0; -static int g_curIndent = 0; -static bool g_importTuple; - -static QDict<QCString> g_packageNameCache(257); - -static char g_atomStart; -static char g_atomEnd; -static int g_atomCount; - - -//static bool g_insideConstructor; - -static QCString g_moduleScope; -static QCString g_packageName; - -//static bool g_hideClassDocs; - -static QGString g_defVal; -static int g_braceCount; - -static bool g_lexInit = FALSE; -static bool g_packageCommentAllowed; - -static bool g_start_init = FALSE; -static int g_search_count = 0; - -static QCString g_argType = ""; -static bool g_funcParamsEnd; -//----------------------------------------------------------------------------- -static const char *stateToString(int state); +#define USE_STATE2STRING 0 +/* ----------------------------------------------------------------- */ -static void initParser() -{ - protection = Public; - mtype = Method; - gstat = FALSE; - virt = Normal; - previous = 0; - g_packageCommentAllowed = TRUE; - g_packageNameCache.setAutoDelete(TRUE); -} - -static void initEntry() -{ - //current->python = TRUE; - current->protection = protection ; - current->mtype = mtype; - current->virt = virt; - current->stat = gstat; - current->lang = SrcLangExt_Python; - Doxygen::docGroup.initGroupInfo(current.get()); - gstat = FALSE; -} - -static void newEntry() -{ - previous = current; - current_root->moveToSubEntryAndRefresh(current); - initEntry(); -} - -static void newVariable() -{ - if (!current->name.isEmpty() && current->name.at(0)=='_') // mark as private - { - current->protection=Private; - } - if (current_root->section&Entry::COMPOUND_MASK) // mark as class variable - { - current->stat = TRUE; - } - newEntry(); -} - -static void newFunction() -{ - if (current->name.left(2)=="__" && current->name.right(2)=="__") - { - // special method name, see - // http://docs.python.org/ref/specialnames.html - current->protection=Public; - } - else if (current->name.at(0)=='_') - { - current->protection=Private; - } -} - -static inline int computeIndent(const char *s) -{ - int col=0; - static int tabSize=Config_getInt(TAB_SIZE); - const char *p=s; - char c; - while ((c=*p++)) - { - if (c==' ') col++; - else if (c=='\t') col+=tabSize-(col%tabSize); - else break; - } - return col; -} - -static QCString findPackageScopeFromPath(const QCString &path) -{ - QCString *pScope = g_packageNameCache.find(path); - if (pScope) - { - return *pScope; - } - QFileInfo pf(path+"/__init__.py"); // found package initialization file - if (pf.exists()) - { - int i=path.findRev('/'); - if (i!=-1) - { - QCString scope = findPackageScopeFromPath(path.left(i)); - if (!scope.isEmpty()) - { - scope+="::"; - } - scope+=path.mid(i+1); - g_packageNameCache.insert(path,new QCString(scope)); - return scope; - } - } - return ""; -} - -static QCString findPackageScope(const char *fileName) +struct pyscannerYY_state { - if (fileName==0) return ""; - QFileInfo fi(fileName); - return findPackageScopeFromPath(fi.dirPath(TRUE).data()); -} + pyscannerYY_state() : packageNameCache(257) {} + CommentScanner commentScanner; + OutlineParserInterface *thisParser = 0; + const char * inputString = 0; + yy_size_t inputPosition = 0; + Protection protection = Public; + std::shared_ptr<Entry> current_root; + std::shared_ptr<Entry> current; + std::shared_ptr<Entry> previous; + std::shared_ptr<Entry> bodyEntry; + int yyLineNr = 1 ; + QCString yyFileName; + MethodTypes mtype = Method; + bool stat = FALSE; + Specifier virt = Normal; + int docBlockContext = 0; + QCString docBlock; + bool docBlockInBody = FALSE; + bool docBlockJavaStyle = FALSE; + bool docBrief = FALSE; + bool docBlockSpecial = FALSE; + bool doubleQuote = FALSE; + bool specialBlock = FALSE; + int stringContext = 0; + QGString * copyString = 0; + int indent = 0; + int curIndent = 0; + int commentIndent = 0; + bool importTuple = FALSE; + QDict<QCString> packageNameCache; + char atomStart = 0; + char atomEnd = 0; + int atomCount = 0; + QCString moduleScope; + QCString packageName; + QGString defVal; + int braceCount = 0; + bool lexInit = FALSE; + bool packageCommentAllowed = FALSE; + bool start_init = FALSE; + int search_count = 0; + QCString argType; + bool funcParamsEnd = FALSE; +}; -static void addFrom(bool all) -{ - QCString item=all ? g_packageName : g_packageName+"."+yytext; - current->name=removeRedundantWhiteSpace(substitute(item,".","::")); - current->fileName = yyFileName; - //printf("Adding using declaration: found:%s:%d name=%s\n",yyFileName.data(),yyLineNr,current->name.data()); - current->section=all ? Entry::USINGDIR_SEC : Entry::USINGDECL_SEC; - current_root->moveToSubEntryAndRefresh(current); - initEntry(); -} //----------------------------------------------------------------------------- +#if USE_STATE2STRING +static const char *stateToString(int state); +#endif -static void lineCount() -{ - DBG_CTX((stderr,"yyLineNr=%d\n",yyLineNr)); - for (const char *p = yytext; *p; ++p) - { - yyLineNr += (*p == '\n') ; - } -} - -static void incLineNr() -{ - DBG_CTX((stderr,"yyLineNr=%d\n",yyLineNr)); - yyLineNr++; -} - -//----------------------------------------------------------------- -static void startCommentBlock(bool brief) -{ - if (brief) - { - current->briefFile = yyFileName; - current->briefLine = yyLineNr; - } - else - { - current->docFile = yyFileName; - current->docLine = yyLineNr; - } -} - -static void handleCommentBlock(const QCString &doc,bool brief) -{ - //printf("handleCommentBlock(doc=[%s] brief=%d docBlockInBody=%d docBlockJavaStyle=%d\n", - // doc.data(),brief,docBlockInBody,docBlockJavaStyle); - - // TODO: Fix me - docBlockInBody=FALSE; - - if (docBlockInBody && previous && !previous->doc.isEmpty()) - { - previous->doc=previous->doc.stripWhiteSpace()+"\n\n"; - } - - 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.get() : current.get(), - processedDoc, // text - yyFileName, // file - lineNr, - docBlockInBody ? FALSE : brief, - docBlockJavaStyle, // javadoc style // or FALSE, - docBlockInBody, - protection, - position, - needsEntry) - ) // need to start a new entry - { - if (needsEntry) - { - newEntry(); - } - } - if (needsEntry) - { - newEntry(); - } - -} - -static void endOfDef(int correction=0) -{ - //printf("endOfDef at=%d\n",yyLineNr); - if (bodyEntry) - { - bodyEntry->endBodyLine = yyLineNr-correction; - bodyEntry = 0; - } - newEntry(); - //g_insideConstructor = FALSE; -} - -static inline void addToString(const char *s) -{ - if (g_copyString) (*g_copyString)+=s; -} - -static void initTriDoubleQuoteBlock() -{ - docBlockContext = YY_START; - docBlockInBody = FALSE; - docBlockJavaStyle = TRUE; - docBlockSpecial = yytext[strlen(yytext) - 1]=='!'; - docBlock.resize(0); - g_doubleQuote = TRUE; - startCommentBlock(FALSE); -} - -static void initTriSingleQuoteBlock() -{ - docBlockContext = YY_START; - docBlockInBody = FALSE; - docBlockJavaStyle = TRUE; - docBlockSpecial = yytext[strlen(yytext) - 1]=='!'; - docBlock.resize(0); - g_doubleQuote = FALSE; - startCommentBlock(FALSE); -} - -static void initSpecialBlock() -{ - docBlockContext = YY_START; - docBlockInBody = FALSE; - docBlockJavaStyle = TRUE; - docBrief = TRUE; - docBlock.resize(0); - startCommentBlock(TRUE); -} - -static void searchFoundDef() -{ - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - current->section = Entry::FUNCTION_SEC; - current->lang = SrcLangExt_Python; - current->virt = Normal; - current->stat = gstat; - current->mtype = mtype = Method; - current->type.resize(0); - current->name.resize(0); - current->args.resize(0); - current->argList.clear(); - g_packageCommentAllowed = FALSE; - gstat=FALSE; - //printf("searchFoundDef at=%d\n",yyLineNr); -} - -static void searchFoundClass() -{ - current->section = Entry::CLASS_SEC; - current->argList.clear(); - current->type += "class" ; - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - g_packageCommentAllowed = FALSE; -} +static inline int computeIndent(const char *s); + +static void initParser(yyscan_t yyscanner); +static void initEntry(yyscan_t yyscanner); +static void newEntry(yyscan_t yyscanner); +static void newVariable(yyscan_t yyscanner); +static void newFunction(yyscan_t yyscanner); +static QCString findPackageScopeFromPath(yyscan_t yyscanner,const QCString &path); +static void addFrom(yyscan_t yyscanner,bool all); +static void lineCount(yyscan_t yyscanner); +static void incLineNr(yyscan_t yyscanner); +static void startCommentBlock(yyscan_t yyscanner,bool brief); +static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief); +static void endOfDef(yyscan_t yyscanner,int correction=0); +static inline void addToString(yyscan_t yyscanner,const char *s); +static void initTriDoubleQuoteBlock(yyscan_t yyscanner); +static void initTriSingleQuoteBlock(yyscan_t yyscanner); +static void initSpecialBlock(yyscan_t yyscanner); +static void searchFoundDef(yyscan_t yyscanner); +static void searchFoundClass(yyscan_t yyscanner); +static QCString findPackageScope(yyscan_t yyscanner,const char *fileName); + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); //----------------------------------------------------------------------------- /* ----------------------------------------------------------------- */ #undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static int yyread(char *buf,int max_size) -{ - int c=0; - while ( c < max_size && inputString[inputPosition] ) - { - *buf = inputString[inputPosition++] ; - //printf("%d (%c)\n",*buf,*buf); - c++; buf++; - } - return c; -} +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} @@ -517,125 +254,125 @@ STARTDOCSYMS "##" <Search>{ ^{B}"def"{BB} { // start of a function/method definition with indent - DBG_CTX((stderr,"Found def at %d\n",yyLineNr)); - g_indent=computeIndent(yytext); - searchFoundDef(); + DBG_CTX((stderr,"Found def at %d\n",yyextra->yyLineNr)); + yyextra->indent=computeIndent(yytext); + searchFoundDef(yyscanner); BEGIN( FunctionDec ); } "def"{BB} { // start of a function/method definition - searchFoundDef(); + searchFoundDef(yyscanner); BEGIN( FunctionDec ); } ^{B}"class"{BB} { // start of a class definition with indent - DBG_CTX((stderr,"Found class at %d\n",yyLineNr)); - g_indent=computeIndent(yytext); - searchFoundClass(); + DBG_CTX((stderr,"Found class at %d\n",yyextra->yyLineNr)); + yyextra->indent=computeIndent(yytext); + searchFoundClass(yyscanner); BEGIN( ClassDec ) ; } "class"{BB} { // start of a class definition - searchFoundClass(); + searchFoundClass(yyscanner); BEGIN( ClassDec ) ; } ^{B}"from"{BB} | "from"{BB} { // start of an from import - g_packageCommentAllowed = FALSE; + yyextra->packageCommentAllowed = FALSE; BEGIN( FromMod ); } ^{B}"import"{BB} | "import"{BB} { // start of an import statement - g_packageCommentAllowed = FALSE; + yyextra->packageCommentAllowed = FALSE; BEGIN( Import ); } ^{B}{IDENTIFIER}/{B}"="{B}"property" { // property - current->section = Entry::VARIABLE_SEC; - current->mtype = Property; - current->name = QCString(yytext).stripWhiteSpace(); - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - g_packageCommentAllowed = FALSE; + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->mtype = Property; + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->packageCommentAllowed = FALSE; BEGIN(VariableDec); } ^{B}{IDENTIFIER}/{B}"="[^=] { // variable - if (g_search_count) REJECT; - g_indent=computeIndent(yytext); - current->section = Entry::VARIABLE_SEC; - current->name = QCString(yytext).stripWhiteSpace(); - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - g_packageCommentAllowed = FALSE; + if (yyextra->search_count) REJECT; + yyextra->indent=computeIndent(yytext); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->packageCommentAllowed = FALSE; BEGIN(VariableDec); } {B}{IDENTIFIER}/({B},{B}{IDENTIFIER})*{B}")"*{B}"="[^=] { // list of variables, we cannot place the default value // so we will skip it later on in a general rule // Also note ")" this is to catch also (a,b). the "(" // is caught in the rule: [(], the ")" will be handled in [)] - if (g_search_count > 1) REJECT; - g_indent=computeIndent(yytext); - current->section = Entry::VARIABLE_SEC; - current->name = QCString(yytext).stripWhiteSpace(); - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - g_packageCommentAllowed = FALSE; - newVariable(); + if (yyextra->search_count > 1) REJECT; + yyextra->indent=computeIndent(yytext); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->packageCommentAllowed = FALSE; + newVariable(yyscanner); } "'" { // start of a single quoted string - g_stringContext=YY_START; - g_copyString=0; - g_packageCommentAllowed = FALSE; + yyextra->stringContext=YY_START; + yyextra->copyString=0; + yyextra->packageCommentAllowed = FALSE; BEGIN( SingleQuoteString ); } "\"" { // start of a double quoted string - g_stringContext=YY_START; - g_copyString=0; - g_packageCommentAllowed = FALSE; + yyextra->stringContext=YY_START; + yyextra->copyString=0; + yyextra->packageCommentAllowed = FALSE; BEGIN( DoubleQuoteString ); } "@staticmethod" { - gstat=TRUE; + yyextra->stat=TRUE; } {SCRIPTCOMMENT} { // Unix type script comment - if (yyLineNr != 1) REJECT; + if (yyextra->yyLineNr != 1) REJECT; } {POUNDCOMMENT} { // normal comment - g_packageCommentAllowed = FALSE; + yyextra->packageCommentAllowed = FALSE; } {IDENTIFIER} { // some other identifier - g_packageCommentAllowed = FALSE; + yyextra->packageCommentAllowed = FALSE; } ^{BB} { - g_curIndent=computeIndent(yytext); + yyextra->curIndent=computeIndent(yytext); } {NEWLINE}+ { // new line - lineCount(); + lineCount(yyscanner); } {TRIDOUBLEQUOTE} { // start of a comment block - initTriDoubleQuoteBlock(); + initTriDoubleQuoteBlock(yyscanner); BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - initTriSingleQuoteBlock(); + initTriSingleQuoteBlock(yyscanner); BEGIN(TripleComment); } {STARTDOCSYMS}/[^#] { // start of a special comment - g_curIndent=computeIndent(yytext); - g_packageCommentAllowed = FALSE; - initSpecialBlock(); + yyextra->curIndent=computeIndent(yytext); + yyextra->packageCommentAllowed = FALSE; + initSpecialBlock(yyscanner); BEGIN(SpecialComment); } [(] { // we have to do something with ( - g_search_count += 1; + yyextra->search_count += 1; } [)] { // we have to do something with ) - g_search_count -= 1; + yyextra->search_count -= 1; } [^\n] { // any other character... // This is the major default @@ -648,13 +385,13 @@ STARTDOCSYMS "##" "." { // python3 style imports } {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { // from package import - g_packageName=yytext; + yyextra->packageName=yytext; } "import"{B} { BEGIN(FromModItem); } \n { - incLineNr(); + incLineNr(yyscanner); BEGIN(Search); } {B} { @@ -667,25 +404,25 @@ STARTDOCSYMS "##" <FromModItem>{ "*" { // import all - addFrom(TRUE); + addFrom(yyscanner,TRUE); BEGIN(Search); } {IDENTIFIER}/{B}","{B} { - addFrom(FALSE); + addFrom(yyscanner,FALSE); } {IDENTIFIER}/{B}")" { - addFrom(FALSE); + addFrom(yyscanner,FALSE); } {IDENTIFIER} { - addFrom(FALSE); - if (!g_importTuple) + addFrom(yyscanner,FALSE); + if (!yyextra->importTuple) { BEGIN(Search); } } \n { - incLineNr(); - if (!g_importTuple) + incLineNr(yyscanner); + if (!yyextra->importTuple) { BEGIN(Search); } @@ -693,16 +430,16 @@ STARTDOCSYMS "##" {B} { } "(" { - g_importTuple=TRUE; + yyextra->importTuple=TRUE; } ")" { - g_importTuple=FALSE; + yyextra->importTuple=FALSE; BEGIN(Search); } "," { } "\\"{B}\n { // line continuation - incLineNr(); + incLineNr(yyscanner); } . { unput(*yytext); @@ -712,16 +449,16 @@ STARTDOCSYMS "##" <Import>{ {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { - current->name=removeRedundantWhiteSpace(substitute(yytext,".","::")); - current->fileName = yyFileName; - //printf("Adding using declaration: found:%s:%d name=%s\n",yyFileName.data(),yyLineNr,current->name.data()); - current->section=Entry::USINGDECL_SEC; - current_root->moveToSubEntryAndRefresh(current); - initEntry(); + yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,".","::")); + yyextra->current->fileName = yyextra->yyFileName; + //printf("Adding using declaration: found:%s:%d name=%s\n",yyextra->yyFileName.data(),yyextra->yyLineNr,yyextra->current->name.data()); + yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); BEGIN(Search); } \n { - incLineNr(); + incLineNr(yyscanner); BEGIN(Search); } {B} { @@ -734,60 +471,60 @@ STARTDOCSYMS "##" <SearchMemVars>{ "self."{IDENTIFIER}/{B}"=" { - DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",&yytext[5],current_root->name.data(),yyLineNr)); - current->name=&yytext[5]; - current->section=Entry::VARIABLE_SEC; - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - current->type.resize(0); - if (current->name.at(0)=='_') // mark as private + DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",&yytext[5],yyextra->current_root->name.data(),yyextra->yyLineNr)); + yyextra->current->name=&yytext[5]; + yyextra->current->section=Entry::VARIABLE_SEC; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->type.resize(0); + if (yyextra->current->name.at(0)=='_') // mark as private { - current->protection=Private; + yyextra->current->protection=Private; } - newEntry(); + newEntry(yyscanner); } "cls."{IDENTIFIER}/{B}"=" { - DBG_CTX((stderr,"Found class method variable %s in %s at %d\n",&yytext[4],current_root->name.data(),yyLineNr)); - current->name=&yytext[4]; - current->section=Entry::VARIABLE_SEC; - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - current->type.resize(0); - if (current->name.at(0)=='_') // mark as private + DBG_CTX((stderr,"Found class method variable %s in %s at %d\n",&yytext[4],yyextra->current_root->name.data(),yyextra->yyLineNr)); + yyextra->current->name=&yytext[4]; + yyextra->current->section=Entry::VARIABLE_SEC; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->type.resize(0); + if (yyextra->current->name.at(0)=='_') // mark as private { - current->protection=Private; + yyextra->current->protection=Private; } - newEntry(); + newEntry(yyscanner); } {TRIDOUBLEQUOTE} { // start of a comment block - initTriDoubleQuoteBlock(); + initTriDoubleQuoteBlock(yyscanner); BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - initTriSingleQuoteBlock(); + initTriSingleQuoteBlock(yyscanner); BEGIN(TripleComment); } {STARTDOCSYMS}/[^#] { // start of a special comment - initSpecialBlock(); + initSpecialBlock(yyscanner); BEGIN(SpecialComment); } {POUNDCOMMENT} { // # } "'" { // start of a single quoted string - g_stringContext=YY_START; - g_copyString=0; + yyextra->stringContext=YY_START; + yyextra->copyString=0; BEGIN( SingleQuoteString ); } "\"" { // start of a double quoted string - g_stringContext=YY_START; - g_copyString=0; + yyextra->stringContext=YY_START; + yyextra->copyString=0; BEGIN( DoubleQuoteString ); } - \n { incLineNr(); } + \n { incLineNr(yyscanner); } {IDENTIFIER} // identifiers [^'"\.#a-z_A-Z\n]+ // other uninteresting stuff . // anything else @@ -795,106 +532,106 @@ STARTDOCSYMS "##" <FunctionBody>{ \n{B}/{IDENTIFIER}{BB} { - DBG_CTX((stderr,"indent %d<=%d\n",computeIndent(&yytext[1]),g_indent)); - if (computeIndent(&yytext[1])<=g_indent) + DBG_CTX((stderr,"indent %d<=%d\n",computeIndent(&yytext[1]),yyextra->indent)); + if (computeIndent(&yytext[1])<=yyextra->indent) { int i; for (i=(int)yyleng-1;i>=0;i--) { unput(yytext[i]); } - endOfDef(); + endOfDef(yyscanner); //YY_CURRENT_BUFFER->yy_at_bol=TRUE; BEGIN(Search); } else { - incLineNr(); - current->program+=yytext; + incLineNr(yyscanner); + yyextra->current->program+=yytext; } } \n{B}/"##" { - if (computeIndent(&yytext[1])<=g_indent) + if (computeIndent(&yytext[1])<=yyextra->indent) { int i; for (i=(int)yyleng-1;i>=0;i--) { unput(yytext[i]); } - endOfDef(); + endOfDef(yyscanner); //YY_CURRENT_BUFFER->yy_at_bol=TRUE; BEGIN(Search); } else { - incLineNr(); - current->program+=yytext; + incLineNr(yyscanner); + yyextra->current->program+=yytext; } } <<EOF>> { - endOfDef(); + endOfDef(yyscanner); yyterminate(); } ^{BB}/\n { // skip empty line - current->program+=yytext; + yyextra->current->program+=yytext; } ^{BB} { // something at indent >0 - current->program+=yytext; - g_curIndent = computeIndent(yytext); - if (g_curIndent<=g_indent) + yyextra->current->program+=yytext; + yyextra->curIndent = computeIndent(yytext); + if (yyextra->curIndent<=yyextra->indent) // jumped out of the function { - endOfDef(1); + endOfDef(yyscanner,1); BEGIN(Search); } } "'" { // start of a single quoted string - current->program+=yytext; - g_stringContext=YY_START; - g_specialBlock = FALSE; - g_copyString=¤t->program; + yyextra->current->program+=yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( SingleQuoteString ); } "\"" { // start of a double quoted string - current->program+=yytext; - g_stringContext=YY_START; - g_specialBlock = FALSE; - g_copyString=¤t->program; + yyextra->current->program+=yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( DoubleQuoteString ); } [^ \t\n#'".]+ { // non-special stuff - current->program+=yytext; - g_specialBlock = FALSE; + yyextra->current->program+=yytext; + yyextra->specialBlock = FALSE; } ^{POUNDCOMMENT} { // normal comment - current->program+=yytext; + yyextra->current->program+=yytext; } "#".* { // comment half way - current->program+=yytext; + yyextra->current->program+=yytext; } {NEWLINE} { - incLineNr(); - current->program+=yytext; + incLineNr(yyscanner); + yyextra->current->program+=yytext; } . { // any character - current->program+=*yytext; - g_specialBlock = FALSE; + yyextra->current->program+=*yytext; + yyextra->specialBlock = FALSE; } {TRIDOUBLEQUOTE} { // start of a comment block - current->program+=yytext; - initTriDoubleQuoteBlock(); + yyextra->current->program+=yytext; + initTriDoubleQuoteBlock(yyscanner); BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - current->program+=yytext; - initTriSingleQuoteBlock(); + yyextra->current->program+=yytext; + initTriSingleQuoteBlock(yyscanner); BEGIN(TripleComment); } {STARTDOCSYMS}/[^#] { // start of a special comment - initSpecialBlock(); + initSpecialBlock(yyscanner); BEGIN(SpecialComment); } @@ -903,37 +640,37 @@ STARTDOCSYMS "##" <FunctionDec>{ {IDENTIFIER} { //found function name - if (current->type.isEmpty()) + if (yyextra->current->type.isEmpty()) { - current->type = "def"; + yyextra->current->type = "def"; } - current->name = yytext; - current->name = current->name.stripWhiteSpace(); - newFunction(); + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + newFunction(yyscanner); } {B}":"{B} { // function without arguments - g_specialBlock = TRUE; // expecting a docstring - bodyEntry = current; + yyextra->specialBlock = TRUE; // expecting a docstring + yyextra->bodyEntry = yyextra->current; BEGIN(FunctionBody); } "->" { - g_defVal.resize(0); - g_braceCount = 0; + yyextra->defVal.resize(0); + yyextra->braceCount = 0; BEGIN(FunctionTypeAnnotation); } {B}"(" { - g_funcParamsEnd = FALSE; - current->bodyLine = yyLineNr; + yyextra->funcParamsEnd = FALSE; + yyextra->current->bodyLine = yyextra->yyLineNr; BEGIN(FunctionParams); } ")" { // end of parameter list - if (current->argList.empty()) + if (yyextra->current->argList.empty()) { - current->argList.noParameters=TRUE; + yyextra->current->argList.setNoParameters(TRUE); } - current->args = argListToString(current->argList); - g_funcParamsEnd = TRUE; + yyextra->current->args = argListToString(yyextra->current->argList); + yyextra->funcParamsEnd = TRUE; } } @@ -942,21 +679,21 @@ STARTDOCSYMS "##" } [\*]+ { - g_argType = yytext; + yyextra->argType = yytext; } {IDENTIFIER} { // Name of parameter - lineCount(); + lineCount(yyscanner); Argument a; a.name = QCString(yytext).stripWhiteSpace(); - a.type = g_argType; - current->argList.push_back(a); - g_argType = ""; + a.type = yyextra->argType; + yyextra->current->argList.push_back(a); + yyextra->argType = ""; } "=" { // default value // TODO: this rule is too simple, need to be able to // match things like =")" as well! - g_defVal.resize(0); - g_braceCount = 0; + yyextra->defVal.resize(0); + yyextra->braceCount = 0; BEGIN(FunctionParamDefVal); } ")" { @@ -964,8 +701,8 @@ STARTDOCSYMS "##" BEGIN(FunctionDec); } ":"{B} { - g_defVal.resize(0); - g_braceCount = 0; + yyextra->defVal.resize(0); + yyextra->braceCount = 0; BEGIN(FunctionAnnotation); } {POUNDCOMMENT} { // a comment @@ -979,43 +716,43 @@ STARTDOCSYMS "##" "{" | "[" | "(" { - ++g_braceCount; - g_defVal+=*yytext; + ++yyextra->braceCount; + yyextra->defVal+=*yytext; } "}" | "]" | ")" { - --g_braceCount; - g_defVal+=*yytext; + --yyextra->braceCount; + yyextra->defVal+=*yytext; } ":" { - if (g_braceCount == 0) + if (yyextra->braceCount == 0) { - current->type = g_defVal.data(); + yyextra->current->type = yyextra->defVal.data(); unput(*yytext); BEGIN(FunctionDec); } else - g_defVal+=*yytext; + yyextra->defVal+=*yytext; } "'" { - g_defVal+=*yytext; - g_copyString=&g_defVal; - g_stringContext=FunctionTypeAnnotation; + yyextra->defVal+=*yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionTypeAnnotation; BEGIN(SingleQuoteString); } "\"" { - g_defVal+=*yytext; - g_copyString=&g_defVal; - g_stringContext=FunctionTypeAnnotation; + yyextra->defVal+=*yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionTypeAnnotation; BEGIN(DoubleQuoteString); } \n { - g_defVal+=*yytext; - incLineNr(); + yyextra->defVal+=*yytext; + incLineNr(yyscanner); } . { - g_defVal+=*yytext; + yyextra->defVal+=*yytext; } } @@ -1023,21 +760,21 @@ STARTDOCSYMS "##" "{" | "[" | "(" { - ++g_braceCount; - g_defVal+=*yytext; + ++yyextra->braceCount; + yyextra->defVal+=*yytext; } "}" | "]" { - --g_braceCount; - g_defVal+=*yytext; + --yyextra->braceCount; + yyextra->defVal+=*yytext; } ")" | "=" | "," { - if (g_braceCount == 0) + if (yyextra->braceCount == 0) { - if (!current->argList.empty()) - current->argList.back().type += g_defVal; + if (!yyextra->current->argList.empty()) + yyextra->current->argList.back().type += yyextra->defVal; if (*yytext != ',') unput(*yytext); BEGIN(FunctionParams); @@ -1045,28 +782,28 @@ STARTDOCSYMS "##" else { if (*yytext == ')') - --g_braceCount; - g_defVal += *yytext; + --yyextra->braceCount; + yyextra->defVal += *yytext; } } "'" { - g_defVal+=*yytext; - g_copyString=&g_defVal; - g_stringContext=FunctionAnnotation; + yyextra->defVal+=*yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionAnnotation; BEGIN(SingleQuoteString); } "\"" { - g_defVal+=*yytext; - g_copyString=&g_defVal; - g_stringContext=FunctionAnnotation; + yyextra->defVal+=*yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionAnnotation; BEGIN(DoubleQuoteString); } \n { - g_defVal+=*yytext; - incLineNr(); + yyextra->defVal+=*yytext; + incLineNr(yyscanner); } . { - g_defVal+=*yytext; + yyextra->defVal+=*yytext; } } @@ -1074,20 +811,20 @@ STARTDOCSYMS "##" "{" | "[" | "(" { // internal opening brace, assumption is that we have correct code so braces do match - ++g_braceCount; - g_defVal+=*yytext; + ++yyextra->braceCount; + yyextra->defVal+=*yytext; } "}" | "]" { - --g_braceCount; - g_defVal+=*yytext; + --yyextra->braceCount; + yyextra->defVal+=*yytext; } ")" | "," { - if (g_braceCount == 0) + if (yyextra->braceCount == 0) { - if (!current->argList.empty()) - current->argList.back().defval=QCString(g_defVal).stripWhiteSpace(); + if (!yyextra->current->argList.empty()) + yyextra->current->argList.back().defval=QCString(yyextra->defVal).stripWhiteSpace(); if (*yytext == ')') unput(*yytext); BEGIN(FunctionParams); @@ -1095,140 +832,140 @@ STARTDOCSYMS "##" else { if (*yytext == ')') - --g_braceCount; - g_defVal += *yytext; + --yyextra->braceCount; + yyextra->defVal += *yytext; } } "'" { - g_defVal+=*yytext; - g_copyString=&g_defVal; - g_stringContext=FunctionParamDefVal; + yyextra->defVal+=*yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionParamDefVal; BEGIN( SingleQuoteString ); } "\"" { - g_defVal+=*yytext; - g_copyString=&g_defVal; - g_stringContext=FunctionParamDefVal; + yyextra->defVal+=*yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionParamDefVal; BEGIN( DoubleQuoteString ); } \n { - g_defVal+=*yytext; - incLineNr(); + yyextra->defVal+=*yytext; + incLineNr(yyscanner); } . { - g_defVal+=*yytext; + yyextra->defVal+=*yytext; } } <ClassBody>{ \n/{IDENTIFIER}{BB} { // new def at indent 0 - incLineNr(); - endOfDef(); - //g_hideClassDocs = FALSE; + incLineNr(yyscanner); + endOfDef(yyscanner); + //yyextra->hideClassDocs = FALSE; //YY_CURRENT_BUFFER->yy_at_bol=TRUE; BEGIN(Search); } \n/"##"[^#] { // start of a special comment at indent 0 - incLineNr(); - endOfDef(); - //g_hideClassDocs = FALSE; + incLineNr(yyscanner); + endOfDef(yyscanner); + //yyextra->hideClassDocs = FALSE; //YY_CURRENT_BUFFER->yy_at_bol=TRUE; BEGIN(Search); } ^{BB}/\n { // skip empty line - current->program+=yytext; + yyextra->current->program+=yytext; } <<EOF>> { - endOfDef(); + endOfDef(yyscanner); yyterminate(); } ^{BB} { // something at indent >0 - g_curIndent=computeIndent(yytext); - DBG_CTX((stderr,"g_curIndent=%d g_indent=%d\n",g_curIndent,g_indent)); - if (g_curIndent<=g_indent) + yyextra->curIndent=computeIndent(yytext); + DBG_CTX((stderr,"yyextra->curIndent=%d yyextra->indent=%d\n",yyextra->curIndent,yyextra->indent)); + if (yyextra->curIndent<=yyextra->indent) // jumped out of the class/method { - endOfDef(1); - g_indent=g_curIndent; + endOfDef(yyscanner,1); + yyextra->indent=yyextra->curIndent; // make sure the next rule matches ^... //YY_CURRENT_BUFFER->yy_at_bol=TRUE; - //g_hideClassDocs = FALSE; + //yyextra->hideClassDocs = FALSE; BEGIN(Search); } else { - current->program+=yytext; + yyextra->current->program+=yytext; } } "'" { // start of a single quoted string - current->program+=*yytext; - g_stringContext=YY_START; - g_specialBlock = FALSE; - g_copyString=¤t->program; + yyextra->current->program+=*yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( SingleQuoteString ); } "\"" { // start of a double quoted string - current->program+=*yytext; - g_stringContext=YY_START; - g_specialBlock = FALSE; - g_copyString=¤t->program; + yyextra->current->program+=*yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( DoubleQuoteString ); } [^ \t\n#'"]+ { // non-special stuff - current->program+=yytext; - g_specialBlock = FALSE; - //g_hideClassDocs = FALSE; + yyextra->current->program+=yytext; + yyextra->specialBlock = FALSE; + //yyextra->hideClassDocs = FALSE; } {NEWLINE} { - current->program+=*yytext; - incLineNr(); + yyextra->current->program+=*yytext; + incLineNr(yyscanner); } {POUNDCOMMENT} { // normal comment - current->program+=yytext; + yyextra->current->program+=yytext; } . { // any character - g_specialBlock = FALSE; - current->program+=*yytext; + yyextra->specialBlock = FALSE; + yyextra->current->program+=*yytext; } {TRIDOUBLEQUOTE} { // start of a comment block - //if (!g_hideClassDocs) - current->program+=yytext; - initTriDoubleQuoteBlock(); + //if (!yyextra->hideClassDocs) + yyextra->current->program+=yytext; + initTriDoubleQuoteBlock(yyscanner); BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - //if (!g_hideClassDocs) - current->program+=yytext; - initTriSingleQuoteBlock(); + //if (!yyextra->hideClassDocs) + yyextra->current->program+=yytext; + initTriSingleQuoteBlock(yyscanner); BEGIN(TripleComment); } } <ClassDec>{IDENTIFIER} { - if (current->type.isEmpty()) + if (yyextra->current->type.isEmpty()) { - current->type = "class"; + yyextra->current->type = "class"; } - current->section = Entry::CLASS_SEC; - current->name = yytext; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->name = yytext; // prepend scope in case of nested classes - if (current_root->section&Entry::SCOPE_MASK) + if (yyextra->current_root->section&Entry::SCOPE_MASK) { - //printf("*** Prepending scope %s to class %s\n",current_root->name.data(),current->name.data()); - current->name.prepend(current_root->name+"::"); + //printf("*** Prepending scope %s to class %s\n",yyextra->current_root->name.data(),yyextra->current->name.data()); + yyextra->current->name.prepend(yyextra->current_root->name+"::"); } - current->name = current->name.stripWhiteSpace(); - current->fileName = yyFileName; - docBlockContext = YY_START; - docBlockInBody = FALSE; - docBlockJavaStyle = FALSE; - docBlock.resize(0); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockJavaStyle = FALSE; + yyextra->docBlock.resize(0); BEGIN(ClassInheritance); } @@ -1238,37 +975,37 @@ STARTDOCSYMS "##" } ":" { // begin of the class definition - g_specialBlock = TRUE; // expecting a docstring - current->bodyLine = yyLineNr; - current->program.resize(0); + yyextra->specialBlock = TRUE; // expecting a docstring + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->program.resize(0); BEGIN(ClassCaptureIndent); } {SCOPE} { - current->extends.push_back( + yyextra->current->extends.push_back( BaseInfo(substitute(yytext,".","::"),Public,Normal) ); //Has base class-do stuff } "'" { // start of a single quoted string - g_stringContext=YY_START; + yyextra->stringContext=YY_START; BEGIN( SingleQuoteStringIgnore ); } "\"" { // start of a double quoted string - g_stringContext=YY_START; + yyextra->stringContext=YY_START; BEGIN( DoubleQuoteStringIgnore ); } } <SingleQuoteStringIgnore>{ "'" { // end of a single quoted string - BEGIN(g_stringContext); + BEGIN(yyextra->stringContext); } . { } } <DoubleQuoteStringIgnore>{ "\"" { // end of a double quoted string - BEGIN(g_stringContext); + BEGIN(yyextra->stringContext); } . { } } @@ -1276,42 +1013,42 @@ STARTDOCSYMS "##" <ClassCaptureIndent>{ "\n"|({BB}"\n") { // Blankline - ignore, keep looking for indentation. - lineCount(); - current->program+=yytext; + lineCount(yyscanner); + yyextra->current->program+=yytext; } {TRIDOUBLEQUOTE} { // start of a comment block - initTriDoubleQuoteBlock(); - current->program+=yytext; + initTriDoubleQuoteBlock(yyscanner); + yyextra->current->program+=yytext; BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - initTriSingleQuoteBlock(); - current->program+=yytext; + initTriSingleQuoteBlock(yyscanner); + yyextra->current->program+=yytext; BEGIN(TripleComment); } {STARTDOCSYMS}[#]* { // start of a special comment - initSpecialBlock(); + initSpecialBlock(yyscanner); BEGIN(SpecialComment); } {POUNDCOMMENT} { // ignore comment with just one # } ^{BB} { - current->program+=yytext; - //current->startLine = yyLineNr; - g_curIndent=computeIndent(yytext); - bodyEntry = current; - DBG_CTX((stderr,"setting indent %d\n",g_curIndent)); - //printf("current->program=[%s]\n",current->program.data()); - //g_hideClassDocs = TRUE; + yyextra->current->program+=yytext; + //yyextra->current->startLine = yyextra->yyLineNr; + yyextra->curIndent=computeIndent(yytext); + yyextra->bodyEntry = yyextra->current; + DBG_CTX((stderr,"setting indent %d\n",yyextra->curIndent)); + //printf("yyextra->current->program=[%s]\n",yyextra->current->program.data()); + //yyextra->hideClassDocs = TRUE; BEGIN(ClassBody); } ""/({NONEMPTY}|{EXPCHAR}) { // Just pushback an empty class, and // resume parsing the body. - newEntry(); - current->program+=yytext; + newEntry(yyscanner); + yyextra->current->program+=yytext; // printf("Failed to find indent - skipping!"); BEGIN( Search ); @@ -1321,82 +1058,82 @@ STARTDOCSYMS "##" <VariableDec>{ "=" { // the assignment operator - //printf("====== VariableDec at line %d\n",yyLineNr); - g_start_init = TRUE; - current->initializer = yytext; - current->initializer += " "; + //printf("====== VariableDec at line %d\n",yyextra->yyLineNr); + yyextra->start_init = TRUE; + yyextra->current->initializer = yytext; + yyextra->current->initializer += " "; } {B} { // spaces - current->initializer += yytext; + yyextra->current->initializer += yytext; } {INTNUMBER} { // integer value - if (current-> type.isEmpty()) current->type = "int"; - current->initializer += yytext; + if (yyextra->current-> type.isEmpty()) yyextra->current->type = "int"; + yyextra->current->initializer += yytext; } {FLOATNUMBER} { // floating point value - if (current->type.isEmpty()) current->type = "float"; - current->initializer += yytext; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "float"; + yyextra->current->initializer += yytext; } {BOOL} { // boolean value - if (current->type.isEmpty()) current->type = "bool"; - current->initializer += yytext; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "bool"; + yyextra->current->initializer += yytext; } {STRINGPREFIX}?"'" { // string - if (current->type.isEmpty()) current->type = "string"; - current->initializer += yytext; - g_copyString=¤t->initializer; - g_stringContext=VariableDec; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer += yytext; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; BEGIN( SingleQuoteString ); } {STRINGPREFIX}?"\"" { // string - if (current->type.isEmpty()) current->type = "string"; - current->initializer += yytext; - g_copyString=¤t->initializer; - g_stringContext=VariableDec; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer += yytext; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; BEGIN( DoubleQuoteString ); } {TRIDOUBLEQUOTE} { // start of a comment block - if (current->type.isEmpty()) current->type = "string"; - current->initializer += yytext; - g_doubleQuote=TRUE; - g_copyString=¤t->initializer; - g_stringContext=VariableDec; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer += yytext; + yyextra->doubleQuote=TRUE; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; BEGIN(TripleString); } {TRISINGLEQUOTE} { // start of a comment block - if (current->type.isEmpty()) current->type = "string"; - current->initializer += yytext; - g_doubleQuote=FALSE; - g_copyString=¤t->initializer; - g_stringContext=VariableDec; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer += yytext; + yyextra->doubleQuote=FALSE; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; BEGIN(TripleString); } "(" { // tuple, only when direct after = - if (current->mtype!=Property && g_start_init) + if (yyextra->current->mtype!=Property && yyextra->start_init) { - current->type = "tuple"; + yyextra->current->type = "tuple"; } - current->initializer+=*yytext; - g_atomStart='('; - g_atomEnd=')'; - g_atomCount=1; + yyextra->current->initializer+=*yytext; + yyextra->atomStart='('; + yyextra->atomEnd=')'; + yyextra->atomCount=1; BEGIN( VariableAtom ); } "[" { // list - if (g_start_init) current->type = "list"; - current->initializer+=*yytext; - g_atomStart='['; - g_atomEnd=']'; - g_atomCount=1; + if (yyextra->start_init) yyextra->current->type = "list"; + yyextra->current->initializer+=*yytext; + yyextra->atomStart='['; + yyextra->atomEnd=']'; + yyextra->atomCount=1; BEGIN( VariableAtom ); } "{" { // dictionary - if (g_start_init) current->type = "dictionary"; - current->initializer+=*yytext; - g_atomStart='{'; - g_atomEnd='}'; - g_atomCount=1; + if (yyextra->start_init) yyextra->current->type = "dictionary"; + yyextra->current->initializer+=*yytext; + yyextra->atomStart='{'; + yyextra->atomEnd='}'; + yyextra->atomCount=1; BEGIN( VariableAtom ); } "#".* { // comment @@ -1404,26 +1141,26 @@ STARTDOCSYMS "##" } {IDENTIFIER} { // do something based on the type of the IDENTIFIER - if (current->type.isEmpty()) + if (yyextra->current->type.isEmpty()) { - //QListIterator<Entry> eli(*(current_root->children())); + //QListIterator<Entry> eli(*(yyextra->current_root->children())); //Entry *child; - //for (eli.toFirst();(child=eli.current());++eli) - for (const auto &child : current_root->children()) + //for (eli.toFirst();(child=eli.yyextra->current());++eli) + for (const auto &child : yyextra->current_root->children()) { if (child->name == QCString(yytext)) { - current->type = child->type; + yyextra->current->type = child->type; break; } } } - g_start_init = FALSE; - current->initializer+=yytext; + yyextra->start_init = FALSE; + yyextra->current->initializer+=yytext; } . { - g_start_init = FALSE; - current->initializer+=*yytext; + yyextra->start_init = FALSE; + yyextra->current->initializer+=*yytext; } \n { unput('\n'); @@ -1433,71 +1170,71 @@ STARTDOCSYMS "##" <VariableAtom>{ [\(\[\{] { - current->initializer+=*yytext; - if (g_atomStart==*yytext) + yyextra->current->initializer+=*yytext; + if (yyextra->atomStart==*yytext) { - g_atomCount++; + yyextra->atomCount++; } } [\)\]\}] { - current->initializer+=*yytext; - if (g_atomEnd==*yytext) + yyextra->current->initializer+=*yytext; + if (yyextra->atomEnd==*yytext) { - g_atomCount--; + yyextra->atomCount--; } - if (g_atomCount==0) + if (yyextra->atomCount==0) { - g_start_init = FALSE; + yyextra->start_init = FALSE; BEGIN(VariableDec); } } {TRIDOUBLEQUOTE} { // start of a comment block - g_specialBlock = FALSE; - current->program+=yytext; - initTriDoubleQuoteBlock(); + yyextra->specialBlock = FALSE; + yyextra->current->program+=yytext; + initTriDoubleQuoteBlock(yyscanner); BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - g_specialBlock = FALSE; - current->program+=yytext; - initTriSingleQuoteBlock(); + yyextra->specialBlock = FALSE; + yyextra->current->program+=yytext; + initTriSingleQuoteBlock(yyscanner); BEGIN(TripleComment); } "'" { - g_stringContext=YY_START; - current->initializer+="'"; - g_copyString=¤t->initializer; + yyextra->stringContext=YY_START; + yyextra->current->initializer+="'"; + yyextra->copyString=&yyextra->current->initializer; BEGIN( SingleQuoteString ); } "\"" { - g_stringContext=YY_START; - current->initializer+="\""; - g_copyString=¤t->initializer; + yyextra->stringContext=YY_START; + yyextra->current->initializer+="\""; + yyextra->copyString=&yyextra->current->initializer; BEGIN( DoubleQuoteString ); } {IDENTIFIER} { - current->initializer+=yytext; + yyextra->current->initializer+=yytext; } . { - current->initializer+=*yytext; + yyextra->current->initializer+=*yytext; } \n { - current->initializer+=*yytext; - incLineNr(); + yyextra->current->initializer+=*yytext; + incLineNr(yyscanner); } } <VariableEnd>{ \n { - incLineNr(); - newVariable(); + incLineNr(yyscanner); + newVariable(yyscanner); BEGIN(Search); } . { unput(*yytext); - newVariable(); + newVariable(yyscanner); BEGIN(Search); } <<EOF>> { yyterminate(); @@ -1507,78 +1244,75 @@ STARTDOCSYMS "##" <TripleComment>{ {ENDTRIDOUBLEQUOTE} | {ENDTRISINGLEQUOTE} { - // printf("Expected module block %d special=%d\n",g_expectModuleDocs,g_specialBlock); - if (g_doubleQuote==(yytext[0]=='"')) + // printf("Expected module block %d special=%d\n",yyextra->expectModuleDocs,yyextra->specialBlock); + if (yyextra->doubleQuote==(yytext[0]=='"')) { - if (g_specialBlock) // expecting a docstring + if (yyextra->specialBlock) // expecting a docstring { - QCString actualDoc=docBlock; - if (!docBlockSpecial) // legacy unformatted docstring + QCString actualDoc=yyextra->docBlock; + if (!yyextra->docBlockSpecial) // legacy unformatted docstring { - actualDoc.prepend("\\verbatim "); - actualDoc.append("\\endverbatim "); + if (!actualDoc.isEmpty()) + { + stripIndentation(actualDoc,yyextra->commentIndent); + actualDoc.prepend("\\verbatim\n"); + actualDoc.append("\\endverbatim "); + } } - //printf("-------> current=%p bodyEntry=%p\n",current,bodyEntry); - handleCommentBlock(actualDoc, FALSE); + //printf("-------> yyextra->current=%p yyextra->bodyEntry=%p\n",yyextra->current,yyextra->bodyEntry); + handleCommentBlock(yyscanner, actualDoc, FALSE); } - else if (g_packageCommentAllowed) // expecting module docs + else if (yyextra->packageCommentAllowed) // expecting module docs { - QCString actualDoc=docBlock; - if (!docBlockSpecial) // legacy unformatted docstring + QCString actualDoc=yyextra->docBlock; + if (!yyextra->docBlockSpecial) // legacy unformatted docstring { - actualDoc.prepend("\\verbatim "); - actualDoc.append("\\endverbatim "); + if (!actualDoc.isEmpty()) + { + stripIndentation(actualDoc,yyextra->commentIndent); + actualDoc.prepend("\\verbatim\n"); + actualDoc.append("\\endverbatim "); + } } - actualDoc.prepend("\\namespace "+g_moduleScope+" "); - handleCommentBlock(actualDoc, FALSE); + actualDoc.prepend("\\namespace "+yyextra->moduleScope+" "); + handleCommentBlock(yyscanner, actualDoc, FALSE); } - if ((docBlockContext==ClassBody /*&& !g_hideClassDocs*/) || - docBlockContext==FunctionBody) + if ((yyextra->docBlockContext==ClassBody /*&& !yyextra->hideClassDocs*/) || + yyextra->docBlockContext==FunctionBody) { - current->program+=docBlock; - current->program+=yytext; + yyextra->current->program+=yyextra->docBlock; + yyextra->current->program+=yytext; } - //if (g_hideClassDocs) + //if (yyextra->hideClassDocs) //{ - // current->startLine = yyLineNr; + // yyextra->current->startLine = yyextra->yyLineNr; //} - //g_hideClassDocs=FALSE; - BEGIN(docBlockContext); + //yyextra->hideClassDocs=FALSE; + BEGIN(yyextra->docBlockContext); } else { - docBlock += yytext; + yyextra->docBlock += yytext; } - g_packageCommentAllowed = FALSE; + yyextra->packageCommentAllowed = FALSE; } ^{BB} { // leading whitespace - int indent = computeIndent(yytext); - if (indent>=g_curIndent) - { // strip g_curIndent amount of whitespace - int i; - for (i=0;i<indent-g_curIndent;i++) docBlock+=' '; - DBG_CTX((stderr,"stripping indent %d\n",g_curIndent)); - } - else - { - DBG_CTX((stderr,"not stripping: %d<%d\n",indent,g_curIndent)); - docBlock += yytext; - } + yyextra->docBlock += yytext; } [^"'\n \t\\]+ { - docBlock += yytext; + yyextra->docBlock += yytext; } \n { - incLineNr(); - docBlock += yytext; + incLineNr(yyscanner); + yyextra->docBlock += yytext; } \\. { // escaped char - docBlock += yytext; + yyextra->docBlock += yytext; } . { - docBlock += yytext; + yyextra->docBlock += yytext; } } @@ -1586,91 +1320,91 @@ STARTDOCSYMS "##" ^{B}"#"("#")* { // skip leading hashes } \n/{B}"#" { // continuation of the comment on the next line - docBlock+='\n'; - docBrief = FALSE; - startCommentBlock(FALSE); - incLineNr(); + yyextra->docBlock+='\n'; + yyextra->docBrief = FALSE; + startCommentBlock(yyscanner,FALSE); + incLineNr(yyscanner); } [^#\n]+ { // any other stuff - docBlock+=yytext; + yyextra->docBlock+=yytext; } \n { // new line that ends the comment - handleCommentBlock(docBlock, docBrief); - incLineNr(); - BEGIN(docBlockContext); + handleCommentBlock(yyscanner, yyextra->docBlock, yyextra->docBrief); + incLineNr(yyscanner); + BEGIN(yyextra->docBlockContext); } . { // anything we missed - docBlock+=*yytext; + yyextra->docBlock+=*yytext; } } <SingleQuoteString>{ \\{B}\n { // line continuation - addToString(yytext); - incLineNr(); + addToString(yyscanner,yytext); + incLineNr(yyscanner); } \\. { // escaped char - addToString(yytext); + addToString(yyscanner,yytext); } "\"\"\"" { // triple double quotes - addToString(yytext); + addToString(yyscanner,yytext); } "'" { // end of the string - addToString(yytext); - BEGIN(g_stringContext); + addToString(yyscanner,yytext); + BEGIN(yyextra->stringContext); } [^"'\n\\]+ { // normal chars - addToString(yytext); + addToString(yyscanner,yytext); } . { // normal char - addToString(yytext); + addToString(yyscanner,yytext); } } <DoubleQuoteString>{ \\{B}\n { // line continuation - addToString(yytext); - incLineNr(); + addToString(yyscanner,yytext); + incLineNr(yyscanner); } \\. { // escaped char - addToString(yytext); + addToString(yyscanner,yytext); } "'''" { // triple single quotes - addToString(yytext); + addToString(yyscanner,yytext); } "\"" { // end of the string - addToString(yytext); - BEGIN(g_stringContext); + addToString(yyscanner,yytext); + BEGIN(yyextra->stringContext); } [^"'\n\\]+ { // normal chars - addToString(yytext); + addToString(yyscanner,yytext); } . { // normal char - addToString(yytext); + addToString(yyscanner,yytext); } } <TripleString>{ {ENDTRIDOUBLEQUOTE} | {ENDTRISINGLEQUOTE} { - *g_copyString += yytext; - if (g_doubleQuote==(yytext[0]=='"')) + *yyextra->copyString += yytext; + if (yyextra->doubleQuote==(yytext[0]=='"')) { - BEGIN(g_stringContext); + BEGIN(yyextra->stringContext); } } ({LONGSTRINGBLOCK}) { - lineCount(); - *g_copyString += yytext; + lineCount(yyscanner); + *yyextra->copyString += yytext; } \n { - incLineNr(); - *g_copyString += yytext; + incLineNr(yyscanner); + *yyextra->copyString += yytext; } . { - *g_copyString += *yytext; + *yyextra->copyString += *yytext; } } @@ -1679,16 +1413,16 @@ STARTDOCSYMS "##" /* <*>({NONEMPTY}|{EXPCHAR}|{BB}) { // This should go one character at a time. // printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, yyLineNr); + // yytext, YY_START, yyextra->yyLineNr); } */ <*>{NEWLINE} { //printf("[pyscanner] %d NEWLINE [line %d] no match\n", - // YY_START, yyLineNr); + // YY_START, yyextra->yyLineNr); - lineCount(); + lineCount(yyscanner); } <*>"'" { @@ -1697,7 +1431,7 @@ STARTDOCSYMS "##" <*>. { //printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, yyLineNr); + // yytext, YY_START, yyextra->yyLineNr); } @@ -1706,10 +1440,319 @@ STARTDOCSYMS "##" //---------------------------------------------------------------------------- -static void parseCompounds(std::shared_ptr<Entry> rt) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t c=0; + const char *p = yyextra->inputString + yyextra->inputPosition; + while ( c < max_size && *p ) { *buf++ = *p++; c++; } + yyextra->inputPosition+=c; + return c; +} + +static void initParser(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->protection = Public; + yyextra->mtype = Method; + yyextra->stat = FALSE; + yyextra->virt = Normal; + yyextra->previous = 0; + yyextra->packageCommentAllowed = TRUE; + yyextra->packageNameCache.setAutoDelete(TRUE); +} + +static void initEntry(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //yyextra->current->python = TRUE; + yyextra->current->protection = yyextra->protection ; + yyextra->current->mtype = yyextra->mtype; + yyextra->current->virt = yyextra->virt; + yyextra->current->stat = yyextra->stat; + yyextra->current->lang = SrcLangExt_Python; + yyextra->commentScanner.initGroupInfo(yyextra->current.get()); + yyextra->stat = FALSE; +} + +static void newEntry(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->previous = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); +} + +static void newVariable(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->current->name.isEmpty() && yyextra->current->name.at(0)=='_') // mark as private + { + yyextra->current->protection=Private; + } + if (yyextra->current_root->section&Entry::COMPOUND_MASK) // mark as class variable + { + yyextra->current->stat = TRUE; + } + newEntry(yyscanner); +} + +static void newFunction(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->current->name.left(2)=="__" && yyextra->current->name.right(2)=="__") + { + // special method name, see + // http://docs.python.org/ref/specialnames.html + yyextra->current->protection=Public; + } + else if (yyextra->current->name.at(0)=='_') + { + yyextra->current->protection=Private; + } +} + +static inline int computeIndent(const char *s) +{ + int col=0; + int tabSize=Config_getInt(TAB_SIZE); + const char *p=s; + char c; + while ((c=*p++)) + { + if (c==' ') col++; + else if (c=='\t') col+=tabSize-(col%tabSize); + else break; + } + return col; +} + +static QCString findPackageScopeFromPath(yyscan_t yyscanner,const QCString &path) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString *pScope = yyextra->packageNameCache.find(path); + if (pScope) + { + return *pScope; + } + QFileInfo pf(path+"/__init__.py"); // found package initialization file + if (pf.exists()) + { + int i=path.findRev('/'); + if (i!=-1) + { + QCString scope = findPackageScopeFromPath(yyscanner,path.left(i)); + if (!scope.isEmpty()) + { + scope+="::"; + } + scope+=path.mid(i+1); + yyextra->packageNameCache.insert(path,new QCString(scope)); + return scope; + } + } + return ""; +} + +static QCString findPackageScope(yyscan_t yyscanner,const char *fileName) +{ + if (fileName==0) return ""; + QFileInfo fi(fileName); + return findPackageScopeFromPath(yyscanner,fi.dirPath(TRUE).data()); +} + +static void addFrom(yyscan_t yyscanner,bool all) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString item=all ? yyextra->packageName : yyextra->packageName+"."+yytext; + yyextra->current->name=removeRedundantWhiteSpace(substitute(item,".","::")); + yyextra->current->fileName = yyextra->yyFileName; + //printf("Adding using declaration: found:%s:%d name=%s\n",yyextra->yyFileName.data(),yyextra->yyLineNr,yyextra->current->name.data()); + yyextra->current->section=all ? Entry::USINGDIR_SEC : Entry::USINGDECL_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); +} +//----------------------------------------------------------------------------- + +static void lineCount(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + DBG_CTX((stderr,"yyextra->yyLineNr=%d\n",yyextra->yyLineNr)); + for (const char *p = yytext; *p; ++p) + { + yyextra->yyLineNr += (*p == '\n') ; + } +} + +static void incLineNr(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + DBG_CTX((stderr,"yyextra->yyLineNr=%d\n",yyextra->yyLineNr)); + yyextra->yyLineNr++; +} + +//----------------------------------------------------------------- +static void startCommentBlock(yyscan_t yyscanner,bool brief) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (brief) + { + yyextra->current->briefFile = yyextra->yyFileName; + yyextra->current->briefLine = yyextra->yyLineNr; + } + else + { + yyextra->current->docFile = yyextra->yyFileName; + yyextra->current->docLine = yyextra->yyLineNr; + } +} + +static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("handleCommentBlock(doc=[%s] brief=%d yyextra->docBlockInBody=%d yyextra->docBlockJavaStyle=%d\n", + // doc.data(),brief,yyextra->docBlockInBody,yyextra->docBlockJavaStyle); + + // TODO: Fix me + yyextra->docBlockInBody=FALSE; + + if (!yyextra->current->doc.isEmpty()) + { + yyextra->current->doc=yyextra->current->doc.stripWhiteSpace()+"\n\n"; + } + if (yyextra->docBlockInBody && yyextra->previous && !yyextra->previous->doc.isEmpty()) + { + yyextra->previous->doc=yyextra->previous->doc.stripWhiteSpace()+"\n\n"; + } + + int position = 0; + bool needsEntry; + int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine; + Markdown markdown(yyextra->yyFileName,lineNr); + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc,lineNr) : doc; + while (yyextra->commentScanner.parseCommentBlock( + yyextra->thisParser, + (yyextra->docBlockInBody && yyextra->previous) ? yyextra->previous.get() : yyextra->current.get(), + processedDoc, // text + yyextra->yyFileName, // file + lineNr, + yyextra->docBlockInBody ? FALSE : brief, + yyextra->docBlockJavaStyle, // javadoc style // or FALSE, + yyextra->docBlockInBody, + yyextra->protection, + position, + needsEntry, + Config_getBool(MARKDOWN_SUPPORT)) + ) // need to start a new entry + { + if (needsEntry) + { + newEntry(yyscanner); + } + } + if (needsEntry) + { + newEntry(yyscanner); + } + +} + +static void endOfDef(yyscan_t yyscanner,int correction) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("endOfDef at=%d\n",yyextra->yyLineNr); + if (yyextra->bodyEntry) + { + yyextra->bodyEntry->endBodyLine = yyextra->yyLineNr-correction; + yyextra->bodyEntry = 0; + } + newEntry(yyscanner); + //yyextra->insideConstructor = FALSE; +} + +static inline void addToString(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->copyString) (*yyextra->copyString)+=s; +} + +static void initTriDoubleQuoteBlock(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockJavaStyle = TRUE; + yyextra->docBlockSpecial = yytext[strlen(yytext) - 1]=='!' || !Config_getBool(PYTHON_DOCSTRING); + yyextra->docBlock.resize(0); + yyextra->commentIndent = yyextra->curIndent; + yyextra->doubleQuote = TRUE; + startCommentBlock(yyscanner,FALSE); +} + +static void initTriSingleQuoteBlock(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockJavaStyle = TRUE; + yyextra->docBlockSpecial = yytext[strlen(yytext) - 1]=='!' || !Config_getBool(PYTHON_DOCSTRING); + yyextra->docBlock.resize(0); + yyextra->commentIndent = yyextra->curIndent; + yyextra->doubleQuote = FALSE; + startCommentBlock(yyscanner,FALSE); +} + +static void initSpecialBlock(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockJavaStyle = TRUE; + yyextra->docBrief = TRUE; + yyextra->docBlock.resize(0); + yyextra->commentIndent = yyextra->curIndent; + startCommentBlock(yyscanner,TRUE); +} + +static void searchFoundDef(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->section = Entry::FUNCTION_SEC; + yyextra->current->lang = SrcLangExt_Python; + yyextra->current->virt = Normal; + yyextra->current->stat = yyextra->stat; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + yyextra->packageCommentAllowed = FALSE; + yyextra->stat=FALSE; + //printf("searchFoundDef at=%d\n",yyextra->yyLineNr); +} + +static void searchFoundClass(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->argList.clear(); + yyextra->current->type += "class" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->packageCommentAllowed = FALSE; +} + +//---------------------------------------------------------------------------- + +static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("parseCompounds(%s)\n",rt->name.data()); - for (int i=0; i<rt->children().size(); ++i) + for (size_t i=0; i<rt->children().size(); ++i) { std::shared_ptr<Entry> ce = rt->children()[i]; if (!ce->program.isEmpty()) @@ -1717,184 +1760,189 @@ static void parseCompounds(std::shared_ptr<Entry> rt) //printf("-- %s ---------\n%s\n---------------\n", // ce->name.data(),ce->program.data()); // init scanner state - inputString = ce->program; - inputPosition = 0; - pyscannerYYrestart( pyscannerYYin ) ; + yyextra->inputString = ce->program; + yyextra->inputPosition = 0; + pyscannerYYrestart( 0, yyscanner ); if (ce->section&Entry::COMPOUND_MASK) { - current_root = ce; + yyextra->current_root = ce; BEGIN( Search ); } else if (ce->parent()) { - current_root = rt; + yyextra->current_root = rt; //printf("Searching for member variables in %s parent=%s\n", // ce->name.data(),ce->parent->name.data()); BEGIN( SearchMemVars ); } - yyFileName = ce->fileName; - yyLineNr = ce->bodyLine ; - current = std::make_shared<Entry>(); - initEntry(); + yyextra->yyFileName = ce->fileName; + yyextra->yyLineNr = ce->bodyLine ; + yyextra->current = std::make_shared<Entry>(); + initEntry(yyscanner); QCString name = ce->name; - Doxygen::docGroup.enterCompound(yyFileName,yyLineNr,name); + yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name); - pyscannerYYlex() ; - g_lexInit=TRUE; + pyscannerYYlex(yyscanner) ; + yyextra->lexInit=TRUE; ce->program.resize(0); - Doxygen::docGroup.leaveCompound(yyFileName,yyLineNr,name); + yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name); } - parseCompounds(ce); + parseCompounds(yyscanner,ce); } } //---------------------------------------------------------------------------- -static void parseMain(const char *fileName,const char *fileBuf,const std::shared_ptr<Entry> &rt) +static void parseMain(yyscan_t yyscanner, const char *fileName,const char *fileBuf,const std::shared_ptr<Entry> &rt) { - initParser(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + initParser(yyscanner); + + yyextra->inputString = fileBuf; + yyextra->inputPosition = 0; - inputString = fileBuf; - inputPosition = 0; + yyextra->protection = Public; + yyextra->mtype = Method; + yyextra->stat = FALSE; + yyextra->virt = Normal; + yyextra->current_root = rt; + yyextra->specialBlock = FALSE; - protection = Public; - mtype = Method; - gstat = FALSE; - virt = Normal; - current_root = rt; - g_specialBlock = FALSE; + yyextra->yyLineNr= 1 ; + yyextra->yyFileName = fileName; + //setContext(); + msg("Parsing file %s...\n",yyextra->yyFileName.data()); - inputFile.setName(fileName); - if (inputFile.open(IO_ReadOnly)) + QFileInfo fi(fileName); + yyextra->moduleScope = findPackageScope(yyscanner,fileName); + QCString baseName=fi.baseName().utf8(); + if (baseName!="__init__") // package initializer file is not a package itself { - yyLineNr= 1 ; - yyFileName = fileName; - //setContext(); - msg("Parsing file %s...\n",yyFileName.data()); - - QFileInfo fi(fileName); - g_moduleScope = findPackageScope(fileName); - QCString baseName=fi.baseName().utf8(); - if (baseName!="__init__") // package initializer file is not a package itself + if (!yyextra->moduleScope.isEmpty()) { - if (!g_moduleScope.isEmpty()) - { - g_moduleScope+="::"; - } - g_moduleScope+=baseName; + yyextra->moduleScope+="::"; } + yyextra->moduleScope+=baseName; + } - current = std::make_shared<Entry>(); - initEntry(); - current->name = g_moduleScope; - current->section = Entry::NAMESPACE_SEC; - current->type = "namespace"; - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; + yyextra->current = std::make_shared<Entry>(); + initEntry(yyscanner); + yyextra->current->name = yyextra->moduleScope; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "namespace"; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; - current_root = current; + yyextra->current_root = yyextra->current; - rt->moveToSubEntryAndRefresh(current); + rt->moveToSubEntryAndRefresh(yyextra->current); - initParser(); + initParser(yyscanner); - Doxygen::docGroup.enterFile(yyFileName,yyLineNr); - - current->reset(); - initEntry(); - pyscannerYYrestart( pyscannerYYin ); - BEGIN( Search ); - pyscannerYYlex(); - g_lexInit=TRUE; + yyextra->commentScanner.enterFile(yyextra->yyFileName,yyextra->yyLineNr); - Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); + yyextra->current->reset(); + initEntry(yyscanner); + pyscannerYYrestart(0,yyscanner); + BEGIN( Search ); + pyscannerYYlex(yyscanner); + yyextra->lexInit=TRUE; - current_root->program.resize(0); + yyextra->commentScanner.leaveFile(yyextra->yyFileName,yyextra->yyLineNr); - parseCompounds(current_root); + yyextra->current_root->program.resize(0); - inputFile.close(); - } - + parseCompounds(yyscanner, yyextra->current_root); } //---------------------------------------------------------------------------- -static void parsePrototype(const QCString &text) +static void parsePrototype(yyscan_t yyscanner,const QCString &text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("**** parsePrototype(%s) begin\n",text.data()); if (text.isEmpty()) { - warn(yyFileName,yyLineNr,"Empty prototype found!"); + warn(yyextra->yyFileName,yyextra->yyLineNr,"Empty prototype found!"); return; } - g_specialBlock = FALSE; - g_packageCommentAllowed = FALSE; + yyextra->specialBlock = FALSE; + yyextra->packageCommentAllowed = FALSE; const char *orgInputString; - int orgInputPosition; + yy_size_t orgInputPosition; YY_BUFFER_STATE orgState; // save scanner state orgState = YY_CURRENT_BUFFER; - yy_switch_to_buffer(yy_create_buffer(pyscannerYYin, YY_BUF_SIZE)); - orgInputString = inputString; - orgInputPosition = inputPosition; + yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner), yyscanner); + orgInputString = yyextra->inputString; + orgInputPosition = yyextra->inputPosition; // set new string - inputString = text; - inputPosition = 0; - pyscannerYYrestart( pyscannerYYin ); + yyextra->inputString = text; + yyextra->inputPosition = 0; + pyscannerYYrestart( 0, yyscanner ); BEGIN( FunctionDec ); - pyscannerYYlex(); - g_lexInit=TRUE; + pyscannerYYlex(yyscanner); + yyextra->lexInit=TRUE; - current->name = current->name.stripWhiteSpace(); - if (current->section == Entry::MEMBERDOC_SEC && current->args.isEmpty()) - current->section = Entry::VARIABLEDOC_SEC; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + if (yyextra->current->section == Entry::MEMBERDOC_SEC && yyextra->current->args.isEmpty()) + yyextra->current->section = Entry::VARIABLEDOC_SEC; // restore original scanner state YY_BUFFER_STATE tmpBuf = YY_CURRENT_BUFFER; - yy_switch_to_buffer(orgState); - yy_delete_buffer(tmpBuf); + yy_switch_to_buffer(orgState, yyscanner); + yy_delete_buffer(tmpBuf, yyscanner); - inputString = orgInputString; - inputPosition = orgInputPosition; + yyextra->inputString = orgInputString; + yyextra->inputPosition = orgInputPosition; //printf("**** parsePrototype end\n"); } -void pyscanFreeScanner() +//---------------------------------------------------------------------------- + +struct PythonOutlineParser::Private { -#if defined(YY_FLEX_SUBMINOR_VERSION) - if (g_lexInit) - { - pyscannerYYlex_destroy(); - } + yyscan_t yyscanner; + pyscannerYY_state state; +}; + +PythonOutlineParser::PythonOutlineParser() : p(std::make_unique<PythonOutlineParser::Private>()) +{ + pyscannerYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + pyscannerYYset_debug(1,p->yyscanner); #endif } -//---------------------------------------------------------------------------- +PythonOutlineParser::~PythonOutlineParser() +{ + pyscannerYYlex_destroy(p->yyscanner); +} + void PythonOutlineParser::parseInput(const char *fileName, const char *fileBuf, const std::shared_ptr<Entry> &root, - bool /*sameTranslationUnit*/, - QStrList & /*filesInSameTranslationUnit*/) + ClangTUParser * /*clangParser*/) { - g_thisParser = this; + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->thisParser = this; printlex(yy_flex_debug, TRUE, __FILE__, fileName); - ::parseMain(fileName,fileBuf,root); + ::parseMain(p->yyscanner, fileName,fileBuf,root); printlex(yy_flex_debug, FALSE, __FILE__, fileName); // May print the AST for debugging purposes @@ -1908,10 +1956,12 @@ bool PythonOutlineParser::needsPreprocessing(const QCString &) const void PythonOutlineParser::parsePrototype(const char *text) { - ::parsePrototype(text); + ::parsePrototype(p->yyscanner,text); } //---------------------------------------------------------------------------- +#if USE_STATE2STRING #include "pyscanner.l.h" +#endif diff --git a/src/reflist.cpp b/src/reflist.cpp index 016ef49..0aaa75f 100644 --- a/src/reflist.cpp +++ b/src/reflist.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,196 +13,117 @@ * */ +#include <algorithm> + #include <stdio.h> #include "reflist.h" #include "util.h" #include "ftextstream.h" #include "definition.h" +#include "sortdict.h" +#include "config.h" -/*! Create a list of items that are cross referenced with documentation blocks - * @param listName String representing the name of the list. - * @param pageTitle String representing the title of the list page. - * @param secTitle String representing the title of the section. - */ -RefList::RefList(const char *listName, - const char *pageTitle, - const char *secTitle - ) -{ - m_itemList = 0; - m_dict = 0; - m_dictIterator = 0; - m_id = 0; - m_listName = listName; - m_fileName = convertNameToFile(listName,FALSE,TRUE); - m_pageTitle = pageTitle; - m_secTitle = secTitle; -} - -/*! Destroy the todo list. Currently not called! */ -RefList::~RefList() +RefList::RefList(const char *listName, const char *pageTitle, const char *secTitle) : + m_listName(listName), m_fileName(convertNameToFile(listName,FALSE,TRUE)), + m_pageTitle(pageTitle), m_secTitle(secTitle) { - delete m_dictIterator; - delete m_dict; - delete m_itemList; } -/*! Adds a new item to the list. - * \returns A unique id for this item. - */ -int RefList::addRefItem() +RefItem *RefList::add() { - if (m_dict==0) - { - m_dict = new QIntDict<RefItem>(1009); - m_dict->setAutoDelete(TRUE); - m_dictIterator = new QIntDictIterator<RefItem>(*m_dict); - } - RefItem *item = new RefItem; m_id++; - m_dict->insert(m_id,item); - return m_id; -} - -/*! Returns an item given it's id that is obtained with addRefItem() - * \param itemId item's identifier. - * \returns A pointer to the todo item's structure. - */ -RefItem *RefList::getRefItem(int itemId) -{ - return m_dict ? m_dict->find(itemId) : 0; -} - -/*! Returns the first item in the dictionary or 0 if - * non is available. - * Items are not sorted. - */ -RefItem *RefList::getFirstRefItem() -{ - return m_dictIterator ? m_dictIterator->toFirst() : 0; -} - -/*! Returns the next item in the dictionary or 0 if - * we are at the end of the list. - * Items are not sorted. - */ -RefItem *RefList::getNextRefItem() -{ - return m_dictIterator ? m_dictIterator->operator++() : 0; -} - -/*! Returns the name of the list as set in the constructor. */ -QCString RefList::listName() const -{ - return m_listName; -} - -QCString RefList::fileName() const -{ - return m_fileName; + std::unique_ptr<RefItem> item = std::make_unique<RefItem>(m_id,this); + RefItem *result = item.get(); + m_entries.push_back(std::move(item)); + m_lookup.insert({m_id,result}); + return result; } -QCString RefList::pageTitle() const +RefItem *RefList::find(int itemId) { - return m_pageTitle; + auto it = m_lookup.find(itemId); + return it!=m_lookup.end() ? it->second : nullptr; } -QCString RefList::sectionTitle() const +bool RefList::isEnabled() const { - return m_secTitle; + if (m_listName=="todo" && !Config_getBool(GENERATE_TODOLIST)) return false; + else if (m_listName=="test" && !Config_getBool(GENERATE_TESTLIST)) return false; + else if (m_listName=="bug" && !Config_getBool(GENERATE_BUGLIST)) return false; + else if (m_listName=="deprecated" && !Config_getBool(GENERATE_DEPRECATEDLIST)) return false; + return true; } -void RefList::insertIntoList(const char *key,RefItem *item) -{ - if (m_itemList==0) - { - m_itemList = new SortedRefItems(1009); - } - RefItem *ri = m_itemList->find(key); - if (ri==0) - { - m_itemList->append(key,item); - } - else // item already added to the list (i.e. multiple item for the same - // entity) - { - if (ri!=item) - { - // We also have to check if the item is not already in the "extra" list - QListIterator<RefItem> li(ri->extraItems); - RefItem *extraItem; - bool doubleItem = false; - for (li.toFirst();(extraItem=li.current());++li) - { - if (item == extraItem) doubleItem = true; - } - if (!doubleItem) ri->extraItems.append(item); - } - } -} - - void RefList::generatePage() { - if (m_itemList==0) return; - m_itemList->sort(); - SDict<RefItem>::Iterator it(*m_itemList); - RefItem *item; + if (!isEnabled()) return; + + std::sort(m_entries.begin(),m_entries.end(), + [](std::unique_ptr<RefItem> &left,std::unique_ptr<RefItem> &right) + { return qstricmp(left->title(),left->title()); }); + //RefItem *item; QCString doc; + int cnt = 0; doc += "<dl class=\"reflist\">"; - for (it.toFirst();(item=it.current());++it) + QCString lastGroup; + bool first=true; + for (const std::unique_ptr<RefItem> &item : m_entries) { - doc += " <dt>"; - doc += "\n"; - if (item->scope) + if (!item->name()) continue; + cnt++; + bool startNewGroup = item->group()!=lastGroup; + if (startNewGroup) { - if (item->scope->name() != "<globalScope>") + if (!first) { - doc += "\\_setscope "; - doc += item->scope->name(); - doc += " "; + doc += "</dd>"; + first=false; } + doc += " <dt>"; + doc += "\n"; + if (item->scope()) + { + if (item->scope()->name() != "<globalScope>") + { + doc += "\\_setscope "; + doc += item->scope()->name(); + doc += " "; + } + } + doc += item->prefix(); + doc += " \\_internalref "; + doc += item->name(); + // escape \'s in title, see issue #5901 + QCString escapedTitle = substitute(item->title(),"\\","\\\\"); + doc += " \""+escapedTitle+"\" "; + // write declaration in case a function with arguments + if (!item->args().isEmpty()) + { + // escape @'s in argument list, needed for Java annotations (see issue #6208) + // escape \'s in argument list (see issue #6533) + doc += substitute(substitute(item->args(),"@","@@"),"\\","\\\\"); + } + doc += "</dt><dd>"; } - doc += item->prefix; - doc += " \\_internalref "; - doc += item->name; - // escape \'s in title, see issue #5901 - QCString escapedTitle = substitute(item->title,"\\","\\\\"); - if (item->scope && - (item->scope->definitionType()==Definition::TypeClass || - item->scope->definitionType()==Definition::TypeNamespace || - item->scope->definitionType()==Definition::TypeMember || - item->scope->definitionType()==Definition::TypePackage) - ) - { - // prevent Obj-C names in e.g. todo list are seen as emoji - escapedTitle = substitute(escapedTitle,":","∷"); - } - doc += " \""+escapedTitle+"\" "; - // write declaration in case a function with arguments - if (!item->args.isEmpty()) + else { - // escape @'s in argument list, needed for Java annotations (see issue #6208) - // escape \'s in argument list (see issue #6533) - doc += substitute(substitute(item->args,"@","@@"),"\\","\\\\"); + doc += "<p>"; } - doc += "</dt><dd> \\anchor "; - doc += item->listAnchor; + doc += " \\anchor "; + doc += item->anchor(); doc += " "; - doc += item->text; - QListIterator<RefItem> li(item->extraItems); - RefItem *extraItem; - for (li.toFirst();(extraItem=li.current());++li) - { - doc += "<p> \\anchor "; - doc += extraItem->listAnchor; - doc += " "; - doc += extraItem->text; - } + doc += item->text(); + lastGroup = item->group(); + first = false; + } + if (!first) + { doc += "</dd>"; } doc += "</dl>\n"; //printf("generatePage('%s')\n",doc.data()); - addRelatedPage(m_listName,m_pageTitle,doc,m_fileName,1,std::vector<ListItemInfo>(),0,0,TRUE); + if (cnt>0) + { + addRelatedPage(m_listName,m_pageTitle,doc,m_fileName,1,RefItemVector(),0,0,TRUE); + } } - diff --git a/src/reflist.h b/src/reflist.h index d064c58..0ced63b 100644 --- a/src/reflist.h +++ b/src/reflist.h @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,46 +16,61 @@ #ifndef _REFLIST_H #define _REFLIST_H +#include <vector> +#include <unordered_map> +#include <memory> + #include <qintdict.h> #include <qlist.h> -#include "sortdict.h" +#include "linkedmap.h" class Definition; +class RefList; /** This struct represents an item in the list of references. */ -struct RefItem -{ - RefItem() : scope(0) {} - QCString text; //!< text of the item. - QCString listAnchor; //!< anchor in the list - - QCString prefix; //!< type prefix for the name - Definition *scope; //!< scope to use for references. - QCString name; //!< name of the entity containing the reference - QCString title; //!< display name of the entity - QCString args; //!< optional arguments for the entity (if function) - //bool written; - QList<RefItem> extraItems; //!< more items belonging to the same entity -}; - -/** List of items sorted by title */ -class SortedRefItems : public SDict<RefItem> +class RefItem { public: - SortedRefItems(int size=17) : SDict<RefItem>(size) {} - virtual ~SortedRefItems() {} + RefItem(int id,RefList *list) : m_id(id), m_list(list) {} + + void setText (const char *text) { m_text = text; } + void setAnchor(const char *anchor) { m_anchor = anchor; } + void setPrefix(const char *prefix) { m_prefix = prefix; } + void setName (const char *name) { m_name = name; } + void setTitle (const char *title) { m_title = title; } + void setArgs (const char *args) { m_args = args; } + void setGroup (const char *group) { m_group = group; } + void setScope (const Definition *scope) { m_scope = scope; } + + QCString text() const { return m_text; } + QCString anchor() const { return m_anchor; } + QCString prefix() const { return m_prefix; } + QCString name() const { return m_name; } + QCString title() const { return m_title; } + QCString args() const { return m_args; } + QCString group() const { return m_group; } + int id() const { return m_id; } + RefList *list() const { return m_list; } + const Definition *scope() const { return m_scope; } + private: - int compareValues(const RefItem *r1,const RefItem *r2) const - { - return qstricmp(r1->title,r2->title); - } + int m_id = 0; //!< unique identifier for this item within its list + RefList *m_list; //!< list owning this item + QCString m_text; //!< text of the item. + QCString m_anchor; //!< anchor in the list + QCString m_prefix; //!< type prefix for the name + QCString m_name; //!< name of the entity containing the reference + QCString m_title; //!< display name of the entity + QCString m_args; //!< optional arguments for the entity (if function) + QCString m_group; //!< group id used to combine item under a single header + const Definition *m_scope = 0; //!< scope to use for references. }; -/** List of cross-referenced items - * +/** List of cross-referenced items + * * This class represents a list of items that are put - * at a certain point in the documentation by some special command - * and are collected in a list. The items cross-reference the + * at a certain point in the documentation by some special command + * and are collected in a list. The items cross-reference the * documentation and the list. * * Examples are the todo list, the test list and the bug list, @@ -67,31 +79,57 @@ class SortedRefItems : public SDict<RefItem> class RefList { public: - int addRefItem(); - RefItem *getRefItem(int todoItemId); - RefItem *getFirstRefItem(); - RefItem *getNextRefItem(); - QCString listName() const; - QCString fileName() const; - QCString pageTitle() const; - QCString sectionTitle() const; - - RefList(const char *listName, - const char *pageTitle,const char *secTitle - ); - ~RefList(); - void insertIntoList(const char *key,RefItem *item); + /*! Create a list of items that are cross referenced with documentation blocks + * @param listName String representing the name of the list. + * @param pageTitle String representing the title of the list page. + * @param secTitle String representing the title of the section. + */ + RefList(const char *listName, const char *pageTitle, const char *secTitle); + bool isEnabled() const; + + /*! Adds a new item to the list. + * @returns A unique id for this item. + */ + RefItem *add(); + + /*! Returns an item given it's id that is obtained with addRefItem() + * @param itemId item's identifier. + * @returns A pointer to the todo item's structure. + */ + RefItem *find(int itemId); + + QCString listName() const { return m_listName; } + QCString fileName() const { return m_fileName; } + QCString pageTitle() const { return m_pageTitle; } + QCString sectionTitle() const { return m_secTitle; } + void generatePage(); private: - int m_id; + int m_id = 0; QCString m_listName; QCString m_fileName; QCString m_pageTitle; QCString m_secTitle; - SortedRefItems *m_itemList; - QIntDict<RefItem> *m_dict; - QIntDictIterator<RefItem> *m_dictIterator; + std::vector< std::unique_ptr< RefItem > > m_entries; + std::unordered_map< int, RefItem* > m_lookup; +}; + +class RefListManager : public LinkedMap<RefList> +{ + public: + static RefListManager &instance() + { + static RefListManager rlm; + return rlm; + } + + private: + RefListManager() {} + RefListManager(const RefListManager &other) = delete; + RefListManager &operator=(const RefListManager &other) = delete; }; +using RefItemVector = std::vector<RefItem*>; + #endif diff --git a/src/res2cc_cmd.py b/src/res2cc_cmd.py index 86d999d..f6321f6 100755 --- a/src/res2cc_cmd.py +++ b/src/res2cc_cmd.py @@ -58,6 +58,7 @@ class File(object): if ext=='.lum': return LumFile(directory,subdir,fname) if ext=='.luma': return LumaFile(directory,subdir,fname) if ext=='.css': return CSSFile(directory,subdir,fname) + if ext=='.svg': return SVGFile(directory,subdir,fname) return VerbatimFile(directory,subdir,fname) class VerbatimFile(File): @@ -76,6 +77,14 @@ class CSSFile(File): def writeDirEntry(self,outputFile): print(" { \"%s\", \"%s\", %s_data, %s_len, Resource::CSS }," % (self.subdir,self.fileName,self.bareName,self.bareName), file=outputFile) +class SVGFile(File): + def __init__(self,directory,subdir,fileName): + File.__init__(self,directory,subdir,fileName,"r") + def writeContents(self,outputFile): + self.writeBytes(self.inputFile.read(),outputFile) + def writeDirEntry(self,outputFile): + print(" { \"%s\", \"%s\", %s_data, %s_len, Resource::SVG }," % (self.subdir,self.fileName,self.bareName,self.bareName), file=outputFile) + class LumFile(File): def __init__(self,directory,subdir,fileName): File.__init__(self,directory,subdir,fileName,"r") @@ -107,13 +116,10 @@ def main(): print("#include \"resourcemgr.h\"\n",file=outputFile) for f in files: f.writeContents(outputFile) - print("static Resource resourceDir[] =",file=outputFile) - print("{",file=outputFile) + print("void initResources() { ResourceMgr::instance().registerResources({",file=outputFile) for f in files: f.writeDirEntry(outputFile) - print("};",file=outputFile) - print("static int resourceDir_len = %s;" % len(files), file=outputFile) - print("void initResources() { ResourceMgr::instance().registerResources(resourceDir,resourceDir_len); }",file=outputFile) + print("});}",file=outputFile) if __name__ == '__main__': main() diff --git a/src/resourcemgr.cpp b/src/resourcemgr.cpp index 8cb831e..36ce30d 100644 --- a/src/resourcemgr.cpp +++ b/src/resourcemgr.cpp @@ -12,7 +12,8 @@ * input used in their production; they are not affected by this license. * */ -#include <qdict.h> + +#include <map> #include <qfile.h> #include <qcstring.h> #include <qglobal.h> @@ -28,8 +29,7 @@ class ResourceMgr::Private { public: - Private() : resources(257) {} - QDict<Resource> resources; + std::map<std::string,Resource> resources; }; ResourceMgr &ResourceMgr::instance() @@ -38,37 +38,34 @@ ResourceMgr &ResourceMgr::instance() return theInstance; } -ResourceMgr::ResourceMgr() +ResourceMgr::ResourceMgr() : p(std::make_unique<Private>()) { - p = new Private; } ResourceMgr::~ResourceMgr() { - delete p; } -void ResourceMgr::registerResources(const Resource resources[],int numResources) +void ResourceMgr::registerResources(std::initializer_list<Resource> resources) { - for (int i=0;i<numResources;i++) + for (auto &res : resources) { - p->resources.insert(resources[i].name,&resources[i]); + p->resources.insert({res.name,res}); } } bool ResourceMgr::writeCategory(const char *categoryName,const char *targetDir) const { - QDictIterator<Resource> it(p->resources); - const Resource *res; - for (it.toFirst();(res=it.current());++it) + for (auto &kv : p->resources) { - if (qstrcmp(res->category,categoryName)==0) + Resource &res = kv.second; + if (qstrcmp(res.category,categoryName)==0) { - QCString pathName = QCString(targetDir)+"/"+res->name; + QCString pathName = QCString(targetDir)+"/"+res.name; QFile f(pathName); - if (!f.open(IO_WriteOnly) || f.writeBlock((const char *)res->data,res->size)!=res->size) + if (!f.open(IO_WriteOnly) || f.writeBlock((const char *)res.data,res.size)!=res.size) { - err("Failed to write resource '%s' to directory '%s'\n",res->name,targetDir); + err("Failed to write resource '%s' to directory '%s'\n",res.name,targetDir); return FALSE; } } @@ -97,14 +94,14 @@ bool ResourceMgr::copyResourceAs(const char *name,const char *targetDir,const ch { QCString n = name; n = n.left(n.length()-4)+".png"; // replace .lum by .png - uchar *p = (uchar*)res->data; - int width = (p[0]<<8)+p[1]; - int height = (p[2]<<8)+p[3]; + uchar *data = (uchar*)res->data; + ushort width = (data[0]<<8)+data[1]; + ushort height = (data[2]<<8)+data[3]; ColoredImgDataItem images[2]; images[0].name = n; images[0].width = width; images[0].height = height; - images[0].content = &p[4]; + images[0].content = &data[4]; images[0].alpha = 0; images[1].name = 0; // terminator writeColoredImgData(targetDir,images); @@ -115,15 +112,15 @@ bool ResourceMgr::copyResourceAs(const char *name,const char *targetDir,const ch { QCString n = name; n = n.left(n.length()-5)+".png"; // replace .luma by .png - uchar *p = (uchar*)res->data; - int width = (p[0]<<8)+p[1]; - int height = (p[2]<<8)+p[3]; + uchar *data = (uchar*)res->data; + ushort width = (data[0]<<8)+data[1]; + ushort height = (data[2]<<8)+data[3]; ColoredImgDataItem images[2]; images[0].name = n; images[0].width = width; images[0].height = height; - images[0].content = &p[4]; - images[0].alpha = &p[4+width*height]; + images[0].content = &data[4]; + images[0].alpha = &data[4+width*height]; images[1].name = 0; // terminator writeColoredImgData(targetDir,images); return TRUE; @@ -144,12 +141,24 @@ bool ResourceMgr::copyResourceAs(const char *name,const char *targetDir,const ch } else { - t << substitute(buf,"$doxygenversion",getVersion()); + t << substitute(buf,"$doxygenversion",getDoxygenVersion()); } return TRUE; } } break; + case Resource::SVG: + { + QFile f(pathName); + if (f.open(IO_WriteOnly)) + { + QCString buf(res->size+1); + memcpy(buf.rawData(),res->data,res->size); + FTextStream t(&f); + t << replaceColorMarkers(buf); + return TRUE; + } + } } } else @@ -166,7 +175,9 @@ bool ResourceMgr::copyResource(const char *name,const char *targetDir) const const Resource *ResourceMgr::get(const char *name) const { - return p->resources.find(name); + auto it = p->resources.find(name); + if (it!=p->resources.end()) return &it->second; + return 0; } QCString ResourceMgr::getAsString(const char *name) const diff --git a/src/resourcemgr.h b/src/resourcemgr.h index 6e1587d..2d7ad9b 100644 --- a/src/resourcemgr.h +++ b/src/resourcemgr.h @@ -15,12 +15,15 @@ #ifndef RESOURCEMGR_H #define RESOURCEMGR_H +#include <memory> +#include <initializer_list> + #include <qcstring.h> /** @brief Compiled resource */ struct Resource { - enum Type { Verbatim, Luminance, LumAlpha, CSS }; + enum Type { Verbatim, Luminance, LumAlpha, CSS, SVG }; const char *category; const char *name; const unsigned char *data; @@ -36,7 +39,7 @@ class ResourceMgr static ResourceMgr &instance(); /** Registers an array of resources */ - void registerResources(const Resource resources[],int numResources); + void registerResources(std::initializer_list<Resource> resources); /** Writes all resource belonging to a given category to a given target directory */ bool writeCategory(const char *categoryName,const char *targetDir) const; @@ -57,7 +60,7 @@ class ResourceMgr ResourceMgr(); ~ResourceMgr(); class Private; - Private *p; + std::unique_ptr<Private> p; }; #endif diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index 471cf85..fbe7cc1 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -44,13 +44,13 @@ static QCString align(DocHtmlCell *cell) { HtmlAttribList attrs = cell->attribs(); uint i; - for (i=0; i<attrs.count(); ++i) + for (i=0; i<attrs.count(); ++i) { if (attrs.at(i)->name.lower()=="align") { - if (attrs.at(i)->value.lower()=="center") + if (attrs.at(i)->value.lower()=="center") return "\\qc "; - else if (attrs.at(i)->value.lower()=="right") + else if (attrs.at(i)->value.lower()=="right") return "\\qr "; else return ""; } @@ -59,8 +59,8 @@ static QCString align(DocHtmlCell *cell) } RTFDocVisitor::RTFDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const char *langExt) - : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_insidePre(FALSE), + const char *langExt) + : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_indentLevel(0), m_lastIsPara(FALSE), m_langExt(langExt) { } @@ -71,7 +71,7 @@ QCString RTFDocVisitor::getStyle(const char *name) n.sprintf("%s%d",name,m_indentLevel); StyleData *sd = rtf_Style[n]; ASSERT(sd!=0); - return sd->reference; + return sd->reference(); } void RTFDocVisitor::incIndentLevel() @@ -213,7 +213,7 @@ void RTFDocVisitor::visit(DocLineBreak *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visit(DocLineBreak)}\n"); - m_t << "\\par" << endl; + m_t << "\\par" << endl; m_lastIsPara=TRUE; } @@ -309,34 +309,34 @@ void RTFDocVisitor::visit(DocVerbatim *s) Doxygen::parserManager->getCodeParser(lang) .parseCode(m_ci,s->context(),s->text(),langExt, s->isExample(),s->exampleFile()); - //m_t << "\\par" << endl; + //m_t << "\\par" << endl; m_t << "}" << endl; break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); filter(s->text(),TRUE); - //m_t << "\\par" << endl; + //m_t << "\\par" << endl; m_t << "}" << endl; break; - case DocVerbatim::RtfOnly: - m_t << s->text(); + case DocVerbatim::RtfOnly: + m_t << s->text(); break; - case DocVerbatim::HtmlOnly: - case DocVerbatim::LatexOnly: - case DocVerbatim::XmlOnly: + case DocVerbatim::HtmlOnly: + case DocVerbatim::LatexOnly: + case DocVerbatim::XmlOnly: case DocVerbatim::ManOnly: case DocVerbatim::DocbookOnly: /* nothing */ break; - case DocVerbatim::Dot: + case DocVerbatim::Dot: { static int dotindex = 1; QCString fileName(4096); - fileName.sprintf("%s%d%s", - (Config_getString(RTF_OUTPUT)+"/inline_dotgraph_").data(), + fileName.sprintf("%s%d%s", + (Config_getString(RTF_OUTPUT)+"/inline_dotgraph_").data(), dotindex++, ".dot" ); @@ -355,13 +355,13 @@ void RTFDocVisitor::visit(DocVerbatim *s) if (Config_getBool(DOT_CLEANUP)) file.remove(); } break; - case DocVerbatim::Msc: + case DocVerbatim::Msc: { static int mscindex = 1; QCString baseName(4096); baseName.sprintf("%s%d%s", - (Config_getString(RTF_OUTPUT)+"/inline_mscgraph_").data(), + (Config_getString(RTF_OUTPUT)+"/inline_mscgraph_").data(), mscindex++, ".msc" ); @@ -427,7 +427,7 @@ void RTFDocVisitor::visit(DocInclude *inc) switch(inc->type()) { case DocInclude::IncWithLines: - { + { m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); @@ -451,7 +451,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "}" << endl; } break; - case DocInclude::Include: + case DocInclude::Include: m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); @@ -473,8 +473,14 @@ void RTFDocVisitor::visit(DocInclude *inc) case DocInclude::DontIncWithLines: case DocInclude::HtmlInclude: case DocInclude::LatexInclude: + case DocInclude::ManInclude: + case DocInclude::XmlInclude: + case DocInclude::DocbookInclude: break; - case DocInclude::VerbInclude: + case DocInclude::RtfInclude: + m_t << inc->text(); + break; + case DocInclude::VerbInclude: m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); @@ -509,7 +515,7 @@ void RTFDocVisitor::visit(DocInclude *inc) extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -521,8 +527,8 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "}"; } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -538,7 +544,7 @@ void RTFDocVisitor::visit(DocIncOperator *op) QCString locLangExt = getFileNameExtension(op->includeFileName()); if (locLangExt.isEmpty()) locLangExt = m_langExt; SrcLangExt langExt = getLanguageFromFileName(locLangExt); - if (op->isFirst()) + if (op->isFirst()) { if (!m_hide) { @@ -549,10 +555,10 @@ void RTFDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide = TRUE; } - if (op->type()!=DocIncOperator::Skip) + if (op->type()!=DocIncOperator::Skip) { popEnabled(); - if (!m_hide) + if (!m_hide) { FileDef *fd = 0; if (!op->includeFileName().isEmpty()) @@ -576,7 +582,7 @@ void RTFDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); if (!m_hide) @@ -598,7 +604,7 @@ void RTFDocVisitor::visit(DocFormula *f) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visit(DocFormula)}\n"); bool bDisplay = !f->isInline(); - if (bDisplay) + if (bDisplay) { m_t << "\\par"; m_t << "{"; @@ -607,7 +613,7 @@ void RTFDocVisitor::visit(DocFormula *f) m_t << "\\qc"; } m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"" << f->relPath() << f->name() << ".png\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}"; - if (bDisplay) + if (bDisplay) { m_t << "\\par}"; } @@ -630,7 +636,7 @@ void RTFDocVisitor::visit(DocCite *cite) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCite)}\n"); - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { startLink(cite->ref(),cite->file(),cite->anchor()); } @@ -639,7 +645,7 @@ void RTFDocVisitor::visit(DocCite *cite) m_t << "{\\b "; } filter(cite->text()); - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { endLink(cite->ref()); } @@ -671,7 +677,7 @@ void RTFDocVisitor::visitPost(DocAutoList *) if (!m_lastIsPara) m_t << "\\par"; m_t << "}" << endl; m_lastIsPara=TRUE; - if (!m_indentLevel) m_t << "\\par"; + if (!m_indentLevel) m_t << "\\par" << endl; } void RTFDocVisitor::visitPre(DocAutoListItem *) @@ -694,13 +700,13 @@ void RTFDocVisitor::visitPre(DocAutoListItem *) m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocAutoListItem *) +void RTFDocVisitor::visitPost(DocAutoListItem *) { decIndentLevel(); DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoListItem)}\n"); } -void RTFDocVisitor::visitPre(DocPara *) +void RTFDocVisitor::visitPre(DocPara *) { DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n"); } @@ -714,7 +720,7 @@ void RTFDocVisitor::visitPost(DocPara *p) !(p->parent() && // and for parameters & sections p->parent()->kind()==DocNode::Kind_ParamSect ) - ) + ) { m_t << "\\par" << endl; m_lastIsPara=TRUE; @@ -726,7 +732,7 @@ void RTFDocVisitor::visitPre(DocRoot *r) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRoot)}\n"); if (r->indent()) incIndentLevel(); - m_t << "{" << rtf_Style["BodyText"]->reference << endl; + m_t << "{" << rtf_Style["BodyText"]->reference() << endl; } void RTFDocVisitor::visitPost(DocRoot *r) @@ -746,24 +752,24 @@ void RTFDocVisitor::visitPre(DocSimpleSect *s) if (!m_lastIsPara) m_t << "\\par" << endl; m_t << "{"; // start desc //m_t << "{\\b "; // start bold - m_t << "{" << rtf_Style["Heading5"]->reference << endl; + m_t << "{" << rtf_Style["Heading5"]->reference() << endl; switch(s->type()) { - case DocSimpleSect::See: + case DocSimpleSect::See: m_t << theTranslator->trSeeAlso(); break; - case DocSimpleSect::Return: + case DocSimpleSect::Return: m_t << theTranslator->trReturns(); break; - case DocSimpleSect::Author: + case DocSimpleSect::Author: m_t << theTranslator->trAuthor(TRUE,TRUE); break; - case DocSimpleSect::Authors: + case DocSimpleSect::Authors: m_t << theTranslator->trAuthor(TRUE,FALSE); break; - case DocSimpleSect::Version: + case DocSimpleSect::Version: m_t << theTranslator->trVersion(); break; - case DocSimpleSect::Since: + case DocSimpleSect::Since: m_t << theTranslator->trSince(); break; - case DocSimpleSect::Date: + case DocSimpleSect::Date: m_t << theTranslator->trDate(); break; - case DocSimpleSect::Note: + case DocSimpleSect::Note: m_t << theTranslator->trNote(); break; case DocSimpleSect::Warning: m_t << theTranslator->trWarning(); break; @@ -850,7 +856,7 @@ void RTFDocVisitor::visitPre(DocSimpleListItem *) incIndentLevel(); } -void RTFDocVisitor::visitPost(DocSimpleListItem *) +void RTFDocVisitor::visitPost(DocSimpleListItem *) { decIndentLevel(); DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleListItem)}\n"); @@ -869,7 +875,7 @@ void RTFDocVisitor::visitPre(DocSection *s) int level = QMIN(s->level()+1,4); heading.sprintf("Heading%d",level); // set style - m_t << rtf_Style[heading]->reference << endl; + m_t << rtf_Style[heading]->reference() << endl; // make table of contents entry filter(s->title()); m_t << endl << "\\par" << "}" << endl; @@ -879,7 +885,7 @@ void RTFDocVisitor::visitPre(DocSection *s) m_lastIsPara=TRUE; } -void RTFDocVisitor::visitPost(DocSection *) +void RTFDocVisitor::visitPost(DocSection *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSection)}\n"); @@ -892,12 +898,12 @@ void RTFDocVisitor::visitPre(DocHtmlList *l) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlList)}\n"); m_t << "{" << endl; - rtf_listItemInfo[m_indentLevel].isEnum = l->type()==DocHtmlList::Ordered; + rtf_listItemInfo[m_indentLevel].isEnum = l->type()==DocHtmlList::Ordered; rtf_listItemInfo[m_indentLevel].number = 1; m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHtmlList *) +void RTFDocVisitor::visitPost(DocHtmlList *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlList)}\n"); @@ -925,7 +931,7 @@ void RTFDocVisitor::visitPre(DocHtmlListItem *) m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHtmlListItem *) +void RTFDocVisitor::visitPost(DocHtmlListItem *) { decIndentLevel(); DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlListItem)}\n"); @@ -940,7 +946,7 @@ void RTFDocVisitor::visitPre(DocHtmlDescList *) //m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHtmlDescList *) +void RTFDocVisitor::visitPost(DocHtmlDescList *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescList)}\n"); @@ -955,11 +961,11 @@ void RTFDocVisitor::visitPre(DocHtmlDescTitle *) DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescTitle)}\n"); //m_t << "\\par" << endl; //m_t << "{\\b "; - m_t << "{" << rtf_Style["Heading5"]->reference << endl; + m_t << "{" << rtf_Style["Heading5"]->reference() << endl; m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHtmlDescTitle *) +void RTFDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescTitle)}\n"); @@ -976,7 +982,7 @@ void RTFDocVisitor::visitPre(DocHtmlDescData *) m_t << "{" << rtf_Style_Reset << getStyle("DescContinue"); } -void RTFDocVisitor::visitPost(DocHtmlDescData *) +void RTFDocVisitor::visitPost(DocHtmlDescData *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescData)}\n"); @@ -994,7 +1000,7 @@ void RTFDocVisitor::visitPre(DocHtmlTable *) m_lastIsPara=TRUE; } -void RTFDocVisitor::visitPost(DocHtmlTable *) +void RTFDocVisitor::visitPost(DocHtmlTable *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlTable)}\n"); @@ -1010,7 +1016,7 @@ void RTFDocVisitor::visitPre(DocHtmlCaption *) m_t << "{Table \\field\\flddirty{\\*\\fldinst { SEQ Table \\\\*Arabic }}{\\fldrslt {\\noproof 1}} "; } -void RTFDocVisitor::visitPost(DocHtmlCaption *) +void RTFDocVisitor::visitPost(DocHtmlCaption *) { DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCaption)}\n"); m_t << "}\n\\par" << endl; @@ -1045,7 +1051,7 @@ void RTFDocVisitor::visitPre(DocHtmlRow *r) m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHtmlRow *) +void RTFDocVisitor::visitPost(DocHtmlRow *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlRow)}\n"); @@ -1063,7 +1069,7 @@ void RTFDocVisitor::visitPre(DocHtmlCell *c) m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHtmlCell *) +void RTFDocVisitor::visitPost(DocHtmlCell *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCell)}\n"); @@ -1085,7 +1091,7 @@ void RTFDocVisitor::visitPre(DocInternal *) //m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocInternal *) +void RTFDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternal)}\n"); @@ -1101,14 +1107,30 @@ void RTFDocVisitor::visitPre(DocHRef *href) DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHRef)}\n"); if (Config_getBool(RTF_HYPERLINKS)) { - m_t << "{\\field " - "{\\*\\fldinst " - "{ HYPERLINK \"" << href->url() << "\" " - "}{}" - "}" - "{\\fldrslt " - "{\\cs37\\ul\\cf2 "; - + if (href->url().startsWith("#CITEREF")) + { + // when starting with #CITEREF it is a doxygen generated "url"a + // so a local link + QCString cite; + cite = "citelist_" + href->url().right(href->url().length()-1); + m_t << "{\\field " + "{\\*\\fldinst " + "{ HYPERLINK \\\\l \"" << rtfFormatBmkStr(cite) << "\" " + "}{}" + "}" + "{\\fldrslt " + "{\\cs37\\ul\\cf2 "; + } + else + { + m_t << "{\\field " + "{\\*\\fldinst " + "{ HYPERLINK \"" << href->url() << "\" " + "}{}" + "}" + "{\\fldrslt " + "{\\cs37\\ul\\cf2 "; + } } else { @@ -1117,12 +1139,12 @@ void RTFDocVisitor::visitPre(DocHRef *href) m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHRef *) +void RTFDocVisitor::visitPost(DocHRef *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHRef)}\n"); if (Config_getBool(RTF_HYPERLINKS)) - { + { m_t << "}" "}" "}"; @@ -1144,13 +1166,13 @@ void RTFDocVisitor::visitPre(DocHtmlHeader *header) int level = QMIN(header->level(),5); heading.sprintf("Heading%d",level); // set style - m_t << rtf_Style[heading]->reference; + m_t << rtf_Style[heading]->reference(); // make open table of contents entry that will be closed in visitPost method m_t << "{\\tc\\tcl" << level << " "; m_lastIsPara=FALSE; } -void RTFDocVisitor::visitPost(DocHtmlHeader *) +void RTFDocVisitor::visitPost(DocHtmlHeader *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlHeader)}\n"); @@ -1242,7 +1264,7 @@ void RTFDocVisitor::visitPre(DocDotFile *df) writeDotFile(df); } -void RTFDocVisitor::visitPost(DocDotFile *df) +void RTFDocVisitor::visitPost(DocDotFile *df) { DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDotFile)}\n"); includePicturePostRTF(true, df->hasCaption()); @@ -1253,7 +1275,7 @@ void RTFDocVisitor::visitPre(DocMscFile *df) writeMscFile(df); } -void RTFDocVisitor::visitPost(DocMscFile *df) +void RTFDocVisitor::visitPost(DocMscFile *df) { DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocMscFile)}\n"); includePicturePostRTF(true, df->hasCaption()); @@ -1278,7 +1300,7 @@ void RTFDocVisitor::visitPre(DocLink *lnk) startLink(lnk->ref(),lnk->file(),lnk->anchor()); } -void RTFDocVisitor::visitPost(DocLink *lnk) +void RTFDocVisitor::visitPost(DocLink *lnk) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLink)}\n"); @@ -1302,7 +1324,7 @@ void RTFDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void RTFDocVisitor::visitPost(DocRef *ref) +void RTFDocVisitor::visitPost(DocRef *ref) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRef)}\n"); @@ -1316,7 +1338,7 @@ void RTFDocVisitor::visitPre(DocSecRefItem *) DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefItem)}\n"); } -void RTFDocVisitor::visitPost(DocSecRefItem *) +void RTFDocVisitor::visitPost(DocSecRefItem *) { DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefItem)}\n"); } @@ -1332,7 +1354,7 @@ void RTFDocVisitor::visitPre(DocSecRefList *) m_lastIsPara=TRUE; } -void RTFDocVisitor::visitPost(DocSecRefList *) +void RTFDocVisitor::visitPost(DocSecRefList *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefList)}\n"); @@ -1353,7 +1375,7 @@ void RTFDocVisitor::visitPost(DocSecRefList *) // } //} // -//void RTFDocVisitor::visitPost(DocLanguage *l) +//void RTFDocVisitor::visitPost(DocLanguage *l) //{ // DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLanguage)}\n"); // QCString langId = Config_getEnum(OUTPUT_LANGUAGE); @@ -1370,16 +1392,16 @@ void RTFDocVisitor::visitPre(DocParamSect *s) m_t << "{"; // start param list if (!m_lastIsPara) m_t << "\\par" << endl; //m_t << "{\\b "; // start bold - m_t << "{" << rtf_Style["Heading5"]->reference << endl; + m_t << "{" << rtf_Style["Heading5"]->reference() << endl; switch(s->type()) { - case DocParamSect::Param: + case DocParamSect::Param: m_t << theTranslator->trParameters(); break; - case DocParamSect::RetVal: + case DocParamSect::RetVal: m_t << theTranslator->trReturnValues(); break; - case DocParamSect::Exception: + case DocParamSect::Exception: m_t << theTranslator->trExceptions(); break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: m_t << theTranslator->trTemplateParameters(); break; default: ASSERT(0); @@ -1416,7 +1438,7 @@ void RTFDocVisitor::visitPost(DocParamSect *s) void RTFDocVisitor::visitPre(DocParamList *pl) { - static int columnPos[4][5] = + static int columnPos[4][5] = { { 2, 25, 100, 100, 100 }, // no inout, no type { 3, 14, 35, 100, 100 }, // inout, no type { 3, 25, 50, 100, 100 }, // no inout, type @@ -1503,11 +1525,11 @@ void RTFDocVisitor::visitPre(DocParamList *pl) { if (type->kind()==DocNode::Kind_Word) { - visit((DocWord*)type); + visit((DocWord*)type); } else if (type->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)type); + visit((DocLinkedWord*)type); } else if (type->kind()==DocNode::Kind_Sep) { @@ -1519,7 +1541,7 @@ void RTFDocVisitor::visitPre(DocParamList *pl) m_t << "\\cell }"; } } - + if (useTable) { @@ -1537,11 +1559,11 @@ void RTFDocVisitor::visitPre(DocParamList *pl) if (!first) m_t << ","; else first=FALSE; if (param->kind()==DocNode::Kind_Word) { - visit((DocWord*)param); + visit((DocWord*)param); } else if (param->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)param); + visit((DocLinkedWord*)param); } } m_t << "} "; @@ -1596,7 +1618,7 @@ void RTFDocVisitor::visitPre(DocXRefItem *x) } m_t << "{"; // start param list //m_t << "{\\b "; // start bold - m_t << "{" << rtf_Style["Heading5"]->reference << endl; + m_t << "{" << rtf_Style["Heading5"]->reference() << endl; if (Config_getBool(RTF_HYPERLINKS) && !anonymousEnum) { QCString refName; @@ -1615,7 +1637,7 @@ void RTFDocVisitor::visitPre(DocXRefItem *x) m_t << "{\\field " "{\\*\\fldinst " - "{ HYPERLINK \\\\l \"" << refName << "\" " + "{ HYPERLINK \\\\l \"" << rtfFormatBmkStr(refName) << "\" " "}{}" "}" "{\\fldrslt " @@ -1655,7 +1677,7 @@ void RTFDocVisitor::visitPre(DocInternalRef *ref) startLink("",ref->file(),ref->anchor()); } -void RTFDocVisitor::visitPost(DocInternalRef *) +void RTFDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternalRef)}\n"); @@ -1682,7 +1704,7 @@ void RTFDocVisitor::visitPre(DocHtmlBlockQuote *) if (!m_lastIsPara) m_t << "\\par" << endl; m_t << "{"; // start desc incIndentLevel(); - m_t << rtf_Style_Reset << getStyle("DescContinue"); + m_t << rtf_Style_Reset << getStyle("DescContinue"); } void RTFDocVisitor::visitPost(DocHtmlBlockQuote *) @@ -1724,7 +1746,7 @@ void RTFDocVisitor::visitPost(DocParBlock *) //} void RTFDocVisitor::filter(const char *str,bool verbatim) -{ +{ if (str) { const unsigned char *p=(const unsigned char *)str; @@ -1755,7 +1777,7 @@ void RTFDocVisitor::filter(const char *str,bool verbatim) case '\\': m_t << "\\\\"; break; case '\n': if (verbatim) { - m_t << "\\par" << endl; + m_t << "\\par" << endl; } else { @@ -1836,7 +1858,7 @@ void RTFDocVisitor::writeDotFile(const QCString &filename, bool hasCaption) if ((i=baseName.findRev('/'))!=-1) { baseName=baseName.right(baseName.length()-i-1); - } + } QCString outDir = Config_getString(RTF_OUTPUT); writeDotGraphFromFile(filename,outDir,baseName,GOF_BITMAP); QCString imgExt = getDotImageExtension(); @@ -1854,7 +1876,7 @@ void RTFDocVisitor::writeMscFile(const QCString &fileName, bool hasCaption) if ((i=baseName.findRev('/'))!=-1) { baseName=baseName.right(baseName.length()-i-1); - } + } QCString outDir = Config_getString(RTF_OUTPUT); writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP); includePicturePreRTF(baseName + ".png", true, hasCaption); diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 79411c6..9d0a957 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Parker Waechter & Dimitri van Heesch. * @@ -61,7 +61,7 @@ static QCString dateToRTFDateString() d.date().year(), d.date().month(), d.date().day(), d.time().hour(),d.time().minute(),d.time().second()); return result; -} +} RTFGenerator::RTFGenerator() : OutputGenerator() { @@ -79,10 +79,20 @@ RTFGenerator::~RTFGenerator() { } +void RTFGenerator::setRelativePath(const QCString &path) +{ + m_relPath = path; +} + +void RTFGenerator::setSourceFileName(const QCString &name) +{ + m_sourceFileName = name; +} + void RTFGenerator::writeStyleSheetFile(QFile &file) { FTextStream t(&file); - t << "# Generated by doxygen " << getVersion() << "\n\n"; + t << "# Generated by doxygen " << getDoxygenVersion() << "\n\n"; t << "# This file describes styles used for generating RTF output.\n"; t << "# All text after a hash (#) is considered a comment and will be ignored.\n"; t << "# Remove a hash to activate a line.\n\n"; @@ -99,7 +109,7 @@ void RTFGenerator::writeStyleSheetFile(QFile &file) void RTFGenerator::writeExtensionsFile(QFile &file) { FTextStream t(&file); - t << "# Generated by doxygen " << getVersion() << "\n\n"; + t << "# Generated by doxygen " << getDoxygenVersion() << "\n\n"; t << "# This file describes extensions used for generating RTF output.\n"; t << "# All text after a hash (#) is considered a comment and will be ignored.\n"; t << "# Remove a hash to activate a line.\n\n"; @@ -164,21 +174,26 @@ void RTFGenerator::init() while(def->reference != 0) { if (def->definition == 0) + { err("Internal: rtf_Style_Default[%s] has no definition.\n", def->name); - StyleData* styleData = new StyleData(def->reference, def->definition); - rtf_Style.insert(def->name, styleData); + } + else + { + StyleData* styleData = new StyleData(def->reference, def->definition); + rtf_Style.insert(def->name, styleData); + } def++; } // overwrite some (or all) definitions from file - QCString &rtfStyleSheetFile = Config_getString(RTF_STYLESHEET_FILE); + QCString rtfStyleSheetFile = Config_getString(RTF_STYLESHEET_FILE); if (!rtfStyleSheetFile.isEmpty()) { loadStylesheet(rtfStyleSheetFile, rtf_Style); } // If user has defined an extension file, load its contents. - QCString &rtfExtensionsFile = Config_getString(RTF_EXTENSIONS_FILE); + QCString rtfExtensionsFile = Config_getString(RTF_EXTENSIONS_FILE); if (!rtfExtensionsFile.isEmpty()) { loadExtensions(rtfExtensionsFile); @@ -273,21 +288,20 @@ void RTFGenerator::beginRTFDocument() // sort styles ascending by \s-number via an intermediate QArray QDictIterator<StyleData> iter(rtf_Style); - const StyleData* style; + const StyleData* style = 0; unsigned maxIndex = 0; for(; (style = iter.current()); ++iter) { - unsigned index = style->index; + uint index = style->index(); if (maxIndex < index) maxIndex = index; } - QArray<const StyleData*> array(maxIndex + 1); - array.fill(0); + std::vector<const StyleData*> array(maxIndex + 1, 0); ASSERT(maxIndex < array.size()); iter.toFirst(); for(; (style = iter.current()); ++iter) { - unsigned index = style->index; + uint index = style->index(); if (array.at(index) != 0) { QCString key(iter.currentKey()); @@ -297,12 +311,14 @@ void RTFGenerator::beginRTFDocument() } // write array elements - unsigned size = array.size(); - for(unsigned i = 0; i < size; i++) + size_t size = array.size(); + for(size_t i = 0; i < size; i++) { - const StyleData* style = array.at(i); + style = array.at(i); if (style != 0) - t <<"{" << style->reference << style->definition << ";}\n"; + { + t <<"{" << style->reference() << style->definition() << ";}\n"; + } } t <<"}" << endl; @@ -328,7 +344,7 @@ void RTFGenerator::beginRTFChapter() t <<"\\sect\\sbkpage\n"; //t <<"\\sect\\sectd\\sbkpage\n"; - t << rtf_Style["Heading1"]->reference << "\n"; + t << rtf_Style["Heading1"]->reference() << "\n"; } void RTFGenerator::beginRTFSection() @@ -340,15 +356,15 @@ void RTFGenerator::beginRTFSection() // if we are compact, no extra page breaks... if (Config_getBool(COMPACT_RTF)) { - // t <<"\\sect\\sectd\\sbknone\n"; t <<"\\sect\\sbknone\n"; rtfwriteRuler_emboss(); } else + { t <<"\\sect\\sbkpage\n"; - //t <<"\\sect\\sectd\\sbkpage\n"; + } - t << rtf_Style["Heading2"]->reference << "\n"; + t << rtf_Style["Heading2"]->reference() << "\n"; } void RTFGenerator::startFile(const char *name,const char *,const char *) @@ -359,6 +375,8 @@ void RTFGenerator::startFile(const char *name,const char *,const char *) if (fileName.right(4)!=".rtf" ) fileName+=".rtf"; startPlainFile(fileName); + setRelativePath(m_relPath); + setSourceFileName(stripPath(fileName)); beginRTFDocument(); } @@ -368,6 +386,7 @@ void RTFGenerator::endFile() t << "}"; endPlainFile(); + setSourceFileName(""); } void RTFGenerator::startProjectNumber() @@ -500,7 +519,7 @@ void RTFGenerator::startIndexSection(IndexSections is) bool found=FALSE; for (cli.toFirst();(cd=cli.current()) && !found;++cli) { - if (cd->isLinkableInProject() && + if (cd->isLinkableInProject() && cd->templateMaster()==0 && !cd->isEmbeddedInOuterScope() ) @@ -515,13 +534,9 @@ void RTFGenerator::startIndexSection(IndexSections is) { //File Documentation bool isFirst=TRUE; - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->isLinkableInProject()) { @@ -561,7 +576,7 @@ void RTFGenerator::startIndexSection(IndexSections is) void RTFGenerator::endIndexSection(IndexSections is) { bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); + bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); static QCString projectName = Config_getString(PROJECT_NAME); @@ -576,18 +591,18 @@ void RTFGenerator::endIndexSection(IndexSections is) break; case isTitlePageAuthor: { - t << " doxygen.}\n"; + t << " doxygen" << getDoxygenVersion() << ".}\n"; t << "{\\creatim " << dateToRTFDateString() << "}\n}"; DBG_RTF(t << "{\\comment end of infoblock}\n"); // setup for this section t << rtf_Style_Reset <<"\n"; t <<"\\sectd\\pgnlcrm\n"; - t <<"{\\footer "<<rtf_Style["Footer"]->reference << "{\\chpgn}}\n"; + t <<"{\\footer "<<rtf_Style["Footer"]->reference() << "{\\chpgn}}\n"; // the title entry DBG_RTF(t << "{\\comment begin title page}\n") - t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to title style + t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference() << endl; // set to title style t << "\\vertalc\\qc\\par\\par\\par\\par\\par\\par\\par\n"; if (rtf_logoFilename) @@ -600,7 +615,7 @@ void RTFGenerator::endIndexSection(IndexSections is) t << rtf_company << "\\par\\par\n"; } - t << rtf_Style_Reset << rtf_Style["Title"]->reference << endl; // set to title style + t << rtf_Style_Reset << rtf_Style["Title"]->reference() << endl; // set to title style if (rtf_title) // User has overridden document title in extensions file t << "{\\field\\fldedit {\\*\\fldinst TITLE \\\\*MERGEFORMAT}{\\fldrslt " << rtf_title << "}}\\par" << endl; @@ -610,10 +625,10 @@ void RTFGenerator::endIndexSection(IndexSections is) t << "{\\field\\fldedit {\\*\\fldinst TITLE \\\\*MERGEFORMAT}{\\fldrslt "; writeDoc(root,0,0); t << "}}\\par" << endl; - + } - t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to title style + t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference() << endl; // set to title style t << "\\par\n"; if (rtf_documentType) { @@ -625,7 +640,7 @@ void RTFGenerator::endIndexSection(IndexSections is) } t << "\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\n"; - t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to subtitle style + t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference() << endl; // set to subtitle style if (rtf_author) t << "{\\field\\fldedit {\\*\\fldinst AUTHOR \\\\*MERGEFORMAT}{\\fldrslt "<< rtf_author << " }}\\par" << endl; else @@ -641,7 +656,7 @@ void RTFGenerator::endIndexSection(IndexSections is) DBG_RTF(t << "{\\comment Table of contents}\n") t << "\\vertalt\n"; t << rtf_Style_Reset << endl; - t << rtf_Style["Heading1"]->reference; + t << rtf_Style["Heading1"]->reference(); t << theTranslator->trRTFTableOfContents() << "\\par"<< endl; t << rtf_Style_Reset << "\\par" << endl; t << "{\\field\\fldedit {\\*\\fldinst TOC \\\\f \\\\*MERGEFORMAT}{\\fldrslt Table of contents}}\\par\n"; @@ -688,7 +703,7 @@ void RTFGenerator::endIndexSection(IndexSections is) { t << "{\\tc \\v " << theTranslator->trNamespaceIndex() << "}" << endl; } - + t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"namespaces.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isClassHierarchyIndex: @@ -801,7 +816,7 @@ void RTFGenerator::endIndexSection(IndexSections is) } for (cli.toFirst();(cd=cli.current()) && !found;++cli) { - if (cd->isLinkableInProject() && + if (cd->isLinkableInProject() && cd->templateMaster()==0 && !cd->isEmbeddedInOuterScope() ) @@ -815,7 +830,7 @@ void RTFGenerator::endIndexSection(IndexSections is) } for (;(cd=cli.current());++cli) { - if (cd->isLinkableInProject() && + if (cd->isLinkableInProject() && cd->templateMaster()==0 && !cd->isEmbeddedInOuterScope() ) @@ -834,13 +849,9 @@ void RTFGenerator::endIndexSection(IndexSections is) bool isFirst=TRUE; t << "{\\tc \\v " << theTranslator->trFileDocumentation() << "}"<< endl; - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (fnli.toFirst();(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (fd->isLinkableInProject()) { @@ -927,7 +938,7 @@ void RTFGenerator::endIndexSection(IndexSections is) break; case isEndIndex: beginRTFChapter(); - t << rtf_Style["Heading1"]->reference; + t << rtf_Style["Heading1"]->reference(); t << theTranslator->trRTFGeneralIndex() << "\\par "<< endl; t << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trRTFGeneralIndex() << "}" << endl; @@ -953,8 +964,7 @@ void RTFGenerator::lastIndexPage() t <<"\\sect \\sectd \\sbknone\n"; // set new footer with arabic numbers - t <<"{\\footer "<< rtf_Style["Footer"]->reference << "{\\chpgn}}\n"; - //t << rtf_Style["Heading1"]->reference << "\n"; + t <<"{\\footer "<< rtf_Style["Footer"]->reference() << "{\\chpgn}}\n"; } @@ -1212,7 +1222,7 @@ void RTFGenerator::startSubsection() t <<"\n"; DBG_RTF(t << "{\\comment Begin SubSection}\n") t << rtf_Style_Reset; - t << rtf_Style["Heading3"]->reference << "\n"; + t << rtf_Style["Heading3"]->reference() << "\n"; } void RTFGenerator::endSubsection() @@ -1227,7 +1237,7 @@ void RTFGenerator::startSubsubsection() t << "\n"; DBG_RTF(t << "{\\comment Begin SubSubSection}\n") t << "{" << endl; - t << rtf_Style_Reset << rtf_Style["Heading4"]->reference << "\n"; + t << rtf_Style_Reset << rtf_Style["Heading4"]->reference() << "\n"; } void RTFGenerator::endSubsubsection() @@ -1245,22 +1255,22 @@ void RTFGenerator::endSubsubsection() // t << "}"; //} -//void RTFGenerator::startTable(bool,int colNumbers) +//void RTFGenerator::startTable(bool,int colNumbers) //{ // DBG_RTF(t << "{\\comment startTable}\n";) // m_numCols=colNumbers; // t << "\\par\n"; //} // -//void RTFGenerator::endTable(bool hasCaption) -//{ +//void RTFGenerator::endTable(bool hasCaption) +//{ // DBG_RTF(t << "{\\comment endTable}\n";) -// if (!hasCaption) -// t << "\n\\pard \\widctlpar\\intbl\\adjustright\n{\\row }\n"; -// t << "\\pard\n" << endl; +// if (!hasCaption) +// t << "\n\\pard \\widctlpar\\intbl\\adjustright\n{\\row }\n"; +// t << "\\pard\n" << endl; //} // -//void RTFGenerator::startCaption() +//void RTFGenerator::startCaption() //{ // DBG_RTF(t << "{\\comment startCaption}\n";) // endTableRow(); @@ -1269,15 +1279,15 @@ void RTFGenerator::endSubsubsection() // nextTableColumn(); //} // -//void RTFGenerator::endCaption() +//void RTFGenerator::endCaption() //{ // DBG_RTF(t << "{\\comment endCaption}\n";) // endTableColumn(); // endTableRow(); //} // -//void RTFGenerator::nextTableRow() -//{ +//void RTFGenerator::nextTableRow() +//{ // DBG_RTF(t << "{\\comment nextTableRow}\n";) // ASSERT(m_numCols>0 && m_numCols<25); // uint columnWidth=rtf_pageWidth/m_numCols; @@ -1285,7 +1295,7 @@ void RTFGenerator::endSubsubsection() // "\\trbrdrl\\brdrs\\brdrw10 \\trbrdrb\\brdrs\\brdrw10 " // "\\trbrdrr\\brdrs\\brdrw10 \\trbrdrh\\brdrs\\brdrw10 " // "\\trbrdrv\\brdrs\\brdrw10 "<<endl; -// for (int i=0;i<m_numCols;i++) +// for (int i=0;i<m_numCols;i++) // { // t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 \\clbrdrl\\brdrs\\brdrw10 " // "\\clbrdrb\\brdrs\\brdrw10 \\clbrdrr \\brdrs\\brdrw10 \\cltxlrtb " @@ -1293,21 +1303,21 @@ void RTFGenerator::endSubsubsection() // } // t << "\\pard \\widctlpar\\intbl\\adjustright\n{"; //} -// -//void RTFGenerator::endTableRow() -//{ +// +//void RTFGenerator::endTableRow() +//{ // DBG_RTF(t << "{\\comment endTableRow}\n";) // t << "\n\\pard \\widctlpar\\intbl\\adjustright\n{\\row }\n"; //} -// -//void RTFGenerator::nextTableColumn() +// +//void RTFGenerator::nextTableColumn() //{ // DBG_RTF(t << "{\\comment nextTableColumn}\n";) // t << "{ "; //} // -//void RTFGenerator::endTableColumn() -//{ +//void RTFGenerator::endTableColumn() +//{ // DBG_RTF(t << "{\\comment endTableColumn}\n";) // t << " \\cell }"; //} @@ -1435,7 +1445,7 @@ void RTFGenerator::startTitleHead(const char *) DBG_RTF(t <<"{\\comment startTitleHead}" << endl) // beginRTFSection(); - t << rtf_Style_Reset << rtf_Style["Heading2"]->reference << endl; + t << rtf_Style_Reset << rtf_Style["Heading2"]->reference() << endl; } void RTFGenerator::endTitleHead(const char *fileName,const char *name) @@ -1480,15 +1490,15 @@ void RTFGenerator::startGroupHeader(int extraIndent) t << rtf_Style_Reset; if (extraIndent==2) { - t << rtf_Style["Heading5"]->reference; + t << rtf_Style["Heading5"]->reference(); } else if (extraIndent==1) { - t << rtf_Style["Heading4"]->reference; + t << rtf_Style["Heading4"]->reference(); } else // extraIndent==0 { - t << rtf_Style["Heading3"]->reference; + t << rtf_Style["Heading3"]->reference(); } t << endl; } @@ -1514,10 +1524,10 @@ void RTFGenerator::startMemberDoc(const char *clname, addIndexItem(memname,clname); addIndexItem(clname,memname); } - t << rtf_Style_Reset << rtf_Style[showInline ? "Heading5" : "Heading4"]->reference; + t << rtf_Style_Reset << rtf_Style[showInline ? "Heading5" : "Heading4"]->reference(); //styleStack.push(rtf_Style_Heading4); t << "{" << endl; - //printf("RTFGenerator::startMemberDoc() '%s'\n",rtf_Style["Heading4"]->reference); + //printf("RTFGenerator::startMemberDoc() '%s'\n",rtf_Style["Heading4"]->reference()); startBold(); t << endl; } @@ -1527,7 +1537,7 @@ void RTFGenerator::endMemberDoc(bool) DBG_RTF(t << "{\\comment endMemberDoc}" << endl) //const char *style = styleStack.pop(); //printf("RTFGenerator::endMemberDoc() '%s'\n",style); - //ASSERT(style==rtf_Style["Heading4"]->reference); + //ASSERT(style==rtf_Style["Heading4"]->reference()); endBold(); t << "}" << endl; newParagraph(); @@ -1686,7 +1696,7 @@ void RTFGenerator::endDescForItem() //} -void RTFGenerator::startSection(const char *,const char *title,SectionInfo::SectionType type) +void RTFGenerator::startSection(const char *,const char *title,SectionType type) { DBG_RTF(t << "{\\comment (startSection)}" << endl) t << "{"; @@ -1694,24 +1704,24 @@ void RTFGenerator::startSection(const char *,const char *title,SectionInfo::Sect int num=4; switch(type) { - case SectionInfo::Page: num=2; break; - case SectionInfo::Section: num=3; break; - case SectionInfo::Subsection: num=4; break; - case SectionInfo::Subsubsection: num=4; break; - case SectionInfo::Paragraph: num=4; break; + case SectionType::Page: num=2; break; + case SectionType::Section: num=3; break; + case SectionType::Subsection: num=4; break; + case SectionType::Subsubsection: num=4; break; + case SectionType::Paragraph: num=4; break; default: ASSERT(0); break; } QCString heading; heading.sprintf("Heading%d",num); // set style - t << rtf_Style[heading]->reference; + t << rtf_Style[heading]->reference(); // make table of contents entry t << "{\\tc\\tcl" << num << " \\v "; docify(title); t << "}" << endl; } -void RTFGenerator::endSection(const char *lab,SectionInfo::SectionType) +void RTFGenerator::endSection(const char *lab,SectionType) { DBG_RTF(t << "{\\comment (endSection)}" << endl) // make bookmark @@ -2012,7 +2022,7 @@ void RTFGenerator::startDescTable(const char *title) { DBG_RTF(t << "{\\comment (startDescTable) }" << endl) t << "{\\par" << endl; - t << "{" << rtf_Style["Heading5"]->reference << endl; + t << "{" << rtf_Style["Heading5"]->reference() << endl; docify(title); t << ":\\par}" << endl; t << rtf_Style_Reset << rtf_DList_DepthStyle(); @@ -2100,40 +2110,40 @@ void RTFGenerator::decrementIndentLevel() const char * RTFGenerator::rtf_CList_DepthStyle() { QCString n=makeIndexName("ListContinue",m_listLevel); - return rtf_Style[n]->reference; + return rtf_Style[n]->reference(); } // a style for list formatted as a "latext style" table of contents const char * RTFGenerator::rtf_LCList_DepthStyle() { QCString n=makeIndexName("LatexTOC",m_listLevel); - return rtf_Style[n]->reference; + return rtf_Style[n]->reference(); } // a style for list formatted as a "bullet" style const char * RTFGenerator::rtf_BList_DepthStyle() { QCString n=makeIndexName("ListBullet",m_listLevel); - return rtf_Style[n]->reference; + return rtf_Style[n]->reference(); } // a style for list formatted as a "enumeration" style const char * RTFGenerator::rtf_EList_DepthStyle() { QCString n=makeIndexName("ListEnum",m_listLevel); - return rtf_Style[n]->reference; + return rtf_Style[n]->reference(); } const char * RTFGenerator::rtf_DList_DepthStyle() { QCString n=makeIndexName("DescContinue",m_listLevel); - return rtf_Style[n]->reference; + return rtf_Style[n]->reference(); } const char * RTFGenerator::rtf_Code_DepthStyle() { QCString n=makeIndexName("CodeExample",m_listLevel); - return rtf_Style[n]->reference; + return rtf_Style[n]->reference(); } void RTFGenerator::startTextBlock(bool dense) @@ -2143,11 +2153,11 @@ void RTFGenerator::startTextBlock(bool dense) t << rtf_Style_Reset; if (dense) // no spacing between "paragraphs" { - t << rtf_Style["DenseText"]->reference; + t << rtf_Style["DenseText"]->reference(); } else // some spacing { - t << rtf_Style["BodyText"]->reference; + t << rtf_Style["BodyText"]->reference(); } } @@ -2463,7 +2473,7 @@ static bool preProcessFile(QDir &d,QCString &infName, FTextStream &t, bool bIncl { // null terminate at the last '}' //char *str = strrchr(buffer,'}'); - int pos = lineBuf.findRev('}'); + pos = lineBuf.findRev('}'); if (pos != -1) lineBuf.at(pos) = '\0'; @@ -2681,7 +2691,7 @@ void RTFGenerator::startMemberGroupHeader(bool hasHeader) DBG_RTF(t << "{\\comment startMemberGroupHeader}" << endl) t << "{" << endl; if (hasHeader) incrementIndentLevel(); - t << rtf_Style_Reset << rtf_Style["GroupHeader"]->reference; + t << rtf_Style_Reset << rtf_Style["GroupHeader"]->reference(); } void RTFGenerator::endMemberGroupHeader() @@ -2795,32 +2805,32 @@ void RTFGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); - delete visitor; + delete visitor; m_omitParagraph = TRUE; } -void RTFGenerator::rtfwriteRuler_doubleline() -{ +void RTFGenerator::rtfwriteRuler_doubleline() +{ DBG_RTF(t << "{\\comment (rtfwriteRuler_doubleline)}" << endl) - t << "{\\pard\\widctlpar\\brdrb\\brdrdb\\brdrw15\\brsp20 \\adjustright \\par}" << endl; + t << "{\\pard\\widctlpar\\brdrb\\brdrdb\\brdrw15\\brsp20 \\adjustright \\par}" << endl; } -void RTFGenerator::rtfwriteRuler_emboss() -{ +void RTFGenerator::rtfwriteRuler_emboss() +{ DBG_RTF(t << "{\\comment (rtfwriteRuler_emboss)}" << endl) - t << "{\\pard\\widctlpar\\brdrb\\brdremboss\\brdrw15\\brsp20 \\adjustright \\par}" << endl; + t << "{\\pard\\widctlpar\\brdrb\\brdremboss\\brdrw15\\brsp20 \\adjustright \\par}" << endl; } -void RTFGenerator::rtfwriteRuler_thick() -{ +void RTFGenerator::rtfwriteRuler_thick() +{ DBG_RTF(t << "{\\comment (rtfwriteRuler_thick)}" << endl) - t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw75\\brsp20 \\adjustright \\par}" << endl; + t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw75\\brsp20 \\adjustright \\par}" << endl; } -void RTFGenerator::rtfwriteRuler_thin() -{ +void RTFGenerator::rtfwriteRuler_thin() +{ DBG_RTF(t << "{\\comment (rtfwriteRuler_thin)}" << endl) - t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}" << endl; + t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}" << endl; } #if 0 @@ -2833,9 +2843,9 @@ void RTFGenerator::postProcess(QByteArray &a) for (i=0;i<a.size();i++) { unsigned char c = (unsigned char)a.at(i); - + // treat characters > 0x80 as multibyte characters, except when they - // are control characters + // are control characters if (c>0x80 || (mbFlag && c!='\\' && c!='{' && c!='}')) { char s[10]; @@ -2858,7 +2868,7 @@ void RTFGenerator::startConstraintList(const char *header) { DBG_RTF(t << "{\\comment (startConstraintList)}" << endl) t << "{"; // ends at endConstraintList - t << "{"; + t << "{"; startBold(); newParagraph(); docify(header); @@ -2926,15 +2936,15 @@ void RTFGenerator::endIndexListItem() t << "\\par" << endl; } -void RTFGenerator::startInlineHeader() +void RTFGenerator::startInlineHeader() { DBG_RTF(t << "{\\comment (startInlineHeader)}" << endl) t << "{" << endl; - t << rtf_Style_Reset << rtf_Style["Heading5"]->reference; + t << rtf_Style_Reset << rtf_Style["Heading5"]->reference(); startBold(); } -void RTFGenerator::endInlineHeader() +void RTFGenerator::endInlineHeader() { DBG_RTF(t << "{\\comment (endInlineHeader)}" << endl) endBold(); @@ -2946,7 +2956,7 @@ void RTFGenerator::startMemberDocSimple(bool isEnum) { DBG_RTF(t << "{\\comment (startMemberDocSimple)}" << endl) t << "{\\par" << endl; - t << "{" << rtf_Style["Heading5"]->reference << endl; + t << "{" << rtf_Style["Heading5"]->reference() << endl; if (isEnum) { t << theTranslator->trEnumerationValues(); @@ -3025,12 +3035,33 @@ void RTFGenerator::endInlineMemberDoc() t << "\\cell }{\\row }" << endl; } -void RTFGenerator::writeLineNumber(const char *,const char *,const char *,int l) +void RTFGenerator::writeLineNumber(const char *ref,const char *fileName,const char *anchor,int l) { + static bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS); + DoxyCodeLineOpen = TRUE; QCString lineNumber; lineNumber.sprintf("%05d",l); - t << lineNumber << " "; + if (m_prettyCode) + { + if (fileName && !m_sourceFileName.isEmpty() && rtfHyperlinks) + { + QCString lineAnchor; + lineAnchor.sprintf("_l%05d",l); + lineAnchor.prepend(stripExtensionGeneral(m_sourceFileName, ".rtf")); + t << "{\\bkmkstart "; + t << rtfFormatBmkStr(lineAnchor); + t << "}"; + t << "{\\bkmkend "; + t << rtfFormatBmkStr(lineAnchor); + t << "}" << endl; + } + t << lineNumber << " "; + } + else + { + t << l << " "; + } m_col=0; } void RTFGenerator::startCodeLine(bool) diff --git a/src/rtfgen.h b/src/rtfgen.h index c6cb76b..9330b13 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -32,6 +32,8 @@ class RTFGenerator : public OutputGenerator static void writeStyleSheetFile(QFile &f); static void writeExtensionsFile(QFile &file); + void setRelativePath(const QCString &path); + void setSourceFileName(const QCString &sourceFileName); void enable() { if (m_genStack->top()) m_active=*m_genStack->top(); else m_active=TRUE; } void disable() { m_active=FALSE; } @@ -171,8 +173,8 @@ class RTFGenerator : public OutputGenerator //void writeDescItem(); void startDescForItem(); void endDescForItem(); - void startSection(const char *,const char *,SectionInfo::SectionType); - void endSection(const char *,SectionInfo::SectionType); + void startSection(const char *,const char *,SectionType); + void endSection(const char *,SectionType); void addIndexItem(const char *,const char *); void startIndent(); void endIndent(); @@ -279,6 +281,7 @@ class RTFGenerator : public OutputGenerator const char *rtf_Code_DepthStyle(); void incrementIndentLevel(); void decrementIndentLevel(); + QCString m_sourceFileName; int m_col; bool m_prettyCode; diff --git a/src/rtfstyle.cpp b/src/rtfstyle.cpp index 47a8166..98581bb 100644 --- a/src/rtfstyle.cpp +++ b/src/rtfstyle.cpp @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -224,27 +224,22 @@ Rtf_Style_Default rtf_Style_Default[] = } }; -const QRegExp StyleData::s_clause("\\\\s[0-9]+\\s*"); +static const QRegExp s_clause("\\\\s[0-9]+\\s*"); StyleData::StyleData(const char* reference, const char* definition) { - int start = s_clause.match(reference); ASSERT(start >= 0); - reference += start; - index = (int)atol(reference + 2); ASSERT(index > 0); + const char *ref = reference; - ASSERT(reference != 0); - size_t size = 1 + strlen(reference); - memcpy(this->reference = new char[size], reference, size); + int start = s_clause.match(ref); ASSERT(start >= 0); + ref += start; + m_index = (int)atol(ref + 2); ASSERT(m_index > 0); - ASSERT(definition != 0); - size = 1 + strlen(definition); - memcpy(this->definition = new char[size], definition, size); + m_reference = ref; + m_definition = definition; } StyleData::~StyleData() { - delete[] reference; - delete[] definition; } bool StyleData::setStyle(const char* s, const char* styleName) @@ -261,7 +256,7 @@ bool StyleData::setStyle(const char* s, const char* styleName) return FALSE; } s += start; - index = (int)atol(s + 2); ASSERT(index > 0); + m_index = (int)atol(s + 2); ASSERT(m_index > 0); // search for the end of pure formatting codes const char* end = s + len; @@ -299,16 +294,10 @@ bool StyleData::setStyle(const char* s, const char* styleName) else // plain name without leading \\snext break; } - delete[] reference; - reference = new char[ref_len + 1]; - memcpy(reference, s, ref_len); - reference[ref_len] = 0; + m_reference = s; if (haveNewDefinition) { - delete[] definition; - size_t size = 1 + strlen(end); - definition = new char[size]; - memcpy(definition, end, size); + m_definition = end; } return TRUE; } diff --git a/src/rtfstyle.h b/src/rtfstyle.h index 1058351..d45972c 100644 --- a/src/rtfstyle.h +++ b/src/rtfstyle.h @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -63,15 +60,18 @@ struct StyleData // to define a tag in the header reference + definition is required // to use a tag in the body of the document only reference is required - unsigned index; // index in style-sheet, i.e. number in s-clause - char* reference; // everything required to apply the style - char* definition; // additional tags like \snext and style name - - StyleData(const char* reference, const char* definition); - ~StyleData(); - bool setStyle(const char* s, const char* styleName); - - static const QRegExp s_clause; + public: + StyleData(const char* reference, const char* definition); + ~StyleData(); + bool setStyle(const char* s, const char* styleName); + const char *reference() const { return m_reference.c_str(); } + const char *definition() const { return m_definition.c_str(); } + uint index() const { return m_index; } + + private: + uint m_index; // index in style-sheet, i.e. number in s-clause + std::string m_reference; // everything required to apply the style + std::string m_definition; // additional tags like \snext and style name }; extern QDict<StyleData> rtf_Style; diff --git a/src/scanner.h b/src/scanner.h index 70df660..cefc934 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -23,7 +23,7 @@ /** \brief C-like language parser using state-based lexical scanning. * * This is the language parser for doxygen. It is somewhat fuzzy and - * supports C++ and various languages that are closely related to C++, + * supports C++ and various languages that are closely related to C++, * such as C, C#, Objective-C, Java, PHP, and IDL. */ class COutlineParser : public OutlineParserInterface @@ -31,13 +31,10 @@ class COutlineParser : public OutlineParserInterface public: COutlineParser(); virtual ~COutlineParser(); - void startTranslationUnit(const char *fileName); - void finishTranslationUnit(); void parseInput(const char *fileName, const char *fileBuf, const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList &filesInSameTranslationUnit); + ClangTUParser *clangParser); bool needsPreprocessing(const QCString &extension) const; void parsePrototype(const char *text); private: diff --git a/src/scanner.l b/src/scanner.l index 7b24d39..7c710fa 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -18,6 +18,9 @@ %option prefix="scannerYY" %option reentrant %option extra-type="struct scannerYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -35,7 +38,6 @@ #include <ctype.h> #include <qarray.h> -#include <qstack.h> #include <qregexp.h> #include <qfile.h> @@ -48,17 +50,20 @@ #include "defargs.h" #include "language.h" #include "commentscan.h" -#include "code.h" #include "arguments.h" #include "clangparser.h" +#include "markdown.h" #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + struct scannerYY_state { OutlineParserInterface *thisParser; + CommentScanner commentScanner; const char * inputString = 0; int inputPosition = 0; int lastContext = 0; @@ -155,7 +160,6 @@ struct scannerYY_state QGString *pCopyHereDocGString = 0; QGString *pCopyRawGString = 0; QGString *pSkipVerbString = 0; - QStack<Grouping> autoGroupStack; bool insideFormula = false; bool insideTryBlock = false; @@ -186,12 +190,16 @@ struct scannerYY_state int column = 0; - int fencedSize = 0; + uint fencedSize = 0; bool nestedComment = false; std::vector< std::pair<Entry*,std::shared_ptr<Entry> > > outerScopeEntries; + + ClangTUParser * clangParser = 0; }; +#if USE_STATE2STRING static const char *stateToString(int state); +#endif //----------------------------------------------------------------------------- // forward declarations for stateless functions @@ -214,7 +222,7 @@ static bool checkForKnRstyleC(yyscan_t yyscanner); static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &oldStyleArgName); static void addKnRArgInfo(yyscan_t yyscanner,const QCString &type,const QCString &name, const QCString &brief,const QCString &docs); -static int yyread(yyscan_t yyscanner,char *buf,int max_size); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); /* ----------------------------------------------------------------- */ @@ -243,7 +251,7 @@ RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" RAWEND ")"[^ \t\(\)\\]{0,16}\" ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++" ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=" -LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!" +LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"|"<=>" BITOP "&"|"|"|"^"|"<<"|">>"|"~" OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) @@ -619,6 +627,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) lineCount(yyscanner) ; yyextra->current->mtype = yyextra->mtype = Event; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->curlyCount=0; BEGIN( CliPropertyType ); } @@ -627,6 +636,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) lineCount(yyscanner) ; yyextra->current->mtype = Event; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; } else { @@ -640,6 +650,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) lineCount(yyscanner) ; yyextra->current->mtype = yyextra->mtype = Property; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->curlyCount=0; BEGIN( CliPropertyType ); } @@ -733,6 +744,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->section = Entry::FUNCTION_SEC; yyextra->current->protection = yyextra->protection = Public ; yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; @@ -756,9 +768,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->type = "id"; } yyextra->current->name = yytext; - if (yyextra->insideCpp || yyextra->insideObjC) + if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { - yyextra->current->id = ClangParser::instance()->lookup(yyextra->yyLineNr,yytext); + yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } } <ObjCMethod>":"{B}* { // start of parameter list @@ -840,7 +852,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } if (yyextra->current->argList.empty()) // method without parameters { - yyextra->current->argList.noParameters = TRUE; + yyextra->current->argList.setNoParameters(TRUE); } yyextra->current->args = argListToString(yyextra->current->argList); //printf("argList=%s\n",yyextra->current->args.data()); @@ -858,7 +870,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } if (yyextra->current->argList.empty()) // method without parameters { - yyextra->current->argList.noParameters = TRUE; + yyextra->current->argList.setNoParameters(TRUE); } yyextra->current->args = argListToString(yyextra->current->argList); unput('{'); @@ -869,6 +881,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { lineCount(yyscanner); yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->fileName = yyextra->yyFileName ; yyextra->current->startLine = yyextra->yyLineNr ; yyextra->current->startColumn = yyextra->yyColNr; @@ -885,6 +898,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { lineCount(yyscanner); yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->fileName = yyextra->yyFileName ; yyextra->current->startLine = yyextra->yyLineNr ; yyextra->current->startColumn = yyextra->yyColNr; @@ -998,6 +1012,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner); } <PackageName>";" { @@ -1025,9 +1040,16 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->explicitExternal = TRUE; lineCount(yyscanner); } -<FindMembers>{B}*"const"{BN}+ { yyextra->current->type += " const "; - if (yyextra->insideCS) yyextra->current->stat = TRUE; - lineCount(yyscanner); +<FindMembers>{B}*"const"{BN}+ { if (yyextra->insideCS) + { + yyextra->current->type += " const "; + if (yyextra->insideCS) yyextra->current->stat = TRUE; + lineCount(yyscanner); + } + else + { + REJECT; + } } <FindMembers>{B}*"virtual"{BN}+ { yyextra->current->type += " virtual "; yyextra->current->virt = Virtual; @@ -1109,6 +1131,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner); if (yyextra->insidePHP) { @@ -1130,6 +1153,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } else if (yyextra->insideD) @@ -1154,6 +1178,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } else @@ -1173,6 +1198,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } else @@ -1195,6 +1221,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->fileName = yyextra->yyFileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } else // TODO is addType right? just copy/pasted @@ -1216,6 +1243,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->fileName = yyextra->yyFileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } else // TODO is addType right? just copy/pasted @@ -1239,6 +1267,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } else @@ -1259,6 +1288,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->fileName = yyextra->yyFileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } <FindMembers>{B}*"@interface"{BN}+ { // Objective-C class interface, or Java attribute @@ -1278,6 +1308,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } <FindMembers>{B}*"@protocol"{BN}+ { // Objective-C protocol definition @@ -1294,6 +1325,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( CompoundName ); } <FindMembers>{B}*"exception"{BN}+ { // Corba IDL/Slice exception @@ -1309,6 +1341,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner); BEGIN( CompoundName ); } @@ -1344,6 +1377,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; if (yytext[0]=='@') { yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; @@ -1364,6 +1398,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1379,6 +1414,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1394,6 +1430,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1409,6 +1446,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; BEGIN( CompoundName ) ; } @@ -1426,7 +1464,6 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; bool isVolatile=decl.find("volatile")!=-1; - uint64 spec = yyextra->current->spec; yyextra->current->section = Entry::CLASS_SEC ; // preserve UNO IDL & Inline attributes, Slice local yyextra->current->spec = Entry::Struct | @@ -1449,6 +1486,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1464,6 +1502,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1479,6 +1518,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1494,6 +1534,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1522,6 +1563,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1550,6 +1592,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner) ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; @@ -1601,17 +1644,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <NSAliasArg>({ID}"::")*{ID} { //printf("Inserting namespace alias %s::%s->%s\n",yyextra->current_root->name.data(),yyextra->aliasName.data(),yytext); - //if (yyextra->current_root->name.isEmpty()) - //{ // TODO: namespace aliases are now treated as global entities // while they should be aware of the scope they are in - Doxygen::namespaceAliasDict.insert(yyextra->aliasName,new QCString(yytext)); - //} - //else - //{ - // Doxygen::namespaceAliasDict.insert(yyextra->current_root->name+"::"+yyextra->aliasName, - // new QCString(yyextra->current_root->name+"::"+yytext)); - //} + Doxygen::namespaceAliasMap.insert({yyextra->aliasName.data(),std::string(yytext)}); } <NSAliasArg>";" { BEGIN( FindMembers ); @@ -1644,9 +1679,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) //printf("PHP: adding use as relation: %s->%s\n",yytext,yyextra->aliasName.data()); if (!yyextra->aliasName.isEmpty()) { - Doxygen::namespaceAliasDict.insert(yytext, - new QCString(removeRedundantWhiteSpace( - substitute(yyextra->aliasName,"\\","::")))); + Doxygen::namespaceAliasMap.insert({yytext, + std::string(removeRedundantWhiteSpace( + substitute(yyextra->aliasName,"\\","::")).data())}); } yyextra->aliasName.resize(0); } @@ -1730,6 +1765,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->previous->args.resize(0); yyextra->previous->name=yyextra->previous->name.stripWhiteSpace(); yyextra->previous->bodyLine = yyextra->yyLineNr; + yyextra->previous->bodyColumn = yyextra->yyColNr; yyextra->previous->spec |= Entry::Alias; BEGIN(FindMembers); } @@ -1864,6 +1900,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) { yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->args = "("; yyextra->currentArgumentContext = FuncQual; yyextra->fullArgString = yyextra->current->args.copy(); @@ -1903,6 +1940,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yyextra->insidePHP) { yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( DefinePHP ); } else @@ -1964,33 +2002,37 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) unput(';'); BEGIN(FindMembers); } -<QtPropType>"const"|"volatile"|"unsigned"|"signed"|"long"|"short" { - yyextra->current->type+=yytext; - } <QtPropType>{B}+ { - yyextra->current->type+=yytext; + yyextra->current->name+=yytext; } -<QtPropType>({TSCOPE}"::")*{TSCOPE} { - yyextra->current->type+=yytext; - BEGIN(QtPropName); +<QtPropType>"*" { + yyextra->current->type+= yyextra->current->name; + yyextra->current->type+= yytext; + yyextra->current->name=""; } -<QtPropName>{ID} { +<QtPropType>({TSCOPE}"::")*{TSCOPE} { + yyextra->current->type+= yyextra->current->name; yyextra->current->name=yytext; - BEGIN(QtPropAttr); } -<QtPropAttr>"READ" { +<QtPropType,QtPropAttr>{B}+"READ"{B}+ { yyextra->current->spec |= Entry::Readable; BEGIN(QtPropRead); } -<QtPropAttr>"WRITE" { +<QtPropType,QtPropAttr>{B}+"WRITE"{B}+ { yyextra->current->spec |= Entry::Writable; BEGIN(QtPropWrite); } -<QtPropAttr>"RESET"{B}+{ID} { // reset method => not supported yet - } -<QtPropAttr>"SCRIPTABLE"{B}+{ID} { // scriptable property => not supported yet - } -<QtPropAttr>"DESIGNABLE"{B}+{ID} { // designable property => not supported yet +<QtPropType,QtPropAttr>{B}+"MEMBER"{B}+{ID} | // member property => not supported yet +<QtPropType,QtPropAttr>{B}+"RESET"{B}+{ID} | // reset method => not supported yet +<QtPropType,QtPropAttr>{B}+"SCRIPTABLE"{B}+{ID} | // scriptable property => not supported yet +<QtPropType,QtPropAttr>{B}+"DESIGNABLE"{B}+{ID} | // designable property => not supported yet +<QtPropType,QtPropAttr>{B}+"NOTIFY"{B}+{ID} | // notify property => not supported yet +<QtPropType,QtPropAttr>{B}+"REVISION"{B}+{ID} | // revision property => not supported yet +<QtPropType,QtPropAttr>{B}+"STORED"{B}+{ID} | // stored property => not supported yet +<QtPropType,QtPropAttr>{B}+"USER"{B}+{ID} | // user property => not supported yet +<QtPropType,QtPropAttr>{B}+"CONSTANT"{B} | // constant property => not supported yet +<QtPropType,QtPropAttr>{B}+"FINAL"{B} { // final property => not supported yet + BEGIN(QtPropAttr); } <QtPropRead>{ID} { yyextra->current->read = yytext; @@ -2005,9 +2047,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(FindMembers); } <FindMembers,FindMemberName>{SCOPENAME} { - if (yyextra->insideCpp || yyextra->insideObjC) + if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { - yyextra->current->id = ClangParser::instance()->lookup(yyextra->yyLineNr,yytext); + yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } yyextra->yyBegColNr=yyextra->yyColNr; yyextra->yyBegLineNr=yyextra->yyLineNr; @@ -2237,6 +2279,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yyextra->insidePHP) REJECT; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->lastDefineContext = YY_START; BEGIN( Define ); } @@ -2289,6 +2332,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); yyextra->current->args = "("; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->currentArgumentContext = DefineEnd; yyextra->fullArgString=yyextra->current->args.copy(); yyextra->copyArgString=&yyextra->current->args; @@ -2306,17 +2350,17 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) */ <Define>{ID} { //printf("Define '%s' without args\n",yytext); - if (yyextra->insideCpp || yyextra->insideObjC) + if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { - yyextra->current->id = ClangParser::instance()->lookup(yyextra->yyLineNr,yytext); + yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->name = yytext; BEGIN(DefineEnd); } <DefineEnd>\n { //printf("End define: doc=%s docFile=%s docLine=%d\n",yyextra->current->doc.data(),yyextra->current->docFile.data(),yyextra->current->docLine); - lineCount(yyscanner); yyextra->current->fileName = yyextra->yyFileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; @@ -2325,6 +2369,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->name = yyextra->current->name.stripWhiteSpace(); yyextra->current->section = Entry::DEFINE_SEC; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + lineCount(yyscanner); initEntry(yyscanner); BEGIN(yyextra->lastDefineContext); } @@ -2367,6 +2412,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1); yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->lastRoundContext = DefinePHPEnd; yyextra->pCopyRoundGString = &yyextra->current->initializer; yyextra->roundCount = 0; @@ -2392,6 +2438,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yyextra->current->bodyLine==-1) { yyextra->current->bodyLine=yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; } yyextra->docBlockContext = YY_START; yyextra->docBlockInBody = FALSE; @@ -2455,6 +2502,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yyextra->current->bodyLine==-1) { yyextra->current->bodyLine=yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; } yyextra->docBlockContext = YY_START; yyextra->docBlockInBody = FALSE; @@ -2483,12 +2531,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yyextra->previous && yyextra->previous->section==Entry::GROUPDOC_SEC) { // link open command to the group defined in the yyextra->previous entry - Doxygen::docGroup.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr); } else { // link open command to the yyextra->current entry - Doxygen::docGroup.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr); } //yyextra->current = tmp; initEntry(yyscanner); @@ -2532,11 +2580,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <FindMembers,FindFields,ReadInitializer>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" { bool insideEnum = YY_START==FindFields || (YY_START==ReadInitializer && yyextra->lastInitializerContext==FindFields); // see bug746226 - Doxygen::docGroup.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum); + yyextra->commentScanner.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum); lineCount(yyscanner); } <FindMembers>"=" { // in PHP code this could also be due to "<?=" yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->initializer = yytext; yyextra->lastInitializerContext = YY_START; yyextra->initBracketCount=0; @@ -2855,7 +2904,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopyRoundString+=yytext; } } -<CopyRound>[^"'()\n]+ { +<CopyRound>[^"'()\n,]+ { *yyextra->pCopyRoundString+=yytext; } <CopyRound>. { @@ -2905,7 +2954,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopyRoundGString+=yytext; } } -<GCopyRound>[^"'()\n/]+ { +<GCopyRound>[^"'()\n\/,]+ { *yyextra->pCopyRoundGString+=yytext; } <GCopyRound>. { @@ -2955,7 +3004,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopySquareGString+=yytext; } } -<GCopySquare>[^"\[\]\n/]+ { +<GCopySquare>[^"\[\]\n\/,]+ { *yyextra->pCopySquareGString+=yytext; } <GCopySquare>. { @@ -2996,7 +3045,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopyCurlyString+=yytext; } } -<CopyCurly>[^"'{}\/\n]+ { +<CopyCurly>[^"'{}\/\n,]+ { *yyextra->pCopyCurlyString+=yytext; } <CopyCurly>"/" { *yyextra->pCopyCurlyString+=yytext; } @@ -3108,6 +3157,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yyextra->current->bodyLine==-1) { yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; } if ( yyextra->insidePHP && yyextra->current->type.left(3) == "var" ) { @@ -3415,11 +3465,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <Sharp>. { yyextra->current->type += *yytext ; } <FindFields>{ID} { - if (yyextra->insideCpp || yyextra->insideObjC) + if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { - yyextra->current->id = ClangParser::instance()->lookup(yyextra->yyLineNr,yytext); + yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->name = yytext; } <FindFields>"(" { @@ -3614,10 +3665,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->name = yyextra->current->name.left(split_point); if (!yyextra->current_root->name.isEmpty()) yyextra->current->name.prepend(yyextra->current_root->name+"::"); - std::shared_ptr<Entry> tmp = yyextra->current; yyextra->current_root->moveToSubEntryAndKeep(yyextra->current); - yyextra->current_root = tmp; - + yyextra->current_root = yyextra->current; yyextra->current = new_current; } // restore documentation values @@ -3661,7 +3710,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else { yyextra->memspecEntry = yyextra->current; - yyextra->current_root->copyToSubEntry( yyextra->current ) ; + yyextra->current_root->moveToSubEntryAndKeep( yyextra->current ) ; + yyextra->current = std::make_shared<Entry>(*yyextra->current); if (yyextra->current->section==Entry::NAMESPACE_SEC || (yyextra->current->spec==Entry::Interface) || yyextra->insideJava || yyextra->insidePHP || yyextra->insideCS || yyextra->insideD || yyextra->insideJS || @@ -3946,6 +3996,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else { yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; lineCount(yyscanner); addType(yyscanner); yyextra->funcPtrType=yytext; @@ -4013,6 +4064,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) //yyextra->roundCount=0; //BEGIN( FuncFunc ); yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->currentArgumentContext = FuncFuncEnd; yyextra->fullArgString=yyextra->current->args.copy(); yyextra->copyArgString=&yyextra->current->args; @@ -4077,12 +4129,14 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) // the bodyLine check is to prevent this guard to be true more than once { yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; BEGIN( GetCallType ); } else if (!yyextra->current->name.isEmpty()) // normal function { yyextra->current->args = yytext; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->currentArgumentContext = FuncQual; yyextra->fullArgString=yyextra->current->args.copy(); yyextra->copyArgString=&yyextra->current->args; @@ -4103,6 +4157,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->current->args = yytext; yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->currentArgumentContext = FuncQual; yyextra->fullArgString=yyextra->current->args.copy(); yyextra->copyArgString=&yyextra->current->args; @@ -4160,7 +4215,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <ReadFuncArgType>")" { *yyextra->copyArgString+=*yytext; yyextra->fullArgString+=*yytext; - stringToArgumentList(yyextra->language, yyextra->fullArgString,yyextra->current->argList); + yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); if (yyextra->insideJS) { fixArgumentListForJavaScript(yyextra->current->argList); @@ -4187,7 +4242,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { unput(yytext[i]); } - stringToArgumentList(yyextra->language, yyextra->fullArgString,yyextra->current->argList); + yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); handleParametersCommentBlocks(yyscanner,yyextra->current->argList); BEGIN( yyextra->currentArgumentContext ); } @@ -4240,7 +4295,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } *yyextra->copyArgString+=*yytext; yyextra->fullArgString+=*yytext; - stringToArgumentList(yyextra->language, yyextra->fullArgString,yyextra->current->argList); + yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); handleParametersCommentBlocks(yyscanner,yyextra->current->argList); BEGIN( yyextra->currentArgumentContext ); } @@ -4272,7 +4327,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) unput(yyextra->lastCopyArgChar); BEGIN( yyextra->lastCommentInArgContext ); } -<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) +<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) yyextra->docBlockName=&yytext[1]; yyextra->fullArgString+=yytext; BEGIN(CopyArgVerbatim); @@ -4290,7 +4345,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->fullArgString+=yytext; BEGIN(CopyArgVerbatim); } -<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9\-] { // end of verbatim block +<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9\-] { // end of verbatim block yyextra->fullArgString+=yytext; if (yytext[1]=='f') // end of formula { @@ -4321,7 +4376,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->copyArgString+=*yytext; yyextra->fullArgString+=*yytext; //printf("end template list '%s'\n",yyextra->copyArgString->data()); - stringToArgumentList(yyextra->language, yyextra->fullArgString,*yyextra->currentArgumentList); + *yyextra->currentArgumentList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); BEGIN( yyextra->currentArgumentContext ); } <CopyArgRound>"(" { @@ -4473,12 +4528,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <FuncQual>{BN}*"const"{BN}* { // const member function lineCount(yyscanner) ; yyextra->current->args += " const "; - yyextra->current->argList.constSpecifier=TRUE; + yyextra->current->argList.setConstSpecifier(TRUE); } <FuncQual>{BN}*"volatile"{BN}* { // volatile member function lineCount(yyscanner) ; yyextra->current->args += " volatile "; - yyextra->current->argList.volatileSpecifier=TRUE; + yyextra->current->argList.setVolatileSpecifier(TRUE); } <FuncQual>{BN}*"noexcept"{BN}* { // noexcept qualifier lineCount(yyscanner) ; @@ -4496,25 +4551,25 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <FuncQual>{BN}*"&" { yyextra->current->args += " &"; - yyextra->current->argList.refQualifier=RefQualifierLValue; + yyextra->current->argList.setRefQualifier(RefQualifierLValue); } <FuncQual>{BN}*"&&" { yyextra->current->args += " &&"; - yyextra->current->argList.refQualifier=RefQualifierRValue; + yyextra->current->argList.setRefQualifier(RefQualifierRValue); } <FuncQual,TrailingReturn>{BN}*"="{BN}*"0"{BN}* { // pure virtual member function lineCount(yyscanner) ; yyextra->current->args += " = 0"; yyextra->current->virt = Pure; - yyextra->current->argList.pureSpecifier=TRUE; + yyextra->current->argList.setPureSpecifier(TRUE); BEGIN(FuncQual); } <FuncQual,TrailingReturn>{BN}*"="{BN}*"delete"{BN}* { // C++11 explicitly delete member lineCount(yyscanner); yyextra->current->args += " = delete"; yyextra->current->spec |= Entry::Delete; - yyextra->current->argList.isDeleted=TRUE; + yyextra->current->argList.setIsDeleted(TRUE); BEGIN(FuncQual); } <FuncQual,TrailingReturn>{BN}*"="{BN}*"default"{BN}* { // C++11 explicitly defaulted constructor/assignment operator @@ -4525,7 +4580,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <FuncQual>{BN}*"->"{BN}* { lineCount(yyscanner); - yyextra->current->argList.trailingReturnType = " -> "; + yyextra->current->argList.setTrailingReturnType(" -> "); yyextra->current->args += " -> "; BEGIN(TrailingReturn); } @@ -4534,12 +4589,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(FuncQual); } <TrailingReturn>. { - yyextra->current->argList.trailingReturnType+=yytext; + yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); yyextra->current->args+=yytext; } <TrailingReturn>\n { lineCount(yyscanner); - yyextra->current->argList.trailingReturnType+=yytext; + yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); yyextra->current->args+=' '; } <FuncRound,FuncFunc>{BN}*","{BN}* { @@ -4665,7 +4720,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <OldStyleArgs>"{" { if (yyextra->current->argList.empty()) { - yyextra->current->argList.noParameters=TRUE; + yyextra->current->argList.setNoParameters(TRUE); } yyextra->current->args = argListToString(yyextra->current->argList); unput('{'); @@ -4743,23 +4798,25 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->startLine = yyextra->yyBegLineNr; yyextra->current->startColumn = yyextra->yyBegColNr; static QRegExp re("([^)]*[*&][^)]*)"); // (...*...) + int ts=yyextra->current->type.find('<'); + int te=yyextra->current->type.findRev('>'); + int ti=yyextra->current->type.find(re,0); + + // bug677315: A<int(void *, char *)> get(); is not a function pointer + bool isFunction = ti==-1 || // not a (...*...) pattern + (ts!=-1 && ts<te && ts<ti && ti<te); // (...*...) is part of a template argument list + bool isVariable = (!yyextra->current->type.isEmpty() && + (!isFunction || yyextra->current->type.left(8)=="typedef ")); + + //printf("type=%s ts=%d te=%d ti=%d isFunction=%d\n", + // yyextra->current->type.data(),ts,te,ti,isFunction); + if (*yytext!=';' || (yyextra->current_root->section&Entry::COMPOUND_MASK) ) { int tempArg=yyextra->current->name.find('<'); - int ts=yyextra->current->type.find('<'); - int te=yyextra->current->type.findRev('>'); - int ti=yyextra->current->type.find(re,0); - - // bug677315: A<int(void *, char *)> get(); is not a function pointer - bool isFunction = ti==-1 || // not a (...*...) pattern - (ts!=-1 && ts<te && ts<ti && ti<te); // (...*...) is part of a template argument list - - //printf("type=%s ts=%d te=%d ti=%d isFunction=%d\n", - // yyextra->current->type.data(),ts,te,ti,isFunction); QCString tempName; if (tempArg==-1) tempName=yyextra->current->name; else tempName=yyextra->current->name.left(tempArg); - if (!yyextra->current->type.isEmpty() && - (!isFunction || yyextra->current->type.left(8)=="typedef ")) + if (isVariable) { //printf("Scanner.l: found in class variable: '%s' '%s' '%s'\n", yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") @@ -4768,7 +4825,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } yyextra->current->section = Entry::VARIABLE_SEC ; } - else + else { //printf("Scanner.l: found in class function: '%s' '%s' '%s'\n", yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); yyextra->current->section = Entry::FUNCTION_SEC ; @@ -4778,8 +4835,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else // a global function prototype or function variable { //printf("Scanner.l: prototype? type='%s' name='%s' args='%s'\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); - if (!yyextra->current->type.isEmpty() && - (yyextra->current->type.find(re,0)!=-1 || yyextra->current->type.left(8)=="typedef ")) + if (isVariable) { if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") { @@ -4912,7 +4968,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { lineCount(yyscanner); - if ( yyextra->curlyCount ) + if ( yyextra->curlyCount ) { //addToBody(yytext); --yyextra->curlyCount ; @@ -4920,10 +4976,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else { yyextra->current->endBodyLine=yyextra->yyLineNr; - // take yyextra->previous out of yyextra->current_root and move it into yyextra->current - yyextra->tempEntry = yyextra->current; // remember yyextra->current - yyextra->current_root->moveFromSubEntry(yyextra->previous.get(),yyextra->current); - yyextra->previous.reset(); + yyextra->tempEntry = yyextra->current; // temporarily switch to the previous entry + yyextra->current = yyextra->previous; yyextra->docBlockContext = SkipCurlyEndDoc; yyextra->docBlockInBody = FALSE; @@ -5282,9 +5336,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <CompoundName>{SCOPENAME} { yyextra->current->name = yytext ; - if (yyextra->insideCpp || yyextra->insideObjC) + if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { - yyextra->current->id = ClangParser::instance()->lookup(yyextra->yyLineNr,yytext); + yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } lineCount(yyscanner); if (yyextra->current->spec & Entry::Protocol) @@ -5347,9 +5401,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } <ClassVar>{ID} { - if (yyextra->insideCpp || yyextra->insideObjC) + if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { - yyextra->current->id = ClangParser::instance()->lookup(yyextra->yyLineNr,yytext); + yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } if (yyextra->insideIDL && qstrcmp(yytext,"switch")==0) { @@ -5575,9 +5629,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } <CompoundName,ClassVar>{B}*"{"{B}* { + yyextra->current->program.resize(0); yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); if (yyextra->current->name.isEmpty() && !yyextra->isTypedef) // anonymous compound { @@ -5826,9 +5881,11 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(BasesProt); } } -<Bases>{B}*"{"{B}* { yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; +<Bases>{B}*"{"{B}* { + yyextra->current->program.resize(0); + yyextra->current->fileName = yyextra->yyFileName ; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); if (!yyextra->baseName.isEmpty()) yyextra->current->extends.push_back( @@ -6027,6 +6084,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->mtype = yyextra->mtype = Property; } yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->curlyCount=0; BEGIN( CSAccessorDecl ); } @@ -6070,6 +6128,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) // C++11 style initializer list yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->initializer = yytext; yyextra->lastInitializerContext = YY_START; yyextra->initBracketCount=1; @@ -6252,7 +6311,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->nestedComment=FALSE; BEGIN(DocCopyBlock); } -<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) yyextra->docBlock+=yytext; yyextra->docBlockName=&yytext[1]; yyextra->fencedSize=0; @@ -6320,7 +6379,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->docBlock+=yytext; BEGIN(DocBlock); } -<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block +<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block yyextra->docBlock+=yytext; if (&yytext[4]==yyextra->docBlockName) { @@ -6472,16 +6531,16 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <PrototypeQual>{B}*"const"{B}* { yyextra->current->args += " const "; - yyextra->current->argList.constSpecifier=TRUE; + yyextra->current->argList.setConstSpecifier(TRUE); } <PrototypeQual>{B}*"volatile"{B}* { yyextra->current->args += " volatile "; - yyextra->current->argList.volatileSpecifier=TRUE; + yyextra->current->argList.setVolatileSpecifier(TRUE); } <PrototypeQual>{B}*"="{B}*"0"{B}* { yyextra->current->args += " = 0"; yyextra->current->virt = Pure; - yyextra->current->argList.pureSpecifier=TRUE; + yyextra->current->argList.setPureSpecifier(TRUE); } <PrototypeQual>"throw"{B}*"(" { yyextra->current->exception = "throw("; @@ -6586,10 +6645,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) %% //---------------------------------------------------------------------------- -static int yyread(yyscan_t yyscanner,char *buf,int max_size) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - int c=0; + yy_size_t c=0; while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) { *buf = yyextra->inputString[yyextra->inputPosition++] ; @@ -6615,9 +6674,7 @@ static void initParser(yyscan_t yyscanner) yyextra->virt = Normal; yyextra->baseVirt = Normal; yyextra->isTypedef = FALSE; - yyextra->autoGroupStack.clear(); yyextra->insideTryBlock = FALSE; - yyextra->autoGroupStack.setAutoDelete(TRUE); yyextra->insideFormula = FALSE; yyextra->insideCode=FALSE; yyextra->insideCli=Config_getBool(CPP_CLI_SUPPORT); @@ -6639,7 +6696,7 @@ static void initEntry(yyscan_t yyscanner) yyextra->current->stat = yyextra->stat; yyextra->current->lang = yyextra->language; //printf("*** initEntry(yyscanner) yyextra->language=%d\n",yyextra->language); - Doxygen::docGroup.initGroupInfo(yyextra->current.get()); + yyextra->commentScanner.initGroupInfo(yyextra->current.get()); yyextra->isTypedef=FALSE; } @@ -6822,7 +6879,6 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol else // normal "int *var" { int l=si,i=l-1,j; - char c; // look for start of name in "type *name" while (i>=0 && isId(yyextra->current->args.at(i))) i--; j=i+1; @@ -6965,8 +7021,10 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief int position=0; bool needsEntry=FALSE; - QCString processedDoc = preprocessCommentBlock(stripIndentation(doc),yyextra->yyFileName,lineNr); - while (parseCommentBlock( + Markdown markdown(yyextra->yyFileName,lineNr); + QCString strippedDoc = stripIndentation(doc); + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc; + while (yyextra->commentScanner.parseCommentBlock( yyextra->thisParser, yyextra->docBlockInBody && yyextra->previous ? yyextra->previous.get() : yyextra->current.get(), processedDoc, // text @@ -6977,7 +7035,8 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief yyextra->docBlockInBody, // isInBody yyextra->protection, position, - needsEntry + needsEntry, + Config_getBool(MARKDOWN_SUPPORT) ) ) { @@ -7025,7 +7084,7 @@ static void handleParametersCommentBlocks(yyscan_t yyscanner,ArgumentList &al) yyextra->current->brief.resize(0); //printf("handleParametersCommentBlock [%s]\n",doc.data()); - while (parseCommentBlock( + while (yyextra->commentScanner.parseCommentBlock( yyextra->thisParser, yyextra->current.get(), a.docs, // text @@ -7036,9 +7095,10 @@ static void handleParametersCommentBlocks(yyscan_t yyscanner,ArgumentList &al) FALSE, yyextra->protection, position, - needsEntry + needsEntry, + Config_getBool(MARKDOWN_SUPPORT) ) - ) + ) { //printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position); if (needsEntry) newEntry(yyscanner); @@ -7084,8 +7144,8 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) yyextra->current_root = ce; yyextra->yyFileName = ce->fileName; //setContext(); - yyextra->yyLineNr = ce->startLine ; - yyextra->yyColNr = ce->startColumn ; + yyextra->yyLineNr = ce->bodyLine; + yyextra->yyColNr = ce->bodyColumn; yyextra->insideObjC = ce->lang==SrcLangExt_ObjC; //printf("---> Inner block starts at line %d objC=%d\n",yyextra->yyLineNr,yyextra->insideObjC); yyextra->current = std::make_shared<Entry>(); @@ -7151,13 +7211,13 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) //memberGroupRelates.resize(0); //memberGroupInside.resize(0); QCString name = ce->name; - Doxygen::docGroup.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name); + yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name); scannerYYlex(yyscanner); yyextra->lexInit=TRUE; //forceEndGroup(); - Doxygen::docGroup.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name); + yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name); ce->program.resize(0); @@ -7177,8 +7237,7 @@ static void parseMain(yyscan_t yyscanner, const char *fileName, const char *fileBuf, const std::shared_ptr<Entry> &rt, - bool sameTranslationUnit, - QStrList & filesInSameTranslationUnit) + ClangTUParser *clangParser) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; initParser(yyscanner); @@ -7199,25 +7258,14 @@ static void parseMain(yyscan_t yyscanner, yyextra->yyBegLineNr = 1; yyextra->yyBegColNr = 0; yyextra->yyFileName = fileName; + yyextra->clangParser = clangParser; setContext(yyscanner); - bool processWithClang = yyextra->insideCpp || yyextra->insideObjC; - if (processWithClang) - { - if (!sameTranslationUnit) // new file - { - ClangParser::instance()->start(fileName,filesInSameTranslationUnit); - } - else - { - ClangParser::instance()->switchToFile(fileName); - } - } rt->lang = yyextra->language; msg("Parsing file %s...\n",yyextra->yyFileName.data()); yyextra->current_root = rt; initParser(yyscanner); - Doxygen::docGroup.enterFile(yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.enterFile(yyextra->yyFileName,yyextra->yyLineNr); yyextra->current = std::make_shared<Entry>(); //printf("yyextra->current=%p yyextra->current_root=%p\n",yyextra->current,yyextra->current_root); int sec=guessSection(yyextra->yyFileName); @@ -7247,7 +7295,7 @@ static void parseMain(yyscan_t yyscanner, } //forceEndGroup(); - Doxygen::docGroup.leaveFile(yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.leaveFile(yyextra->yyFileName,yyextra->yyLineNr); rt->program.resize(0); @@ -7348,33 +7396,17 @@ COutlineParser::~COutlineParser() scannerYYlex_destroy(p->yyscanner); } -void COutlineParser::startTranslationUnit(const char *) -{ -} - -void COutlineParser::finishTranslationUnit() -{ - struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; - bool processWithClang = yyextra->insideCpp || yyextra->insideObjC; - if (processWithClang) - { - ClangParser::instance()->finish(); - } -} - void COutlineParser::parseInput(const char *fileName, const char *fileBuf, const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList & filesInSameTranslationUnit) + ClangTUParser *clangParser) { struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; yyextra->thisParser = this; printlex(yy_flex_debug, TRUE, __FILE__, fileName); - ::parseMain(p->yyscanner, fileName,fileBuf,root, - sameTranslationUnit,filesInSameTranslationUnit); + ::parseMain(p->yyscanner,fileName,fileBuf,root,clangParser); printlex(yy_flex_debug, FALSE, __FILE__, fileName); } @@ -7397,4 +7429,6 @@ void COutlineParser::parsePrototype(const char *text) //---------------------------------------------------------------------------- +#if USE_STATE2STRING #include "scanner.l.h" +#endif diff --git a/src/searchindex.cpp b/src/searchindex.cpp index eee1aa1..ec7f7d6 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -394,8 +394,6 @@ void SearchIndex::write(const char *fileName) } } // write urls - QIntDictIterator<URL> udi(m_urls); - URL *url; for (udi.toFirst();(url=udi.current());++udi) { writeString(f,url->name); @@ -833,53 +831,41 @@ void createJavaScriptSearchIndex() } // index files - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { uint letter = getUtf8CodeToLower(fd->name(),0); if (fd->isLinkable() && isId(letter)) { - g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,fd); - g_searchIndexInfo[SEARCH_INDEX_FILES].symbolList.append(letter,fd); + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,fd.get()); + g_searchIndexInfo[SEARCH_INDEX_FILES].symbolList.append(letter,fd.get()); } } } // index class members { - MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); - MemberName *mn; // for each member name - for (mnli.toFirst();(mn=mnli.current());++mnli) + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); // for each member definition - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { - addMemberToSearchIndex(md); + addMemberToSearchIndex(md.get()); } } } // index file/namespace members { - MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); - MemberName *mn; // for each member name - for (fnli.toFirst();(mn=fnli.current());++fnli) + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *md; - MemberNameIterator mni(*mn); // for each member definition - for (mni.toFirst();(md=mni.current());++mni) + for (const auto &md : *mn) { - addMemberToSearchIndex(md); + addMemberToSearchIndex(md.get()); } } } @@ -984,7 +970,7 @@ void writeJavaScriptSearchIndex() " \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl; t << "<html><head><title></title>" << endl; t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl; - t << "<meta name=\"generator\" content=\"Doxygen " << getVersion() << "\"/>" << endl; + t << "<meta name=\"generator\" content=\"Doxygen " << getDoxygenVersion() << "\"/>" << endl; t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl; t << "<script type=\"text/javascript\" src=\"" << baseName << ".js\"></script>" << endl; t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl; @@ -1009,6 +995,12 @@ void writeJavaScriptSearchIndex() t << "document.getElementById(\"NoMatches\").style.display=\"none\";" << endl; t << "var searchResults = new SearchResults(\"searchResults\");" << endl; t << "searchResults.Search();" << endl; + t << "window.addEventListener(\"message\", function(event) {" << endl; + t << " if (event.data == \"take_focus\") {" << endl; + t << " var elem = searchResults.NavNext(0);" << endl; + t << " if (elem) elem.focus();" << endl; + t << " }" << endl; + t << "});" << endl; t << "/* @license-end */\n"; t << "--></script>" << endl; t << "</div>" << endl; // SRIndex @@ -1036,7 +1028,7 @@ void writeJavaScriptSearchIndex() int itemCount=0; for (li.toFirst();(dl=li.current());++li) { - Definition *d = dl->getFirst(); + const Definition *d = dl->getFirst(); if (!firstEntry) { @@ -1048,11 +1040,11 @@ void writeJavaScriptSearchIndex() if (dl->count()==1) // item with a unique name { - MemberDef *md = dynamic_cast<MemberDef*>(d); + const MemberDef *md = dynamic_cast<const MemberDef*>(d); QCString anchor = d->anchor(); ti << "'" << externalRef("../",d->getReference(),TRUE) - << d->getOutputFileBase() << Doxygen::htmlFileExtension; + << addHtmlExtensionIfMissing(d->getOutputFileBase()); if (!anchor.isEmpty()) { ti << "#" << anchor; @@ -1092,15 +1084,15 @@ void writeJavaScriptSearchIndex() { QListIterator<Definition> di(*dl); bool overloadedFunction = FALSE; - Definition *prevScope = 0; + const Definition *prevScope = 0; int childCount=0; for (di.toFirst();(d=di.current());) { ++di; - Definition *scope = d->getOuterScope(); - Definition *next = di.current(); - Definition *nextScope = 0; - MemberDef *md = dynamic_cast<MemberDef*>(d); + const Definition *scope = d->getOuterScope(); + const Definition *next = di.current(); + const Definition *nextScope = 0; + const MemberDef *md = dynamic_cast<const MemberDef*>(d); if (next) nextScope = next->getOuterScope(); QCString anchor = d->anchor(); @@ -1109,7 +1101,7 @@ void writeJavaScriptSearchIndex() ti << "],["; } ti << "'" << externalRef("../",d->getReference(),TRUE) - << d->getOutputFileBase() << Doxygen::htmlFileExtension; + << addHtmlExtensionIfMissing(d->getOutputFileBase()); if (!anchor.isEmpty()) { ti << "#" << anchor; @@ -1144,12 +1136,12 @@ void writeJavaScriptSearchIndex() QCString name; if (d->definitionType()==Definition::TypeClass) { - name = convertToXML((dynamic_cast<ClassDef*>(d))->displayName()); + name = convertToXML((dynamic_cast<const ClassDef*>(d))->displayName()); found = TRUE; } else if (d->definitionType()==Definition::TypeNamespace) { - name = convertToXML((dynamic_cast<NamespaceDef*>(d))->displayName()); + name = convertToXML((dynamic_cast<const NamespaceDef*>(d))->displayName()); found = TRUE; } else if (scope==0 || scope==Doxygen::globalScope) // in global scope diff --git a/src/section.h b/src/section.h index 9e6c695..74eb04b 100644 --- a/src/section.h +++ b/src/section.h @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,42 +16,144 @@ #ifndef SECTION_H #define SECTION_H -#include "sortdict.h" +#include <string> +#include <unordered_map> + +#include <qcstring.h> + +#include "linkedmap.h" class Definition; -/** Class representing a section in a page */ -struct SectionInfo +//! enum representing the various types of sections and entities that can be referred to. +enum class SectionType { - enum SectionType { Page = 0, - Section = 1, - Subsection = 2, - Subsubsection = 3, - Paragraph = 4, - Anchor = 5, - Table = 6 - }; - SectionInfo(const char *f,const int lin,const char *l,const char *t, - SectionType st,int lev,const char *r=0) : - label(l), title(t), type(st), ref(r), definition(0), - fileName(f), lineNr(lin), generated(FALSE), level(lev) {} - QCString label; - QCString title; - SectionType type; - QCString ref; - Definition *definition; - QCString fileName; - int lineNr; - bool generated; - int level; + Page = 0, + Section = 1, + Subsection = 2, + Subsubsection = 3, + Paragraph = 4, + Anchor = 5, + Table = 6 }; -/** Unsorted dictionary of SectionInfo objects. */ -class SectionDict : public SDict<SectionInfo> +//! return true if type is a section, and false if it is a page, anchor or table. +inline constexpr bool isSection(SectionType type) +{ + return (type==SectionType::Section || + type==SectionType::Subsection || + type==SectionType::Subsubsection || + type==SectionType::Paragraph); +} + +//! class that provide information about a section. +class SectionInfo { public: - SectionDict(int size) : SDict<SectionInfo>(size) {} - ~SectionDict() {} + SectionInfo(const char *label, const char *fileName, int lineNr, + const char *title, SectionType type, int level,const char *ref) : + m_label(label), m_title(title), m_type(type), m_ref(ref), + m_lineNr(lineNr), m_fileName(fileName), m_level(level) + { + //printf("SectionInfo(%p)\n",this); + } + ~SectionInfo() + { + //printf("~SectionInfo(%p)\n",this); + } + + // getters + QCString label() const { return m_label; } + QCString title() const { return m_title; } + SectionType type() const { return m_type; } + QCString ref() const { return m_ref; } + int lineNr() const { return m_lineNr; } + QCString fileName() const { return m_fileName; } + bool generated() const { return m_generated; } + int level() const { return m_level; } + Definition *definition() const { return m_definition; } + + // setters + void setFileName(const char *fn) { m_fileName = fn; } + void setType(SectionType t) { m_type = t; } + void setGenerated(bool b) { m_generated = b; } + void setDefinition(Definition *d) { m_definition = d; } + + private: + QCString m_label; + QCString m_title; + SectionType m_type; + QCString m_ref; + int m_lineNr; + QCString m_fileName; + bool m_generated = false; + int m_level; + Definition *m_definition = 0; }; +//! class that represents a list of constant references to sections. +class SectionRefs +{ + using SectionInfoVec = std::vector<const SectionInfo*>; + public: + using const_iterator = SectionInfoVec::const_iterator; + + //! Returns a constant pointer to the section info given a section label or nullptr + //! if no section with the given label can be found. + const SectionInfo *find(const char *label) const + { + auto it = m_lookup.find(label); + return it!=m_lookup.end() ? it->second : nullptr; + } + + //! Adds a non-owning section reference. + void add(const SectionInfo *si) + { + m_lookup.insert({toStdString(si->label()),si}); + m_entries.push_back(si); + } + + const_iterator begin() const { return m_entries.cbegin(); } + const_iterator end() const { return m_entries.cend(); } + bool empty() const { return m_entries.empty(); } + size_t size() const { return m_entries.size(); } + + private: + SectionInfoVec m_entries; + std::unordered_map< std::string, const SectionInfo* > m_lookup; +}; + +//! singleton class that owns the list of all sections +class SectionManager : public LinkedMap<SectionInfo> +{ + public: + //! Add a new section given the data of an existing section. + //! Returns a non-owning pointer to the newly added section. + SectionInfo *add(const SectionInfo &si) + { + return LinkedMap<SectionInfo>::add(si.label(),si.fileName(),si.lineNr(),si.title(),si.type(),si.level(),si.ref()); + } + + //! Add a new section + //! Return a non-owning pointer to the newly added section + SectionInfo *add(const char *label, const char *fileName, int lineNr, + const char *title, SectionType type, int level,const char *ref=0) + { + return LinkedMap<SectionInfo>::add(label,fileName,lineNr,title,type,level,ref); + } + + //! returns a reference to the singleton + static SectionManager &instance() + { + static SectionManager sm; + return sm; + } + + private: + SectionManager() {} + SectionManager(const SectionManager &other) = delete; + SectionManager &operator=(const SectionManager &other) = delete; +}; + + #endif diff --git a/src/sortdict.h b/src/sortdict.h index 203ae5e..15282ec 100644 --- a/src/sortdict.h +++ b/src/sortdict.h @@ -99,7 +99,7 @@ class SDict private: SList<T> *m_list; QDict<T> *m_dict; - int m_sizeIndex; + uint m_sizeIndex; public: /*! Create an ordered dictionary. @@ -108,7 +108,7 @@ class SDict * \param caseSensitive indicated whether the keys should be sorted * in a case sensitive way. */ - SDict(int size=17,bool caseSensitive=TRUE) : m_sizeIndex(0) + SDict(uint size=17,bool caseSensitive=TRUE) : m_sizeIndex(0) { m_list = new SList<T>(this); #if AUTORESIZE @@ -277,7 +277,7 @@ class SDict /*! Returns the number of items stored in the dictionary */ - int count() const + uint count() const { return m_list->count(); } diff --git a/src/sqlcode.l b/src/sqlcode.l index 02c2c14..58a2fce 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -19,6 +19,9 @@ %option nounput %option reentrant %option extra-type="struct sqlcodeYY_state *" +%top{ +#include <stdint.h> +} %{ @@ -41,6 +44,8 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define USE_STATE2STRING 0 + struct sqlcodeYY_state { CodeOutputInterface * code; @@ -62,8 +67,10 @@ struct sqlcodeYY_state const char *currentFontClass; }; -static void codify(const char* text); +#if USE_STATE2STRING static const char *stateToString(int state); +#endif + static void setCurrentDoc(const QCString &anchor,yyscan_t yyscanner); static void startCodeLine(yyscan_t yyscanner); static void endFontClass(yyscan_t yyscanner); @@ -72,7 +79,7 @@ static void nextCodeLine(yyscan_t yyscanner); static void codifyLines(char *text,yyscan_t yyscanner); static void startFontClass(const char *s,yyscan_t yyscanner); static int countLines(yyscan_t yyscanner); -static int yyread(char *buf,int max_size,yyscan_t yyscanner); +static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); @@ -190,12 +197,6 @@ commentclose "\*/" %% -static void codify(const char* text, yyscan_t yyscanner) -{ - struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->code->codify(text); -} - static void setCurrentDoc(const QCString &anchor, yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -345,10 +346,10 @@ static int countLines(yyscan_t yyscanner) return count; } -static int yyread(char *buf,int max_size,yyscan_t yyscanner) +static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - int c=0; + yy_size_t c=0; while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) { *buf = yyextra->inputString[yyextra->inputPosition++] ; @@ -484,4 +485,6 @@ void SQLCodeParser::resetCodeParserState() //--------------------------------------------------------------------------------- +#if USE_STATE2STRING #include "sqlcode.l.h" +#endif diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 14a73d8..2f72221 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -501,9 +501,9 @@ const char * table_schema[][2] = { ////////////////////////////////////////////////////// struct SqlStmt { - const char *query; - sqlite3_stmt *stmt; - sqlite3 *db; + const char *query = 0; + sqlite3_stmt *stmt = 0; + sqlite3 *db = 0; }; ////////////////////////////////////////////////////// /* If you add a new statement below, make sure to add it to @@ -854,16 +854,16 @@ class TextGeneratorSqlite3Impl : public TextGeneratorIntf }; -static bool bindTextParameter(SqlStmt &s,const char *name,const char *value, bool _static=TRUE) +static bool bindTextParameter(SqlStmt &s,const char *name,const char *value, bool _static=FALSE) { int idx = sqlite3_bind_parameter_index(s.stmt, name); if (idx==0) { - msg("sqlite3_bind_parameter_index(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db)); + err("sqlite3_bind_parameter_index(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db)); return false; } int rv = sqlite3_bind_text(s.stmt, idx, value, -1, _static==TRUE?SQLITE_STATIC:SQLITE_TRANSIENT); if (rv!=SQLITE_OK) { - msg("sqlite3_bind_text(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db)); + err("sqlite3_bind_text(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db)); return false; } return true; @@ -873,12 +873,12 @@ static bool bindIntParameter(SqlStmt &s,const char *name,int value) { int idx = sqlite3_bind_parameter_index(s.stmt, name); if (idx==0) { - msg("sqlite3_bind_parameter_index(%s)[%s] failed to find column: %s\n", name, s.query, sqlite3_errmsg(s.db)); + err("sqlite3_bind_parameter_index(%s)[%s] failed to find column: %s\n", name, s.query, sqlite3_errmsg(s.db)); return false; } int rv = sqlite3_bind_int(s.stmt, idx, value); if (rv!=SQLITE_OK) { - msg("sqlite3_bind_int(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db)); + err("sqlite3_bind_int(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db)); return false; } return true; @@ -909,11 +909,11 @@ static int insertPath(QCString name, bool local=TRUE, bool found=TRUE, int type= name = stripFromPath(name); - bindTextParameter(path_select,":name",name.data(),FALSE); + bindTextParameter(path_select,":name",name.data()); rowid=step(path_select,TRUE,TRUE); if (rowid==0) { - bindTextParameter(path_insert,":name",name.data(),FALSE); + bindTextParameter(path_insert,":name",name.data()); bindIntParameter(path_insert,":type",type); bindIntParameter(path_insert,":local",local?1:0); bindIntParameter(path_insert,":found",found?1:0); @@ -924,10 +924,10 @@ static int insertPath(QCString name, bool local=TRUE, bool found=TRUE, int type= static void recordMetadata() { - bindTextParameter(meta_insert,":doxygen_version",getVersion()); - bindTextParameter(meta_insert,":schema_version","0.2.0"); //TODO: this should be a constant somewhere; not sure where - bindTextParameter(meta_insert,":generated_at",dateToString(TRUE), FALSE); - bindTextParameter(meta_insert,":generated_on",dateToString(FALSE), FALSE); + bindTextParameter(meta_insert,":doxygen_version",getFullVersion()); + bindTextParameter(meta_insert,":schema_version","0.2.0",TRUE); //TODO: this should be a constant somewhere; not sure where + bindTextParameter(meta_insert,":generated_at",dateToString(TRUE)); + bindTextParameter(meta_insert,":generated_on",dateToString(FALSE)); bindTextParameter(meta_insert,":project_name",Config_getString(PROJECT_NAME)); bindTextParameter(meta_insert,":project_number",Config_getString(PROJECT_NUMBER)); bindTextParameter(meta_insert,":project_brief",Config_getString(PROJECT_BRIEF)); @@ -1155,7 +1155,7 @@ static int prepareStatement(sqlite3 *db, SqlStmt &s) rc = sqlite3_prepare_v2(db,s.query,-1,&s.stmt,0); if (rc!=SQLITE_OK) { - msg("prepare failed for %s\n%s\n", s.query, sqlite3_errmsg(db)); + err("prepare failed for %s\n%s\n", s.query, sqlite3_errmsg(db)); s.db = NULL; return -1; } @@ -1218,8 +1218,6 @@ static void pragmaTuning(sqlite3 *db) static int initializeTables(sqlite3* db) { int rc; - sqlite3_stmt *stmt = 0; - msg("Initializing DB schema (tables)...\n"); for (unsigned int k = 0; k < sizeof(table_schema) / sizeof(table_schema[0]); k++) { @@ -1228,7 +1226,7 @@ static int initializeTables(sqlite3* db) rc = sqlite3_exec(db, q, NULL, NULL, &errmsg); if (rc != SQLITE_OK) { - msg("failed to execute query: %s\n\t%s\n", q, errmsg); + err("failed to execute query: %s\n\t%s\n", q, errmsg); return -1; } } @@ -1238,8 +1236,6 @@ static int initializeTables(sqlite3* db) static int initializeViews(sqlite3* db) { int rc; - sqlite3_stmt *stmt = 0; - msg("Initializing DB schema (views)...\n"); for (unsigned int k = 0; k < sizeof(view_schema) / sizeof(view_schema[0]); k++) { @@ -1248,7 +1244,7 @@ static int initializeViews(sqlite3* db) rc = sqlite3_exec(db, q, NULL, NULL, &errmsg); if (rc != SQLITE_OK) { - msg("failed to execute query: %s\n\t%s\n", q, errmsg); + err("failed to execute query: %s\n\t%s\n", q, errmsg); return -1; } } @@ -1340,20 +1336,15 @@ static void writeInnerFiles(const FileList *fl, struct Refid outer_refid) } } -static void writeInnerDirs(const DirList *dl, struct Refid outer_refid) +static void writeInnerDirs(const DirList &dl, struct Refid outer_refid) { - if (dl) + for (const auto subdir : dl) { - QListIterator<DirDef> subdirs(*dl); - const DirDef *subdir; - for (subdirs.toFirst();(subdir=subdirs.current());++subdirs) - { - struct Refid inner_refid = insertRefid(subdir->getOutputFileBase()); + struct Refid inner_refid = insertRefid(subdir->getOutputFileBase()); - bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid); - bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid); - step(contains_insert); - } + bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid); + bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid); + step(contains_insert); } } @@ -1433,7 +1424,11 @@ QCString getSQLDocBlock(const Definition *scope, dynamic_cast<const MemberDef*>(def), doc, FALSE, - FALSE + FALSE, + 0, + FALSE, + FALSE, + Config_getBool(MARKDOWN_SUPPORT) ); XMLCodeGenerator codeGen(t); // create a parse tree visitor for XML @@ -1450,15 +1445,14 @@ static void getSQLDesc(SqlStmt &s,const char *col,const char *value,const Defini bindTextParameter( s, col, - getSQLDocBlock( - def->getOuterScope(), - def, - value, - def->docFile(), - def->docLine() - ), - FALSE - ); + getSQLDocBlock( + def->getOuterScope(), + def, + value, + def->docFile(), + def->docLine() + ) + ); } //////////////////////////////////////////// @@ -1650,7 +1644,7 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref } bindIntParameter(memberdef_insert,":rowid", refid.rowid); - bindTextParameter(memberdef_insert,":kind",md->memberTypeName(),FALSE); + bindTextParameter(memberdef_insert,":kind",md->memberTypeName()); bindIntParameter(memberdef_insert,":prot",md->protection()); bindIntParameter(memberdef_insert,":static",md->isStatic()); @@ -1672,8 +1666,8 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref if (isFunc) { const ArgumentList &al = md->argumentList(); - bindIntParameter(memberdef_insert,":const",al.constSpecifier); - bindIntParameter(memberdef_insert,":volatile",al.volatileSpecifier); + bindIntParameter(memberdef_insert,":const",al.constSpecifier()); + bindIntParameter(memberdef_insert,":volatile",al.volatileSpecifier()); bindIntParameter(memberdef_insert,":explicit",md->isExplicit()); bindIntParameter(memberdef_insert,":inline",md->isInline()); bindIntParameter(memberdef_insert,":final",md->isFinal()); @@ -1740,7 +1734,7 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref } const MemberDef *rmd = md->reimplements(); - if(rmd) + if (rmd) { QCString qreimplemented_refid = rmd->getOutputFileBase() + "_1" + rmd->anchor(); @@ -1766,7 +1760,7 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref linkifyText(TextGeneratorSqlite3Impl(l), def, md->getBodyDef(),md,typeStr); if (typeStr) { - bindTextParameter(memberdef_insert,":type",typeStr,FALSE); + bindTextParameter(memberdef_insert,":type",typeStr); } if (md->definition()) @@ -1811,7 +1805,7 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref if ( md->getScopeString() ) { - bindTextParameter(memberdef_insert,":scope",md->getScopeString(),FALSE); + bindTextParameter(memberdef_insert,":scope",md->getScopeString()); } // +Brief, detailed and inbody description @@ -1866,7 +1860,6 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref if (mdict!=0) { MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { insertMemberReference(md,rmd, "inline"); @@ -1877,7 +1870,6 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref if (mdict!=0) { MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { insertMemberReference(rmd,md, "inline"); @@ -1910,20 +1902,13 @@ static void generateSqlite3Section( const Definition *d, static void associateAllClassMembers(const ClassDef *cd, struct Refid scope_refid) { - if (cd->memberNameInfoSDict()) + for (auto &mni : cd->memberNameInfoLinkedMap()) { - MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict()); - MemberNameInfo *mni; - for (mnii.toFirst();(mni=mnii.current());++mnii) + for (auto &mi : *mni) { - MemberNameInfoIterator mii(*mni); - MemberInfo *mi; - for (mii.toFirst();(mi=mii.current());++mii) - { - MemberDef *md = mi->memberDef; - QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor(); - associateMember(md, insertRefid(qrefid), scope_refid); - } + MemberDef *md = mi->memberDef(); + QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor(); + associateMember(md, insertRefid(qrefid), scope_refid); } } } @@ -1965,8 +1950,8 @@ static void generateSqlite3ForClass(const ClassDef *cd) bindIntParameter(compounddef_insert,":rowid", refid.rowid); bindTextParameter(compounddef_insert,":name",cd->name()); - bindTextParameter(compounddef_insert,":title",cd->title(), FALSE); - bindTextParameter(compounddef_insert,":kind",cd->compoundTypeString(),FALSE); + bindTextParameter(compounddef_insert,":title",cd->title()); + bindTextParameter(compounddef_insert,":kind",cd->compoundTypeString()); bindIntParameter(compounddef_insert,":prot",cd->protection()); int file_id = insertPath(cd->getDefFileName()); @@ -2010,7 +1995,6 @@ static void generateSqlite3ForClass(const ClassDef *cd) DBG_CTX(("-----> ClassDef includeInfo for %s\n", nm.data())); DBG_CTX((" local : %d\n", ii->local)); DBG_CTX((" imported : %d\n", ii->imported)); - DBG_CTX((" indirect : %d\n", ii->indirect)); DBG_CTX(("header: %s\n", ii->fileDef->absFilePath().data())); DBG_CTX((" file_id : %d\n", file_id)); DBG_CTX((" header_id: %d\n", header_id)); @@ -2112,8 +2096,8 @@ static void generateSqlite3ForNamespace(const NamespaceDef *nd) bindIntParameter(compounddef_insert,":rowid", refid.rowid); bindTextParameter(compounddef_insert,":name",nd->name()); - bindTextParameter(compounddef_insert,":title",nd->title(), FALSE); - bindTextParameter(compounddef_insert,":kind","namespace",FALSE); + bindTextParameter(compounddef_insert,":title",nd->title()); + bindTextParameter(compounddef_insert,":kind","namespace"); int file_id = insertPath(nd->getDefFileName()); bindIntParameter(compounddef_insert,":file_id",file_id); @@ -2178,9 +2162,9 @@ static void generateSqlite3ForFile(const FileDef *fd) if(!refid.created && compounddefExists(refid)){return;} bindIntParameter(compounddef_insert,":rowid", refid.rowid); - bindTextParameter(compounddef_insert,":name",fd->name(),FALSE); - bindTextParameter(compounddef_insert,":title",fd->title(),FALSE); - bindTextParameter(compounddef_insert,":kind","file",FALSE); + bindTextParameter(compounddef_insert,":name",fd->name()); + bindTextParameter(compounddef_insert,":title",fd->title()); + bindTextParameter(compounddef_insert,":kind","file"); int file_id = insertPath(fd->getDefFileName()); bindIntParameter(compounddef_insert,":file_id",file_id); @@ -2226,7 +2210,6 @@ static void generateSqlite3ForFile(const FileDef *fd) DBG_CTX(("-----> FileDef includeInfo for %s\n", ii->includeName.data())); DBG_CTX((" local: %d\n", ii->local)); DBG_CTX((" imported: %d\n", ii->imported)); - DBG_CTX((" indirect: %d\n", ii->indirect)); if(ii->fileDef) { DBG_CTX(("include: %s\n", ii->fileDef->absFilePath().data())); @@ -2346,8 +2329,8 @@ static void generateSqlite3ForGroup(const GroupDef *gd) bindIntParameter(compounddef_insert,":rowid", refid.rowid); bindTextParameter(compounddef_insert,":name",gd->name()); - bindTextParameter(compounddef_insert,":title",gd->groupTitle(), FALSE); - bindTextParameter(compounddef_insert,":kind","group",FALSE); + bindTextParameter(compounddef_insert,":title",gd->groupTitle()); + bindTextParameter(compounddef_insert,":kind","group"); int file_id = insertPath(gd->getDefFileName()); bindIntParameter(compounddef_insert,":file_id",file_id); @@ -2413,7 +2396,7 @@ static void generateSqlite3ForDir(const DirDef *dd) bindIntParameter(compounddef_insert,":rowid", refid.rowid); bindTextParameter(compounddef_insert,":name",dd->displayName()); - bindTextParameter(compounddef_insert,":kind","dir",FALSE); + bindTextParameter(compounddef_insert,":kind","dir"); int file_id = insertPath(dd->getDefFileName(),TRUE,TRUE,2); bindIntParameter(compounddef_insert,":file_id",file_id); @@ -2437,7 +2420,7 @@ static void generateSqlite3ForDir(const DirDef *dd) step(compounddef_insert); // + files - writeInnerDirs(&dd->subDirs(),refid); + writeInnerDirs(dd->subDirs(),refid); // + files writeInnerFiles(dd->getFiles(),refid); @@ -2486,19 +2469,19 @@ static void generateSqlite3ForPage(const PageDef *pd,bool isExample) } else { - SectionInfo *si = Doxygen::sectionDict->find(pd->name()); + SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) { - title = si->title; + title = si->title(); } if(!title){title = pd->title();} } // + title - bindTextParameter(compounddef_insert,":title",title,FALSE); + bindTextParameter(compounddef_insert,":title",title); - bindTextParameter(compounddef_insert,":kind", isExample ? "example" : "page"); + bindTextParameter(compounddef_insert,":kind", isExample ? "example" : "page",TRUE); int file_id = insertPath(pd->getDefFileName()); @@ -2520,29 +2503,36 @@ static void generateSqlite3ForPage(const PageDef *pd,bool isExample) static sqlite3* openDbConnection() { - QCString outputDirectory = Config_getString(OUTPUT_DIRECTORY); + QCString outputDirectory = Config_getString(SQLITE3_OUTPUT); QDir sqlite3Dir(outputDirectory); sqlite3 *db; int rc; - struct stat buf; rc = sqlite3_initialize(); if (rc != SQLITE_OK) { - msg("sqlite3_initialize failed\n"); + err("sqlite3_initialize failed\n"); return NULL; } + QCString dbFileName = "doxygen_sqlite3.db"; + QFileInfo fi(outputDirectory+"/"+dbFileName); - if (stat (outputDirectory+"/doxygen_sqlite3.db", &buf) == 0) + if (fi.exists()) { - msg("doxygen_sqlite3.db already exists! aborting sqlite3 output generation!\n"); - msg("If you wish to re-generate the database, remove or archive the existing copy first.\n"); - return NULL; + if (Config_getBool(SQLITE3_RECREATE_DB)) + { + QDir().remove(fi.absFilePath()); + } + else + { + err("doxygen_sqlite3.db already exists! Rename, remove, or archive it to regenerate\n"); + return NULL; + } } rc = sqlite3_open_v2( - outputDirectory+"/doxygen_sqlite3.db", + fi.absFilePath().utf8(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0 @@ -2550,8 +2540,7 @@ static sqlite3* openDbConnection() if (rc != SQLITE_OK) { sqlite3_close(db); - msg("database open failed: %s\n", "doxygen_sqlite3.db"); - return NULL; + err("Database open failed: %s\n", "doxygen_sqlite3.db"); } return db; } @@ -2612,16 +2601,12 @@ void generateSqlite3() } // + files - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - const FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { msg("Generating Sqlite3 output for file %s\n",fd->name().data()); - generateSqlite3ForFile(fd); + generateSqlite3ForFile(fd.get()); } } diff --git a/src/tagreader.cpp b/src/tagreader.cpp index 3f9a7a1..62aadc3 100644 --- a/src/tagreader.cpp +++ b/src/tagreader.cpp @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -18,6 +18,10 @@ #include "tagreader.h" +#include <map> +#include <functional> +#include <utility> + #include <assert.h> #include <stdio.h> #include <stdarg.h> @@ -25,15 +29,10 @@ #include <qxml.h> -#include <qstack.h> -#include <qdict.h> #include <qfileinfo.h> -#include <qlist.h> #include <qstring.h> -#include <qcstringlist.h> #include "entry.h" -#include "classdef.h" #include "doxygen.h" #include "util.h" #include "message.h" @@ -42,7 +41,7 @@ #include "filedef.h" #include "filename.h" #include "section.h" -#include "groupdef.h" +#include "containers.h" /** Information about an linkable anchor */ class TagAnchorInfo @@ -50,21 +49,13 @@ class TagAnchorInfo public: TagAnchorInfo(const QCString &f, const QCString &l, - const QCString &t=QCString()) + const QCString &t=QCString()) : label(l), fileName(f), title(t) {} QCString label; QCString fileName; QCString title; }; -/** List of TagAnchorInfo objects. */ -class TagAnchorInfoList : public QList<TagAnchorInfo> -{ - public: - TagAnchorInfoList() : QList<TagAnchorInfo>() { setAutoDelete(TRUE); } - virtual ~TagAnchorInfoList() {} -}; - /** Container for enum values that are scoped within an enum */ class TagEnumValueInfo { @@ -75,12 +66,21 @@ class TagEnumValueInfo QCString clangid; }; +/** Container for include info that can be read from a tagfile */ +class TagIncludeInfo +{ + public: + QCString id; + QCString name; + QCString text; + bool isLocal; + bool isImported; +}; + /** Container for member specific info that can be read from a tagfile */ class TagMemberInfo { public: - TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) - { enumValues.setAutoDelete(TRUE); } QCString type; QCString name; QCString anchorFile; @@ -88,129 +88,165 @@ class TagMemberInfo QCString arglist; QCString kind; QCString clangId; - TagAnchorInfoList docAnchors; - Protection prot; - Specifier virt; - bool isStatic; - QList<TagEnumValueInfo> enumValues; + std::vector<TagAnchorInfo> docAnchors; + Protection prot = Public; + Specifier virt = Normal; + bool isStatic = false; + std::vector<TagEnumValueInfo> enumValues; }; -/** Container for class specific info that can be read from a tagfile */ -class TagClassInfo +/** Base class for all compound types */ +class TagCompoundInfo { public: - enum Kind { None=-1, Class, Struct, Union, Interface, Exception, Protocol, Category, Enum, Service, Singleton }; - TagClassInfo() { templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; kind = None; } - ~TagClassInfo() { delete templateArguments; } + enum class CompoundType { Class, Namespace, Package, File, Group, Page, Dir }; + explicit TagCompoundInfo(CompoundType type) : m_type(type) {} + virtual ~TagCompoundInfo() {} + CompoundType compoundType() const { return m_type; } + std::vector<TagMemberInfo> members; QCString name; QCString filename; + std::vector<TagAnchorInfo> docAnchors; + private: + CompoundType m_type; +}; + +/** Container for class specific info that can be read from a tagfile */ +class TagClassInfo : public TagCompoundInfo +{ + public: + enum class Kind { None=-1, Class, Struct, Union, Interface, Exception, Protocol, Category, Enum, Service, Singleton }; + TagClassInfo(Kind k) : TagCompoundInfo(CompoundType::Class), kind(k) {} QCString clangId; QCString anchor; - TagAnchorInfoList docAnchors; std::vector<BaseInfo> bases; - QList<TagMemberInfo> members; - QList<QCString> *templateArguments; - QCStringList classList; + StringVector templateArguments; + StringVector classList; Kind kind; - bool isObjC; + bool isObjC = false; + static TagClassInfo *get(std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<TagClassInfo*>(t.get()); + } + static const TagClassInfo *get(const std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<const TagClassInfo*>(t.get()); + } }; /** Container for namespace specific info that can be read from a tagfile */ -class TagNamespaceInfo +class TagNamespaceInfo : public TagCompoundInfo { public: - TagNamespaceInfo() { members.setAutoDelete(TRUE); } - QCString name; - QCString filename; + TagNamespaceInfo() :TagCompoundInfo(CompoundType::Namespace) {} QCString clangId; - QCStringList classList; - QCStringList namespaceList; - TagAnchorInfoList docAnchors; - QList<TagMemberInfo> members; + StringVector classList; + StringVector namespaceList; + static TagNamespaceInfo *get(std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<TagNamespaceInfo*>(t.get()); + } + static const TagNamespaceInfo *get(const std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<const TagNamespaceInfo*>(t.get()); + } }; /** Container for package specific info that can be read from a tagfile */ -class TagPackageInfo -{ - public: - TagPackageInfo() { members.setAutoDelete(TRUE); } - QCString name; - QCString filename; - TagAnchorInfoList docAnchors; - QList<TagMemberInfo> members; - QCStringList classList; -}; - -/** Container for include info that can be read from a tagfile */ -class TagIncludeInfo +class TagPackageInfo : public TagCompoundInfo { public: - QCString id; - QCString name; - QCString text; - bool isLocal; - bool isImported; + TagPackageInfo() : TagCompoundInfo(CompoundType::Package) { } + StringVector classList; + static TagPackageInfo *get(std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<TagPackageInfo*>(t.get()); + } + static const TagPackageInfo *get(const std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<const TagPackageInfo*>(t.get()); + } }; /** Container for file specific info that can be read from a tagfile */ -class TagFileInfo +class TagFileInfo : public TagCompoundInfo { public: - TagFileInfo() { members.setAutoDelete(TRUE); includes.setAutoDelete(TRUE); } - QCString name; + TagFileInfo() : TagCompoundInfo(CompoundType::File) { } QCString path; - QCString filename; - TagAnchorInfoList docAnchors; - QList<TagMemberInfo> members; - QCStringList classList; - QCStringList namespaceList; - QList<TagIncludeInfo> includes; + StringVector classList; + StringVector namespaceList; + std::vector<TagIncludeInfo> includes; + static TagFileInfo *get(std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<TagFileInfo*>(t.get()); + } + static const TagFileInfo *get(const std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<const TagFileInfo*>(t.get()); + } }; /** Container for group specific info that can be read from a tagfile */ -class TagGroupInfo +class TagGroupInfo : public TagCompoundInfo { public: - TagGroupInfo() { members.setAutoDelete(TRUE); } - QCString name; + TagGroupInfo() : TagCompoundInfo(CompoundType::Group) { } QCString title; - QCString filename; - TagAnchorInfoList docAnchors; - QList<TagMemberInfo> members; - QCStringList subgroupList; - QCStringList classList; - QCStringList namespaceList; - QCStringList fileList; - QCStringList pageList; - QCStringList dirList; + StringVector subgroupList; + StringVector classList; + StringVector namespaceList; + StringVector fileList; + StringVector pageList; + StringVector dirList; + static TagGroupInfo *get(std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<TagGroupInfo*>(t.get()); + } + static const TagGroupInfo *get(const std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<const TagGroupInfo*>(t.get()); + } }; /** Container for page specific info that can be read from a tagfile */ -class TagPageInfo +class TagPageInfo : public TagCompoundInfo { public: - QCString name; + TagPageInfo() : TagCompoundInfo(CompoundType::Page) {} QCString title; - QCString filename; - TagAnchorInfoList docAnchors; + static TagPageInfo *get(std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<TagPageInfo*>(t.get()); + } + static const TagPageInfo *get(const std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<const TagPageInfo*>(t.get()); + } }; /** Container for directory specific info that can be read from a tagfile */ -class TagDirInfo +class TagDirInfo : public TagCompoundInfo { public: - QCString name; - QCString filename; + TagDirInfo() : TagCompoundInfo(CompoundType::Dir) {} QCString path; - QCStringList subdirList; - QCStringList fileList; - TagAnchorInfoList docAnchors; + StringVector subdirList; + StringVector fileList; + static TagDirInfo *get(std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<TagDirInfo*>(t.get()); + } + static const TagDirInfo *get(const std::unique_ptr<TagCompoundInfo> &t) + { + return dynamic_cast<const TagDirInfo*>(t.get()); + } }; -/** Tag file parser. +/** Tag file parser. * * Reads an XML-structured tagfile and builds up the structure in - * memory. The method buildLists() is used to transfer/translate + * memory. The method buildLists() is used to transfer/translate * the structures to the doxygen engine. */ class TagFileParser : public QXmlDefaultHandler @@ -227,48 +263,16 @@ class TagFileParser : public QXmlDefaultHandler InDir, InTempArgList }; - class StartElementHandler - { - typedef void (TagFileParser::*Handler)(const QXmlAttributes &attrib); - public: - StartElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {} - void operator()(const QXmlAttributes &attrib) { (m_parent->*m_handler)(attrib); } - private: - TagFileParser *m_parent; - Handler m_handler; - }; - class EndElementHandler + struct CompoundFactory { - typedef void (TagFileParser::*Handler)(); - public: - EndElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {} - void operator()() { (m_parent->*m_handler)(); } - private: - TagFileParser *m_parent; - Handler m_handler; + using CreateFunc = std::function<std::unique_ptr<TagCompoundInfo>()>; + CompoundFactory(State s,CreateFunc f) : state(s), make_instance(f) {} + State state; + CreateFunc make_instance; }; - public: - TagFileParser(const char *tagName) : m_startElementHandlers(17), - m_endElementHandlers(17), - m_tagName(tagName) - { - m_startElementHandlers.setAutoDelete(TRUE); - m_endElementHandlers.setAutoDelete(TRUE); - m_curClass=0; - m_curFile=0; - m_curNamespace=0; - m_curPackage=0; - m_curGroup=0; - m_curPage=0; - m_curDir=0; - m_curMember=0; - m_curEnumValue=0; - m_curIncludes=0; - m_state = Invalid; - m_locator = 0; - } + TagFileParser(const char *tagName) : m_tagName(tagName) {} void setDocumentLocator ( QXmlLocator * locator ) { @@ -282,8 +286,9 @@ class TagFileParser : public QXmlDefaultHandler void warn(const char *fmt) { - ::warn(m_inputFileName,m_locator->lineNumber(),fmt); + ::warn(m_inputFileName,m_locator->lineNumber(),"%s", fmt); } + void warn(const char *fmt,const char *s) { ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s); @@ -294,104 +299,23 @@ class TagFileParser : public QXmlDefaultHandler m_curString = ""; QString kind = attrib.value("kind"); QString isObjC = attrib.value("objc"); - if (kind=="class") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Class; - m_state = InClass; - } - else if (kind=="struct") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Struct; - m_state = InClass; - } - else if (kind=="union") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Union; - m_state = InClass; - } - else if (kind=="interface") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Interface; - m_state = InClass; - } - else if (kind=="enum") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Enum; - m_state = InClass; - } - else if (kind=="exception") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Exception; - m_state = InClass; - } - else if (kind=="protocol") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Protocol; - m_state = InClass; - } - else if (kind=="category") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Category; - m_state = InClass; - } - else if (kind=="service") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Service; - m_state = InClass; - } - else if (kind=="singleton") - { - m_curClass = new TagClassInfo; - m_curClass->kind = TagClassInfo::Singleton; - m_state = InClass; - } - else if (kind=="file") - { - m_curFile = new TagFileInfo; - m_state = InFile; - } - else if (kind=="namespace") - { - m_curNamespace = new TagNamespaceInfo; - m_state = InNamespace; - } - else if (kind=="group") - { - m_curGroup = new TagGroupInfo; - m_state = InGroup; - } - else if (kind=="page") - { - m_curPage = new TagPageInfo; - m_state = InPage; - } - else if (kind=="package") - { - m_curPackage = new TagPackageInfo; - m_state = InPackage; - } - else if (kind=="dir") + + auto it = m_compoundFactory.find(kind.utf8().str()); + if (it!=m_compoundFactory.end()) { - m_curDir = new TagDirInfo; - m_state = InDir; + m_curCompound = it->second.make_instance(); + m_state = it->second.state; } else { warn("Unknown compound attribute '%s' found!",kind.data()); m_state = Invalid; } - if (isObjC=="yes" && m_curClass) + + if (isObjC=="yes" && m_curCompound && + m_curCompound->compoundType()==TagCompoundInfo::CompoundType::Class) { - m_curClass->isObjC = TRUE; + TagClassInfo::get(m_curCompound)->isObjC = TRUE; } } @@ -399,68 +323,68 @@ class TagFileParser : public QXmlDefaultHandler { switch (m_state) { - case InClass: m_tagFileClasses.append(m_curClass); - m_curClass=0; break; - case InFile: m_tagFileFiles.append(m_curFile); - m_curFile=0; break; - case InNamespace: m_tagFileNamespaces.append(m_curNamespace); - m_curNamespace=0; break; - case InGroup: m_tagFileGroups.append(m_curGroup); - m_curGroup=0; break; - case InPage: m_tagFilePages.append(m_curPage); - m_curPage=0; break; - case InDir: m_tagFileDirs.append(m_curDir); - m_curDir=0; break; - case InPackage: m_tagFilePackages.append(m_curPackage); - m_curPackage=0; break; + case InClass: + case InFile: + case InNamespace: + case InGroup: + case InPage: + case InDir: + case InPackage: + m_tagFileCompounds.push_back(std::move(m_curCompound)); + break; default: - warn("tag 'compound' was not expected!"); + warn("tag 'compound' was not expected!"); + break; } } void startMember( const QXmlAttributes& attrib) { - m_curMember = new TagMemberInfo; - m_curMember->kind = attrib.value("kind").utf8(); + m_curMember = TagMemberInfo(); + m_curMember.kind = attrib.value("kind").utf8(); QCString protStr = attrib.value("protection").utf8(); QCString virtStr = attrib.value("virtualness").utf8(); QCString staticStr = attrib.value("static").utf8(); if (protStr=="protected") { - m_curMember->prot = Protected; + m_curMember.prot = Protected; } else if (protStr=="private") { - m_curMember->prot = Private; + m_curMember.prot = Private; } if (virtStr=="virtual") { - m_curMember->virt = Virtual; + m_curMember.virt = Virtual; } else if (virtStr=="pure") { - m_curMember->virt = Pure; + m_curMember.virt = Pure; } if (staticStr=="yes") { - m_curMember->isStatic = TRUE; + m_curMember.isStatic = TRUE; } - m_stateStack.push(new State(m_state)); + m_stateStack.push(m_state); m_state = InMember; } void endMember() { - m_state = *m_stateStack.top(); - m_stateStack.remove(); + m_state = m_stateStack.top(); + m_stateStack.pop(); switch(m_state) { - case InClass: m_curClass->members.append(m_curMember); break; - case InFile: m_curFile->members.append(m_curMember); break; - case InNamespace: m_curNamespace->members.append(m_curMember); break; - case InGroup: m_curGroup->members.append(m_curMember); break; - case InPackage: m_curPackage->members.append(m_curMember); break; - default: warn("Unexpected tag 'member' found"); break; + case InClass: + case InFile: + case InNamespace: + case InGroup: + case InPackage: + m_curCompound->members.push_back(m_curMember); + break; + default: + warn("Unexpected tag 'member' found"); + break; } } @@ -469,11 +393,11 @@ class TagFileParser : public QXmlDefaultHandler if (m_state==InMember) { m_curString = ""; - m_curEnumValue = new TagEnumValueInfo; - m_curEnumValue->file = attrib.value("file").utf8(); - m_curEnumValue->anchor = attrib.value("anchor").utf8(); - m_curEnumValue->clangid = attrib.value("clangid").utf8(); - m_stateStack.push(new State(m_state)); + m_curEnumValue = TagEnumValueInfo(); + m_curEnumValue.file = attrib.value("file").utf8(); + m_curEnumValue.anchor = attrib.value("anchor").utf8(); + m_curEnumValue.clangid = attrib.value("clangid").utf8(); + m_stateStack.push(m_state); m_state = InEnumValue; } else @@ -484,13 +408,13 @@ class TagFileParser : public QXmlDefaultHandler void endEnumValue() { - m_curEnumValue->name = m_curString.stripWhiteSpace(); - m_state = *m_stateStack.top(); - m_stateStack.remove(); + m_curEnumValue.name = QCString(m_curString).stripWhiteSpace(); + m_state = m_stateStack.top(); + m_stateStack.pop(); if (m_state==InMember) { - m_curMember->enumValues.append(m_curEnumValue); - m_curEnumValue=0; + m_curMember.enumValues.push_back(m_curEnumValue); + m_curEnumValue=TagEnumValueInfo(); } } @@ -515,14 +439,18 @@ class TagFileParser : public QXmlDefaultHandler } switch(m_state) { - case InClass: m_curClass->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; - case InFile: m_curFile->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; - case InNamespace: m_curNamespace->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; - case InGroup: m_curGroup->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; - case InPage: m_curPage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; - case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; - case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; - case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break; + case InClass: + case InFile: + case InNamespace: + case InGroup: + case InPage: + case InPackage: + case InDir: + m_curCompound->docAnchors.push_back(TagAnchorInfo(m_fileName,m_curString,m_title)); + break; + case InMember: + m_curMember.docAnchors.push_back(TagAnchorInfo(m_fileName,m_curString,m_title)); + break; default: break; // will not be reached } } @@ -531,12 +459,24 @@ class TagFileParser : public QXmlDefaultHandler { switch(m_state) { - case InClass: m_curClass->classList.append(m_curString); break; - case InFile: m_curFile->classList.append(m_curString); break; - case InNamespace: m_curNamespace->classList.append(m_curString); break; - case InGroup: m_curGroup->classList.append(m_curString); break; - case InPackage: m_curPackage->classList.append(m_curString); break; - default: warn("Unexpected tag 'class' found"); break; + case InClass: + TagClassInfo::get(m_curCompound)->classList.push_back(m_curString); + break; + case InFile: + TagFileInfo::get(m_curCompound)->classList.push_back(m_curString); + break; + case InNamespace: + TagNamespaceInfo::get(m_curCompound)->classList.push_back(m_curString); + break; + case InGroup: + TagGroupInfo::get(m_curCompound)->classList.push_back(m_curString); + break; + case InPackage: + TagPackageInfo::get(m_curCompound)->classList.push_back(m_curString); + break; + default: + warn("Unexpected tag 'class' found"); + break; } } @@ -544,10 +484,18 @@ class TagFileParser : public QXmlDefaultHandler { switch(m_state) { - case InNamespace: m_curNamespace->classList.append(m_curString); break; - case InFile: m_curFile->namespaceList.append(m_curString); break; - case InGroup: m_curGroup->namespaceList.append(m_curString); break; - default: warn("Unexpected tag 'namespace' found"); break; + case InNamespace: + TagNamespaceInfo::get(m_curCompound)->namespaceList.push_back(m_curString); + break; + case InFile: + TagFileInfo::get(m_curCompound)->namespaceList.push_back(m_curString); + break; + case InGroup: + TagGroupInfo::get(m_curCompound)->namespaceList.push_back(m_curString); + break; + default: + warn("Unexpected tag 'namespace' found"); + break; } } @@ -555,9 +503,15 @@ class TagFileParser : public QXmlDefaultHandler { switch(m_state) { - case InGroup: m_curGroup->fileList.append(m_curString); break; - case InDir: m_curDir->fileList.append(m_curString); break; - default: warn("Unexpected tag 'file' found"); break; + case InGroup: + TagGroupInfo::get(m_curCompound)->fileList.push_back(m_curString); + break; + case InDir: + TagDirInfo::get(m_curCompound)->fileList.push_back(m_curString); + break; + default: + warn("Unexpected tag 'file' found"); + break; } } @@ -565,8 +519,12 @@ class TagFileParser : public QXmlDefaultHandler { switch(m_state) { - case InGroup: m_curGroup->fileList.append(m_curString); break; - default: warn("Unexpected tag 'page' found"); break; + case InGroup: + TagGroupInfo::get(m_curCompound)->fileList.push_back(m_curString); + break; + default: + warn("Unexpected tag 'page' found"); + break; } } @@ -574,8 +532,12 @@ class TagFileParser : public QXmlDefaultHandler { switch(m_state) { - case InDir: m_curDir->subdirList.append(m_curString); break; - default: warn("Unexpected tag 'dir' found"); break; + case InDir: + TagDirInfo::get(m_curCompound)->subdirList.push_back(m_curString); + break; + default: + warn("Unexpected tag 'dir' found"); + break; } } @@ -595,7 +557,7 @@ class TagFileParser : public QXmlDefaultHandler { if (m_state==InMember) { - m_curMember->type = m_curString; + m_curMember.type = m_curString; } else { @@ -607,22 +569,28 @@ class TagFileParser : public QXmlDefaultHandler { switch (m_state) { - case InClass: m_curClass->name = m_curString; break; - case InFile: m_curFile->name = m_curString; break; - case InNamespace: m_curNamespace->name = m_curString; break; - case InGroup: m_curGroup->name = m_curString; break; - case InPage: m_curPage->name = m_curString; break; - case InDir: m_curDir->name = m_curString; break; - case InMember: m_curMember->name = m_curString; break; - case InPackage: m_curPackage->name = m_curString; break; - default: warn("Unexpected tag 'name' found"); break; + case InClass: + case InFile: + case InNamespace: + case InGroup: + case InPage: + case InDir: + case InPackage: + m_curCompound->name = m_curString; + break; + case InMember: + m_curMember.name = m_curString; + break; + default: + warn("Unexpected tag 'name' found"); + break; } } void startBase(const QXmlAttributes& attrib ) { m_curString=""; - if (m_state==InClass && m_curClass) + if (m_state==InClass && m_curCompound) { QString protStr = attrib.value("protection"); QString virtStr = attrib.value("virtualness"); @@ -640,7 +608,7 @@ class TagFileParser : public QXmlDefaultHandler { virt = Virtual; } - m_curClass->bases.push_back(BaseInfo(m_curString,prot,virt)); + TagClassInfo::get(m_curCompound)->bases.push_back(BaseInfo(m_curString.c_str(),prot,virt)); } else { @@ -650,9 +618,9 @@ class TagFileParser : public QXmlDefaultHandler void endBase() { - if (m_state==InClass && m_curClass) + if (m_state==InClass && m_curCompound) { - m_curClass->bases.back().name = m_curString; + TagClassInfo::get(m_curCompound)->bases.back().name = m_curString; } else { @@ -662,37 +630,32 @@ class TagFileParser : public QXmlDefaultHandler void startIncludes(const QXmlAttributes& attrib ) { - if (m_state==InFile && m_curFile) + m_curIncludes = TagIncludeInfo(); + m_curIncludes.id = attrib.value("id").utf8(); + m_curIncludes.name = attrib.value("name").utf8(); + m_curIncludes.isLocal = attrib.value("local").utf8()=="yes" ? TRUE : FALSE; + m_curIncludes.isImported = attrib.value("imported").utf8()=="yes" ? TRUE : FALSE; + m_curString=""; + } + + void endIncludes() + { + m_curIncludes.text = m_curString; + if (m_state==InFile && m_curCompound) { - m_curIncludes = new TagIncludeInfo; - m_curIncludes->id = attrib.value("id").utf8(); - m_curIncludes->name = attrib.value("name").utf8(); - m_curIncludes->isLocal = attrib.value("local").utf8()=="yes" ? TRUE : FALSE; - m_curIncludes->isImported = attrib.value("imported").utf8()=="yes" ? TRUE : FALSE; - m_curFile->includes.append(m_curIncludes); + TagFileInfo::get(m_curCompound)->includes.push_back(m_curIncludes); } else { warn("Unexpected tag 'includes' found"); } - m_curString=""; - } - - void endIncludes() - { - m_curIncludes->text = m_curString; } void endTemplateArg() { - if (m_state==InClass && m_curClass) + if (m_state==InClass && m_curCompound) { - if (m_curClass->templateArguments==0) - { - m_curClass->templateArguments = new QList<QCString>; - m_curClass->templateArguments->setAutoDelete(TRUE); - } - m_curClass->templateArguments->append(new QCString(m_curString)); + TagClassInfo::get(m_curCompound)->templateArguments.push_back(m_curString); } else { @@ -704,14 +667,18 @@ class TagFileParser : public QXmlDefaultHandler { switch (m_state) { - case InClass: m_curClass->filename = m_curString; break; - case InNamespace: m_curNamespace->filename = m_curString; break; - case InFile: m_curFile->filename = m_curString; break; - case InGroup: m_curGroup->filename = m_curString; break; - case InPage: m_curPage->filename = m_curString; break; - case InPackage: m_curPackage->filename = m_curString; break; - case InDir: m_curDir->filename = m_curString; break; - default: warn("Unexpected tag 'filename' found"); break; + case InClass: + case InNamespace: + case InFile: + case InGroup: + case InPage: + case InPackage: + case InDir: + m_curCompound->filename = m_curString; + break; + default: + warn("Unexpected tag 'filename' found"); + break; } } @@ -719,21 +686,27 @@ class TagFileParser : public QXmlDefaultHandler { switch (m_state) { - case InFile: m_curFile->path = m_curString; break; - case InDir: m_curDir->path = m_curString; break; - default: warn("Unexpected tag 'path' found"); break; + case InFile: + TagFileInfo::get(m_curCompound)->path = m_curString; + break; + case InDir: + TagDirInfo::get(m_curCompound)->path = m_curString; + break; + default: + warn("Unexpected tag 'path' found"); + break; } } - + void endAnchor() { if (m_state==InMember) { - m_curMember->anchor = m_curString; + m_curMember.anchor = m_curString; } else if (m_state==InClass) { - m_curClass->anchor = m_curString; + TagClassInfo::get(m_curCompound)->anchor = m_curString; } else { @@ -745,15 +718,15 @@ class TagFileParser : public QXmlDefaultHandler { if (m_state==InMember) { - m_curMember->clangId = m_curString; + m_curMember.clangId = m_curString; } else if (m_state==InClass) { - m_curClass->clangId = m_curString; + TagClassInfo::get(m_curCompound)->clangId = m_curString; } else if (m_state==InNamespace) { - m_curNamespace->clangId = m_curString; + TagNamespaceInfo::get(m_curCompound)->clangId = m_curString; } else { @@ -762,37 +735,44 @@ class TagFileParser : public QXmlDefaultHandler } - + void endAnchorFile() { if (m_state==InMember) { - m_curMember->anchorFile = m_curString; + m_curMember.anchorFile = m_curString; } else { warn("Unexpected tag 'anchorfile' found"); } } - + void endArglist() { if (m_state==InMember) { - m_curMember->arglist = m_curString; + m_curMember.arglist = m_curString; } else { warn("Unexpected tag 'arglist' found"); } } + void endTitle() { switch (m_state) { - case InGroup: m_curGroup->title = m_curString; break; - case InPage: m_curPage->title = m_curString; break; - default: warn("Unexpected tag 'title' found"); break; + case InGroup: + TagGroupInfo::get(m_curCompound)->title = m_curString; + break; + case InPage: + TagPageInfo::get(m_curCompound)->title = m_curString; + break; + default: + warn("Unexpected tag 'title' found"); + break; } } @@ -800,7 +780,7 @@ class TagFileParser : public QXmlDefaultHandler { if (m_state==InGroup) { - m_curGroup->subgroupList.append(m_curString); + TagGroupInfo::get(m_curCompound)->subgroupList.push_back(m_curString); } else { @@ -820,84 +800,71 @@ class TagFileParser : public QXmlDefaultHandler { m_state = Invalid; - m_curClass=0; - m_curNamespace=0; - m_curFile=0; - m_curGroup=0; - m_curPage=0; - m_curPackage=0; - m_curDir=0; - - m_stateStack.setAutoDelete(TRUE); - m_tagFileClasses.setAutoDelete(TRUE); - m_tagFileFiles.setAutoDelete(TRUE); - m_tagFileNamespaces.setAutoDelete(TRUE); - m_tagFileGroups.setAutoDelete(TRUE); - m_tagFilePages.setAutoDelete(TRUE); - m_tagFilePackages.setAutoDelete(TRUE); - m_tagFileDirs.setAutoDelete(TRUE); - - m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound)); - m_startElementHandlers.insert("member", new StartElementHandler(this,&TagFileParser::startMember)); - m_startElementHandlers.insert("enumvalue", new StartElementHandler(this,&TagFileParser::startEnumValue)); - m_startElementHandlers.insert("name", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("base", new StartElementHandler(this,&TagFileParser::startBase)); - m_startElementHandlers.insert("filename", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("includes", new StartElementHandler(this,&TagFileParser::startIncludes)); - m_startElementHandlers.insert("path", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("anchorfile", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("anchor", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("clangid", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("arglist", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("title", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("subgroup", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("class", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("namespace", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("file", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("dir", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startDocAnchor)); - m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement)); - m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue)); - m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue)); - - m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound)); - m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember)); - m_endElementHandlers.insert("enumvalue", new EndElementHandler(this,&TagFileParser::endEnumValue)); - m_endElementHandlers.insert("name", new EndElementHandler(this,&TagFileParser::endName)); - m_endElementHandlers.insert("base", new EndElementHandler(this,&TagFileParser::endBase)); - m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename)); - m_endElementHandlers.insert("includes", new EndElementHandler(this,&TagFileParser::endIncludes)); - m_endElementHandlers.insert("path", new EndElementHandler(this,&TagFileParser::endPath)); - m_endElementHandlers.insert("anchorfile", new EndElementHandler(this,&TagFileParser::endAnchorFile)); - m_endElementHandlers.insert("anchor", new EndElementHandler(this,&TagFileParser::endAnchor)); - m_endElementHandlers.insert("clangid", new EndElementHandler(this,&TagFileParser::endClangId)); - m_endElementHandlers.insert("arglist", new EndElementHandler(this,&TagFileParser::endArglist)); - m_endElementHandlers.insert("title", new EndElementHandler(this,&TagFileParser::endTitle)); - m_endElementHandlers.insert("subgroup", new EndElementHandler(this,&TagFileParser::endSubgroup)); - m_endElementHandlers.insert("class" , new EndElementHandler(this,&TagFileParser::endClass)); - m_endElementHandlers.insert("namespace", new EndElementHandler(this,&TagFileParser::endNamespace)); - m_endElementHandlers.insert("file", new EndElementHandler(this,&TagFileParser::endFile)); - m_endElementHandlers.insert("dir", new EndElementHandler(this,&TagFileParser::endDir)); - m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage)); - m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor)); - m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement)); - m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg)); - m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType)); + m_startElementHandlers.insert({ + { "compound", std::bind(&TagFileParser::startCompound, this, std::placeholders::_1) }, + { "member", std::bind(&TagFileParser::startMember, this, std::placeholders::_1) }, + { "enumvalue", std::bind(&TagFileParser::startEnumValue, this, std::placeholders::_1) }, + { "name", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "base", std::bind(&TagFileParser::startBase, this, std::placeholders::_1) }, + { "filename", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "includes", std::bind(&TagFileParser::startIncludes, this, std::placeholders::_1) }, + { "path", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "anchorfile", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "anchor", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "clangid", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "arglist", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "title", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "subgroup", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "class", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "namespace", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "file", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "dir", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "page", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "docanchor", std::bind(&TagFileParser::startDocAnchor, this, std::placeholders::_1) }, + { "tagfile", std::bind(&TagFileParser::startIgnoreElement,this, std::placeholders::_1) }, + { "templarg", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, + { "type", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) } + }); + + m_endElementHandlers.insert({ + { "compound", std::bind(&TagFileParser::endCompound, this) }, + { "member", std::bind(&TagFileParser::endMember, this) }, + { "enumvalue", std::bind(&TagFileParser::endEnumValue, this) }, + { "name", std::bind(&TagFileParser::endName, this) }, + { "base", std::bind(&TagFileParser::endBase, this) }, + { "filename", std::bind(&TagFileParser::endFilename, this) }, + { "includes", std::bind(&TagFileParser::endIncludes, this) }, + { "path", std::bind(&TagFileParser::endPath, this) }, + { "anchorfile", std::bind(&TagFileParser::endAnchorFile, this) }, + { "anchor", std::bind(&TagFileParser::endAnchor, this) }, + { "clangid", std::bind(&TagFileParser::endClangId, this) }, + { "arglist", std::bind(&TagFileParser::endArglist, this) }, + { "title", std::bind(&TagFileParser::endTitle, this) }, + { "subgroup", std::bind(&TagFileParser::endSubgroup, this) }, + { "class" , std::bind(&TagFileParser::endClass, this) }, + { "namespace", std::bind(&TagFileParser::endNamespace, this) }, + { "file", std::bind(&TagFileParser::endFile, this) }, + { "dir", std::bind(&TagFileParser::endDir, this) }, + { "page", std::bind(&TagFileParser::endPage, this) }, + { "docanchor", std::bind(&TagFileParser::endDocAnchor, this) }, + { "tagfile", std::bind(&TagFileParser::endIgnoreElement,this) }, + { "templarg", std::bind(&TagFileParser::endTemplateArg, this) }, + { "type", std::bind(&TagFileParser::endType, this) } + }); return TRUE; } - bool startElement( const QString&, const QString&, + bool startElement( const QString&, const QString&, const QString&name, const QXmlAttributes& attrib ) { //printf("startElement '%s'\n",name.data()); - StartElementHandler *handler = m_startElementHandlers[name.utf8()]; - if (handler) + auto it = m_startElementHandlers.find(name.utf8().str()); + if (it!=std::end(m_startElementHandlers)) { - (*handler)(attrib); + it->second(attrib); } - else + else { warn("Unknown tag '%s' found!",name.data()); } @@ -907,19 +874,19 @@ class TagFileParser : public QXmlDefaultHandler bool endElement( const QString&, const QString&, const QString& name ) { //printf("endElement '%s'\n",name.data()); - EndElementHandler *handler = m_endElementHandlers[name.utf8()]; - if (handler) + auto it = m_endElementHandlers.find(name.utf8().str()); + if (it!=std::end(m_endElementHandlers)) { - (*handler)(); + it->second(); } - else + else { warn("Unknown tag '%s' found!",name.data()); } return TRUE; } - bool characters ( const QString & ch ) + bool characters ( const QString & ch ) { m_curString+=ch.utf8(); return TRUE; @@ -928,40 +895,52 @@ class TagFileParser : public QXmlDefaultHandler void dump(); void buildLists(const std::shared_ptr<Entry> &root); void addIncludes(); - + private: - void buildMemberList(const std::shared_ptr<Entry> &ce,QList<TagMemberInfo> &members); - void addDocAnchors(const std::shared_ptr<Entry> &e,const TagAnchorInfoList &l); - QList<TagClassInfo> m_tagFileClasses; - QList<TagFileInfo> m_tagFileFiles; - QList<TagNamespaceInfo> m_tagFileNamespaces; - QList<TagGroupInfo> m_tagFileGroups; - QList<TagPageInfo> m_tagFilePages; - QList<TagPackageInfo> m_tagFilePackages; - QList<TagDirInfo> m_tagFileDirs; - QDict<StartElementHandler> m_startElementHandlers; - QDict<EndElementHandler> m_endElementHandlers; - TagClassInfo *m_curClass; - TagFileInfo *m_curFile; - TagNamespaceInfo *m_curNamespace; - TagPackageInfo *m_curPackage; - TagGroupInfo *m_curGroup; - TagPageInfo *m_curPage; - TagDirInfo *m_curDir; - TagMemberInfo *m_curMember; - TagEnumValueInfo *m_curEnumValue; - TagIncludeInfo *m_curIncludes; - QCString m_curString; + void buildMemberList(const std::shared_ptr<Entry> &ce,const std::vector<TagMemberInfo> &members); + void addDocAnchors(const std::shared_ptr<Entry> &e,const std::vector<TagAnchorInfo> &l); + std::vector< std::unique_ptr<TagCompoundInfo> > m_tagFileCompounds; + + std::map< std::string, std::function<void(const QXmlAttributes&)> > m_startElementHandlers; + std::map< std::string, std::function<void()> > m_endElementHandlers; + std::map< std::string, CompoundFactory > m_compoundFactory = + { + // kind tag state creation function + { "class", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Class); } } }, + { "struct", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Struct); } } }, + { "union", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Union); } } }, + { "interface", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Interface); } } }, + { "enum", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Enum); } } }, + { "exception", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Exception); } } }, + { "protocol", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Protocol); } } }, + { "category", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Category); } } }, + { "service", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Service); } } }, + { "singleton", { InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Singleton); } } }, + { "file", { InFile, []() { return std::make_unique<TagFileInfo>(); } } }, + { "namespace", { InNamespace, []() { return std::make_unique<TagNamespaceInfo>(); } } }, + { "group", { InGroup, []() { return std::make_unique<TagGroupInfo>(); } } }, + { "page", { InPage, []() { return std::make_unique<TagPageInfo>(); } } }, + { "package", { InPackage, []() { return std::make_unique<TagPackageInfo>(); } } }, + { "dir", { InDir, []() { return std::make_unique<TagDirInfo>(); } } } + }; + + std::unique_ptr<TagCompoundInfo> m_curCompound; + + TagMemberInfo m_curMember; + TagEnumValueInfo m_curEnumValue; + TagIncludeInfo m_curIncludes; + + std::string m_curString; QCString m_tagName; QCString m_fileName; QCString m_title; - State m_state; - QStack<State> m_stateStack; - QXmlLocator *m_locator; + State m_state = Invalid; + std::stack<State> m_stateStack; + QXmlLocator *m_locator = nullptr; QCString m_inputFileName; }; -/** Error handler for the XML tag file parser. +/** Error handler for the XML tag file parser. * * Basically dumps all fatal error to stderr using err(). */ @@ -994,300 +973,289 @@ class TagFileErrorHandler : public QXmlErrorHandler void TagFileParser::dump() { msg("Result:\n"); - QListIterator<TagClassInfo> lci(m_tagFileClasses); - //============== CLASSES - TagClassInfo *cd; - for (;(cd=lci.current());++lci) + for (const auto &comp : m_tagFileCompounds) { - msg("class '%s'\n",cd->name.data()); - msg(" filename '%s'\n",cd->filename.data()); - for (const BaseInfo &bi : cd->bases) + if (comp->compoundType()==TagCompoundInfo::CompoundType::Class) { - msg( " base: %s \n", bi.name.data() ); - } + const TagClassInfo *cd = TagClassInfo::get(comp); + msg("class '%s'\n",cd->name.data()); + msg(" filename '%s'\n",cd->filename.data()); + for (const BaseInfo &bi : cd->bases) + { + msg( " base: %s \n", bi.name.data() ); + } - QListIterator<TagMemberInfo> mci(cd->members); - TagMemberInfo *md; - for (;(md=mci.current());++mci) - { - msg(" member:\n"); - msg(" kind: '%s'\n",md->kind.data()); - msg(" name: '%s'\n",md->name.data()); - msg(" anchor: '%s'\n",md->anchor.data()); - msg(" arglist: '%s'\n",md->arglist.data()); + for (const auto &md : cd->members) + { + msg(" member:\n"); + msg(" kind: '%s'\n",md.kind.data()); + msg(" name: '%s'\n",md.name.data()); + msg(" anchor: '%s'\n",md.anchor.data()); + msg(" arglist: '%s'\n",md.arglist.data()); + } } } //============== NAMESPACES - QListIterator<TagNamespaceInfo> lni(m_tagFileNamespaces); - TagNamespaceInfo *nd; - for (;(nd=lni.current());++lni) + for (const auto &comp : m_tagFileCompounds) { - msg("namespace '%s'\n",nd->name.data()); - msg(" filename '%s'\n",nd->filename.data()); - QCStringList::Iterator it; - for ( it = nd->classList.begin(); - it != nd->classList.end(); ++it ) + if (comp->compoundType()==TagCompoundInfo::CompoundType::Namespace) { - msg( " class: %s \n", (*it).data() ); - } + const TagNamespaceInfo *nd = TagNamespaceInfo::get(comp); - QListIterator<TagMemberInfo> mci(nd->members); - TagMemberInfo *md; - for (;(md=mci.current());++mci) - { - msg(" member:\n"); - msg(" kind: '%s'\n",md->kind.data()); - msg(" name: '%s'\n",md->name.data()); - msg(" anchor: '%s'\n",md->anchor.data()); - msg(" arglist: '%s'\n",md->arglist.data()); + msg("namespace '%s'\n",nd->name.data()); + msg(" filename '%s'\n",nd->filename.data()); + for (const auto &cls : nd->classList) + { + msg( " class: %s \n", cls.c_str() ); + } + + for (const auto &md : nd->members) + { + msg(" member:\n"); + msg(" kind: '%s'\n",md.kind.data()); + msg(" name: '%s'\n",md.name.data()); + msg(" anchor: '%s'\n",md.anchor.data()); + msg(" arglist: '%s'\n",md.arglist.data()); + } } } + //============== FILES - QListIterator<TagFileInfo> lfi(m_tagFileFiles); - TagFileInfo *fd; - for (;(fd=lfi.current());++lfi) + for (const auto &comp : m_tagFileCompounds) { - msg("file '%s'\n",fd->name.data()); - msg(" filename '%s'\n",fd->filename.data()); - QCStringList::Iterator it; - for ( it = fd->namespaceList.begin(); - it != fd->namespaceList.end(); ++it ) - { - msg( " namespace: %s \n", (*it).data() ); - } - for ( it = fd->classList.begin(); - it != fd->classList.end(); ++it ) + if (comp->compoundType()==TagCompoundInfo::CompoundType::File) { - msg( " class: %s \n", (*it).data() ); - } + const TagFileInfo *fd = TagFileInfo::get(comp); - QListIterator<TagMemberInfo> mci(fd->members); - TagMemberInfo *md; - for (;(md=mci.current());++mci) - { - msg(" member:\n"); - msg(" kind: '%s'\n",md->kind.data()); - msg(" name: '%s'\n",md->name.data()); - msg(" anchor: '%s'\n",md->anchor.data()); - msg(" arglist: '%s'\n",md->arglist.data()); - } + msg("file '%s'\n",fd->name.data()); + msg(" filename '%s'\n",fd->filename.data()); + for (const auto &ns : fd->namespaceList) + { + msg( " namespace: %s \n", ns.c_str() ); + } + for (const auto &cs : fd->classList) + { + msg( " class: %s \n", cs.c_str() ); + } - QListIterator<TagIncludeInfo> mii(fd->includes); - TagIncludeInfo *ii; - for (;(ii=mii.current());++mii) - { - msg(" includes id: %s name: %s\n",ii->id.data(),ii->name.data()); + for (const auto &md : fd->members) + { + msg(" member:\n"); + msg(" kind: '%s'\n",md.kind.data()); + msg(" name: '%s'\n",md.name.data()); + msg(" anchor: '%s'\n",md.anchor.data()); + msg(" arglist: '%s'\n",md.arglist.data()); + } + + for (const auto &ii : fd->includes) + { + msg(" includes id: %s name: %s\n",ii.id.data(),ii.name.data()); + } } } //============== GROUPS - QListIterator<TagGroupInfo> lgi(m_tagFileGroups); - TagGroupInfo *gd; - for (;(gd=lgi.current());++lgi) + for (const auto &comp : m_tagFileCompounds) { - msg("group '%s'\n",gd->name.data()); - msg(" filename '%s'\n",gd->filename.data()); - QCStringList::Iterator it; - for ( it = gd->namespaceList.begin(); - it != gd->namespaceList.end(); ++it ) - { - msg( " namespace: %s \n", (*it).data() ); - } - for ( it = gd->classList.begin(); - it != gd->classList.end(); ++it ) - { - msg( " class: %s \n", (*it).data() ); - } - for ( it = gd->fileList.begin(); - it != gd->fileList.end(); ++it ) + if (comp->compoundType()==TagCompoundInfo::CompoundType::Group) { - msg( " file: %s \n", (*it).data() ); - } - for ( it = gd->subgroupList.begin(); - it != gd->subgroupList.end(); ++it ) - { - msg( " subgroup: %s \n", (*it).data() ); - } - for ( it = gd->pageList.begin(); - it != gd->pageList.end(); ++it ) - { - msg( " page: %s \n", (*it).data() ); - } + const TagGroupInfo *gd = TagGroupInfo::get(comp); + msg("group '%s'\n",gd->name.data()); + msg(" filename '%s'\n",gd->filename.data()); - QListIterator<TagMemberInfo> mci(gd->members); - TagMemberInfo *md; - for (;(md=mci.current());++mci) - { - msg(" member:\n"); - msg(" kind: '%s'\n",md->kind.data()); - msg(" name: '%s'\n",md->name.data()); - msg(" anchor: '%s'\n",md->anchor.data()); - msg(" arglist: '%s'\n",md->arglist.data()); + for (const auto &ns : gd->namespaceList) + { + msg( " namespace: %s \n", ns.c_str() ); + } + for (const auto &cs : gd->classList) + { + msg( " class: %s \n", cs.c_str() ); + } + for (const auto &fi : gd->fileList) + { + msg( " file: %s \n", fi.c_str() ); + } + for (const auto &sg : gd->subgroupList) + { + msg( " subgroup: %s \n", sg.c_str() ); + } + for (const auto &pg : gd->pageList) + { + msg( " page: %s \n", pg.c_str() ); + } + + for (const auto &md : gd->members) + { + msg(" member:\n"); + msg(" kind: '%s'\n",md.kind.data()); + msg(" name: '%s'\n",md.name.data()); + msg(" anchor: '%s'\n",md.anchor.data()); + msg(" arglist: '%s'\n",md.arglist.data()); + } } } + //============== PAGES - QListIterator<TagPageInfo> lpi(m_tagFilePages); - TagPageInfo *pd; - for (;(pd=lpi.current());++lpi) + for (const auto &comp : m_tagFileCompounds) { - msg("page '%s'\n",pd->name.data()); - msg(" title '%s'\n",pd->title.data()); - msg(" filename '%s'\n",pd->filename.data()); + if (comp->compoundType()==TagCompoundInfo::CompoundType::Page) + { + const TagPageInfo *pd = TagPageInfo::get(comp); + msg("page '%s'\n",pd->name.data()); + msg(" title '%s'\n",pd->title.data()); + msg(" filename '%s'\n",pd->filename.data()); + } } + //============== DIRS - QListIterator<TagDirInfo> ldi(m_tagFileDirs); - TagDirInfo *dd; - for (;(dd=ldi.current());++ldi) + for (const auto &comp : m_tagFileCompounds) { - msg("dir '%s'\n",dd->name.data()); - msg(" path '%s'\n",dd->path.data()); - QCStringList::Iterator it; - for ( it = dd->fileList.begin(); - it != dd->fileList.end(); ++it ) - { - msg( " file: %s \n", (*it).data() ); - } - for ( it = dd->subdirList.begin(); - it != dd->subdirList.end(); ++it ) + if (comp->compoundType()==TagCompoundInfo::CompoundType::Dir) { - msg( " subdir: %s \n", (*it).data() ); + const TagDirInfo *dd = TagDirInfo::get(comp); + { + msg("dir '%s'\n",dd->name.data()); + msg(" path '%s'\n",dd->path.data()); + for (const auto &fi : dd->fileList) + { + msg( " file: %s \n", fi.c_str() ); + } + for (const auto &sd : dd->subdirList) + { + msg( " subdir: %s \n", sd.c_str() ); + } + } } } } -void TagFileParser::addDocAnchors(const std::shared_ptr<Entry> &e,const TagAnchorInfoList &l) +void TagFileParser::addDocAnchors(const std::shared_ptr<Entry> &e,const std::vector<TagAnchorInfo> &l) { - QListIterator<TagAnchorInfo> tli(l); - TagAnchorInfo *ta; - for (tli.toFirst();(ta=tli.current());++tli) + for (const auto &ta : l) { - if (Doxygen::sectionDict->find(ta->label)==0) + if (SectionManager::instance().find(ta.label)==0) { //printf("New sectionInfo file=%s anchor=%s\n", // ta->fileName.data(),ta->label.data()); - SectionInfo *si=new SectionInfo(ta->fileName,-1,ta->label,ta->title, - SectionInfo::Anchor,0,m_tagName); - Doxygen::sectionDict->append(ta->label,si); + SectionInfo *si=SectionManager::instance().add( + ta.label,ta.fileName,-1,ta.title, + SectionType::Anchor,0,m_tagName); e->anchors.push_back(si); } else { - warn("Duplicate anchor %s found",ta->label.data()); + warn("Duplicate anchor %s found",ta.label.data()); } } } -void TagFileParser::buildMemberList(const std::shared_ptr<Entry> &ce,QList<TagMemberInfo> &members) +void TagFileParser::buildMemberList(const std::shared_ptr<Entry> &ce,const std::vector<TagMemberInfo> &members) { - QListIterator<TagMemberInfo> mii(members); - TagMemberInfo *tmi; - for (;(tmi=mii.current());++mii) + for (const auto &tmi : members) { std::shared_ptr<Entry> me = std::make_shared<Entry>(); - me->type = tmi->type; - me->name = tmi->name; - me->args = tmi->arglist; + me->type = tmi.type; + me->name = tmi.name; + me->args = tmi.arglist; if (!me->args.isEmpty()) { - stringToArgumentList(SrcLangExt_Cpp,me->args,me->argList); + me->argList = *stringToArgumentList(SrcLangExt_Cpp,me->args); } - if (tmi->enumValues.count()>0) + if (tmi.enumValues.size()>0) { me->spec |= Entry::Strong; - QListIterator<TagEnumValueInfo> evii(tmi->enumValues); - TagEnumValueInfo *evi; - for (evii.toFirst();(evi=evii.current());++evii) + for (const auto &evi : tmi.enumValues) { std::shared_ptr<Entry> ev = std::make_shared<Entry>(); ev->type = "@"; - ev->name = evi->name; - ev->id = evi->clangid; + ev->name = evi.name; + ev->id = evi.clangid; ev->section = Entry::VARIABLE_SEC; ev->tagInfoData.tagName = m_tagName; - ev->tagInfoData.anchor = evi->anchor; - ev->tagInfoData.fileName = evi->file; + ev->tagInfoData.anchor = evi.anchor; + ev->tagInfoData.fileName = evi.file; ev->hasTagInfo = TRUE; me->moveToSubEntryAndKeep(ev); } } - me->protection = tmi->prot; - me->virt = tmi->virt; - me->stat = tmi->isStatic; + me->protection = tmi.prot; + me->virt = tmi.virt; + me->stat = tmi.isStatic; me->fileName = ce->fileName; - me->id = tmi->clangId; + me->id = tmi.clangId; if (ce->section == Entry::GROUPDOC_SEC) { me->groups.push_back(Grouping(ce->name,Grouping::GROUPING_INGROUP)); } - addDocAnchors(me,tmi->docAnchors); + addDocAnchors(me,tmi.docAnchors); me->tagInfoData.tagName = m_tagName; - me->tagInfoData.anchor = tmi->anchor; - me->tagInfoData.fileName = tmi->anchorFile; + me->tagInfoData.anchor = tmi.anchor; + me->tagInfoData.fileName = tmi.anchorFile; me->hasTagInfo = TRUE; - if (tmi->kind=="define") + if (tmi.kind=="define") { me->type="#define"; me->section = Entry::DEFINE_SEC; } - else if (tmi->kind=="enumvalue") + else if (tmi.kind=="enumvalue") { me->section = Entry::VARIABLE_SEC; me->mtype = Method; } - else if (tmi->kind=="property") + else if (tmi.kind=="property") { me->section = Entry::VARIABLE_SEC; me->mtype = Property; } - else if (tmi->kind=="event") + else if (tmi.kind=="event") { me->section = Entry::VARIABLE_SEC; me->mtype = Event; } - else if (tmi->kind=="variable") + else if (tmi.kind=="variable") { me->section = Entry::VARIABLE_SEC; me->mtype = Method; } - else if (tmi->kind=="typedef") + else if (tmi.kind=="typedef") { me->section = Entry::VARIABLE_SEC; //Entry::TYPEDEF_SEC; me->type.prepend("typedef "); me->mtype = Method; } - else if (tmi->kind=="enumeration") + else if (tmi.kind=="enumeration") { me->section = Entry::ENUM_SEC; me->mtype = Method; } - else if (tmi->kind=="function") + else if (tmi.kind=="function") { me->section = Entry::FUNCTION_SEC; me->mtype = Method; } - else if (tmi->kind=="signal") + else if (tmi.kind=="signal") { me->section = Entry::FUNCTION_SEC; me->mtype = Signal; } - else if (tmi->kind=="prototype") + else if (tmi.kind=="prototype") { me->section = Entry::FUNCTION_SEC; me->mtype = Method; } - else if (tmi->kind=="friend") + else if (tmi.kind=="friend") { me->section = Entry::FUNCTION_SEC; me->type.prepend("friend "); me->mtype = Method; } - else if (tmi->kind=="dcop") + else if (tmi.kind=="dcop") { me->section = Entry::FUNCTION_SEC; me->mtype = DCOP; } - else if (tmi->kind=="slot") + else if (tmi.kind=="slot") { me->section = Entry::FUNCTION_SEC; me->mtype = Slot; @@ -1310,230 +1278,238 @@ static QCString stripPath(const QCString &s) } /*! Injects the info gathered by the XML parser into the Entry tree. - * This tree contains the information extracted from the input in a + * This tree contains the information extracted from the input in a * "unrelated" form. */ void TagFileParser::buildLists(const std::shared_ptr<Entry> &root) { // build class list - QListIterator<TagClassInfo> cit(m_tagFileClasses); - TagClassInfo *tci; - for (cit.toFirst();(tci=cit.current());++cit) + for (const auto &comp : m_tagFileCompounds) { - std::shared_ptr<Entry> ce = std::make_shared<Entry>(); - ce->section = Entry::CLASS_SEC; - switch (tci->kind) - { - case TagClassInfo::Class: break; - case TagClassInfo::Struct: ce->spec = Entry::Struct; break; - case TagClassInfo::Union: ce->spec = Entry::Union; break; - case TagClassInfo::Interface: ce->spec = Entry::Interface; break; - case TagClassInfo::Enum: ce->spec = Entry::Enum; break; - case TagClassInfo::Exception: ce->spec = Entry::Exception; break; - case TagClassInfo::Protocol: ce->spec = Entry::Protocol; break; - case TagClassInfo::Category: ce->spec = Entry::Category; break; - case TagClassInfo::Service: ce->spec = Entry::Service; break; - case TagClassInfo::Singleton: ce->spec = Entry::Singleton; break; - case TagClassInfo::None: // should never happen, means not properly initialized - assert(tci->kind != TagClassInfo::None); - break; - } - ce->name = tci->name; - if (tci->kind==TagClassInfo::Protocol) - { - ce->name+="-p"; - } - addDocAnchors(ce,tci->docAnchors); - ce->tagInfoData.tagName = m_tagName; - ce->tagInfoData.anchor = tci->anchor; - ce->tagInfoData.fileName = tci->filename; - ce->hasTagInfo = TRUE; - ce->id = tci->clangId; - ce->lang = tci->isObjC ? SrcLangExt_ObjC : SrcLangExt_Unknown; - // transfer base class list - ce->extends = tci->bases; - tci->bases.clear(); - if (tci->templateArguments) - { - ArgumentList al; - QListIterator<QCString> sli(*tci->templateArguments); - QCString *argName; - for (;(argName=sli.current());++sli) - { - Argument a; - a.type = "class"; - a.name = *argName; - al.push_back(a); - } - ce->tArgLists.push_back(al); - } - - buildMemberList(ce,tci->members); - root->moveToSubEntryAndKeep(ce); + if (comp->compoundType()==TagCompoundInfo::CompoundType::Class) + { + const TagClassInfo *tci = TagClassInfo::get(comp); + std::shared_ptr<Entry> ce = std::make_shared<Entry>(); + ce->section = Entry::CLASS_SEC; + switch (tci->kind) + { + case TagClassInfo::Kind::Class: break; + case TagClassInfo::Kind::Struct: ce->spec = Entry::Struct; break; + case TagClassInfo::Kind::Union: ce->spec = Entry::Union; break; + case TagClassInfo::Kind::Interface: ce->spec = Entry::Interface; break; + case TagClassInfo::Kind::Enum: ce->spec = Entry::Enum; break; + case TagClassInfo::Kind::Exception: ce->spec = Entry::Exception; break; + case TagClassInfo::Kind::Protocol: ce->spec = Entry::Protocol; break; + case TagClassInfo::Kind::Category: ce->spec = Entry::Category; break; + case TagClassInfo::Kind::Service: ce->spec = Entry::Service; break; + case TagClassInfo::Kind::Singleton: ce->spec = Entry::Singleton; break; + case TagClassInfo::Kind::None: // should never happen, means not properly initialized + assert(tci->kind != TagClassInfo::Kind::None); + break; + } + ce->name = tci->name; + if (tci->kind==TagClassInfo::Kind::Protocol) + { + ce->name+="-p"; + } + addDocAnchors(ce,tci->docAnchors); + ce->tagInfoData.tagName = m_tagName; + ce->tagInfoData.anchor = tci->anchor; + ce->tagInfoData.fileName = tci->filename; + ce->hasTagInfo = TRUE; + ce->id = tci->clangId; + ce->lang = tci->isObjC ? SrcLangExt_ObjC : SrcLangExt_Unknown; + // transfer base class list + ce->extends = tci->bases; + if (!tci->templateArguments.empty()) + { + ArgumentList al; + for (const auto &argName : tci->templateArguments) + { + Argument a; + a.type = "class"; + a.name = argName.c_str(); + al.push_back(a); + } + ce->tArgLists.push_back(al); + } + + buildMemberList(ce,tci->members); + root->moveToSubEntryAndKeep(ce); + } } // build file list - QListIterator<TagFileInfo> fit(m_tagFileFiles); - TagFileInfo *tfi; - for (fit.toFirst();(tfi=fit.current());++fit) + for (const auto &comp : m_tagFileCompounds) { - std::shared_ptr<Entry> fe = std::make_shared<Entry>(); - fe->section = guessSection(tfi->name); - fe->name = tfi->name; - addDocAnchors(fe,tfi->docAnchors); - fe->tagInfoData.tagName = m_tagName; - fe->tagInfoData.fileName = tfi->filename; - fe->hasTagInfo = TRUE; - - QCString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name); - fe->fileName = fullName; - //printf("createFileDef() filename=%s\n",tfi->filename.data()); - FileDef *fd = createFileDef(m_tagName+":"+tfi->path, - tfi->name,m_tagName, - tfi->filename - ); - FileName *mn; - if ((mn=Doxygen::inputNameDict->find(tfi->name))) - { - mn->append(fd); - } - else + if (comp->compoundType()==TagCompoundInfo::CompoundType::File) { - mn = new FileName(fullName,tfi->name); - mn->append(fd); - Doxygen::inputNameList->inSort(mn); - Doxygen::inputNameDict->insert(tfi->name,mn); + const TagFileInfo *tfi = TagFileInfo::get(comp); + + std::shared_ptr<Entry> fe = std::make_shared<Entry>(); + fe->section = guessSection(tfi->name); + fe->name = tfi->name; + addDocAnchors(fe,tfi->docAnchors); + fe->tagInfoData.tagName = m_tagName; + fe->tagInfoData.fileName = tfi->filename; + fe->hasTagInfo = TRUE; + + QCString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name); + fe->fileName = fullName; + //printf("createFileDef() filename=%s\n",tfi->filename.data()); + std::unique_ptr<FileDef> fd { createFileDef(m_tagName+":"+tfi->path, + tfi->name,m_tagName, + tfi->filename) }; + FileName *mn; + if ((mn=Doxygen::inputNameLinkedMap->find(tfi->name))) + { + mn->push_back(std::move(fd)); + } + else + { + mn = Doxygen::inputNameLinkedMap->add(tfi->name,fullName); + mn->push_back(std::move(fd)); + } + buildMemberList(fe,tfi->members); + root->moveToSubEntryAndKeep(fe); } - buildMemberList(fe,tfi->members); - root->moveToSubEntryAndKeep(fe); } // build namespace list - QListIterator<TagNamespaceInfo> nit(m_tagFileNamespaces); - TagNamespaceInfo *tni; - for (nit.toFirst();(tni=nit.current());++nit) + for (const auto &comp : m_tagFileCompounds) { - std::shared_ptr<Entry> ne = std::make_shared<Entry>(); - ne->section = Entry::NAMESPACE_SEC; - ne->name = tni->name; - addDocAnchors(ne,tni->docAnchors); - ne->tagInfoData.tagName = m_tagName; - ne->tagInfoData.fileName = tni->filename; - ne->hasTagInfo = TRUE; - ne->id = tni->clangId; - - buildMemberList(ne,tni->members); - root->moveToSubEntryAndKeep(ne); + if (comp->compoundType()==TagCompoundInfo::CompoundType::Namespace) + { + const TagNamespaceInfo *tni = TagNamespaceInfo::get(comp); + + std::shared_ptr<Entry> ne = std::make_shared<Entry>(); + ne->section = Entry::NAMESPACE_SEC; + ne->name = tni->name; + addDocAnchors(ne,tni->docAnchors); + ne->tagInfoData.tagName = m_tagName; + ne->tagInfoData.fileName = tni->filename; + ne->hasTagInfo = TRUE; + ne->id = tni->clangId; + + buildMemberList(ne,tni->members); + root->moveToSubEntryAndKeep(ne); + } } // build package list - QListIterator<TagPackageInfo> pit(m_tagFilePackages); - TagPackageInfo *tpgi; - for (pit.toFirst();(tpgi=pit.current());++pit) + for (const auto &comp : m_tagFileCompounds) { - std::shared_ptr<Entry> pe = std::make_shared<Entry>(); - pe->section = Entry::PACKAGE_SEC; - pe->name = tpgi->name; - addDocAnchors(pe,tpgi->docAnchors); - pe->tagInfoData.tagName = m_tagName; - pe->tagInfoData.fileName = tpgi->filename; - pe->hasTagInfo = TRUE; - - buildMemberList(pe,tpgi->members); - root->moveToSubEntryAndKeep(pe); + if (comp->compoundType()==TagCompoundInfo::CompoundType::Package) + { + const TagPackageInfo *tpgi = TagPackageInfo::get(comp); + + std::shared_ptr<Entry> pe = std::make_shared<Entry>(); + pe->section = Entry::PACKAGE_SEC; + pe->name = tpgi->name; + addDocAnchors(pe,tpgi->docAnchors); + pe->tagInfoData.tagName = m_tagName; + pe->tagInfoData.fileName = tpgi->filename; + pe->hasTagInfo = TRUE; + + buildMemberList(pe,tpgi->members); + root->moveToSubEntryAndKeep(pe); + } } // build group list - QListIterator<TagGroupInfo> git(m_tagFileGroups); - TagGroupInfo *tgi; - for (git.toFirst();(tgi=git.current());++git) + for (const auto &comp : m_tagFileCompounds) { - std::shared_ptr<Entry> ge = std::make_shared<Entry>(); - ge->section = Entry::GROUPDOC_SEC; - ge->name = tgi->name; - ge->type = tgi->title; - addDocAnchors(ge,tgi->docAnchors); - ge->tagInfoData.tagName = m_tagName; - ge->tagInfoData.fileName = tgi->filename; - ge->hasTagInfo = TRUE; - - buildMemberList(ge,tgi->members); - root->moveToSubEntryAndKeep(ge); + if (comp->compoundType()==TagCompoundInfo::CompoundType::Group) + { + const TagGroupInfo *tgi = TagGroupInfo::get(comp); + + std::shared_ptr<Entry> ge = std::make_shared<Entry>(); + ge->section = Entry::GROUPDOC_SEC; + ge->name = tgi->name; + ge->type = tgi->title; + addDocAnchors(ge,tgi->docAnchors); + ge->tagInfoData.tagName = m_tagName; + ge->tagInfoData.fileName = tgi->filename; + ge->hasTagInfo = TRUE; + + buildMemberList(ge,tgi->members); + root->moveToSubEntryAndKeep(ge); + } } - // set subgroup relations bug_774118 - for (git.toFirst();(tgi=git.current());++git) + for (const auto &comp : m_tagFileCompounds) { - QCStringList::Iterator it; - for ( it = tgi->subgroupList.begin(); it != tgi->subgroupList.end(); ++it ) + if (comp->compoundType()==TagCompoundInfo::CompoundType::Group) { - //QListIterator<Entry> eli(*(root->children())); - //Entry *childNode; - //for (eli.toFirst();(childNode=eli.current());++eli) - const auto &children = root->children(); - auto i = std::find_if(children.begin(),children.end(), - [&](const std::shared_ptr<Entry> &e) { return e->name = *it; }); - if (i!=children.end()) + const TagGroupInfo *tgi = TagGroupInfo::get(comp); + // set subgroup relations bug_774118 + + for (const auto &sg : tgi->subgroupList) { - (*i)->groups.push_back(Grouping(tgi->name,Grouping::GROUPING_INGROUP)); + const auto &children = root->children(); + auto i = std::find_if(children.begin(),children.end(), + [&](const std::shared_ptr<Entry> &e) { return e->name == sg.c_str(); }); + if (i!=children.end()) + { + (*i)->groups.push_back(Grouping(tgi->name,Grouping::GROUPING_INGROUP)); + } } } } // build page list - QListIterator<TagPageInfo> pgit(m_tagFilePages); - TagPageInfo *tpi; - for (pgit.toFirst();(tpi=pgit.current());++pgit) + for (const auto &comp : m_tagFileCompounds) { - std::shared_ptr<Entry> pe = std::make_shared<Entry>(); - pe->section = tpi->filename=="index" ? Entry::MAINPAGEDOC_SEC : Entry::PAGEDOC_SEC; - pe->name = tpi->name; - pe->args = tpi->title; - addDocAnchors(pe,tpi->docAnchors); - pe->tagInfoData.tagName = m_tagName; - pe->tagInfoData.fileName = tpi->filename; - pe->hasTagInfo = TRUE; - root->moveToSubEntryAndKeep(pe); + if (comp->compoundType()==TagCompoundInfo::CompoundType::Page) + { + const TagPageInfo *tpi = TagPageInfo::get(comp); + + std::shared_ptr<Entry> pe = std::make_shared<Entry>(); + bool isIndex = (stripExtensionGeneral(tpi->filename,getFileNameExtension(tpi->filename))=="index"); + pe->section = isIndex ? Entry::MAINPAGEDOC_SEC : Entry::PAGEDOC_SEC; + pe->name = tpi->name; + pe->args = tpi->title; + addDocAnchors(pe,tpi->docAnchors); + pe->tagInfoData.tagName = m_tagName; + pe->tagInfoData.fileName = tpi->filename; + pe->hasTagInfo = TRUE; + root->moveToSubEntryAndKeep(pe); + } } } void TagFileParser::addIncludes() { - QListIterator<TagFileInfo> fit(m_tagFileFiles); - TagFileInfo *tfi; - for (fit.toFirst();(tfi=fit.current());++fit) + for (const auto &comp : m_tagFileCompounds) { - //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data()); - FileName *fn = Doxygen::inputNameDict->find(tfi->name); - if (fn) + if (comp->compoundType()==TagCompoundInfo::CompoundType::File) { - //printf("found\n"); - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + const TagFileInfo *tfi = TagFileInfo::get(comp); + //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data()); + FileName *fn = Doxygen::inputNameLinkedMap->find(tfi->name); + if (fn) { - //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data()); - if (fd->getPath()==QCString(m_tagName+":"+tfi->path)) + for (const auto &fd : *fn) { - //printf("found\n"); - QListIterator<TagIncludeInfo> mii(tfi->includes); - TagIncludeInfo *ii; - for (;(ii=mii.current());++mii) + //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data()); + if (fd->getPath()==QCString(m_tagName+":"+tfi->path)) { - //printf("ii->name='%s'\n",ii->name.data()); - FileName *ifn = Doxygen::inputNameDict->find(ii->name); - ASSERT(ifn!=0); - if (ifn) + //printf("found\n"); + for (const auto &ii : tfi->includes) { - FileNameIterator ifni(*ifn); - FileDef *ifd; - for (;(ifd=ifni.current());++ifni) + //printf("ii->name='%s'\n",ii->name.data()); + FileName *ifn = Doxygen::inputNameLinkedMap->find(ii.name); + ASSERT(ifn!=0); + if (ifn) { - //printf("ifd->getOutputFileBase()=%s ii->id=%s\n", - // ifd->getOutputFileBase().data(),ii->id.data()); - if (ifd->getOutputFileBase()==QCString(ii->id)) + for (const auto &ifd : *ifn) { - fd->addIncludeDependency(ifd,ii->text,ii->isLocal,ii->isImported,FALSE); + //printf("ifd->getOutputFileBase()=%s ii->id=%s\n", + // ifd->getOutputFileBase().data(),ii->id.data()); + if (ifd->getOutputFileBase()==QCString(ii.id)) + { + fd->addIncludeDependency(ifd.get(),ii.text,ii.isLocal,ii.isImported); + } } } } @@ -1561,5 +1537,3 @@ void parseTagFile(const std::shared_ptr<Entry> &root,const char *fullName) handler.addIncludes(); //handler.dump(); } - - diff --git a/src/tclscanner.h b/src/tclscanner.h deleted file mode 100644 index cdd56d8..0000000 --- a/src/tclscanner.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * Copyright (C) 2010-2011 by Rene Zaumseil - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#ifndef SCANNER_TCL_H -#define SCANNER_TCL_H - -#include "parserintf.h" - -/** \brief Tcl language parser using state-based lexical scanning. - * - * This is the Tcl language parser for doxygen. - */ -class TclOutlineParser : public OutlineParserInterface -{ - public: - void startTranslationUnit(const char *) {} - void finishTranslationUnit() {} - void parseInput(const char *fileName, - const char *fileBuf, - const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList &filesInSameTranslationUnit); - bool needsPreprocessing(const QCString &extension) const; - void parsePrototype(const char *text); -}; - -class TclCodeParser : public CodeParserInterface -{ - public: - void parseCode(CodeOutputInterface &codeOutIntf, - const char *scopeName, - const QCString &input, - SrcLangExt lang, - bool isExampleBlock, - const char *exampleName=0, - FileDef *fileDef=0, - int startLine=-1, - int endLine=-1, - bool inlineFragment=FALSE, - const MemberDef *memberDef=0, - bool showLineNumbers=TRUE, - const Definition *searchCtx=0, - bool collectXRefs=TRUE - ); - void resetCodeParserState(); -}; - -#endif diff --git a/src/tclscanner.l b/src/tclscanner.l deleted file mode 100644 index a4709ce..0000000 --- a/src/tclscanner.l +++ /dev/null @@ -1,3143 +0,0 @@ -/***************************************************************************** - * Parser for Tcl subset - * - * Copyright (C) 2010 by Rene Zaumseil - * based on the work of Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ -%option never-interactive -%option case-insensitive -%option prefix="tclscannerYY" - -%{ -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <ctype.h> - -#include <qstring.h> -#include <qcstringlist.h> -#include <qlist.h> -#include <qmap.h> -#include <qarray.h> -#include <qstack.h> -#include <qregexp.h> -#include <qfile.h> -#include <qdict.h> - -#include "entry.h" -#include "message.h" -#include "config.h" -#include "doxygen.h" -#include "util.h" -#include "defargs.h" -#include "language.h" -#include "commentscan.h" -#include "pre.h" -#include "tclscanner.h" -#include "outputlist.h" -#include "membername.h" -#include "searchindex.h" -#include "commentcnv.h" -#include "bufstr.h" -#include "portable.h" -#include "arguments.h" -#include "namespacedef.h" -#include "filedef.h" - -#define YY_NO_INPUT 1 -#define YY_NO_UNISTD_H 1 - -#define MAX_INCLUDE_DEPTH 10 - -static const char *stateToString(int state); - -//! Application error. -#define tcl_err \ - printf("Error %d %s() at line %d! ",__LINE__,tcl.file_name.data(),yylineno); \ - yy_push_state(ERROR); \ - yyless(0); \ - printf - -//! Application warning. -#define tcl_war \ - printf("Warning %d %s() at line %d: ",__LINE__,tcl.file_name.data(),yylineno); \ - printf - -//! Application message. -#define tcl_inf \ - if (0) printf("--- %.4d %d@%d: ",__LINE__,yylineno,yy_start_stack_ptr) && printf - -//! Debug message. -#define D\ - if (0) printf("--- %.4d %d@%d: %s\n",__LINE__,yylineno,yy_start_stack_ptr,yytext); - -// BEGIN of copy from tclUtil.c -// - Tcl_Interp removed -// - changes are marked with RZ -// #define's to adapt the code: -#define CONST const -#define UCHAR (unsigned char) -#define TCL_ERROR 1 -#define TCL_OK 0 -#define ckalloc malloc -#define ckfree free -#define TclCopyAndCollapse(size,src,dest) memcpy(dest,src,size); *(dest+size)=0 -int TclFindElement( - CONST char *list, /* Points to the first byte of a string - * containing a Tcl list with zero or more - * elements (possibly in braces). */ - int listLength, /* Number of bytes in the list's string. */ - CONST char **elementPtr, /* Where to put address of first significant - * character in first element of list. */ - CONST char **nextPtr, /* Fill in with location of character just - * after all white space following end of - * argument (next arg or end of list). */ - int *sizePtr, /* If non-zero, fill in with size of - * element. */ - int *bracePtr) /* If non-zero, fill in with non-zero/zero to - * indicate that arg was/wasn't in braces. */ -{ - CONST char *p = list; - CONST char *elemStart; /* Points to first byte of first element. */ - CONST char *limit; /* Points just after list's last byte. */ - int openBraces = 0; /* Brace nesting level during parse. */ - int inQuotes = 0; - int size = 0; /* lint. */ - //RZ int numChars; - - /* - * Skim off leading white space and check for an opening brace or quote. - * We treat embedded NULLs in the list as bytes belonging to a list - * element. - */ - - limit = (list + listLength); - while ((p < limit) && (isspace(UCHAR(*p)))) - { /* INTL: ISO space. */ - p++; - } - if (p == limit) - { /* no element found */ - elemStart = limit; - goto done; - } - - if (*p == '{') /* } to keep vi happy */ - { - openBraces = 1; - p++; - } - else if (*p == '"') - { - inQuotes = 1; - p++; - } - elemStart = p; - if (bracePtr != 0) - { - *bracePtr = openBraces; - } - - /* - * Find element's end (a space, close brace, or the end of the string). - */ - - while (p < limit) - { - switch (*p) - { - /* - * Open brace: don't treat specially unless the element is in - * braces. In this case, keep a nesting count. - */ - - case '{': - if (openBraces != 0) - { - openBraces++; - } - break; - - /* - * Close brace: if element is in braces, keep nesting count and - * quit when the last close brace is seen. - */ - - case '}': - if (openBraces > 1) - { - openBraces--; - } - else if (openBraces == 1) - { - size = (int)(p - elemStart); - p++; - if ((p >= limit) || isspace(UCHAR(*p))) - { /* INTL: ISO space. */ - goto done; - } - - /* - * Garbage after the closing brace; return an error. - */ - - return TCL_ERROR; - } - break; - - /* - * Backslash: skip over everything up to the end of the backslash - * sequence. - */ - - case '\\': - //RZ Tcl_UtfBackslash(p, &numChars, NULL); - //RZ p += (numChars - 1); - p++; //RZ - break; - - /* - * Space: ignore if element is in braces or quotes; otherwise - * terminate element. - */ - - case ' ': - case '\f': - case '\n': - case '\r': - case '\t': - case '\v': - if ((openBraces == 0) && !inQuotes) - { - size = (int)(p - elemStart); - goto done; - } - break; - - /* - * Double-quote: if element is in quotes then terminate it. - */ - - case '"': - if (inQuotes) - { - size = (int)(p - elemStart); - p++; - if ((p >= limit) || isspace(UCHAR(*p))) - { /* INTL: ISO space */ - goto done; - } - - /* - * Garbage after the closing quote; return an error. - */ - return TCL_ERROR; - } - break; - } - p++; - } - - /* - * End of list: terminate element. - */ - - if (p == limit) - { - if (openBraces != 0) - { - return TCL_ERROR; - } - else if (inQuotes) - { - return TCL_ERROR; - } - size = (int)(p - elemStart); - } - -done: - while ((p < limit) && (isspace(UCHAR(*p)))) - { /* INTL: ISO space. */ - p++; - } - *elementPtr = elemStart; - *nextPtr = p; - if (sizePtr != 0) - { - *sizePtr = size; - } - return TCL_OK; -} - -int Tcl_SplitList( - CONST char *list, /* Pointer to string with list structure. */ - int *argcPtr, /* Pointer to location to fill in with the - * number of elements in the list. */ - CONST char ***argvPtr) /* Pointer to place to store pointer to array - * of pointers to list elements. */ -{ - CONST char **argv, *l, *element; - char *p; - int length, size, i, result, elSize, brace; - - /* - * Figure out how much space to allocate. There must be enough space for - * both the array of pointers and also for a copy of the list. To estimate - * the number of pointers needed, count the number of space characters in - * the list. - */ - - for (size = 2, l = list; *l != 0; l++) - { - if (isspace(UCHAR(*l))) - { /* INTL: ISO space. */ - size++; - - /* - * Consecutive space can only count as a single list delimiter. - */ - - while (1) - { - char next = *(l + 1); - - if (next == '\0') - { - break; - } - ++l; - if (isspace(UCHAR(next))) - { /* INTL: ISO space. */ - continue; - } - break; - } - } - } - length = (int)(l - list); - argv = (CONST char **) ckalloc((unsigned) - ((size * sizeof(char *)) + length + 1)); - for (i = 0, p = ((char *) argv) + size*sizeof(char *); - *list != 0; i++) - { - CONST char *prevList = list; - - result = TclFindElement(list, length, &element, &list, - &elSize, &brace); - length -= (int)(list - prevList); - if (result != TCL_OK) - { - ckfree((char *) argv); - return result; - } - if (*element == 0) - { - break; - } - if (i >= size) - { - ckfree((char *) argv); - return TCL_ERROR; - } - argv[i] = p; - if (brace) - { - memcpy(p, element, (size_t) elSize); - p += elSize; - *p = 0; - p++; - } - else - { - TclCopyAndCollapse(elSize, element, p); - p += elSize+1; - } - } - - argv[i] = NULL; - *argvPtr = argv; - *argcPtr = i; - return TCL_OK; -} -// END of tclUtil.c - -void tcl_split_list(QCString &str, QCStringList &list) -{ - int argc; - const char **argv; - - list.clear(); - if (str.left(1)=="{" && str.right(1)=="}") - { - str=str.mid(1,str.length()-2); - } - else if (str.left(1)=="\"" && str.right(1)=="\"") - { - str=str.mid(1,str.length()-2); - } - if (!str.isEmpty()) - { - if (Tcl_SplitList(str,&argc,&argv) != TCL_OK) - { - list.append(str); - } - else - { - for (int i = 0; i < argc; i++) - { - list.append(argv[i]); - } - ckfree((char *) argv); - } - } -} - -//! Structure containing information about current scan context. -typedef struct -{ - char type[2]; // type of scan context: "\"" "{" "[" "?" " " - int line0; // start line of scan context - int line1; // end line of scan context - YY_BUFFER_STATE buffer_state; // value of scan context - QCString ns; // current namespace - Entry *entry_fn; // if set contains the current proc/method/constructor/destructor - Entry *entry_cl; // if set contain the current class - Entry *entry_scan; // current scan entry - Protection protection; // current protections state - QCStringList after; // option/value list (options: NULL comment keyword script) -} tcl_scan; - -//* Structure containing all internal global variables. -static struct -{ - CodeOutputInterface * code; // if set then we are codifying the file - int code_line; // current line of code - int code_linenumbers; // if true create line numbers in code - const char *code_font; // used font to codify - bool config_autobrief; // value of configuration option - QMap<QCString,QCString> config_subst; // map of configuration option values - QCString input_string; // file contents - int input_position; // position in file - QCString file_name; // name of used file - OutlineParserInterface *this_parser; // myself - int command; // true if command was found - int comment; // set true if comment was scanned - int brace_level; // bookkeeping of braces - int bracket_level; // bookkeeping of brackets - int bracket_quote; // bookkeeping of quotes (toggles) - char word_is; // type of current word: "\"" "{" "[" "?" " " - int line_comment; // line number of comment - int line_commentline; // line number of comment after command - int line_command; // line number of command - int line_body0; // start line of body - int line_body1; // end line of body - QCString string_command; // contain current command - QCString string_commentline; // contain current comment after command - QCString string_commentcodify; // current comment string used in codifying - QCString string_comment; // contain current comment - QCString string_last; // contain last read word or part of word - QCString string; // temporary string value - Entry* entry_main; // top level entry - Entry* entry_file; // entry of current file - Entry* entry_current; // currently used entry - Entry* entry_inside; // contain entry of current scan context - QCStringList list_commandwords; // list of command words - QList<tcl_scan> scan; // stack of scan contexts - QAsciiDict<Entry> ns; // all read namespace entries - QAsciiDict<Entry> cl; // all read class entries - QAsciiDict<Entry> fn; // all read function entries - QList<Entry> entry; // list of all created entries, will be deleted after codifying - Protection protection; // current protections state - const MemberDef *memberdef; // contain current MemberDef when codifying - bool collectXRefs; -} tcl; - -// scanner functions -static int yyread(char *buf,int max_size); -static tcl_scan *tcl_scan_start(char type, QCString content, QCString ns, Entry *entry_cls, Entry *entry_fn); -static void tcl_scan_end(); -static void tcl_comment(int what,const char *text); -static void tcl_word(int what,const char *text); -static void tcl_command(int what,const char *text); - -// helper functions - -//! Create new entry. -// @return new initialised entry -Entry* tcl_entry_new() -{ - Entry *myEntry = new Entry; - myEntry->section = Entry::EMPTY_SEC; - myEntry->name = ""; -// myEntry->type = ""; - myEntry->brief = ""; -// myEntry->doc = ""; - myEntry->protection = Public; -// myEntry->mtype = Method; -// myEntry->virt = Normal; -// myEntry->stat = FALSE; - myEntry->docFile = tcl.file_name; - myEntry->inbodyFile = tcl.file_name; - myEntry->fileName = tcl.file_name; - myEntry->lang = SrcLangExt_Tcl; - Doxygen::docGroup.initGroupInfo(myEntry); - // collect entries - if (!tcl.code) - { - tcl.entry.insert(0,myEntry); - } - return myEntry; -} - -//! Set protection level. -void tcl_protection(Entry *entry) -{ - if (entry->protection!=Public&&entry->protection!=Protected&&entry->protection!=Private) - { - entry->protection = tcl.protection; - } - if (entry->protection!=Protected&&entry->protection!=Private) - { - entry->protection = Public; - } -} - -//! Check name. -// @return 'ns' and 'name' of given current 'ns0' and 'name0' -static void tcl_name(const QCString &ns0, const QCString &name0, QCString &ns, QCString &name) -{ - QCString myNm; - int myStart; - - if (qstrncmp(name0.data(),"::",2)==0) - { - myNm = name0.mid(2); - } - else if (ns0.length() && ns0 != " ") - { - myNm = ns0 + "::" + name0; - } - else - { - myNm = name0; - } - myStart = myNm.findRev("::"); - if (myStart == -1) - { - ns = ""; - name = myNm; - } - else if (myNm.length()-myStart == 2) - { - // ending with :: so get name equal to last component - ns = myNm.mid(0,myStart); - myStart = ns.findRev("::"); - name = myNm.mid(myStart+2); - } - else - { - ns = myNm.mid(0,myStart); - name = myNm.mid(myStart+2); - } -} - -//! Check name. Strip namespace qualifiers from name0 if inside inlined code segment. -// @return 'ns' and 'name' of given current 'ns0' and 'name0' -static void tcl_name_SnippetAware(const QCString &ns0, const QCString &name0, QCString &ns, QCString &name) -{ - // If we are inside an inlined code snippet then ns0 - // already contains the complete namespace path. - // Any namespace qualifiers in name0 are redundant. - int i = name0.findRev("::"); - if (i>=0 && tcl.memberdef) - { - tcl_name(ns0, name0.mid(i+2), ns, name); - } - else - { - tcl_name(ns0, name0, ns, name); - } -} - -// Check and return namespace entry. -// @return namespace entry -Entry* tcl_entry_namespace(const QCString ns) -{ - Entry *myEntry; - if (ns.length()) - { - myEntry = tcl.ns.find(ns); - } - else - { - myEntry = tcl.ns.find("::"); - } - if (myEntry == NULL) - { - myEntry = tcl_entry_new(); - myEntry->section = Entry::NAMESPACE_SEC; - myEntry->name = ns; - tcl.entry_main->moveToSubEntryAndKeep(myEntry); - tcl.ns.insert(ns,myEntry); - } - return myEntry; -} - -// Check and return class entry. -// @return class entry -Entry* tcl_entry_class(const QCString cl) -{ - Entry *myEntry; - if (!cl.length()) return(NULL); - - myEntry = tcl.cl.find(cl); - if (myEntry == NULL) - { - myEntry = tcl_entry_new(); - myEntry->section = Entry::CLASS_SEC; - myEntry->name = cl; - tcl.entry_main->moveToSubEntryAndKeep(myEntry); - tcl.cl.insert(cl,myEntry); - } - return myEntry; -} - -//! Check for keywords. -// @return 1 if keyword and 0 otherwise -static int tcl_keyword(QCString str) -{ - static QCStringList myList; - static int myInit=1; - if (myInit) - { - // tcl keywords - myList <<"append"<<"apply"<<"array"<<"auto_execok"<<"auto_import"<<"auto_load"<<"auto_mkindex"<<"auto_qualify"<<"auto_reset"; - myList <<"binary"; - myList <<"catch"<<"cd"<<"close"<<"clock"<<"concat"; - myList <<"eof"<<"eval"<<"exec"<<"exit"<<"expr"; - myList <<"fblocked"<<"fconfigure"<<"file"<<"fileevent"<<"flush"<<"for"<<"foreach"<<"format"; - myList <<"gets"<<"global"; - myList <<"http"; - myList <<"if"<<"incr"<<"info"<<"interp"; - myList <<"join"; - myList <<"lappend"<<"lassign"<<"lindex"<<"linsert"<<"llength"<<"load"<<"lrange"<<"lrepeat"<<"lreplace"<<"lreverse"<<"lset"; - myList <<"namespace"; - myList <<"package"<<"parray"<<"pid"<<"pkg_mkIndex"<<"proc"<<"puts"<<"pwd"; - myList <<"registry"<<"rename"<<"return"; - myList <<"scan"<<"set"<<"split"<<"string"<<"switch"; - myList <<"tclLog"<<"tcl_endOfWord"<<"tcl_findLibrary"<<"tcl_startOfNextWord"<<"tcl_startOfPreviousWord"<<"tcl_wordBreakAfter"<<"tcl_wordBreakBefore"<<"tell"<<"time"; - myList <<"unknown"<<"upvar"; - myList <<"variable"<<"vwait"; -// tk keywords - myList <<"bell"<<"bind"<<"bindtags"; - myList <<"clipboard"<<"console"<<"consoleinterp"; - myList <<"destroy"; - myList <<"event"; - myList <<"focus"; - myList <<"grid"; - myList <<"lower"; - myList <<"option"; - myList <<"pack"<<"place"; - myList <<"raise"; - myList <<"send"; - myList <<"tkerror"<<"tkwait"<<"tk_bisque"<<"tk_focusNext"<<"tk_focusPrev"<<"tk_focusFollowsMouse"<<"tk_popup"<<"tk_setPalette"<<"tk_textCut"<<"tk_TextCopy"<<"tk_textPaste"<<"chooseColor"<<"tk_chooseColor"<<"tk_chooseDirectory"<<"tk_dialog"<<"tk_getOpenFile"<<"tkDialog"<<"tk_getSaveFile"<<"tk_messageBox"; - myList <<"winfo"<<"wm"; - myList <<"button"<<"canvas"<<"checkbutton"<<"entry"<<"frame"<<"image"<<"label"<<"labelframe"<<"listbox"<<"menu"<<"menubutton"<<"message"<<"panedwindow"<<"radiobutton"<<"scale"<<"scrollbar"<<"spinbox"<<"toplevel"; - //myList.sort(); - myInit=0; - } - str=str.stripWhiteSpace(); - if (str.left(2)=="::") {str=str.mid(2);} - if (myList.findIndex(str) != -1) return(1); - return 0; -} - -//! End codifying with special font class. -static void tcl_font_end() -{ - if (!tcl.code) return; - if (tcl.code_font) - { - tcl.code->endFontClass(); - tcl.code_font=NULL; - } -} - -//! Codify 'str' with special font class 's'. -static void tcl_codify(const char *s,const char *str) -{ - if (!tcl.code || !str) return; - if (s && qstrcmp(s,"NULL")!=0) - { - tcl_font_end(); - tcl.code->startFontClass(s); - tcl.code_font=s; - } - char *tmp = (char *) malloc(strlen(str)+1); - strcpy(tmp, str); - char *p=tmp,*sp=p; - char c; - bool done=FALSE; - while (!done) - { - sp=p; - while ((c=*p++) && c!='\n') {} - if (c=='\n') - { - tcl.code_line++; - *(p-1)='\0'; // Dimitri: is this really needed? - // wtschueller: As far as I can see: yes. - // Deletes that \n that would produce ugly source listings otherwise. - // However, there may exist more sophisticated solutions. - tcl.code->codify(sp); - if (tcl.code_font) - { - tcl.code->endFontClass(); - } - tcl.code->endCodeLine(); - tcl.code->startCodeLine(tcl.code_linenumbers); - if (tcl.code_linenumbers) - { - tcl.code->writeLineNumber(0,0,0,tcl.code_line); - } - if (tcl.code_font) - { - tcl.code->startFontClass(tcl.code_font); - } - } - else - { - if (*(p-2)==0x1A) *(p-2) = '\0'; // remove ^Z - tcl.code->codify(sp); - done=TRUE; - } - } - free(tmp); - tcl_font_end(); -} - -#if 0 -//! Codify 'str' with special font class 's'. -static void tcl_codify(const char *s,const char *str) -{ - if (tcl.code==NULL) return; - char *tmp= (char *) malloc(strlen(str)+1); - strcpy(tmp, str); - tcl_codify(s,tmp); - free(tmp); -} - -//! Codify 'str' with special font class 's'. -static void tcl_codify(const char *s,const QCString &str) -{ - if (tcl.code==NULL) return; - tcl_codify(s,str); -} - -//! Codify 'str' with special font class 's'. -static void tcl_codify(const char *s,const QCString &str) -{ - if (!tcl.code) return; - tcl_codify(s,str.data()); -} -#endif - -static void tcl_codify_cmd(const char *s,int i) -{ - tcl_codify(s,(*tcl.list_commandwords.at(i))); -} -//! codify a string token -// -// codifies string according to type. -// Starts a new scan context if needed (*myScan==0 and type == "script"). -// Returns NULL or the created scan context. -// -static tcl_scan *tcl_codify_token(tcl_scan *myScan, const QCString type, const QCString string) -{ - if (myScan != NULL) - { - if (type != NULL) - { - myScan->after << type << string; - } - else - { - myScan->after << "NULL" << string; - } - } - else - { - if (qstrcmp(type, "script") == 0) - { - myScan = tcl.scan.at(0); - myScan = tcl_scan_start('?', string, - myScan->ns, myScan->entry_cl, myScan->entry_fn); - } - else - { - tcl_codify((const char*)type, string); - } - } - return myScan; -} - -//----------------------------------------------------------------------------- -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -//----------------------------------------------------------------------------- -%} -ws ([ \t]|\\\n) - -%option yylineno -%option noyywrap -%option stack - -%x ERROR -%x TOP -%x COMMAND -%x WORD -%x COMMENT -%x COMMENT_NL -%x COMMENT_CODE -%x COMMENT_VERB -%x COMMENTLINE -%x COMMENTLINE_NL -%% -<ERROR>. { -D - yyterminate(); -} -<<EOF>> { -D - if (tcl.scan.count()<1) - {// error -D - tcl_err("Tcl parser stack empty! Parser error in file '%s'.\n",tcl.file_name.data()); - yyterminate(); - } - else if (tcl.scan.count()==1) - {// exit, check on input? -D - yyterminate(); - } - else - {// continue -D - tcl_command(-1,""); - tcl_scan_end(); - } -} -<TOP>"#" { -D - yyless(0); - tcl.line_comment=yylineno; - tcl_comment(0,""); -} -<TOP>({ws}|[\;\n])+ { -D - tcl_codify(NULL,yytext); -} -<TOP>. { -D - yyless(0); - tcl.line_command=yylineno; - tcl_command(0,""); -} - -<COMMENT>[ \t]* { -D - tcl_codify("comment",yytext); -} -<COMMENT>"###".*\n { -D - tcl_codify("comment",yytext); - tcl_comment(2,yytext+1); -} -<COMMENT>"##".*\\\n { -D - tcl_codify("comment",yytext); - QCString t=yytext; - t = t.mid(2,t.length()-3); - t.append("\n"); - tcl_comment(1,t.data()); - yy_push_state(COMMENT_NL); -} -<COMMENT>"##".*\n { -D - tcl_codify("comment",yytext); - tcl_comment(1,yytext+2); -} -<COMMENT>"#"[@\\]"code"\n[ \t]*[^#] { -D - QCString t=yytext; - tcl_codify("comment",t.left(7)); - tcl_comment(2,"\n@code\n"); - yyless(7); - yy_push_state(COMMENT_CODE); -} -<COMMENT>"#"[@\\]"verbatim"\n[ \t]*[^#] { -D - QCString t=yytext; - tcl_codify("comment",t.left(11)); - tcl_comment(2,"\n@verbatim\n"); - yyless(11); - yy_push_state(COMMENT_VERB); -} -<COMMENT>"#".*\\\n { -D - tcl_codify("comment",yytext); - QCString t=yytext; - t = t.mid(1,t.length()-3); - t.append("\n"); - tcl_comment(2,t.data()); - yy_push_state(COMMENT_NL); -} -<COMMENT>"#".*\n { -D - tcl_codify("comment",yytext); - tcl_comment(2,yytext+1); -} -<COMMENT>"#".*\x1A { -D - QCString t=yytext; - t = t.mid(0,t.length()-1); - tcl_codify("comment",t.data()); - t = t.mid(1,t.length()); - tcl_comment(-2,t.data()); - unput(0x1A); -} -<COMMENT>\x1A { -D - tcl_comment(-2,""); - unput(0x1A); -} -<COMMENT>.|\n { -D - tcl_comment(-2,yytext); - yyless(0); -} - -<COMMENT_CODE>"#"[@\\]"endcode"\n { -D - QCString t=yytext; - t = t.left(t.length()-10); - tcl_comment(2,t.data()); - tcl_comment(2,"\n@endcode\n"); - yy_pop_state(); - yyless(0); -} -<COMMENT_CODE>.*\n { -D - yymore(); -} -<COMMENT_CODE>.*\x1A { -D - yy_pop_state(); - yyless(0); -} - -<COMMENT_VERB>"#"[@\\]"endverbatim"\n { -D - QCString t=yytext; - t = t.left(t.length()-14); - tcl_comment(2,t.data()); - tcl_comment(2,"\n@endverbatim\n"); - yy_pop_state(); - yyless(0); -} -<COMMENT_VERB>.*\n { -D - yymore(); -} -<COMMENT_VERB>.*\x1A { -D - yy_pop_state(); - yyless(0); -} - -<COMMENT_NL>.*\\\n { -D - tcl_codify("comment",yytext); - tcl_comment(2,yytext); -} -<COMMENT_NL>.*\n { -D - tcl_codify("comment",yytext); - tcl_comment(2,yytext); - yy_pop_state(); -} -<COMMENT_NL>.*\x1A { -D - yy_pop_state(); - yyless(0); -} - -<COMMENTLINE>.*\x1A { -D - yy_pop_state(); - yyless(0); -} -<COMMENTLINE>[ \t]* { -D - tcl.string_commentcodify += yytext; -} -<COMMENTLINE>"#<".*\\\n { -D - tcl.string_commentcodify += yytext; - QCString t=yytext; - t = t.mid(2,t.length()-4); - t.append("\n"); - tcl.string_commentline += t; - yy_push_state(COMMENTLINE_NL); -} -<COMMENTLINE>"#<".*\n { -D - tcl.string_commentcodify += yytext; - tcl.string_commentline += (yytext+2); -} -<COMMENTLINE>.|\n { -D - yy_pop_state(); - if (tcl.string_commentline.length()) - { - tcl.entry_current->brief = tcl.string_commentline; - tcl.entry_current->briefLine = tcl.line_commentline; - tcl.entry_current->briefFile = tcl.file_name; - } - yyless(0); - tcl_command(-1,tcl.string_commentcodify.data()); - tcl.string_commentline=""; - tcl.string_commentcodify=""; -} - -<COMMENTLINE_NL>.*\\\n { -D - tcl.string_commentcodify += yytext; - QCString t=yytext; - t = t.left(t.length()-3); - t.append("\n"); - tcl.string_commentline += t; -} -<COMMENTLINE_NL>.*\n { -D - tcl.string_commentcodify += yytext; - tcl.string_commentline += yytext; - yy_pop_state(); -} -<COMMENTLINE_NL>.*\x1A { -D - QCString t=yytext; - t = t.left(t.length()-1); - tcl.string_commentcodify += t; - tcl.string_commentline += t; - yy_pop_state(); - unput(0x1A); -} - -<COMMAND>{ws}*[\;]{ws}*"#<" { -D - tcl.string_commentcodify = yytext; - tcl.string_commentcodify = tcl.string_commentcodify.left(tcl.string_commentcodify.length()-2); - tcl.string_commentline = ""; - tcl.line_commentline = yylineno; - tcl.line_body1=yylineno; - unput('<'); - unput('#'); - yy_push_state(COMMENTLINE); -} -<COMMAND>{ws}*\x1A { -D - tcl.string_commentcodify = ""; - tcl.string_commentline = ""; - tcl.line_body1=yylineno; - tcl_command(-1,yytext); -} -<COMMAND>{ws}*; { -D - tcl.string_commentcodify = ""; - tcl.string_commentline = ""; - tcl.line_body1=yylineno; - tcl_command(-1,yytext); -} -<COMMAND>{ws}*\n { -D - tcl.string_commentcodify = ""; - tcl.string_commentline = ""; - tcl.line_body1=yylineno-1; - tcl_command(-1,yytext); -} -<COMMAND>{ws}+ { -D - tcl_command(1,yytext); -} -<COMMAND>"{*}". { -D - tcl.word_is = ' '; - tcl.string_last = "{*}"; - tcl_word(0,&yytext[3]); -} -<COMMAND>"\\"[\{\}\[\]\;\" \t] { -D - tcl.word_is=' '; - tcl.string_last = ""; - tcl_word(0,yytext); -} -<COMMAND>. { -D - tcl.word_is=' '; - if (yytext[0]=='{'||yytext[0]=='['||yytext[0]=='"') tcl.word_is = yytext[0]; - tcl.string_last = ""; - tcl_word(0,yytext); -} - -<WORD>"\\\\" | -<WORD>"\\"[\{\}\[\]\;\" \t] { - tcl_word(1,yytext); -} -<WORD>"\\\n" { - tcl_word(2,yytext); -} -<WORD>"{" { - tcl_word(3,yytext); -} -<WORD>"}" { - tcl_word(4,yytext); -} -<WORD>"[" { - tcl_word(5,yytext); -} -<WORD>"]" { - tcl_word(6,yytext); -} -<WORD>"\"" { - tcl_word(7,yytext); -} -<WORD>" " { - tcl_word(8,yytext); -} -<WORD>"\t" { - tcl_word(9,yytext); -} -<WORD>";" { - tcl_word(10,yytext); -} -<WORD>"\n" { - tcl_word(11,yytext); -} -<WORD>\x1A { - tcl_word(12,yytext); -} -<WORD>. { - tcl_word(1,yytext); -} -%% - -//! Start new scan context for given 'content'. -// @return created new scan context. -static tcl_scan *tcl_scan_start(char type, QCString content, QCString ns, Entry *entry_cl, Entry *entry_fn) -{ - tcl_scan *myScan=tcl.scan.at(0); -tcl_inf("line=%d type=%d '%s'\n",tcl.line_body0,type,content.data()); - - myScan->line1=yylineno; - yy_push_state(TOP); - - myScan=new tcl_scan; - myScan->type[0] =' '; - myScan->type[1] = '\0'; - switch (type) { - case '"': - case '{': - case '[': - myScan->type[0] = type; - break; - case '?': - if (content[0]=='"' && content[content.length()-1]=='"') myScan->type[0]='"'; - if (content[0]=='{' && content[content.length()-1]=='}') myScan->type[0]='{'; - if (content[0]=='[' && content[content.length()-1]==']') myScan->type[0]='['; - } - if (myScan->type[0]!=' ') - { - tcl_codify(NULL,&myScan->type[0]); - content = content.mid(1,content.length()-2); - } - content += (char)0x1A;// for detection end of scan context - myScan->ns = ns; - myScan->entry_cl = entry_cl; - myScan->entry_fn = entry_fn; - myScan->entry_scan = tcl.entry_current; - myScan->buffer_state=yy_scan_string(content.data()); - myScan->line0=tcl.line_body0; - myScan->line1=tcl.line_body1; - myScan->after.clear(); - yylineno=myScan->line0; - myScan->protection = tcl.protection; - - tcl.entry_inside = myScan->entry_scan; - tcl.entry_current = tcl_entry_new(); - tcl.scan.insert(0,myScan); - yy_switch_to_buffer(myScan->buffer_state); - return (myScan); -} - -//! Close current scan context. -static void tcl_scan_end() -{ - tcl_scan *myScan=tcl.scan.at(0); - tcl_scan *myScan1=tcl.scan.at(1); -tcl_inf("line=%d\n",myScan->line1); - - if (myScan->type[0]=='{') myScan->type[0]='}'; - if (myScan->type[0]=='[') myScan->type[0]=']'; - if (myScan->type[0]!=' ') tcl_codify(NULL,&myScan->type[0]); - int myStart=-1; - for (unsigned int i=0;i<myScan->after.count();i=i+2) - { - if (myScan->after[i]=="script") { - myStart=i; - break; - } - tcl_codify(myScan->after[i],myScan->after[i+1]); - } - yy_delete_buffer(myScan->buffer_state); - yy_pop_state(); - tcl.entry_inside = myScan1->entry_scan; - yy_switch_to_buffer(myScan1->buffer_state); - yylineno=myScan1->line1; - tcl.protection = myScan1->protection; - if (myStart>=0) - { - myScan1 = tcl_scan_start('?', myScan->after[myStart+1], myScan->ns, myScan->entry_cl, myScan->entry_fn); - for (unsigned int i=myStart+2;i<myScan->after.count();i++) - { - myScan1->after.append(myScan->after[i]); - } - tcl.scan.remove(1); - } - else - { - tcl.scan.removeFirst(); - } -} - -//! Handling of word parsing. -static void tcl_word(int what,const char *text) -{ - static char myList[1024]="";// nesting level list - static int myLevel=0;// number of current nesting level - static int myWhite=0;// set true when next char should be whitespace - static char myWord;// internal state - - switch (what) - { - case 0:// start - yy_push_state(WORD); - switch (text[0]) - { - case '{': - case '[': - case '"': myWord = text[0]; break; - default: myWord = '.'; - } - myList[0]=myWord; - myLevel=1; - myWhite=0; - break; - case 1:// all other chars - if (myWhite) - {// {x}y "x"y - tcl_err("expected word separator: %s\n",text); - return; - } - if (myLevel==0) - { - myWord='.'; - myList[0]=myWord; - myLevel=1; - } - break; - case 2:// \\\n - if (myLevel==0) - { - myWord=' '; - yy_pop_state(); - yyless(0); -tcl_inf("(\\\n) ?%s?\n",tcl.string_last.data()); - return; - } - switch (myList[myLevel-1]) - { - case '{': - case '[': - case '"': - break; - case '.': - if (myLevel==1) - { - myWord=' '; - yy_pop_state(); - yyless(0); -tcl_inf("(\\\n) ?%s?\n",tcl.string_last.data()); - return; - } - break; - } - myWhite=0; - break; - case 3:// { - if (myWhite) - {// {x}{ "x"{ - tcl_err("expected word separator: %s\n",text); - return; - } - switch (myList[myLevel-1]) - { - case '{': - case '[': - myList[myLevel++]='{'; - break; - case '"': - case '.': - break; - } - myWhite=0; - break; - case 4:// } - if (myWhite) - {// {x}{ "x"{ - tcl_err("expected word separator: %s\n",text); - return; - } - switch (myList[myLevel-1]) - { - case '{':// {{x}} - myLevel--; - if (myLevel==0 && !tcl.code) - { - myWhite=1; - } - break; - case '[': - case '"': - case '.': - break; - } - break; - case 5:// [ - if (myWhite) - {// {x}[ - tcl_err("expected word separator: %s\n",text); - return; - } - switch (myList[myLevel-1]) - { - case '{': - break; - case '[': - case '"': - case '.': - myList[myLevel++]='['; - break; - } - myWhite=0; - break; - case 6:// ] - if (myWhite) - {// {x}] - tcl_err("expected word separator: %s\n",text); - return; - } - switch (myList[myLevel-1]) - { - case '{': - break; - case '[': - myLevel--; - break; - case '"': - case '.': - break; - } - myWhite=0; - break; - case 7:// " - if (myWhite) - {// {x}" - tcl_err("expected word separator: %s\n",text); - return; - } - switch (myList[myLevel-1]) - { - case '{': - break; - case '[': - myList[myLevel++]='"'; - break; - case '"': - myLevel--; - case '.': - break; - } - break; - case 8:// ' ' - case 9:// \t - case 10:// ; - case 11:// \n - if (myLevel==0) - { - myWord=' '; - yy_pop_state(); - yyless(0); -tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data()); - return; - } - switch (myList[myLevel-1]) - { - case '{': - case '[': - case '"': - break; - case '.': - if (myLevel==1) - { - myWord=' '; - yy_pop_state(); - yyless(0); -tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data()); - return; - } - else - { - myLevel--; - } - break; - } - myWhite=0; - break; - case 12:// \x1A - if (myLevel==0) - { - myWord=' '; - yy_pop_state(); - yyless(0); -tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data()); - return; - } - if (myLevel!=1 || myList[0] != '.') - { - tcl_war("level=%d expected=%c\n",myLevel,myList[myLevel-1]); - } - myWord=' '; - yy_pop_state(); - yyless(0); -tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data()); - return; - break; - default: - tcl_err("wrong state: %d\n",what); - return; - } - tcl.string_last += text; -} - -//! Handling of comment parsing. -static void tcl_comment(int what,const char *text) -{ - if (what==0) - { // begin of comment - if (tcl.comment) - { - tcl_err("comment in comment\n"); - return; - } - yy_push_state(COMMENT); -tcl_inf("<- %s\n",text); - tcl.string_comment=""; - tcl.comment=0; - } - else if (what==1) - { // start new comment - if (tcl.comment) - { - tcl_comment(99,""); // inbody - } - tcl.string_comment=text; - tcl.comment=1; - } - else if (what==2) - { // add to comment - if (tcl.comment) - { - tcl.string_comment+=text; - } - } - else if (what==-1 || what == -2) - { // end of comment without/with command - if (tcl.comment) - { - tcl.string_last=tcl.string_comment; - tcl_comment(100+what,""); - } - else - { - tcl.string_last = ""; -tcl_inf("-> %s\n",(const char *)tcl.string_comment); - } - yy_pop_state(); - tcl.string_comment=""; - tcl.comment=0; - } - else if (what==98 || what==99) - { // 98=new 99=inbody - if (tcl.this_parser && tcl.string_comment.length()) - { -tcl_inf("-> %s\n",(const char *)tcl.string_comment); - int myPos=0; - bool myNew=false; - int myLine=tcl.line_comment; - BufStr myI(1024); - BufStr myO(1024); - Protection myProt=tcl.protection; - - // resolve ALIASES - myI.addArray("/*!",3); - myI.addArray(tcl.string_comment.data(),tcl.string_comment.length()); - myI.addArray("*/",2); - convertCppComments(&myI,&myO,tcl.file_name); - myO.dropFromStart(3); - 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; - int myLine0; - Entry myEntry0; // used to test parsing - Entry *myEntry; - - Entry *myEntry1=NULL; - if (tcl.scan.at(0)->entry_fn) - { - myEntry1=tcl.scan.at(0)->entry_fn; - } - else if (tcl.scan.at(0)->entry_cl) - { - myEntry1=tcl.scan.at(0)->entry_cl; - } - - myPos0=myPos; - myLine0=myLine; - 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(); - 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->moveToSubEntryAndRefresh(myEntry); - } - else - { // we can add to current entry in this case - if (!myEntry1) - { - myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); - } - 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; - myLine0=myLine; - } - if (myNew) - { // we need a new entry - myNew=0; - myEntry = tcl_entry_new(); - 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->moveToSubEntryAndKeep(myEntry); - } - else - { // we can add to current entry - if (!myEntry1) - { - myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); - } - 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(); - 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)) - { - if (myNew) - { - tcl.entry_inside->moveToSubEntryAndKeep(tcl.entry_current); - tcl.entry_current = tcl_entry_new(); - } - else - { - tcl.entry_current->section = tcl.entry_inside->section; - tcl.entry_current->name = tcl.entry_inside->name; - } - } - if (myNew) - { - tcl.entry_inside->moveToSubEntryAndKeep(tcl.entry_current); - tcl.entry_current = tcl_entry_new(); - } - else - { - tcl.entry_current->section = tcl.entry_inside->section; - tcl.entry_current->name = tcl.entry_inside->name; - } - } - if (tcl.protection != myProt) - { - tcl.scan.at(0)->protection = tcl.protection = myProt; - } - } - } - else - { - tcl_err("what %d\n",what); - return; - } -} - -//! Parse given \c arglist . -static void tcl_command_ARGLIST(QCString &arglist) -{ -D - QCStringList myArgs; - QCString myArglist=""; - - tcl_split_list(arglist,myArgs); - for (uint i=0;i<myArgs.count();i++) - { - QCStringList myArgs1; - Argument myArg; - - tcl_split_list(*myArgs.at(i),myArgs1); - if (myArgs1.count()==2) - { - myArg.name= (*myArgs1.at(0)); - myArg.defval= (*myArgs1.at(1)); - if (myArg.defval.isEmpty()) - { - myArg.defval = " "; - } - myArglist += "?" + QCString(myArg.name) + "? "; - } - else - { - myArg.name= (*myArgs.at(i)); - myArglist += myArg.name + " "; - } - tcl.entry_current->argList.push_back(myArg); - } - arglist = myArglist; - tcl.entry_current->args = arglist; -} - -//! Create link. -static void tcl_codify_link(QCString name) -{ - if (tcl.code == NULL || name.isEmpty()) return; - static int init=0; - static QAsciiDict<MemberDef> fn; - if (init==0) - { - init=1; - MemberNameSDict::Iterator mni(*Doxygen::memberNameSDict); - MemberNameSDict::Iterator fni(*Doxygen::functionNameSDict); - MemberName *mn=0; - MemberDef *md; - for (mni.toFirst();(mn=mni.current());++mni) - { - MemberNameIterator mi(*mn); - for (mi.toFirst();(md=mi.current());++mi) - { - fn.insert(md->qualifiedName(),md); - } - } - for (fni.toFirst();(mn=fni.current());++fni) - { - MemberNameIterator fi(*mn); - for (fi.toFirst();(md=fi.current());++fi) - { - fn.insert(md->qualifiedName(),md); - } - } - } - MemberDef *myDef; - QCString myName=name; - if (name.mid(0,2)=="::") // fully qualified global command - { - myName = myName.mid(2); - myDef = fn.find(myName); - } - else // not qualified name - { - QCString myName1=myName; - myDef = NULL; - myName1 = tcl.scan.at(0)->ns; - if (myName1 == " " || myName1 == "") - { - myName1 = myName; - } - else - { - myName1 = myName1 + "::" + myName; - } - myDef = fn.find(myName1); // search namespace command - if (myDef == NULL) - { - myDef = fn.find(myName); // search global command - } - } - if (myDef != NULL) // documented command - { - tcl.code->writeCodeLink(myDef->getReference().data(), - myDef->getOutputFileBase().data(), - myDef->anchor().data(), - name, - myDef->qualifiedName().data()); - if (tcl.memberdef) - { - myDef->addSourceReferencedBy(tcl.memberdef); - //tcl.memberdef->addSourceReferences(myDef); - } else { - Entry* callerEntry; - unsigned int i; - // walk the stack of scan contexts and find the enclosing method or proc - for (i=0;i<tcl.scan.count();i++) - { - callerEntry=tcl.scan.at(i)->entry_scan; - if (callerEntry->mtype==Method && !callerEntry->name.isEmpty()) - { - break; - } - } - if (i<tcl.scan.count()) - { - // enclosing method found - QCString callerName = callerEntry->name; - if (callerName.mid(0,2)=="::") // fully qualified global command - { - callerName = callerName.mid(2); - } - else - { - if (!(tcl.scan.at(0)->ns.stripWhiteSpace().isEmpty())) - { - callerName = tcl.scan.at(0)->ns + "::" + callerEntry->name; - } - } - MemberDef *callerDef=NULL; - callerDef = fn.find(callerName); - if (callerDef!=NULL && myDef!= NULL && tcl.collectXRefs) - { - addDocCrossReference(callerDef,myDef); - } - } - } - } - else if (tcl_keyword(myName)) // check keyword - { - tcl_codify("keyword",name); - } - else - { - tcl_codify(NULL,name); // something else - } - -} - -//! scan general argument for brackets -// -// parses (*tcl.list_commandwords.at(i)) and checks for brackets. -// Starts a new scan context if needed (*myScan==0 and brackets found). -// Returns NULL or the created scan context. -// -static tcl_scan *tcl_command_ARG(tcl_scan *myScan, unsigned int i, bool ignoreOutermostBraces) -{ - QCString myName; - bool insideQuotes=false; - unsigned int insideBrackets=0; - unsigned int insideBraces=0; - myName = (*tcl.list_commandwords.at(i)); - if (i%2 != 0) - { - // handle white space - myScan = tcl_codify_token(myScan, "NULL", myName); - } - else - { - QCString myStr = ""; - unsigned int j; - for (j=0;j<myName.length();j++) - { - QChar c = myName[j]; - bool backslashed = false; - if (j>0) - { - backslashed = myName[j-1]=='\\'; - } - // this is a state machine - // input is c - // internal state is myScan and insideXXX - // these are the transitions: - if (c=='[' && !backslashed && insideBraces==0) - { - insideBrackets++; - } - if (c==']' && !backslashed && insideBraces==0 && insideBrackets>0) - { - insideBrackets--; - } - if (c=='{' && !backslashed && !insideQuotes && !(ignoreOutermostBraces && j==0)) - { - insideBraces++; - } - if (c=='}' && !backslashed && !insideQuotes && insideBraces>0) - { - insideBraces--; - } - if (c=='"' && !backslashed && insideBraces==0) - { - insideQuotes=!insideQuotes; - } - // all output, depending on state and input - if (c=='[' && !backslashed && insideBrackets==1 && insideBraces==0) - { - // the first opening bracket, output what we have so far - myStr+=c; - myScan = tcl_codify_token(myScan, "NULL", myStr); - myStr=""; - } - else if (c==']' && !backslashed && insideBrackets==0 && insideBraces==0) - { - // the last closing bracket, start recursion, switch to deferred - myScan = tcl_codify_token(myScan, "script", myStr); - myStr=""; - myStr+=c; - } - else - { - myStr+=c; - } - } - if (i == 0 && myScan == NULL) - { - tcl_codify_link(myStr); - } - else - { - myScan = tcl_codify_token(myScan, "NULL", myStr); - } - } - return (myScan); -} - -//! Handle internal tcl commands. -// "eval arg ?arg ...?" -static void tcl_command_EVAL() -{ -D - tcl_codify_cmd("keyword", 0); - tcl_scan *myScan = tcl.scan.at(0); - QCString myString = ""; - // we simply rescan the line without the eval - // we include leading whitespace because tcl_scan_start will examine - // the first char. If it finds a bracket it will assume one expression in brackets. - // Example: eval [list set] [list NotInvoked] [Invoked NotInvoked] - for (unsigned int i = 1; i < tcl.list_commandwords.count(); i++) - { - myString += (*tcl.list_commandwords.at(i)); - } - myScan = tcl_scan_start('?', myString, - myScan->ns, myScan->entry_cl, myScan->entry_fn); -} - -//! Handle internal tcl commands. -// switch ?options? string pattern body ?pattern body ...? -// switch ?options? string {pattern body ?pattern body ...?} -static void tcl_command_SWITCH() -{ -D - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_scan *myScan=NULL; - unsigned int i; - QCString token; - // first: find the last option token - unsigned int lastOptionIndex = 0; - for (i = 2; i<tcl.list_commandwords.count(); i += 2) - { - token = (*tcl.list_commandwords.at(i)); - if (token == "--") - { - lastOptionIndex = i; - break; - } - if (token[0] == '-' && i - lastOptionIndex == 2) - { - // options start with dash and should form a continuous chain - lastOptionIndex = i; - } - } - // second: eat up options - for (i = 2; i <= lastOptionIndex; i++) - { - myScan = tcl_command_ARG(myScan, i, false); - } - // third: how many tokens are left? - if (tcl.list_commandwords.count() - lastOptionIndex == 5) - { - //printf("syntax: switch ?options? string {pattern body ?pattern body ...?}\n"); - myScan = tcl_command_ARG(myScan, lastOptionIndex + 1, false); - myScan = tcl_command_ARG(myScan, lastOptionIndex + 2, false); - myScan = tcl_command_ARG(myScan, lastOptionIndex + 3, false); - // walk trough the list step by step - // this way we can preserve whitespace - bool inBraces = false; - bool nextIsPattern = true; - int size; - const char *elem; - const char *next; - token = (*tcl.list_commandwords.at(lastOptionIndex + 4)); - if (token[0] == '{') - { - inBraces = true; - token = token.mid(1, token.length() - 2); - myScan = tcl_codify_token(myScan, "NULL", QCString("{")); - } - // ToDo: check if multibyte chars are handled correctly - while (token.length() > 0) - { - TclFindElement((const char*)token, token.length(), &elem, &next, &size, NULL); - //printf("%s\nstart=%d, elem=%d, next=%d, size=%d, brace=%d\n", - // (const char*) token, (const char*) token, elem, next, size, brace); - // - // handle leading whitespace/opening brace/double quotes - if (elem - token > 0) - { - myScan = tcl_codify_token(myScan, "NULL", token.left(elem - token)); - } - // handle actual element without braces/double quotes - if (nextIsPattern) - { - myScan = tcl_codify_token(myScan, "NULL", token.mid(elem - token,size)); - //printf("pattern=%s\n",(const char*) token.mid(elem - token, size)); - } - else { - myScan = tcl_codify_token(myScan, "script", token.mid(elem - token, size)); - //printf("script =%s\n", (const char*) token.mid(elem - token, size)); - } - // handle trailing whitespace/closing brace/double quotes - if (next - elem - size > 0) - { - myScan = tcl_codify_token(myScan, "NULL", token.mid(elem - token + size, next - elem - size)); - } - nextIsPattern = !nextIsPattern; - token = token.mid(next - token); - } - if (inBraces) - { - myScan = tcl_codify_token(myScan, "NULL", QCString("}")); - } - if (!nextIsPattern) - { - tcl_war("Invalid switch syntax: last token is not a list of even elements.\n"); - //tcl_war("%s\n", tcl.list_commandwords.join(" ").ascii()); - } - } - else if ((tcl.list_commandwords.count() - lastOptionIndex > 6) && - ((tcl.list_commandwords.count() - lastOptionIndex-3) % 4 == 0)) - { - //printf("detected: switch ?options? string pattern body ?pattern body ...?\n"); - myScan = tcl_command_ARG(myScan, lastOptionIndex + 1, false); - myScan = tcl_command_ARG(myScan, lastOptionIndex + 2, false); - //printf("value=%s\n",(const char*) (*tcl.list_commandwords.at(lastOptionIndex + 2))); - for (i = lastOptionIndex + 3; i < tcl.list_commandwords.count(); i += 4) - { - myScan = tcl_command_ARG(myScan, i + 0, false); // whitespace - myScan = tcl_command_ARG(myScan, i + 1, false); // pattern - myScan = tcl_command_ARG(myScan, i + 2, false); // whitespace - myScan = tcl_codify_token(myScan, "script", (*tcl.list_commandwords.at(i+3))); // script - //printf("pattern=%s\n",(const char*) (*tcl.list_commandwords.at(i+1)))); - //printf("script=%s\n",(const char*) (*tcl.list_commandwords.at(i+3))); - } - } - else - { - // not properly detected syntax - tcl_war("Invalid switch syntax: %d options followed by %d tokens.\n", - lastOptionIndex / 2, (tcl.list_commandwords.count() - 1) / 2 - lastOptionIndex / 2); - for (i = lastOptionIndex + 1; i <= tcl.list_commandwords.count(); i++) - { - myScan = tcl_command_ARG(myScan, i, false); - } - } -} - -//! Handle internal tcl commands. -// "catch script ?resultVarName? ?optionsVarName?" -static void tcl_command_CATCH() -{ -D - tcl_codify_cmd("keyword", 0); - tcl_codify_cmd(NULL, 1); - tcl_scan *myScan = tcl.scan.at(0); - myScan = tcl_scan_start('?', *tcl.list_commandwords.at(2), - myScan->ns, myScan->entry_cl, myScan->entry_fn); - for (unsigned int i = 3; i < tcl.list_commandwords.count(); i++) - { - myScan = tcl_command_ARG(myScan, i, false); - } -} - -//! Handle internal tcl commands. -// "if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?" -static void tcl_command_IF(QCStringList type) -{ -D - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_scan *myScan = NULL; - myScan = tcl_command_ARG(myScan, 2, true); - for (unsigned int i = 3;i<tcl.list_commandwords.count();i++) - { - if (type[i] == "expr") - { - myScan = tcl_command_ARG(myScan, i, true); - } - else - { - if (myScan!=0) - { - myScan->after << type[i] << tcl.list_commandwords[i]; - } - else - { - myScan=tcl.scan.at(0); - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(i), - myScan->ns,myScan->entry_cl,myScan->entry_fn); - } - } - } -} -//! Handle internal tcl commands. -// "for start test next body" -static void tcl_command_FOR() -{ -D - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_scan *myScan=tcl.scan.at(0); - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(2), - myScan->ns,myScan->entry_cl,myScan->entry_fn); - myScan->after << "NULL" << tcl.list_commandwords[3]; - myScan = tcl_command_ARG(myScan, 4, true); - myScan->after << "NULL" << tcl.list_commandwords[5]; - myScan->after << "script" << tcl.list_commandwords[6]; - myScan->after << "NULL" << tcl.list_commandwords[7]; - myScan->after << "script" << tcl.list_commandwords[8]; -} - -///! Handle internal tcl commands. -// "foreach varname list body" and -// "foreach varlist1 list1 ?varlist2 list2 ...? body" -static void tcl_command_FOREACH() -{ -D - unsigned int i; - tcl_scan *myScan=NULL; - tcl_codify_cmd("keyword",0); - for (i = 1;i<tcl.list_commandwords.count()-1;i++) - { - myScan = tcl_command_ARG(myScan, i, false); - } - if (myScan!=0) - { - myScan->after << "script" << tcl.list_commandwords[tcl.list_commandwords.count()-1]; - } - else - { - myScan=tcl.scan.at(0); - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(tcl.list_commandwords.count()-1), - myScan->ns,myScan->entry_cl,myScan->entry_fn); - } -} - -///! Handle internal tcl commands. -// "while test body" -static void tcl_command_WHILE() -{ -D - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_scan *myScan = NULL; - myScan = tcl_command_ARG(myScan, 2, true); - myScan = tcl_command_ARG(myScan, 3, false); - if (myScan!=0) - { - myScan->after << "script" << tcl.list_commandwords[4]; - } - else - { - myScan=tcl.scan.at(0); - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(4), - myScan->ns,myScan->entry_cl,myScan->entry_fn); - } -} - -//! Handle all other commands. -// Create links of first command word or first command word inside []. -static void tcl_command_OTHER() -{ - tcl_scan *myScan=NULL; - for (unsigned int i=0; i< tcl.list_commandwords.count(); i++) - { - myScan = tcl_command_ARG(myScan, i, false); - } -} - -//! Handle \c proc statements. -static void tcl_command_PROC() -{ -D - QCString myNs, myName; - Entry *myEntryNs; - Entry *myEntry; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_codify_cmd(NULL,2); - tcl_codify_cmd(NULL,3); - tcl_codify_cmd(NULL,4); - tcl_codify_cmd(NULL,5); - tcl_name_SnippetAware(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); - if (myNs.length()) - { - myEntryNs = tcl_entry_namespace(myNs); - } - else - { - myEntryNs = tcl_entry_namespace(myScan->ns); - } - //why not needed here? tcl.fn.remove(myName); - tcl.entry_current->section = Entry::FUNCTION_SEC; - tcl.entry_current->mtype = Method; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl_protection(tcl.entry_current); - tcl_command_ARGLIST(*tcl.list_commandwords.at(4)); - myEntryNs->moveToSubEntryAndKeep(tcl.entry_current); - myEntry = tcl.entry_current; - tcl.fn.insert(myName,myEntry); - myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6), - myEntryNs->name,NULL,myEntry); -} - -//! Handle \c itcl::body statements and \c oo::define method and method inside \c itcl::class statements. -static void tcl_command_METHOD() -{ -D - QCString myNs, myName; - Entry *myEntryCl, *myEntry; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_codify_cmd(NULL,2); - tcl_codify_cmd(NULL,3); - tcl_codify_cmd(NULL,4); - tcl_codify_cmd(NULL,5); - tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); - if (myNs.length()) - { - myEntryCl = tcl_entry_class(myNs); - } - else - { - myNs = myScan->ns; - myEntryCl = myScan->entry_cl; - } - // needed in case of more then one definition p.e. itcl::method and itcl::body - // see also bug # - tcl.fn.remove(myName); - tcl.entry_current->section = Entry::FUNCTION_SEC; - tcl.entry_current->mtype = Method; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl_protection(tcl.entry_current); - tcl_command_ARGLIST(*tcl.list_commandwords.at(4)); - myEntryCl->moveToSubEntryAndKeep(tcl.entry_current); - tcl.fn.insert(myName,tcl.entry_current); - myEntry = tcl.entry_current; - myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6), - myNs, myEntryCl, myEntry); -} - -//! Handle \c constructor statements inside class definitions. -static void tcl_command_CONSTRUCTOR() -{ -D - QCString myNs, myName; - Entry *myEntryCl, *myEntry; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_codify_cmd(NULL,2); - tcl_codify_cmd(NULL,3); - tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)),myNs,myName); - if (myNs.length()) - { - myEntryCl = tcl_entry_class(myNs); - } - else - { - myNs = myScan->ns; - myEntryCl = myScan->entry_cl; - } - tcl.entry_current->section = Entry::FUNCTION_SEC; - tcl.entry_current->mtype = Method; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl_protection(tcl.entry_current); - tcl_command_ARGLIST(*tcl.list_commandwords.at(2)); - if (myEntryCl) myEntryCl->moveToSubEntryAndKeep(tcl.entry_current); - myEntry = tcl.entry_current; - tcl.fn.insert(myName,myEntry); - myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4), - myNs, myEntryCl, myEntry); -} - -//! Handle \c destructor statements inside class definitions. -static void tcl_command_DESTRUCTOR() -{ -D - QCString myNs, myName; - Entry *myEntryCl, *myEntry; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_name(myScan->ns,(*tcl.list_commandwords.at(0)),myNs,myName); - if (myNs.length()) - { - myEntryCl = tcl_entry_class(myNs); - } - else - { - myNs = myScan->ns; - myEntryCl = myScan->entry_cl; - } - tcl.entry_current->section = Entry::FUNCTION_SEC; - tcl.entry_current->mtype = Method; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl_protection(tcl.entry_current); - myEntryCl->moveToSubEntryAndKeep(tcl.entry_current); - myEntry = tcl.entry_current; - tcl.fn.insert(myName,myEntry); - myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(2), - myNs, myEntryCl, myEntry); -} - -//! Handle \c namespace statements. -static bool tcl_command_NAMESPACE() -{ -D - QCString myNs, myName, myStr; - //Entry *myEntryNs=NULL; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_name(myScan->ns,(*tcl.list_commandwords.at(4)),myNs,myName); - if (myName.isEmpty()) return false; // not a namespace - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_codify_cmd("keyword",2); - tcl_codify_cmd(NULL,3); - tcl_codify_cmd(NULL,4); - tcl_codify_cmd(NULL,5); - if (!myNs.isEmpty()) - { - myName = myNs+"::"+myName; - } - tcl.entry_current->section = Entry::NAMESPACE_SEC; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl.entry_main->moveToSubEntryAndKeep(tcl.entry_current); - tcl.ns.insert(myName,tcl.entry_current); - //myEntryNs = tcl.entry_current; - myStr = (*tcl.list_commandwords.at(6)); - if (tcl.list_commandwords.count() > 7) - { - for (uint i=7;i<tcl.list_commandwords.count();i++) - { - myStr.append((*tcl.list_commandwords.at(i))); - } - tcl.word_is=' '; - } - myScan = tcl_scan_start(tcl.word_is,myStr, myName, NULL, NULL); - return true; -} - -//! Handle \c itcl::class statements. -static void tcl_command_ITCL_CLASS() -{ -D - QCString myNs, myName; - Entry *myEntryCl; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_codify_cmd("NULL",2); - tcl_codify_cmd("NULL",3); - tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); - if (myNs.length()) - { - myName = myNs+"::"+myName; - } - tcl.entry_current->section = Entry::CLASS_SEC; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl.entry_main->moveToSubEntryAndKeep(tcl.entry_current); - tcl.cl.insert(myName,tcl.entry_current); - myEntryCl = tcl.entry_current; - myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(4), - myName, myEntryCl, NULL); -} - -//! Handle \c oo::class statements. -static void tcl_command_OO_CLASS() -{ -D - QCString myNs, myName; - //Entry *myEntryNs; - Entry *myEntryCl; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_codify_cmd("NULL",2); - tcl_codify_cmd("NULL",3); - tcl_codify_cmd("NULL",4); - tcl_codify_cmd("NULL",5); - tcl_name(myScan->ns,(*tcl.list_commandwords.at(4)),myNs,myName); - if (myNs.length()) - { - myName = myNs+"::"+myName; - } - tcl.entry_current->section = Entry::CLASS_SEC; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl.entry_main->moveToSubEntryAndKeep(tcl.entry_current); - //myEntryNs = tcl_entry_namespace(myName); - tcl.cl.insert(myName,tcl.entry_current); - myEntryCl = tcl.entry_current; - myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(6), - myName, myEntryCl, NULL); -} - -//! Handle \c oo::define statements. -static void tcl_command_OO_DEFINE() -{ -D - QCString myNs, myName, myStr; - Entry *myEntryCl; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl_codify_cmd("NULL",2); - tcl_codify_cmd("NULL",3); - tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); - if (myNs.length()) - { - myName = myNs+"::"+myName; - } - myEntryCl = tcl_entry_class(myName); - myStr = (*tcl.list_commandwords.at(4)); - // - // special cases first - // oo::define classname method methodname args script - // oo::define classname constructor argList bodyScript - // oo::define classname destructor bodyScript - unsigned int n =tcl.list_commandwords.count(); - if ((myStr == "method" && n == 11) || - (myStr == "constructor" && n == 9) || - (myStr == "destructor" && n == 7)) - { - for (unsigned int i = 4; i < n-1; i++) - { - tcl_codify_cmd("NULL",i); - } - Entry *myEntry; - QCString myMethod; - tcl_name(myScan->ns,(*tcl.list_commandwords.at(n==11?6:4)),myNs,myMethod); - // code snippet taken from tcl_command_METHOD()/tcl_command_CONSTRUCTOR - tcl.fn.remove(myMethod); - tcl.entry_current->section = Entry::FUNCTION_SEC; - tcl.entry_current->mtype = Method; - tcl.entry_current->name = myMethod; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl_protection(tcl.entry_current); - if (n==11) - { - tcl_command_ARGLIST(*tcl.list_commandwords.at(8)); - } - else if (n==9) - { - tcl_command_ARGLIST(*tcl.list_commandwords.at(6)); - } - if (myEntryCl) myEntryCl->moveToSubEntryAndKeep(tcl.entry_current); - tcl.fn.insert(myMethod,tcl.entry_current); - myEntry = tcl.entry_current; - myScan = tcl_scan_start('?',*tcl.list_commandwords.at(n-1), - myNs, myEntryCl, myEntry); - } - else - { - // The general case - // Simply concat all arguments into a script. - // Note: all documentation collected just before the - // oo::define command is lost - if (tcl.list_commandwords.count() > 5) - { - for (uint i=5;i<tcl.list_commandwords.count();i++) - { - myStr.append((*tcl.list_commandwords.at(i))); - } - tcl.word_is=' '; - } - myScan = tcl_scan_start(tcl.word_is,myStr,myName,myEntryCl,NULL); - } -} - -//! Handle \c variable statements. -static void tcl_command_VARIABLE(int inclass) -{ -D - QCString myNs, myName; - Entry *myEntry; - tcl_scan *myScan = tcl.scan.at(0); - - tcl_codify_cmd("keyword",0); - for (unsigned int i=1; i< tcl.list_commandwords.count(); i++) - { - tcl_codify_cmd(NULL,i); - } - tcl_name(myScan->ns,(*tcl.list_commandwords.at(2)),myNs,myName); - if (myNs.length()) - {// qualified variables go into namespace - myEntry = tcl_entry_namespace(myNs); - tcl.entry_current->stat = true; - } - else - { - if (inclass) - { - myEntry = myScan->entry_cl; - tcl.entry_current->stat = false; - } - else - { - myEntry = tcl_entry_namespace(myScan->ns); - tcl.entry_current->stat = true; - } - } - tcl.entry_current->section = Entry::VARIABLE_SEC; - tcl.entry_current->name = myName; - tcl.entry_current->startLine = tcl.line_command; - tcl.entry_current->docLine = tcl.line_comment; - tcl.entry_current->inbodyLine = tcl.line_comment; - tcl.entry_current->bodyLine = tcl.line_body0; - tcl.entry_current->endBodyLine = tcl.line_body1; - tcl_protection(tcl.entry_current); - myEntry->moveToSubEntryAndKeep(tcl.entry_current); - tcl.entry_current = tcl_entry_new(); -} - -//! Handling of command parsing. -//! what=0 -> ... -//! what=1 -> ... -//! what=-1 -> ... -static void tcl_command(int what,const char *text) -{ - int myLine=0; - if (what==0) - { - tcl.scan.at(0)->line1=yylineno;// current line in scan context - tcl.line_body0=yylineno;// start line of command -tcl_inf("<- %s\n",text); - yy_push_state(COMMAND); - tcl.list_commandwords.clear(); - tcl.string_command=""; - tcl.string_last=""; - tcl.command=1; - return; - } - else if (what==1) - { - if (tcl.string_last.length()) - { - tcl.list_commandwords.append(tcl.string_last); - tcl.string_last=""; - } - if (text) - { - tcl.list_commandwords.append(text); - } - return; - } - else if (what!=-1) - {// should not happen - tcl_err("what %d\n",what); - return; - } - QCString myText = text; -tcl_inf("->\n"); - if (tcl.command==0) - { - return; //TODO check on inside comment - } - if (tcl.string_last != "") - {// get last word - tcl.list_commandwords.append(tcl.string_last); - tcl.string_last=""; - } - yy_pop_state(); - - // check command - QCString myStr = (*tcl.list_commandwords.at(0)); - tcl_scan *myScanBackup=tcl.scan.at(0); - int myLevel = 0; - Protection myProt = tcl.protection; - - if (tcl.list_commandwords.count() < 3) - { - tcl_command_OTHER(); - goto command_end; - } - // remove leading "::" and apply TCL_SUBST - if (myStr.left(2)=="::") myStr = myStr.mid(2); - if (tcl.config_subst.contains(myStr)) - { - myStr=tcl.config_subst[myStr]; - } - if (myStr=="private") - { - tcl.protection = Private; - myLevel = 1; - } - else if (myStr=="protected") - { - tcl.protection = Protected; - myLevel = 1; - } - else if (myStr=="public") - { - tcl.protection = Public; - myLevel = 1; - } - if (myLevel) - { - tcl_codify_cmd("keyword",0); - tcl_codify_cmd(NULL,1); - tcl.list_commandwords.remove(tcl.list_commandwords.at(1)); - tcl.list_commandwords.remove(tcl.list_commandwords.at(0)); - if (tcl.list_commandwords.count()==1) - { - tcl_scan *myScan = tcl.scan.at(0); - myScan = tcl_scan_start(tcl.word_is,*tcl.list_commandwords.at(0), - myScan->ns,myScan->entry_cl,myScan->entry_fn); - myProt = tcl.protection; - goto command_end; - } - myStr = (*tcl.list_commandwords.at(0)); - // remove leading "::" and apply TCL_SUBST - if (myStr.left(2)=="::") myStr = myStr.mid(2); - if (tcl.config_subst.contains(myStr)) - { - myStr=tcl.config_subst[myStr]; - } - } - if (myStr=="proc") - { - if (tcl.list_commandwords.count() == 5) - {// itcl::proc - tcl.list_commandwords.append(""); - tcl.list_commandwords.append(""); - } - if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} - tcl_command_PROC(); - goto command_end; - } - if (myStr=="method") - { - if (tcl.list_commandwords.count() == 5) - {// itcl::method - tcl.list_commandwords.append(""); - tcl.list_commandwords.append(""); - } - if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} - tcl_command_METHOD(); - goto command_end; - } - if (myStr=="constructor") - { - if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;} - tcl_command_CONSTRUCTOR(); - goto command_end; - } - if (myStr=="destructor") - { - if (tcl.list_commandwords.count() != 3) {myLine=__LINE__;goto command_warn;} - tcl_command_DESTRUCTOR(); - goto command_end; - } - if (myStr=="namespace") - { - if ((*tcl.list_commandwords.at(2))=="eval") - { - if (tcl.list_commandwords.count() < 7) {myLine=__LINE__;goto command_warn;} - if (tcl_command_NAMESPACE()) - { - goto command_end; - } - } - else - { - tcl_command_OTHER(); - goto command_end; - } - } - if (myStr=="itcl::class") - { - if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;} - tcl_command_ITCL_CLASS(); - goto command_end; - } - if (myStr=="itcl::body") - { - if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} - tcl_command_METHOD(); - goto command_end; - } - if (myStr=="oo::class") - { - if ((*tcl.list_commandwords.at(2))=="create") - { - if (tcl.list_commandwords.count() != 7) {myLine=__LINE__;goto command_warn;} - tcl_command_OO_CLASS(); - goto command_end; - } - tcl_command_OTHER(); - goto command_end; - } - if (myStr=="oo::define") - { - if (tcl.list_commandwords.count() < 5) {myLine=__LINE__;goto command_warn;} - tcl_command_OO_DEFINE(); - goto command_end; - } - if (myStr=="variable") - { - if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} - if (tcl.scan.at(0)->entry_fn == NULL) - {// only parsed outside functions - tcl_command_VARIABLE(tcl.scan.at(0)->entry_cl && tcl.scan.at(0)->entry_cl->name!=""); - goto command_end; - } - } - if (myStr=="common") - { - if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} - if (tcl.scan.at(0)->entry_fn == NULL) - {// only parsed outside functions - tcl_command_VARIABLE(0); - goto command_end; - } - } - if (myStr=="inherit" || myStr=="superclass") - { - if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} - if (tcl.scan.at(0)->entry_cl && tcl.scan.at(0)->entry_cl->name!="") - { - for (unsigned int i = 2; i < tcl.list_commandwords.count(); i = i + 2) - { - tcl.scan.at(0)->entry_cl->extends.push_back(BaseInfo((*tcl.list_commandwords.at(i)),Public,Normal)); - } - } - goto command_end; - } - /* - * Start of internal tcl keywords - * Ready: switch, eval, catch, if, for, foreach, while - */ - if (myStr=="switch") - { - if (tcl.list_commandwords.count() < 5) {myLine=__LINE__;goto command_warn;} - tcl_command_SWITCH(); - goto command_end; - } - if (myStr=="eval") - { - if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} - tcl_command_EVAL(); - goto command_end; - } - if (myStr=="catch") - { - if (tcl.list_commandwords.count() < 3) {myLine=__LINE__;goto command_warn;} - tcl_command_CATCH(); - goto command_end; - } - if (myStr=="for") - { - if (tcl.list_commandwords.count() != 9) {myLine=__LINE__;goto command_warn;} - tcl_command_FOR(); - goto command_end; - } - if (myStr=="foreach") - { - if (tcl.list_commandwords.count() < 7 || tcl.list_commandwords.count()%2==0) {myLine=__LINE__;goto command_warn;} - tcl_command_FOREACH(); - goto command_end; - } - /* -if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN? - */ - if (myStr=="if" && tcl.list_commandwords.count() > 4) - { - QCStringList myType; - myType << "keyword" << "NULL" << "expr" << "NULL"; - char myState='x';// last word: e'x'pr 't'hen 'b'ody 'e'lse else'i'f.. - for (unsigned int i = 4; i < tcl.list_commandwords.count(); i = i + 2) - { - QCString myStr=(*tcl.list_commandwords.at(i)); - if (myState=='x') - { - if (myStr=="then") - { - myState='t'; - myType << "keyword" << "NULL"; - } - else - { - myState='b'; - myType << "script" << "NULL"; - } - } - else if (myState=='t') - { - myState='b'; - myType << "script" << "NULL"; - } - else if (myState=='b') - { - if (myStr=="elseif") { - myState='i'; - myType << "keyword" << "NULL"; - } - else if (myStr=="else" && i==tcl.list_commandwords.count()-3) - { - myState = 'b'; - myType << "keyword" << "NULL" << "script"; - i = tcl.list_commandwords.count(); - } - else if (i==tcl.list_commandwords.count()-1) - { - myState = 'b'; - myType << "script"; - i = tcl.list_commandwords.count(); - } - else - { - myLine=__LINE__;goto command_warn; - } - } - else if (myState=='i') - { - myState='x'; - myType << "expr" << "NULL"; - } - } - if (myState != 'b') {myLine=__LINE__;goto command_warn;} - tcl_command_IF(myType); - goto command_end; - } - if (myStr=="while") - { - if (tcl.list_commandwords.count() != 5) {myLine=__LINE__;goto command_warn;} - tcl_command_WHILE(); - goto command_end; - } - tcl_command_OTHER(); - goto command_end; - command_warn:// print warning message because of wrong used syntax - tcl_war("%d count=%d: %s\n",myLine,tcl.list_commandwords.count(),tcl.list_commandwords.join(" ").data()); - tcl_command_OTHER(); - command_end:// add remaining text to current context - if (!myText.isEmpty()) - { - if(myScanBackup==tcl.scan.at(0)) - { - tcl_codify("comment",myText); - } - else - { - tcl.scan.at(0)->after << "comment" << myText; - } - } - tcl.list_commandwords.clear(); - tcl.command = 0; - tcl.protection = myProt; -} - -//---------------------------------------------------------------------------- -//! Common initializations. -static void tcl_init() -{ - // Get values from option TCL_SUBST - tcl.config_subst.clear(); - QStrList myStrList = Config_getList(TCL_SUBST); - const char *s=myStrList.first(); - while (s) - { - QCString myStr=s; - int i=myStr.find('='); - if (i>0) - { - QCString myName=myStr.left(i).stripWhiteSpace(); - QCString myValue=myStr.right(myStr.length()-i-1).stripWhiteSpace(); - if (!myName.isEmpty() && !myValue.isEmpty()) - tcl_inf("TCL_SUBST: use '%s'\n",s); - tcl.config_subst[myName] = myValue; - } - s = myStrList.next(); - } - - if (tcl.input_string.at(tcl.input_string.length()-1) == 0x1A) - { - } - else if (tcl.input_string.at(tcl.input_string.length()-1) == '\n') - { - tcl.input_string[tcl.input_string.length()-1] = 0x1A; - } - else - { - tcl.input_string += 0x1A; - } - - tcl.code = NULL; - tcl.code_font=NULL; - tcl.code_line=1; - tcl.code_linenumbers=1; - tcl.config_autobrief = Config_getBool(JAVADOC_AUTOBRIEF); - tcl.input_position = 0; - tcl.file_name = NULL; - tcl.this_parser = NULL; - tcl.command=0; - tcl.comment=0; - tcl.brace_level=0; - tcl.bracket_level=0; - tcl.bracket_quote=0; - tcl.word_is=' '; - tcl.string_command=""; - tcl.string_commentline=""; - tcl.string_commentcodify=""; - tcl.string_comment = ""; - tcl.string_last = ""; - tcl.entry_main = NULL; - tcl.entry_file = NULL; - tcl.entry_current = NULL; - tcl.entry_inside = NULL; - tcl.list_commandwords.clear(); - tcl.scan.clear(); - tcl.ns.clear(); - tcl.cl.clear(); - tcl.fn.clear(); - yylineno = 1; - tcl.protection = Public; - tcl.memberdef = NULL; -} - -//! Start parsing. -static void tcl_parse(const QCString ns, const QCString cls) -{ - tcl_scan *myScan; - - tcl.entry_file = tcl_entry_new(); - tcl.entry_file->name = tcl.file_name; - tcl.entry_file->section = Entry::SOURCE_SEC; - tcl.entry_file->protection = Public; - tcl.entry_main->moveToSubEntryAndKeep(tcl.entry_file); - Entry *myEntry=tcl_entry_new(); - myEntry->name=""; - tcl.entry_main->moveToSubEntryAndKeep(myEntry); - tcl.ns.insert("::",myEntry); - tcl.entry_current = tcl_entry_new(); - - tclscannerYYrestart( tclscannerYYin ); - BEGIN( TOP ); - yylineno=1; - myScan = new tcl_scan; - myScan->type[0]=' ';myScan->type[1]='\n'; - myScan->after.clear(); - myScan->line0=yylineno; - myScan->line1=yylineno; - myScan->buffer_state=YY_CURRENT_BUFFER; - myScan->ns=ns; - myScan->entry_cl=tcl_entry_class(cls); - myScan->entry_fn=NULL; - tcl.entry_inside = tcl.entry_file; - myScan->entry_scan = tcl.entry_inside; - tcl.scan.insert(0,myScan); - tclscannerYYlex(); - tcl.scan.clear(); - tcl.ns.clear(); - tcl.cl.clear(); - tcl.fn.clear(); - tcl.entry.clear(); -} - -//! Parse text file and build up entry tree. -void TclOutlineParser::parseInput(const char *fileName, - const char *input, - const std::shared_ptr<Entry> &root, - bool /*sameTranslationUnit*/, - QStrList & /*filesInSameTranslationUnit*/) -{ - QFile myFile; -tcl_inf("%s\n",fileName); - myFile.setName(fileName); - if (!myFile.open(IO_ReadOnly)) return; - if (strlen(input)<1) return; - - tcl.input_string = input; - if (tcl.input_string.length()<1) return; - printlex(yy_flex_debug, TRUE, __FILE__, fileName); - - msg("Parsing %s...\n",fileName); - Doxygen::docGroup.enterFile(fileName,yylineno); - - tcl_init(); - tcl.code = NULL; - tcl.file_name = fileName; - tcl.this_parser = this; - tcl.entry_main = root.get(); /* toplevel entry */ - tcl_parse("",""); - Doxygen::docGroup.leaveFile(tcl.file_name,yylineno); - root->program.resize(0); - myFile.close(); - printlex(yy_flex_debug, FALSE, __FILE__, fileName); -} - - -bool TclOutlineParser::needsPreprocessing(const QCString &extension) const -{ - (void)extension; - return FALSE; -} - -void TclOutlineParser::parsePrototype(const char *text) -{ - (void)text; -} - -static int yyread(char *buf,int max_size) -{ - int c=0; - - *buf = '\0'; - while ( c < max_size && tcl.input_string.at(tcl.input_position) ) - { - *buf = tcl.input_string.at(tcl.input_position++) ; - c++; buf++; - } - //printf("Read from=%d size=%d max=%d c=%d\n",tcl.input_position,strlen(&tcl.input_string[tcl.input_position]),max_size,c); - return c; -} - -//---------------------------------------------------------------------------- - -void TclCodeParser::resetCodeParserState() -{ -} - -//! Parse file and codify. -void TclCodeParser::parseCode(CodeOutputInterface & codeOutIntf, - const char * scopeName, - const QCString & input, - SrcLangExt lang, - bool isExampleBlock, - const char * exampleName, - FileDef * fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - (void)scopeName; - (void)lang; - (void)exampleName; - (void)fileDef; - (void)endLine; - (void)inlineFragment; - (void)searchCtx; - (void)collectXRefs; - - if (input.length()<1) return; - printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); - tcl.input_string = input; - - QCString myNs=""; - QCString myCls=""; - if (memberDef) - { - if (memberDef->getClassDef()) - { - myCls = memberDef->getClassDef()->displayName(); - myNs = myCls; - } - else if (memberDef->getNamespaceDef()) - { - myNs = memberDef->getNamespaceDef()->displayName(); - } - } - - QCString myStr="Codifying.."; - if (scopeName) - { - myStr +=" scope="; - myStr+=scopeName; - } - if (exampleName) - { - myStr+=" example="; - myStr+=exampleName; - } - if (memberDef) - { - myStr+=" member="; - myStr+=memberDef->memberTypeName(); - myStr+=" "; - myStr+=memberDef->qualifiedName(); - } - if (fileDef) - { - myStr+=" file="; - myStr+=fileDef->fileName(); - } -tcl_inf("%s (%d,%d) %d %d\n",myStr.data(),startLine,endLine,isExampleBlock,inlineFragment); -//tcl_inf("%s\n"input.data()); - tcl_init(); - tcl.collectXRefs = collectXRefs; - tcl.memberdef = memberDef; - tcl.code = &codeOutIntf; - if (startLine<0) - { - startLine=1; - } - yylineno=startLine; - tcl.code_linenumbers = showLineNumbers; - tcl.code_line=yylineno; - tcl.code->startCodeLine(tcl.code_linenumbers); - if (tcl.code_linenumbers) - { - tcl.code->writeLineNumber(0,0,0,tcl.code_line); - } - tcl.file_name = ""; - tcl.this_parser = NULL; - if (isExampleBlock) - { - tcl_codify(NULL,input); - } - else - { - tcl.entry_main = tcl_entry_new(); - tcl_parse(myNs,myCls); - } - tcl.code->endCodeLine(); - tcl.scan.clear(); - tcl.ns.clear(); - tcl.cl.clear(); - tcl.fn.clear(); - tcl.entry.clear(); - printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); -} -//---------------------------------------------------------------------------- - -// to avoid a warning -void tclDummy() -{ - yy_top_state(); -} - -#include "tclscanner.l.h" diff --git a/src/template.cpp b/src/template.cpp index ca28c73..66347c4 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -48,10 +48,10 @@ class TemplateToken; //------------------------------------------------------------------- -static QValueList<QCString> split(const QCString &str,const QCString &sep, +static std::vector<QCString> split(const QCString &str,const QCString &sep, bool allowEmptyEntries=FALSE,bool cleanup=TRUE) { - QValueList<QCString> lst; + std::vector<QCString> lst; int j = 0; int i = str.find( sep, j ); @@ -62,16 +62,16 @@ static QValueList<QCString> split(const QCString &str,const QCString &sep, { if (cleanup) { - lst.append(str.mid(j,i-j).stripWhiteSpace()); + lst.push_back(str.mid(j,i-j).stripWhiteSpace()); } else { - lst.append(str.mid(j,i-j)); + lst.push_back(str.mid(j,i-j)); } } else if (allowEmptyEntries) { - lst.append(""); + lst.push_back(""); } j = i + sep.length(); i = str.find(sep,j); @@ -82,16 +82,16 @@ static QValueList<QCString> split(const QCString &str,const QCString &sep, { if (cleanup) { - lst.append(str.mid(j,l-j+1).stripWhiteSpace()); + lst.push_back(str.mid(j,l-j+1).stripWhiteSpace()); } else { - lst.append(str.mid(j,l-j+1)); + lst.push_back(str.mid(j,l-j+1)); } } else if (allowEmptyEntries) { - lst.append(""); + lst.push_back(""); } return lst; @@ -305,7 +305,7 @@ class TemplateList::Private { public: Private() : index(-1), refCount(0) {} - QValueList<TemplateVariant> elems; + std::vector<TemplateVariant> elems; int index = -1; int refCount = 0; }; @@ -336,69 +336,67 @@ int TemplateList::release() return count; } -int TemplateList::count() const +uint TemplateList::count() const { - return p->elems.count(); + return p->elems.size(); } void TemplateList::append(const TemplateVariant &v) { - p->elems.append(v); + p->elems.push_back(v); } // iterator support class TemplateListConstIterator : public TemplateListIntf::ConstIterator { public: - TemplateListConstIterator(const TemplateList &l) : m_list(l) { m_index=-1; } + TemplateListConstIterator(const TemplateList &l) : m_list(l) { m_index=0; } virtual ~TemplateListConstIterator() {} virtual void toFirst() { - m_it = m_list.p->elems.begin(); m_index=0; } virtual void toLast() { - m_it = m_list.p->elems.fromLast(); - m_index=m_list.count()-1; + if (m_list.p->elems.size()>0) + { + m_index=m_list.p->elems.size()-1; + } + else + { + m_index=0; + } } virtual void toNext() { - if (m_it!=m_list.p->elems.end()) + if (m_index<m_list.p->elems.size()) { - ++m_it; - ++m_index; + m_index++; } } virtual void toPrev() { if (m_index>0) { - --m_it; --m_index; } - else - { - m_index=-1; - } } virtual bool current(TemplateVariant &v) const { - if (m_index<0 || m_it==m_list.p->elems.end()) + if (m_index<m_list.p->elems.size()) { - v = TemplateVariant(); - return FALSE; + v = m_list.p->elems[m_index]; + return TRUE; } else { - v = *m_it; - return TRUE; + v = TemplateVariant(); + return FALSE; } } private: const TemplateList &m_list; - QValueList<TemplateVariant>::ConstIterator m_it; - int m_index = 0; + size_t m_index = 0; }; TemplateListIntf::ConstIterator *TemplateList::createIterator() const @@ -406,9 +404,9 @@ TemplateListIntf::ConstIterator *TemplateList::createIterator() const return new TemplateListConstIterator(*this); } -TemplateVariant TemplateList::at(int index) const +TemplateVariant TemplateList::at(uint index) const { - if (index>=0 && index<(int)p->elems.count()) + if (index<p->elems.size()) { return p->elems[index]; } @@ -545,7 +543,7 @@ class TemplateContextImpl : public TemplateContext QCString outputDirectory() const { return m_outputDir; } TemplateEscapeIntf *escapeIntf() const { return m_activeEscapeIntf; } TemplateSpacelessIntf *spacelessIntf() const { return m_spacelessIntf; } - void enableSpaceless(bool b) { if (b && !m_spacelessEnabled) m_spacelessIntf->reset(); + void enableSpaceless(bool b) { if (b && !m_spacelessEnabled) m_spacelessIntf->reset(); m_spacelessEnabled=b; } bool spacelessEnabled() const { return m_spacelessEnabled && m_spacelessIntf; } @@ -562,7 +560,7 @@ class TemplateContextImpl : public TemplateContext // index related functions void openSubIndex(const QCString &indexName); void closeSubIndex(const QCString &indexName); - void addIndexEntry(const QCString &indexName,const QValueList<TemplateKeyValue> &arguments); + void addIndexEntry(const QCString &indexName,const std::vector<TemplateKeyValue> &arguments); private: const TemplateEngine *m_engine = 0; @@ -780,7 +778,7 @@ class FilterLength } if (v.type()==TemplateVariant::List) { - return TemplateVariant(v.toList()->count()); + return TemplateVariant((int)v.toList()->count()); } else if (v.type()==TemplateVariant::String) { @@ -1125,7 +1123,7 @@ class FilterAlphaIndex { int i=0; if (startLetter>='0' && startLetter<='9') s[i++] = 'x'; - s[i++]=tolower((char)startLetter); + s[i++]=(char)tolower((char)startLetter); s[i++]=0; } else @@ -1483,11 +1481,11 @@ class ExprAstFunctionVariable : public ExprAst } virtual TemplateVariant resolve(TemplateContext *c) { - QValueList<TemplateVariant> args; + std::vector<TemplateVariant> args; for (uint i=0;i<m_args.count();i++) { TemplateVariant v = m_args.at(i)->resolve(c); - args.append(v); + args.push_back(v); } TemplateVariant v = m_var->resolve(c); if (v.type()==TemplateVariant::Function) @@ -2268,7 +2266,6 @@ class ExpressionParser if (p==q) // still no valid token found -> error { m_curToken.type = ExprToken::Unknown; - char s[2]; s[0]=c; s[1]=0; warn(m_parser->templateName(),m_line,"Found unknown token '%s' (%d) while parsing %s",s,c,m_tokenStream); @@ -2608,7 +2605,7 @@ static void getPathListFunc(TemplateStructIntf *entry,TemplateList *list) list->append(entry); } -static TemplateVariant getPathFunc(const void *ctx, const QValueList<TemplateVariant> &) +static TemplateVariant getPathFunc(const void *ctx, const std::vector<TemplateVariant> &) { TemplateStruct *entry = (TemplateStruct*)ctx; TemplateList *result = TemplateList::alloc(); @@ -2616,9 +2613,9 @@ static TemplateVariant getPathFunc(const void *ctx, const QValueList<TemplateVar return result; } -void TemplateContextImpl::addIndexEntry(const QCString &indexName,const QValueList<TemplateKeyValue> &arguments) +void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vector<TemplateKeyValue> &arguments) { - QValueListConstIterator<TemplateKeyValue> it = arguments.begin(); + auto it = arguments.begin(); //printf("TemplateContextImpl::addIndexEntry(%s)\n",indexName.data()); //while (it!=arguments.end()) //{ @@ -2760,7 +2757,7 @@ class TemplateNodeVariable : public TemplateNode TemplateVariant v = m_var->resolve(c); if (v.type()==TemplateVariant::Function) { - v = v.call(QValueList<TemplateVariant>()); + v = v.call(std::vector<TemplateVariant>()); } if (ci->escapeIntf() && !v.raw()) { @@ -2844,7 +2841,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; @@ -2877,19 +2878,21 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf> stopAt.append("else"); // if 'nodes' - GuardedNodes *guardedNodes = new GuardedNodes; - ExpressionParser ex(parser,line); - guardedNodes->line = line; - guardedNodes->guardAst = ex.parse(data); - parser->parse(this,line,stopAt,guardedNodes->trueNodes); - m_ifGuardedNodes.append(guardedNodes); + { + GuardedNodes *guardedNodes = new GuardedNodes; + ExpressionParser ex(parser,line); + guardedNodes->line = line; + guardedNodes->guardAst = ex.parse(data); + parser->parse(this,line,stopAt,guardedNodes->trueNodes); + m_ifGuardedNodes.append(guardedNodes); + } TemplateToken *tok = parser->takeNextToken(); // elif 'nodes' while (tok && tok->data.left(5)=="elif ") { ExpressionParser ex(parser,line); - guardedNodes = new GuardedNodes; + GuardedNodes *guardedNodes = new GuardedNodes; guardedNodes->line = tok->line; guardedNodes->guardAst = ex.parse(tok->data.mid(5)); parser->parse(this,tok->line,stopAt,guardedNodes->trueNodes); @@ -3119,15 +3122,15 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange> while (!done) { // set the forloop meta-data variable - TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc()); - s->set("counter0", (int)index); - s->set("counter", (int)(index+1)); - s->set("revcounter", (int)(l-index)); - s->set("revcounter0", (int)(l-index-1)); - s->set("first",index==0); - s->set("last", (int)index==l-1); - s->set("parentloop",parentLoop ? *parentLoop : TemplateVariant()); - c->set("forloop",s.get()); + TemplateAutoRef<TemplateStruct> ls(TemplateStruct::alloc()); + ls->set("counter0", (int)index); + ls->set("counter", (int)(index+1)); + ls->set("revcounter", (int)(l-index)); + ls->set("revcounter0", (int)(l-index-1)); + ls->set("first",index==0); + ls->set("last", (int)index==l-1); + ls->set("parentloop",parentLoop ? *parentLoop : TemplateVariant()); + c->set("forloop",ls.get()); // set the iterator variable c->set(m_var,i); @@ -3212,7 +3215,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> else { m_vars = split(data.left(i),","); - if (m_vars.count()==0) + if (m_vars.size()==0) { parser->warn(m_templateName,line,"for needs at least one iterator variable"); } @@ -3265,7 +3268,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> TemplateVariant v = m_expr->resolve(c); if (v.type()==TemplateVariant::Function) { - v = v.call(QValueList<TemplateVariant>()); + v = v.call(std::vector<TemplateVariant>()); } const TemplateListIntf *list = v.toList(); if (list) @@ -3278,12 +3281,13 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> } c->push(); //int index = m_reversed ? list.count() : 0; - TemplateVariant v; + //TemplateVariant v; const TemplateVariant *parentLoop = c->getRef("forloop"); uint index = m_reversed ? listSize-1 : 0; TemplateListIntf::ConstIterator *it = list->createIterator(); + TemplateVariant ve; for (m_reversed ? it->toLast() : it->toFirst(); - (it->current(v)); + (it->current(ve)); m_reversed ? it->toPrev() : it->toNext()) { TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc()); @@ -3299,19 +3303,19 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> // add variables for this loop to the context //obj->addVariableToContext(index,m_vars,c); uint vi=0; - if (m_vars.count()==1) // loop variable represents an item + if (m_vars.size()==1) // loop variable represents an item { - c->set(m_vars[vi++],v); + c->set(m_vars[vi++],ve); } - else if (m_vars.count()>1 && v.type()==TemplateVariant::Struct) + else if (m_vars.size()>1 && ve.type()==TemplateVariant::Struct) // loop variables represent elements in a list item { - for (uint i=0;i<m_vars.count();i++,vi++) + for (uint i=0;i<m_vars.size();i++,vi++) { - c->set(m_vars[vi],v.toStruct()->get(m_vars[vi])); + c->set(m_vars[vi],ve.toStruct()->get(m_vars[vi])); } } - for (;vi<m_vars.count();vi++) + for (;vi<m_vars.size();vi++) { c->set(m_vars[vi],TemplateVariant()); } @@ -3334,7 +3338,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> private: bool m_reversed = false; ExprAst *m_expr = 0; - QValueList<QCString> m_vars; + std::vector<QCString> m_vars; TemplateNodeList m_loopNodes; TemplateNodeList m_emptyNodes; }; @@ -3622,7 +3626,6 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> : TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line), m_templateExpr(0), m_fileExpr(0) { TRACE(("TemplateNodeCreate(%s)\n",data.data())); - ExpressionParser ep(parser,line); if (data.isEmpty()) { parser->warn(m_templateName,line,"create tag is missing arguments"); @@ -3762,7 +3765,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> { delete m_treeExpr; } - static TemplateVariant renderChildrenStub(const void *ctx, const QValueList<TemplateVariant> &) + static TemplateVariant renderChildrenStub(const void *ctx, const std::vector<TemplateVariant> &) { return TemplateVariant(((TreeContext*)ctx)->object-> renderChildren((const TreeContext*)ctx),TRUE); @@ -3862,8 +3865,8 @@ class TemplateNodeIndexEntry : public TemplateNodeCreator<TemplateNodeIndexEntry TRACE(("{TemplateNodeIndexEntry(%s)\n",data.data())); m_args.setAutoDelete(TRUE); ExpressionParser expParser(parser,line); - QValueList<QCString> args = split(data," "); - QValueListIterator<QCString> it = args.begin(); + std::vector<QCString> args = split(data," "); + auto it = args.begin(); if (it==args.end() || (*it).find('=')!=-1) { parser->warn(parser->templateName(),line,"Missing name for indexentry tag"); @@ -3902,10 +3905,10 @@ class TemplateNodeIndexEntry : public TemplateNodeCreator<TemplateNodeIndexEntry ci->setLocation(m_templateName,m_line); QListIterator<Mapping> it(m_args); Mapping *mapping; - QValueList<TemplateKeyValue> list; + std::vector<TemplateKeyValue> list; for (it.toFirst();(mapping=it.current());++it) { - list.append(TemplateKeyValue(mapping->name,mapping->value->resolve(c))); + list.push_back(TemplateKeyValue(mapping->name,mapping->value->resolve(c))); } ci->addIndexEntry(m_name,list); } @@ -4008,8 +4011,8 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> m_args.setAutoDelete(TRUE); ExpressionParser expParser(parser,line); QCString filteredData = removeSpacesAroundEquals(data); - QValueList<QCString> args = split(filteredData," "); - QValueListIterator<QCString> it = args.begin(); + std::vector<QCString> args = split(filteredData," "); + auto it = args.begin(); while (it!=args.end()) { QCString arg = *it; @@ -4071,8 +4074,8 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle> m_args.setAutoDelete(TRUE); m_index=0; ExpressionParser expParser(parser,line); - QValueList<QCString> args = split(data," "); - QValueListIterator<QCString> it = args.begin(); + std::vector<QCString> args = split(data," "); + auto it = args.begin(); while (it!=args.end()) { ExprAst *expr = expParser.parse(*it); @@ -4097,7 +4100,7 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle> TemplateVariant v = m_args.at(m_index)->resolve(c); if (v.type()==TemplateVariant::Function) { - v = v.call(QValueList<TemplateVariant>()); + v = v.call(std::vector<TemplateVariant>()); } if (ci->escapeIntf() && !v.raw()) { @@ -4979,7 +4982,7 @@ TemplateToken *TemplateParser::takeNextToken() const TemplateToken *TemplateParser::currentToken() const { return m_tokens.getFirst(); -}; +} void TemplateParser::removeNextToken() { diff --git a/src/template.h b/src/template.h index 4602c53..c9e9041 100644 --- a/src/template.h +++ b/src/template.h @@ -17,7 +17,7 @@ #define TEMPLATE_H #include <qcstring.h> -#include <qvaluelist.h> +#include <vector> class FTextStream; @@ -95,12 +95,12 @@ class TemplateVariant { public: /** Callback type to use when creating a delegate from a function. */ - typedef TemplateVariant (*StubType)(const void *obj, const QValueList<TemplateVariant> &args); + typedef TemplateVariant (*StubType)(const void *obj, const std::vector<TemplateVariant> &args); Delegate() : m_objectPtr(0) , m_stubPtr(0) {} /** Creates a delegate given an object. The method to call is passed as a template parameter */ - template <class T, TemplateVariant (T::*TMethod)(const QValueList<TemplateVariant> &) const> + template <class T, TemplateVariant (T::*TMethod)(const std::vector<TemplateVariant> &) const> static Delegate fromMethod(const T* objectPtr) { Delegate d; @@ -118,7 +118,7 @@ class TemplateVariant } /** Invokes the function/method stored in the delegate */ - TemplateVariant operator()(const QValueList<TemplateVariant> &args) const + TemplateVariant operator()(const std::vector<TemplateVariant> &args) const { return (*m_stubPtr)(m_objectPtr, args); } @@ -127,8 +127,8 @@ class TemplateVariant const void* m_objectPtr; StubType m_stubPtr; - template <class T, TemplateVariant (T::*TMethod)(const QValueList<TemplateVariant> &) const> - static TemplateVariant methodStub(const void* objectPtr, const QValueList<TemplateVariant> &args) + template <class T, TemplateVariant (T::*TMethod)(const std::vector<TemplateVariant> &) const> + static TemplateVariant methodStub(const void* objectPtr, const std::vector<TemplateVariant> &args) { T* p = (T*)(objectPtr); return (p->*TMethod)(args); @@ -269,7 +269,7 @@ class TemplateVariant /** Return the result of apply this function with \a args. * Returns an empty string if the variant type is not a function. */ - TemplateVariant call(const QValueList<TemplateVariant> &args) + TemplateVariant call(const std::vector<TemplateVariant> &args) { if (m_type==Function) return m_delegate(args); return TemplateVariant(); @@ -355,10 +355,10 @@ class TemplateListIntf virtual ~TemplateListIntf() {} /** Returns the number of elements in the list */ - virtual int count() const = 0; + virtual uint count() const = 0; /** Returns the element at index position \a index. */ - virtual TemplateVariant at(int index) const = 0; + virtual TemplateVariant at(uint index) const = 0; /** Creates a new iterator for this list. * @note the user should call delete on the returned pointer. @@ -377,8 +377,8 @@ class TemplateList : public TemplateListIntf { public: // TemplateListIntf methods - virtual int count() const; - virtual TemplateVariant at(int index) const; + virtual uint count() const; + virtual TemplateVariant at(uint index) const; virtual TemplateListIntf::ConstIterator *createIterator() const; virtual int addRef(); virtual int release(); @@ -457,6 +457,7 @@ class TemplateStruct : public TemplateStructIntf class TemplateEscapeIntf { public: + virtual ~TemplateEscapeIntf() {} /** Returns the \a input after escaping certain characters */ virtual QCString escape(const QCString &input) = 0; /** Setting tabbing mode on or off (for LaTeX) */ @@ -469,6 +470,7 @@ class TemplateEscapeIntf class TemplateSpacelessIntf { public: + virtual ~TemplateSpacelessIntf() {} /** Returns the \a input after removing redundant whitespace */ virtual QCString remove(const QCString &input) = 0; /** Reset filter state */ diff --git a/src/threadpool.h b/src/threadpool.h new file mode 100644 index 0000000..5239fd4 --- /dev/null +++ b/src/threadpool.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef THREADPOOL_H +#define THREADPOOL_H + +#include <condition_variable> +#include <deque> +#include <functional> +#include <future> +#include <mutex> +#include <thread> +#include <type_traits> +#include <utility> +#include <vector> + +/// Class managing a pool of worker threads. +/// Work can be queued by passing a function to queue(). A future will be +/// returned that can be used to obtain the result of the function after execution. +/// +/// Usage example: +/// @code +/// ThreadPool pool(10); +/// std::vector< std::future< int > > results; +/// for (int i=0;i<10;i++) +/// { +/// auto run = [](int i) { return i*i; }; +/// results.emplace_back(pool.queue(std::bind(run,i))); +/// } +/// for (auto &f : results) +/// { +/// printf("Result %d:\n", f.get()); +/// } +/// @endcode +class ThreadPool +{ + public: + /// start N threads in the thread pool. + ThreadPool(std::size_t N=1) + { + for (std::size_t i = 0; i < N; ++i) + { + // each thread is a std::async running thread_task(): + m_finished.push_back( + std::async( + std::launch::async, + [this]{ threadTask(); } + ) + ); + } + } + /// deletes the thread pool by finishing all threads + ~ThreadPool() + { + finish(); + } + + /// Queue the callable function \a f for the threads to execute. + /// A future of the return type of the function is returned to capture the result. + template<class F, class R=std::result_of_t<F&()> > + std::future<R> queue(F&& f) + { + // We wrap the function object into a packaged task, splitting + // execution from the return value. + // Since the packaged_task object is not copyable, we create it on the heap + // and capture it via a shared pointer in a lambda and then assign that lambda + // to a std::function. + auto ptr = std::make_shared< std::packaged_task<R()> >(std::forward<F>(f)); + auto taskFunc = [ptr]() { if (ptr->valid()) (*ptr)(); }; + + auto r=ptr->get_future(); // get the return value before we hand off the task + { + std::unique_lock<std::mutex> l(m_mutex); + m_work.emplace_back(taskFunc); + m_cond.notify_one(); // wake a thread to work on the task + } + + return r; // return the future result of the task + } + + /// finish enques a "stop the thread" message for every thread, + /// then waits for them to finish + void finish() + { + { + std::unique_lock<std::mutex> l(m_mutex); + for(auto&& u : m_finished) + { + unused_variable(u); + m_work.push_back({}); // insert empty function object to signal abort + } + } + m_cond.notify_all(); + m_finished.clear(); + } + private: + + // helper to silence the compiler warning about unused variables + template <typename ...Args> + void unused_variable(Args&& ...args) { (void)(sizeof...(args)); } + + // the work that a worker thread does: + void threadTask() + { + while(true) + { + // pop a task off the queue: + std::function<void()> f; + { + // usual thread-safe queue code: + std::unique_lock<std::mutex> l(m_mutex); + if (m_work.empty()) + { + m_cond.wait(l,[&]{return !m_work.empty();}); + } + f = std::move(m_work.front()); + m_work.pop_front(); + } + // if the function is empty, it means we are asked to abort + if (!f) return; + // run the task + f(); + } + } + + // the mutex, condition variable and deque form a single + // thread-safe triggered queue of tasks: + std::mutex m_mutex; + std::condition_variable m_cond; + + // hold the queue of work + std::deque< std::function<void()> > m_work; + + // this holds futures representing the worker threads being done: + std::vector< std::future<void> > m_finished; +}; + +#endif + diff --git a/src/translator.h b/src/translator.h index 188b775..bcc70ff 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. @@ -73,6 +78,7 @@ class Translator } return latex_command; } + virtual QCString trISOLang() = 0; // --- Language translation methods ------------------- @@ -588,7 +594,6 @@ class Translator virtual QCString trClassMethods() = 0; virtual QCString trInstanceMethods() = 0; virtual QCString trMethodDocumentation() = 0; - virtual QCString trDesignOverview() = 0; ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 @@ -646,6 +651,12 @@ class Translator virtual QCString trOperationDocumentation() = 0; virtual QCString trDataMembers() = 0; virtual QCString trDataMemberDocumentation() = 0; + +////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + + virtual QCString trDesignUnitDocumentation() = 0; }; #endif diff --git a/src/translator_adapter.h b/src/translator_adapter.h index b0c8a24..388304c 100644 --- a/src/translator_adapter.h +++ b/src/translator_adapter.h @@ -41,7 +41,17 @@ class TranslatorAdapterBase : public Translator }; -class TranslatorAdapter_1_8_15 : public TranslatorAdapterBase +class TranslatorAdapter_1_8_19 : public TranslatorAdapterBase +{ + public: + virtual QCString updateNeededMessage() + { return createUpdateNeededMessage(idLanguage(),"release 1.8.19"); } + + virtual QCString trDesignUnitDocumentation() + { return english.trDesignUnitDocumentation(); } +}; + +class TranslatorAdapter_1_8_15 : public TranslatorAdapter_1_8_19 { public: virtual QCString updateNeededMessage() @@ -216,9 +226,6 @@ class TranslatorAdapter_1_8_2 : public TranslatorAdapter_1_8_4 virtual QCString trMethodDocumentation() { return english.trMethodDocumentation(); } - - virtual QCString trDesignOverview() - { return english.trDesignOverview(); } }; @@ -271,16 +278,6 @@ class TranslatorAdapter_1_7_5 : public TranslatorAdapter_1_8_0 virtual QCString trDirDepGraph(const char *name) { return english.trDirDepGraph(name); } -}; - -/** Adapter class for languages that only contain translations up to - * version 1.6.3. - */ -class TranslatorAdapter_1_6_3 : public TranslatorAdapter_1_7_5 -{ - public: - virtual QCString updateNeededMessage() - { return createUpdateNeededMessage(idLanguage(),"release 1.6.3"); } virtual QCString trFileIn(const char *name) { return english.trFileIn(name); } @@ -295,7 +292,7 @@ class TranslatorAdapter_1_6_3 : public TranslatorAdapter_1_7_5 /** Adapter class for languages that only contain translations up to * version 1.6.0. */ -class TranslatorAdapter_1_6_0 : public TranslatorAdapter_1_6_3 +class TranslatorAdapter_1_6_0 : public TranslatorAdapter_1_7_5 { public: virtual QCString updateNeededMessage() @@ -315,16 +312,6 @@ class TranslatorAdapter_1_6_0 : public TranslatorAdapter_1_6_3 virtual QCString trNoMatches() { return english.trNoMatches(); } -}; - -/** Adapter class for languages that only contain translations up to - * version 1.5.4 - */ -class TranslatorAdapter_1_5_4 : public TranslatorAdapter_1_6_0 -{ - public: - virtual QCString updateNeededMessage() - { return createUpdateNeededMessage(idLanguage(),"release 1.5.4"); } virtual QCString trMemberFunctionDocumentationFortran() { return english.trMemberFunctionDocumentationFortran(); } @@ -399,7 +386,7 @@ class TranslatorAdapter_1_5_4 : public TranslatorAdapter_1_6_0 /** Adapter class for languages that only contain translations up to * version 1.4.6 */ -class TranslatorAdapter_1_4_6 : public TranslatorAdapter_1_5_4 +class TranslatorAdapter_1_4_6 : public TranslatorAdapter_1_6_0 { public: virtual QCString updateNeededMessage() diff --git a/src/translator_am.h b/src/translator_am.h index 5b4c446..812d8fb 100644 --- a/src/translator_am.h +++ b/src/translator_am.h @@ -32,9 +32,11 @@ class TranslatorArmenian : public TranslatorAdapter_1_8_0 /* Used to get the command(s) for the language support. */
virtual QCString latexLanguageSupportCommand()
{
- return "\\usepackage[latin]{armtex}\n"
- "\\usepackage[armscii8]{inputenc}\n";
+ return "\\usepackage[latin]{armtex}\n"
+ "\\usepackage[armscii8]{inputenc}\n";
}
+ virtual QCString trISOLang()
+ { return "hy"; }
// --- Language translation methods -------------------
@@ -1800,5 +1802,4 @@ class TranslatorArmenian : public TranslatorAdapter_1_8_0 { return name + QCString("-ի ֆայլադարանների կախվածությունների գծագիր:"); }
};
-
#endif
diff --git a/src/translator_ar.h b/src/translator_ar.h index 24281fd..0989249 100644 --- a/src/translator_ar.h +++ b/src/translator_ar.h @@ -68,6 +68,9 @@ class TranslatorArabic : public TranslatorAdapter_1_4_6 return ""; } + virtual QCString trISOLang() + { return "ar-EG"; } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1564,6 +1567,7 @@ class TranslatorArabic : public TranslatorAdapter_1_4_6 "وجد أنها ملائمة. إنها تختلف عن الدالة أعلاه" "فقط في نوعية ال argument(s) التي تقبلها."; } + }; #endif diff --git a/src/translator_br.h b/src/translator_br.h index 01c5b9f..5be0282 100644 --- a/src/translator_br.h +++ b/src/translator_br.h @@ -49,7 +49,7 @@ #ifndef TRANSLATOR_BR_H #define TRANSLATOR_BR_H -class TranslatorBrazilian : public Translator +class TranslatorBrazilian : public TranslatorAdapter_1_8_19 { public: @@ -85,6 +85,11 @@ class TranslatorBrazilian : public Translator return "\\usepackage[brazil]{babel}"; } + virtual QCString trISOLang() + { + return "pt-BR"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -2011,15 +2016,6 @@ class TranslatorBrazilian : public Translator return "Documentação do método"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - // I'm not sure how to accurately translate it - return "Visão geral do design"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2335,7 +2331,6 @@ class TranslatorBrazilian : public Translator return "Dados Membros"; } -////////////////////////////////////////////////////////////////////////// }; diff --git a/src/translator_ca.h b/src/translator_ca.h index ca9b7e9..a608ff0 100644 --- a/src/translator_ca.h +++ b/src/translator_ca.h @@ -75,6 +75,11 @@ class TranslatorCatalan : public TranslatorAdapter_1_8_0 return "\\usepackage[catalan]{babel}\n"; } + virtual QCString trISOLang() + { + return "ca"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1838,6 +1843,7 @@ class TranslatorCatalan : public TranslatorAdapter_1_8_0 virtual QCString trDirDepGraph(const char *name) { return QCString("Graf de dependència de directoris per a ")+name+":"; } + }; #endif diff --git a/src/translator_cn.h b/src/translator_cn.h index 0e559c1..a3b5803 100644 --- a/src/translator_cn.h +++ b/src/translator_cn.h @@ -55,6 +55,10 @@ class TranslatorChinese : public TranslatorAdapter_1_8_15 { return "\\usepackage{CJKutf8}\n"; } + virtual QCString trISOLang() + { + return "zh"; + } virtual QCString latexFontenc() { return ""; @@ -1862,14 +1866,6 @@ class TranslatorChinese : public TranslatorAdapter_1_8_15 return "函数文档"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "设计概要"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -1920,7 +1916,6 @@ class TranslatorChinese : public TranslatorAdapter_1_8_15 return "该单例的文档由下列文件生成:"; } -////////////////////////////////////////////////////////////////////////// }; #endif diff --git a/src/translator_cz.h b/src/translator_cz.h index 9d6c489..4fb3bc2 100644 --- a/src/translator_cz.h +++ b/src/translator_cz.h @@ -105,6 +105,11 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 "\\makeatother\n"; } + virtual QCString trISOLang() + { + return "cs"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1977,14 +1982,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 return "Dokumentace metody"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Návrhové schéma"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2041,8 +2038,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 return result; } -////////////////////////////////////////////////////////////////////////// - }; #endif // TRANSLATOR_CZ_H diff --git a/src/translator_de.h b/src/translator_de.h index bf5ce5e..63b0802 100644 --- a/src/translator_de.h +++ b/src/translator_de.h @@ -166,6 +166,11 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15 return "\\usepackage[ngerman]{babel}\n"; } + virtual QCString trISOLang() + { + return "de"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -480,7 +485,7 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15 } else if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) { - return "Entwurfseinheiten-Dokumentation"; + return trDesignUnitDocumentation(); } else { @@ -2072,14 +2077,6 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15 return "Methodendokumentation"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Übersicht"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2254,7 +2251,13 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15 virtual QCString trCustomReference(const char *name) { return QCString(name)+"-Referenz"; } - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit documentation */ + virtual QCString trDesignUnitDocumentation() + { return "Entwurfseinheiten-Dokumentation"; } }; diff --git a/src/translator_dk.h b/src/translator_dk.h index 70e9032..2e9f7d0 100644 --- a/src/translator_dk.h +++ b/src/translator_dk.h @@ -119,6 +119,11 @@ class TranslatorDanish : public TranslatorAdapter_1_8_0 "\\usepackage[danish]{babel}\n"; } + virtual QCString trISOLang() + { + return "da"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1766,6 +1771,7 @@ class TranslatorDanish : public TranslatorAdapter_1_8_0 } + /*---------- For internal use: ----------------------------------------*/ protected: /*! For easy flexible-noun implementation. @@ -1775,7 +1781,7 @@ class TranslatorDanish : public TranslatorAdapter_1_8_0 const char* base, const char* plurSuffix) { QCString result(base); - if (first_capital) result.at(0) = toupper(result.at(0)); + if (first_capital) result[0] = (char)toupper(result[0]); if (!singular) result+=plurSuffix; return result; } diff --git a/src/translator_en.h b/src/translator_en.h index 400e59c..ba26bc7 100644 --- a/src/translator_en.h +++ b/src/translator_en.h @@ -74,6 +74,11 @@ class TranslatorEnglish : public Translator return ""; } + virtual QCString trISOLang() + { + return "en-US"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -394,6 +399,10 @@ class TranslatorEnglish : public Translator { return "Data Structure Documentation"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) + { + return trDesignUnitDocumentation(); + } else { return "Class Documentation"; @@ -1940,14 +1949,6 @@ class TranslatorEnglish : public Translator return "Method Documentation"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Design Overview"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2254,6 +2255,12 @@ class TranslatorEnglish : public Translator } ////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit documentation */ + virtual QCString trDesignUnitDocumentation() + { return "Design Unit Documentation"; } }; diff --git a/src/translator_eo.h b/src/translator_eo.h index 28876d7..3ab9f8a 100644 --- a/src/translator_eo.h +++ b/src/translator_eo.h @@ -76,6 +76,11 @@ class TranslatorEsperanto : public TranslatorAdapter_1_8_4 return "\\usepackage[esperanto]{babel}\n"; } + virtual QCString trISOLang() + { + return "eo"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1941,8 +1946,6 @@ class TranslatorEsperanto : public TranslatorAdapter_1_8_4 return "Fasona Superrigardo"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_es.h b/src/translator_es.h index b28ed75..e4b35f3 100644 --- a/src/translator_es.h +++ b/src/translator_es.h @@ -68,6 +68,11 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15 return "\\usepackage[spanish]{babel}"; } + virtual QCString trISOLang() + { + return "es"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1992,14 +1997,6 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15 return "Método de documentación"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Diseño información general"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2304,8 +2301,6 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15 return "Documentación miembro de datos"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_fa.h b/src/translator_fa.h index 5a37330..56ba3da 100644 --- a/src/translator_fa.h +++ b/src/translator_fa.h @@ -91,6 +91,11 @@ class TranslatorPersian : public TranslatorAdapter_1_7_5 return ""; } + virtual QCString trISOLang() + { + return "fa"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ diff --git a/src/translator_fi.h b/src/translator_fi.h index 2b94f48..bc6cbd9 100644 --- a/src/translator_fi.h +++ b/src/translator_fi.h @@ -130,6 +130,10 @@ class TranslatorFinnish : public TranslatorAdapter_1_6_0 return "\\usepackage[finnish]{babel}\n"; } + virtual QCString trISOLang() + { + return "fi"; + } // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ diff --git a/src/translator_fr.h b/src/translator_fr.h index f355619..a4eafc2 100644 --- a/src/translator_fr.h +++ b/src/translator_fr.h @@ -129,1077 +129,1093 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 * "\\usepackage[T1]{fontenc}\n" * </pre> */ - virtual QCString latexLanguageSupportCommand() - { - return "\\usepackage[french]{babel}\n" - "\\NoAutoSpaceBeforeFDP\n"; - } + virtual QCString latexLanguageSupportCommand() + { + return "\\usepackage[french]{babel}\n" + "\\NoAutoSpaceBeforeFDP\n"; + } + + virtual QCString trISOLang() + { + return "fr"; + } // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ - virtual QCString trRelatedFunctions() - { return "Fonctions associées"; } + virtual QCString trRelatedFunctions() + { return "Fonctions associées"; } /*! subscript for the related functions. */ - virtual QCString trRelatedSubscript() - { return "(Notez que ce ne sont pas des fonctions membres)"; } + virtual QCString trRelatedSubscript() + { return "(Notez que ce ne sont pas des fonctions membres)"; } /*! header that is put before the detailed description of files, classes and namespaces. */ - virtual QCString trDetailedDescription() - { return "Description détaillée"; } + virtual QCString trDetailedDescription() + { return "Description détaillée"; } /*! header that is put before the list of typedefs. */ - virtual QCString trMemberTypedefDocumentation() - { return "Documentation des définitions de type membres"; } + virtual QCString trMemberTypedefDocumentation() + { return "Documentation des définitions de type membres"; } /*! header that is put before the list of enumerations. */ - virtual QCString trMemberEnumerationDocumentation() - { return "Documentation des énumérations membres"; } + virtual QCString trMemberEnumerationDocumentation() + { return "Documentation des énumérations membres"; } /*! header that is put before the list of member functions. */ - virtual QCString trMemberFunctionDocumentation() - { return "Documentation des fonctions membres"; } + virtual QCString trMemberFunctionDocumentation() + { return "Documentation des fonctions membres"; } /*! header that is put before the list of member attributes. */ - virtual QCString trMemberDataDocumentation() + virtual QCString trMemberDataDocumentation() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Documentation des champs"; - } - else - { - return "Documentation des données membres"; - } + return "Documentation des champs"; } + else + { + return "Documentation des données membres"; + } + } /*! this is the text of a link put after brief descriptions. */ - virtual QCString trMore() - { return "Plus de détails..."; } + virtual QCString trMore() + { return "Plus de détails..."; } /*! put in the class documentation */ - virtual QCString trListOfAllMembers() - { return "Liste de tous les membres"; } + virtual QCString trListOfAllMembers() + { return "Liste de tous les membres"; } /*! used as the title of the "list of all members" page of a class */ - virtual QCString trMemberList() - { return "Liste des membres"; } + virtual QCString trMemberList() + { return "Liste des membres"; } /*! this is the first part of a sentence that is followed by a class name */ - virtual QCString trThisIsTheListOfAllMembers() - { return "Liste complète des membres de "; } + virtual QCString trThisIsTheListOfAllMembers() + { return "Liste complète des membres de "; } /*! this is the remainder of the sentence after the class name */ - virtual QCString trIncludingInheritedMembers() - { return ", y compris les membres hérités :"; } + virtual QCString trIncludingInheritedMembers() + { return ", y compris les membres hérités :"; } /*! this is put at the author sections at the bottom of man pages. * parameter s is name of the project name. */ - virtual QCString trGeneratedAutomatically(const char *s) - { QCString result="Généré automatiquement par Doxygen"; - if (s) result+=(QCString)" pour "+s; - result+=" à partir du code source."; - return result; - } + virtual QCString trGeneratedAutomatically(const char *s) + { QCString result="Généré automatiquement par Doxygen"; + if (s) result+=(QCString)" pour "+s; + result+=" à partir du code source."; + return result; + } /*! put after an enum name in the list of all members */ - virtual QCString trEnumName() - { return "énumération"; } + virtual QCString trEnumName() + { return "énumération"; } /*! put after an enum value in the list of all members */ - virtual QCString trEnumValue() - { return "valeur énumérée"; } + virtual QCString trEnumValue() + { return "valeur énumérée"; } /*! put after an undocumented member in the list of all members */ - virtual QCString trDefinedIn() - { return "défini dans"; } + virtual QCString trDefinedIn() + { return "défini dans"; } // quick reference sections /*! This is put above each page as a link to the list of all groups of * compounds or files (see the \\group command). */ - virtual QCString trModules() - { return "Modules"; } + virtual QCString trModules() + { return "Modules"; } /*! This is put above each page as a link to the class hierarchy */ - virtual QCString trClassHierarchy() - { return "Hiérarchie des classes"; } + virtual QCString trClassHierarchy() + { return "Hiérarchie des classes"; } /*! This is put above each page as a link to the list of annotated classes */ - virtual QCString trCompoundList() + virtual QCString trCompoundList() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + return "Structures de données"; + } + else { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Structures de données"; - } - else - { - return "Liste des classes"; - } + return "Liste des classes"; } + } /*! This is put above each page as a link to the list of documented files */ - virtual QCString trFileList() - { return "Liste des fichiers"; } + virtual QCString trFileList() + { return "Liste des fichiers"; } /*! This is put above each page as a link to all members of compounds. */ - virtual QCString trCompoundMembers() + virtual QCString trCompoundMembers() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + return "Champs de donnée"; + } + else { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Champs de donnée"; - } - else - { - return "Membres de classe"; - } + return "Membres de classe"; } + } /*! This is put above each page as a link to all members of files. */ - virtual QCString trFileMembers() + virtual QCString trFileMembers() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + return "Variables globale"; + } + else { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Variables globale"; - } - else - { - return "Membres de fichier"; - } + return "Membres de fichier"; } + } /*! This is put above each page as a link to all related pages. */ - virtual QCString trRelatedPages() - { return "Pages associées"; } + virtual QCString trRelatedPages() + { return "Pages associées"; } /*! This is put above each page as a link to all examples. */ - virtual QCString trExamples() - { return "Exemples"; } + virtual QCString trExamples() + { return "Exemples"; } /*! This is put above each page as a link to the search engine. */ - virtual QCString trSearch() - { return "Recherche"; } + virtual QCString trSearch() + { return "Recherche"; } /*! This is an introduction to the class hierarchy. */ - virtual QCString trClassHierarchyDescription() - { return "Cette liste d'héritage est classée " - "approximativement par ordre alphabétique :"; + virtual QCString trClassHierarchyDescription() + { + if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) + { + return "Liste hiérarchique de toutes les entités :"; } - - /*! This is an introduction to the list with all files. */ - virtual QCString trFileListDescription(bool extractAll) + else { - QCString result="Liste de tous les fichiers "; - if (!extractAll) result+="documentés "; - result+="avec une brève description :"; - return result; + return "Cette liste d'héritage est classée " + "approximativement par ordre alphabétique :"; } + } + + /*! This is an introduction to the list with all files. */ + virtual QCString trFileListDescription(bool extractAll) + { + QCString result="Liste de tous les fichiers "; + if (!extractAll) result+="documentés "; + result+="avec une brève description :"; + return result; + } /*! This is an introduction to the annotated compound list. */ - virtual QCString trCompoundListDescription() + virtual QCString trCompoundListDescription() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Liste des structures de données avec une brève description :"; - } - else - { - return "Liste des classes, structures, " + return "Liste des structures de données avec une brève description :"; + } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Liste des classes avec une brève description :"; + } + else + { + return "Liste des classes, structures, " "unions et interfaces avec une brève description :"; - } } + } /*! This is an introduction to the page with all class members. */ - virtual QCString trCompoundMembersDescription(bool extractAll) + virtual QCString trCompoundMembersDescription(bool extractAll) + { + QCString result="Liste de tous les "; + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - QCString result="Liste de tous les "; - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - result+="champs de structure et d'union "; - } - else - { - result+="membres de classe "; - } - if (!extractAll) - { - result+="documentés "; - } - result+="avec des liens vers "; - if (!extractAll) - { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - result+="la documentation de structure/union de chaque champ :"; - } - else - { - result+="la documentation de classe de chaque membre :"; - } - } - else - { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - result+="les structures/unions auxquelles ils appartiennent :"; - } - else - { - result+="les classes auxquelles ils appartiennent :"; - } - } - return result; + result+="champs de structure et d'union "; } + else + { + result+="membres de classe "; + } + if (!extractAll) + { + result+="documentés "; + } + result+="avec des liens vers "; + if (!extractAll) + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + result+="la documentation de structure/union de chaque champ :"; + } + else + { + result+="la documentation de classe de chaque membre :"; + } + } + else + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + result+="les structures/unions auxquelles ils appartiennent :"; + } + else + { + result+="les classes auxquelles ils appartiennent :"; + } + } + return result; + } /*! This is an introduction to the page with all file members. */ - virtual QCString trFileMembersDescription(bool extractAll) + virtual QCString trFileMembersDescription(bool extractAll) + { + QCString result="Liste "; + + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - QCString result="Liste "; - - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - result+="de toutes les fonctions, variables, macros, enumérations, et définitions de type "; - } - else - { - result+="de tous les membres de fichier "; - } - if (!extractAll) result+="documentés "; - result+="avec des liens vers "; - if (extractAll) - result+="les fichiers auxquels ils appartiennent :"; - else - result+="la documentation :"; - return result; + result+="de toutes les fonctions, variables, macros, enumérations, et définitions de type "; } + else + { + result+="de tous les membres de fichier "; + } + if (!extractAll) result+="documentés "; + result+="avec des liens vers "; + if (extractAll) + result+="les fichiers auxquels ils appartiennent :"; + else + result+="la documentation :"; + return result; + } /*! This is an introduction to the page with the list of all examples */ - virtual QCString trExamplesDescription() - { return "Liste de tous les exemples :"; } + virtual QCString trExamplesDescription() + { return "Liste de tous les exemples :"; } /*! This is an introduction to the page with the list of related pages */ - virtual QCString trRelatedPagesDescription() - { return "Liste de toutes les pages de documentation associées :"; } + virtual QCString trRelatedPagesDescription() + { return "Liste de toutes les pages de documentation associées :"; } /*! This is an introduction to the page with the list of class/file groups */ - virtual QCString trModulesDescription() - { return "Liste de tous les modules :"; } + virtual QCString trModulesDescription() + { return "Liste de tous les modules :"; } /*! This is used in HTML as the title of index.html. */ - virtual QCString trDocumentation() - { return "Documentation"; } + virtual QCString trDocumentation() + { return "Documentation"; } /*! This is used in LaTeX as the title of the chapter with the * index of all groups. */ - virtual QCString trModuleIndex() - { return "Index des modules"; } + virtual QCString trModuleIndex() + { return "Index des modules"; } /*! This is used in LaTeX as the title of the chapter with the * class hierarchy. */ - virtual QCString trHierarchicalIndex() - { return "Index hiérarchique"; } + virtual QCString trHierarchicalIndex() + { return "Index hiérarchique"; } /*! This is used in LaTeX as the title of the chapter with the * annotated compound index. */ - virtual QCString trCompoundIndex() + virtual QCString trCompoundIndex() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Index des structures de données"; - } - else - { - return "Index des classes"; - } + return "Index des structures de données"; } + else + { + return "Index des classes"; + } + } /*! This is used in LaTeX as the title of the chapter with the * list of all files. */ - virtual QCString trFileIndex() - { return "Index des fichiers"; } + virtual QCString trFileIndex() + { return "Index des fichiers"; } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all groups. */ - virtual QCString trModuleDocumentation() - { return "Documentation des modules"; } + virtual QCString trModuleDocumentation() + { return "Documentation des modules"; } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all classes, structs and unions. */ - virtual QCString trClassDocumentation() + virtual QCString trClassDocumentation() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Documentation des structures de données"; - } - else - { - return "Documentation des classes"; - } + return "Documentation des structures de données"; } + else + { + return "Documentation des classes"; + } + } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all files. */ - virtual QCString trFileDocumentation() - { return "Documentation des fichiers"; } + virtual QCString trFileDocumentation() + { return "Documentation des fichiers"; } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all examples. */ - virtual QCString trExampleDocumentation() - { return "Documentation des exemples"; } + virtual QCString trExampleDocumentation() + { return "Documentation des exemples"; } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all related pages. */ - virtual QCString trPageDocumentation() - { return "Documentation des pages associées"; } + virtual QCString trPageDocumentation() + { return "Documentation des pages associées"; } /*! This is used in LaTeX as the title of the document */ - virtual QCString trReferenceManual() - { return "Manuel de référence"; } + virtual QCString trReferenceManual() + { return "Manuel de référence"; } /*! This is used in the documentation of a file as a header before the * list of defines */ - virtual QCString trDefines() - { return "Macros"; } + virtual QCString trDefines() + { return "Macros"; } /*! This is used in the documentation of a file as a header before the * list of typedefs */ - virtual QCString trTypedefs() - { return "Définitions de type"; } + virtual QCString trTypedefs() + { return "Définitions de type"; } /*! This is used in the documentation of a file as a header before the * list of enumerations */ - virtual QCString trEnumerations() - { return "Énumérations"; } + virtual QCString trEnumerations() + { return "Énumérations"; } /*! This is used in the documentation of a file as a header before the * list of (global) functions */ - virtual QCString trFunctions() - { return "Fonctions"; } + virtual QCString trFunctions() + { return "Fonctions"; } /*! This is used in the documentation of a file as a header before the * list of (global) variables */ - virtual QCString trVariables() - { return "Variables"; } + virtual QCString trVariables() + { return "Variables"; } /*! This is used in the documentation of a file as a header before the * list of (global) variables */ - virtual QCString trEnumerationValues() - { return "Valeurs énumérées"; } + virtual QCString trEnumerationValues() + { return "Valeurs énumérées"; } /*! This is used in the documentation of a file before the list of * documentation blocks for defines */ - virtual QCString trDefineDocumentation() - { return "Documentation des macros"; } + virtual QCString trDefineDocumentation() + { return "Documentation des macros"; } /*! This is used in the documentation of a file/namespace before the list * of documentation blocks for typedefs */ - virtual QCString trTypedefDocumentation() - { return "Documentation des définitions de type"; } + virtual QCString trTypedefDocumentation() + { return "Documentation des définitions de type"; } /*! This is used in the documentation of a file/namespace before the list * of documentation blocks for enumeration types */ - virtual QCString trEnumerationTypeDocumentation() - { return "Documentation du type de l'énumération"; } + virtual QCString trEnumerationTypeDocumentation() + { return "Documentation du type de l'énumération"; } /*! This is used in the documentation of a file/namespace before the list * of documentation blocks for functions */ - virtual QCString trFunctionDocumentation() - { return "Documentation des fonctions"; } + virtual QCString trFunctionDocumentation() + { return "Documentation des fonctions"; } /*! This is used in the documentation of a file/namespace before the list * of documentation blocks for variables */ - virtual QCString trVariableDocumentation() - { return "Documentation des variables"; } + virtual QCString trVariableDocumentation() + { return "Documentation des variables"; } /*! This is used in the documentation of a file/namespace/group before * the list of links to documented compounds */ - virtual QCString trCompounds() + virtual QCString trCompounds() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + return "Structures de données"; + } + else { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Structures de données"; - } - else - { - return "Classes"; - } + return "Classes"; } + } /*! This is used in the standard footer of each page and indicates when * the page was generated */ - virtual QCString trGeneratedAt(const char *date,const char *projName) - { - QCString result=(QCString)"Généré le "+date; - if (projName) result+=(QCString)" pour "+projName; - result+=(QCString)" par"; - return result; - } + virtual QCString trGeneratedAt(const char *date,const char *projName) + { + QCString result=(QCString)"Généré le "+date; + if (projName) result+=(QCString)" pour "+projName; + result+=(QCString)" par"; + return result; + } /*! this text is put before a class diagram */ - virtual QCString trClassDiagram(const char *clName) - { - return (QCString)"Graphe d'héritage de "+clName+":"; - } + virtual QCString trClassDiagram(const char *clName) + { + return (QCString)"Graphe d'héritage de "+clName+":"; + } /*! this text is generated when the \\internal command is used. */ - virtual QCString trForInternalUseOnly() - { return "Pour un usage interne uniquement."; } + virtual QCString trForInternalUseOnly() + { return "Pour un usage interne uniquement."; } /*! this text is generated when the \\warning command is used. */ - virtual QCString trWarning() - { return "Avertissement"; } + virtual QCString trWarning() + { return "Avertissement"; } /*! this text is generated when the \\version command is used. */ - virtual QCString trVersion() - { return "Version"; } + virtual QCString trVersion() + { return "Version"; } /*! this text is generated when the \\date command is used. */ - virtual QCString trDate() - { return "Date"; } + virtual QCString trDate() + { return "Date"; } /*! this text is generated when the \\return command is used. */ - virtual QCString trReturns() - { return "Renvoie"; } + virtual QCString trReturns() + { return "Renvoie"; } /*! this text is generated when the \\sa command is used. */ - virtual QCString trSeeAlso() - { return "Voir également"; } + virtual QCString trSeeAlso() + { return "Voir également"; } /*! this text is generated when the \\param command is used. */ - virtual QCString trParameters() - { return "Paramètres"; } + virtual QCString trParameters() + { return "Paramètres"; } /*! this text is generated when the \\exception command is used. */ - virtual QCString trExceptions() - { return "Exceptions"; } + virtual QCString trExceptions() + { return "Exceptions"; } /*! this text is used in the title page of a LaTeX document. */ - virtual QCString trGeneratedBy() - { return "Généré par"; } + virtual QCString trGeneratedBy() + { return "Généré par"; } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-990307 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990307 +////////////////////////////////////////////////////////////////////////// /*! used as the title of page containing all the index of all namespaces. */ - virtual QCString trNamespaceList() - { return "Liste des espaces de nommage"; } + virtual QCString trNamespaceList() + { return "Liste des espaces de nommage"; } /*! used as an introduction to the namespace list */ - virtual QCString trNamespaceListDescription(bool extractAll) - { - QCString result="Liste de tous les espaces de nommage "; - if (!extractAll) result+="documentés "; - result+="avec une brève description:"; - return result; - } + virtual QCString trNamespaceListDescription(bool extractAll) + { + QCString result="Liste de tous les espaces de nommage "; + if (!extractAll) result+="documentés "; + result+="avec une brève description:"; + return result; + } /*! used in the class documentation as a header before the list of all * friends of a class */ - virtual QCString trFriends() - { return "Amis"; } + virtual QCString trFriends() + { return "Amis"; } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-990405 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990405 +////////////////////////////////////////////////////////////////////////// /*! used in the class documentation as a header before the list of all * related classes */ - virtual QCString trRelatedFunctionDocumentation() - { return "Documentation des fonctions amies et associées"; } + virtual QCString trRelatedFunctionDocumentation() + { return "Documentation des fonctions amies et associées"; } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-990425 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990425 +////////////////////////////////////////////////////////////////////////// /*! used as the title of the HTML page of a class/struct/union */ - virtual QCString trCompoundReference(const char *clName, + virtual QCString trCompoundReference(const char *clName, ClassDef::CompoundType compType, bool isTemplate) + { + QCString result="Référence "; + if (isTemplate) result+="du modèle "; + result+="de "; + switch(compType) { - QCString result="Référence "; - if (isTemplate) result+="du modèle "; - result+="de "; - switch(compType) - { - case ClassDef::Class: result+="la classe "; break; - case ClassDef::Struct: result+="la structure "; break; - case ClassDef::Union: result+="l'union "; break; - case ClassDef::Interface: result+="l'interface "; break; - case ClassDef::Protocol: result+="le protocol "; break; - case ClassDef::Category: result+="la catégorie "; break; - case ClassDef::Exception: result+="l'exception "; break; - default: break; - } - result+=(QCString)clName; - return result; + case ClassDef::Class: result+="la classe "; break; + case ClassDef::Struct: result+="la structure "; break; + case ClassDef::Union: result+="l'union "; break; + case ClassDef::Interface: result+="l'interface "; break; + case ClassDef::Protocol: result+="le protocol "; break; + case ClassDef::Category: result+="la catégorie "; break; + case ClassDef::Exception: result+="l'exception "; break; + default: break; } + result+=(QCString)clName; + return result; + } /*! used as the title of the HTML page of a file */ - virtual QCString trFileReference(const char *fileName) - { - QCString result= "Référence du fichier "; - result+=fileName; - return result; - } + virtual QCString trFileReference(const char *fileName) + { + QCString result= "Référence du fichier "; + result+=fileName; + return result; + } /*! used as the title of the HTML page of a namespace */ - virtual QCString trNamespaceReference(const char *namespaceName) - { - QCString result= "Référence de l'espace de nommage "; - result+=namespaceName; - return result; - } + virtual QCString trNamespaceReference(const char *namespaceName) + { + QCString result= "Référence de l'espace de nommage "; + result+=namespaceName; + return result; + } - virtual QCString trPublicMembers() - { return "Fonctions membres publiques"; } - virtual QCString trPublicSlots() - { return "Connecteurs publics"; } - virtual QCString trSignals() - { return "Signaux"; } - virtual QCString trStaticPublicMembers() - { return "Fonctions membres publiques statiques"; } - virtual QCString trProtectedMembers() - { return "Fonctions membres protégées"; } - virtual QCString trProtectedSlots() - { return "Connecteurs protégés"; } - virtual QCString trStaticProtectedMembers() - { return "Fonctions membres protégées statiques"; } - virtual QCString trPrivateMembers() - { return "Fonctions membres privées"; } - virtual QCString trPrivateSlots() - { return "Connecteurs privés"; } - virtual QCString trStaticPrivateMembers() - { return "Fonctions membres privées statiques"; } + virtual QCString trPublicMembers() + { return "Fonctions membres publiques"; } + virtual QCString trPublicSlots() + { return "Connecteurs publics"; } + virtual QCString trSignals() + { return "Signaux"; } + virtual QCString trStaticPublicMembers() + { return "Fonctions membres publiques statiques"; } + virtual QCString trProtectedMembers() + { return "Fonctions membres protégées"; } + virtual QCString trProtectedSlots() + { return "Connecteurs protégés"; } + virtual QCString trStaticProtectedMembers() + { return "Fonctions membres protégées statiques"; } + virtual QCString trPrivateMembers() + { return "Fonctions membres privées"; } + virtual QCString trPrivateSlots() + { return "Connecteurs privés"; } + virtual QCString trStaticPrivateMembers() + { return "Fonctions membres privées statiques"; } /*! this function is used to produce a comma-separated list of items. * use generateMarker(i) to indicate where item i should be put. */ - virtual QCString trWriteList(int numEntries) - { - QCString result; - int i; + virtual QCString trWriteList(int numEntries) + { + QCString result; + int i; // the inherits list contain `numEntries' classes - for (i=0;i<numEntries;i++) - { - // use generateMarker to generate placeholders for the class links! - result+=generateMarker(i); // generate marker for entry i in the list + for (i=0;i<numEntries;i++) + { + // use generateMarker to generate placeholders for the class links! + result+=generateMarker(i); // generate marker for entry i in the list // (order is left to right) - if (i!=numEntries-1) // not the last entry, so we need a separator - { - if (i<numEntries-2) // not the fore last entry - result+=", "; - else // the fore last entry - result+=", et "; - } - } - return result; + if (i!=numEntries-1) // not the last entry, so we need a separator + { + if (i<numEntries-2) // not the fore last entry + result+=", "; + else // the fore last entry + result+=", et "; + } } + return result; + } /*! used in class documentation to produce a list of base classes, * if class diagrams are disabled. */ - virtual QCString trInheritsList(int numEntries) - { - return "Est dérivée de "+trWriteList(numEntries)+"."; - } + virtual QCString trInheritsList(int numEntries) + { + return "Est dérivée de "+trWriteList(numEntries)+"."; + } /*! used in class documentation to produce a list of super classes, * if class diagrams are disabled. */ - virtual QCString trInheritedByList(int numEntries) - { - return "Dérivée par "+trWriteList(numEntries)+"."; - } + virtual QCString trInheritedByList(int numEntries) + { + return "Dérivée par "+trWriteList(numEntries)+"."; + } /*! used in member documentation blocks to produce a list of * members that are hidden by this one. */ - virtual QCString trReimplementedFromList(int numEntries) - { - return "Réimplémentée à partir de "+trWriteList(numEntries)+"."; - } + virtual QCString trReimplementedFromList(int numEntries) + { + return "Réimplémentée à partir de "+trWriteList(numEntries)+"."; + } /*! used in member documentation blocks to produce a list of * all member that overwrite the implementation of this member. */ - virtual QCString trReimplementedInList(int numEntries) - { - return "Réimplémentée dans "+trWriteList(numEntries)+"."; - } + virtual QCString trReimplementedInList(int numEntries) + { + return "Réimplémentée dans "+trWriteList(numEntries)+"."; + } /*! This is put above each page as a link to all members of namespaces. */ - virtual QCString trNamespaceMembers() - { return "Membres de l'espace de nommage"; } + virtual QCString trNamespaceMembers() + { return "Membres de l'espace de nommage"; } /*! This is an introduction to the page with all namespace members */ - virtual QCString trNamespaceMemberDescription(bool extractAll) - { - QCString result="Liste de tous les membres des espaces de nommage "; - if (!extractAll) result+="documentés "; - result+="avec des liens vers "; - if (extractAll) - result+="la documentation de namespace de chaque membre :"; - else - result+="les espaces de nommage auxquels ils appartiennent :"; - return result; - } + virtual QCString trNamespaceMemberDescription(bool extractAll) + { + QCString result="Liste de tous les membres des espaces de nommage "; + if (!extractAll) result+="documentés "; + result+="avec des liens vers "; + if (extractAll) + result+="la documentation de namespace de chaque membre :"; + else + result+="les espaces de nommage auxquels ils appartiennent :"; + return result; + } /*! This is used in LaTeX as the title of the chapter with the * index of all namespaces. */ - virtual QCString trNamespaceIndex() - { return "Index des espaces de nommage"; } + virtual QCString trNamespaceIndex() + { return "Index des espaces de nommage"; } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all namespaces. */ - virtual QCString trNamespaceDocumentation() - { return "Documentation des espaces de nommage"; } + virtual QCString trNamespaceDocumentation() + { return "Documentation des espaces de nommage"; } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-990522 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990522 +////////////////////////////////////////////////////////////////////////// /*! This is used in the documentation before the list of all * namespaces in a file. */ - virtual QCString trNamespaces() - { return "Espaces de nommage"; } + virtual QCString trNamespaces() + { return "Espaces de nommage"; } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-990728 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990728 +////////////////////////////////////////////////////////////////////////// /*! This is put at the bottom of a class documentation page and is * followed by a list of files that were used to generate the page. */ - virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType, + virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType, bool single) - { // here s is one of " Class", " Struct" or " Union" + { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file - bool female = true; - QCString result=(QCString)"La documentation de "; - switch(compType) - { - case ClassDef::Class: result+="cette classe"; break; - case ClassDef::Struct: result+="cette structure"; break; - case ClassDef::Union: result+="cette union"; break; - case ClassDef::Interface: result+="cette interface"; break; - case ClassDef::Protocol: result+="ce protocol"; female = false; break; - case ClassDef::Category: result+="cette catégorie"; break; - case ClassDef::Exception: result+="cette exception"; break; - default: break; - } - if (female) result+= " a été générée à partir "; - else result+=" a été généré à partir "; - if (single) result+="du fichier suivant :"; - else result+="des fichiers suivants :"; - return result; + bool feminine = true; + QCString result=(QCString)"La documentation de "; + switch(compType) + { + case ClassDef::Class: result+="cette classe"; break; + case ClassDef::Struct: result+="cette structure"; break; + case ClassDef::Union: result+="cette union"; break; + case ClassDef::Interface: result+="cette interface"; break; + case ClassDef::Protocol: result+="ce protocol"; feminine = false; break; + case ClassDef::Category: result+="cette catégorie"; break; + case ClassDef::Exception: result+="cette exception"; break; + default: break; } + if (feminine) result+= " a été générée à partir "; + else result+=" a été généré à partir "; + if (feminine) result+="du fichier suivant :"; + else result+="des fichiers suivants :"; + return result; + } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-990901 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990901 +////////////////////////////////////////////////////////////////////////// /*! This is used as the heading text for the retval command. */ - virtual QCString trReturnValues() - { return "Valeurs retournées"; } + virtual QCString trReturnValues() + { return "Valeurs retournées"; } /*! This is in the (quick) index as a link to the main page (index.html) */ - virtual QCString trMainPage() - { return "Page principale"; } + virtual QCString trMainPage() + { return "Page principale"; } /*! This is used in references to page that are put in the LaTeX * documentation. It should be an abbreviation of the word page. */ - virtual QCString trPageAbbreviation() - { return "p."; } + virtual QCString trPageAbbreviation() + { return "p."; } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-991003 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-991003 +////////////////////////////////////////////////////////////////////////// - virtual QCString trDefinedAtLineInSourceFile() - { - return "Définition à la ligne @0 du fichier @1."; - } - virtual QCString trDefinedInSourceFile() - { - return "Définition dans le fichier @0."; - } + virtual QCString trDefinedAtLineInSourceFile() + { + return "Définition à la ligne @0 du fichier @1."; + } + virtual QCString trDefinedInSourceFile() + { + return "Définition dans le fichier @0."; + } - ////////////////////////////////////////////////////////////////////////// - // new since 0.49-991205 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 0.49-991205 +////////////////////////////////////////////////////////////////////////// - virtual QCString trDeprecated() - { - return "Obsolète"; - } + virtual QCString trDeprecated() + { + return "Obsolète"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.0.0 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.0.0 +////////////////////////////////////////////////////////////////////////// /*! this text is put before a collaboration diagram */ - virtual QCString trCollaborationDiagram(const char *clName) - { - return (QCString)"Graphe de collaboration de "+clName+":"; - } + virtual QCString trCollaborationDiagram(const char *clName) + { + return (QCString)"Graphe de collaboration de "+clName+":"; + } /*! this text is put before an include dependency graph */ - virtual QCString trInclDepGraph(const char *fName) - { - return (QCString)"Graphe des dépendances par inclusion de "+fName+":"; - } + virtual QCString trInclDepGraph(const char *fName) + { + return (QCString)"Graphe des dépendances par inclusion de "+fName+":"; + } /*! header that is put before the list of constructor/destructors. */ - virtual QCString trConstructorDocumentation() - { - return "Documentation des constructeurs et destructeur"; - } + virtual QCString trConstructorDocumentation() + { + return "Documentation des constructeurs et destructeur"; + } /*! Used in the file documentation to point to the corresponding sources. */ - virtual QCString trGotoSourceCode() - { - return "Aller au code source de ce fichier."; - } + virtual QCString trGotoSourceCode() + { + return "Aller au code source de ce fichier."; + } /*! Used in the file sources to point to the corresponding documentation. */ - virtual QCString trGotoDocumentation() - { - return "Aller à la documentation de ce fichier."; - } + virtual QCString trGotoDocumentation() + { + return "Aller à la documentation de ce fichier."; + } /*! Text for the \\pre command */ - virtual QCString trPrecondition() - { - return "Précondition"; - } + virtual QCString trPrecondition() + { + return "Précondition"; + } /*! Text for the \\post command */ - virtual QCString trPostcondition() - { - return "Postcondition"; - } + virtual QCString trPostcondition() + { + return "Postcondition"; + } /*! Text for the \\invariant command */ - virtual QCString trInvariant() - { - return "Invariant"; - } + virtual QCString trInvariant() + { + return "Invariant"; + } /*! Text shown before a multi-line variable/enum initialization */ - virtual QCString trInitialValue() - { - return "Valeur initiale :"; - } + virtual QCString trInitialValue() + { + return "Valeur initiale :"; + } /*! Text used the source code in the file index */ - virtual QCString trCode() - { - return "code"; - } - virtual QCString trGraphicalHierarchy() - { - return "Graphe hiérarchique des classes"; - } - virtual QCString trGotoGraphicalHierarchy() - { - return "Aller au graphe hiérarchique des classes"; - } - virtual QCString trGotoTextualHierarchy() - { - return "Aller à la hiérarchie des classes en mode texte"; - } - virtual QCString trPageIndex() - { - return "Index des pages"; - } + virtual QCString trCode() + { + return "code"; + } + virtual QCString trGraphicalHierarchy() + { + return "Graphe hiérarchique des classes"; + } + virtual QCString trGotoGraphicalHierarchy() + { + return "Aller au graphe hiérarchique des classes"; + } + virtual QCString trGotoTextualHierarchy() + { + return "Aller à la hiérarchie des classes en mode texte"; + } + virtual QCString trPageIndex() + { + return "Index des pages"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.1.0 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.1.0 +////////////////////////////////////////////////////////////////////////// - virtual QCString trNote() - { - return "Note"; - } - virtual QCString trPublicTypes() - { - return "Types publics"; - } - virtual QCString trPublicAttribs() - { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Champs de données"; - } - else - { - return "Attributs publics"; - } - } - virtual QCString trStaticPublicAttribs() - { - return "Attributs publics statiques"; - } - virtual QCString trProtectedTypes() - { - return "Types protégés"; - } - virtual QCString trProtectedAttribs() - { - return "Attributs protégés"; - } - virtual QCString trStaticProtectedAttribs() - { - return "Attributs protégés statiques"; - } - virtual QCString trPrivateTypes() - { - return "Types privés"; - } - virtual QCString trPrivateAttribs() + virtual QCString trNote() + { + return "Note"; + } + virtual QCString trPublicTypes() + { + return "Types publics"; + } + virtual QCString trPublicAttribs() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - return "Attributs privés"; + return "Champs de données"; } - virtual QCString trStaticPrivateAttribs() + else { - return "Attributs privés statiques"; + return "Attributs publics"; } + } + virtual QCString trStaticPublicAttribs() + { + return "Attributs publics statiques"; + } + virtual QCString trProtectedTypes() + { + return "Types protégés"; + } + virtual QCString trProtectedAttribs() + { + return "Attributs protégés"; + } + virtual QCString trStaticProtectedAttribs() + { + return "Attributs protégés statiques"; + } + virtual QCString trPrivateTypes() + { + return "Types privés"; + } + virtual QCString trPrivateAttribs() + { + return "Attributs privés"; + } + virtual QCString trStaticPrivateAttribs() + { + return "Attributs privés statiques"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.1.3 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.1.3 +////////////////////////////////////////////////////////////////////////// /*! Used as a marker that is put before a \\todo item */ - virtual QCString trTodo() - { - return "A faire"; - } + virtual QCString trTodo() + { + return "A faire"; + } /*! Used as the header of the todo list */ - virtual QCString trTodoList() - { - return "Liste des choses à faire"; - } + virtual QCString trTodoList() + { + return "Liste des choses à faire"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.1.4 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.1.4 +////////////////////////////////////////////////////////////////////////// - virtual QCString trReferencedBy() - { - return "Référencé par"; - } - virtual QCString trRemarks() - { - return "Remarques"; - } - virtual QCString trAttention() - { - return "Attention"; - } - virtual QCString trInclByDepGraph() - { - return "Ce graphe montre quels fichiers incluent directement " + virtual QCString trReferencedBy() + { + return "Référencé par"; + } + virtual QCString trRemarks() + { + return "Remarques"; + } + virtual QCString trAttention() + { + return "Attention"; + } + virtual QCString trInclByDepGraph() + { + return "Ce graphe montre quels fichiers incluent directement " "ou indirectement ce fichier :"; - } - virtual QCString trSince() - { - return "Depuis"; - } + } + virtual QCString trSince() + { + return "Depuis"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.1.5 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.1.5 +////////////////////////////////////////////////////////////////////////// /*! title of the graph legend page */ - virtual QCString trLegendTitle() - { - return "Légende du graphe"; - } + virtual QCString trLegendTitle() + { + return "Légende du graphe"; + } /*! page explaining how the dot graph's should be interpreted * The %A in the text below are to prevent link to classes called "A". */ - virtual QCString trLegendDocs() - { - return - "Cette page explique comment interpréter les graphes générés " - "par doxygen.<p>\n" - "Considérez l'exemple suivant :\n" - "\\code\n" - "/*! Classe invisible à cause d'une troncature */\n" - "class Invisible { };\n\n" - "/*! Classe tronquée, la relation d'héritage est masquée */\n" - "class Truncated : public Invisible { };\n\n" - "/*! Classe non documentée avec des commentaires Doxygen */\n" - "class Undocumented { };\n\n" - "/*! Classe dérivée par héritage public */\n" - "class PublicBase : public Truncated { };\n\n" - "/*! Un modèle de classe */\n" - "template<class T> class Templ { };\n\n" - "/*! Classe dérivée par héritage protégé */\n" - "class ProtectedBase { };\n\n" - "/*! Classe dérivée par héritage privé */\n" - "class PrivateBase { };\n\n" - "/*! Classe utilisée par la classe dérivée */\n" - "class Used { };\n\n" - "/*! Super-classe qui hérite de plusieurs autres classes */\n" - "class Inherited : public PublicBase,\n" - " protected ProtectedBase,\n" - " private PrivateBase,\n" - " public Undocumented,\n" - " public Templ<int>\n" - "{\n" - " private:\n" - " Used *m_usedClass;\n" - "};\n" - "\\endcode\n" - "Cela aboutira au graphe suivant :" - "<p><center><img alt=\"\" src=\"graph_legend."+getDotImageExtension()+"\"></center></p>\n" - "<p>\n" - "Les rectangles du graphe ci-dessus ont la signification suivante :\n" - "<ul>\n" - "<li>Un rectangle plein noir représente la structure ou la classe pour laquelle " - "le graphe est généré.\n" - "<li>Un rectangle avec un bord noir indique une classe ou une structure documentée.\n" - "<li>Un rectangle avec un bord gris indique une classe ou une structure non documentée.\n" - "<li>Un rectangle avec un bord rouge indique une structure ou une classe documentée\n" - "pour laquelle des relations d'héritage ou de collaboration manquent. Un graphe est " - "tronqué s'il n'entre pas dans les limites spécifiées." - "</ul>\n" - "Les flèches ont la signification suivante :\n" - "<ul>\n" - "<li>Une flèche bleu foncé est utilisée pour visualiser une relation d'héritage publique " - "entre deux classes.\n" - "<li>Une flèche vert foncé est utilisée pour une relation d'héritage protégée.\n" - "<li>Une flèche rouge foncé est utilisée pour une relation d'héritage privée.\n" - "<li>Une flèche violette en pointillés est utilisée si une classe est contenue ou " - "utilisée par une autre classe. La flèche est étiquetée avec la ou les variable(s) " - "qui permettent d'accéder à la classe ou structure pointée. \n" - "<li>Une flèche jaune en pointillés indique une relation entre un modèle d'instance et " - "le modèle de classe duquel il est instancié. La flèche est étiquetée avec " - "les paramètres de modèle de l'instance.\n" - "</ul>\n"; - } + virtual QCString trLegendDocs() + { + return + "Cette page explique comment interpréter les graphes générés " + "par doxygen.<p>\n" + "Considérez l'exemple suivant :\n" + "\\code\n" + "/*! Classe invisible à cause d'une troncature */\n" + "class Invisible { };\n\n" + "/*! Classe tronquée, la relation d'héritage est masquée */\n" + "class Truncated : public Invisible { };\n\n" + "/*! Classe non documentée avec des commentaires Doxygen */\n" + "class Undocumented { };\n\n" + "/*! Classe dérivée par héritage public */\n" + "class PublicBase : public Truncated { };\n\n" + "/*! Un modèle de classe */\n" + "template<class T> class Templ { };\n\n" + "/*! Classe dérivée par héritage protégé */\n" + "class ProtectedBase { };\n\n" + "/*! Classe dérivée par héritage privé */\n" + "class PrivateBase { };\n\n" + "/*! Classe utilisée par la classe dérivée */\n" + "class Used { };\n\n" + "/*! Super-classe qui hérite de plusieurs autres classes */\n" + "class Inherited : public PublicBase,\n" + " protected ProtectedBase,\n" + " private PrivateBase,\n" + " public Undocumented,\n" + " public Templ<int>\n" + "{\n" + " private:\n" + " Used *m_usedClass;\n" + "};\n" + "\\endcode\n" + "Cela aboutira au graphe suivant :" + "<p><center><img alt=\"\" src=\"graph_legend."+getDotImageExtension()+"\"></center></p>\n" + "<p>\n" + "Les rectangles du graphe ci-dessus ont la signification suivante :\n" + "<ul>\n" + "<li>Un rectangle plein noir représente la structure ou la classe pour laquelle " + "le graphe est généré.\n" + "<li>Un rectangle avec un bord noir indique une classe ou une structure documentée.\n" + "<li>Un rectangle avec un bord gris indique une classe ou une structure non documentée.\n" + "<li>Un rectangle avec un bord rouge indique une structure ou une classe documentée\n" + "pour laquelle des relations d'héritage ou de collaboration manquent. Un graphe est " + "tronqué s'il n'entre pas dans les limites spécifiées." + "</ul>\n" + "Les flèches ont la signification suivante :\n" + "<ul>\n" + "<li>Une flèche bleu foncé est utilisée pour visualiser une relation d'héritage publique " + "entre deux classes.\n" + "<li>Une flèche vert foncé est utilisée pour une relation d'héritage protégée.\n" + "<li>Une flèche rouge foncé est utilisée pour une relation d'héritage privée.\n" + "<li>Une flèche violette en pointillés est utilisée si une classe est contenue ou " + "utilisée par une autre classe. La flèche est étiquetée avec la ou les variable(s) " + "qui permettent d'accéder à la classe ou structure pointée. \n" + "<li>Une flèche jaune en pointillés indique une relation entre un modèle d'instance et " + "le modèle de classe duquel il est instancié. La flèche est étiquetée avec " + "les paramètres de modèle de l'instance.\n" + "</ul>\n"; + } /*! text for the link to the legend page */ - virtual QCString trLegend() - { - return "légende"; - } + virtual QCString trLegend() + { + return "légende"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.0 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.0 +////////////////////////////////////////////////////////////////////////// /*! Used as a marker that is put before a test item */ - virtual QCString trTest() - { - return "Test"; - } + virtual QCString trTest() + { + return "Test"; + } /*! Used as the header of the test list */ - virtual QCString trTestList() - { - return "Liste des tests"; - } + virtual QCString trTestList() + { + return "Liste des tests"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.2 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.2 +////////////////////////////////////////////////////////////////////////// /*! Used as a section header for IDL properties */ - virtual QCString trProperties() - { - return "Propriétés"; - } + virtual QCString trProperties() + { + return "Propriétés"; + } /*! Used as a section header for IDL property documentation */ - virtual QCString trPropertyDocumentation() - { - return "Documentation des propriétés"; - } + virtual QCString trPropertyDocumentation() + { + return "Documentation des propriétés"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.4 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.4 +////////////////////////////////////////////////////////////////////////// /*! Used for Java classes in the summary section of Java packages */ - virtual QCString trClasses() + virtual QCString trClasses() + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) - { - return "Structures de données"; - } - else - { - return "Classes"; - } + return "Structures de données"; } - /*! Used as the title of a Java package */ - virtual QCString trPackage(const char *name) + else { - return (QCString)"Paquetage "+name; + return "Classes"; } + } + /*! Used as the title of a Java package */ + virtual QCString trPackage(const char *name) + { + return (QCString)"Paquetage "+name; + } /*! Title of the package index page */ - virtual QCString trPackageList() - { - return "Liste des paquetages"; - } + virtual QCString trPackageList() + { + return "Liste des paquetages"; + } /*! The description of the package index page */ - virtual QCString trPackageListDescription() - { - return "Liste des paquetages avec une brève description (si disponible) :"; - } + virtual QCString trPackageListDescription() + { + return "Liste des paquetages avec une brève description (si disponible) :"; + } /*! The link name in the Quick links header for each page */ - virtual QCString trPackages() - { - return "Paquetages"; - } + virtual QCString trPackages() + { + return "Paquetages"; + } /*! Text shown before a multi-line define */ - virtual QCString trDefineValue() - { - return "Valeur :"; - } + virtual QCString trDefineValue() + { + return "Valeur :"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.5 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.5 +////////////////////////////////////////////////////////////////////////// /*! Used as a marker that is put before a \\bug item */ - virtual QCString trBug() - { - return "Bogue"; - } + virtual QCString trBug() + { + return "Bogue"; + } /*! Used as the header of the bug list */ - virtual QCString trBugList() - { - return "Liste des bogues"; - } + virtual QCString trBugList() + { + return "Liste des bogues"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.6 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.6 +////////////////////////////////////////////////////////////////////////// /*! Used as ansicpg for RTF file * @@ -1226,256 +1242,256 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 * </pre> * */ - virtual QCString trRTFansicp() - { - return "1252"; - } + virtual QCString trRTFansicp() + { + return "1252"; + } /*! Used as ansicpg for RTF fcharset * \see trRTFansicp() for a table of possible values. */ - virtual QCString trRTFCharSet() - { - return "0"; - } + virtual QCString trRTFCharSet() + { + return "0"; + } /*! Used as header RTF general index */ - virtual QCString trRTFGeneralIndex() - { - return "Index"; - } + virtual QCString trRTFGeneralIndex() + { + return "Index"; + } /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. */ - virtual QCString trClass(bool first_capital, bool singular) - { - QCString result((first_capital ? "Classe" : "classe")); - if (!singular) result+="s"; - return result; - } + virtual QCString trClass(bool first_capital, bool singular) + { + QCString result((first_capital ? "Classe" : "classe")); + if (!singular) result+="s"; + return result; + } /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. */ - virtual QCString trFile(bool first_capital, bool singular) - { - QCString result((first_capital ? "Fichier" : "fichier")); - if (!singular) result+="s"; - return result; - } + virtual QCString trFile(bool first_capital, bool singular) + { + QCString result((first_capital ? "Fichier" : "fichier")); + if (!singular) result+="s"; + return result; + } /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. */ - virtual QCString trNamespace(bool first_capital, bool singular) - { - QCString result((first_capital ? "Espace" : "espace")); - if (!singular) result+="s"; - result+=" de nommage"; - return result; - } + virtual QCString trNamespace(bool first_capital, bool singular) + { + QCString result((first_capital ? "Espace" : "espace")); + if (!singular) result+="s"; + result+=" de nommage"; + return result; + } /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. */ - virtual QCString trGroup(bool first_capital, bool singular) - { - QCString result((first_capital ? "Groupe" : "groupe")); - if (!singular) result+="s"; - return result; - } + virtual QCString trGroup(bool first_capital, bool singular) + { + QCString result((first_capital ? "Groupe" : "groupe")); + if (!singular) result+="s"; + return result; + } /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. */ - virtual QCString trPage(bool first_capital, bool singular) - { - QCString result((first_capital ? "Page" : "page")); - if (!singular) result+="s"; - return result; - } + virtual QCString trPage(bool first_capital, bool singular) + { + QCString result((first_capital ? "Page" : "page")); + if (!singular) result+="s"; + return result; + } /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. */ - virtual QCString trMember(bool first_capital, bool singular) - { - QCString result((first_capital ? "Membre" : "membre")); - if (!singular) result+="s"; - return result; - } + virtual QCString trMember(bool first_capital, bool singular) + { + QCString result((first_capital ? "Membre" : "membre")); + if (!singular) result+="s"; + return result; + } /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. */ - virtual QCString trGlobal(bool first_capital, bool singular) - { - QCString result((first_capital ? "Globa" : "globa")); - if (!singular) result+="ux(ales)"; else result+="l(e)"; - return result; - } + virtual QCString trGlobal(bool first_capital, bool singular) + { + QCString result((first_capital ? "Globa" : "globa")); + if (!singular) result+="ux(ales)"; else result+="l(e)"; + return result; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.7 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.7 +////////////////////////////////////////////////////////////////////////// /*! This text is generated when the \\author command is used and * for the author section in man pages. */ - virtual QCString trAuthor(bool first_capital, bool singular) - { - QCString result((first_capital ? "Auteur" : "auteur")); - if (!singular) result+="s"; - return result; - } + virtual QCString trAuthor(bool first_capital, bool singular) + { + QCString result((first_capital ? "Auteur" : "auteur")); + if (!singular) result+="s"; + return result; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.11 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.11 +////////////////////////////////////////////////////////////////////////// /*! This text is put before the list of members referenced by a member */ - virtual QCString trReferences() - { - return "Références"; - } + virtual QCString trReferences() + { + return "Références"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.13 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.13 +////////////////////////////////////////////////////////////////////////// /*! used in member documentation blocks to produce a list of * members that are implemented by this one. */ - virtual QCString trImplementedFromList(int numEntries) - { - return "Implémente "+trWriteList(numEntries)+"."; - } + virtual QCString trImplementedFromList(int numEntries) + { + return "Implémente "+trWriteList(numEntries)+"."; + } /*! used in member documentation blocks to produce a list of * all members that implement this abstract member. */ - virtual QCString trImplementedInList(int numEntries) - { - return "Implémenté dans "+trWriteList(numEntries)+"."; - } + virtual QCString trImplementedInList(int numEntries) + { + return "Implémenté dans "+trWriteList(numEntries)+"."; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.16 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.16 +////////////////////////////////////////////////////////////////////////// /*! used in RTF documentation as a heading for the Table * of Contents. */ - virtual QCString trRTFTableOfContents() - { - return "Table des matières"; - } + virtual QCString trRTFTableOfContents() + { + return "Table des matières"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.17 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.17 +////////////////////////////////////////////////////////////////////////// /*! Used as the header of the list of item that have been * flagged deprecated */ - virtual QCString trDeprecatedList() - { - return "Liste des éléments obsolètes"; - } + virtual QCString trDeprecatedList() + { + return "Liste des éléments obsolètes"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.2.18 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.2.18 +////////////////////////////////////////////////////////////////////////// /*! Used as a header for declaration section of the events found in * a C# program */ - virtual QCString trEvents() - { - return "Événements"; - } + virtual QCString trEvents() + { + return "Événements"; + } /*! Header used for the documentation section of a class' events. */ - virtual QCString trEventDocumentation() - { - return "Documentation des événements"; - } + virtual QCString trEventDocumentation() + { + return "Documentation des événements"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.3 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.3 +////////////////////////////////////////////////////////////////////////// /*! Used as a heading for a list of Java class types with package scope. */ - virtual QCString trPackageTypes() - { - return "Types de paquetage"; - } + virtual QCString trPackageTypes() + { + return "Types de paquetage"; + } /*! Used as a heading for a list of Java class functions with package * scope. */ - virtual QCString trPackageMembers() - { - return "Fonctions de paquetage"; - } + virtual QCString trPackageMembers() + { + return "Fonctions de paquetage"; + } /*! Used as a heading for a list of static Java class functions with * package scope. */ - virtual QCString trStaticPackageMembers() - { - return "Fonctions statiques de paquetage"; - } + virtual QCString trStaticPackageMembers() + { + return "Fonctions statiques de paquetage"; + } /*! Used as a heading for a list of Java class variables with package * scope. */ - virtual QCString trPackageAttribs() - { - return "Attributs de paquetage"; - } + virtual QCString trPackageAttribs() + { + return "Attributs de paquetage"; + } /*! Used as a heading for a list of static Java class variables with * package scope. */ - virtual QCString trStaticPackageAttribs() - { - return "Attributs statiques de paquetage"; - } + virtual QCString trStaticPackageAttribs() + { + return "Attributs statiques de paquetage"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.3.1 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.3.1 +////////////////////////////////////////////////////////////////////////// /*! Used in the quick index of a class/file/namespace member list page * to link to the unfiltered list of all members. */ - virtual QCString trAll() - { - return "Tout"; - } + virtual QCString trAll() + { + return "Tout"; + } /*! Put in front of the call graph for a function. */ - virtual QCString trCallGraph() - { - return "Voici le graphe d'appel pour cette fonction :"; - } + virtual QCString trCallGraph() + { + return "Voici le graphe d'appel pour cette fonction :"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.3.3 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.3.3 +////////////////////////////////////////////////////////////////////////// /*! This string is used as the title for the page listing the search * results. */ - virtual QCString trSearchResultsTitle() - { - return "Résultats de la recherche"; - } + virtual QCString trSearchResultsTitle() + { + return "Résultats de la recherche"; + } /*! This string is put just before listing the search results. The * text can be different depending on the number of documents found. * Inside the text you can put the special marker $num to insert @@ -1484,104 +1500,104 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 * value 2 represents 2 or more matches. HTML markup is allowed inside * the returned string. */ - virtual QCString trSearchResults(int numDocuments) + virtual QCString trSearchResults(int numDocuments) + { + if (numDocuments==0) + { + return "Désolé, aucun document ne correspond à votre requête."; + } + else if (numDocuments==1) { - if (numDocuments==0) - { - return "Désolé, aucun document ne correspond à votre requête."; - } - else if (numDocuments==1) - { - return "Trouvé <b>1</b> document correspondant à votre requête."; - } - else - { - return "Trouvé <b>$num</b> documents correspondant à votre requête. " + return "Trouvé <b>1</b> document correspondant à votre requête."; + } + else + { + return "Trouvé <b>$num</b> documents correspondant à votre requête. " "Classé par ordre de pertinence décroissant."; - } } + } /*! This string is put before the list of matched words, for each search * result. What follows is the list of words that matched the query. */ - virtual QCString trSearchMatches() - { - return "Correspondances :"; - } + virtual QCString trSearchMatches() + { + return "Correspondances :"; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.3.8 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.3.8 +////////////////////////////////////////////////////////////////////////// - /*! This is used in HTML as the title of page with source code for file filename - */ - virtual QCString trSourceFile(QCString& filename) - { - return " Fichier source de " + filename; - } + /*! This is used in HTML as the title of page with source code for file filename + */ + virtual QCString trSourceFile(QCString& filename) + { + return " Fichier source de " + filename; + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.3.9 - ////////////////////////////////////////////////////////////////////////// - - /*! This is used as the name of the chapter containing the directory - * hierarchy. - */ - virtual QCString trDirIndex() - { return "Hiérarchie de répertoires"; } - - /*! This is used as the name of the chapter containing the documentation - * of the directories. - */ - virtual QCString trDirDocumentation() - { return "Documentation des répertoires"; } - - /*! This is used as the title of the directory index and also in the - * Quick links of a HTML page, to link to the directory hierarchy. - */ - virtual QCString trDirectories() - { return "Répertoires"; } - - /*! This returns a sentences that introduces the directory hierarchy. - * and the fact that it is sorted alphabetically per level - */ - virtual QCString trDirDescription() - { return "Cette hiérarchie de répertoire est triée approximativement, " - "mais pas complètement, par ordre alphabétique :"; - } +////////////////////////////////////////////////////////////////////////// +// new since 1.3.9 +////////////////////////////////////////////////////////////////////////// - /*! This returns the title of a directory page. The name of the - * directory is passed via \a dirName. - */ - virtual QCString trDirReference(const char *dirName) - { QCString result="Répertoire de référence de "; result+=dirName; return result; } + /*! This is used as the name of the chapter containing the directory + * hierarchy. + */ + virtual QCString trDirIndex() + { return "Hiérarchie de répertoires"; } - /*! This returns the word directory with or without starting capital - * (\a first_capital) and in sigular or plural form (\a singular). - */ - virtual QCString trDir(bool first_capital, bool singular) - { - QCString result((first_capital ? "Répertoire" : "répertoire")); - if (singular) result+=""; else result+="s"; - return result; - } + /*! This is used as the name of the chapter containing the documentation + * of the directories. + */ + virtual QCString trDirDocumentation() + { return "Documentation des répertoires"; } - ////////////////////////////////////////////////////////////////////////// - // new since 1.4.1 - ////////////////////////////////////////////////////////////////////////// + /*! This is used as the title of the directory index and also in the + * Quick links of an HTML page, to link to the directory hierarchy. + */ + virtual QCString trDirectories() + { return "Répertoires"; } + + /*! This returns a sentences that introduces the directory hierarchy. + * and the fact that it is sorted alphabetically per level + */ + virtual QCString trDirDescription() + { return "Cette hiérarchie de répertoire est triée approximativement, " + "mais pas complètement, par ordre alphabétique :"; + } + + /*! This returns the title of a directory page. The name of the + * directory is passed via \a dirName. + */ + virtual QCString trDirReference(const char *dirName) + { QCString result="Répertoire de référence de "; result+=dirName; return result; } + + /*! This returns the word directory with or without starting capital + * (\a first_capital) and in singular or plural form (\a singular). + */ + virtual QCString trDir(bool first_capital, bool singular) + { + QCString result((first_capital ? "Répertoire" : "répertoire")); + if (singular) result+=""; else result+="s"; + return result; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.4.1 +////////////////////////////////////////////////////////////////////////// /*! This text is added to the documentation when the \\overload command * is used for a overloaded function. */ - virtual QCString trOverloadText() - { - return "Ceci est une fonction membre surchargée, " + virtual QCString trOverloadText() + { + return "Ceci est une fonction membre surchargée, " "proposée par commodité. Elle diffère de la fonction " "ci-dessus uniquement par le(s) argument(s) qu'elle accepte."; - } + } - ////////////////////////////////////////////////////////////////////////// - // new since 1.4.6 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.4.6 +////////////////////////////////////////////////////////////////////////// /*! This is used to introduce a caller (or called-by) graph */ virtual QCString trCallerGraph() @@ -1595,9 +1611,9 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 virtual QCString trEnumerationValueDocumentation() { return "Documentation des énumérations"; } - ////////////////////////////////////////////////////////////////////////// - // new since 1.5.4 (mainly for Fortran) - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.5.4 (mainly for Fortran) +////////////////////////////////////////////////////////////////////////// /*! header that is put before the list of member subprograms (Fortran). */ virtual QCString trMemberFunctionDocumentationFortran() @@ -1832,7 +1848,7 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 } ////////////////////////////////////////////////////////////////////////// -// new since 1.6.3 +// new since 1.6.3 (missing items for the directory pages) ////////////////////////////////////////////////////////////////////////// /*! when clicking a directory dependency label, a page with a @@ -1990,14 +2006,6 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 return "Documentation des méthodes"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Vue d'ensemble"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2269,20 +2277,23 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 } virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal) { - QCString result = "Référence de "; - + QCString result = "Référence "; + bool feminine = true; switch(compType) { - case ClassDef::Class: result+="la classe "; break; - case ClassDef::Struct: result+="la structure "; break; - case ClassDef::Interface: result+="l'interface "; break; - case ClassDef::Exception: result+="l'exception "; break; + case ClassDef::Class: result+="de la classe "; break; + case ClassDef::Struct: result+="de la structure "; break; + case ClassDef::Union: result+="de l'union "; break; + case ClassDef::Interface: result+="de l'interface "; break; + case ClassDef::Protocol: result+="du protocole "; feminine=false; break; + case ClassDef::Category: result+="de la catégorie "; break; + case ClassDef::Exception: result+="de l'exception "; break; default: break; } if(isLocal) { - result += "locale "; + result += (feminine) ? "locale " : "local "; } result += (QCString)clName; @@ -2306,8 +2317,6 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 return "Documentation des champs de données"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_gr.h b/src/translator_gr.h index 6ed43db..c4af814 100644 --- a/src/translator_gr.h +++ b/src/translator_gr.h @@ -36,9 +36,9 @@ exception -> εξαίρεση namespace -> χώρος ονομάτων enumeration -> απαρίθμηση -*/ - - +*/ + + #ifndef TRANSLATOR_GR_H #define TRANSLATOR_GR_H @@ -59,8 +59,23 @@ 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 trISOLang() + { + return "el"; + } + + virtual QCString latexFontenc() + { + return ""; + } + virtual QCString latexFont() + { + return "\\setmainfont{Libertinus Sans}\n" + "\\setmonofont{Courier New}\n"; } // --- Language translation methods ------------------- @@ -1159,6 +1174,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 */ @@ -1916,14 +1941,6 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 return "Τεκμηρίωση Μεθόδου"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Επισκόπηση σχεδίασης"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -1980,6 +1997,7 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 return result; } + }; #endif diff --git a/src/translator_hr.h b/src/translator_hr.h index 1d17e2a..3f9f492 100644 --- a/src/translator_hr.h +++ b/src/translator_hr.h @@ -92,6 +92,8 @@ class TranslatorCroatian : public TranslatorAdapter_1_8_2 { return "croatian"; } QCString latexLanguageSupportCommand() { return "\\usepackage[croatian]{babel}\n"; } + QCString trISOLang() + { return "hr"; } QCString trRelatedFunctions() { return "Povezane funkcije"; } QCString trRelatedSubscript() @@ -1567,8 +1569,6 @@ class TranslatorCroatian : public TranslatorAdapter_1_8_2 virtual QCString trAdditionalInheritedMembers() { return "Dodatni naslijeđeni članovi"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_hu.h b/src/translator_hu.h index 44363c9..f7d9788 100644 --- a/src/translator_hu.h +++ b/src/translator_hu.h @@ -100,6 +100,11 @@ class TranslatorHungarian : public TranslatorAdapter_1_8_15 "\\usepackage[magyar]{babel}\n"; } + virtual QCString trISOLang() + { + return "hu"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1955,14 +1960,6 @@ class TranslatorHungarian : public TranslatorAdapter_1_8_15 return "Metódus dokumentáció"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Dizájn áttekintés"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2020,9 +2017,6 @@ class TranslatorHungarian : public TranslatorAdapter_1_8_15 result+="lett létrehozva:"; return result; } - -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_id.h b/src/translator_id.h index 2039c76..05d36ee 100644 --- a/src/translator_id.h +++ b/src/translator_id.h @@ -58,6 +58,11 @@ class TranslatorIndonesian : public TranslatorAdapter_1_8_0 return "\\usepackage[bahasa]{babel}"; } + virtual QCString trISOLang() + { + return "id"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ diff --git a/src/translator_it.h b/src/translator_it.h index 9638a01..f7f3534 100644 --- a/src/translator_it.h +++ b/src/translator_it.h @@ -112,6 +112,11 @@ class TranslatorItalian : public TranslatorAdapter_1_8_15 return "\\usepackage[italian]{babel}\n"; } + virtual QCString trISOLang() + { + return "it"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1912,14 +1917,6 @@ class TranslatorItalian : public TranslatorAdapter_1_8_15 return "Documentazione dei metodi"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Panoramica del progetto"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -1976,8 +1973,6 @@ class TranslatorItalian : public TranslatorAdapter_1_8_15 return result; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_je.h b/src/translator_je.h index d555421..66ee178 100644 --- a/src/translator_je.h +++ b/src/translator_je.h @@ -62,6 +62,11 @@ class TranslatorJapaneseEn : public TranslatorEnglish { return "128"; } + + virtual QCString trISOLang() + { + return "ja"; + } }; #endif diff --git a/src/translator_jp.h b/src/translator_jp.h index fc0d65d..7985823 100644 --- a/src/translator_jp.h +++ b/src/translator_jp.h @@ -79,6 +79,10 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 { return "\\usepackage{CJKutf8}\n"; } + virtual QCString trISOLang() + { + return "ja"; + } virtual QCString latexFontenc() { return ""; @@ -158,7 +162,7 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 /*! this is the remainder of the sentence after the class name */ virtual QCString trIncludingInheritedMembers() { return " の全メンバ一覧です。"; } - /* trThisIsTheListOfAllMembers から続くように定義すること */ + /* trThisIsTheListOfAllMembers から続くように定義すること */ /*! this is put at the author sections at the bottom of man pages. * parameter s is name of the project name. @@ -268,7 +272,7 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 } return "詳解が付けられているファイルの一覧です。"; } - + /*! This is an introduction to the annotated compound list. */ virtual QCString trCompoundListDescription() @@ -844,7 +848,7 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 { return "非推奨"; } - + /*! this text is put before a collaboration diagram */ virtual QCString trCollaborationDiagram(const char *clName) { @@ -1851,7 +1855,7 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 /*! Used file list for a Java enum */ virtual QCString trEnumGeneratedFromFiles(bool) - { + { return "次のファイルからこの列挙についての詳解を抽出しました:"; } @@ -1879,7 +1883,7 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 */ virtual QCString trPanelSynchronisationTooltip(bool enable) { - + QCString opt = enable ? "有効" : "無効"; return "クリックで同期表示が"+opt+"になります"; } @@ -1925,14 +1929,6 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 return "メソッド詳解"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "デザイン概観"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -1985,8 +1981,6 @@ class TranslatorJapanese : public TranslatorAdapter_1_8_15 "の詳解を抽出しました:"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_ke.h b/src/translator_ke.h index c9f488c..2dda941 100644 --- a/src/translator_ke.h +++ b/src/translator_ke.h @@ -59,6 +59,11 @@ class TranslatorKoreanEn : public TranslatorEnglish { return "129"; } + + virtual QCString trISOLang() + { + return "ko"; + } }; #endif diff --git a/src/translator_kr.h b/src/translator_kr.h index fb1c356..dda8f6e 100644 --- a/src/translator_kr.h +++ b/src/translator_kr.h @@ -98,6 +98,10 @@ class TranslatorKorean : public TranslatorAdapter_1_8_15 } return latex_command; } + virtual QCString trISOLang() + { + return "ko"; + } // --- Language translation methods ------------------- @@ -1948,14 +1952,6 @@ class TranslatorKorean : public TranslatorAdapter_1_8_15 return "메소드 문서화"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "디자인 개요"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2012,8 +2008,6 @@ class TranslatorKorean : public TranslatorAdapter_1_8_15 return result; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_lt.h b/src/translator_lt.h index f47d9d4..b491080 100644 --- a/src/translator_lt.h +++ b/src/translator_lt.h @@ -65,6 +65,11 @@ class TranslatorLithuanian : public TranslatorAdapter_1_4_6 "\\usepackage[lithuanian]{babel}\n"; } + virtual QCString trISOLang() + { + return "lt"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ diff --git a/src/translator_lv.h b/src/translator_lv.h index bd579da..36cd78a 100644 --- a/src/translator_lv.h +++ b/src/translator_lv.h @@ -80,6 +80,11 @@ class TranslatorLatvian : public TranslatorAdapter_1_8_4 "\\usepackage[latvian]{babel}\n"; } + virtual QCString trISOLang() + { + return "lv"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1944,8 +1949,6 @@ class TranslatorLatvian : public TranslatorAdapter_1_8_4 return "Dizaina pārskats"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_mk.h b/src/translator_mk.h index 3fc046e..ea5c3c8 100644 --- a/src/translator_mk.h +++ b/src/translator_mk.h @@ -65,6 +65,10 @@ class TranslatorMacedonian : public TranslatorAdapter_1_6_0 { return "\\usepackage[macedonian]{babel}\n"; } + virtual QCString trISOLang() + { + return "mk"; + } // --- Language translation methods ------------------- @@ -1718,6 +1722,7 @@ class TranslatorMacedonian : public TranslatorAdapter_1_6_0 { return "Ограничувања на Тип"; } + }; #endif diff --git a/src/translator_nl.h b/src/translator_nl.h index 7cecc7d..07e90ae 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -35,9 +35,9 @@ class TranslatorDutch : public Translator * </pre> */ QCString latexLanguageSupportCommand() - { - return "\\usepackage[dutch]{babel}\n"; - } + { return "\\usepackage[dutch]{babel}\n"; } + QCString trISOLang() + { return "nl"; } QCString trRelatedFunctions() { return "Gerelateerde functies"; } QCString trRelatedSubscript() @@ -1530,14 +1530,6 @@ class TranslatorDutch : public Translator return "Methode Documentatie"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Ontwerp Overzicht"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -1784,7 +1776,12 @@ class TranslatorDutch : public Translator { return "Data members"; } virtual QCString trDataMemberDocumentation() { return "Documentatie van data members"; } - ////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + virtual QCString trDesignUnitDocumentation() + { return "Ontwerp Eenheid Documentatie"; } }; #endif diff --git a/src/translator_no.h b/src/translator_no.h index eccd952..1dc331a 100644..100755 --- a/src/translator_no.h +++ b/src/translator_no.h @@ -75,6 +75,11 @@ class TranslatorNorwegian : public TranslatorAdapter_1_4_6 "\\usepackage[norsk]{babel}\n"; } + virtual QCString trISOLang() + { + return "nn"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1563,6 +1568,7 @@ class TranslatorNorwegian : public TranslatorAdapter_1_4_6 "generert for deg. Den skiller seg ut fra " "funksjonen ovenfor i argument(ene) den aksepterer."; } + }; #endif diff --git a/src/translator_pl.h b/src/translator_pl.h index e0ecc8f..096e9b0 100644 --- a/src/translator_pl.h +++ b/src/translator_pl.h @@ -54,6 +54,11 @@ class TranslatorPolish : public TranslatorAdapter_1_8_2 */ } + virtual QCString trISOLang() + { + return "pl"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1866,8 +1871,6 @@ class TranslatorPolish : public TranslatorAdapter_1_8_2 virtual QCString trAdditionalInheritedMembers() { return "Dodatkowe Dziedziczone Składowe"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_pt.h b/src/translator_pt.h index 970cf45..0185aea 100644 --- a/src/translator_pt.h +++ b/src/translator_pt.h @@ -59,7 +59,7 @@ #define TRANSLATOR_PT_H -class TranslatorPortuguese : public Translator +class TranslatorPortuguese : public TranslatorAdapter_1_8_19 { public: @@ -94,6 +94,11 @@ class TranslatorPortuguese : public Translator "\\usepackage[portuges]{babel}\n"; } + virtual QCString trISOLang() + { + return "pt"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1945,15 +1950,6 @@ class TranslatorPortuguese : public Translator return "Documentação do método"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - // I'm not sure how to accurately translate it - return "Visão geral do design"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2272,7 +2268,6 @@ class TranslatorPortuguese : public Translator return "Dados Membros"; } -////////////////////////////////////////////////////////////////////////// }; diff --git a/src/translator_ro.h b/src/translator_ro.h index 6f0c197..edb82bf 100644 --- a/src/translator_ro.h +++ b/src/translator_ro.h @@ -74,6 +74,10 @@ class TranslatorRomanian : public TranslatorAdapter_1_8_15 { return "\\usepackage[romanian]{babel}\n"; } + virtual QCString trISOLang() + { + return "ro"; + } // --- Language translation methods ------------------- @@ -1943,14 +1947,6 @@ class TranslatorRomanian : public TranslatorAdapter_1_8_15 return "Documentația Metodelor"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Vedere de Ansamblu a Designului"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2013,8 +2009,6 @@ class TranslatorRomanian : public TranslatorAdapter_1_8_15 return result; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_ru.h b/src/translator_ru.h index 9d92888..aafae90 100644 --- a/src/translator_ru.h +++ b/src/translator_ru.h @@ -35,9 +35,10 @@ class TranslatorRussian : public TranslatorAdapter_1_8_15 /* Used to get the command(s) for the language support. */ virtual QCString latexLanguageSupportCommand() - { - return "\\usepackage[T2A]{fontenc}\n\\usepackage[russian]{babel}\n"; - } + { return "\\usepackage[T2A]{fontenc}\n\\usepackage[russian]{babel}\n"; } + + virtual QCString trISOLang() + { return "ru"; } // --- Language translation methods ------------------- @@ -1904,14 +1905,6 @@ class TranslatorRussian : public TranslatorAdapter_1_8_15 return "Документация метода"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Обзор дизайна"; - } - /////////////////////////////////////////////////////////////////////// // new since 1.8.4 /////////////////////////////////////////////////////////////////////// @@ -1967,8 +1960,6 @@ class TranslatorRussian : public TranslatorAdapter_1_8_15 if (single) result+="а:"; else result+="ов:"; return result; } - -/////////////////////////////////////////////////////////////////////// }; #endif diff --git a/src/translator_sc.h b/src/translator_sc.h index e8191df..5217948 100644 --- a/src/translator_sc.h +++ b/src/translator_sc.h @@ -72,12 +72,16 @@ class TranslatorSerbianCyrillic : public TranslatorAdapter_1_6_0 virtual QCString latexLanguageSupportCommand() { return "\\usepackage[T2A]{fontenc}\n" - "\\usepackage[russian]{babel}\n"; + "\\usepackage[serbianc]{babel}\n"; } virtual QCString latexFontenc() { return ""; } + virtual QCString trISOLang() + { + return "sr-Cyrl"; + } // --- Language translation methods ------------------- diff --git a/src/translator_si.h b/src/translator_si.h index 2dd7e5b..5a03a71 100644 --- a/src/translator_si.h +++ b/src/translator_si.h @@ -35,9 +35,9 @@ class TranslatorSlovene : public TranslatorAdapter_1_4_6 * method is used to generate the command for using the babel package. */ QCString latexLanguageSupportCommand() - { - return "\\usepackage[slovene]{babel}\n"; - } + { return "\\usepackage[slovene]{babel}\n"; } + QCString trISOLang() + { return "sl"; } QCString trRelatedFunctions() { return "Povezane funkcije"; } QCString trRelatedSubscript() @@ -1207,6 +1207,7 @@ class TranslatorSlovene : public TranslatorAdapter_1_4_6 "podana je zaradi priročnosti. Metoda se od predhodnje razlikuje " "samo v številu in/ali tipu formalnih argumentov."; } + }; #endif diff --git a/src/translator_sk.h b/src/translator_sk.h index 9ee8252..1e5d258 100644 --- a/src/translator_sk.h +++ b/src/translator_sk.h @@ -49,6 +49,10 @@ class TranslatorSlovak : public TranslatorAdapter_1_8_15 "\\xpatchparametertext\\@cline{-}{\\cA-}{}{}\n" "\\makeatother\n"; } + virtual QCString trISOLang() + { + return "sk"; + } // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -1907,14 +1911,6 @@ class TranslatorSlovak : public TranslatorAdapter_1_8_15 return "Dokumentácia metódy"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Návrhová schéma"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -1971,7 +1967,6 @@ class TranslatorSlovak : public TranslatorAdapter_1_8_15 return result; } -////////////////////////////////////////////////////////////////////////// }; #endif // TRANSLATOR_SK_H diff --git a/src/translator_sr.h b/src/translator_sr.h index f5f132f..bfd32f6 100644 --- a/src/translator_sr.h +++ b/src/translator_sr.h @@ -58,6 +58,10 @@ class TranslatorSerbian : public TranslatorAdapter_1_6_0 QCString result="\\usepackage[serbian]{babel}\n"; return result; } + virtual QCString trISOLang() + { + return "sr-Latn"; + } // --- Language translation methods ------------------- diff --git a/src/translator_sv.h b/src/translator_sv.h index 5da89df..bc63870 100644 --- a/src/translator_sv.h +++ b/src/translator_sv.h @@ -23,6 +23,7 @@ Xet Erixon <xet@xeqt.com> Mikael Hallin <mikaelhallin@yahoo.se> 2003-07-28 Björn Palmqvist <bjorn@aidium.se> 2014-02-01 Magnus Österlund <magnus.osterlund@capgemini.com> 2016-09-12 +Björn Palmqvist <bjorn@aidium.se> 2020-01-08 ================================================================================== Uppdateringar. 1999/04/29 @@ -66,20 +67,46 @@ Problem! Deprecated: nån hygglig svensk översättning??? Skicka gärna synpunkter. + 2015/01/09 * Uppdaterat den till senaste versionen 1.8.9.1 + 2015/09/12 * Fixat lite särksirvningar och inkonsekvenser + +2020/01/08 +* Uppdaterat den till senaste språkversionen 1.8.15 + +Bytte ut Deprecated från Föråldrad till Obsolet + +VHDL översättningarna är kanske inte perfekta, då jag endast använt de en gång tidigare. +Jag lämnade use clause orörd, då jag inte hittade en lämplig översättning för den. + +English: +* Updated the language translation to 1.8.15 + +Changed Deprecated from Föråldrad to Obsolet + +The VHDL translations may not perfect, as I only used it once before. +I left use clause untouched as I didn't find a suitable translation for it. + +2020/08/14 +* Uppdaterat översättningarna till 1.8.19 +English: +* Updated the language translation to 1.8.19 + =================================================================================== Ordlista =================================================================================== ENGELSKA SVENSKA * Attribute Attribut -* Category Lategori +* Category Kategori * Class Klass * Compound Sammansatt -* Deprecated Föråldrad +* Deprecated Obsolet * Directory Katalog +* Dictionary Uppslagsverk // Frågan om de är de som menas i de fallet +* Entity Entitet * Enum Enum * Enumeration Egenuppräknande * Event Händelse @@ -89,6 +116,7 @@ Problem! * Function Funktion * Inherited Ärvd * Interface Gränssnitt +* Library Biblotek * Macro Makro * Member Medlem * Member Data Medlemsdata @@ -103,16 +131,19 @@ Problem! * Protected Skyddad * Protocol Protokoll * Public Publik +* Record Post // Ge gärna exempel på bättre översättning * Service Tjänst * Signal Signal -* Slot Slot //Ge gärna exempel på bättre översättning +* Slot Slot // Ge gärna exempel på bättre översättning * Static Statisk * Struct Struktur * Subprogram Underprogram * Subroutine Subrutin +* Subtype Undertyp * Template Mall * Typedef Typdefinition * Union Union +* Unit Enhet // Lämplig översättning i VHDL kontextet? * Variable Variabel =================================================================================== */ @@ -120,7 +151,7 @@ Problem! #ifndef TRANSLATOR_SE_H #define TRANSLATOR_SE_H -class TranslatorSwedish : public TranslatorAdapter_1_8_15 +class TranslatorSwedish : public Translator { public: @@ -146,6 +177,11 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 return "\\usepackage[swedish]{babel}\n"; } + virtual QCString trISOLang() + { + return "sv"; + } + // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ @@ -881,7 +917,7 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 virtual QCString trDeprecated() { - return "Föråldrad"; + return "Obsolet"; } ////////////////////////////////////////////////////////////////////////// @@ -1041,7 +1077,7 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 virtual QCString trInclByDepGraph() { return "Den här grafen visar vilka filer som direkt eller " - "indirekt inkluderar denna filen:"; + "indirekt inkluderar denna filen:"; } virtual QCString trSince() { @@ -1152,7 +1188,7 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 /*! Used as a section header for IDL properties */ virtual QCString trProperties() { - return "Egenskaper"; + return "Egenskaper"; } /*! Used as a section header for IDL property documentation */ virtual QCString trPropertyDocumentation() @@ -1230,8 +1266,8 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 * Charset Name Charset Value(hex) Codepage number * ------------------------------------------------------ * ANSI_CHARSET 0 (x00) 1252 - * </pre> - */ + * </pre> + */ virtual QCString trRTFansicp() { return "1252"; @@ -1552,7 +1588,7 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 * and the fact that it is sorted alphabetically per level */ virtual QCString trDirDescription() - { return "Den här katalogen är grovt sorterad, " + { return "Den här katalogen är grovt sorterad, " "men inte helt, i alfabetisk ordning:"; } @@ -1952,7 +1988,7 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 */ virtual QCString trPanelSynchronisationTooltip(bool enable) { - QCString opt = enable ? "aktivera" : "inaktivera"; + QCString opt = enable ? "aktivera" : "inaktivera"; return "klicka för att "+opt+" panelsynkronisering"; } @@ -1997,14 +2033,6 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 return "Metoddokumentation"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "Designöversikt"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -2055,13 +2083,272 @@ class TranslatorSwedish : public TranslatorAdapter_1_8_15 virtual QCString trSingletonGeneratedFromFiles(bool single) { // single is true implies a single file - QCString result=(QCString)"Dokumentationen för denna singleton" + QCString result=(QCString)"Dokumentationen för denna singleton " "genererades från följande fil"; if (single) result+=":"; else result+="er:"; return result; } +////////////////////////////////////////////////////////////////////////// +// new since 1.8.15 +////////////////////////////////////////////////////////////////////////// -}; + /** VHDL design unit hierarchy */ + virtual QCString trDesignUnitHierarchy() + { return "Designenhetshirarki"; } + /** VHDL design unit list */ + virtual QCString trDesignUnitList() + { return "Designenhetslista"; } + /** VHDL design unit members */ + virtual QCString trDesignUnitMembers() + { return "Designenhetsmedlemmar"; } + /** VHDL design unit list description + * Orginal: Here is a list of all design unit members with links to + * the Entities they belong to: + */ + virtual QCString trDesignUnitListDescription() + { + return "Här är en lista av alla designenhetsmedlemmar med länkar till " + "entiteterna som de hör till:"; + } + /** VHDL design unit index */ + virtual QCString trDesignUnitIndex() + { return "Designenhetsindex"; } + /** VHDL design units */ + virtual QCString trDesignUnits() + { return "Designenheter"; } + /** VHDL functions/procedures/processes */ + virtual QCString trFunctionAndProc() + { return "Funktioner/Procedurer/Processer"; } + /** VHDL type */ + virtual QCString trVhdlType(uint64 type,bool single) + { + switch(type) + { + case VhdlDocGen::LIBRARY: + return "Biblotek"; + case VhdlDocGen::PACKAGE: + return "Paket"; + case VhdlDocGen::SIGNAL: + if (single) return "Signal"; + else return "Signaler"; + case VhdlDocGen::COMPONENT: + if (single) return "Komponent"; + else return "Komponenter"; + case VhdlDocGen::CONSTANT: + if (single) return "Konstant"; + else return "Konstanter"; + case VhdlDocGen::ENTITY: + if (single) return "Entitet"; + else return "Entiteter"; + case VhdlDocGen::TYPE: + if (single) return "Typ"; + else return "Typer"; + case VhdlDocGen::SUBTYPE: + if (single) return "Undertyp"; + else return "Undertyper"; + case VhdlDocGen::FUNCTION: + if (single) return "Funktion"; + else return "Funktioner"; + case VhdlDocGen::RECORD: + if (single) return "Post"; + else return "Poster"; + case VhdlDocGen::PROCEDURE: + if (single) return "Procedur"; + else return "Procedurer"; + case VhdlDocGen::ARCHITECTURE: + if (single) return "Arkitektur"; + else return "Arkitekturer"; + case VhdlDocGen::ATTRIBUTE: + return "Attribut"; + case VhdlDocGen::PROCESS: + if (single) return "Process"; + else return "Processer"; + case VhdlDocGen::PORT: + if (single) return "Port"; + else return "Portar"; + case VhdlDocGen::USE: + if (single) return "use clause"; + else return "Use Clauses"; + case VhdlDocGen::GENERIC: + if (single) return "Generisk"; + else return "Generiska"; + case VhdlDocGen::PACKAGE_BODY: + return "Paketinehåll"; + case VhdlDocGen::UNITS: + return "Enheter"; + case VhdlDocGen::SHAREDVARIABLE: + if (single) return "Delad Variabel"; + else return "Delade Variabler"; + case VhdlDocGen::VFILE: + if (single) return "Fil"; + else return "Filer"; + case VhdlDocGen::GROUP: + if (single) return "Grupp"; + else return "Grupper"; + case VhdlDocGen::INSTANTIATION: + if (single) return "Instantiation"; + else return "Instantiations"; + case VhdlDocGen::ALIAS: + return "Alias"; + case VhdlDocGen::CONFIG: + if (single) return "Konfiguration"; + else return "Konfigurationer"; + case VhdlDocGen::MISCELLANEOUS: + return "Diverse"; + case VhdlDocGen::UCF_CONST: + return "Begränsningar"; + default: + return "Klass"; + } + } + virtual QCString trCustomReference(const char *name) + { return QCString(name)+"referens"; } + + /* Slice */ + virtual QCString trConstants() + { + return "Konstanter"; + } + virtual QCString trConstantDocumentation() + { + return "Konstantdokumentation"; + } + virtual QCString trSequences() + { + return "Sekvenser"; + } + virtual QCString trSequenceDocumentation() + { + return "Sekvensdokumentation"; + } + virtual QCString trDictionaries() + { + return "Uppslagsverk"; + } + virtual QCString trDictionaryDocumentation() + { + return "Uppslagsverksdokumentation"; + } + virtual QCString trSliceInterfaces() + { + return "Gränssnitt"; + } + virtual QCString trInterfaceIndex() + { + return "Gränssnittsindex"; + } + virtual QCString trInterfaceList() + { + return "Gränssnittslist"; + } + /** Orginal: Here are the interfaces with brief descriptions: */ + virtual QCString trInterfaceListDescription() + { + return "Här är gränssnitten med en kort beskrivning"; + } + virtual QCString trInterfaceHierarchy() + { + return "Gränssnittshirarkin"; + } + /** Orginal: This inheritance list is sorted roughly, but not completely, alphabetically: */ + virtual QCString trInterfaceHierarchyDescription() + { + return "Denna arvslista är grovt sorterad, men inte helt, i alfabetisk ordning:"; + } + virtual QCString trInterfaceDocumentation() + { + return "Gränssnittsdokumentation"; + } + virtual QCString trStructs() + { + return "Strukturer"; + } + virtual QCString trStructIndex() + { + return "Strukturindex"; + } + virtual QCString trStructList() + { + return "Strukturlist"; + } + /** Orginal: Here are the structs with brief descriptions: */ + virtual QCString trStructListDescription() + { + return "Här är strukturerna med en kort beskrivning:"; + } + virtual QCString trStructDocumentation() + { + return "Strukturdokumentation"; + } + virtual QCString trExceptionIndex() + { + return "Undantagsindex"; + } + virtual QCString trExceptionList() + { + return "Undantagslista"; + } + /** Orginal: Here are the exceptions with brief descriptions: */ + virtual QCString trExceptionListDescription() + { + return "Här är undantagen med en kort beskrivning:"; + } + virtual QCString trExceptionHierarchy() + { + return "Undantagshirarki"; + } + /** Orginal: This inheritance list is sorted roughly, but not completely, alphabetically: */ + virtual QCString trExceptionHierarchyDescription() + { + return "Denna arvslista är grovt sorterad, men inte helt, i alfabetisk ordning:"; + } + virtual QCString trExceptionDocumentation() + { + return "Undantagsdokumentation"; + } + virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal) + { + QCString result=(QCString)clName; + if (isLocal) result+=" Lokal"; + switch(compType) + { + case ClassDef::Class: result+=" Klass"; break; + case ClassDef::Struct: result+=" Struktur"; break; + case ClassDef::Union: result+=" Unions"; break; + case ClassDef::Interface: result+=" Gränssnitts"; break; + case ClassDef::Protocol: result+=" Protokoll"; break; + case ClassDef::Category: result+=" Kategori"; break; + case ClassDef::Exception: result+=" Undantags"; break; + default: break; + } + result+="referens"; + return result; + } + virtual QCString trOperations() + { + return "Operationer"; + } + virtual QCString trOperationDocumentation() + { + return "Operationsdokumentation"; + } + virtual QCString trDataMembers() + { + return "Datamedlemmar"; + } + virtual QCString trDataMemberDocumentation() + { + return "Datamedlemsdokumentation"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit documentation */ + virtual QCString trDesignUnitDocumentation() + { return "Designenhetsdokumentation"; } +}; #endif diff --git a/src/translator_tr.h b/src/translator_tr.h index d18f800..4a68184 100644 --- a/src/translator_tr.h +++ b/src/translator_tr.h @@ -71,7 +71,11 @@ class TranslatorTurkish : public TranslatorAdapter_1_7_5 */ virtual QCString latexLanguageSupportCommand() { - return ""; + return "\\usepackage[turkish]{babel}\n"; + } + virtual QCString trISOLang() + { + return "tr"; } // --- Language translation methods ------------------- @@ -1816,7 +1820,6 @@ class TranslatorTurkish : public TranslatorAdapter_1_7_5 return sdate; } - }; #endif diff --git a/src/translator_tw.h b/src/translator_tw.h index 9e9092d..8d9658b 100644 --- a/src/translator_tw.h +++ b/src/translator_tw.h @@ -86,6 +86,10 @@ class TranslatorChinesetraditional : public TranslatorAdapter_1_8_15 { return "\\end{CJK}\n"; } + virtual QCString trISOLang() + { + return "zh-Hant"; + } // --- Language translation methods ------------------- @@ -1913,14 +1917,6 @@ class TranslatorChinesetraditional : public TranslatorAdapter_1_8_15 return "方法文件"; } - /*! Used as the title of the design overview picture created for the - * VHDL output. - */ - virtual QCString trDesignOverview() - { - return "設計概述"; - } - ////////////////////////////////////////////////////////////////////////// // new since 1.8.4 ////////////////////////////////////////////////////////////////////////// @@ -1977,8 +1973,6 @@ class TranslatorChinesetraditional : public TranslatorAdapter_1_8_15 return result; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_ua.h b/src/translator_ua.h index 034cb1b..2c5047c 100644 --- a/src/translator_ua.h +++ b/src/translator_ua.h @@ -31,6 +31,10 @@ class TranslatorUkrainian : public TranslatorAdapter_1_8_4 { return "\\usepackage[T2A]{fontenc}\n\\usepackage[ukrainian]{babel}\n"; } + virtual QCString trISOLang() + { + return "uk"; + } // --- Language translation methods ------------------- @@ -1909,8 +1913,6 @@ class TranslatorUkrainian : public TranslatorAdapter_1_8_4 return "Огляд дизайну проекту"; } -////////////////////////////////////////////////////////////////////////// - }; #endif diff --git a/src/translator_vi.h b/src/translator_vi.h index b391b0c..50c0a01 100644 --- a/src/translator_vi.h +++ b/src/translator_vi.h @@ -95,6 +95,10 @@ class TranslatorVietnamese : public TranslatorAdapter_1_6_0 } return latex_command; } + virtual QCString trISOLang() + { + return "vi"; + } // --- Language translation methods ------------------- /*! used in the compound documentation before a list of related functions. */ diff --git a/src/translator_za.h b/src/translator_za.h index dd5ddf9..fdf3e6a 100644 --- a/src/translator_za.h +++ b/src/translator_za.h @@ -57,9 +57,11 @@ class TranslatorAfrikaans : public TranslatorAdapter_1_6_0 */ virtual QCString latexLanguageSupportCommand() { - //should we use return "\\usepackage[afrikaans]{babel}\n"; - // not sure - for now return an empty string - return ""; + return "\\usepackage[afrikaans]{babel}\n"; + } + virtual QCString trISOLang() + { + return "af"; } // --- Language translation methods ------------------- diff --git a/src/types.h b/src/types.h index 189a93d..d34444c 100644 --- a/src/types.h +++ b/src/types.h @@ -54,7 +54,7 @@ enum SrcLangExt SrcLangExt_Fortran = 0x01000, SrcLangExt_VHDL = 0x02000, SrcLangExt_XML = 0x04000, - SrcLangExt_Tcl = 0x08000, + //SrcLangExt_Tcl = 0x08000, // no longer supported SrcLangExt_Markdown = 0x10000, SrcLangExt_SQL = 0x20000, SrcLangExt_Slice = 0x40000 @@ -97,12 +97,6 @@ struct Grouping }; -struct ListItemInfo -{ - QCString type; - int itemId; -}; - enum MemberListType { MemberListType_privateLists = 0x0800, diff --git a/src/util.cpp b/src/util.cpp index abcd910..acc6098 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,11 +1,11 @@ /***************************************************************************** - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,6 +19,11 @@ #include <errno.h> #include <math.h> #include <limits.h> +#include <cinttypes> +#include <string.h> + +#include <mutex> +#include <unordered_set> #include "md5.h" @@ -84,7 +89,7 @@ #define ALGO_COUNT 1 #define ALGO_CRC16 2 #define ALGO_MD5 3 - + //#define MAP_ALGO ALGO_COUNT //#define MAP_ALGO ALGO_CRC16 #define MAP_ALGO ALGO_MD5 @@ -95,12 +100,12 @@ // TextGeneratorOLImpl implementation //------------------------------------------------------------------------ -TextGeneratorOLImpl::TextGeneratorOLImpl(OutputDocInterface &od) : m_od(od) +TextGeneratorOLImpl::TextGeneratorOLImpl(OutputDocInterface &od) : m_od(od) { } void TextGeneratorOLImpl::writeString(const char *s,bool keepSpaces) const -{ +{ if (s==0) return; //printf("TextGeneratorOlImpl::writeString('%s',%d)\n",s,keepSpaces); if (keepSpaces) @@ -113,19 +118,19 @@ void TextGeneratorOLImpl::writeString(const char *s,bool keepSpaces) const cs[1]='\0'; while ((c=*p++)) { - if (c==' ') m_od.writeNonBreakableSpace(1); + if (c==' ') m_od.writeNonBreakableSpace(1); else cs[0]=c,m_od.docify(cs); } } } else { - m_od.docify(s); + m_od.docify(s); } } void TextGeneratorOLImpl::writeBreak(int indent) const -{ +{ m_od.lineBreak("typebreak"); int i; for (i=0;i<indent;i++) @@ -146,9 +151,9 @@ void TextGeneratorOLImpl::writeLink(const char *extRef,const char *file, //------------------------------------------------------------------------ // an inheritance tree of depth of 100000 should be enough for everyone :-) -const int maxInheritanceDepth = 100000; +const int maxInheritanceDepth = 100000; -/*! +/*! Removes all anonymous scopes from string s Possible examples: \verbatim @@ -177,9 +182,9 @@ QCString removeAnonymousScopes(const QCString &s) while (c<i+l && s.at(c)!='@') if (s.at(c++)==':') b1=TRUE; c=i+l-1; while (c>=i && s.at(c)!='@') if (s.at(c--)==':') b2=TRUE; - if (b1 && b2) - { - result+="::"; + if (b1 && b2) + { + result+="::"; } p=i+l; } @@ -248,7 +253,7 @@ done: void writePageRef(OutputDocInterface &od,const char *cn,const char *mn) { od.pushGeneratorState(); - + od.disable(OutputGenerator::Html); od.disable(OutputGenerator::Man); od.disable(OutputGenerator::Docbook); @@ -273,22 +278,20 @@ QCString generateMarker(int id) return result; } -static QCString stripFromPath(const QCString &path,QStrList &l) +static QCString stripFromPath(const QCString &path,const StringVector &l) { - // look at all the strings in the list and strip the longest match - const char *s=l.first(); + // look at all the strings in the list and strip the longest match QCString potential; unsigned int length = 0; - while (s) + for (const auto &s : l) { - QCString prefix = s; + QCString prefix = s.c_str(); if (prefix.length() > length && qstricmp(path.left(prefix.length()),prefix)==0) // case insensitive compare { length = prefix.length(); potential = path.right(path.length()-prefix.length()); } - s = l.next(); } if (length) return potential; return path; @@ -311,7 +314,7 @@ QCString stripFromIncludePath(const QCString &path) } /*! try to determine if \a name is a source or a header file name by looking - * at the extension. A number of variations is allowed in both upper and + * at the extension. A number of variations is allowed in both upper and * lower case) If anyone knows or uses another extension please let me know :-) */ int guessSection(const char *name) @@ -331,7 +334,7 @@ int guessSection(const char *name) n.right(4)==".i++" || n.right(4)==".inl" || n.right(4)==".xml" || - n.right(4)==".sql" + n.right(4)==".sql" ) return Entry::SOURCE_SEC; if (n.right(2)==".h" || // header n.right(3)==".hh" || @@ -352,7 +355,7 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, //printf("<<resolveTypeDef(%s,%s)\n", // context ? context->name().data() : "<none>",qualifiedName.data()); QCString result; - if (qualifiedName.isEmpty()) + if (qualifiedName.isEmpty()) { //printf(" qualified name empty!\n"); return result; @@ -374,12 +377,12 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, return result; } } - MemberDef *md=0; + const MemberDef *md=0; while (mContext && md==0) { // step 1: get the right scope const Definition *resScope=mContext; - if (scopeIndex!=-1) + if (scopeIndex!=-1) { // split-off scope part QCString resScopeName = qualifiedName.left(scopeIndex); @@ -400,31 +403,30 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, } } //printf("resScope=%s\n",resScope?resScope->name().data():"<none>"); - + // step 2: get the member - if (resScope) // no scope or scope found in the current context + if (resScope) // no scope or scope found in the current context { //printf("scope found: %s, look for typedef %s\n", // resScope->qualifiedName().data(),resName.data()); - MemberNameSDict *mnd=0; + MemberNameLinkedMap *mnd=0; if (resScope->definitionType()==Definition::TypeClass) { - mnd=Doxygen::memberNameSDict; + mnd=Doxygen::memberNameLinkedMap; } else { - mnd=Doxygen::functionNameSDict; + mnd=Doxygen::functionNameLinkedMap; } MemberName *mn=mnd->find(resName); if (mn) { - MemberNameIterator mni(*mn); - MemberDef *tmd=0; int minDist=-1; - for (;(tmd=mni.current());++mni) + for (const auto &tmd_p : *mn) { + const MemberDef *tmd = tmd_p.get(); //printf("Found member %s resScope=%s outerScope=%s mContext=%p\n", - // tmd->name().data(), resScope->name().data(), + // tmd->name().data(), resScope->name().data(), // tmd->getOuterScope()->name().data(), mContext); if (tmd->isTypedef() /*&& tmd->getOuterScope()==resScope*/) { @@ -465,48 +467,38 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, // qualifiedName.data(),context ? context->name().data() : "<global>"); } return result; - + } -/*! Get a class definition given its name. +/*! Get a class definition given its name. * Returns 0 if the class is not found. */ ClassDef *getClass(const char *n) { if (n==0 || n[0]=='\0') return 0; - QCString name=n; - ClassDef *result = Doxygen::classSDict->find(name); - //if (result==0 && !exact) // also try generic and protocol versions - //{ - // result = Doxygen::classSDict->find(name+"-g"); - // if (result==0) - // { - // result = Doxygen::classSDict->find(name+"-p"); - // } - //} - //printf("getClass(%s)=%s\n",n,result?result->name().data():"<none>"); - return result; + return Doxygen::classSDict->find(n); } NamespaceDef *getResolvedNamespace(const char *name) { if (name==0 || name[0]=='\0') return 0; - QCString *subst = Doxygen::namespaceAliasDict[name]; - if (subst) + auto it = Doxygen::namespaceAliasMap.find(name); + if (it!=Doxygen::namespaceAliasMap.end()) { int count=0; // recursion detection guard - QCString *newSubst; - while ((newSubst=Doxygen::namespaceAliasDict[*subst]) && count<10) + StringUnorderedMap::iterator it2; + while ((it2=Doxygen::namespaceAliasMap.find(it->second))!=Doxygen::namespaceAliasMap.end() && + count<10) { - subst=newSubst; + it=it2; count++; } if (count==10) { warn_uncond("possible recursive namespace alias detected for %s!\n",name); } - return Doxygen::namespaceSDict->find(subst->data()); + return Doxygen::namespaceSDict->find(it->second.data()); } else { @@ -532,7 +524,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop * within file \a fileScope. * * Example: typedef A T; will return the class representing A if it is a class. - * + * * Example: typedef int T; will return 0, since "int" is not a class. */ const ClassDef *newResolveTypedef(const FileDef *fileScope, @@ -540,7 +532,7 @@ const ClassDef *newResolveTypedef(const FileDef *fileScope, const MemberDef **pMemType, QCString *pTemplSpec, QCString *pResolvedType, - const ArgumentList *actTemplParams) + const std::unique_ptr<ArgumentList> &actTemplParams) { //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); bool isCached = md->isTypedefValCached(); // value already cached @@ -560,19 +552,19 @@ const ClassDef *newResolveTypedef(const FileDef *fileScope, if (g_resolvedTypedefs.find(qname)) return 0; // typedef already done g_resolvedTypedefs.insert(qname,md); // put on the trace list - + const ClassDef *typeClass = md->getClassDef(); QCString type = md->typeString(); // get the "value" of the typedef if (typeClass && typeClass->isTemplate() && actTemplParams && !actTemplParams->empty()) { type = substituteTemplateArgumentsInString(type, - typeClass->templateArguments(),*actTemplParams); + typeClass->templateArguments(),actTemplParams); } QCString typedefValue = type; int tl=type.length(); int ip=tl-1; // remove * and & at the end - while (ip>=0 && (type.at(ip)=='*' || type.at(ip)=='&' || type.at(ip)==' ')) + while (ip>=0 && (type.at(ip)=='*' || type.at(ip)=='&' || type.at(ip)==' ')) { ip--; } @@ -587,7 +579,7 @@ const ClassDef *newResolveTypedef(const FileDef *fileScope, const ClassDef *result = getResolvedClassRec(md->getOuterScope(), fileScope,type,&memTypeDef,0,pResolvedType); // if type is a typedef then return what it resolves to. - if (memTypeDef && memTypeDef->isTypedef()) + if (memTypeDef && memTypeDef->isTypedef()) { result=newResolveTypedef(fileScope,memTypeDef,pMemType,pTemplSpec); goto done; @@ -647,8 +639,8 @@ done: } // remember computed value for next time - if (result && result->getDefFileName()!="<code>") - // this check is needed to prevent that temporary classes that are + if (result && result->getDefFileName()!="<code>") + // this check is needed to prevent that temporary classes that are // introduced while parsing code fragments are being cached here. { //printf("setting cached typedef %p in result %p\n",md,result); @@ -659,9 +651,9 @@ done: pResolvedType ? *pResolvedType : QCString() ); } - + g_resolvedTypedefs.remove(qname); // remove from the trace list - + return result; } @@ -696,11 +688,11 @@ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,co { // test accessibility of typedef within scope. int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); - if (distance!=-1 && distance<minDistance) + if (distance!=-1 && distance<minDistance) // definition is accessible and a better match { minDistance=distance; - bestMatch = md; + bestMatch = md; } } } @@ -715,18 +707,18 @@ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,co { // test accessibility of typedef within scope. int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); - if (distance!=-1) // definition is accessible + if (distance!=-1) // definition is accessible { - bestMatch = md; + bestMatch = md; } } } - if (bestMatch) + if (bestMatch) { result = bestMatch->typeString(); if (pTypeDef) *pTypeDef=bestMatch; } - + //printf("substTypedef(%s,%s)=%s\n",scope?scope->name().data():"<global>", // name.data(),result.data()); return result; @@ -750,8 +742,8 @@ static const Definition *endOfPathIsUsedClass(const SDict<Definition> *cl,const } /*! Starting with scope \a start, the string \a path is interpreted as - * a part of a qualified scope name (e.g. A::B::C), and the scope is - * searched. If found the scope definition is returned, otherwise 0 + * a part of a qualified scope name (e.g. A::B::C), and the scope is + * searched. If found the scope definition is returned, otherwise 0 * is returned. */ static const Definition *followPath(const Definition *start,const FileDef *fileScope,const QCString &path) @@ -782,7 +774,7 @@ static const Definition *followPath(const Definition *start,const FileDef *fileS // qualScopePart.data(), // current->name().data(), // next?next->name().data():"<null>"); - if (next==0) // failed to follow the path + if (next==0) // failed to follow the path { //printf("==> next==0!\n"); if (current->definitionType()==Definition::TypeNamespace) @@ -817,7 +809,7 @@ bool accessibleViaUsingClass(const SDict<Definition> *cl, ) { //printf("accessibleViaUsingClass(%p)\n",cl); - if (cl) // see if the class was imported via a using statement + if (cl) // see if the class was imported via a using statement { SDict<Definition>::Iterator cli(*cl); Definition *ucd; @@ -826,7 +818,7 @@ bool accessibleViaUsingClass(const SDict<Definition> *cl, { //printf("Trying via used class %s\n",ucd->name().data()); const Definition *sc = explicitScopePartEmpty ? ucd : followPath(ucd,fileScope,explicitScopePart); - if (sc && sc==item) return TRUE; + if (sc && sc==item) return TRUE; //printf("Try via used class done\n"); } } @@ -849,10 +841,10 @@ bool accessibleViaUsingNamespace(const NamespaceSDict *nl, //printf("[Trying via used namespace %s: count=%d/%d\n",und->name().data(), // count,nl->count()); const Definition *sc = explicitScopePart.isEmpty() ? und : followPath(und,fileScope,explicitScopePart); - if (sc && item->getOuterScope()==sc) + if (sc && item->getOuterScope()==sc) { //printf("] found it\n"); - return TRUE; + return TRUE; } if (item->getLanguage()==SrcLangExt_Cpp) { @@ -916,7 +908,7 @@ class AccessStack for (i=0;i<m_index;i++) { AccessElem *e = &m_elements[i]; - if (e->scope==scope && e->fileScope==fileScope && e->item==item) + if (e->scope==scope && e->fileScope==fileScope && e->item==item) { return TRUE; } @@ -929,7 +921,7 @@ class AccessStack for (i=0;i<m_index;i++) { AccessElem *e = &m_elements[i]; - if (e->scope==scope && e->fileScope==fileScope && e->item==item && e->expScope==expScope) + if (e->scope==scope && e->fileScope==fileScope && e->item==item && e->expScope==expScope) { return TRUE; } @@ -951,7 +943,7 @@ class AccessStack }; /* Returns the "distance" (=number of levels up) from item to scope, or -1 - * if item in not inside scope. + * if item in not inside scope. */ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Definition *item) { @@ -969,20 +961,20 @@ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Defi int i; Definition *itemScope=item->getOuterScope(); - bool memberAccessibleFromScope = + bool memberAccessibleFromScope = (item->definitionType()==Definition::TypeMember && // a member itemScope && itemScope->definitionType()==Definition::TypeClass && // of a class scope->definitionType()==Definition::TypeClass && // accessible (dynamic_cast<const ClassDef*>(scope))->isAccessibleMember(dynamic_cast<const MemberDef *>(item)) // from scope ); - bool nestedClassInsideBaseClass = + bool nestedClassInsideBaseClass = (item->definitionType()==Definition::TypeClass && // a nested class - itemScope && itemScope->definitionType()==Definition::TypeClass && // inside a base + itemScope && itemScope->definitionType()==Definition::TypeClass && // inside a base scope->definitionType()==Definition::TypeClass && // class of scope - (dynamic_cast<const ClassDef*>(scope))->isBaseClass(dynamic_cast<ClassDef*>(itemScope),TRUE) + (dynamic_cast<const ClassDef*>(scope))->isBaseClass(dynamic_cast<ClassDef*>(itemScope),TRUE) ); - if (itemScope==scope || memberAccessibleFromScope || nestedClassInsideBaseClass) + if (itemScope==scope || memberAccessibleFromScope || nestedClassInsideBaseClass) { //printf("> found it\n"); if (nestedClassInsideBaseClass) result++; // penalty for base class to prevent @@ -994,13 +986,13 @@ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Defi if (fileScope) { SDict<Definition> *cl = fileScope->getUsedClasses(); - if (accessibleViaUsingClass(cl,fileScope,item)) + if (accessibleViaUsingClass(cl,fileScope,item)) { //printf("> found via used class\n"); goto done; } NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) + if (accessibleViaUsingNamespace(nl,fileScope,item)) { //printf("> found via used namespace\n"); goto done; @@ -1017,13 +1009,13 @@ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Defi const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); //printf(" %s is namespace with %d used classes\n",nscope->name().data(),nscope->getUsedClasses()); const SDict<Definition> *cl = nscope->getUsedClasses(); - if (accessibleViaUsingClass(cl,fileScope,item)) + if (accessibleViaUsingClass(cl,fileScope,item)) { //printf("> found via used class\n"); goto done; } const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) + if (accessibleViaUsingNamespace(nl,fileScope,item)) { //printf("> found via used namespace\n"); goto done; @@ -1050,10 +1042,10 @@ done: * class B { public: class J {}; }; * * - Looking for item=='J' inside scope=='B' will return 0. - * - Looking for item=='I' inside scope=='B' will return -1 + * - Looking for item=='I' inside scope=='B' will return -1 * (as it is not found in B nor in the global scope). - * - Looking for item=='A::I' inside scope=='B', first the match B::A::I is tried but - * not found and then A::I is searched in the global scope, which matches and + * - Looking for item=='A::I' inside scope=='B', first the match B::A::I is tried but + * not found and then A::I is searched in the global scope, which matches and * thus the result is 1. */ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope, @@ -1097,7 +1089,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop (dynamic_cast<const ClassDef*>(newScope))->isBaseClass(dynamic_cast<const ClassDef*>(itemScope),TRUE,0) ) { - // inheritance is also ok. Example: looking for B::I, where + // inheritance is also ok. Example: looking for B::I, where // class A { public: class I {} }; // class B : public A {} // but looking for B::I, where @@ -1172,7 +1164,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop { const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) + if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) { //printf("> found in used namespace\n"); goto done; @@ -1183,7 +1175,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop if (fileScope) { const NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) + if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) { //printf("> found in used namespace\n"); goto done; @@ -1216,9 +1208,9 @@ int computeQualifiedIndex(const QCString &name) static void getResolvedSymbol(const Definition *scope, const FileDef *fileScope, - Definition *d, + Definition *d, const QCString &explicitScopePart, - ArgumentList *actTemplParams, + const std::unique_ptr<ArgumentList> &actTemplParams, int &minDistance, const ClassDef *&bestMatch, const MemberDef *&bestTypedef, @@ -1231,8 +1223,8 @@ static void getResolvedSymbol(const Definition *scope, // only look at classes and members that are enums or typedefs if (d->definitionType()==Definition::TypeClass || - (d->definitionType()==Definition::TypeMember && - ((dynamic_cast<MemberDef*>(d))->isTypedef() || (dynamic_cast<MemberDef*>(d))->isEnumerate()) + (d->definitionType()==Definition::TypeMember && + ((dynamic_cast<MemberDef*>(d))->isTypedef() || (dynamic_cast<MemberDef*>(d))->isEnumerate()) ) ) { @@ -1248,23 +1240,23 @@ static void getResolvedSymbol(const Definition *scope, ClassDef *cd = dynamic_cast<ClassDef *>(d); //printf("cd=%s\n",cd->name().data()); if (!cd->isTemplateArgument()) // skip classes that - // are only there to - // represent a template + // are only there to + // represent a template // argument { //printf("is not a templ arg\n"); if (distance<minDistance) // found a definition that is "closer" { minDistance=distance; - bestMatch = cd; + bestMatch = cd; bestTypedef = 0; bestTemplSpec.resize(0); bestResolvedType = cd->qualifiedName(); } else if (distance==minDistance && fileScope && bestMatch && - fileScope->getUsedNamespaces() && - d->getOuterScope()->definitionType()==Definition::TypeNamespace && + fileScope->getUsedNamespaces() && + d->getOuterScope()->definitionType()==Definition::TypeNamespace && bestMatch->getOuterScope()==Doxygen::globalScope ) { @@ -1277,7 +1269,7 @@ static void getResolvedSymbol(const Definition *scope, // Just a non-perfect heuristic but it could help in some situations // (kdecore code is an example). minDistance=distance; - bestMatch = cd; + bestMatch = cd; bestTypedef = 0; bestTemplSpec.resize(0); bestResolvedType = cd->qualifiedName(); @@ -1376,7 +1368,7 @@ static void getResolvedSymbol(const Definition *scope, /* Find the fully qualified class name referred to by the input class * or typedef name against the input scope. * Loops through scope and each of its parent scopes looking for a - * match against the input name. Can recursively call itself when + * match against the input name. Can recursively call itself when * resolving typedefs. */ static const ClassDef *getResolvedClassRec(const Definition *scope, @@ -1388,16 +1380,17 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, ) { //printf("[getResolvedClassRec(%s,%s)\n",scope?scope->name().data():"<global>",n); + if (n==0 || *n=='\0') return 0; QCString name; QCString explicitScopePart; QCString strippedTemplateParams; name=stripTemplateSpecifiersFromScope (removeRedundantWhiteSpace(n),TRUE, &strippedTemplateParams); - ArgumentList actTemplParams; + std::unique_ptr<ArgumentList> actTemplParams; if (!strippedTemplateParams.isEmpty()) // template part that was stripped { - stringToArgumentList(scope->getLanguage(),strippedTemplateParams,actTemplParams); + actTemplParams = stringToArgumentList(scope->getLanguage(),strippedTemplateParams); } int qualifierIndex = computeQualifiedIndex(name); @@ -1411,7 +1404,7 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, name=name.mid(qualifierIndex+2); } - if (name.isEmpty()) + if (name.isEmpty()) { //printf("] empty name\n"); return 0; // empty name @@ -1419,28 +1412,24 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, //printf("Looking for symbol %s\n",name.data()); DefinitionIntf *di = Doxygen::symbolMap->find(name); - // the -g (for C# generics) and -p (for ObjC protocols) are now already + // the -g (for C# generics) and -p (for ObjC protocols) are now already // stripped from the key used in the symbolMap, so that is not needed here. - if (di==0) + if (di==0) { - //di = Doxygen::symbolMap->find(name+"-g"); - //if (di==0) - //{ - di = Doxygen::symbolMap->find(name+"-p"); - if (di==0) - { - //printf("no such symbol!\n"); - return 0; - } - //} + di = Doxygen::symbolMap->find(name+"-p"); + if (di==0) + { + //printf("no such symbol!\n"); + return 0; + } } //printf("found symbol!\n"); - bool hasUsingStatements = - (fileScope && ((fileScope->getUsedNamespaces() && + bool hasUsingStatements = + (fileScope && ((fileScope->getUsedNamespaces() && fileScope->getUsedNamespaces()->count()>0) || - (fileScope->getUsedClasses() && - fileScope->getUsedClasses()->count()>0)) + (fileScope->getUsedClasses() && + fileScope->getUsedClasses()->count()>0)) ); //printf("hasUsingStatements=%d\n",hasUsingStatements); // Since it is often the case that the same name is searched in the same @@ -1467,7 +1456,7 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, // if a file scope is given and it contains using statements we should // also use the file part in the key (as a class name can be in - // two different namespaces and a using statement in a file can select + // two different namespaces and a using statement in a file can select // one of them). if (hasUsingStatements) { @@ -1483,19 +1472,19 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, //printf("Searching for %s result=%p\n",key.data(),pval); if (pval) { - //printf("LookupInfo %p %p '%s' %p\n", - // pval->classDef, pval->typeDef, pval->templSpec.data(), - // pval->resolvedType.data()); + //printf("LookupInfo %p %p '%s' %p\n", + // pval->classDef, pval->typeDef, pval->templSpec.data(), + // pval->resolvedType.data()); if (pTemplSpec) *pTemplSpec=pval->templSpec; if (pTypeDef) *pTypeDef=pval->typeDef; if (pResolvedType) *pResolvedType=pval->resolvedType; //printf("] cachedMatch=%s\n", // pval->classDef?pval->classDef->name().data():"<none>"); - //if (pTemplSpec) + //if (pTemplSpec) // printf("templSpec=%s\n",pTemplSpec->data()); - return pval->classDef; + return pval->classDef; } - else // not found yet; we already add a 0 to avoid the possibility of + else // not found yet; we already add a 0 to avoid the possibility of // endless recursion. { Doxygen::lookupCache->insert(key,new LookupInfo); @@ -1515,7 +1504,7 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, int count=0; for (dli.toFirst();(d=dli.current());++dli,++count) // foreach definition { - getResolvedSymbol(scope,fileScope,d,explicitScopePart,&actTemplParams, + getResolvedSymbol(scope,fileScope,d,explicitScopePart,actTemplParams, minDistance,bestMatch,bestTypedef,bestTemplSpec, bestResolvedType); } @@ -1524,12 +1513,12 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, { //printf(" name is unique\n"); Definition *d = (Definition *)di; - getResolvedSymbol(scope,fileScope,d,explicitScopePart,&actTemplParams, + getResolvedSymbol(scope,fileScope,d,explicitScopePart,actTemplParams, minDistance,bestMatch,bestTypedef,bestTemplSpec, bestResolvedType); } - if (pTypeDef) + if (pTypeDef) { *pTypeDef = bestTypedef; } @@ -1558,7 +1547,7 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, } //printf("] bestMatch=%s distance=%d\n", // bestMatch?bestMatch->name().data():"<none>",minDistance); - //if (pTemplSpec) + //if (pTemplSpec) // printf("templSpec=%s\n",pTemplSpec->data()); return bestMatch; } @@ -1566,7 +1555,7 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, /* Find the fully qualified class name referred to by the input class * or typedef name against the input scope. * Loops through scope and each of its parent scopes looking for a - * match against the input name. + * match against the input name. */ const ClassDef *getResolvedClass(const Definition *scope, const FileDef *fileScope, @@ -1581,7 +1570,7 @@ const ClassDef *getResolvedClass(const Definition *scope, static bool optimizeOutputVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); g_resolvedTypedefs.clear(); if (scope==0 || - (scope->definitionType()!=Definition::TypeClass && + (scope->definitionType()!=Definition::TypeClass && scope->definitionType()!=Definition::TypeNamespace ) || (scope->getLanguage()==SrcLangExt_Java && QCString(n).find("::")!=-1) @@ -1610,7 +1599,7 @@ const ClassDef *getResolvedClass(const Definition *scope, { result = getClass(n); } - if (!mayBeUnlinkable && result && !result->isLinkable()) + if (!mayBeUnlinkable && result && !result->isLinkable()) { if (!mayBeHidden || !result->isHidden()) { @@ -1628,34 +1617,6 @@ const ClassDef *getResolvedClass(const Definition *scope, //------------------------------------------------------------------------- //------------------------------------------------------------------------- -static bool findOperator(const QCString &s,int i) -{ - int b = s.findRev("operator",i); - if (b==-1) return FALSE; // not found - b+=8; - while (b<i) // check if there are only spaces in between - // the operator and the > - { - if (!isspace((uchar)s.at(b))) return FALSE; - b++; - } - return TRUE; -} - -static bool findOperator2(const QCString &s,int i) -{ - int b = s.findRev("operator",i); - if (b==-1) return FALSE; // not found - b+=8; - while (b<i) // check if there are only non-ascii - // characters in front of the operator - { - if (isId((uchar)s.at(b))) return FALSE; - b++; - } - return TRUE; -} - static const char constScope[] = { 'c', 'o', 'n', 's', 't', ':' }; static const char virtualScope[] = { 'v', 'i', 'r', 't', 'u', 'a', 'l', ':' }; static const char operatorScope[] = { 'o', 'p', 'e', 'r', 'a', 't', 'o', 'r', '?', '?', '?' }; @@ -1664,30 +1625,30 @@ struct CharAroundSpace { CharAroundSpace() { - charMap['('].before=FALSE; - charMap['='].before=FALSE; - charMap['&'].before=FALSE; - charMap['*'].before=FALSE; - charMap['['].before=FALSE; - charMap['|'].before=FALSE; - charMap['+'].before=FALSE; - charMap[';'].before=FALSE; - charMap[':'].before=FALSE; - charMap['/'].before=FALSE; - - charMap['='].after=FALSE; - charMap[' '].after=FALSE; - charMap['['].after=FALSE; - charMap[']'].after=FALSE; - charMap['\t'].after=FALSE; - charMap['\n'].after=FALSE; - charMap[')'].after=FALSE; - charMap[','].after=FALSE; - charMap['<'].after=FALSE; - charMap['|'].after=FALSE; - charMap['+'].after=FALSE; - charMap['('].after=FALSE; - charMap['/'].after=FALSE; + charMap[static_cast<int>('(')].before=FALSE; + charMap[static_cast<int>('=')].before=FALSE; + charMap[static_cast<int>('&')].before=FALSE; + charMap[static_cast<int>('*')].before=FALSE; + charMap[static_cast<int>('[')].before=FALSE; + charMap[static_cast<int>('|')].before=FALSE; + charMap[static_cast<int>('+')].before=FALSE; + charMap[static_cast<int>(';')].before=FALSE; + charMap[static_cast<int>(':')].before=FALSE; + charMap[static_cast<int>('/')].before=FALSE; + + charMap[static_cast<int>('=')].after=FALSE; + charMap[static_cast<int>(' ')].after=FALSE; + charMap[static_cast<int>('[')].after=FALSE; + charMap[static_cast<int>(']')].after=FALSE; + charMap[static_cast<int>('\t')].after=FALSE; + charMap[static_cast<int>('\n')].after=FALSE; + charMap[static_cast<int>(')')].after=FALSE; + charMap[static_cast<int>(',')].after=FALSE; + charMap[static_cast<int>('<')].after=FALSE; + charMap[static_cast<int>('|')].after=FALSE; + charMap[static_cast<int>('+')].after=FALSE; + charMap[static_cast<int>('(')].after=FALSE; + charMap[static_cast<int>('/')].after=FALSE; } struct CharElem { @@ -1704,15 +1665,16 @@ static CharAroundSpace g_charAroundSpace; // Note: this function is not reentrant due to the use of static buffer! QCString removeRedundantWhiteSpace(const QCString &s) { - static bool cliSupport = Config_getBool(CPP_CLI_SUPPORT); - static bool vhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); + bool cliSupport = Config_getBool(CPP_CLI_SUPPORT); + bool vhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); if (s.isEmpty() || vhdl) return s; // We use a static character array to // improve the performance of this function - static char *growBuf = 0; - static int growBufLen = 0; + // and thread_local is needed to make it multi-thread safe + static THREAD_LOCAL char *growBuf = 0; + static THREAD_LOCAL int growBufLen = 0; if ((int)s.length()*3>growBufLen) // For input character we produce at most 3 output characters, { growBufLen = s.length()*3; @@ -1994,10 +1956,10 @@ bool rightScopeMatch(const QCString &scope, const QCString &name) { int sl=scope.length(); int nl=name.length(); - return (name==scope || // equal - (scope.right(nl)==name && // substring + return (name==scope || // equal + (scope.right(nl)==name && // substring sl-nl>1 && scope.at(sl-nl-1)==':' && scope.at(sl-nl-2)==':' // scope - ) + ) ); } @@ -2005,10 +1967,10 @@ bool leftScopeMatch(const QCString &scope, const QCString &name) { int sl=scope.length(); int nl=name.length(); - return (name==scope || // equal - (scope.left(nl)==name && // substring + return (name==scope || // equal + (scope.left(nl)==name && // substring sl>nl+1 && scope.at(nl)==':' && scope.at(nl+1)==':' // scope - ) + ) ); } @@ -2021,8 +1983,10 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, //printf("linkify='%s'\n",text); static QRegExp regExp("[a-z_A-Z\\x80-\\xFF][~!a-z_A-Z0-9$\\\\.:\\x80-\\xFF]*"); static QRegExp regExpSplit("(?!:),"); + if (text==0) return; QCString txtStr=text; int strLen = txtStr.length(); + if (strLen==0) return; //printf("linkifyText scope=%s fileScope=%s strtxt=%s strlen=%d external=%d\n", // scope?scope->name().data():"<none>", // fileScope?fileScope->name().data():"<none>", @@ -2032,7 +1996,6 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, int newIndex; int skipIndex=0; int floatingIndex=0; - if (strLen==0) return; // read a word from the text string while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1) { @@ -2045,11 +2008,11 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, } // add non-word part to the result - bool insideString=FALSE; + bool insideString=FALSE; int i; - for (i=index;i<newIndex;i++) - { - if (txtStr.at(i)=='"') insideString=!insideString; + for (i=index;i<newIndex;i++) + { + if (txtStr.at(i)=='"') insideString=!insideString; } //printf("floatingIndex=%d strlen=%d autoBreak=%d\n",floatingIndex,strLen,autoBreak); @@ -2069,16 +2032,16 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, out.writeBreak(indentLevel==0 ? 0 : indentLevel+1); out.writeString(splitText.right(splitLength-i-offset),keepSpaces); floatingIndex=splitLength-i-offset+matchLen; - } + } else { - out.writeString(splitText,keepSpaces); + out.writeString(splitText,keepSpaces); } } else { - //ol.docify(txtStr.mid(skipIndex,newIndex-skipIndex)); - out.writeString(txtStr.mid(skipIndex,newIndex-skipIndex),keepSpaces); + //ol.docify(txtStr.mid(skipIndex,newIndex-skipIndex)); + out.writeString(txtStr.mid(skipIndex,newIndex-skipIndex),keepSpaces); } // get word from string QCString word=txtStr.mid(newIndex,matchLen); @@ -2112,7 +2075,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, } } } - if (!found && (cd || (cd=getClass(matchWord)))) + if (!found && (cd || (cd=getClass(matchWord)))) { //printf("Found class %s\n",cd->name().data()); // add link to the result @@ -2156,10 +2119,10 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, int m = matchWord.findRev("::"); QCString scopeName; - if (scope && - (scope->definitionType()==Definition::TypeClass || + if (scope && + (scope->definitionType()==Definition::TypeClass || scope->definitionType()==Definition::TypeNamespace - ) + ) ) { scopeName=scope->name(); @@ -2171,19 +2134,19 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, } //printf("ScopeName=%s\n",scopeName.data()); - //if (!found) printf("Trying to link %s in %s\n",word.data(),scopeName.data()); - if (!found && - getDefs(scopeName,matchWord,0,md,cd,fd,nd,gd) && - //(md->isTypedef() || md->isEnumerate() || + //if (!found) printf("Trying to link %s in %s\n",word.data(),scopeName.data()); + if (!found && + getDefs(scopeName,matchWord,0,md,cd,fd,nd,gd) && + //(md->isTypedef() || md->isEnumerate() || // md->isReference() || md->isVariable() - //) && - (external ? md->isLinkable() : md->isLinkableInProject()) + //) && + (external ? md->isLinkable() : md->isLinkableInProject()) ) { //printf("Found ref scope=%s\n",d?d->name().data():"<global>"); //ol.writeObjectLink(d->getReference(),d->getOutputFileBase(), // md->anchor(),word); - if (md!=self && (self==0 || md->name()!=self->name())) + if (md!=self && (self==0 || md->name()!=self->name())) // name check is needed for overloaded members, where getDefs just returns one { /* in case of Fortran scop and the variable is a non Fortran variable: don't link, @@ -2230,7 +2193,7 @@ void writeExample(OutputList &ol,ExampleSDict *ed) ol.parseText(exampleLine.mid(index,newIndex-index)); uint entryIndex = exampleLine.mid(newIndex+1,matchLen-1).toUInt(&ok); Example *e=ed->at(entryIndex); - if (ok && e) + if (ok && e) { ol.pushGeneratorState(); //if (latexEnabled) ol.disable(OutputGenerator::Latex); @@ -2254,7 +2217,7 @@ void writeExample(OutputList &ol,ExampleSDict *ed) ol.popGeneratorState(); } index=newIndex+matchLen; - } + } ol.parseText(exampleLine.right(exampleLine.length()-index)); ol.writeString("."); } @@ -2296,12 +2259,12 @@ QCString argListToString(const ArgumentList &al,bool useCanonicalType,bool showD if (it!=al.end()) result+=", "; } result+=")"; - if (al.constSpecifier) result+=" const"; - if (al.volatileSpecifier) result+=" volatile"; - if (al.refQualifier==RefQualifierLValue) result+=" &"; - else if (al.refQualifier==RefQualifierRValue) result+=" &&"; - if (!al.trailingReturnType.isEmpty()) result+=" -> "+al.trailingReturnType; - if (al.pureSpecifier) result+=" =0"; + if (al.constSpecifier()) result+=" const"; + if (al.volatileSpecifier()) result+=" volatile"; + if (al.refQualifier()==RefQualifierLValue) result+=" &"; + else if (al.refQualifier()==RefQualifierRValue) result+=" &&"; + if (!al.trailingReturnType().isEmpty()) result+=" -> "+al.trailingReturnType(); + if (al.pureSpecifier()) result+=" =0"; return removeRedundantWhiteSpace(result); } @@ -2404,7 +2367,7 @@ int filterCRLF(char *buf,int len) { c = '\n'; // each CR to LF if (src<len && buf[src] == '\n') - ++src; // skip LF just after CR (DOS) + ++src; // skip LF just after CR (DOS) } else if ( c == '\0' && src<len-1) // filter out internal \0 characters, as it will confuse the parser { @@ -2415,21 +2378,19 @@ int filterCRLF(char *buf,int len) return dest; // length of the valid part of the buf } -static QCString getFilterFromList(const char *name,const QStrList &filterList,bool &found) +static QCString getFilterFromList(const char *name,const StringVector &filterList,bool &found) { found=FALSE; // compare the file name to the filter pattern list - QStrListIterator sli(filterList); - char* filterStr; - for (sli.toFirst(); (filterStr = sli.current()); ++sli) + for (const auto &filterStr : filterList) { - QCString fs = filterStr; + QCString fs = filterStr.c_str(); int i_equals=fs.find('='); if (i_equals!=-1) { QCString filterPattern = fs.left(i_equals); - QRegExp fpat(filterPattern,Portable::fileSystemIsCaseSensitive(),TRUE); - if (fpat.match(name)!=-1) + QRegExp fpat(filterPattern,Portable::fileSystemIsCaseSensitive(),TRUE); + if (fpat.match(name)!=-1) { // found a match! QCString filterName = fs.mid(i_equals+1); @@ -2457,12 +2418,12 @@ QCString getFileFilter(const char* name,bool isSourceCode) // sanity check if (name==0) return ""; - QStrList& filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS); - QStrList& filterList = Config_getList(FILTER_PATTERNS); + const StringVector& filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS); + const StringVector& filterList = Config_getList(FILTER_PATTERNS); QCString filterName; bool found=FALSE; - if (isSourceCode && !filterSrcList.isEmpty()) + if (isSourceCode && !filterSrcList.empty()) { // first look for source filter pattern list filterName = getFilterFromList(name,filterSrcList,found); } @@ -2497,7 +2458,7 @@ QCString transcodeCharacterStringToUTF8(const QCString &input) int outputSize=inputSize*4+1; QCString output(outputSize); void *cd = portable_iconv_open(outputEncoding,inputEncoding); - if (cd==(void *)(-1)) + if (cd==(void *)(-1)) { err("unsupported character conversion: '%s'->'%s'\n", inputEncoding.data(),outputEncoding); @@ -2529,7 +2490,7 @@ QCString transcodeCharacterStringToUTF8(const QCString &input) /*! reads a file with name \a name and returns it as a string. If \a filter * is TRUE the file will be filtered by any user specified input filter. - * If \a name is "-" the string will be read from standard input. + * If \a name is "-" the string will be read from standard input. */ QCString fileToString(const char *name,bool filter,bool isSourceCode) { @@ -2543,13 +2504,13 @@ QCString fileToString(const char *name,bool filter,bool isSourceCode) if (fileOpened) { const int bSize=4096; - QCString contents(bSize); + QCString contents(bSize+1); int totalSize=0; int size; while ((size=f.readBlock(contents.rawData()+totalSize,bSize))==bSize) { totalSize+=bSize; - contents.resize(totalSize+bSize); + contents.resize(totalSize+bSize+1); } totalSize = filterCRLF(contents.rawData(),totalSize+size)+2; contents.resize(totalSize); @@ -2579,7 +2540,7 @@ QCString fileToString(const char *name,bool filter,bool isSourceCode) return buf.data(); } } - if (!fileOpened) + if (!fileOpened) { err("cannot open file '%s' for reading\n",name); } @@ -2609,7 +2570,7 @@ static QDateTime getCurrentDateTime() static bool warnedOnce=FALSE; if (!warnedOnce) { - warn_uncond("Environment variable SOURCE_DATE_EPOCH must have a value smaller than or equal to %llu; actual value %llu\n",UINT_MAX,epoch); + warn_uncond("Environment variable SOURCE_DATE_EPOCH must have a value smaller than or equal to %d; actual value %" PRIu64 "\n",UINT_MAX, (uint64_t)epoch); warnedOnce=TRUE; } } @@ -2643,24 +2604,24 @@ QCString yearToString() } //---------------------------------------------------------------------- -// recursive function that returns the number of branches in the +// recursive function that returns the number of branches in the // inheritance tree that the base class 'bcd' is below the class 'cd' int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level) { - if (bcd->categoryOf()) // use class that is being extended in case of + if (bcd->categoryOf()) // use class that is being extended in case of // an Objective-C category { bcd=bcd->categoryOf(); } - if (cd==bcd) return level; + if (cd==bcd) return level; if (level==256) { warn_uncond("class %s seem to have a recursive " "inheritance relation!\n",cd->name().data()); return -1; } - int m=maxInheritanceDepth; + int m=maxInheritanceDepth; if (cd->baseClasses()) { BaseClassListIterator bcli(*cd->baseClasses()); @@ -2677,12 +2638,12 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level) Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd,Protection prot,int level) { - if (bcd->categoryOf()) // use class that is being extended in case of + if (bcd->categoryOf()) // use class that is being extended in case of // an Objective-C category { bcd=bcd->categoryOf(); } - if (cd==bcd) + if (cd==bcd) { goto exit; } @@ -2707,165 +2668,6 @@ exit: return prot; } -#ifndef NEWMATCH -// strip any template specifiers that follow className in string s -static QCString trimTemplateSpecifiers( - const QCString &namespaceName, - const QCString &className, - const QCString &s - ) -{ - //printf("trimTemplateSpecifiers(%s,%s,%s)\n",namespaceName.data(),className.data(),s.data()); - QCString scopeName=mergeScopes(namespaceName,className); - ClassDef *cd=getClass(scopeName); - if (cd==0) return s; // should not happen, but guard anyway. - - QCString result=s; - - int i=className.length()-1; - if (i>=0 && className.at(i)=='>') // template specialization - { - // replace unspecialized occurrences in s, with their specialized versions. - int count=1; - int cl=i+1; - while (i>=0) - { - char c=className.at(i); - if (c=='>') count++,i--; - else if (c=='<') { count--; if (count==0) break; } - else i--; - } - QCString unspecClassName=className.left(i); - int l=i; - int p=0; - while ((i=result.find(unspecClassName,p))!=-1) - { - if (result.at(i+l)!='<') // unspecialized version - { - result=result.left(i)+className+result.right(result.length()-i-l); - l=cl; - } - p=i+l; - } - } - - //printf("result after specialization: %s\n",result.data()); - - QCString qualName=cd->qualifiedNameWithTemplateParameters(); - //printf("QualifiedName = %s\n",qualName.data()); - // We strip the template arguments following className (if any) - if (!qualName.isEmpty()) // there is a class name - { - int is,ps=0; - int p=0,l,i; - - while ((is=getScopeFragment(qualName,ps,&l))!=-1) - { - QCString qualNamePart = qualName.right(qualName.length()-is); - //printf("qualNamePart=%s\n",qualNamePart.data()); - while ((i=result.find(qualNamePart,p))!=-1) - { - int ql=qualNamePart.length(); - result=result.left(i)+cd->name()+result.right(result.length()-i-ql); - p=i+cd->name().length(); - } - ps=is+l; - } - } - //printf("result=%s\n",result.data()); - - return result.stripWhiteSpace(); -} - -/*! - * @param pattern pattern to look for - * @param s string to search in - * @param p position to start - * @param len resulting pattern length - * @returns position on which string is found, or -1 if not found - */ -static int findScopePattern(const QCString &pattern,const QCString &s, - int p,int *len) -{ - int sl=s.length(); - int pl=pattern.length(); - int sp=0; - *len=0; - while (p<sl) - { - sp=p; // start of match - int pp=0; // pattern position - while (p<sl && pp<pl) - { - if (s.at(p)=='<') // skip template arguments while matching - { - int bc=1; - //printf("skipping pos=%d c=%c\n",p,s.at(p)); - p++; - while (p<sl) - { - if (s.at(p)=='<') bc++; - else if (s.at(p)=='>') - { - bc--; - if (bc==0) - { - p++; - break; - } - } - //printf("skipping pos=%d c=%c\n",p,s.at(p)); - p++; - } - } - else if (s.at(p)==pattern.at(pp)) - { - //printf("match at position p=%d pp=%d c=%c\n",p,pp,s.at(p)); - p++; - pp++; - } - else // no match - { - //printf("restarting at %d c=%c pat=%s\n",p,s.at(p),pattern.data()); - p=sp+1; - break; - } - } - if (pp==pl) // whole pattern matches - { - *len=p-sp; - return sp; - } - } - return -1; -} - -static QCString trimScope(const QCString &name,const QCString &s) -{ - int scopeOffset=name.length(); - QCString result=s; - do // for each scope - { - QCString tmp; - QCString scope=name.left(scopeOffset)+"::"; - //printf("Trying with scope='%s'\n",scope.data()); - - int i,p=0,l; - while ((i=findScopePattern(scope,result,p,&l))!=-1) // for each occurrence - { - tmp+=result.mid(p,i-p); // add part before pattern - p=i+l; - } - tmp+=result.right(result.length()-p); // add trailing part - - scopeOffset=name.findRev("::",scopeOffset-1); - result = tmp; - } while (scopeOffset>0); - //printf("trimScope(name=%s,scope=%s)=%s\n",name.data(),s.data(),result.data()); - return result; -} -#endif - void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) { //printf("trimBaseClassScope level=%d '%s'\n",level,s.data()); @@ -2884,7 +2686,7 @@ void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) } //printf("base class '%s'\n",cd->name().data()); if (cd->baseClasses()) - trimBaseClassScope(cd->baseClasses(),s,level+1); + trimBaseClassScope(cd->baseClasses(),s,level+1); } } @@ -2982,7 +2784,7 @@ static void stripIrrelevantString(QCString &target,const QCString &str) if (i1==-1 && i2==-1) { // strip str from target at index i - target=target.left(i)+target.right(target.length()-i-l); + target=target.left(i)+target.right(target.length()-i-l); changed=TRUE; i-=l; } @@ -3011,8 +2813,8 @@ static void stripIrrelevantString(QCString &target,const QCString &str) \code const T param -> T param // not relevant - const T& param -> const T& param // const needed - T* const param -> T* param // not relevant + const T& param -> const T& param // const needed + T* const param -> T* param // not relevant const T* param -> const T* param // const needed \endcode */ @@ -3032,276 +2834,6 @@ void stripIrrelevantConstVolatile(QCString &s) //#define MATCH printf("Match at line %d\n",__LINE__); //#define NOMATCH printf("Nomatch at line %d\n",__LINE__); -#ifndef NEWMATCH -static bool matchArgument(const Argument *srcA,const Argument *dstA, - const QCString &className, - const QCString &namespaceName, - NamespaceSDict *usingNamespaces, - SDict<Definition> *usingClasses) -{ - //printf("match argument start '%s|%s' <-> '%s|%s' using nsp=%p class=%p\n", - // srcA->type.data(),srcA->name.data(), - // dstA->type.data(),dstA->name.data(), - // usingNamespaces, - // usingClasses); - - // TODO: resolve any typedefs names that are part of srcA->type - // before matching. This should use className and namespaceName - // and usingNamespaces and usingClass to determine which typedefs - // are in-scope, so it will not be very efficient :-( - - QCString srcAType=trimTemplateSpecifiers(namespaceName,className,srcA->type); - QCString dstAType=trimTemplateSpecifiers(namespaceName,className,dstA->type); - QCString srcAName=srcA->name.stripWhiteSpace(); - QCString dstAName=dstA->name.stripWhiteSpace(); - srcAType.stripPrefix("class "); - dstAType.stripPrefix("class "); - - // allow distinguishing "const A" from "const B" even though - // from a syntactic point of view they would be two names of the same - // type "const". This is not fool prove of course, but should at least - // catch the most common cases. - if ((srcAType=="const" || srcAType=="volatile") && !srcAName.isEmpty()) - { - srcAType+=" "; - srcAType+=srcAName; - } - if ((dstAType=="const" || dstAType=="volatile") && !dstAName.isEmpty()) - { - dstAType+=" "; - dstAType+=dstAName; - } - if (srcAName=="const" || srcAName=="volatile") - { - srcAType+=srcAName; - srcAName.resize(0); - } - else if (dstA->name=="const" || dstA->name=="volatile") - { - dstAType+=dstA->name; - dstAName.resize(0); - } - - stripIrrelevantConstVolatile(srcAType); - stripIrrelevantConstVolatile(dstAType); - - // strip typename keyword - if (qstrncmp(srcAType,"typename ",9)==0) - { - srcAType = srcAType.right(srcAType.length()-9); - } - if (qstrncmp(dstAType,"typename ",9)==0) - { - dstAType = dstAType.right(dstAType.length()-9); - } - - srcAType = removeRedundantWhiteSpace(srcAType); - dstAType = removeRedundantWhiteSpace(dstAType); - - //srcAType=stripTemplateSpecifiersFromScope(srcAType,FALSE); - //dstAType=stripTemplateSpecifiersFromScope(dstAType,FALSE); - - //printf("srcA='%s|%s' dstA='%s|%s'\n",srcAType.data(),srcAName.data(), - // dstAType.data(),dstAName.data()); - - if (srcA->array!=dstA->array) // nomatch for char[] against char - { - NOMATCH - return FALSE; - } - if (srcAType!=dstAType) // check if the argument only differs on name - { - - // remove a namespace scope that is only in one type - // (assuming a using statement was used) - //printf("Trimming %s<->%s: %s\n",srcAType.data(),dstAType.data(),namespaceName.data()); - //trimNamespaceScope(srcAType,dstAType,namespaceName); - //printf("After Trimming %s<->%s\n",srcAType.data(),dstAType.data()); - - //QCString srcScope; - //QCString dstScope; - - // strip redundant scope specifiers - if (!className.isEmpty()) - { - srcAType=trimScope(className,srcAType); - dstAType=trimScope(className,dstAType); - //printf("trimScope: '%s' <=> '%s'\n",srcAType.data(),dstAType.data()); - ClassDef *cd; - if (!namespaceName.isEmpty()) - cd=getClass(namespaceName+"::"+className); - else - cd=getClass(className); - if (cd && cd->baseClasses()) - { - trimBaseClassScope(cd->baseClasses(),srcAType); - trimBaseClassScope(cd->baseClasses(),dstAType); - } - //printf("trimBaseClassScope: '%s' <=> '%s'\n",srcAType.data(),dstAType.data()); - } - if (!namespaceName.isEmpty()) - { - srcAType=trimScope(namespaceName,srcAType); - dstAType=trimScope(namespaceName,dstAType); - } - //printf("#usingNamespace=%d\n",usingNamespaces->count()); - if (usingNamespaces && usingNamespaces->count()>0) - { - NamespaceSDict::Iterator nli(*usingNamespaces); - NamespaceDef *nd; - for (;(nd=nli.current());++nli) - { - srcAType=trimScope(nd->name(),srcAType); - dstAType=trimScope(nd->name(),dstAType); - } - } - //printf("#usingClasses=%d\n",usingClasses->count()); - if (usingClasses && usingClasses->count()>0) - { - SDict<Definition>::Iterator cli(*usingClasses); - Definition *cd; - for (;(cd=cli.current());++cli) - { - srcAType=trimScope(cd->name(),srcAType); - dstAType=trimScope(cd->name(),dstAType); - } - } - - //printf("2. srcA=%s|%s dstA=%s|%s\n",srcAType.data(),srcAName.data(), - // dstAType.data(),dstAName.data()); - - if (!srcAName.isEmpty() && !dstA->type.isEmpty() && - (srcAType+" "+srcAName)==dstAType) - { - MATCH - return TRUE; - } - else if (!dstAName.isEmpty() && !srcA->type.isEmpty() && - (dstAType+" "+dstAName)==srcAType) - { - MATCH - return TRUE; - } - - - uint srcPos=0,dstPos=0; - bool equal=TRUE; - while (srcPos<srcAType.length() && dstPos<dstAType.length() && equal) - { - equal=srcAType.at(srcPos)==dstAType.at(dstPos); - if (equal) srcPos++,dstPos++; - } - uint srcATypeLen=srcAType.length(); - uint dstATypeLen=dstAType.length(); - if (srcPos<srcATypeLen && dstPos<dstATypeLen) - { - // if nothing matches or the match ends in the middle or at the - // end of a string then there is no match - if (srcPos==0 || dstPos==0) - { - NOMATCH - return FALSE; - } - if (isId(srcAType.at(srcPos)) && isId(dstAType.at(dstPos))) - { - //printf("partial match srcPos=%d dstPos=%d!\n",srcPos,dstPos); - // check if a name if already found -> if no then there is no match - if (!srcAName.isEmpty() || !dstAName.isEmpty()) - { - NOMATCH - return FALSE; - } - // types only - while (srcPos<srcATypeLen && isId(srcAType.at(srcPos))) srcPos++; - while (dstPos<dstATypeLen && isId(dstAType.at(dstPos))) dstPos++; - if (srcPos<srcATypeLen || - dstPos<dstATypeLen || - (srcPos==srcATypeLen && dstPos==dstATypeLen) - ) - { - NOMATCH - return FALSE; - } - } - else - { - // otherwise we assume that a name starts at the current position. - while (srcPos<srcATypeLen && isId(srcAType.at(srcPos))) srcPos++; - while (dstPos<dstATypeLen && isId(dstAType.at(dstPos))) dstPos++; - - // if nothing more follows for both types then we assume we have - // found a match. Note that now 'signed int' and 'signed' match, but - // seeing that int is not a name can only be done by looking at the - // semantics. - - if (srcPos!=srcATypeLen || dstPos!=dstATypeLen) - { - NOMATCH - return FALSE; - } - } - } - else if (dstPos<dstAType.length()) - { - if (!isspace((uchar)dstAType.at(dstPos))) // maybe the names differ - { - if (!dstAName.isEmpty()) // dst has its name separated from its type - { - NOMATCH - return FALSE; - } - while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; - if (dstPos!=dstAType.length()) - { - NOMATCH - return FALSE; // more than a difference in name -> no match - } - } - else // maybe dst has a name while src has not - { - dstPos++; - while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; - if (dstPos!=dstAType.length() || !srcAName.isEmpty()) - { - NOMATCH - return FALSE; // nope not a name -> no match - } - } - } - else if (srcPos<srcAType.length()) - { - if (!isspace((uchar)srcAType.at(srcPos))) // maybe the names differ - { - if (!srcAName.isEmpty()) // src has its name separated from its type - { - NOMATCH - return FALSE; - } - while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; - if (srcPos!=srcAType.length()) - { - NOMATCH - return FALSE; // more than a difference in name -> no match - } - } - else // maybe src has a name while dst has not - { - srcPos++; - while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; - if (srcPos!=srcAType.length() || !dstAName.isEmpty()) - { - NOMATCH - return FALSE; // nope not a name -> no match - } - } - } - } - MATCH - return TRUE; -} - -#endif - static QCString stripDeclKeywords(const QCString &s) { int i=s.find(" class "); @@ -3320,11 +2852,11 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr QCString getCanonicalTemplateSpec(const Definition *d,const FileDef *fs,const QCString& spec) { - + QCString templSpec = spec.stripWhiteSpace(); // this part had been commented out before... but it is needed to match for instance // std::list<std::string> against list<string> so it is now back again! - if (!templSpec.isEmpty() && templSpec.at(0) == '<') + if (!templSpec.isEmpty() && templSpec.at(0) == '<') { templSpec = "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1).stripWhiteSpace()); } @@ -3346,7 +2878,7 @@ static QCString getCanonicalTypeForIdentifier( QCString symName,result,templSpec,tmpName; //DefinitionList *defList=0; - if (tSpec && !tSpec->isEmpty()) + if (tSpec && !tSpec->isEmpty()) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec)); if (word.findRev("::")!=-1 && !(tmpName=stripScope(word)).isEmpty()) @@ -3508,7 +3040,7 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr QCString ct = getCanonicalTypeForIdentifier(d,fs,word,&templSpec); // in case the ct is empty it means that "word" represents scope "d" - // and this does not need to be added to the canonical + // and this does not need to be added to the canonical // type (it is redundant), so/ we skip it. This solves problem 589616. if (ct.isEmpty() && type.mid(p,2)=="::") { @@ -3522,7 +3054,7 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr // word.data(),templSpec.data(),canType.data(),ct.data()); if (!templSpec.isEmpty()) // if we didn't use up the templSpec already // (i.e. type is not a template specialization) - // then resolve any identifiers inside. + // then resolve any identifiers inside. { static QRegExp re("[a-z_A-Z\\x80-\\xFF][a-z_A-Z0-9\\x80-\\xFF]*"); int tp=0,tl,ti; @@ -3550,11 +3082,11 @@ static QCString extractCanonicalArgType(const Definition *d,const FileDef *fs,co QCString type = arg.type.stripWhiteSpace(); QCString name = arg.name; //printf("----- extractCanonicalArgType(type=%s,name=%s)\n",type.data(),name.data()); - if ((type=="const" || type=="volatile") && !name.isEmpty()) + if ((type=="const" || type=="volatile") && !name.isEmpty()) { // name is part of type => correct type+=" "; type+=name; - } + } if (name=="const" || name=="volatile") { // name is part of type => correct if (!type.isEmpty()) type+=" "; @@ -3630,34 +3162,46 @@ static bool matchArgument2( // new algorithm for argument matching -bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList &inSrcAl, - const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList &inDstAl, +bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList *srcAl, + const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList *dstAl, bool checkCV) { ASSERT(srcScope!=0 && dstScope!=0); - ArgumentList srcAl = inSrcAl; - ArgumentList dstAl = inDstAl; + if (srcAl==0 || dstAl==0) + { + bool match = srcAl==dstAl; + if (match) + { + MATCH + return TRUE; + } + else + { + NOMATCH + return FALSE; + } + } // handle special case with void argument - if ( srcAl.empty() && dstAl.size()==1 && dstAl.front().type=="void" ) + if ( srcAl->empty() && dstAl->size()==1 && dstAl->front().type=="void" ) { // special case for finding match between func() and func(void) Argument a; a.type = "void"; - srcAl.push_back(a); + const_cast<ArgumentList*>(srcAl)->push_back(a); MATCH return TRUE; } - if ( dstAl.empty() && srcAl.size()==1 && srcAl.front().type=="void" ) + if ( dstAl->empty() && srcAl->size()==1 && srcAl->front().type=="void" ) { // special case for finding match between func(void) and func() Argument a; a.type = "void"; - dstAl.push_back(a); + const_cast<ArgumentList*>(dstAl)->push_back(a); MATCH return TRUE; } - if (srcAl.size() != dstAl.size()) + if (srcAl->size() != dstAl->size()) { NOMATCH return FALSE; // different number of arguments -> no match @@ -3665,19 +3209,19 @@ bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,cons if (checkCV) { - if (srcAl.constSpecifier != dstAl.constSpecifier) + if (srcAl->constSpecifier() != dstAl->constSpecifier()) { NOMATCH return FALSE; // one member is const, the other not -> no match } - if (srcAl.volatileSpecifier != dstAl.volatileSpecifier) + if (srcAl->volatileSpecifier() != dstAl->volatileSpecifier()) { NOMATCH return FALSE; // one member is volatile, the other not -> no match } } - if (srcAl.refQualifier != dstAl.refQualifier) + if (srcAl->refQualifier() != dstAl->refQualifier()) { NOMATCH return FALSE; // one member is has a different ref-qualifier than the other @@ -3685,12 +3229,12 @@ bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,cons // so far the argument list could match, so we need to compare the types of // all arguments. - auto srcIt = srcAl.begin(); - auto dstIt = dstAl.begin(); - for (;srcIt!=srcAl.end() && dstIt!=dstAl.end();++srcIt,++dstIt) + auto srcIt = srcAl->begin(); + auto dstIt = dstAl->begin(); + for (;srcIt!=srcAl->end() && dstIt!=dstAl->end();++srcIt,++dstIt) { - Argument &srcA = *srcIt; - Argument &dstA = *dstIt; + Argument &srcA = const_cast<Argument&>(*srcIt); + Argument &dstA = const_cast<Argument&>(*dstIt); if (!matchArgument2(srcScope,srcFileScope,srcA, dstScope,dstFileScope,dstA) ) @@ -3700,7 +3244,7 @@ bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,cons } } MATCH - return TRUE; // all arguments match + return TRUE; // all arguments match } @@ -3843,7 +3387,7 @@ void mergeArguments(ArgumentList &srcAl,ArgumentList &dstAl,bool forceNameOverwr } } -static void findMembersWithSpecificName(MemberName *mn, +static void findMembersWithSpecificName(const MemberName *mn, const char *args, bool checkStatics, const FileDef *currentFile, @@ -3853,34 +3397,31 @@ static void findMembersWithSpecificName(MemberName *mn, { //printf(" Function with global scope name '%s' args='%s'\n", // mn->memberName(),args); - MemberNameIterator mli(*mn); - const MemberDef *md = 0; - for (mli.toFirst();(md=mli.current());++mli) + for (const auto &md_p : *mn) { + const MemberDef *md = md_p.get(); const FileDef *fd=md->getFileDef(); const GroupDef *gd=md->getGroupDef(); //printf(" md->name()='%s' md->args='%s' fd=%p gd=%p current=%p ref=%s\n", // md->name().data(),args,fd,gd,currentFile,md->getReference().data()); if ( - ((gd && gd->isLinkable()) || (fd && fd->isLinkable()) || md->isReference()) && + ((gd && gd->isLinkable()) || (fd && fd->isLinkable()) || md->isReference()) && md->getNamespaceDef()==0 && md->isLinkable() && - (!checkStatics || (!md->isStatic() && !md->isDefine()) || + (!checkStatics || (!md->isStatic() && !md->isDefine()) || currentFile==0 || fd==currentFile) // statics must appear in the same file - ) + ) { bool match=TRUE; - ArgumentList *argList=0; if (args && !md->isDefine() && qstrcmp(args,"()")!=0) { const ArgumentList &mdAl = md->argumentList(); - ArgumentList argList; - stringToArgumentList(md->getLanguage(),args,argList); + auto argList_p = stringToArgumentList(md->getLanguage(),args); match=matchArguments2( - md->getOuterScope(),fd,mdAl, - Doxygen::globalScope,fd,argList, + md->getOuterScope(),fd,&mdAl, + Doxygen::globalScope,fd,argList_p.get(), checkCV); } - if (match && (forceTagFile==0 || md->getReference()==forceTagFile)) + if (match && (forceTagFile==0 || md->getReference()==forceTagFile)) { //printf("Found match!\n"); members.append(md); @@ -3894,17 +3435,17 @@ static void findMembersWithSpecificName(MemberName *mn, * memberName may also include a (partial) scope to indicate the scope * in which the member is located. * - * The parameter 'scName' is a string representing the name of the scope in + * The parameter 'scName' is a string representing the name of the scope in * which the link was found. * - * In case of a function args contains a string representation of the - * argument list. Passing 0 means the member has no arguments. + * In case of a function args contains a string representation of the + * argument list. Passing 0 means the member has no arguments. * Passing "()" means any argument list will do, but "()" is preferred. * * The function returns TRUE if the member is known and documented or * FALSE if it is not. - * If TRUE is returned parameter 'md' contains a pointer to the member - * definition. Furthermore exactly one of the parameter 'cd', 'nd', or 'fd' + * If TRUE is returned parameter 'md' contains a pointer to the member + * definition. Furthermore exactly one of the parameter 'cd', 'nd', or 'fd' * will be non-zero: * - if 'cd' is non zero, the member was found in a class pointed to by cd. * - if 'nd' is non zero, the member was found in a namespace pointed to by nd. @@ -3912,12 +3453,12 @@ static void findMembersWithSpecificName(MemberName *mn, * file fd. */ bool getDefs(const QCString &scName, - const QCString &mbName, + const QCString &mbName, const char *args, - const MemberDef *&md, - const ClassDef *&cd, - const FileDef *&fd, - const NamespaceDef *&nd, + const MemberDef *&md, + const ClassDef *&cd, + const FileDef *&fd, + const NamespaceDef *&nd, const GroupDef *&gd, bool forceEmptyScope, const FileDef *currentFile, @@ -3937,12 +3478,12 @@ bool getDefs(const QCString &scName, int is,im=0,pm=0; // strip common part of the scope from the scopeName - while ((is=scopeName.findRev("::"))!=-1 && + while ((is=scopeName.findRev("::"))!=-1 && (im=memberName.find("::",pm))!=-1 && (scopeName.right(scopeName.length()-is-2)==memberName.mid(pm,im-pm)) ) { - scopeName=scopeName.left(is); + scopeName=scopeName.left(is); pm=im+2; } //printf("result after scope corrections scope=%s name=%s\n", @@ -3952,11 +3493,11 @@ bool getDefs(const QCString &scName, QCString mScope; if (memberName.left(9)!="operator " && // treat operator conversion methods // as a special case - (im=memberName.findRev("::"))!=-1 && + (im=memberName.findRev("::"))!=-1 && im<(int)memberName.length()-2 // not A:: ) { - mScope=memberName.left(im); + mScope=memberName.left(im); mName=memberName.right(memberName.length()-im-2); } @@ -3965,7 +3506,7 @@ bool getDefs(const QCString &scName, //printf("mScope='%s' mName='%s'\n",mScope.data(),mName.data()); - MemberName *mn = Doxygen::memberNameSDict->find(mName); + MemberName *mn = Doxygen::memberNameLinkedMap->find(mName); //printf("mName=%s mn=%p\n",mName.data(),mn); if ((!forceEmptyScope || scopeName.isEmpty()) && // this was changed for bug638856, forceEmptyScope => empty scopeName @@ -3995,26 +3536,25 @@ bool getDefs(const QCString &scName, //printf("Trying class scope %s: fcd=%p tmd=%p\n",className.data(),fcd,tmd); // todo: fill in correct fileScope! if (fcd && // is it a documented class - fcd->isLinkable() + fcd->isLinkable() ) { //printf(" Found fcd=%p\n",fcd); - MemberNameIterator mmli(*mn); - MemberDef *mmd; - int mdist=maxInheritanceDepth; - ArgumentList argList; + int mdist=maxInheritanceDepth; + std::unique_ptr<ArgumentList> argList; if (args) { - stringToArgumentList(fcd->getLanguage(),args,argList); + argList = stringToArgumentList(fcd->getLanguage(),args); } - for (mmli.toFirst();(mmd=mmli.current());++mmli) + for (const auto &mmd_p : *mn) { + MemberDef *mmd = mmd_p.get(); if (!mmd->isStrongEnumValue()) { const ArgumentList &mmdAl = mmd->argumentList(); bool match=args==0 || - matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),mmdAl, - fcd, fcd->getFileDef(),argList, + matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),&mmdAl, + fcd, fcd->getFileDef(),argList.get(), checkCV); //printf("match=%d\n",match); if (match) @@ -4037,8 +3577,9 @@ bool getDefs(const QCString &scName, // no exact match found, but if args="()" an arbitrary member will do { //printf(" >Searching for arbitrary member\n"); - for (mmli.toFirst();(mmd=mmli.current());++mmli) + for (const auto &mmd_p : *mn) { + MemberDef *mmd = mmd_p.get(); //if (mmd->isLinkable()) //{ ClassDef *mcd=mmd->getClassDef(); @@ -4058,9 +3599,9 @@ bool getDefs(const QCString &scName, } } //printf(" >Success=%d\n",mdist<maxInheritanceDepth); - if (mdist<maxInheritanceDepth) + if (mdist<maxInheritanceDepth) { - if (!md->isLinkable() || md->isStrongEnumValue()) + if (!md->isLinkable() || md->isStrongEnumValue()) { md=0; // avoid returning things we cannot link to cd=0; @@ -4073,7 +3614,7 @@ bool getDefs(const QCString &scName, return TRUE; /* found match */ } } - } + } if (tmd && tmd->isEnumerate() && tmd->isStrong()) // scoped enum { //printf("Found scoped enum!\n"); @@ -4117,18 +3658,18 @@ bool getDefs(const QCString &scName, if (mn && scopeName.isEmpty() && mScope.isEmpty()) // Maybe a related function? { //printf("Global symbol\n"); - MemberNameIterator mmli(*mn); - MemberDef *mmd, *fuzzy_mmd = 0; - ArgumentList argList; + const MemberDef *fuzzy_mmd = 0; + std::unique_ptr<ArgumentList> argList; bool hasEmptyArgs = args && qstrcmp(args, "()") == 0; if (args) { - stringToArgumentList(SrcLangExt_Cpp, args, argList); + argList = stringToArgumentList(SrcLangExt_Cpp, args); } - for (mmli.toFirst(); (mmd = mmli.current()); ++mmli) + for (const auto &mmd_p : *mn) { + const MemberDef *mmd = mmd_p.get(); if (!mmd->isLinkable() || (!mmd->isRelated() && !mmd->isForeign()) || !mmd->getClassDef()) { @@ -4137,16 +3678,18 @@ bool getDefs(const QCString &scName, if (!args) { + fuzzy_mmd = mmd; break; } - ArgumentList &mmdAl = mmd->argumentList(); - if (matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),mmdAl, - Doxygen::globalScope,mmd->getFileDef(),argList, + const ArgumentList &mmdAl = mmd->argumentList(); + if (matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),&mmdAl, + Doxygen::globalScope,mmd->getFileDef(),argList.get(), checkCV ) ) { + fuzzy_mmd = mmd; break; } @@ -4156,12 +3699,10 @@ bool getDefs(const QCString &scName, } } - mmd = mmd ? mmd : fuzzy_mmd; - - if (mmd && !mmd->isStrongEnumValue()) + if (fuzzy_mmd && !fuzzy_mmd->isStrongEnumValue()) { - md = mmd; - cd = mmd->getClassDef(); + md = fuzzy_mmd; + cd = fuzzy_mmd->getClassDef(); return TRUE; } } @@ -4170,7 +3711,7 @@ bool getDefs(const QCString &scName, // maybe an namespace, file or group member ? //printf("Testing for global symbol scopeName='%s' mScope='%s' :: mName='%s'\n", // scopeName.data(),mScope.data(),mName.data()); - if ((mn=Doxygen::functionNameSDict->find(mName))) // name is known + if ((mn=Doxygen::functionNameLinkedMap->find(mName))) // name is known { //printf(" >symbol name found\n"); NamespaceDef *fnd=0; @@ -4187,7 +3728,7 @@ bool getDefs(const QCString &scName, namespaceName=mScope.copy(); } //printf("Trying namespace %s\n",namespaceName.data()); - if (!namespaceName.isEmpty() && + if (!namespaceName.isEmpty() && (fnd=Doxygen::namespaceSDict->find(namespaceName)) && fnd->isLinkable() ) @@ -4195,23 +3736,23 @@ bool getDefs(const QCString &scName, //printf("Symbol inside existing namespace '%s' count=%d\n", // namespaceName.data(),mn->count()); bool found=FALSE; - MemberNameIterator mmli(*mn); - const MemberDef *mmd; - for (mmli.toFirst();((mmd=mmli.current()) && !found);++mmli) + for (const auto &mmd_p : *mn) { + const MemberDef *mmd = mmd_p.get(); //printf("mmd->getNamespaceDef()=%p fnd=%p\n", // mmd->getNamespaceDef(),fnd); const MemberDef *emd = mmd->getEnumScope(); if (emd && emd->isStrong()) { //printf("yes match %s<->%s!\n",mScope.data(),emd->localName().data()); - if (emd->getNamespaceDef()==fnd && + if (emd->getNamespaceDef()==fnd && rightScopeMatch(mScope,emd->localName())) { //printf("found it!\n"); nd=fnd; md=mmd; found=TRUE; + break; } else { @@ -4223,14 +3764,13 @@ bool getDefs(const QCString &scName, else if (mmd->getOuterScope()==fnd /* && mmd->isLinkable() */ ) { // namespace is found bool match=TRUE; - ArgumentList argList; if (args && qstrcmp(args,"()")!=0) { const ArgumentList &mmdAl = mmd->argumentList(); - stringToArgumentList(mmd->getLanguage(),args,argList); + auto argList_p = stringToArgumentList(mmd->getLanguage(),args); match=matchArguments2( - mmd->getOuterScope(),mmd->getFileDef(),mmdAl, - fnd,mmd->getFileDef(),argList, + mmd->getOuterScope(),mmd->getFileDef(),&mmdAl, + fnd,mmd->getFileDef(),argList_p.get(), checkCV); } if (match) @@ -4238,26 +3778,29 @@ bool getDefs(const QCString &scName, nd=fnd; md=mmd; found=TRUE; + break; } } } - if (!found && args && !qstrcmp(args,"()")) - // no exact match found, but if args="()" an arbitrary + if (!found && args && !qstrcmp(args,"()")) + // no exact match found, but if args="()" an arbitrary // member will do { - for (mmli.toFirst();((mmd=mmli.current()) && !found);++mmli) + for (const auto &mmd_p : *mn) { + const MemberDef *mmd = mmd_p.get(); if (mmd->getNamespaceDef()==fnd /*&& mmd->isLinkable() */ ) { nd=fnd; md=mmd; found=TRUE; + break; } } } if (found) { - if (!md->isLinkable()) + if (!md->isLinkable()) { md=0; // avoid returning things we cannot link to nd=0; @@ -4274,10 +3817,9 @@ bool getDefs(const QCString &scName, else { //printf("not a namespace\n"); - MemberNameIterator mmli(*mn); - MemberDef *mmd; - for (mmli.toFirst();(mmd=mmli.current());++mmli) + for (const auto &mmd_p : *mn) { + const MemberDef *mmd = mmd_p.get(); const MemberDef *tmd = mmd->getEnumScope(); //printf("try member %s tmd=%s\n",mmd->name().data(),tmd?tmd->name().data():"<none>"); int ni=namespaceName.findRev("::"); @@ -4325,20 +3867,23 @@ bool getDefs(const QCString &scName, { // no exact match found, but if args="()" an arbitrary // member will do - MemberNameIterator mni(*mn); - for (mni.toLast();(md=mni.current());--mni) + //MemberNameIterator mni(*mn); + //for (mni.toLast();(md=mni.current());--mni) + for (auto it = mn->rbegin(); it!=mn->rend(); ++it) { - //printf("Found member '%s'\n",md->name().data()); - //printf("member is linkable md->name()='%s'\n",md->name().data()); - fd=md->getFileDef(); - gd=md->getGroupDef(); - const MemberDef *tmd = md->getEnumScope(); + const auto &mmd_p = *it; + const MemberDef *mmd = mmd_p.get(); + //printf("Found member '%s'\n",mmd->name().data()); + //printf("member is linkable mmd->name()='%s'\n",mmd->name().data()); + fd=mmd->getFileDef(); + gd=mmd->getGroupDef(); + const MemberDef *tmd = mmd->getEnumScope(); if ( (gd && gd->isLinkable()) || (fd && fd->isLinkable()) || (tmd && tmd->isStrong()) ) { - members.append(md); + members.append(mmd); } } } @@ -4351,7 +3896,7 @@ bool getDefs(const QCString &scName, QListIterator<MemberDef> mit(members); for (mit.toFirst();(md=mit.current());++mit) { - if (md->getFileDef() && md->getFileDef()->name() == currentFile->name()) + if (md->getFileDef() && md->getFileDef()->name() == currentFile->name()) { break; // found match in the current file } @@ -4366,7 +3911,7 @@ bool getDefs(const QCString &scName, md=members.getLast(); } } - if (md && (md->getEnumScope()==0 || !md->getEnumScope()->isStrong())) + if (md && (md->getEnumScope()==0 || !md->getEnumScope()->isStrong())) // found a matching global member, that is not a scoped enum value (or uniquely matches) { fd=md->getFileDef(); @@ -4384,14 +3929,14 @@ bool getDefs(const QCString &scName, /*! * Searches for a scope definition given its name as a string via parameter - * `scope`. + * `scope`. * - * The parameter `docScope` is a string representing the name of the scope in + * The parameter `docScope` is a string representing the name of the scope in * which the `scope` string was found. * * The function returns TRUE if the scope is known and documented or * FALSE if it is not. - * If TRUE is returned exactly one of the parameter `cd`, `nd` + * If TRUE is returned exactly one of the parameter `cd`, `nd` * will be non-zero: * - if `cd` is non zero, the scope was a class pointed to by cd. * - if `nd` is non zero, the scope was a namespace pointed to by nd. @@ -4408,7 +3953,7 @@ static bool getScopeDefs(const char *docScope,const char *scope, bool explicitGlobalScope=FALSE; if (scopeName.at(0)==':' && scopeName.at(1)==':') { - scopeName=scopeName.right(scopeName.length()-2); + scopeName=scopeName.right(scopeName.length()-2); explicitGlobalScope=TRUE; } if (scopeName.isEmpty()) @@ -4429,11 +3974,11 @@ static bool getScopeDefs(const char *docScope,const char *scope, //(cd=getClass(fullName+"-g")) // C# generic ) && cd->isLinkable()) { - return TRUE; // class link written => quit + return TRUE; // class link written => quit } else if ((nd=Doxygen::namespaceSDict->find(fullName)) && nd->isLinkable()) { - return TRUE; // namespace link written => quit + return TRUE; // namespace link written => quit } if (scopeOffset==0) { @@ -4454,10 +3999,10 @@ static bool isLowerCase(QCString &s) if (p==0) return TRUE; int c; while ((c=*p++)) if (!islower(c)) return FALSE; - return TRUE; + return TRUE; } -/*! Returns an object to reference to given its name and context +/*! Returns an object to reference to given its name and context * @post return value TRUE implies *resContext!=0 or *resMember!=0 */ bool resolveRef(/* in */ const char *scName, @@ -4501,10 +4046,10 @@ bool resolveRef(/* in */ const char *scName, ClassDef *cd=0; NamespaceDef *nd=0; - // the following if() was commented out for releases in the range + // the following if() was commented out for releases in the range // 1.5.2 to 1.6.1, but has been restored as a result of bug report 594787. if (!inSeeBlock && scopePos==-1 && isLowerCase(tsName)) - { // link to lower case only name => do not try to autolink + { // link to lower case only name => do not try to autolink return FALSE; } @@ -4524,7 +4069,7 @@ bool resolveRef(/* in */ const char *scName, } return TRUE; } - else if (scName==fullName || (!inSeeBlock && scopePos==-1)) + else if (scName==fullName || (!inSeeBlock && scopePos==-1)) // nothing to link => output plain text { //printf("found scName=%s fullName=%s scName==fullName=%d " @@ -4544,7 +4089,7 @@ bool resolveRef(/* in */ const char *scName, if (bracePos!=-1) argsStr=fullName.right(fullName.length()-bracePos); // strip template specifier - // TODO: match against the correct partial template instantiation + // TODO: match against the correct partial template instantiation int templPos=nameStr.find('<'); bool tryUnspecializedVersion = FALSE; if (templPos!=-1 && nameStr.find("operator")==-1) @@ -4584,11 +4129,11 @@ bool resolveRef(/* in */ const char *scName, ) { //printf("after getDefs checkScope=%d nameStr=%s cd=%p nd=%p\n",checkScope,nameStr.data(),cd,nd); - if (checkScope && md && md->getOuterScope()==Doxygen::globalScope && + if (checkScope && md && md->getOuterScope()==Doxygen::globalScope && !md->isStrongEnumValue() && (!scopeStr.isEmpty() || nameStr.find("::")>0)) { - // we did find a member, but it is a global one while we were explicitly + // we did find a member, but it is a global one while we were explicitly // looking for a scoped variable. See bug 616387 for an example why this check is needed. // note we do need to support autolinking to "::symbol" hence the >0 //printf("not global member!\n"); @@ -4615,7 +4160,7 @@ bool resolveRef(/* in */ const char *scName, else if (tsName.find('.')!=-1) // maybe a link to a file { bool ambig; - fd=findFileDef(Doxygen::inputNameDict,tsName,ambig); + fd=findFileDef(Doxygen::inputNameLinkedMap,tsName,ambig); if (fd && !ambig) { *resContext=fd; @@ -4667,20 +4212,20 @@ QCString linkToText(SrcLangExt lang,const char *link,bool isFileName) #if 0 /* * generate a reference to a class, namespace or member. - * 'scName' is the name of the scope that contains the documentation + * 'scName' is the name of the scope that contains the documentation * string that is returned. * 'name' is the name that we want to link to. * 'name' may have the following formats: * 1) "ScopeName" - * 2) "memberName()" one of the (overloaded) function or define + * 2) "memberName()" one of the (overloaded) function or define * with name memberName. - * 3) "memberName(...)" a specific (overloaded) function or define + * 3) "memberName(...)" a specific (overloaded) function or define * with name memberName * 4) "::name a global variable or define * 4) "\#memberName member variable, global variable or define - * 5) ("ScopeName::")+"memberName()" - * 6) ("ScopeName::")+"memberName(...)" - * 7) ("ScopeName::")+"memberName" + * 5) ("ScopeName::")+"memberName()" + * 6) ("ScopeName::")+"memberName(...)" + * 7) ("ScopeName::")+"memberName" * instead of :: the \# symbol may also be used. */ @@ -4752,7 +4297,7 @@ bool resolveLink(/* in */ const char *scName, const ClassDef *cd; const DirDef *dir; const NamespaceDef *nd; - SectionInfo *si=0; + const SectionInfo *si=0; bool ambig; if (linkRef.isEmpty()) // no reference name! { @@ -4760,12 +4305,12 @@ bool resolveLink(/* in */ const char *scName, } else if ((pd=Doxygen::pageSDict->find(linkRef))) // link to a page { - const GroupDef *gd = pd->getGroupDef(); + gd = pd->getGroupDef(); if (gd) { - if (!pd->name().isEmpty()) si=Doxygen::sectionDict->find(pd->name()); + if (!pd->name().isEmpty()) si=SectionManager::instance().find(pd->name()); *resContext=gd; - if (si) resAnchor = si->label; + if (si) resAnchor = si->label(); } else { @@ -4773,10 +4318,10 @@ bool resolveLink(/* in */ const char *scName, } return TRUE; } - else if ((si=Doxygen::sectionDict->find(linkRef))) + else if ((si=SectionManager::instance().find(linkRef))) { - *resContext=si->definition; - resAnchor = si->label; + *resContext=si->definition(); + resAnchor = si->label(); return TRUE; } else if ((pd=Doxygen::exampleSDict->find(linkRef))) // link to an example @@ -4789,7 +4334,7 @@ bool resolveLink(/* in */ const char *scName, *resContext=gd; return TRUE; } - else if ((fd=findFileDef(Doxygen::inputNameDict,linkRef,ambig)) // file link + else if ((fd=findFileDef(Doxygen::inputNameLinkedMap,linkRef,ambig)) // file link && fd->isLinkable()) { *resContext=fd; @@ -4842,7 +4387,7 @@ bool resolveLink(/* in */ const char *scName, //---------------------------------------------------------------------- // General function that generates the HTML code for a reference to some -// file, class or member from text 'lr' within the context of class 'clName'. +// file, class or member from text 'lr' within the context of class 'clName'. // This link has the text 'lt' (if not 0), otherwise 'lr' is used as a // basis for the link's text. // returns TRUE if a link could be generated. @@ -4860,14 +4405,14 @@ bool generateLink(OutputDocInterface &od,const char *clName, if (compound) // link to compound { if (lt==0 && anchor.isEmpty() && /* compound link */ - compound->definitionType()==Definition::TypeGroup /* is group */ + compound->definitionType()==Definition::TypeGroup /* is group */ ) { linkText=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeFile) { - linkText=linkToText(compound->getLanguage(),lt,TRUE); + linkText=linkToText(compound->getLanguage(),lt,TRUE); } od.writeObjectLink(compound->getReference(), compound->getOutputFileBase(),anchor,linkText); @@ -4896,12 +4441,12 @@ void generateFileRef(OutputDocInterface &od,const char *name,const char *text) //FileInfo *fi; FileDef *fd; bool ambig; - if ((fd=findFileDef(Doxygen::inputNameDict,name,ambig)) && - fd->isLinkable()) + if ((fd=findFileDef(Doxygen::inputNameLinkedMap,name,ambig)) && + fd->isLinkable()) // link to documented input file od.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,linkText); else - od.docify(linkText); + od.docify(linkText); } //---------------------------------------------------------------------- @@ -4944,14 +4489,18 @@ struct FindFileCacheElem static QCache<FindFileCacheElem> g_findFileDefCache(5000); -FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig) +static std::mutex g_findFileDefMutex; + +FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) { ambig=FALSE; if (n==0) return 0; + std::unique_lock<std::mutex> lock(g_findFileDefMutex); + const int maxAddrSize = 20; char addr[maxAddrSize]; - qsnprintf(addr,maxAddrSize,"%p:",fnDict); + qsnprintf(addr,maxAddrSize,"%p:",(void*)fnMap); QCString key = addr; key+=n; @@ -4972,49 +4521,46 @@ FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig) QCString name=QDir::cleanDirPath(n).utf8(); QCString path; int slashPos; - FileName *fn; + const FileName *fn; if (name.isEmpty()) goto exit; slashPos=QMAX(name.findRev('/'),name.findRev('\\')); if (slashPos!=-1) { path=name.left(slashPos+1); - name=name.right(name.length()-slashPos-1); + name=name.right(name.length()-slashPos-1); //printf("path=%s name=%s\n",path.data(),name.data()); } if (name.isEmpty()) goto exit; - if ((fn=(*fnDict)[name])) + if ((fn=fnMap->find(name))) { //printf("fn->count()=%d\n",fn->count()); - if (fn->count()==1) + if (fn->size()==1) { - FileDef *fd = fn->getFirst(); -#if defined(_WIN32) || defined(__MACOSX__) || defined(__CYGWIN__) // Windows or MacOSX - bool isSamePath = fd->getPath().right(path.length()).lower()==path.lower(); -#else // Unix - bool isSamePath = fd->getPath().right(path.length())==path; -#endif + const std::unique_ptr<FileDef> &fd = fn->front(); + bool isSamePath = Portable::fileSystemIsCaseSensitive() ? + fd->getPath().right(path.length())==path : + fd->getPath().right(path.length()).lower()==path.lower(); if (path.isEmpty() || isSamePath) { - cachedResult->fileDef = fd; + cachedResult->fileDef = fd.get(); g_findFileDefCache.insert(key,cachedResult); //printf("=1 ===> add to cache %p\n",fd); - return fd; + return fd.get(); } } else // file name alone is ambiguous { int count=0; - FileNameIterator fni(*fn); - FileDef *fd; FileDef *lastMatch=0; QCString pathStripped = stripFromIncludePath(path); - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd_p : *fn) { + FileDef *fd = fd_p.get(); QCString fdStripPath = stripFromIncludePath(fd->getPath()); - if (path.isEmpty() || fdStripPath.right(pathStripped.length())==pathStripped) - { - count++; - lastMatch=fd; + if (path.isEmpty() || fdStripPath.right(pathStripped.length())==pathStripped) + { + count++; + lastMatch=fd; } } //printf(">1 ===> add to cache %p\n",fd); @@ -5039,7 +4585,7 @@ exit: //---------------------------------------------------------------------- -QCString showFileDefMatches(const FileNameDict *fnDict,const char *n) +QCString showFileDefMatches(const FileNameLinkedMap *fnMap,const char *n) { QCString result; QCString name=n; @@ -5048,14 +4594,12 @@ QCString showFileDefMatches(const FileNameDict *fnDict,const char *n) if (slashPos!=-1) { path=name.left(slashPos+1); - name=name.right(name.length()-slashPos-1); + name=name.right(name.length()-slashPos-1); } - FileName *fn; - if ((fn=(*fnDict)[name])) + const FileName *fn; + if ((fn=fnMap->find(name))) { - FileNameIterator fni(*fn); - FileDef *fd; - for (fni.toFirst();(fd=fni.current());++fni) + for (const auto &fd : *fn) { if (path.isEmpty() || fd->getPath().right(path.length())==path) { @@ -5068,118 +4612,6 @@ QCString showFileDefMatches(const FileNameDict *fnDict,const char *n) //---------------------------------------------------------------------- -/// substitute all occurrences of \a src in \a s by \a dst -QCString substitute(const QCString &s,const QCString &src,const QCString &dst) -{ - if (s.isEmpty() || src.isEmpty()) return s; - const char *p, *q; - int srcLen = src.length(); - int dstLen = dst.length(); - int resLen; - if (srcLen!=dstLen) - { - int count; - for (count=0, p=s.data(); (q=strstr(p,src))!=0; p=q+srcLen) count++; - resLen = s.length()+count*(dstLen-srcLen); - } - else // result has same size as s - { - resLen = s.length(); - } - QCString result(resLen+1); - char *r; - for (r=result.rawData(), p=s; (q=strstr(p,src))!=0; p=q+srcLen) - { - int l = (int)(q-p); - memcpy(r,p,l); - r+=l; - - if (dst) memcpy(r,dst,dstLen); - r+=dstLen; - } - qstrcpy(r,p); - //printf("substitute(%s,%s,%s)->%s\n",s,src,dst,result.data()); - return result; -} - - -/// substitute all occurrences of \a src in \a s by \a dst, but skip -/// each consecutive sequence of \a src where the number consecutive -/// \a src matches \a skip_seq; if \a skip_seq is negative, skip any -/// number of consecutive \a src -QCString substitute(const QCString &s,const QCString &src,const QCString &dst,int skip_seq) -{ - if (s.isEmpty() || src.isEmpty()) return s; - const char *p, *q; - int srcLen = src.length(); - int dstLen = dst.length(); - int resLen; - if (srcLen!=dstLen) - { - int count; - for (count=0, p=s.data(); (q=strstr(p,src))!=0; p=q+srcLen) count++; - resLen = s.length()+count*(dstLen-srcLen); - } - else // result has same size as s - { - resLen = s.length(); - } - QCString result(resLen+1); - char *r; - for (r=result.rawData(), p=s; (q=strstr(p,src))!=0; p=q+srcLen) - { - // search a consecutive sequence of src - int seq = 0, skip = 0; - if (skip_seq) - { - for (const char *n=q+srcLen; qstrncmp(n,src,srcLen)==0; seq=1+skip, n+=srcLen) - ++skip; // number of consecutive src after the current one - - // verify the allowed number of consecutive src to skip - if (skip_seq > 0 && skip_seq != seq) - seq = skip = 0; - } - - // skip a consecutive sequence of src when necessary - int l = (int)((q + seq * srcLen)-p); - memcpy(r,p,l); - r+=l; - - if (skip) - { - // skip only the consecutive src found after the current one - q += skip * srcLen; - // the next loop will skip the current src, aka (p=q+srcLen) - continue; - } - - if (dst) memcpy(r,dst,dstLen); - r+=dstLen; - } - qstrcpy(r,p); - result.resize(strlen(result.data())+1); - //printf("substitute(%s,%s,%s)->%s\n",s,src,dst,result.data()); - return result; -} - -/// substitute all occurrences of \a srcChar in \a s by \a dstChar -QCString substitute(const QCString &s,char srcChar,char dstChar) -{ - int l=s.length(); - QCString result(l+1); - char *q=result.rawData(); - if (l>0) - { - const char *p=s.data(); - char c; - while ((c=*p++)) *q++ = (c==srcChar) ? dstChar : c; - } - *q='\0'; - return result; -} - -//---------------------------------------------------------------------- - QCString substituteKeywords(const QCString &s,const char *title, const char *projName,const char *projNum,const char *projBrief) { @@ -5188,7 +4620,7 @@ QCString substituteKeywords(const QCString &s,const char *title, result = substitute(result,"$datetime",dateToString(TRUE)); result = substitute(result,"$date",dateToString(FALSE)); result = substitute(result,"$year",yearToString()); - result = substitute(result,"$doxygenversion",getVersion()); + result = substitute(result,"$doxygenversion",getDoxygenVersion()); result = substitute(result,"$projectname",projName); result = substitute(result,"$projectnumber",projNum); result = substitute(result,"$projectbrief",projBrief); @@ -5201,15 +4633,14 @@ QCString substituteKeywords(const QCString &s,const char *title, /*! Returns the character index within \a name of the first prefix * in Config_getList(IGNORE_PREFIX) that matches \a name at the left hand side, * or zero if no match was found - */ + */ int getPrefixIndex(const QCString &name) { if (name.isEmpty()) return 0; - static QStrList &sl = Config_getList(IGNORE_PREFIX); - char *s = sl.first(); - while (s) + const StringVector &sl = Config_getList(IGNORE_PREFIX); + for (const auto &s : sl) { - const char *ps=s; + const char *ps=s.c_str(); const char *pd=name.data(); int i=0; while (*ps!=0 && *pd!=0 && *ps==*pd) ps++,pd++,i++; @@ -5217,7 +4648,6 @@ int getPrefixIndex(const QCString &name) { return i; } - s = sl.next(); } return 0; } @@ -5249,7 +4679,7 @@ bool classHasVisibleChildren(const ClassDef *cd) if (cd->baseClasses()==0) return FALSE; bcl=cd->baseClasses(); } - else + else { if (cd->subClasses()==0) return FALSE; bcl=cd->subClasses(); @@ -5307,8 +4737,8 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor static GrowBuf growBuf; growBuf.clear(); if (name==0) return ""; - char c; - const char *p=name; + signed char c; + const signed char *p=(const signed char*)name; while ((c=*p++)!=0) { switch(c) @@ -5340,7 +4770,8 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor case '@': growBuf.addStr("_0d"); break; case ']': growBuf.addStr("_0e"); break; case '[': growBuf.addStr("_0f"); break; - default: + case '#': growBuf.addStr("_0g"); break; + default: if (c<0) { char ids[5]; @@ -5348,7 +4779,7 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor bool doEscape = TRUE; if (allowUnicodeNames && uc <= 0xf7) { - const char* pt = p; + const signed char* pt = p; ids[ 0 ] = c; int l = 0; if ((uc&0xE0)==0xC0) @@ -5402,7 +4833,7 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor else { growBuf.addChar('_'); - growBuf.addChar(tolower(c)); + growBuf.addChar((char)tolower(c)); } break; } @@ -5454,6 +4885,7 @@ QCString unescapeCharsInString(const char *s) case 'd': result+='@'; p+=2; break; // _0d -> '@' case 'e': result+=']'; p+=2; break; // _0e -> ']' case 'f': result+='['; p+=2; break; // _0f -> '[' + case 'g': result+='#'; p+=2; break; // _0g -> '#' default: // unknown escape, just pass underscore character as-is result+=c; break; @@ -5462,7 +4894,7 @@ QCString unescapeCharsInString(const char *s) default: if (!caseSenseNames && c>='a' && c<='z') // lower to upper case escape, _a -> 'A' { - result+=toupper(*p); + result+=(char)toupper(*p); p++; } else // unknown escape, pass underscore character as-is @@ -5482,7 +4914,7 @@ QCString unescapeCharsInString(const char *s) } /*! This function determines the file name on disk of an item - * given its name, which could be a class name with template + * given its name, which could be a class name with template * arguments, so special characters need to be escaped. */ QCString convertNameToFile(const char *name,bool allowDots,bool allowUnderscore) @@ -5508,7 +4940,7 @@ QCString convertNameToFile(const char *name,bool allowDots,bool allowUnderscore) { num = *value; } - result.sprintf("a%05d",num); + result.sprintf("a%05d",num); } else // long names { @@ -5521,17 +4953,17 @@ QCString convertNameToFile(const char *name,bool allowDots,bool allowUnderscore) QCString sigStr(33); MD5Buffer((const unsigned char *)result.data(),resultLen,md5_sig); MD5SigToString(md5_sig,sigStr.rawData(),33); - result=result.left(128-32)+sigStr; + result=result.left(128-32)+sigStr; } } if (createSubdirs) { int l1Dir=0,l2Dir=0; -#if MAP_ALGO==ALGO_COUNT +#if MAP_ALGO==ALGO_COUNT // old algorithm, has the problem that after regeneration the // output can be located in a different dir. - if (Doxygen::htmlDirMap==0) + if (Doxygen::htmlDirMap==0) { Doxygen::htmlDirMap=new QDict<int>(100003); Doxygen::htmlDirMap->setAutoDelete(TRUE); @@ -5540,7 +4972,7 @@ QCString convertNameToFile(const char *name,bool allowDots,bool allowUnderscore) int *dirNum = Doxygen::htmlDirMap->find(result); if (dirNum==0) // new name { - Doxygen::htmlDirMap->insert(result,new int(curDirNum)); + Doxygen::htmlDirMap->insert(result,new int(curDirNum)); l1Dir = (curDirNum)&0xf; // bits 0-3 l2Dir = (curDirNum>>4)&0xff; // bits 4-11 curDirNum++; @@ -5598,10 +5030,20 @@ void createSubDirs(QDir &d) int l1,l2; for (l1=0;l1<16;l1++) { - d.mkdir(QCString().sprintf("d%x",l1)); + QCString subdir; + subdir.sprintf("d%x",l1); + if (!d.exists(subdir) && !d.mkdir(subdir)) + { + term("Failed to create output directory '%s'\n",subdir.data()); + } for (l2=0;l2<256;l2++) { - d.mkdir(QCString().sprintf("d%x/d%02x",l1,l2)); + QCString subsubdir; + subsubdir.sprintf("d%x/d%02x",l1,l2); + if (!d.exists(subsubdir) && !d.mkdir(subsubdir)) + { + term("Failed to create output directory '%s'\n",subsubdir.data()); + } } } } @@ -5624,7 +5066,7 @@ void extractNamespaceName(const QCString &scopeName, goto done; } p=clName.length()-2; - while (p>=0 && (i=clName.findRev("::",p))!=-1) + while (p>=0 && (i=clName.findRev("::",p))!=-1) // see if the first part is a namespace (and not a class) { //printf("Trying %s\n",clName.left(i).data()); @@ -5634,7 +5076,7 @@ void extractNamespaceName(const QCString &scopeName, namespaceName=nd->name().copy(); className=clName.right(clName.length()-i-2); goto done; - } + } p=i-2; // try a smaller piece of the scope } //printf("not found!\n"); @@ -5671,12 +5113,12 @@ QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &te ((cd=getClass(scope.left(si)))==0 || cd->templateArguments().empty()) ) { - //printf("Tried '%s'\n",(scope.left(si)+templ).data()); - pi=si+2; + //printf("Tried '%s'\n",(scope.left(si)+templ).data()); + pi=si+2; } if (si==-1) // not nested => append template specifier { - result+=templ; + result+=templ; } else // nested => insert template specifier before after first class name { @@ -5688,7 +5130,7 @@ QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &te return result; } -#if 0 // original version + /*! Strips the scope from a name. Examples: A::B will return A * and A<T>::B<N::C<D> > will return A<T>. */ @@ -5696,55 +5138,11 @@ QCString stripScope(const char *name) { QCString result = name; int l=result.length(); - int p=l-1; - bool done; - int count; - - while (p>=0) - { - char c=result.at(p); - switch (c) - { - case ':': - //printf("stripScope(%s)=%s\n",name,result.right(l-p-1).data()); - return result.right(l-p-1); - case '>': - count=1; - done=FALSE; - //printf("pos < = %d\n",p); - p--; - while (p>=0 && !done) - { - c=result.at(p--); - switch (c) - { - case '>': count++; break; - case '<': count--; if (count<=0) done=TRUE; break; - default: - //printf("c=%c count=%d\n",c,count); - break; - } - } - //printf("pos > = %d\n",p+1); - break; - default: - p--; - } - } - //printf("stripScope(%s)=%s\n",name,name); - return name; -} -#endif - -// new version by Davide Cesari which also works for Fortran -QCString stripScope(const char *name) -{ - QCString result = name; - int l=result.length(); int p; bool done = FALSE; bool skipBracket=FALSE; // if brackets do not match properly, ignore them altogether int count=0; + int round=0; do { @@ -5754,10 +5152,13 @@ QCString stripScope(const char *name) char c=result.at(p); switch (c) { - case ':': + case ':': // only exit in the case of :: //printf("stripScope(%s)=%s\n",name,result.right(l-p-1).data()); - if (p>0 && result.at(p-1)==':') return result.right(l-p-1); + if (p>0 && result.at(p-1)==':' && (count==0 || skipBracket)) + { + return result.right(l-p-1); + } p--; break; case '>': @@ -5781,22 +5182,31 @@ QCString stripScope(const char *name) c=result.at(p--); switch (c) { - case '>': - count++; + case ')': + round++; + break; + case '(': + round--; + break; + case '>': // ignore > inside (...) to support e.g. (sizeof(T)>0) inside template parameters + if (round==0) count++; break; - case '<': - if (p>0) + case '<': + if (round==0) { - if (result.at(p-1) == '<') // skip << operator + if (p>0) { - p--; - break; + if (result.at(p-1) == '<') // skip << operator + { + p--; + break; + } } + count--; + foundMatch = count==0; } - count--; - foundMatch = count==0; break; - default: + default: //printf("c=%c count=%d\n",c,count); break; } @@ -5848,6 +5258,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) { @@ -5886,7 +5306,7 @@ QCString convertToXML(const char *s, bool keepEntities) growBuf.addStr("&"); } break; - case '\'': 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: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: @@ -5996,10 +5416,10 @@ QCString convertToHtml(const char *s,bool keepEntities) } else { - growBuf.addStr("&"); + growBuf.addStr("&"); } break; - case '\'': growBuf.addStr("'"); break; + case '\'': growBuf.addStr("'"); break; case '"': growBuf.addStr("""); break; default: growBuf.addChar(c); break; } @@ -6110,7 +5530,7 @@ void addMembersToMemberGroup(MemberList *ml, const Definition *context) { ASSERT(context!=0); - //printf("addMemberToMemberGroup()\n"); + //printf("addMemberToMemberGroup() context=%s\n",context->name().data()); if (ml==0) return; MemberListIterator mli(*ml); MemberDef *md; @@ -6143,6 +5563,7 @@ void addMembersToMemberGroup(MemberList *ml, if (mg==0) { mg = new MemberGroup( + context, groupId, info->header, info->doc, @@ -6175,6 +5596,7 @@ void addMembersToMemberGroup(MemberList *ml, if (mg==0) { mg = new MemberGroup( + context, groupId, info->header, info->doc, @@ -6184,7 +5606,7 @@ void addMembersToMemberGroup(MemberList *ml, (*ppMemberGroupSDict)->append(groupId,mg); } md = ml->take(index); // remove from member list - mg->insertMember(md); // insert in member group + mg->insertMember(md->resolveAlias()); // insert in member group mg->setRefItems(info->m_sli); md->setMemberGroup(mg); continue; @@ -6241,11 +5663,11 @@ int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStri int brCount=1; while (te<typeLen && brCount!=0) { - if (type.at(te)=='<') + if (type.at(te)=='<') { if (te<typeLen-1 && type.at(te+1)=='<') te++; else brCount++; } - if (type.at(te)=='>') + if (type.at(te)=='>') { if (te<typeLen-1 && type.at(te+1)=='>') te++; else brCount--; } @@ -6253,7 +5675,7 @@ int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStri } } name = type.mid(i,l); - if (te>ts) + if (te>ts) { templSpec = type.mid(ts,te-ts),tl+=te-ts; pos=i+l+tl; @@ -6334,21 +5756,24 @@ QCString normalizeNonTemplateArgumentsInString( QCString substituteTemplateArgumentsInString( const QCString &name, const ArgumentList &formalArgs, - const ArgumentList &actualArgs) + const std::unique_ptr<ArgumentList> &actualArgs) { //printf("substituteTemplateArgumentsInString(name=%s formal=%s actualArg=%s)\n", // name.data(),argListToString(formalArgs).data(),argListToString(actualArgs).data()); if (formalArgs.empty()) return name; QCString result; - static QRegExp re("[a-z_A-Z\\x80-\\xFF][a-z_A-Z0-9\\x80-\\xFF]*"); + static QRegExp re("[a-z_A-Z\\x80-\\xFF][a-z_A-Z0-9:\\x80-\\xFF]*"); int p=0,l,i; // for each identifier in the base class name (e.g. B<T> -> B and T) while ((i=re.match(name,p,&l))!=-1) { result += name.mid(p,i-p); QCString n = name.mid(i,l); - auto formIt = formalArgs.begin(); - auto actIt = actualArgs.begin(); + ArgumentList::iterator actIt; + if (actualArgs) + { + actIt = actualArgs->begin(); + } // if n is a template argument, then we substitute it // for its template instance argument. @@ -6360,7 +5785,7 @@ QCString substituteTemplateArgumentsInString( { Argument formArg = *formIt; Argument actArg; - if (actIt!=actualArgs.end()) + if (actualArgs && actIt!=actualArgs->end()) { actArg = *actIt; } @@ -6378,35 +5803,35 @@ QCString substituteTemplateArgumentsInString( { //printf("n=%s formArg->type='%s' formArg->name='%s' formArg->defval='%s'\n", // n.data(),formArg->type.data(),formArg->name.data(),formArg->defval.data()); - //printf(">> formArg->name='%s' actArg->type='%s' actArg->name='%s'\n", - // formArg->name.data(),actArg ? actArg->type.data() : "",actArg ? actArg->name.data() : "" + //printf(">> n='%s' formArg->name='%s' actArg->type='%s' actArg->name='%s'\n", + // n.data(),formArg.name.data(),actIt!=actualArgs.end() ? actIt->type.data() : "",actIt!=actualArgs.end() ? actIt->name.data() : "" // ); - if (formArg.name==n && actIt!=actualArgs.end() && !actArg.type.isEmpty()) // base class is a template argument + if (formArg.name==n && actualArgs && actIt!=actualArgs->end() && !actArg.type.isEmpty()) // base class is a template argument { // replace formal argument with the actual argument of the instance - if (!leftScopeMatch(actArg.type,n)) - // the scope guard is to prevent recursive lockup for - // template<class A> class C : public<A::T>, - // where A::T would become A::T::T here, + if (!leftScopeMatch(actArg.type,n)) + // the scope guard is to prevent recursive lockup for + // template<class A> class C : public<A::T>, + // where A::T would become A::T::T here, // since n==A and actArg->type==A::T // see bug595833 for an example { if (actArg.name.isEmpty()) { - result += actArg.type+" "; + result += actArg.type+" "; found=TRUE; } - else + else // for case where the actual arg is something like "unsigned int" // the "int" part is in actArg->name. { - result += actArg.type+" "+actArg.name+" "; + result += actArg.type+" "+actArg.name+" "; found=TRUE; } } } else if (formArg.name==n && - actIt==actualArgs.end() && + (actualArgs==nullptr || actIt==actualArgs->end()) && !formArg.defval.isEmpty() && formArg.defval!=name /* to prevent recursion */ ) @@ -6416,7 +5841,7 @@ QCString substituteTemplateArgumentsInString( } } else if (formArg.name==n && - actIt==actualArgs.end() && + (actualArgs==nullptr || actIt==actualArgs->end()) && !formArg.defval.isEmpty() && formArg.defval!=name /* to prevent recursion */ ) @@ -6424,7 +5849,7 @@ QCString substituteTemplateArgumentsInString( result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs)+" "; found=TRUE; } - if (actIt!=actualArgs.end()) + if (actualArgs && actIt!=actualArgs->end()) { actIt++; } @@ -6441,62 +5866,45 @@ QCString substituteTemplateArgumentsInString( return result.stripWhiteSpace(); } -#if 0 -/*! Makes a deep copy of the list of argument lists \a srcLists. - * Will allocate memory, that is owned by the caller. - */ -QList<ArgumentList> *copyArgumentLists(const QList<ArgumentList> *srcLists) -{ - ASSERT(srcLists!=0); - QList<ArgumentList> *dstLists = new QList<ArgumentList>; - dstLists->setAutoDelete(TRUE); - QListIterator<ArgumentList> sli(*srcLists); - ArgumentList *sl; - for (;(sl=sli.current());++sli) - { - dstLists->append(sl->deepCopy()); - } - return dstLists; -} -#endif -/*! Strips template specifiers from scope \a fullName, except those - * that make up specialized classes. The switch \a parentOnly - * determines whether or not a template "at the end" of a scope - * should be considered, e.g. with \a parentOnly is \c TRUE, A<T>::B<S> will - * try to strip \<T\> and not \<S\>, while \a parentOnly is \c FALSE will - * strip both unless A<T> or B<S> are specialized template classes. +/*! Strips template specifiers from scope \a fullName, except those + * that make up specialized classes. The switch \a parentOnly + * determines whether or not a template "at the end" of a scope + * should be considered, e.g. with \a parentOnly is \c TRUE, \c A<T>::B<S> will + * try to strip `<T>` and not `<S>`, while \a parentOnly is \c FALSE will + * strip both unless `A<T>` or `B<S>` are specialized template classes. */ QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly, QCString *pLastScopeStripped) { + int i=fullName.find('<'); + if (i==-1) return fullName; QCString result; int p=0; int l=fullName.length(); - int i=fullName.find('<'); while (i!=-1) { //printf("1:result+=%s\n",fullName.mid(p,i-p).data()); int e=i+1; - bool done=FALSE; int count=1; - while (e<l && !done) + int round=0; + while (e<l && count>0) { char c=fullName.at(e++); - if (c=='<') - { - count++; - } - else if (c=='>') + switch (c) { - count--; - done = count==0; + case '(': round++; break; + case ')': if (round>0) round--; break; + case '<': if (round==0) count++; break; + case '>': if (round==0) count--; break; + default: + break; } } int si= fullName.find("::",e); - if (parentOnly && si==-1) break; + if (parentOnly && si==-1) break; // we only do the parent scope, so we stop here if needed result+=fullName.mid(p,i-p); @@ -6523,10 +5931,10 @@ QCString stripTemplateSpecifiersFromScope(const QCString &fullName, * Example1: \c A::B and \c B::C will result in \c A::B::C <br> * Example2: \c A and \c B will be \c A::B <br> * Example3: \c A::B and B will be \c A::B - * + * * @param leftScope the left hand part of the scope. * @param rightScope the right hand part of the scope. - * @returns the merged scope. + * @returns the merged scope. */ QCString mergeScopes(const QCString &leftScope,const QCString &rightScope) { @@ -6588,7 +5996,7 @@ int getScopeFragment(const QCString &s,int p,int *l) while (sp<sl && !done) { // TODO: deal with << and >> operators! - char c=s.at(sp++); + c=s.at(sp++); switch(c) { case '<': count++; break; @@ -6613,7 +6021,7 @@ found: PageDef *addRelatedPage(const char *name,const QCString &ptitle, const QCString &doc, const char *fileName,int startLine, - const std::vector<ListItemInfo> &sli, + const RefItemVector &sli, GroupDef *gd, const TagInfo *tagInfo, bool xref, @@ -6635,7 +6043,7 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, else // new page { QCString baseName=name; - if (baseName.right(4)==".tex") + if (baseName.right(4)==".tex") baseName=baseName.left(baseName.length()-4); else if (baseName.right(Doxygen::htmlFileExtension.length())==Doxygen::htmlFileExtension) baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length()); @@ -6667,32 +6075,31 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, { file=gd->getOutputFileBase(); } - else + else { file=pd->getOutputFileBase(); } - SectionInfo *si = Doxygen::sectionDict->find(pd->name()); + const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) { - if (si->lineNr != -1) + if (si->lineNr() != -1) { - warn(file,-1,"multiple use of section label '%s', (first occurrence: %s, line %d)",pd->name().data(),si->fileName.data(),si->lineNr); + warn(file,-1,"multiple use of section label '%s', (first occurrence: %s, line %d)",pd->name().data(),si->fileName().data(),si->lineNr()); } else { - warn(file,-1,"multiple use of section label '%s', (first occurrence: %s)",pd->name().data(),si->fileName.data()); + warn(file,-1,"multiple use of section label '%s', (first occurrence: %s)",pd->name().data(),si->fileName().data()); } } else { - si=new SectionInfo( - file,-1,pd->name(),pd->title(),SectionInfo::Page,0,pd->getReference()); + SectionManager::instance().add(pd->name(), + file,-1,pd->title(),SectionType::Page,0,pd->getReference()); //printf("si->label='%s' si->definition=%s si->fileName='%s'\n", // si->label.data(),si->definition?si->definition->name().data():"<none>", // si->fileName.data()); //printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,si->fileName.data()); //printf("Adding section key=%s si->fileName=%s\n",pageName.data(),si->fileName.data()); - Doxygen::sectionDict->append(pd->name(),si); } } } @@ -6701,39 +6108,21 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, //---------------------------------------------------------------------------- -void addRefItem(const std::vector<ListItemInfo> &sli, - const char *key, - const char *prefix, const char *name,const char *title,const char *args,Definition *scope) +void addRefItem(const RefItemVector &sli, + const char *key, + const char *prefix, const char *name,const char *title,const char *args,const Definition *scope) { - //printf("addRefItem(sli=%p,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",sli,key,prefix,name,title,args); + //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args); if (key && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012) { - for (const ListItemInfo &lii : sli) - { - RefList *refList = Doxygen::xrefLists->find(lii.type); - if (refList - && - ( - // either not a built-in list or the list is enabled - (lii.type!="todo" || Config_getBool(GENERATE_TODOLIST)) && - (lii.type!="test" || Config_getBool(GENERATE_TESTLIST)) && - (lii.type!="bug" || Config_getBool(GENERATE_BUGLIST)) && - (lii.type!="deprecated" || Config_getBool(GENERATE_DEPRECATEDLIST)) - ) - ) - { - RefItem *item = refList->getRefItem(lii.itemId); - ASSERT(item!=0); - - item->prefix = prefix; - item->scope = scope; - item->name = name; - item->title = title; - item->args = args; - - refList->insertIntoList(key,item); - - } + for (RefItem *item : sli) + { + item->setPrefix(prefix); + item->setScope(scope); + item->setName(name); + item->setTitle(title); + item->setArgs(args); + item->setGroup(key); } } } @@ -6754,11 +6143,11 @@ bool recursivelyAddGroupListToTitle(OutputList &ol,const Definition *d,bool root bool first=true; for (gli.toFirst();(gd=gli.current());++gli) { + if (!first) { ol.writeString(" | "); } else first=false; if (recursivelyAddGroupListToTitle(ol, gd, FALSE)) { ol.writeString(" » "); } - if (!first) { ol.writeString(" | "); } else first=FALSE; ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),0,gd->groupTitle()); } if (root) @@ -6812,6 +6201,7 @@ void filterLatexString(FTextStream &t,const char *str, case '%': t << "\\%"; break; case '#': t << "\\#"; break; case '$': t << "\\$"; break; + case '"': t << "\"{}"; break; case '-': t << "-\\/"; break; case '^': (usedTableLevels()>0) ? t << "\\string^" : t << (char)c; break; case '~': t << "\\string~"; break; @@ -6870,9 +6260,9 @@ void filterLatexString(FTextStream &t,const char *str, } break; case '*': t << "$\\ast$"; break; - case '_': if (!insideTabbing) t << "\\+"; - t << "\\_"; - if (!insideTabbing) t << "\\+"; + case '_': if (!insideTabbing) t << "\\+"; + t << "\\_"; + if (!insideTabbing) t << "\\+"; break; case '{': t << "\\{"; break; case '}': t << "\\}"; break; @@ -6880,8 +6270,8 @@ void filterLatexString(FTextStream &t,const char *str, case '>': t << "$>$"; break; case '|': t << "$\\vert$"; break; case '~': t << "$\\sim$"; break; - case '[': if (Config_getBool(PDF_HYPERLINKS) || insideItem) - t << "\\mbox{[}"; + case '[': if (Config_getBool(PDF_HYPERLINKS) || insideItem) + t << "\\mbox{[}"; else t << "["; break; @@ -6889,12 +6279,12 @@ void filterLatexString(FTextStream &t,const char *str, if (Config_getBool(PDF_HYPERLINKS) || insideItem) t << "\\mbox{]}"; else - t << "]"; + t << "]"; break; case '-': t << "-\\/"; break; case '\\': t << "\\textbackslash{}"; - break; + break; case '"': t << "\\char`\\\"{}"; break; case '`': t << "\\`{}"; @@ -6904,9 +6294,9 @@ void filterLatexString(FTextStream &t,const char *str, case ' ': if (keepSpaces) { if (insideTabbing) t << "\\>"; else t << '~'; } else t << ' '; break; - default: + default: //if (!insideTabbing && forceBreaks && c!=' ' && *p!=' ') - if (!insideTabbing && + if (!insideTabbing && ((c>='A' && c<='Z' && pc!=' ' && pc!='\0' && *p) || (c==':' && pc!=':') || (pc=='.' && isId(c))) ) { @@ -6940,7 +6330,7 @@ QCString latexEscapeLabelName(const char *s) case '}': t << "\\rcurly{}"; break; case '~': t << "````~"; break; // to get it a bit better in index together with other special characters // NOTE: adding a case here, means adding it to while below as well! - default: + default: i=0; // collect as long string as possible, before handing it to docify tmp[i++]=c; @@ -6979,7 +6369,7 @@ QCString latexEscapeIndexChars(const char *s) case '{': t << "\\lcurly{}"; break; case '}': t << "\\rcurly{}"; break; // NOTE: adding a case here, means adding it to while below as well! - default: + default: i=0; // collect as long string as possible, before handing it to docify tmp[i++]=c; @@ -7081,6 +6471,7 @@ QCString rtfFormatBmkStr(const char *name) } } + //printf("Name = %s RTF_tag = %s\n",name,(*tag).data()); return *tag; } @@ -7091,7 +6482,9 @@ bool checkExtension(const char *fName, const char *ext) QCString addHtmlExtensionIfMissing(const char *fName) { - if (QFileInfo(fName).extension(FALSE).isEmpty()) + if (fName==0) return fName; + const char *p = strchr(fName,'.'); + if (p==nullptr) // no extension { return QCString(fName)+Doxygen::htmlFileExtension; } @@ -7118,11 +6511,14 @@ void replaceNamespaceAliases(QCString &scope,int i) while (i>0) { QCString ns = scope.left(i); - QCString *s = Doxygen::namespaceAliasDict[ns]; - if (s) + if (!ns.isEmpty()) { - scope=*s+scope.right(scope.length()-i); - i=s->length(); + auto it = Doxygen::namespaceAliasMap.find(ns.data()); + if (it!=Doxygen::namespaceAliasMap.end()) + { + scope=it->second.data()+scope.right(scope.length()-i); + i=static_cast<int>(it->second.length()); + } } if (i>0 && ns==scope.left(i)) break; } @@ -7163,9 +6559,9 @@ bool findAndRemoveWord(QCString &s,const QCString &word) int p=0,i,l; while ((i=wordExp.match(s,p,&l))!=-1) { - if (s.mid(i,l)==word) + if (s.mid(i,l)==word) { - if (i>0 && isspace((uchar)s.at(i-1))) + if (i>0 && isspace((uchar)s.at(i-1))) i--,l++; else if (i+l<(int)s.length() && isspace((uchar)s.at(i+l))) l++; @@ -7193,10 +6589,11 @@ QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine) // search for leading empty lines int i=0,li=-1,l=s.length(); char c; - while ((c=*p++)) + while ((c=*p)) { - if (c==' ' || c=='\t' || c=='\r') i++; - else if (c=='\n') i++,li=i,docLine++; + if (c==' ' || c=='\t' || c=='\r') i++,p++; + else if (c=='\\' && qstrncmp(p,"\\ilinebr",8)==0) i+=8,li=i,p+=8; + else if (c=='\n') i++,li=i,docLine++,p++; else break; } @@ -7205,9 +6602,10 @@ QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine) p=s.data()+b; while (b>=0) { - c=*p; p--; - if (c==' ' || c=='\t' || c=='\r') b--; - else if (c=='\n') bi=b,b--; + c=*p; + if (c==' ' || c=='\t' || c=='\r') b--,p--; + else if (c=='r' && b>=7 && qstrncmp(p-7,"\\ilinebr",8)==0) bi=b-7,b-=8,p-=8; + else if (c=='\n') bi=b,b--,p--; else break; } @@ -7218,6 +6616,7 @@ QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine) if (bi==-1) bi=l; if (li==-1) li=0; if (bi<=li) return 0; // only empty lines + //printf("docLine='%s' len=%d li=%d bi=%d\n",s.data(),s.length(),li,bi); return s.mid(li,bi-li); } @@ -7249,7 +6648,7 @@ static struct Lang2ExtMap const char *langName; const char *parserName; SrcLangExt parserId; -} +} g_lang2extMap[] = { // language parser parser option @@ -7270,7 +6669,6 @@ g_lang2extMap[] = { "vhdl", "vhdl", SrcLangExt_VHDL }, { "xml", "xml", SrcLangExt_XML }, { "sql", "sql", SrcLangExt_SQL }, - { "tcl", "tcl", SrcLangExt_Tcl }, { "md", "md", SrcLangExt_Markdown }, { 0, 0, (SrcLangExt)0 } }; @@ -7361,9 +6759,9 @@ void initDefaultExtensionMapping() updateLanguageMapping(".f95", "fortran"); updateLanguageMapping(".f03", "fortran"); updateLanguageMapping(".f08", "fortran"); + updateLanguageMapping(".f18", "fortran"); updateLanguageMapping(".vhd", "vhdl"); updateLanguageMapping(".vhdl", "vhdl"); - updateLanguageMapping(".tcl", "tcl"); updateLanguageMapping(".ucf", "vhdl"); updateLanguageMapping(".qsf", "vhdl"); updateLanguageMapping(".md", "md"); @@ -7404,7 +6802,7 @@ QCString getFileNameExtension(QCString fn) //-------------------------------------------------------------------------- -MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, +MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, const char *n) { if (scope==0 || @@ -7488,9 +6886,9 @@ bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char const char *writeUtf8Char(FTextStream &t,const char *s) { - char c=*s++; - t << c; - if (c<0) // multibyte character + uchar c=(uchar)*s++; + t << (char)c; + if (c>=0x80) // multibyte character { if (((uchar)c&0xE0)==0xC0) { @@ -7516,12 +6914,12 @@ const char *writeUtf8Char(FTextStream &t,const char *s) return s; } -int nextUtf8CharPosition(const QCString &utf8Str,int len,int startPos) +int nextUtf8CharPosition(const QCString &utf8Str,uint len,uint startPos) { int bytes=1; if (startPos>=len) return len; - char c = utf8Str[startPos]; - if (c<0) // multibyte utf-8 character + uchar c = (uchar)utf8Str[startPos]; + if (c>=0x80) // multibyte utf-8 character { if (((uchar)c&0xE0)==0xC0) { @@ -7570,7 +6968,8 @@ QCString parseCommentAsText(const Definition *scope,const MemberDef *md, if (doc.isEmpty()) return s.data(); FTextStream t(&s); DocNode *root = validatingParseDoc(fileName,lineNr, - (Definition*)scope,(MemberDef*)md,doc,FALSE,FALSE); + (Definition*)scope,(MemberDef*)md,doc,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); TextDocVisitor *visitor = new TextDocVisitor(t); root->accept(visitor); delete visitor; @@ -7605,9 +7004,8 @@ QCString parseCommentAsText(const Definition *scope,const MemberDef *md, //-------------------------------------------------------------------------------------- -static QDict<void> aliasesProcessed; - -static QCString expandAliasRec(const QCString s,bool allowRecursion=FALSE); +static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed, + const QCString s,bool allowRecursion=FALSE); struct Marker { @@ -7617,8 +7015,8 @@ struct Marker int size; // size of the marker }; -/** For a string \a s that starts with a command name, returns the character - * offset within that string representing the first character after the +/** For a string \a s that starts with a command name, returns the character + * offset within that string representing the first character after the * command. For an alias with argument, this is the offset to the * character just after the argument list. * @@ -7640,16 +7038,17 @@ static int findEndOfCommand(const char *s) QCString args = extractAliasArgs(p,0); i+=args.length(); } - i+=p-s; + i+=(int)(p-s); } return i; } -/** Replaces the markers in an alias definition \a aliasValue - * with the corresponding values found in the comma separated argument +/** Replaces the markers in an alias definition \a aliasValue + * with the corresponding values found in the comma separated argument * list \a argList and the returns the result after recursive alias expansion. */ -static QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList) +static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, + const QCString &aliasValue,const QCString &argList) { //printf("----- replaceAliasArguments(val=[%s],args=[%s])\n",aliasValue.data(),argList.data()); @@ -7661,7 +7060,7 @@ static QCString replaceAliasArguments(const QCString &aliasValue,const QCString for (i=0;i<l;i++) { char c = argList.at(i); - if (c==',' && (i==0 || argList.at(i-1)!='\\')) + if (c==',' && (i==0 || argList.at(i-1)!='\\')) { args.append(new QCString(argList.mid(s,i-s))); s=i+1; // start of next argument @@ -7729,7 +7128,7 @@ static QCString replaceAliasArguments(const QCString &aliasValue,const QCString //printf("part before marker %d: '%s'\n",i,aliasValue.mid(p,m->pos-p).data()); if (m->number>0 && m->number<=(int)args.count()) // valid number { - result+=expandAliasRec(*args.at(m->number-1),TRUE); + result+=expandAliasRec(aliasesProcessed,*args.at(m->number-1),TRUE); //printf("marker index=%d pos=%d number=%d size=%d replacement %s\n",i,m->pos,m->number,m->size, // args.at(m->number-1)->data()); } @@ -7741,7 +7140,7 @@ static QCString replaceAliasArguments(const QCString &aliasValue,const QCString // expand the result again result = substitute(result,"\\{","{"); result = substitute(result,"\\}","}"); - result = expandAliasRec(substitute(result,"\\,",",")); + result = expandAliasRec(aliasesProcessed,substitute(result,"\\,",",")); return result; } @@ -7768,7 +7167,7 @@ static QCString escapeCommas(const QCString &s) return result.data(); } -static QCString expandAliasRec(const QCString s,bool allowRecursion) +static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const QCString s,bool allowRecursion) { QCString result; static QRegExp cmdPat("[\\\\@][a-z_A-Z][a-z_A-Z0-9]*"); @@ -7789,8 +7188,8 @@ static QCString expandAliasRec(const QCString s,bool allowRecursion) cmd += QCString().sprintf("{%d}",numArgs); // alias name + {n} } QCString *aliasText=Doxygen::aliasDict.find(cmd); - if (numArgs>1 && aliasText==0) - { // in case there is no command with numArgs parameters, but there is a command with 1 parameter, + if (numArgs>1 && aliasText==0) + { // in case there is no command with numArgs parameters, but there is a command with 1 parameter, // we also accept all text as the argument of that command (so you don't have to escape commas) aliasText=Doxygen::aliasDict.find(cmdNoArgs+"{1}"); if (aliasText) @@ -7801,19 +7200,20 @@ static QCString expandAliasRec(const QCString s,bool allowRecursion) } //printf("Found command s='%s' cmd='%s' numArgs=%d args='%s' aliasText=%s\n", // s.data(),cmd.data(),numArgs,args.data(),aliasText?aliasText->data():"<none>"); - if ((allowRecursion || aliasesProcessed.find(cmd)==0) && aliasText) // expand the alias + if ((allowRecursion || aliasesProcessed.find(cmd.str())==aliasesProcessed.end()) && + aliasText) // expand the alias { //printf("is an alias!\n"); - if (!allowRecursion) aliasesProcessed.insert(cmd,(void *)0x8); + if (!allowRecursion) aliasesProcessed.insert(cmd.str()); QCString val = *aliasText; if (hasArgs) { - val = replaceAliasArguments(val,args); + val = replaceAliasArguments(aliasesProcessed,val,args); //printf("replace '%s'->'%s' args='%s'\n", // aliasText->data(),val.data(),args.data()); } - result+=expandAliasRec(val); - if (!allowRecursion) aliasesProcessed.remove(cmd); + result+=expandAliasRec(aliasesProcessed,val); + if (!allowRecursion) aliasesProcessed.erase(cmd.str()); p=i+l; if (hasArgs) p+=argsLen+2; } @@ -7836,7 +7236,7 @@ int countAliasArguments(const QCString argList) int count=1; int l = argList.length(); int i; - for (i=0;i<l;i++) + for (i=0;i<l;i++) { char c = argList.at(i); if (c==',' && (i==0 || argList.at(i-1)!='\\')) count++; @@ -7870,7 +7270,7 @@ QCString extractAliasArgs(const QCString &args,int pos) prevChar=0; } - if (bc==0) + if (bc==0) { //printf("extractAliasArgs('%s')->'%s'\n",args.data(),args.mid(pos+1,i-pos-1).data()); return args.mid(pos+1,i-pos-1); @@ -7883,9 +7283,9 @@ QCString extractAliasArgs(const QCString &args,int pos) QCString resolveAliasCmd(const QCString aliasCmd) { QCString result; - aliasesProcessed.clear(); + StringUnorderedSet aliasesProcessed; //printf("Expanding: '%s'\n",aliasCmd.data()); - result = expandAliasRec(aliasCmd); + result = expandAliasRec(aliasesProcessed,aliasCmd); //printf("Expanding result: '%s'->'%s'\n",aliasCmd.data(),result.data()); return result; } @@ -7893,12 +7293,12 @@ QCString resolveAliasCmd(const QCString aliasCmd) QCString expandAlias(const QCString &aliasName,const QCString &aliasValue) { QCString result; - aliasesProcessed.clear(); + StringUnorderedSet aliasesProcessed; // avoid expanding this command recursively - aliasesProcessed.insert(aliasName,(void *)0x8); + aliasesProcessed.insert(aliasName.str()); // expand embedded commands //printf("Expanding: '%s'->'%s'\n",aliasName.data(),aliasValue.data()); - result = expandAliasRec(aliasValue); + result = expandAliasRec(aliasesProcessed,aliasValue); //printf("Expanding result: '%s'->'%s'\n",aliasName.data(),result.data()); return result; } @@ -7906,7 +7306,7 @@ QCString expandAlias(const QCString &aliasName,const QCString &aliasValue) void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList &al) { if (al.empty()) return; - ol.startConstraintList(theTranslator->trTypeConstraints()); + ol.startConstraintList(theTranslator->trTypeConstraints()); for (const Argument &a : al) { ol.startConstraintParam(); @@ -7916,7 +7316,8 @@ void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList linkifyText(TextGeneratorOLImpl(ol),d,0,0,a.type); ol.endConstraintType(); ol.startConstraintDocs(); - ol.generateDoc(d->docFile(),d->docLine(),d,0,a.docs,TRUE,FALSE); + ol.generateDoc(d->docFile(),d->docLine(),d,0,a.docs,TRUE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endConstraintDocs(); } ol.endConstraintList(); @@ -7932,27 +7333,19 @@ void stackTrace() static char cmd[40960]; char *p = cmd; p += sprintf(p,"/usr/bin/atos -p %d ", (int)getpid()); - for (int x = 0; x < frameCount; x++) + for (int x = 0; x < frameCount; x++) { p += sprintf(p,"%p ", backtraceFrames[x]); } fprintf(stderr,"========== STACKTRACE START ==============\n"); - #if defined(_WIN32) && !defined(__CYGWIN__) - if (FILE *fp = _popen(cmd, "r")) - #else - if (FILE *fp = ::popen(cmd, "r")) - #endif + if (FILE *fp = Portable::popen(cmd, "r")) { char resBuf[512]; while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp)) { fwrite(resBuf, 1, len, stderr); } - #if defined(_WIN32) && !defined(__CYGWIN__) - _pclose(fp); - #else - ::pclose(fp); - #endif + Portable::pclose(fp); } fprintf(stderr,"============ STACKTRACE END ==============\n"); //fprintf(stderr,"%s\n", frameStrings[x]); @@ -7965,7 +7358,7 @@ static int transcodeCharacterBuffer(const char *fileName,BufStr &srcBuf,int size if (inputEncoding==0 || outputEncoding==0) return size; if (qstricmp(inputEncoding,outputEncoding)==0) return size; void *cd = portable_iconv_open(outputEncoding,inputEncoding); - if (cd==(void *)(-1)) + if (cd==(void *)(-1)) { term("unsupported character conversion: '%s'->'%s': %s\n" "Check the INPUT_ENCODING setting in the config file!\n", @@ -8111,27 +7504,26 @@ QCString filterTitle(const QCString &title) // returns TRUE if the name of the file represented by 'fi' matches // one of the file patterns in the 'patList' list. -bool patternMatch(const QFileInfo &fi,const QStrList *patList) +bool patternMatch(const QFileInfo &fi,const StringVector &patList) { - static bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); + bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); bool found = FALSE; - // For Windows/Mac, always do the case insensitive match -#if defined(_WIN32) || defined(__MACOSX__) || defined(__CYGWIN__) - caseSenseNames = FALSE; -#endif - - if (patList) + // For platforms where the file system is non case sensitive overrule the setting + if (!Portable::fileSystemIsCaseSensitive()) { - QStrListIterator it(*patList); - QCString pattern; + caseSenseNames = FALSE; + } + if (!patList.empty()) + { QCString fn = fi.fileName().data(); QCString fp = fi.filePath().data(); QCString afp= fi.absFilePath().data(); - for (it.toFirst();(pattern=it.current());++it) + for (const auto &pat: patList) { + QCString pattern = pat.c_str(); if (!pattern.isEmpty()) { int i=pattern.find('='); @@ -8181,10 +7573,15 @@ void writeSummaryLink(OutputList &ol,const char *label,const char *title, } #endif -QCString externalLinkTarget() +QCString externalLinkTarget(const bool parent) { static bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW); - if (extLinksInWindow) return "target=\"_blank\" "; else return ""; + if (extLinksInWindow) + return "target=\"_blank\" "; + else if (parent) + return "target=\"_parent\" "; + else + return ""; } QCString externalRef(const QCString &relPath,const QCString &ref,bool href) @@ -8213,7 +7610,7 @@ QCString externalRef(const QCString &relPath,const QCString &ref,bool href) return result; } -/** Writes the intensity only bitmap represented by \a data as an image to +/** Writes the intensity only bitmap represented by \a data as an image to * directory \a dir using the colors defined by HTML_COLORSTYLE_*. */ void writeColoredImgData(const char *dir,ColoredImgDataItem data[]) @@ -8242,8 +7639,8 @@ void writeColoredImgData(const char *dir,ColoredImgDataItem data[]) } /** Replaces any markers of the form \#\#AA in input string \a str - * by new markers of the form \#AABBCC, where \#AABBCC represents a - * valid color, based on the intensity represented by hex number AA + * by new markers of the form \#AABBCC, where \#AABBCC represents a + * valid color, based on the intensity represented by hex number AA * and the current HTML_COLORSTYLE_* settings. */ QCString replaceColorMarkers(const char *str) @@ -8264,7 +7661,7 @@ QCString replaceColorMarkers(const char *str) #define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \ ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \ ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0) - + double r,g,b; int red,green,blue; int level = HEXTONUM(lumStr[0])*16+HEXTONUM(lumStr[1]); @@ -8290,7 +7687,7 @@ QCString replaceColorMarkers(const char *str) return result; } -/** Copies the contents of file with name \a src to the newly created +/** Copies the contents of file with name \a src to the newly created * file with name \a dest. Returns TRUE if successful. */ bool copyFile(const QCString &src,const QCString &dest) @@ -8322,7 +7719,7 @@ bool copyFile(const QCString &src,const QCString &dest) return TRUE; } -/** Returns the section of text, in between a pair of markers. +/** Returns the section of text, in between a pair of markers. * Full lines are returned, excluding the lines on which the markers appear. * \sa routine lineBlock */ @@ -8410,7 +7807,6 @@ QCString langToString(SrcLangExt lang) case SrcLangExt_VHDL: return "VHDL"; case SrcLangExt_XML: return "XML"; case SrcLangExt_SQL: return "SQL"; - case SrcLangExt_Tcl: return "Tcl"; case SrcLangExt_Markdown: return "Markdown"; case SrcLangExt_Slice: return "Slice"; } @@ -8433,16 +7829,11 @@ QCString getLanguageSpecificSeparator(SrcLangExt lang,bool classScope) return "::"; } } -QCString replaceScopeSeparator(QCString str) -{ - // we don't know about the language so we have to go for the worse - return substitute(substitute(str,"\\","::"),".","::"); // PHP and Java, CSharp, VHDL, Python -} /** Checks whether the given url starts with a supported protocol */ bool isURL(const QCString &url) { QCString loc_url = url.stripWhiteSpace(); - return loc_url.left(5)=="http:" || loc_url.left(6)=="https:" || + return loc_url.left(5)=="http:" || loc_url.left(6)=="https:" || loc_url.left(4)=="ftp:" || loc_url.left(5)=="file:"; } /** Corrects URL \a url according to the relative path \a relPath. @@ -8465,8 +7856,8 @@ bool protectionLevelVisible(Protection prot) static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); static bool extractPackage = Config_getBool(EXTRACT_PACKAGE); - return (prot!=Private && prot!=Package) || - (prot==Private && extractPrivate) || + return (prot!=Private && prot!=Package) || + (prot==Private && extractPrivate) || (prot==Package && extractPackage); } @@ -8489,7 +7880,7 @@ QCString stripIndentation(const QCString &s) if (c=='\t') indent+=tabSize - (indent%tabSize); else if (c=='\n') indent=0,searchIndent=TRUE; else if (c==' ') indent++; - else if (searchIndent) + else if (searchIndent) { searchIndent=FALSE; if (indent<minIndent) minIndent=indent; @@ -8538,6 +7929,55 @@ QCString stripIndentation(const QCString &s) return result.data(); } +// strip up to \a indentationLevel spaces from each line in \a doc (excluding the first line) +void stripIndentation(QCString &doc,const int indentationLevel) +{ + if (indentationLevel <= 0 || doc.isEmpty()) return; // nothing to strip + + // by stripping content the string will only become shorter so we write the results + // back into the input string and then resize it at the end. + char c; + const char *src = doc.data(); + char *dst = doc.rawData(); + bool insideIndent = false; // skip the initial line from stripping + int cnt = 0; + while ((c=*src++)!=0) + { + // invariant: dst<=src + switch(c) + { + case '\n': + *dst++ = c; + insideIndent = true; + cnt = indentationLevel; + break; + case ' ': + if (insideIndent) + { + if (cnt>0) // count down the spacing until the end of the indent + { + cnt--; + } + else // reached the end of the indent, start of the part of the line to keep + { + insideIndent = false; + *dst++ = c; + } + } + else // part after indent, copy to the output + { + *dst++ = c; + } + break; + default: + insideIndent = false; + *dst++ = c; + break; + } + } + doc.resize(dst-doc.data()+1); +} + bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile) { @@ -8546,7 +7986,7 @@ bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile) genSourceFile = !isDocFile && fd->generateSourceFile(); return ( ((allExternals && fd->isLinkable()) || fd->isLinkableInProject() - ) && + ) && !isDocFile ); } @@ -8555,7 +7995,7 @@ void addDocCrossReference(MemberDef *src,MemberDef *dst) { //printf("--> addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data()); if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types - if ((dst->hasReferencedByRelation() || dst->hasCallerGraph()) && + if ((dst->hasReferencedByRelation() || dst->hasCallerGraph()) && src->showInCallGraph() ) { @@ -8571,7 +8011,7 @@ void addDocCrossReference(MemberDef *src,MemberDef *dst) mdDecl->addSourceReferencedBy(src); } } - if ((src->hasReferencesRelation() || src->hasCallGraph()) && + if ((src->hasReferencesRelation() || src->hasCallGraph()) && src->showInCallGraph() ) { @@ -8627,7 +8067,7 @@ uint getUtf8Code( const QCString& s, int idx ) } -/*! @brief Returns one unicode character as an unsigned integer +/*! @brief Returns one unicode character as an unsigned integer * from utf-8 string, making the character lower case if it was upper case. * * @param s utf-8 encoded string @@ -8642,7 +8082,7 @@ uint getUtf8CodeToLower( const QCString& s, int idx ) } -/*! @brief Returns one unicode character as an unsigned integer +/*! @brief Returns one unicode character as an unsigned integer * from utf-8 string, making the character upper case if it was lower case. * * @param s utf-8 encoded string @@ -8723,20 +8163,22 @@ bool classVisibleInIndex(const ClassDef *cd) QCString extractDirection(QCString &docs) { - QRegExp re("\\[[^\\]]+\\]"); // [...] + QRegExp re("\\[[ inout,]+\\]"); // [...] int l=0; - if (re.match(docs,0,&l)==0) + if (re.match(docs,0,&l)==0 && l>2) { - int inPos = docs.find("in", 1,FALSE); - int outPos = docs.find("out",1,FALSE); - bool input = inPos!=-1 && inPos<l; - bool output = outPos!=-1 && outPos<l; - if (input || output) // in,out attributes + // make dir the part inside [...] without separators + QCString dir=substitute(substitute(docs.mid(1,l-2)," ",""),",",""); + int inIndex, outIndex; + unsigned char ioMask=0; + if (( inIndex=dir.find( "in"))!=-1) dir.remove (inIndex,2),ioMask|=(1<<0); + if ((outIndex=dir.find("out"))!=-1) dir.remove(outIndex,3),ioMask|=(1<<1); + if (dir.isEmpty() && ioMask!=0) // only in and/or out attributes found { docs = docs.mid(l); // strip attributes - if (input && output) return "[in,out]"; - else if (input) return "[in]"; - else if (output) return "[out]"; + if (ioMask==((1<<0)|(1<<1))) return "[in,out]"; + else if (ioMask==(1<<0)) return "[in]"; + else if (ioMask==(1<<1)) return "[out]"; } } return QCString(); @@ -8963,7 +8405,7 @@ bool openOutputFile(const char *outFile,QFile &f) if (backup.exists()) // remove existing backup dir.remove(backup.fileName()); dir.rename(fi.fileName(),fi.fileName()+".bak"); - } + } f.setName(outFile); fileOpened = f.open(IO_WriteOnly|IO_Translate); } @@ -8973,18 +8415,16 @@ bool openOutputFile(const char *outFile,QFile &f) void writeExtraLatexPackages(FTextStream &t) { // User-specified packages - QStrList &extraPackages = Config_getList(EXTRA_PACKAGES); - if (!extraPackages.isEmpty()) + const StringVector &extraPackages = Config_getList(EXTRA_PACKAGES); + if (!extraPackages.empty()) { t << "% Packages requested by user\n"; - const char *pkgName=extraPackages.first(); - while (pkgName) + for (const auto &pkgName : extraPackages) { if ((pkgName[0] == '[') || (pkgName[0] == '{')) - t << "\\usepackage" << pkgName << "\n"; + t << "\\usepackage" << pkgName.c_str() << "\n"; else - t << "\\usepackage{" << pkgName << "}\n"; - pkgName=extraPackages.next(); + t << "\\usepackage{" << pkgName.c_str() << "}\n"; } t << "\n"; } @@ -9034,5 +8474,3 @@ int usedTableLevels() } //------------------------------------------------------ - - @@ -22,12 +22,16 @@ * \brief A bunch of utility functions. */ +#include <memory> + #include <qlist.h> #include <ctype.h> #include "types.h" #include "sortdict.h" #include "docparser.h" #include "classdef.h" +#include "arguments.h" +#include "containers.h" //-------------------------------------------------------------------- @@ -35,7 +39,7 @@ class ClassDef; class FileDef; class MemberList; class NamespaceDef; -class FileNameDict; +class FileNameLinkedMap; class ArgumentList; class OutputList; class OutputDocInterface; @@ -48,10 +52,8 @@ class NamespaceSDict; class ClassList; class MemberGroupSDict; struct TagInfo; -class MemberNameInfoSDict; -struct ListItemInfo; class PageDef; -struct SectionInfo; +class SectionInfo; class QDir; class Definition; class BufStr; @@ -119,7 +121,6 @@ class LetterToIndexMap : public SIntDict<T> QCString langToString(SrcLangExt lang); QCString getLanguageSpecificSeparator(SrcLangExt lang,bool classScope=FALSE); -QCString replaceScopeSeparator(QCString str); //-------------------------------------------------------------------- @@ -186,8 +187,8 @@ void writePageRef(OutputDocInterface &od,const char *cn,const char *mn); QCString getCanonicalTemplateSpec(const Definition *d,const FileDef *fs,const QCString& spec); -bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList &srcAl, - const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList &dstAl, +bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList *srcAl, + const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList *dstAl, bool checkCV ); @@ -195,9 +196,6 @@ void mergeArguments(ArgumentList &,ArgumentList &,bool forceNameOverwrite=FALSE) QCString substituteClassNames(const QCString &s); -QCString substitute(const QCString &s,const QCString &src,const QCString &dst); -QCString substitute(const QCString &s,const QCString &src,const QCString &dst,int skip_seq); -QCString substitute(const QCString &s,char srcChar,char dstChar); QCString clearBlock(const char *s,const char *begin,const char *end); @@ -218,10 +216,10 @@ const ClassDef *getResolvedClass(const Definition *scope, NamespaceDef *getResolvedNamespace(const char *key); -FileDef *findFileDef(const FileNameDict *fnDict,const char *n, +FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n, bool &ambig); -QCString showFileDefMatches(const FileNameDict *fnDict,const char *n); +QCString showFileDefMatches(const FileNameLinkedMap *fnMap,const char *n); int guessSection(const char *name); @@ -280,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); @@ -310,7 +309,7 @@ QCString normalizeNonTemplateArgumentsInString( QCString substituteTemplateArgumentsInString( const QCString &name, const ArgumentList &formalArgs, - const ArgumentList &actualArgs); + const std::unique_ptr<ArgumentList> &actualArgs); //QList<ArgumentList> *copyArgumentLists(const QList<ArgumentList> *srcLists); @@ -327,15 +326,19 @@ int getScopeFragment(const QCString &s,int p,int *l); int filterCRLF(char *buf,int len); -void addRefItem(const std::vector<ListItemInfo> &sli,const char *prefix, +void addRefItem(const RefItemVector &sli, const char *key, - const char *name,const char *title,const char *args,Definition *scope); + const char *prefix, + const char *name, + const char *title, + const char *args, + const Definition *scope); PageDef *addRelatedPage(const char *name, const QCString &ptitle, const QCString &doc, const char *fileName,int startLine, - const std::vector<ListItemInfo> &sli = std::vector<ListItemInfo>(), + const RefItemVector &sli = RefItemVector(), GroupDef *gd=0, const TagInfo *tagInfo=0, bool xref=FALSE, @@ -408,7 +411,7 @@ const ClassDef *newResolveTypedef(const FileDef *fileScope, const MemberDef **pMemType=0, QCString *pTemplSpec=0, QCString *pResolvedType=0, - const ArgumentList *actTemplParams=0); + const std::unique_ptr<ArgumentList> &actTemplParams=std::unique_ptr<ArgumentList>()); QCString parseCommentAsText(const Definition *scope,const MemberDef *member,const QCString &doc,const QCString &fileName,int lineNr); @@ -435,11 +438,11 @@ bool readInputFile(const char *fileName,BufStr &inBuf, bool filter=TRUE,bool isSourceCode=FALSE); QCString filterTitle(const QCString &title); -bool patternMatch(const QFileInfo &fi,const QStrList *patList); +bool patternMatch(const QFileInfo &fi,const StringVector &patList); -QCString externalLinkTarget(); +QCString externalLinkTarget(const bool parent = false); QCString externalRef(const QCString &relPath,const QCString &ref,bool href); -int nextUtf8CharPosition(const QCString &utf8Str,int len,int startPos); +int nextUtf8CharPosition(const QCString &utf8Str,uint len,uint startPos); const char *writeUtf8Char(FTextStream &t,const char *s); @@ -469,6 +472,7 @@ QCString processMarkup(const QCString &s); bool protectionLevelVisible(Protection prot); QCString stripIndentation(const QCString &s); +void stripIndentation(QCString &doc,const int indentationLevel); QCString getDotImageExtension(void); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index fe5a8d9..808e5a2 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -20,6 +20,9 @@ %option never-interactive %option case-insensitive %option prefix="vhdlcodeYY" +%top{ +#include <stdint.h> +} %{ @@ -50,6 +53,8 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 + +#define USE_STATE2STRING 0 // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -113,7 +118,10 @@ static bool writeColoredWord(QCString& word ); static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool typeOnly=FALSE, const char *curr_class=0); static void endFontClass(); static void startFontClass(const char *s); + +#if USE_STATE2STRING static const char *stateToString(int state); +#endif //------------------------------------------------------------------- @@ -852,7 +860,7 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI generateMemLink(*g_code,g_PortMapComp,s1); while (index++<t1.size()) { - char cc=t1.at(index); + cc=t1.at(index); if (cc==' ' || cc=='\t') { char c2[2]; @@ -1644,5 +1652,7 @@ void codeFreeVhdlScanner() #endif } +#if USE_STATE2STRING #include "vhdlcode.l.h" +#endif diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 3c30174..8e311b7 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -58,7 +58,7 @@ #include "plantuml.h" #include "vhdljjparser.h" #include "VhdlParser.h" -#include "vhdlcode.h" +//#include "vhdlcode.h" #include "plantuml.h" //#define DEBUGFLOW #define theTranslator_vhdlType theTranslator->trVhdlType @@ -70,7 +70,6 @@ static QDict<QCString> g_vhdlKeyDict3(17,FALSE); static void initUCF(Entry* root,const char* type,QCString & qcs,int line,QCString & fileName,QCString & brief); static void writeUCFLink(const MemberDef* mdef,OutputList &ol); -static void assignBinding(VhdlConfNode* conf); static void addInstance(ClassDef* entity, ClassDef* arch, ClassDef *inst, const std::shared_ptr<Entry> &cur); @@ -200,7 +199,7 @@ void VhdlDocGen::writeOverview() if (!f.open(IO_WriteOnly)) { - fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data()); + err("Warning: Cannot open file %s for writing\n",fileName.data()); return; } @@ -768,22 +767,22 @@ MemberDef* VhdlDocGen::findMember(const QCString& className, const QCString& mem Definition *d = cd->getOuterScope(); QCString tt=d->name(); - ClassDef *ecd =getClass(tt); - if (!ecd) + ClassDef *acd =getClass(tt); + if (!acd) { tt=tt.upper(); - ecd =getClass(tt); + acd =getClass(tt); } - if (!ecd) + if (!acd) { tt=tt.lower(); - ecd =getClass(tt); + acd =getClass(tt); } - if (ecd) //d && d->definitionType()==Definition::TypeClass) + if (acd) //d && d->definitionType()==Definition::TypeClass) { - if(!packages.contains(ecd)) + if(!packages.contains(acd)) { - VhdlDocGen::findAllPackages(ecd); + VhdlDocGen::findAllPackages(acd); } } } @@ -1154,7 +1153,6 @@ void VhdlDocGen::parseFuncProto(const char* text,QCString& name,QCString& ret,bo } else { - QCString s1(text); s1=s1.stripWhiteSpace(); int i=s1.find("(",0,FALSE); int s=s1.find(QRegExp("[ \\t]")); @@ -1421,7 +1419,7 @@ void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef* void VhdlDocGen::writeProcedureProto(OutputList& ol,const ArgumentList &al,const MemberDef* mdef) { bool sem=FALSE; - int len=al.size(); + size_t len=al.size(); ol.docify("( "); if (len > 2) { @@ -1477,7 +1475,7 @@ void VhdlDocGen::writeFunctionProto(OutputList& ol,const ArgumentList &al,const { if (!al.hasParameters()) return; bool sem=FALSE; - int len=al.size(); + size_t len=al.size(); ol.startBold(); ol.docify(" ( "); ol.endBold(); @@ -1586,7 +1584,7 @@ bool VhdlDocGen::writeFuncProcDocu( //bool sem=FALSE; ol.enableAll(); - int index=al.size(); + size_t index=al.size(); if (index==0) { ol.docify(" ( ) "); @@ -1879,7 +1877,7 @@ void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile) tagFile << "\">" << endl; tagFile << " <type>" << convertToXML(mdef->typeString()) << "</type>" << endl; tagFile << " <name>" << convertToXML(mdef->name()) << "</name>" << endl; - tagFile << " <anchorfile>" << convertToXML(mdef->getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl; + tagFile << " <anchorfile>" << convertToXML(mdef->getOutputFileBase()) << Doxygen::htmlFileExtension << "</anchorfile>" << endl; tagFile << " <anchor>" << convertToXML(mdef->anchor()) << "</anchor>" << endl; if (VhdlDocGen::isVhdlFunction(mdef)) @@ -1956,9 +1954,10 @@ void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, } // *** write type /*VHDL CHANGE */ - bool bRec,bUnit; + QCString ltype(mdef->typeString()); QCString largs(mdef->argsString()); + ClassDef *kl=0; const ArgumentList &al = mdef->argumentList(); QCString nn; @@ -2014,7 +2013,7 @@ void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, ol.insertMemberAlign(); if (largs=="context") { - VhdlDocGen::writeRecorUnit(ltype,ol,mdef); + VhdlDocGen::writeRecordUnit(ltype,largs,ol,mdef); } break; @@ -2079,7 +2078,6 @@ void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, ol.insertMemberAlign(); ol.docify(" "); - ol.startBold(); ol.docify(ltype); ol.endBold(); @@ -2128,6 +2126,7 @@ void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, case VhdlDocGen::SHAREDVARIABLE: case VhdlDocGen::VFILE: case VhdlDocGen::GROUP: + case VhdlDocGen::TYPE: writeLink(mdef,ol); ol.docify(" "); ol.insertMemberAlign(); @@ -2135,32 +2134,7 @@ void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, break; case VhdlDocGen::RECORD: case VhdlDocGen::UNITS: - writeLink(mdef,ol); - ol.docify(" "); - ol.startBold(); - if (ltype.isEmpty()) { - ol.docify(" "); - } - ol.insertMemberAlign(); - if (!ltype.isEmpty()) - VhdlDocGen::formatString(ltype,ol,mdef); - ol.endBold(); - break; - case VhdlDocGen::TYPE: - bRec=largs.stripPrefix("record") ; - bUnit=largs.stripPrefix("units") ; - ol.startBold(); - if (bRec) ol.docify("record: "); - if (bUnit) ol.docify("units: "); - writeLink(mdef,ol); - ol.insertMemberAlign(); - if (!bRec && !bUnit) VhdlDocGen::formatString(ltype,ol,mdef); - if (bUnit) ol.lineBreak(); - if (bRec || bUnit) - { - writeRecorUnit(largs,ol,mdef); - } - ol.endBold(); + writeRecordUnit(largs,ltype,ol,mdef); break; default: break; @@ -2191,8 +2165,9 @@ void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, QCString s=mdef->briefDescription(); ol.startMemberDescription(mdef->anchor(), NULL, mm == VhdlDocGen::PORT); ol.generateDoc(mdef->briefFile(),mdef->briefLine(), - mdef->getOuterScope()?mdef->getOuterScope():d, - mdef,s.data(),TRUE,FALSE,0,TRUE,FALSE); + mdef->getOuterScope()?mdef->getOuterScope():d, + mdef,s.data(),TRUE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); if (detailsVisible) { ol.pushGeneratorState(); @@ -2296,7 +2271,8 @@ void VhdlDocGen::writeVHDLDeclarations(const MemberList* ml,OutputList &ol, if (subtitle && subtitle[0]!=0) { ol.startMemberSubtitle(); - ol.generateDoc("[generated]",-1,0,0,subtitle,FALSE,FALSE,0,TRUE,FALSE); + ol.generateDoc("[generated]",-1,0,0,subtitle,FALSE,FALSE, + 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberSubtitle(); } //printf("memberGroupList=%p\n",memberGroupList); @@ -2322,7 +2298,8 @@ void VhdlDocGen::writeVHDLDeclarations(const MemberList* ml,OutputList &ol, { //printf("Member group has docs!\n"); ol.startMemberGroupDocs(); - ol.generateDoc("[generated]",-1,0,0,mg->documentation()+"\n",FALSE,FALSE); + ol.generateDoc("[generated]",-1,0,0,mg->documentation()+"\n",FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endMemberGroupDocs(); } ol.startMemberGroup(); @@ -2479,10 +2456,10 @@ void VhdlDocGen::parseUCF(const char* input, Entry* entity,QCString fileName,b { if (altera) { - int i=temp.find("-name"); - if (i>0) + int in=temp.find("-name"); + if (in>0) { - temp=temp.remove(0,i+5); + temp=temp.remove(0,in+5); } temp.stripPrefix("set_location_assignment"); @@ -2492,8 +2469,8 @@ void VhdlDocGen::parseUCF(const char* input, Entry* entity,QCString fileName,b else { QRegExp ee("[\\s=]"); - int i=temp.find(ee); - QCString ff=temp.left(i); + int in=temp.find(ee); + QCString ff=temp.left(in); temp.stripPrefix(ff.data()); ff.append("#"); if (!temp.isEmpty()) @@ -2593,44 +2570,8 @@ static void writeUCFLink(const MemberDef* mdef,OutputList &ol) VhdlDocGen::formatString(largs,ol,mdef); } -bool VhdlDocGen::findConstraintFile(LayoutNavEntry *lne) -{ - FileName *fn=Doxygen::inputNameList->getFirst(); - //LayoutNavEntry *cc = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Files); - uint count=Doxygen::inputNameList->count(); - LayoutNavEntry *kk = lne->parent();// find(LayoutNavEntry::Files); - // LayoutNavEntry *kks = kk->parent();// find(LayoutNavEntry::Files); - QCString file; - QCString co("Constraints"); - - QCString imgExt = getDotImageExtension(); - if (Config_getBool(HAVE_DOT) && imgExt=="svg") - { - QCString ov = theTranslator->trDesignOverview(); - QCString ofile("vhdl_design_overview"); - LayoutNavEntry *oo=new LayoutNavEntry( lne,LayoutNavEntry::MainPage,TRUE,ofile,ov,""); - kk->addChild(oo); - } - - uint i=0; - while (i<count) - { - FileDef *fd=fn->at(i); - if (fd->name().contains(".ucf") || fd->name().contains(".qsf")) - { - file = convertNameToFile(fd->name().data(),FALSE,FALSE); - LayoutNavEntry *ucf=new LayoutNavEntry(lne,LayoutNavEntry::MainPage,TRUE,file,co,""); - kk->addChild(ucf); - break; - } - i++; - } - return FALSE; -} - - // for cell_inst : [entity] work.proto [ (label|expr) ] -QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) +QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) { int index; QCString label; @@ -2708,133 +2649,6 @@ QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch) } -//@param arch bit0:flipflop -//@param binding e.g entity work.foo(bar) -//@param label |label0|label1 -// label0:architecture name -//@param confVhdl of configuration file (identifier::entity_name) or -// the architecture if isInlineConf TRUE -//@param isInlineConf -//@param confN List of configurations - -void assignBinding(VhdlConfNode * conf) -{ - ClassDef *archClass=0,*entClass=0; - QCString archName; - QCString arcBind,entBind; - - bool others,all; - entBind=conf->binding; - QCString conf2=VhdlDocGen::parseForBinding(entBind,arcBind); - - if (qstricmp(conf2,"configuration")==0) - { - QList<VhdlConfNode> confList = getVhdlConfiguration(); - VhdlConfNode* vconf; - // bool found=false; - for (uint iter=0;iter<confList.count(); iter++) - { - vconf= (VhdlConfNode *)confList.at(iter); - QCString n=VhdlDocGen::getIndexWord(vconf->confVhdl.data(),0); - if (n==entBind) - { - // found=true; - entBind=VhdlDocGen::getIndexWord(vconf->confVhdl.data(),1); - QCString a=VhdlDocGen::getIndexWord(conf->compSpec.data(),0); - QCString e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),1); - a=e+"::"+a; - archClass= VhdlDocGen::findVhdlClass(a.data());//Doxygen::classSDict->find(a.data()); - entClass= VhdlDocGen::findVhdlClass(e.data());//Doxygen::classSDict->find(e.data()); - break; - } - } - } - else // conf2!=configuration - { - QCString a,c,e; - if (conf->isInlineConf) - { - c=conf->confVhdl; - e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),0); - } - else - { - a=VhdlDocGen::getIndexWord(conf->compSpec.data(),0); - e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),1); - c=e+"::"+a; - } - archClass= VhdlDocGen::findVhdlClass(c.data());//Doxygen::classSDict->find(a.data()); - entClass= VhdlDocGen::findVhdlClass(e.data()); //Doxygen::classSDict->find(e.data()); - } - - QCString label=conf->compSpec.lower(); - //label.prepend("|"); - - if (!archClass) - { - // err("architecture %s not found ! ",conf->confVhdl.data()); - return; - } - - archName=archClass->name(); - QCString allOt=VhdlDocGen::getIndexWord(conf->arch.data(),0); - all=allOt.lower()=="all" ; - others= allOt.lower()=="others"; - - for (const auto &cur : getVhdlInstList()) - { - if (cur->exception.lower()==label || conf->isInlineConf) - { - QCString archy; - - if (all || others) - { - archy=VhdlDocGen::getIndexWord(conf->arch.data(),1); - } - else - { - archy=conf->arch; - } - - QCString inst1=VhdlDocGen::getIndexWord(archy.data(),0).lower(); - QCString comp=VhdlDocGen::getIndexWord(archy.data(),1).lower(); - - QCStringList ql=QCStringList::split(",",inst1); - - for (uint j=0;j<ql.count();j++) - { - QCString archy1,sign1; - if (all || others) - { - archy1=VhdlDocGen::getIndexWord(conf->arch.data(),1); - sign1=cur->type; - } - else - { - archy1=comp+":"+ql[j]; - sign1=cur->type+":"+cur->name; - } - - if (archy1==sign1.lower() && !cur->stat) - { - // fprintf(stderr," \n label [%s] [%s] [%s]",cur->exception.data(),cur->type.data(),cur->name.data()); - ClassDef *ent= VhdlDocGen::findVhdlClass(entBind.data());//Doxygen::classSDict->find(entBind.data()); - - if (entClass==0 || ent==0) - { - continue; - } - - addInstance(ent,archClass,entClass,cur); - cur->stat=TRUE; - break; - } - }// for - } - }//for each element in instList - -}//assignBinding - /* // file foo.vhd @@ -2852,17 +2666,6 @@ void VhdlDocGen::computeVhdlComponentRelations() { QCString entity,arch,inst; - QList<VhdlConfNode> confList = getVhdlConfiguration(); - - for (uint iter=0;iter<confList.count(); iter++) - { - VhdlConfNode* conf= (VhdlConfNode *)confList.at(iter); - if (!(conf->isInlineConf || conf->isLeaf)) - { - continue; - } - assignBinding(conf); - } for (const auto &cur : getVhdlInstList()) { @@ -2959,37 +2762,39 @@ ferr: md->setLanguage(SrcLangExt_VHDL); md->setMemberSpecifiers(VhdlDocGen::INSTANTIATION); md->setBriefDescription(cur->brief,cur->briefFile,cur->briefLine); - md->setBodySegment(cur->startLine,-1) ; + md->setBodySegment(cur->startLine,cur->startLine,-1) ; md->setDocumentation(cur->doc.data(),cur->docFile.data(),cur->docLine); FileDef *fd=ar->getFileDef(); md->setBodyDef(fd); - - - QCString info="Info: Elaborating entity "+n1; - fd=ar->getFileDef(); - info+=" for hierarchy "; - QRegExp epr("[|]"); - QCString label=cur->type+":"+cur->write+":"+cur->name; - label.replace(epr,":"); - info+=label; - fprintf(stderr,"\n[%s:%d:%s]\n",fd->fileName().data(),cur->startLine,info.data()); - - + //QCString info="Info: Elaborating entity "+n1; + //fd=ar->getFileDef(); + //info+=" for hierarchy "; + //QRegExp epr("[|]"); + //QCString label=cur->type+":"+cur->write+":"+cur->name; + //label.replace(epr,":"); + //info+=label; + //fprintf(stderr,"\n[%s:%d:%s]\n",fd->fileName().data(),cur->startLine,info.data()); ar->insertMember(md); } -void VhdlDocGen::writeRecorUnit(QCString & largs,OutputList& ol ,const MemberDef *mdef) +void VhdlDocGen::writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDef *mdef) { - QCStringList ql=QCStringList::split("#",largs,FALSE); - uint len=ql.count(); - for(uint i=0;i<len;i++) - { - QCString n=ql[i]; - VhdlDocGen::formatString(n,ol,mdef); - if ((len-i)>1) ol.lineBreak(); - } + int i=mdef->name().find('~'); + if(i>0){ + //sets the real record member name + const_cast<MemberDef*>(mdef)->setName(mdef->name().left(i).data()); + } + + writeLink(mdef,ol); + ol.startBold(); + ol.insertMemberAlign(); + if (!ltype.isEmpty()){ + VhdlDocGen::formatString(ltype,ol,mdef); + } + ol.endBold(); + } @@ -3134,13 +2939,11 @@ void VhdlDocGen::createFlowChart(const MemberDef *mdef) bool b=readCodeFragment( fd->absFilePath().data(), actualStart,actualEnd,codeFragment); if (!b) return; - VHDLOutlineParser &intf =dynamic_cast<VHDLOutlineParser&>(Doxygen::parserManager->getOutlineParser(".vhd")); + auto parser { Doxygen::parserManager->getOutlineParser(".vhd") }; VhdlDocGen::setFlowMember(mdef); std::shared_ptr<Entry> root = std::make_shared<Entry>(); - QStrList filesInSameTu; - intf.startTranslationUnit(""); - intf.parseInput("",codeFragment.data(),root,FALSE,filesInSameTu); - intf.finishTranslationUnit(); + StringVector filesInSameTu; + parser->parseInput("",codeFragment.data(),root,nullptr); } void VhdlDocGen::resetCodeVhdlParserState() @@ -3369,20 +3172,18 @@ void FlowChart::printFlowTree() void FlowChart::colTextNodes() { - QCString text; - FlowChart *flno; + FlowChart *flno = NULL; bool found=FALSE; for (uint j=0;j<flowList.count();j++) { FlowChart *flo=flowList.at(j); if (flo->type&TEXT_NO) { - text+=flo->text+'\n'; if (!found) { flno=flo; } - if (found) + else { flno->text+=flo->text; flowList.remove(flo); @@ -3630,7 +3431,7 @@ void FlowChart::addFlowChart(int type,const char* text,const char* exp, const ch FlowChart *fl=new FlowChart(type,typeString.data(),expression.data(),label); - fl->line=vhdl::parser::VhdlParser::getLine(); + fl->line=1; // TODO: use getLine(); of the parser if (type & (START_NO | VARIABLE_NO)) { @@ -3722,12 +3523,11 @@ void FlowChart::printUmlTree() } qcs+="\n"; - QCString & htmlOutDir = Config_getString(HTML_OUTPUT); + QCString htmlOutDir = Config_getString(HTML_OUTPUT); QCString n=convertNameToFileName(); - QCString tmp=htmlOutDir; - n=PlantumlManager::instance()->writePlantUMLSource(tmp,n,qcs,PlantumlManager::PUML_SVG); - PlantumlManager::instance()->generatePlantUMLOutput(n.data(),tmp.data(),PlantumlManager::PUML_SVG); + n=PlantumlManager::instance()->writePlantUMLSource(htmlOutDir,n,qcs,PlantumlManager::PUML_SVG); + PlantumlManager::instance()->generatePlantUMLOutput(n,htmlOutDir,PlantumlManager::PUML_SVG); } QCString FlowChart::convertNameToFileName() @@ -3836,9 +3636,8 @@ void FlowChart::writeFlowChart() #ifdef DEBUGFLOW printFlowTree(); #endif - const MemberDef *p=VhdlDocGen::getFlowMember(); - if (p->isStatic()) + if (!Config_getString(PLANTUML_JAR_PATH).isEmpty()) { printUmlTree(); delFlowList(); @@ -3935,7 +3734,7 @@ void FlowChart::writeShape(FTextStream &t,const FlowChart* fl) else { if (fl->text.isEmpty()) return; - bool var=(fl->type & FlowChart::VARIABLE_NO); + bool isVar=(fl->type & FlowChart::VARIABLE_NO); QCString q=fl->text; if (exit) @@ -3951,7 +3750,7 @@ void FlowChart::writeShape(FTextStream &t,const FlowChart* fl) } t << "[shape=none margin=0.1, label=<\n"; t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n "; - if (var) + if (isVar) { t << "<TR><TD BGCOLOR=\"" << flowCol.varNode << "\" > "; } @@ -4014,7 +3813,7 @@ void FlowChart::writeEdge(FTextStream &t,int fl_from,int fl_to,int i,bool bFrom, void FlowChart::alignFuncProc( QCString & q,const ArgumentList &al,bool isFunc) { - int index=al.size(); + size_t index=al.size(); if (index==0) return; int len=q.length()+VhdlDocGen::getFlowMember()->name().length(); @@ -4095,7 +3894,7 @@ int FlowChart::findLabel(int index,QCString &label) return j; } } - err("could not find label: ",label.data()); + err("could not find label: %s",label.data()); return 0; } @@ -4310,5 +4109,3 @@ void FlowChart::writeFlowLinks(FTextStream &t) } } //for } //writeFlowLinks - - diff --git a/src/vhdldocgen.h b/src/vhdldocgen.h index 6203196..5442f88 100644 --- a/src/vhdldocgen.h +++ b/src/vhdldocgen.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,8 +16,8 @@ #ifndef VHDLDOCGEN_H #define VHDLDOCGEN_H -/** - * This class implements functions for parsing and generating +/** + * This class implements functions for parsing and generating * vhdl documents */ @@ -39,8 +39,35 @@ class FileDef; class NamespaceDef; struct Argument; + + +struct VhdlConfNode +{ + VhdlConfNode(const char* a,const char* b,const char* config,const char* cs,bool leaf) + { + arch=a; // architecture e.g. for iobuffer + arch=arch.lower(); + binding=b; // binding e.g. use entity work.xxx(bev) + binding=binding.lower(); + confVhdl=config; // configuration foo is bar + compSpec=cs; + isInlineConf=false; // primary configuration? + isLeaf=leaf; + }; + + QCString confVhdl; + QCString arch; + QCString binding; + QCString compSpec; + int level = 0; + bool isLeaf = false; + bool isInlineConf = false; + +}; + + /** Class for generating documentation specific for VHDL */ -class VhdlDocGen +class VhdlDocGen { public: @@ -71,11 +98,11 @@ class VhdlDocGen USE, PROCESS, PORT, - UNITS, + UNITS, GENERIC, INSTANTIATION, GROUP, - VFILE, + VFILE, SHAREDVARIABLE, CONFIG, ALIAS, @@ -88,7 +115,7 @@ class VhdlDocGen static void init(); static QCString convertFileNameToClassName(QCString name); // --- used by vhdlscanner.l ----------- - + static bool isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int level); static QCString getIndexWord(const char* ,int index); @@ -105,7 +132,7 @@ class VhdlDocGen static QCString* findKeyWord(const QCString& word); static ClassDef* getPackageName(const QCString& name); - static MemberDef* findMember(const QCString& className, + static MemberDef* findMember(const QCString& className, const QCString& memName); static void findAllPackages(ClassDef*); static MemberDef* findMemberDef(ClassDef* cd, @@ -180,19 +207,18 @@ class VhdlDocGen static QCString convertArgumentListToString(const ArgumentList &al,bool f); static QCString getProcessNumber(); static QCString getRecordNumber(); - + static QCString getClassName(const ClassDef*); static bool isNumber(const QCString& s); static QCString getProtectionName(int prot); static void parseUCF(const char* input,Entry* entity,QCString f,bool vendor); - static bool findConstraintFile( LayoutNavEntry *lne); static ClassDef* findArchitecture(const ClassDef *cd); static ClassDef* findArchitecture(QCString identifier, QCString entity_name); static void correctMemberProperties(MemberDef *md); - + static void writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname); static QCString parseForConfig(QCString & entity,QCString & arch); @@ -202,15 +228,15 @@ class VhdlDocGen static void writeOverview(OutputList &ol); static void writeOverview(); - + // flowcharts static void createFlowChart(const MemberDef*); //static void addFlowImage(const FTextStream &,const QCString &); - + static void setFlowMember( const MemberDef *flowMember); static const MemberDef *getFlowMember(); - static bool isVhdlClass (const Entry *cu) + static bool isVhdlClass (const Entry *cu) { return cu->spec==VhdlDocGen::ENTITY || cu->spec==VhdlDocGen::PACKAGE || @@ -226,7 +252,7 @@ class VhdlDocGen static void writeVhdlLink(const ClassDef* cdd ,OutputList& ol,QCString& type,QCString& name,QCString& beh); static void writeStringLink(const MemberDef *mdef,QCString mem,OutputList& ol); static void writeRecUnitDocu( const MemberDef *md, OutputList& ol,QCString largs); - static void writeRecorUnit(QCString & largs,OutputList& ol ,const MemberDef *mdef); + static void writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDef *mdef); }; //------------------------------------------------------------------------------------------------------------------- @@ -263,7 +289,7 @@ class FlowChart BEGIN_NO = 1<<21 }; - //---------- create svg ------------------------------------------------------------- + //---------- create svg ------------------------------------------------------------- static void createSVG(); static void startDot(FTextStream &t); static void endDot(FTextStream &t); diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 5dfa9f6..7c83d52 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -13,8 +13,8 @@ #include <qcstring.h> #include <qfileinfo.h> #include <qcstringlist.h> +#include "containers.h" #include "vhdljjparser.h" -#include "vhdlcode.h" #include "vhdldocgen.h" #include "message.h" #include "config.h" @@ -28,205 +28,233 @@ #include "outputlist.h" #include "arguments.h" #include "types.h" -#include "VhdlParserIF.h" #include "growbuf.h" +#include "markdown.h" +#include "VhdlParserTokenManager.h" +#include "VhdlParserErrorHandler.hpp" using namespace vhdl::parser; -using namespace std; -static OutlineParserInterface *g_thisParser; - -static QCString yyFileName; -static int yyLineNr = 1; -static int* lineParse; -static int iDocLine = -1; -static QCString inputString; -static Entry* gBlock = 0; -static Entry* previous = 0; -//------------------------------------------------------- +struct VHDLDocInfo +{ + QCString doc; + bool brief; + bool pending = false; + int iDocLine = 1; +}; -static Entry* oldEntry; -static bool varr=FALSE; -static QCString varName; -static std::vector< std::shared_ptr<Entry> > instFiles; -static std::vector< std::shared_ptr<Entry> > libUse; -static std::vector<Entry*> lineEntry; +static bool isConstraintFile(const QCString &fileName,const QCString &ext) +{ + return fileName.right(ext.length())==ext; +} -Entry* VhdlParser::tempEntry=0; -Entry* VhdlParser::lastEntity=0 ; -Entry* VhdlParser::lastCompound=0 ; -Entry* VhdlParser::current_root = 0; -std::shared_ptr<Entry> VhdlParser::current=0; -QCString VhdlParser::compSpec; -QCString VhdlParser::currName; -QCString VhdlParser::confName; -QCString VhdlParser::genLabels; -QCString VhdlParser::lab; -QCString VhdlParser::forL; -int VhdlParser::param_sec = 0; -int VhdlParser::parse_sec=0; -int VhdlParser::currP=0; -int VhdlParser::levelCounter; +//------------------------------------- -static QList<VhdlConfNode> configL; +static EntryList g_instFiles; -static struct +struct VHDLOutlineParser::Private { - QCString doc; - bool brief; - bool pending; - int iDocLine; -} str_doc; + void parseVhdlfile(const char *fileName,const char* inputBuffer,bool inLine); -static QCString strComment; -static int iCodeLen; -static const char *vhdlFileName = 0; + VHDLOutlineParser *thisParser = 0; + VhdlParser *vhdlParser = 0; + CommentScanner commentScanner; -static bool checkMultiComment(QCString& qcs,int line); -static void insertEntryAtLine(const Entry* ce,int line); - -//------------------------------------- + QCString yyFileName; + int yyLineNr = 1; + IntVector lineParse; + int iDocLine = -1; + QCString inputString; + Entry* gBlock = 0; + Entry* previous = 0; +//------------------------------------------------------- -const QList<VhdlConfNode>& getVhdlConfiguration() { return configL; } -const std::vector<std::shared_ptr<Entry> > &getVhdlInstList() { return instFiles; } + Entry* oldEntry = 0; + bool varr = FALSE; + QCString varName; + EntryList libUse; + EntryList lineEntry; + QCString strComment; + int iCodeLen; + VHDLDocInfo str_doc; + VhdlParser::SharedState shared; + QCString forL; + int code = 0; + +}; + +void VHDLOutlineParser::Private::parseVhdlfile(const char *fileName, + const char* inputBuffer,bool inLine) +{ + JAVACC_STRING_TYPE s =inputBuffer; + CharStream *stream = new CharStream(s.c_str(), (int)s.size(), 1, 1); + VhdlParserTokenManager *tokenManager = new VhdlParserTokenManager(stream); + VhdlTokenManagerErrorHandler *tokErrHandler=new VhdlTokenManagerErrorHandler(fileName); + vhdlParser=new VhdlParser(tokenManager); + vhdlParser->setOutlineParser(thisParser); + vhdlParser->setSharedState(&shared); + tokenManager->setLexParser(vhdlParser); + tokenManager->ReInit(stream,0); + tokenManager->setErrorHandler(tokErrHandler); + VhdlErrorHandler *parserErrHandler=new VhdlErrorHandler(fileName); + vhdlParser->setErrorHandler(parserErrHandler); + try + { + if(inLine) + { + vhdlParser->parseInline(); + } + else + { + vhdlParser->design_file(); + } + } + catch( std::exception &){ /* fprintf(stderr,"\n[%s]",e.what()); */ } + // fprintf(stderr,"\n\nparsed lines: %d\n",yyLineNr); + // fprintf(stderr,"\n\nerrors : %d\n\n",myErr->getErrorCount()); + delete vhdlParser; +} -Entry* getVhdlCompound() +VHDLOutlineParser::VHDLOutlineParser() : p(std::make_unique<Private>()) { - if (VhdlParser::lastEntity) return VhdlParser::lastEntity; - if (VhdlParser::lastCompound) return VhdlParser::lastCompound; - return NULL; } -bool isConstraintFile(const QCString &fileName,const QCString &ext) +VHDLOutlineParser::~VHDLOutlineParser() { - return fileName.right(ext.length())==ext; } - void VHDLOutlineParser::parseInput(const char *fileName,const char *fileBuf, - const std::shared_ptr<Entry> &root, bool ,QStrList&) + const std::shared_ptr<Entry> &root, ClangTUParser *) { - g_thisParser=this; - bool inLine=false; - inputString=fileBuf; + VhdlParser::SharedState *s = &p->shared; + p->thisParser=this; + p->inputString=fileBuf; // fprintf(stderr,"\n ============= %s\n ==========\n",fileBuf); - if (strlen(fileName)==0) - { - inLine=true; - } + bool inLine = (fileName==0 || strlen(fileName)==0); - yyFileName+=fileName; + p->yyFileName=fileName; - bool xilinx_ucf=isConstraintFile(yyFileName,".ucf"); - bool altera_qsf=isConstraintFile(yyFileName,".qsf"); + bool xilinx_ucf=isConstraintFile(p->yyFileName,".ucf"); + bool altera_qsf=isConstraintFile(p->yyFileName,".qsf"); // support XILINX(ucf) and ALTERA (qsf) file if (xilinx_ucf) { - VhdlDocGen::parseUCF(fileBuf,root.get(),yyFileName,FALSE); + VhdlDocGen::parseUCF(fileBuf,root.get(),p->yyFileName,FALSE); return; } if (altera_qsf) { - VhdlDocGen::parseUCF(fileBuf,root.get(),yyFileName,TRUE); + VhdlDocGen::parseUCF(fileBuf,root.get(),p->yyFileName,TRUE); return; } - yyLineNr=1; - VhdlParser::current_root=root.get(); - VhdlParser::lastCompound=0; - VhdlParser::lastEntity=0; - VhdlParser::lastEntity=0; - oldEntry = 0; - VhdlParser::current=std::make_shared<Entry>(); - VhdlParser::initEntry(VhdlParser::current.get()); - Doxygen::docGroup.enterFile(fileName,yyLineNr); - vhdlFileName = fileName; - lineParse=new int[200]; // Dimitri: dangerous constant: should be bigger than largest token id in VhdlParserConstants.h - VhdlParserIF::parseVhdlfile(fileBuf,inLine); - - VhdlParser::current.reset(); + p->yyLineNr=1; + s->current_root=root; + s->lastCompound=0; + s->lastEntity=0; + s->lastEntity=0; + p->oldEntry = 0; + s->current=std::make_shared<Entry>(); + initEntry(s->current.get()); + p->commentScanner.enterFile(fileName,p->yyLineNr); + p->lineParse.reserve(200); + p->parseVhdlfile(fileName,fileBuf,inLine); + p->commentScanner.leaveFile(fileName,p->yyLineNr); + + s->current.reset(); if (!inLine) - VhdlParser::mapLibPackage(root.get()); + mapLibPackage(root.get()); - delete[] lineParse; - yyFileName.resize(0); - libUse.clear(); - VhdlDocGen::resetCodeVhdlParserState(); - vhdlFileName = 0; + p->yyFileName.resize(0); + p->libUse.clear(); } -void VhdlParser::lineCount() +void VHDLOutlineParser::lineCount() { - yyLineNr++; + p->yyLineNr++; } -void VhdlParser::lineCount(const char* text) +void VHDLOutlineParser::lineCount(const char* text) { for (const char* c=text ; *c ; ++c ) { - if (*c == '\n') yyLineNr++; + if (*c == '\n') p->yyLineNr++; } } -void isVhdlDocPending() +void VHDLOutlineParser::initEntry(Entry *e) { - if (!str_doc.pending) return; - - str_doc.pending=FALSE; - oldEntry=0; // prevents endless recursion - iDocLine=str_doc.iDocLine; - VhdlParser::handleCommentBlock(str_doc.doc,str_doc.brief); - iDocLine=-1; -} - -void VhdlParser::initEntry(Entry *e) -{ - e->fileName = yyFileName; + e->fileName = p->yyFileName; e->lang = SrcLangExt_VHDL; - isVhdlDocPending(); - Doxygen::docGroup.initGroupInfo(e); + if (p->str_doc.pending) + { + p->str_doc.pending=FALSE; + p->oldEntry=0; // prevents endless recursion + p->iDocLine=p->str_doc.iDocLine; + handleCommentBlock(p->str_doc.doc,p->str_doc.brief); + p->iDocLine=-1; + } + p->commentScanner.initGroupInfo(e); } -void VhdlParser::newEntry() +void VHDLOutlineParser::newEntry() { - previous = current.get(); - if (current->spec==VhdlDocGen::ENTITY || - current->spec==VhdlDocGen::PACKAGE || - current->spec==VhdlDocGen::ARCHITECTURE || - current->spec==VhdlDocGen::PACKAGE_BODY) + VhdlParser::SharedState *s = &p->shared; + p->previous = s->current.get(); + if (s->current->spec==VhdlDocGen::ENTITY || + s->current->spec==VhdlDocGen::PACKAGE || + s->current->spec==VhdlDocGen::ARCHITECTURE || + s->current->spec==VhdlDocGen::PACKAGE_BODY) { - current_root->moveToSubEntryAndRefresh(current); + s->current_root->moveToSubEntryAndRefresh(s->current); } else { - if (lastCompound) + if (s->lastCompound) { - lastCompound->moveToSubEntryAndRefresh(current); + s->lastCompound->moveToSubEntryAndRefresh(s->current); } else { - if (lastEntity) + if (s->lastEntity) { - lastEntity->moveToSubEntryAndRefresh(current); + s->lastEntity->moveToSubEntryAndRefresh(s->current); } else { - current_root->moveToSubEntryAndRefresh(current); + s->current_root->moveToSubEntryAndRefresh(s->current); } } } - initEntry(current.get()); + initEntry(s->current.get()); +} + +static int idCounter; + +/** returns a unique id for each record member. +* +* type first_rec is record +* RE: data_type; +* end; +* +* type second_rec is record +* RE: data_type; +* end; +*/ + +QString VHDLOutlineParser::getNameID(){ + return QString::number(idCounter++,10); } -void VhdlParser::handleFlowComment(const char* doc) +void VHDLOutlineParser::handleFlowComment(const char* doc) { - lineCount(doc); + lineCount(doc); if (VhdlDocGen::getFlowMember()) { @@ -237,127 +265,217 @@ void VhdlParser::handleFlowComment(const char* doc) } } +int VHDLOutlineParser::checkInlineCode(QCString &doc) +{ + QRegExp cs("[\\\\@]code"); + QRegExp cend("[\\s ]*[\\\\@]endcode"); + QRegExp cbrief("[\\\\@]brief"); + int index = doc.find(cs); + + if (doc.contains(cend) > 0) + return 1; + + if (index < 0) + return index; + + VhdlParser::SharedState *s = &p->shared; + p->strComment += doc; + p->code = p->inputString.find(cs, p->code + 1); + int com = p->inputString.find(p->strComment.data()); + int ref = p->inputString.find(cend, p->code + 1); + int len = p->strComment.size(); + + int ll = com + len; + int diff = ref - ll - 3; + QCString code = p->inputString.mid(ll, diff); + int iLine = 0; + code = stripLeadingAndTrailingEmptyLines(code, iLine); + int val = code.contains('\n'); + VhdlDocGen::prepareComment(p->strComment); + QCStringList ql = QCStringList::split('\n', p->strComment); + + QCString co; + QCString na; + for (QCString qcs : ql) + { + qcs = qcs.simplifyWhiteSpace(); + if (qcs.contains(cs)) + { + int i = qcs.find('{'); + int j = qcs.find('}'); + if (i > 0 && j > 0 && j > i) + { + na = qcs.mid(i + 1, (j - i - 1)); + } + continue; + } + qcs = qcs.replace(cbrief, ""); + co += qcs; + co += '\n'; + } + + VhdlDocGen::prepareComment(co); + + Entry gBlock; + if (!na.isEmpty()) + gBlock.name = na; + else + gBlock.name = "misc" + VhdlDocGen::getRecordNumber(); + gBlock.startLine = p->yyLineNr+iLine-1; + gBlock.bodyLine = p->yyLineNr+iLine-1 ; + gBlock.doc = code; + gBlock.inbodyDocs = code; + gBlock.brief = co; + gBlock.section = Entry::VARIABLE_SEC; + gBlock.spec = VhdlDocGen::MISCELLANEOUS; + gBlock.fileName = p->yyFileName; + gBlock.endBodyLine = p->yyLineNr + val +iLine; + gBlock.lang = SrcLangExt_VHDL; + std::shared_ptr<Entry> compound; + + if (s->lastEntity) + compound = s->lastEntity; + else if (s->lastCompound) + compound = s->lastCompound; + else + compound = 0; + + if (compound) + { + compound->copyToSubEntry(&gBlock); + } + else + { + gBlock.type = "misc"; // global code like library ieee... + s->current_root->copyToSubEntry(&gBlock); + } + p->strComment.resize(0); + return 1; +} -void VhdlParser::handleCommentBlock(const char* doc1,bool brief) +void VHDLOutlineParser::handleCommentBlock(const char *doc1, bool brief) { - QCString doc; - doc.append(doc1); - // fprintf(stderr,"\n %s",doc.data()); - if (doc.isEmpty()) return; + int position = 0; + bool needsEntry = FALSE; + VhdlParser::SharedState *s = &p->shared; + QCString doc = doc1; - if (checkMultiComment(doc,yyLineNr)) + if (doc.isEmpty()) + return; + + if (checkMultiComment(doc, p->yyLineNr)) { - strComment.resize(0); + p->strComment.resize(0); return; } - VhdlDocGen::prepareComment(doc); + if (checkInlineCode(doc) > 0) + { + return; + } - Protection protection=Public; + Protection protection = Public; + VhdlDocGen::prepareComment(doc); - if (oldEntry==current.get()) + if (p->oldEntry == s->current.get()) { - //printf("\n find pending message < %s > at line: %d \n ",doc.data(),iDocLine); - str_doc.doc=doc; - str_doc.iDocLine=iDocLine; - str_doc.brief=brief; - str_doc.pending=TRUE; + p->str_doc.doc = doc; + p->str_doc.iDocLine = p->iDocLine; + p->str_doc.brief = brief; + p->str_doc.pending = TRUE; return; } - oldEntry=current.get(); + p->oldEntry = s->current.get(); if (brief) { - current->briefLine = yyLineNr; + s->current->briefLine = p->yyLineNr; } else { - current->docLine = yyLineNr; + s->current->docLine = p->yyLineNr; } - // printf("parseCommentBlock file<%s>\n [%s]\n at line [%d] \n ",yyFileName.data(),doc.data(),iDocLine); - int j=doc.find("[plant]"); - if (j>=0) - { - doc=doc.remove(j,7); - current->stat=true; - } - int position=0; - bool needsEntry=FALSE; - QCString processedDoc = preprocessCommentBlock(doc,yyFileName,iDocLine); - while (parseCommentBlock( - g_thisParser, - current.get(), - processedDoc, // text - yyFileName, // file - iDocLine, // line of block start - brief, - 0, - FALSE, - protection, - position, - needsEntry - ) - ) + + Markdown markdown(p->yyFileName,p->iDocLine); + int lineNr = p->iDocLine; + QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc,lineNr) : doc; + + while (p->commentScanner.parseCommentBlock( + p->thisParser, + s->current.get(), + processedDoc, // text + p->yyFileName, // file + lineNr, // line of block start + brief, + 0, + FALSE, + protection, + position, + needsEntry, + Config_getBool(MARKDOWN_SUPPORT))) { - //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position); - if (needsEntry) newEntry(); + if (needsEntry) + newEntry(); } if (needsEntry) { - if (varr) + if (p->varr) { - varr=FALSE; - current->name=varName; - current->section=Entry::VARIABLEDOC_SEC; - varName=""; + p->varr = FALSE; + s->current->name = p->varName; + s->current->section = Entry::VARIABLEDOC_SEC; + p->varName = ""; } newEntry(); } - iDocLine=-1; - strComment.resize(0); + p->iDocLine = -1; + p->strComment.resize(0); } void VHDLOutlineParser::parsePrototype(const char *text) { - varName=text; - varr=TRUE; + p->varName=text; + p->varr=TRUE; } -void VhdlParser::addCompInst(const char *n, const char* instName, const char* comp,int iLine) +void VHDLOutlineParser::addCompInst(const char *n, const char* instName, const char* comp,int iLine) { - current->spec=VhdlDocGen::INSTANTIATION; - current->section=Entry::VARIABLE_SEC; - current->startLine=iLine; - current->bodyLine=iLine; - current->type=instName; // foo:instname e.g proto or work. proto(ttt) - current->exception=genLabels.lower(); // |arch|label1:label2... - current->name=n; // foo - if (lastCompound) + VhdlParser::SharedState *s = &p->shared; + s->current->spec=VhdlDocGen::INSTANTIATION; + s->current->section=Entry::VARIABLE_SEC; + s->current->startLine=iLine; + s->current->bodyLine=iLine; + s->current->type=instName; // foo:instname e.g proto or work. proto(ttt) + s->current->exception=s->genLabels.lower(); // |arch|label1:label2... + s->current->name=n; // foo + if (s->lastCompound) { - current->args=lastCompound->name; // architecture name + s->current->args=s->lastCompound->name; // architecture name } - current->includeName=comp; // component/entity/configuration - int u=genLabels.find("|",1); + s->current->includeName=comp; // component/entity/configuration + int u=s->genLabels.find("|",1); if (u>0) { - current->write=genLabels.right(genLabels.length()-u); - current->read=genLabels.left(u); + s->current->write=s->genLabels.right(s->genLabels.length()-u); + s->current->read=s->genLabels.left(u); } //printf (" \n genlabel: [%s] inst: [%s] name: [%s] %d\n",n,instName,comp,iLine); - if (lastCompound) + if (s->lastCompound) { - current->args=lastCompound->name; + s->current->args=s->lastCompound->name; if (true) // !findInstant(current->type)) { - initEntry(current.get()); - instFiles.emplace_back(std::make_shared<Entry>(*current)); + initEntry(s->current.get()); + // TODO: protect with mutex + g_instFiles.emplace_back(std::make_shared<Entry>(*s->current)); + // TODO: end protect with mutex } - current=std::make_shared<Entry>(); + s->current=std::make_shared<Entry>(); } else { @@ -365,13 +483,14 @@ void VhdlParser::addCompInst(const char *n, const char* instName, const char* co } } -void VhdlParser::addVhdlType(const char *n,int startLine,int section, +void VHDLOutlineParser::addVhdlType(const char *n,int startLine,int section, uint64 spec,const char* args,const char* type,Protection prot) { + VhdlParser::SharedState *s = &p->shared; QCString name(n); if (isFuncProcProced() || VhdlDocGen::getFlowMember()) return; - if (parse_sec==GEN_SEC) + if (s->parse_sec==GEN_SEC) { spec= VhdlDocGen::GENERIC; } @@ -380,61 +499,62 @@ void VhdlParser::addVhdlType(const char *n,int startLine,int section, for (uint u=0;u<ql.count();u++) { - current->name=ql[u]; - current->startLine=startLine; - current->bodyLine=startLine; - current->section=section; - current->spec=spec; - current->fileName=yyFileName; - if (current->args.isEmpty()) + s->current->name=ql[u]; + s->current->startLine=startLine; + s->current->bodyLine=startLine; + s->current->section=section; + s->current->spec=spec; + s->current->fileName=p->yyFileName; + if (s->current->args.isEmpty()) { - current->args=args; + s->current->args=args; } - current->type=type; - current->protection=prot; + s->current->type=type; + s->current->protection=prot; - if (!lastCompound && (section==Entry::VARIABLE_SEC) && (spec == VhdlDocGen::USE || spec == VhdlDocGen::LIBRARY) ) + if (!s->lastCompound && (section==Entry::VARIABLE_SEC) && (spec == VhdlDocGen::USE || spec == VhdlDocGen::LIBRARY) ) { - libUse.emplace_back(std::make_shared<Entry>(*current)); - current->reset(); + p->libUse.emplace_back(std::make_shared<Entry>(*s->current)); + s->current->reset(); } newEntry(); } } -void VhdlParser::createFunction(const char *imp,uint64 spec,const char *fn) +void VHDLOutlineParser::createFunction(const char *imp,uint64 spec,const char *fn) { + VhdlParser::SharedState *s = &p->shared; QCString impure(imp); QCString fname(fn); - current->spec=spec; - current->section=Entry::FUNCTION_SEC; + s->current->spec=spec; + s->current->section=Entry::FUNCTION_SEC; if (impure=="impure" || impure=="pure") { - current->exception=impure; + s->current->exception=impure; } - if (parse_sec==GEN_SEC) + if (s->parse_sec==GEN_SEC) { - current->spec= VhdlDocGen::GENERIC; - current->section=Entry::FUNCTION_SEC; + s->current->spec= VhdlDocGen::GENERIC; + s->current->section=Entry::FUNCTION_SEC; } - if (currP==VhdlDocGen::PROCEDURE) + if (s->currP==VhdlDocGen::PROCEDURE) { - current->name=impure; - current->exception=""; + s->current->name=impure; + s->current->exception=""; } else { - current->name=fname; + s->current->name=fname; } if (spec==VhdlDocGen::PROCESS) { - current->args=fname; - current->name=impure; - VhdlDocGen::deleteAllChars(current->args,' '); + s->current->args=fname; + s->current->name=impure; + VhdlDocGen::deleteAllChars(s->current->args,' '); if (!fname.isEmpty()) { QCStringList q1=QCStringList::split(",",fname); @@ -442,19 +562,19 @@ void VhdlParser::createFunction(const char *imp,uint64 spec,const char *fn) { Argument arg; arg.name=q1[ii]; - current->argList.push_back(arg); + s->current->argList.push_back(arg); } } - return; } - } +} -bool VhdlParser::isFuncProcProced() +bool VHDLOutlineParser::isFuncProcProced() { - if (currP==VhdlDocGen::FUNCTION || - currP==VhdlDocGen::PROCEDURE || - currP==VhdlDocGen::PROCESS + VhdlParser::SharedState *s = &p->shared; + if (s->currP==VhdlDocGen::FUNCTION || + s->currP==VhdlDocGen::PROCEDURE || + s->currP==VhdlDocGen::PROCESS ) { return TRUE; @@ -462,13 +582,13 @@ bool VhdlParser::isFuncProcProced() return FALSE; } -void VhdlParser::pushLabel( QCString &label,QCString & val) +void VHDLOutlineParser::pushLabel( QCString &label,QCString & val) { label+="|"; label+=val; } - QCString VhdlParser::popLabel(QCString & q) +QCString VHDLOutlineParser::popLabel(QCString & q) { int i=q.findRev("|"); if (i<0) return ""; @@ -476,63 +596,12 @@ void VhdlParser::pushLabel( QCString &label,QCString & val) return q; } -void VhdlParser::addConfigureNode(const char* a,const char*b, bool,bool isLeaf,bool inlineConf) -{ - VhdlConfNode* co=0; - QCString ent; - ent=a; - - if (b) - { - ent=b; - } - int level=0; - - if (!configL.isEmpty()) - { - VhdlConfNode* vc=configL.getLast(); - level=vc->level; - if (levelCounter==0) - { - pushLabel(forL,ent); - } - else if (level<levelCounter) - { - if (!isLeaf) - { - pushLabel(forL,ent); - } - } - else if (level>levelCounter) - { - forL=popLabel(forL); - } - } - else - { - pushLabel(forL,ent); - } - - if (inlineConf) - { - confName=lastCompound->name; - } - - //fprintf(stderr,"\n[%s %d %d]\n",forL.data(),levelCounter,level); - co=new VhdlConfNode(a,b,confName.lower().data(),forL.lower().data(),isLeaf); - - if (inlineConf) - { - co->isInlineConf=TRUE; - } - - configL.append(co); -} -void VhdlParser::addProto(const char *s1,const char *s2,const char *s3, +void VHDLOutlineParser::addProto(const char *s1,const char *s2,const char *s3, const char *s4,const char *s5,const char *s6) { + VhdlParser::SharedState *s = &p->shared; (void)s5; // avoid unused warning QCString name=s2; QCStringList ql=QCStringList::split(",",name); @@ -551,12 +620,12 @@ void VhdlParser::addProto(const char *s1,const char *s2,const char *s3, { arg.type+=s6; } - if (parse_sec==GEN_SEC && param_sec==0) + if (s->parse_sec==GEN_SEC && s->param_sec==0) { arg.defval="gen!"; } - if (parse_sec==PARAM_SEC) + if (s->parse_sec==PARAM_SEC) { // assert(false); } @@ -564,9 +633,9 @@ void VhdlParser::addProto(const char *s1,const char *s2,const char *s3, arg.defval+=s1; arg.attrib="";//s6; - current->argList.push_back(arg); - current->args+=s2; - current->args+=","; + s->current->argList.push_back(arg); + s->current->args+=s2; + s->current->args+=","; } } @@ -582,13 +651,13 @@ void VhdlParser::addProto(const char *s1,const char *s2,const char *s3, * ..... * and so on.. */ -void VhdlParser::mapLibPackage( Entry* root) +void VHDLOutlineParser::mapLibPackage( Entry* root) { //QList<Entry> epp=libUse; //EntryListIterator eli(epp); //Entry *rt; //for (;(rt=eli.current());++eli) - for (const auto &rt : libUse) + for (const auto &rt : p->libUse) { if (addLibUseClause(rt->name)) { @@ -613,7 +682,7 @@ void VhdlParser::mapLibPackage( Entry* root) }// for }//MapLib -bool VhdlParser::addLibUseClause(const QCString &type) +bool VHDLOutlineParser::addLibUseClause(const QCString &type) { static bool showIEEESTD=Config_getBool(FORCE_LOCAL_INCLUDES); @@ -625,48 +694,50 @@ bool VhdlParser::addLibUseClause(const QCString &type) return TRUE; } -int VhdlParser::getLine() +int VHDLOutlineParser::getLine() { - return yyLineNr; + return p->yyLineNr; } -void VhdlParser::setLineParsed(int tok) +void VHDLOutlineParser::setLineParsed(int tok) { - lineParse[tok]=yyLineNr; + if ((int)p->lineParse.size()<=tok) p->lineParse.resize(tok+1); + p->lineParse[tok]=p->yyLineNr; } -int VhdlParser::getLine(int tok) +int VHDLOutlineParser::getLine(int tok) { - int val=lineParse[tok]; + int val=p->lineParse[tok]; if (val<0) val=0; //assert(val>=0 && val<=yyLineNr); return val; } -void VhdlParser::createFlow() +void VHDLOutlineParser::createFlow() { + VhdlParser::SharedState *s = &p->shared; if (!VhdlDocGen::getFlowMember()) { return; } QCString q,ret; - if (currP==VhdlDocGen::FUNCTION) + if (s->currP==VhdlDocGen::FUNCTION) { q=":function( "; - FlowChart::alignFuncProc(q,tempEntry->argList,true); + FlowChart::alignFuncProc(q,s->tempEntry->argList,true); q+=")"; } - else if (currP==VhdlDocGen::PROCEDURE) + else if (s->currP==VhdlDocGen::PROCEDURE) { q=":procedure ("; - FlowChart::alignFuncProc(q,tempEntry->argList,false); + FlowChart::alignFuncProc(q,s->tempEntry->argList,false); q+=")"; } else { - q=":process( "+tempEntry->args; + q=":process( "+s->tempEntry->args; q+=")"; } @@ -674,11 +745,11 @@ void VhdlParser::createFlow() FlowChart::addFlowChart(FlowChart::START_NO,q,0); - if (currP==VhdlDocGen::FUNCTION) + if (s->currP==VhdlDocGen::FUNCTION) { ret="end function "; } - else if (currP==VhdlDocGen::PROCEDURE) + else if (s->currP==VhdlDocGen::PROCEDURE) { ret="end procedure"; } @@ -690,60 +761,79 @@ void VhdlParser::createFlow() FlowChart::addFlowChart(FlowChart::END_NO,ret,0); // FlowChart::printFlowList(); FlowChart::writeFlowChart(); - currP=0; + s->currP=0; } -void VhdlParser::setMultCommentLine() +void VHDLOutlineParser::setMultCommentLine() { - iDocLine=yyLineNr; + p->iDocLine=p->yyLineNr; } -void VhdlParser::oneLineComment(QCString qcs) +void VHDLOutlineParser::oneLineComment(QCString qcs) { int j=qcs.find("--!"); qcs=qcs.right(qcs.length()-3-j); - if (!checkMultiComment(qcs,iDocLine)) + if (!checkMultiComment(qcs,p->iDocLine)) { handleCommentBlock(qcs,TRUE); } } -bool checkMultiComment(QCString& qcs,int line) +bool VHDLOutlineParser::checkMultiComment(QCString& qcs,int line) { - insertEntryAtLine(VhdlParser::current_root,line); + VhdlParser::SharedState *s = &p->shared; + insertEntryAtLine(s->current_root,line); - if (lineEntry.empty()) return false; + if (p->lineEntry.empty()) return false; VhdlDocGen::prepareComment(qcs); - while (!lineEntry.empty()) + while (!p->lineEntry.empty()) { - Entry *e=lineEntry.back(); + std::shared_ptr<Entry> e=p->lineEntry.back(); e->briefLine=line; e->brief+=qcs; - lineEntry.pop_back(); + p->lineEntry.pop_back(); } return true; } // returns the vhdl parsed types at line xxx -void insertEntryAtLine(const Entry* ce,int line) +void VHDLOutlineParser::insertEntryAtLine(std::shared_ptr<Entry> ce,int line) { for (const auto &rt : ce->children()) { if (rt->bodyLine==line) { - lineEntry.push_back(rt.get()); + p->lineEntry.push_back(rt); } - insertEntryAtLine(rt.get(),line); + insertEntryAtLine(rt,line); } } -const char *getVhdlFileName(void) +const EntryList &getVhdlInstList() { - return vhdlFileName; + return g_instFiles; +} + +void VHDLOutlineParser::error_skipto(int kind) +{ + Token *op; + do + { + p->vhdlParser->getNextToken(); // step to next token + op=p->vhdlParser->getToken(1); // get first token + if (op==0) break; + //fprintf(stderr,"\n %s",t->image.data()); + } while (op->kind != kind); + p->vhdlParser->clearError(); + // The above loop consumes tokens all the way up to a token of + // "kind". We use a do-while loop rather than a while because the + // current token is the one immediately before the erroneous token + // (in our case the token immediately before what should have been + // "if"/"while". } QCString filter2008VhdlComment(const char *s) diff --git a/src/vhdljjparser.h b/src/vhdljjparser.h index f3e7d70..651221c 100644..100755 --- a/src/vhdljjparser.h +++ b/src/vhdljjparser.h @@ -18,22 +18,10 @@ #include "types.h" #include "entry.h" #include "vhdldocgen.h" -#include "vhdlcode.h" -#include "memberlist.h" #include "config.h" - - - enum { GEN_SEC=0x1, PARAM_SEC,CONTEXT_SEC,PROTECTED_SEC } ; -void parserVhdlfile(const char* inputBuffer); - -class Entry; -class ClassSDict; -class ClassDef; -class MemberDef; -struct VhdlConfNode; - +//void parserVhdlfile(const char* inputBuffer); /** \brief VHDL parser using state-based lexical scanning. * @@ -42,46 +30,54 @@ struct VhdlConfNode; class VHDLOutlineParser : public OutlineParserInterface { public: - virtual ~VHDLOutlineParser() {} - void startTranslationUnit(const char *) {} - void finishTranslationUnit() {} + VHDLOutlineParser(); + virtual ~VHDLOutlineParser(); void parseInput(const char * fileName, const char *fileBuf, const std::shared_ptr<Entry> &root, - bool sameTranslationUnit, - QStrList &filesInSameTranslationUnit); + ClangTUParser *clangParser); bool needsPreprocessing(const QCString &) const { return TRUE; } void parsePrototype(const char *text); -}; - -struct VhdlConfNode -{ - VhdlConfNode(const char* a,const char* b,const char* config,const char* cs,bool leaf) - { - arch=a; // architecture e.g. for iobuffer - arch=arch.lower(); - binding=b; // binding e.g. use entity work.xxx(bev) - binding=binding.lower(); - confVhdl=config; // configuration foo is bar - compSpec=cs; - isInlineConf=false; // primary configuration? - isLeaf=leaf; - }; - QCString confVhdl; - QCString arch; - QCString binding; - QCString compSpec; - int level = 0; - bool isLeaf = false; - bool isInlineConf = false; + // interface for generated parser code + + void setLineParsed(int tok); + int getLine(int tok); + int getLine(); + void lineCount(const char*); + void lineCount(); + void addProto(const char *s1,const char *s2,const char *s3,const char *s4,const char *s5,const char *s6); + //void addConfigureNode(const char* a,const char*b, bool,bool isLeaf,bool inlineConf); + void createFunction(const char *impure,uint64 spec,const char *fname); + void addVhdlType(const char *n,int startLine,int section, uint64 spec,const char* args,const char* type,Protection prot); + void addCompInst(const char *n, const char* instName, const char* comp,int iLine); + void handleCommentBlock(const char* doc,bool brief); + void handleFlowComment(const char*); + void initEntry(Entry *e); + void newEntry(); + bool isFuncProcProced(); + void pushLabel(QCString &,QCString&); + QCString popLabel(QCString & q); + bool addLibUseClause(const QCString &type); + void mapLibPackage( Entry* root); + void createFlow(); + void error_skipto(int kind); + void oneLineComment(QCString qcs); + void setMultCommentLine(); + bool checkMultiComment(QCString& qcs,int line); + void insertEntryAtLine(std::shared_ptr<Entry> ce,int line); + QString getNameID(); + int checkInlineCode(QCString & doc); + private: + struct Private; + std::unique_ptr<Private> p; }; -void vhdlscanFreeScanner(); -const QList<VhdlConfNode>& getVhdlConfiguration(); -const std::vector<std::shared_ptr<Entry> >&getVhdlInstList(); +const EntryList &getVhdlInstList(); + QCString filter2008VhdlComment(const char *s); + #endif diff --git a/src/xmlcode.l b/src/xmlcode.l index 94548f8..b583bf5 100644 --- a/src/xmlcode.l +++ b/src/xmlcode.l @@ -19,6 +19,9 @@ %option never-interactive %option prefix="xmlcodeYY" +%top{ +#include <stdint.h> +} %{ @@ -69,7 +72,9 @@ static MemberDef * g_currentMemberDef; static bool g_includeCodeFragment; static const char * g_currentFontClass; +#if USE_STATE2STRING static const char *stateToString(int state); +#endif static void codify(const char* text) { @@ -435,4 +440,6 @@ void XMLCodeParser::resetCodeParserState() resetXmlCodeParserState(); } +#if USE_STATE2STRING #include "xmlcode.l.h" +#endif diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 409c2fe..045f87c 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,7 +13,7 @@ * */ -#include <qfileinfo.h> +#include <qfileinfo.h> #include "xmldocvisitor.h" #include "docparser.h" @@ -32,6 +29,7 @@ #include "config.h" #include "htmlentity.h" #include "emoji.h" +#include "filedef.h" static void visitCaption(XmlDocVisitor *parent, QList<DocNode> children) { @@ -40,9 +38,9 @@ static void visitCaption(XmlDocVisitor *parent, QList<DocNode> children) for (cli.toFirst();(n=cli.current());++cli) n->accept(parent); } -static void visitPreStart(FTextStream &t, const char *cmd, bool doCaption, - XmlDocVisitor *parent, QList<DocNode> children, - const QCString &name, bool writeType, DocImage::Type type, const QCString &width, +static void visitPreStart(FTextStream &t, const char *cmd, bool doCaption, + XmlDocVisitor *parent, QList<DocNode> children, + const QCString &name, bool writeType, DocImage::Type type, const QCString &width, const QCString &height, bool inlineImage = FALSE) { t << "<" << cmd; @@ -88,8 +86,8 @@ static void visitPostEnd(FTextStream &t, const char *cmd) t << "</" << cmd << ">" << endl; } -XmlDocVisitor::XmlDocVisitor(FTextStream &t,CodeOutputInterface &ci) - : DocVisitor(DocVisitor_XML), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) +XmlDocVisitor::XmlDocVisitor(FTextStream &t,CodeOutputInterface &ci) + : DocVisitor(DocVisitor_XML), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) { } @@ -159,7 +157,7 @@ void XmlDocVisitor::visit(DocEmoji *s) void XmlDocVisitor::visit(DocURL *u) { if (m_hide) return; - m_t << "<ulink url=\""; + m_t << "<ulink url=\""; if (u->isEmail()) m_t << "mailto:"; filter(u->url()); m_t << "\">"; @@ -221,12 +219,12 @@ void XmlDocVisitor::visit(DocStyleChange *s) if (s->enable()) m_t << "<small>"; else m_t << "</small>"; break; case DocStyleChange::Preformatted: - if (s->enable()) + if (s->enable()) { - m_t << "<preformatted>"; + m_t << "<preformatted>"; m_insidePre=TRUE; } - else + else { m_t << "</preformatted>"; m_insidePre=FALSE; @@ -257,21 +255,46 @@ void XmlDocVisitor::visit(DocVerbatim *s) Doxygen::parserManager->getCodeParser(lang) .parseCode(m_ci,s->context(),s->text(),langExt, s->isExample(),s->exampleFile()); - m_t << "</programlisting>"; + m_t << "</programlisting>"; break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: m_t << "<verbatim>"; filter(s->text()); - m_t << "</verbatim>"; + m_t << "</verbatim>"; + break; + case DocVerbatim::HtmlOnly: + if (s->isBlock()) + { + m_t << "<htmlonly block=\"yes\">"; + } + else + { + m_t << "<htmlonly>"; + } + filter(s->text()); + m_t << "</htmlonly>"; + break; + case DocVerbatim::RtfOnly: + m_t << "<rtfonly>"; + filter(s->text()); + m_t << "</rtfonly>"; + break; + case DocVerbatim::ManOnly: + m_t << "<manonly>"; + filter(s->text()); + m_t << "</manonly>"; + break; + case DocVerbatim::LatexOnly: + m_t << "<latexonly>"; + filter(s->text()); + m_t << "</latexonly>"; break; - case DocVerbatim::HtmlOnly: - case DocVerbatim::RtfOnly: - case DocVerbatim::ManOnly: - case DocVerbatim::LatexOnly: case DocVerbatim::DocbookOnly: - /* nothing */ + m_t << "<docbookonly>"; + filter(s->text()); + m_t << "</docbookonly>"; break; - case DocVerbatim::XmlOnly: + case DocVerbatim::XmlOnly: m_t << s->text(); break; case DocVerbatim::Dot: @@ -305,7 +328,7 @@ void XmlDocVisitor::visit(DocInclude *inc) switch(inc->type()) { case DocInclude::IncWithLines: - { + { m_t << "<programlisting filename=\"" << inc->file() << "\">"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); @@ -323,10 +346,10 @@ void XmlDocVisitor::visit(DocInclude *inc) TRUE // show line numbers ); delete fd; - m_t << "</programlisting>"; + m_t << "</programlisting>"; } - break; - case DocInclude::Include: + break; + case DocInclude::Include: m_t << "<programlisting filename=\"" << inc->file() << "\">"; Doxygen::parserManager->getCodeParser(inc->extension()) .parseCode(m_ci,inc->context(), @@ -341,12 +364,12 @@ void XmlDocVisitor::visit(DocInclude *inc) 0, // memberDef FALSE // show line numbers ); - m_t << "</programlisting>"; + m_t << "</programlisting>"; break; - case DocInclude::DontInclude: - case DocInclude::DontIncWithLines: + case DocInclude::DontInclude: + case DocInclude::DontIncWithLines: break; - case DocInclude::HtmlInclude: + case DocInclude::HtmlInclude: if (inc->isBlock()) { m_t << "<htmlonly block=\"yes\">"; @@ -363,10 +386,28 @@ void XmlDocVisitor::visit(DocInclude *inc) filter(inc->text()); m_t << "</latexonly>"; break; - case DocInclude::VerbInclude: + case DocInclude::RtfInclude: + m_t << "<rtfonly>"; + filter(inc->text()); + m_t << "</rtfonly>"; + break; + case DocInclude::ManInclude: + m_t << "<manonly>"; + filter(inc->text()); + m_t << "</manonly>"; + break; + case DocInclude::XmlInclude: + filter(inc->text()); + break; + case DocInclude::DocbookInclude: + m_t << "<docbookonly>"; + filter(inc->text()); + m_t << "</docbookonly>"; + break; + case DocInclude::VerbInclude: m_t << "<verbatim>"; filter(inc->text()); - m_t << "</verbatim>"; + m_t << "</verbatim>"; break; case DocInclude::Snippet: m_t << "<programlisting filename=\"" << inc->file() << "\">"; @@ -378,7 +419,7 @@ void XmlDocVisitor::visit(DocInclude *inc) inc->isExample(), inc->exampleFile() ); - m_t << "</programlisting>"; + m_t << "</programlisting>"; break; case DocInclude::SnipWithLines: { @@ -391,7 +432,7 @@ void XmlDocVisitor::visit(DocInclude *inc) extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -400,11 +441,11 @@ void XmlDocVisitor::visit(DocInclude *inc) TRUE // show line number ); delete fd; - m_t << "</programlisting>"; + m_t << "</programlisting>"; } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -415,7 +456,7 @@ void XmlDocVisitor::visit(DocIncOperator *op) { //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n", // op->type(),op->isFirst(),op->isLast(),op->text().data()); - if (op->isFirst()) + if (op->isFirst()) { if (!m_hide) { @@ -427,10 +468,10 @@ void XmlDocVisitor::visit(DocIncOperator *op) QCString locLangExt = getFileNameExtension(op->includeFileName()); if (locLangExt.isEmpty()) locLangExt = m_langExt; SrcLangExt langExt = getLanguageFromFileName(locLangExt); - if (op->type()!=DocIncOperator::Skip) + if (op->type()!=DocIncOperator::Skip) { popEnabled(); - if (!m_hide) + if (!m_hide) { FileDef *fd = 0; if (!op->includeFileName().isEmpty()) @@ -455,10 +496,10 @@ void XmlDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); - if (!m_hide) m_t << "</programlisting>"; + if (!m_hide) m_t << "</programlisting>"; } else { @@ -538,13 +579,13 @@ void XmlDocVisitor::visitPre(DocAutoListItem *) m_t << "<listitem>"; } -void XmlDocVisitor::visitPost(DocAutoListItem *) +void XmlDocVisitor::visitPost(DocAutoListItem *) { if (m_hide) return; m_t << "</listitem>"; } -void XmlDocVisitor::visitPre(DocPara *) +void XmlDocVisitor::visitPre(DocPara *) { if (m_hide) return; m_t << "<para>"; @@ -572,21 +613,21 @@ void XmlDocVisitor::visitPre(DocSimpleSect *s) m_t << "<simplesect kind=\""; switch(s->type()) { - case DocSimpleSect::See: + case DocSimpleSect::See: m_t << "see"; break; - case DocSimpleSect::Return: + case DocSimpleSect::Return: m_t << "return"; break; - case DocSimpleSect::Author: + case DocSimpleSect::Author: m_t << "author"; break; - case DocSimpleSect::Authors: + case DocSimpleSect::Authors: m_t << "authors"; break; - case DocSimpleSect::Version: + case DocSimpleSect::Version: m_t << "version"; break; - case DocSimpleSect::Since: + case DocSimpleSect::Since: m_t << "since"; break; - case DocSimpleSect::Date: + case DocSimpleSect::Date: m_t << "date"; break; - case DocSimpleSect::Note: + case DocSimpleSect::Note: m_t << "note"; break; case DocSimpleSect::Warning: m_t << "warning"; break; @@ -602,9 +643,9 @@ void XmlDocVisitor::visitPre(DocSimpleSect *s) m_t << "remark"; break; case DocSimpleSect::Attention: m_t << "attention"; break; - case DocSimpleSect::User: + case DocSimpleSect::User: m_t << "par"; break; - case DocSimpleSect::Rcs: + case DocSimpleSect::Rcs: m_t << "rcs"; break; case DocSimpleSect::Unknown: break; } @@ -647,7 +688,7 @@ void XmlDocVisitor::visitPre(DocSimpleListItem *) m_t << "<listitem>"; } -void XmlDocVisitor::visitPost(DocSimpleListItem *) +void XmlDocVisitor::visitPost(DocSimpleListItem *) { if (m_hide) return; m_t << "</listitem>\n"; @@ -664,7 +705,7 @@ void XmlDocVisitor::visitPre(DocSection *s) m_t << "</title>" << endl; } -void XmlDocVisitor::visitPost(DocSection *s) +void XmlDocVisitor::visitPost(DocSection *s) { m_t << "</sect" << s->level() << ">\n"; } @@ -672,18 +713,18 @@ void XmlDocVisitor::visitPost(DocSection *s) void XmlDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) - m_t << "<orderedlist>\n"; - else + if (s->type()==DocHtmlList::Ordered) + m_t << "<orderedlist>\n"; + else m_t << "<itemizedlist>\n"; } -void XmlDocVisitor::visitPost(DocHtmlList *s) +void XmlDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) - m_t << "</orderedlist>\n"; - else + if (s->type()==DocHtmlList::Ordered) + m_t << "</orderedlist>\n"; + else m_t << "</itemizedlist>\n"; } @@ -693,7 +734,7 @@ void XmlDocVisitor::visitPre(DocHtmlListItem *) m_t << "<listitem>\n"; } -void XmlDocVisitor::visitPost(DocHtmlListItem *) +void XmlDocVisitor::visitPost(DocHtmlListItem *) { if (m_hide) return; m_t << "</listitem>\n"; @@ -705,7 +746,7 @@ void XmlDocVisitor::visitPre(DocHtmlDescList *) m_t << "<variablelist>\n"; } -void XmlDocVisitor::visitPost(DocHtmlDescList *) +void XmlDocVisitor::visitPost(DocHtmlDescList *) { if (m_hide) return; m_t << "</variablelist>\n"; @@ -717,7 +758,7 @@ void XmlDocVisitor::visitPre(DocHtmlDescTitle *) m_t << "<varlistentry><term>"; } -void XmlDocVisitor::visitPost(DocHtmlDescTitle *) +void XmlDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_t << "</term></varlistentry>\n"; @@ -729,7 +770,7 @@ void XmlDocVisitor::visitPre(DocHtmlDescData *) m_t << "<listitem>"; } -void XmlDocVisitor::visitPost(DocHtmlDescData *) +void XmlDocVisitor::visitPost(DocHtmlDescData *) { if (m_hide) return; m_t << "</listitem>\n"; @@ -738,11 +779,11 @@ void XmlDocVisitor::visitPost(DocHtmlDescData *) void XmlDocVisitor::visitPre(DocHtmlTable *t) { if (m_hide) return; - m_t << "<table rows=\"" << t->numRows() + m_t << "<table rows=\"" << t->numRows() << "\" cols=\"" << t->numColumns() << "\">" ; } -void XmlDocVisitor::visitPost(DocHtmlTable *) +void XmlDocVisitor::visitPost(DocHtmlTable *) { if (m_hide) return; m_t << "</table>\n"; @@ -754,7 +795,7 @@ void XmlDocVisitor::visitPre(DocHtmlRow *) m_t << "<row>\n"; } -void XmlDocVisitor::visitPost(DocHtmlRow *) +void XmlDocVisitor::visitPost(DocHtmlRow *) { if (m_hide) return; m_t << "</row>\n"; @@ -763,13 +804,51 @@ void XmlDocVisitor::visitPost(DocHtmlRow *) void XmlDocVisitor::visitPre(DocHtmlCell *c) { if (m_hide) return; - if (c->isHeading()) m_t << "<entry thead=\"yes\">"; else m_t << "<entry thead=\"no\">"; + if (c->isHeading()) m_t << "<entry thead=\"yes\""; else m_t << "<entry thead=\"no\""; + HtmlAttribListIterator li(c->attribs()); + HtmlAttrib *opt; + for (li.toFirst();(opt=li.current());++li) + { + if (opt->name=="colspan" || opt->name=="rowspan") + { + m_t << " " << opt->name << "=\"" << opt->value.toInt() << "\""; + } + else if (opt->name=="align" && + (opt->value=="right" || opt->value=="left" || opt->value=="center")) + { + m_t << " align=\"" << opt->value << "\""; + } + else if (opt->name=="class") // handle markdown generated attributes + { + if (opt->value.left(13)=="markdownTable") // handle markdown generated attributes + { + if (opt->value.right(5)=="Right") + { + m_t << " align='right'"; + } + else if (opt->value.right(4)=="Left") + { + m_t << " align='left'"; + } + else if (opt->value.right(6)=="Center") + { + m_t << " align='center'"; + } + // skip 'markdownTable*' value ending with "None" + } + else if (!opt->value.isEmpty()) + { + m_t << " class=\"" << convertToXML(opt->value) << "\""; + } + } + } + m_t << ">"; } -void XmlDocVisitor::visitPost(DocHtmlCell *) +void XmlDocVisitor::visitPost(DocHtmlCell *) { if (m_hide) return; - m_t << "</entry>"; + m_t << "</entry>"; } void XmlDocVisitor::visitPre(DocHtmlCaption *) @@ -778,7 +857,7 @@ void XmlDocVisitor::visitPre(DocHtmlCaption *) m_t << "<caption>"; } -void XmlDocVisitor::visitPost(DocHtmlCaption *) +void XmlDocVisitor::visitPost(DocHtmlCaption *) { if (m_hide) return; m_t << "</caption>\n"; @@ -790,7 +869,7 @@ void XmlDocVisitor::visitPre(DocInternal *) m_t << "<internal>"; } -void XmlDocVisitor::visitPost(DocInternal *) +void XmlDocVisitor::visitPost(DocInternal *) { if (m_hide) return; m_t << "</internal>" << endl; @@ -802,7 +881,7 @@ void XmlDocVisitor::visitPre(DocHRef *href) m_t << "<ulink url=\"" << convertToXML(href->url(), TRUE) << "\">"; } -void XmlDocVisitor::visitPost(DocHRef *) +void XmlDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "</ulink>"; @@ -814,7 +893,7 @@ void XmlDocVisitor::visitPre(DocHtmlHeader *header) m_t << "<heading level=\"" << header->level() << "\">"; } -void XmlDocVisitor::visitPost(DocHtmlHeader *) +void XmlDocVisitor::visitPost(DocHtmlHeader *) { if (m_hide) return; m_t << "</heading>\n"; @@ -824,18 +903,22 @@ void XmlDocVisitor::visitPre(DocImage *img) { if (m_hide) return; - QCString baseName=img->name(); - int i; - if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1) + QCString url = img->url(); + QCString baseName; + if (url.isEmpty()) { - baseName=baseName.right(baseName.length()-i-1); + baseName = img->relPath()+img->name(); + } + else + { + baseName = correctURL(url,img->relPath()); } visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE, img->type(), img->width(), img->height(), img ->isInlineImage()); // copy the image to the output dir FileDef *fd; bool ambig; - if ((fd=findFileDef(Doxygen::imageNameDict,img->name(),ambig))) + if (url.isEmpty() && (fd=findFileDef(Doxygen::imageNameLinkedMap,img->name(),ambig))) { QFile inImage(fd->absFilePath()); QFile outImage(Config_getString(XML_OUTPUT)+"/"+baseName.data()); @@ -853,7 +936,7 @@ void XmlDocVisitor::visitPre(DocImage *img) } } -void XmlDocVisitor::visitPost(DocImage *) +void XmlDocVisitor::visitPost(DocImage *) { if (m_hide) return; visitPostEnd(m_t, "image"); @@ -865,7 +948,7 @@ void XmlDocVisitor::visitPre(DocDotFile *df) visitPreStart(m_t, "dotfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height()); } -void XmlDocVisitor::visitPost(DocDotFile *) +void XmlDocVisitor::visitPost(DocDotFile *) { if (m_hide) return; visitPostEnd(m_t, "dotfile"); @@ -877,7 +960,7 @@ void XmlDocVisitor::visitPre(DocMscFile *df) visitPreStart(m_t, "mscfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height()); } -void XmlDocVisitor::visitPost(DocMscFile *) +void XmlDocVisitor::visitPost(DocMscFile *) { if (m_hide) return; visitPostEnd(m_t, "mscfile"); @@ -901,7 +984,7 @@ void XmlDocVisitor::visitPre(DocLink *lnk) startLink(lnk->ref(),lnk->file(),lnk->anchor()); } -void XmlDocVisitor::visitPost(DocLink *) +void XmlDocVisitor::visitPost(DocLink *) { if (m_hide) return; endLink(); @@ -910,14 +993,14 @@ void XmlDocVisitor::visitPost(DocLink *) void XmlDocVisitor::visitPre(DocRef *ref) { if (m_hide) return; - if (!ref->file().isEmpty()) + if (!ref->file().isEmpty()) { startLink(ref->ref(),ref->file(),ref->isSubPage() ? QCString() : ref->anchor()); } if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void XmlDocVisitor::visitPost(DocRef *ref) +void XmlDocVisitor::visitPost(DocRef *ref) { if (m_hide) return; if (!ref->file().isEmpty()) endLink(); @@ -930,7 +1013,7 @@ void XmlDocVisitor::visitPre(DocSecRefItem *ref) m_t << "<tocitem id=\"" << ref->file() << "_1" << ref->anchor() << "\">"; } -void XmlDocVisitor::visitPost(DocSecRefItem *) +void XmlDocVisitor::visitPost(DocSecRefItem *) { if (m_hide) return; m_t << "</tocitem>" << endl; @@ -942,7 +1025,7 @@ void XmlDocVisitor::visitPre(DocSecRefList *) m_t << "<toclist>" << endl; } -void XmlDocVisitor::visitPost(DocSecRefList *) +void XmlDocVisitor::visitPost(DocSecRefList *) { if (m_hide) return; m_t << "</toclist>" << endl; @@ -954,7 +1037,7 @@ void XmlDocVisitor::visitPost(DocSecRefList *) // m_t << "<language langid=\"" << l->id() << "\">"; //} // -//void XmlDocVisitor::visitPost(DocLanguage *) +//void XmlDocVisitor::visitPost(DocLanguage *) //{ // if (m_hide) return; // m_t << "</language>" << endl; @@ -966,13 +1049,13 @@ void XmlDocVisitor::visitPre(DocParamSect *s) m_t << "<parameterlist kind=\""; switch(s->type()) { - case DocParamSect::Param: + case DocParamSect::Param: m_t << "param"; break; - case DocParamSect::RetVal: + case DocParamSect::RetVal: m_t << "retval"; break; - case DocParamSect::Exception: + case DocParamSect::Exception: m_t << "exception"; break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: m_t << "templateparam"; break; default: ASSERT(0); @@ -999,18 +1082,18 @@ void XmlDocVisitor::visitPre(DocParamList *pl) { if (pl->paramTypes().count()>0) { - QListIterator<DocNode> li(pl->paramTypes()); + QListIterator<DocNode> li2(pl->paramTypes()); DocNode *type; m_t << "<parametertype>"; - for (li.toFirst();(type=li.current());++li) + for (li2.toFirst();(type=li2.current());++li2) { if (type->kind()==DocNode::Kind_Word) { - visit((DocWord*)type); + visit((DocWord*)type); } else if (type->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)type); + visit((DocLinkedWord*)type); } else if (type->kind()==DocNode::Kind_Sep) { @@ -1041,11 +1124,11 @@ void XmlDocVisitor::visitPre(DocParamList *pl) m_t << ">"; if (param->kind()==DocNode::Kind_Word) { - visit((DocWord*)param); + visit((DocWord*)param); } else if (param->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)param); + visit((DocLinkedWord*)param); } m_t << "</parametername>" << endl; } @@ -1087,7 +1170,7 @@ void XmlDocVisitor::visitPre(DocInternalRef *ref) startLink(0,ref->file(),ref->anchor()); } -void XmlDocVisitor::visitPost(DocInternalRef *) +void XmlDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; endLink(); @@ -1136,7 +1219,7 @@ void XmlDocVisitor::visitPost(DocParBlock *) void XmlDocVisitor::filter(const char *str) -{ +{ m_t << convertToXML(str); } diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index bf5af84..19f1553 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -154,7 +154,9 @@ static void writeXMLHeader(FTextStream &t) t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; t << "<doxygen xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "; t << "xsi:noNamespaceSchemaLocation=\"compound.xsd\" "; - t << "version=\"" << getVersion() << "\">" << endl; + t << "version=\"" << getDoxygenVersion() << "\" "; + t << "xml:lang=\"" << theTranslator->trISOLang() << "\""; + t << ">" << endl; } static void writeCombineScript() @@ -178,7 +180,7 @@ static void writeCombineScript() "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n" " <xsl:output method=\"xml\" version=\"1.0\" indent=\"no\" standalone=\"yes\" />\n" " <xsl:template match=\"/\">\n" - " <doxygen version=\"{doxygenindex/@version}\">\n" + " <doxygen version=\"{doxygenindex/@version}\" xml:lang=\"{doxygenindex/@xml:lang}\">\n" " <!-- Load all doxygen generated xml files -->\n" " <xsl:for-each select=\"doxygenindex/compound\">\n" " <xsl:copy-of select=\"document( concat( @refid, '.xml' ) )/doxygen/*\" />\n" @@ -195,7 +197,7 @@ void writeXMLLink(FTextStream &t,const char *extRef,const char *compoundId, t << "<ref refid=\"" << compoundId; if (anchorId) t << "_1" << anchorId; t << "\" kindref=\""; - if (anchorId) t << "member"; else t << "compound"; + if (anchorId) t << "member"; else t << "compound"; t << "\""; if (extRef) t << " external=\"" << extRef << "\""; if (tooltip) t << " tooltip=\"" << convertToXML(tooltip) << "\""; @@ -211,7 +213,7 @@ class TextGeneratorXMLImpl : public TextGeneratorIntf TextGeneratorXMLImpl(FTextStream &t): m_t(t) {} void writeString(const char *s,bool /*keepSpaces*/) const { - writeXMLString(m_t,s); + writeXMLString(m_t,s); } void writeBreak(int) const {} void writeLink(const char *extRef,const char *file, @@ -401,7 +403,8 @@ static void writeXMLDocBlock(FTextStream &t, QCString stext = text.stripWhiteSpace(); if (stext.isEmpty()) return; // convert the documentation string into an abstract syntax tree - DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE); + DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE, + 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); // create a code generator XMLCodeGenerator *xmlCodeGen = new XMLCodeGenerator(t); // create a parse tree visitor for XML @@ -412,7 +415,7 @@ static void writeXMLDocBlock(FTextStream &t, delete visitor; delete xmlCodeGen; delete root; - + } void writeXMLCodeBlock(FTextStream &t,FileDef *fd) @@ -448,7 +451,7 @@ static void writeMemberReference(FTextStream &t,const Definition *def,const Memb } t << " <" << tagName << " refid=\""; t << rmd->getOutputFileBase() << "_1" << rmd->anchor() << "\""; - if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { t << " compoundref=\"" << rmd->getBodyDef()->getOutputFileBase() << "\""; t << " startline=\"" << rmd->getStartBodyLine() << "\""; @@ -458,7 +461,7 @@ static void writeMemberReference(FTextStream &t,const Definition *def,const Memb } } t << ">" << convertToXML(name) << "</" << tagName << ">" << endl; - + } static void stripQualifiers(QCString &typeStr) @@ -477,18 +480,18 @@ static void stripQualifiers(QCString &typeStr) static QCString classOutputFileBase(const ClassDef *cd) { //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES); - //if (inlineGroupedClasses && cd->partOfGroups()!=0) + //if (inlineGroupedClasses && cd->partOfGroups()!=0) return cd->getOutputFileBase(); - //else + //else // return cd->getOutputFileBase(); } static QCString memberOutputFileBase(const MemberDef *md) { //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES); - //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0) + //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0) // return md->getClassDef()->getXmlOutputFileBase(); - //else + //else // return md->getOutputFileBase(); return md->getOutputFileBase(); } @@ -506,11 +509,11 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream // + source definition // + source references // + source referenced by - // - body code - // + template arguments + // - body code + // + template arguments // (templateArguments(), definitionTemplateParameterLists()) // - call graph - + // enum values are written as part of the enum if (md->memberType()==MemberType_EnumValue) return; if (md->isHidden()) return; @@ -540,16 +543,16 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream case MemberType_Dictionary: memType="dictionary"; break; } - ti << " <member refid=\"" << memberOutputFileBase(md) - << "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>" + ti << " <member refid=\"" << memberOutputFileBase(md) + << "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>" << convertToXML(md->name()) << "</name></member>" << endl; - + QCString scopeName; - if (md->getClassDef()) + if (md->getClassDef()) scopeName=md->getClassDef()->name(); - else if (md->getNamespaceDef()) + else if (md->getNamespaceDef()) scopeName=md->getNamespaceDef()->name(); - + t << " <memberdef kind=\""; //enum { define_t,variable_t,typedef_t,enum_t,function_t } xmlType = function_t; t << memType << "\" id=\""; @@ -586,7 +589,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream { const ArgumentList &al = md->argumentList(); t << " const=\""; - if (al.constSpecifier) t << "yes"; else t << "no"; + if (al.constSpecifier()) t << "yes"; else t << "no"; t << "\""; t << " explicit=\""; @@ -597,10 +600,10 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream if (md->isInline()) t << "yes"; else t << "no"; t << "\""; - if (al.refQualifier!=RefQualifierNone) + if (al.refQualifier()!=RefQualifierNone) { t << " refqual=\""; - if (al.refQualifier==RefQualifierLValue) t << "lvalue"; else t << "rvalue"; + if (al.refQualifier()==RefQualifierLValue) t << "lvalue"; else t << "rvalue"; t << "\""; } @@ -634,7 +637,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream t << " noexcept=\"yes\""; } - if (al.volatileSpecifier) + if (al.volatileSpecifier()) { t << " volatile=\"yes\""; } @@ -661,12 +664,12 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream { //ArgumentList *al = md->argumentList(); //t << " volatile=\""; - //if (al && al->volatileSpecifier) t << "yes"; else t << "no"; + //if (al && al->volatileSpecifier) t << "yes"; else t << "no"; t << " mutable=\""; if (md->isMutable()) t << "yes"; else t << "no"; t << "\""; - + if (md->isInitonly()) { t << " initonly=\"yes\""; @@ -796,7 +799,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream } t << " <name>" << convertToXML(md->name()) << "</name>" << endl; - + if (md->memberType() == MemberType_Property) { if (md->isReadable()) @@ -811,11 +814,11 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream if (bitfield.at(0)==':') bitfield=bitfield.mid(1); t << " <bitfield>" << convertToXML(bitfield) << "</bitfield>" << endl; } - + const MemberDef *rmd = md->reimplements(); if (rmd) { - t << " <reimplements refid=\"" + t << " <reimplements refid=\"" << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">" << convertToXML(rmd->name()) << "</reimplements>" << endl; } @@ -825,7 +828,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream MemberListIterator mli(*rbml); for (mli.toFirst();(rmd=mli.current());++mli) { - t << " <reimplementedby refid=\"" + t << " <reimplementedby refid=\"" << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">" << convertToXML(rmd->name()) << "</reimplementedby>" << endl; } @@ -863,7 +866,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream if (!a.name.isEmpty()) { t << " <declname>"; - writeXMLString(t,a.name); + writeXMLString(t,a.name); t << "</declname>" << endl; } if (defArg && !defArg->name.isEmpty() && defArg->name!=a.name) @@ -874,8 +877,8 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream } if (!a.array.isEmpty()) { - t << " <array>"; - writeXMLString(t,a.array); + t << " <array>"; + writeXMLString(t,a.array); t << "</array>" << endl; } if (!a.defval.isEmpty()) @@ -895,7 +898,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream } } } - else if (md->memberType()==MemberType_Define && + else if (md->memberType()==MemberType_Define && md->argsString()) // define { if (md->argumentList().empty()) // special case for "foo()" to @@ -925,7 +928,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->excpString()); t << "</exceptions>" << endl; } - + if (md->memberType()==MemberType_Enumeration) // enum { const MemberList *enumFields = md->enumFieldList(); @@ -979,9 +982,9 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream t << " </inbodydescription>" << endl; if (md->getDefLine()!=-1) { - t << " <location file=\"" + t << " <location file=\"" << convertToXML(stripFromPath(md->getDefFileName())) << "\" line=\"" - << md->getDefLine() << "\" column=\"" + << md->getDefLine() << "\" column=\"" << md->getDefColumn() << "\"" ; if (md->getStartBodyLine()!=-1) { @@ -990,7 +993,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream { t << " bodyfile=\"" << convertToXML(stripFromPath(bodyDef->absFilePath())) << "\""; } - t << " bodystart=\"" << md->getStartBodyLine() << "\" bodyend=\"" + t << " bodystart=\"" << md->getStartBodyLine() << "\" bodyend=\"" << md->getEndBodyLine() << "\""; } if (md->getDeclLine()!=-1) @@ -1007,7 +1010,6 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream if (mdict) { MemberSDict::Iterator mdi(*mdict); - const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { writeMemberReference(t,def,rmd,"references"); @@ -1017,13 +1019,12 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream if (mdict) { MemberSDict::Iterator mdi(*mdict); - const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { writeMemberReference(t,def,rmd,"referencedby"); } } - + t << " </memberdef>" << endl; } @@ -1078,45 +1079,38 @@ static void generateXMLSection(const Definition *d,FTextStream &ti,FTextStream & static void writeListOfAllMembers(const ClassDef *cd,FTextStream &t) { t << " <listofallmembers>" << endl; - if (cd->memberNameInfoSDict()) + for (auto &mni : cd->memberNameInfoLinkedMap()) { - MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict()); - MemberNameInfo *mni; - for (mnii.toFirst();(mni=mnii.current());++mnii) + for (auto &mi : *mni) { - MemberNameInfoIterator mii(*mni); - MemberInfo *mi; - for (mii.toFirst();(mi=mii.current());++mii) + const MemberDef *md=mi->memberDef(); + if (!md->isAnonymous()) { - const MemberDef *md=mi->memberDef; - if (!md->isAnonymous()) + Protection prot = mi->prot(); + Specifier virt=md->virtualness(); + t << " <member refid=\"" << memberOutputFileBase(md) << "_1" << + md->anchor() << "\" prot=\""; + switch (prot) { - Protection prot = mi->prot; - Specifier virt=md->virtualness(); - t << " <member refid=\"" << memberOutputFileBase(md) << "_1" << - md->anchor() << "\" prot=\""; - switch (prot) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: t << "package"; break; - } - t << "\" virt=\""; - switch(virt) - { - case Normal: t << "non-virtual"; break; - case Virtual: t << "virtual"; break; - case Pure: t << "pure-virtual"; break; - } - t << "\""; - if (!mi->ambiguityResolutionScope.isEmpty()) - { - t << " ambiguityscope=\"" << convertToXML(mi->ambiguityResolutionScope) << "\""; - } - t << "><scope>" << convertToXML(cd->name()) << "</scope><name>" << - convertToXML(md->name()) << "</name></member>" << endl; + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: t << "package"; break; } + t << "\" virt=\""; + switch(virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; + } + t << "\""; + if (!mi->ambiguityResolutionScope().isEmpty()) + { + t << " ambiguityscope=\"" << convertToXML(mi->ambiguityResolutionScope()) << "\""; + } + t << "><scope>" << convertToXML(cd->name()) << "</scope><name>" << + convertToXML(md->name()) << "</name></member>" << endl; } } } @@ -1159,7 +1153,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; } } } @@ -1173,7 +1168,7 @@ static void writeInnerFiles(const FileList *fl,FTextStream &t) FileDef *fd; for (fli.toFirst();(fd=fli.current());++fli) { - t << " <innerfile refid=\"" << fd->getOutputFileBase() + t << " <innerfile refid=\"" << fd->getOutputFileBase() << "\">" << convertToXML(fd->name()) << "</innerfile>" << endl; } } @@ -1206,7 +1201,7 @@ static void writeInnerGroups(const GroupList *gl,FTextStream &t) for (gli.toFirst();(sgd=gli.current());++gli) { t << " <innergroup refid=\"" << sgd->getOutputFileBase() - << "\">" << convertToXML(sgd->groupTitle()) + << "\">" << convertToXML(sgd->groupTitle()) << "</innergroup>" << endl; } } @@ -1216,16 +1211,14 @@ static void writeInnerDirs(const DirList *dl,FTextStream &t) { if (dl) { - QListIterator<DirDef> subdirs(*dl); - DirDef *subdir; - for (subdirs.toFirst();(subdir=subdirs.current());++subdirs) + for(const auto subdir : *dl) { - t << " <innerdir refid=\"" << subdir->getOutputFileBase() + t << " <innerdir refid=\"" << subdir->getOutputFileBase() << "\">" << convertToXML(subdir->displayName()) << "</innerdir>" << endl; } } } - + static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) { // + brief description @@ -1252,10 +1245,10 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) msg("Generating XML output for class %s\n",cd->name().data()); - ti << " <compound refid=\"" << classOutputFileBase(cd) + ti << " <compound refid=\"" << classOutputFileBase(cd) << "\" kind=\"" << cd->compoundTypeString() << "\"><name>" << convertToXML(cd->name()) << "</name>" << endl; - + QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+ classOutputFileBase(cd)+".xml"; QFile f(fileName); @@ -1268,8 +1261,8 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) //t.setEncoding(FTextStream::UnicodeUTF8); writeXMLHeader(t); - t << " <compounddef id=\"" - << classOutputFileBase(cd) << "\" kind=\"" + t << " <compounddef id=\"" + << classOutputFileBase(cd) << "\" kind=\"" << cd->compoundTypeString() << "\" language=\"" << langToString(cd->getLanguage()) << "\" prot=\""; switch (cd->protection()) @@ -1283,8 +1276,8 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) if (cd->isSealed()) t << "\" sealed=\"yes"; if (cd->isAbstract()) t << "\" abstract=\"yes"; t << "\">" << endl; - t << " <compoundname>"; - writeXMLString(t,cd->name()); + t << " <compoundname>"; + writeXMLString(t,cd->name()); t << "</compoundname>" << endl; if (cd->baseClasses()) { @@ -1333,7 +1326,7 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) BaseClassDef *bcd; for (bcli.toFirst();(bcd=bcli.current());++bcli) { - t << " <derivedcompoundref refid=\"" + t << " <derivedcompoundref refid=\"" << classOutputFileBase(bcd->classDef) << "\" prot=\""; switch (bcd->prot) @@ -1350,7 +1343,7 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) case Virtual: t << "virtual"; break; case Pure: t << "pure-virtual"; break; } - t << "\">" << convertToXML(bcd->classDef->displayName()) + t << "\">" << convertToXML(bcd->classDef->displayName()) << "</derivedcompoundref>" << endl; } } @@ -1417,9 +1410,9 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) collaborationGraph.writeXML(t); t << " </collaborationgraph>" << endl; } - t << " <location file=\"" + t << " <location file=\"" << convertToXML(stripFromPath(cd->getDefFileName())) << "\" line=\"" - << cd->getDefLine() << "\"" << " column=\"" + << cd->getDefLine() << "\"" << " column=\"" << cd->getDefColumn() << "\"" ; if (cd->getStartBodyLine()!=-1) { @@ -1428,7 +1421,7 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) { t << " bodyfile=\"" << convertToXML(stripFromPath(bodyDef->absFilePath())) << "\""; } - t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" + t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" << cd->getEndBodyLine() << "\""; } t << "/>" << endl; @@ -1452,10 +1445,10 @@ static void generateXMLForNamespace(const NamespaceDef *nd,FTextStream &ti) if (nd->isReference() || nd->isHidden()) return; // skip external references - ti << " <compound refid=\"" << nd->getOutputFileBase() - << "\" kind=\"namespace\"" << "><name>" + ti << " <compound refid=\"" << nd->getOutputFileBase() + << "\" kind=\"namespace\"" << "><name>" << convertToXML(nd->name()) << "</name>" << endl; - + QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+nd->getOutputFileBase()+".xml"; QFile f(fileName); @@ -1466,10 +1459,12 @@ static void generateXMLForNamespace(const NamespaceDef *nd,FTextStream &ti) } FTextStream t(&f); //t.setEncoding(FTextStream::UnicodeUTF8); - + writeXMLHeader(t); - t << " <compounddef id=\"" << nd->getOutputFileBase() - << "\" kind=\"namespace\" language=\"" + t << " <compounddef id=\"" << nd->getOutputFileBase() + << "\" kind=\"namespace\" " + << (nd->isInline()?"inline=\"yes\" ":"") + << "language=\"" << langToString(nd->getLanguage()) << "\">" << endl; t << " <compoundname>"; writeXMLString(t,nd->name()); @@ -1530,13 +1525,13 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti) // + source code // + location // - number of lines - + if (fd->isReference()) return; // skip external references - - ti << " <compound refid=\"" << fd->getOutputFileBase() - << "\" kind=\"file\"><name>" << convertToXML(fd->name()) + + ti << " <compound refid=\"" << fd->getOutputFileBase() + << "\" kind=\"file\"><name>" << convertToXML(fd->name()) << "</name>" << endl; - + QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+fd->getOutputFileBase()+".xml"; QFile f(fileName); @@ -1550,7 +1545,7 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti) writeXMLHeader(t); t << " <compounddef id=\"" << fd->getOutputFileBase() - << "\" kind=\"file\" language=\"" + << "\" kind=\"file\" language=\"" << langToString(fd->getLanguage()) << "\">" << endl; t << " <compoundname>"; writeXMLString(t,fd->name()); @@ -1671,9 +1666,9 @@ static void generateXMLForGroup(const GroupDef *gd,FTextStream &ti) if (gd->isReference()) return; // skip external references - ti << " <compound refid=\"" << gd->getOutputFileBase() + ti << " <compound refid=\"" << gd->getOutputFileBase() << "\" kind=\"group\"><name>" << convertToXML(gd->name()) << "</name>" << endl; - + QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+gd->getOutputFileBase()+".xml"; QFile f(fileName); @@ -1686,7 +1681,7 @@ static void generateXMLForGroup(const GroupDef *gd,FTextStream &ti) FTextStream t(&f); //t.setEncoding(FTextStream::UnicodeUTF8); writeXMLHeader(t); - t << " <compounddef id=\"" + t << " <compounddef id=\"" << gd->getOutputFileBase() << "\" kind=\"group\">" << endl; t << " <compoundname>" << convertToXML(gd->name()) << "</compoundname>" << endl; t << " <title>" << convertToXML(gd->groupTitle()) << "</title>" << endl; @@ -1733,8 +1728,8 @@ static void generateXMLForGroup(const GroupDef *gd,FTextStream &ti) static void generateXMLForDir(DirDef *dd,FTextStream &ti) { if (dd->isReference()) return; // skip external references - ti << " <compound refid=\"" << dd->getOutputFileBase() - << "\" kind=\"dir\"><name>" << convertToXML(dd->displayName()) + ti << " <compound refid=\"" << dd->getOutputFileBase() + << "\" kind=\"dir\"><name>" << convertToXML(dd->displayName()) << "</name>" << endl; QCString outputDirectory = Config_getString(XML_OUTPUT); @@ -1749,7 +1744,7 @@ static void generateXMLForDir(DirDef *dd,FTextStream &ti) FTextStream t(&f); //t.setEncoding(FTextStream::UnicodeUTF8); writeXMLHeader(t); - t << " <compounddef id=\"" + t << " <compounddef id=\"" << dd->getOutputFileBase() << "\" kind=\"dir\">" << endl; t << " <compoundname>" << convertToXML(dd->displayName()) << "</compoundname>" << endl; @@ -1778,18 +1773,18 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) const char *kindName = isExample ? "example" : "page"; if (pd->isReference()) return; - + QCString pageName = pd->getOutputFileBase(); if (pd->getGroupDef()) { pageName+=(QCString)"_"+pd->name(); } if (pageName=="index") pageName="indexpage"; // to prevent overwriting the generated index page. - + ti << " <compound refid=\"" << pageName - << "\" kind=\"" << kindName << "\"><name>" << convertToXML(pd->name()) + << "\" kind=\"" << kindName << "\"><name>" << convertToXML(pd->name()) << "</name>" << endl; - + QCString outputDirectory = Config_getString(XML_OUTPUT); QCString fileName=outputDirectory+"/"+pageName+".xml"; QFile f(fileName); @@ -1804,7 +1799,7 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) writeXMLHeader(t); t << " <compounddef id=\"" << pageName; t << "\" kind=\"" << kindName << "\">" << endl; - t << " <compoundname>" << convertToXML(pd->name()) + t << " <compoundname>" << convertToXML(pd->name()) << "</compoundname>" << endl; if (pd==Doxygen::mainPage) // main page is special @@ -1818,37 +1813,32 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) { title = Config_getString(PROJECT_NAME); } - t << " <title>" << convertToXML(convertCharEntitiesToUTF8(title)) + t << " <title>" << convertToXML(convertCharEntitiesToUTF8(title)) << "</title>" << endl; } else { - SectionInfo *si = Doxygen::sectionDict->find(pd->name()); + const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) { - t << " <title>" << convertToXML(convertCharEntitiesToUTF8(filterTitle(si->title))) + t << " <title>" << convertToXML(convertCharEntitiesToUTF8(filterTitle(si->title()))) << "</title>" << endl; } } writeInnerPages(pd->getSubPages(),t); - SectionDict *sectionDict = pd->getSectionDict(); - if (pd->localToc().isXmlEnabled() && sectionDict) + const SectionRefs §ionRefs = pd->getSectionRefs(); + if (pd->localToc().isXmlEnabled() && !sectionRefs.empty()) { t << " <tableofcontents>" << endl; - SDict<SectionInfo>::Iterator li(*sectionDict); - SectionInfo *si; int level=1,l; bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; int maxLevel = pd->localToc().xmlLevel(); - for (li.toFirst();(si=li.current());++li) + for (const SectionInfo *si : sectionRefs) { - if (si->type==SectionInfo::Section || - si->type==SectionInfo::Subsection || - si->type==SectionInfo::Subsubsection || - si->type==SectionInfo::Paragraph) + if (isSection(si->type())) { //printf(" level=%d title=%s\n",level,si->title.data()); - int nextLevel = (int)si->type; + int nextLevel = (int)si->type(); if (nextLevel>level) { for (l=level;l<nextLevel;l++) @@ -1868,10 +1858,10 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) if (nextLevel <= maxLevel) { if (inLi[nextLevel]) t << " </tocsect>" << endl; - QCString titleDoc = convertToXML(si->title); + QCString titleDoc = convertToXML(si->title()); t << " <tocsect>" << endl; - t << " <name>" << (si->title.isEmpty()?si->label:titleDoc) << "</name>" << endl; - t << " <reference>" << convertToXML(pageName) << "_1" << convertToXML(si -> label) << "</reference>" << endl; + t << " <name>" << (si->title().isEmpty()?si->label():titleDoc) << "</name>" << endl; + t << " <reference>" << convertToXML(pageName) << "_1" << convertToXML(si->label()) << "</reference>" << endl; inLi[nextLevel]=TRUE; level = nextLevel; } @@ -1918,11 +1908,12 @@ void generateXML() // + groups // + related pages // - examples - + QCString outputDirectory = Config_getString(XML_OUTPUT); QDir xmlDir(outputDirectory); createSubDirs(xmlDir); + ResourceMgr::instance().copyResource("xml.xsd",outputDirectory); ResourceMgr::instance().copyResource("index.xsd",outputDirectory); QCString fileName=outputDirectory+"/compound.xsd"; @@ -1975,7 +1966,9 @@ void generateXML() t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; t << "<doxygenindex xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "; t << "xsi:noNamespaceSchemaLocation=\"index.xsd\" "; - t << "version=\"" << getVersion() << "\">" << endl; + t << "version=\"" << getDoxygenVersion() << "\" "; + t << "xml:lang=\"" << theTranslator->trISOLang() << "\""; + t << ">" << endl; { ClassSDict::Iterator cli(*Doxygen::classSDict); @@ -2001,16 +1994,12 @@ void generateXML() msg("Generating XML output for namespace %s\n",nd->name().data()); generateXMLForNamespace(nd,t); } - FileNameListIterator fnli(*Doxygen::inputNameList); - FileName *fn; - for (;(fn=fnli.current());++fnli) + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - FileNameIterator fni(*fn); - FileDef *fd; - for (;(fd=fni.current());++fni) + for (const auto &fd : *fn) { msg("Generating XML output for file %s\n",fd->name().data()); - generateXMLForFile(fd,t); + generateXMLForFile(fd.get(),t); } } GroupSDict::Iterator gli(*Doxygen::groupSDict); |